Browse Source

Various bugfixes:

Fix bug in Coins tab, get_utxos_by_mixdepth calls

Fix bug in jmbitcoin.mktx, now respects nVersion choice

Fix bug in tumbler restart wait

Fix bug in makercount for payjoin for fee check, set to 0:
The value of `options.makercount` is set to zero
so that the fee sanity check in the sendpayment script
operates approximately correctly (the receiver will bump
the fee to keep the fee rate the same if necessary).
Also the `bip79` variable is better named `payjoinurl`.

Fix bug in "freeze" context menu function in Qt
master
Adam Gibson 6 years ago
parent
commit
4cf77ed774
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 2
      jmbitcoin/jmbitcoin/secp256k1_transaction.py
  2. 4
      jmclient/jmclient/taker_utils.py
  3. 10
      jmclient/jmclient/wallet_utils.py
  4. 13
      scripts/joinmarket-qt.py
  5. 24
      scripts/sendpayment.py

2
jmbitcoin/jmbitcoin/secp256k1_transaction.py

@ -294,7 +294,7 @@ def mktx(ins, outs, version=1, locktime=0):
out = CMutableTxOut(o["value"],
CCoinAddress(o["address"]).to_scriptPubKey())
vout.append(out)
return CMutableTransaction(vin, vout, nLockTime=locktime)
return CMutableTransaction(vin, vout, nLockTime=locktime, nVersion=version)
def make_shuffled_tx(ins, outs, version=1, locktime=0):
""" Simple wrapper to ensure transaction

4
jmclient/jmclient/taker_utils.py

@ -4,7 +4,7 @@ import os
import sys
import time
import numbers
from jmbase import get_log, jmprint, bintohex
from jmbase import get_log, jmprint, bintohex, hextobin
from .configure import jm_single, validate_address, is_burn_destination
from .schedule import human_readable_schedule_entry, tweak_tumble_schedule,\
schedule_to_text
@ -209,7 +209,7 @@ def restart_wait(txid):
and confirmed (it must be an in-wallet transaction since it always
spends coins from the wallet).
"""
res = jm_single().bc_interface.get_transaction(txid)
res = jm_single().bc_interface.get_transaction(hextobin(txid))
if not res:
return False
if res["confirmations"] == 0:

10
jmclient/jmclient/wallet_utils.py

@ -345,8 +345,8 @@ def get_imported_privkey_branch(wallet_service, m, showprivkey):
addr = wallet_service.get_address_from_path(path)
script = wallet_service.get_script_from_path(path)
balance = 0.0
for data in wallet_service.get_utxos_by_mixdepth(include_disabled=True,
hexfmt=False)[m].values():
for data in wallet_service.get_utxos_by_mixdepth(
include_disabled=True)[m].values():
if script == data['script']:
balance += data['value']
used = ('used' if balance > 0.0 else 'empty')
@ -962,7 +962,7 @@ def wallet_fetch_history(wallet, options):
'history (%s)') % (btc.sat_to_str(total_wallet_balance),
btc.sat_to_str(balance)))
wallet_utxo_count = sum(map(len, wallet.get_utxos_by_mixdepth(
include_disabled=True, hexfmt=False).values()))
include_disabled=True).values()))
if utxo_count + unconfirmed_utxo_count != wallet_utxo_count:
jmprint(('BUG ERROR: wallet utxo count (%d) does not match utxo count from ' +
'history (%s)') % (wallet_utxo_count, utxo_count))
@ -1087,8 +1087,8 @@ def display_utxos_for_disable_choice_default(wallet_service, utxos_enabled,
def get_utxos_enabled_disabled(wallet_service, md):
""" Returns dicts for enabled and disabled separately
"""
utxos_enabled = wallet_service.get_utxos_by_mixdepth(hexfmt=False)[md]
utxos_all = wallet_service.get_utxos_by_mixdepth(include_disabled=True, hexfmt=False)[md]
utxos_enabled = wallet_service.get_utxos_by_mixdepth()[md]
utxos_all = wallet_service.get_utxos_by_mixdepth(include_disabled=True)[md]
utxos_disabled_keyset = set(utxos_all).difference(set(utxos_enabled))
utxos_disabled = {}
for u in utxos_disabled_keyset:

13
scripts/joinmarket-qt.py

@ -64,7 +64,8 @@ donation_address_url = "https://bitcoinprivacy.me/joinmarket-donations"
JM_GUI_VERSION = '15dev'
from jmbase import get_log
from jmbase.support import DUST_THRESHOLD, EXIT_FAILURE, JM_CORE_VERSION
from jmbase.support import DUST_THRESHOLD, EXIT_FAILURE, utxo_to_utxostr,\
bintohex, hextobin, JM_CORE_VERSION
from jmclient import load_program_config, get_network, update_persist_config,\
open_test_wallet_maybe, get_wallet_path,\
jm_single, validate_address, weighted_order_choose, Taker,\
@ -627,6 +628,7 @@ class SpendTab(QWidget):
self.waitingtxid=txid
self.restartTimer.timeout.connect(self.restartWaitWrap)
self.restartTimer.start(5000)
self.updateSchedView()
return
self.updateSchedView()
self.startJoin()
@ -1174,7 +1176,9 @@ class CoinsTab(QWidget):
else:
for k, v in um.items():
# txid:index, btc, address
t = btc.safe_hexlify(k[0])+":"+str(k[1])
success, t = utxo_to_utxostr(k)
# keys must be utxo format else a coding error:
assert success
s = "{0:.08f}".format(v['value']/1e8)
a = mainWindow.wallet_service.script_to_addr(v["script"])
item = QTreeWidgetItem([t, s, a])
@ -1187,7 +1191,7 @@ class CoinsTab(QWidget):
def toggle_utxo_disable(self, txids, idxs):
for i in range(0, len(txids)):
txid = txids[i]
txid_bytes = btc.safe_from_hex(txid)
txid_bytes = hextobin(txid)
mainWindow.wallet_service.toggle_disable_utxo(txid_bytes, idxs[i])
self.updateUtxos()
@ -1206,7 +1210,8 @@ class CoinsTab(QWidget):
assert idx >= 0
txids.append(txid)
idxs.append(idx)
except:
except Exception as e:
log.error("Error retrieving txids in Coins tab: " + repr(e))
return
# current item
item = self.cTW.currentItem()

24
scripts/sendpayment.py

@ -66,7 +66,7 @@ def main():
#without schedule file option, use the arguments to create a schedule
#of a single transaction
sweeping = False
bip79 = False
payjoinurl = None
if options.schedule == '':
if btc.is_bip21_uri(args[1]):
parsed = btc.decode_bip21_uri(args[1])
@ -78,14 +78,22 @@ def main():
destaddr = parsed['address']
if 'jmnick' in parsed:
if "pj" in parsed:
parser.error("Cannot specify both BIP79 and Joinmarket "
parser.error("Cannot specify both BIP79++ and Joinmarket "
"peer-to-peer payjoin at the same time!")
sys.exit(EXIT_ARGERROR)
options.p2ep = parsed['jmnick']
elif "pj" in parsed:
# note that this is a URL; its validity
# checking is deferred to twisted.web.client.Agent
bip79 = parsed["pj"]
payjoinurl = parsed["pj"]
# setting makercount only for fee sanity check.
# note we ignore any user setting and enforce N=0,
# as this is a flag in the code for a non-JM coinjoin;
# for the fee sanity check, note that BIP79++ currently
# will only allow very small fee changes, so N=0 won't
# be very inaccurate.
jmprint("Attempting to pay via payjoin.", "info")
options.makercount = 0
else:
amount = btc.amount_to_sat(args[1])
if amount == 0:
@ -159,13 +167,13 @@ def main():
fee_per_cp_guess))
maxcjfee = (1, float('inf'))
if not (options.p2ep or bip79) and not options.pickorders and \
if not options.p2ep and not options.pickorders and \
options.makercount != 0:
maxcjfee = get_max_cj_fee_values(jm_single().config, options)
log.info("Using maximum coinjoin fee limits per maker of {:.4%}, {} "
"".format(maxcjfee[0], btc.amount_to_str(maxcjfee[1])))
log.debug('starting sendpayment')
log.info('starting sendpayment')
max_mix_depth = max([mixdepth, options.amtmixdepths - 1])
@ -203,7 +211,7 @@ def main():
log.info("Estimated miner/tx fees for this coinjoin amount: {:.1%}"
.format(exp_tx_fees_ratio))
if options.makercount == 0 and not options.p2ep and not bip79:
if options.makercount == 0 and not options.p2ep and not payjoinurl:
tx = direct_send(wallet_service, amount, mixdepth, destaddr,
options.answeryes, with_final_psbt=options.with_psbt)
if options.with_psbt:
@ -314,10 +322,10 @@ def main():
taker = P2EPTaker(options.p2ep, wallet_service, schedule,
callbacks=(None, None, p2ep_on_finished_callback))
elif bip79:
elif payjoinurl:
# TODO sanity check wallet type is segwit
manager = parse_payjoin_setup(args[1], wallet_service, options.mixdepth)
reactor.callWhenRunning(send_payjoin, manager)
reactor.callWhenRunning(send_payjoin, manager, tls_whitelist=["127.0.0.1"])
reactor.run()
return

Loading…
Cancel
Save