From b221f1a5d004386ad10eec2926669ae57bb791ec Mon Sep 17 00:00:00 2001 From: AdamISZ Date: Tue, 19 Sep 2017 14:29:09 +0200 Subject: [PATCH] wif version byte change: wif compressed version byte is the pubkey version byte, not the address version byte (so x80 or xef). This is updated in the scripts and the Qt code for exporting or displaying. sendtomany update: script now works with segwit or non-segwit inputs (segwit by default), still requiring a utxo and a wif compressed privkey as input. small clean up in electrum: remove nonresponsive testnet server remove unwanted print statement from fee estimate --- jmclient/jmclient/electrum_data.py | 2 +- jmclient/jmclient/electruminterface.py | 1 - jmclient/jmclient/wallet_utils.py | 12 ++++++------ scripts/joinmarket-qt.py | 6 +++--- scripts/sendtomany.py | 25 ++++++++++++++++++------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/jmclient/jmclient/electrum_data.py b/jmclient/jmclient/electrum_data.py index 9eedc1b..96d06a9 100644 --- a/jmclient/jmclient/electrum_data.py +++ b/jmclient/jmclient/electrum_data.py @@ -247,7 +247,7 @@ def set_electrum_testnet(): DEFAULT_SERVERS = { 'testnetnode.arihanc.com': {'t':'51001', 's':'51002'}, 'testnet1.bauerj.eu': {'t':'51001', 's':'51002'}, - '14.3.140.101': {'t':'51001', 's':'51002'}, + #'14.3.140.101': {'t':'51001', 's':'51002'}, 'testnet.hsmiths.com': {'t':'53011', 's':'53012'}, 'electrum.akinbo.org': {'t':'51001', 's':'51002'}, 'ELEX05.blackpole.online': {'t':'52011', 's':'52002'},} diff --git a/jmclient/jmclient/electruminterface.py b/jmclient/jmclient/electruminterface.py index 622fbee..b9b7e0f 100644 --- a/jmclient/jmclient/electruminterface.py +++ b/jmclient/jmclient/electruminterface.py @@ -407,7 +407,6 @@ class ElectrumInterface(BlockchainInterface): return result def estimate_fee_per_kb(self, N): - print("N is: " + str(N)) if super(ElectrumInterface, self).fee_per_kb_has_been_manually_set(N): return int(random.uniform(N * float(0.8), N * float(1.2))) fee_info = self.get_from_electrum('blockchain.estimatefee', N, blocking=True) diff --git a/jmclient/jmclient/wallet_utils.py b/jmclient/jmclient/wallet_utils.py index 27eb84f..aceb496 100644 --- a/jmclient/jmclient/wallet_utils.py +++ b/jmclient/jmclient/wallet_utils.py @@ -10,7 +10,7 @@ from mnemonic import Mnemonic from optparse import OptionParser import getpass from jmclient import (get_network, Wallet, Bip39Wallet, podle, - encryptData, get_p2sh_vbyte, jm_single, + encryptData, get_p2sh_vbyte, get_p2pk_vbyte, jm_single, mn_decode, mn_encode, BitcoinCoreInterface, JsonRpcError, sync_wallet, WalletError, SegwitWallet) from jmbase.support import get_password @@ -270,7 +270,7 @@ def get_imported_privkey_branch(wallet, m, showprivkey): used = ('used' if balance > 0.0 else 'empty') if showprivkey: wip_privkey = btc.wif_compressed_privkey( - privkey, get_p2sh_vbyte()) + privkey, get_p2pk_vbyte()) else: wip_privkey = '' entries.append(WalletViewEntry("m/0", m, -1, @@ -290,7 +290,7 @@ def wallet_showutxos(wallet, showprivkey): 'tries': tries, 'tries_remaining': tries_remaining, 'external': False} if showprivkey: - wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2sh_vbyte()) + wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte()) unsp[u]['privkey'] = wifkey used_commitments, external_commitments = podle.get_podle_commitments() @@ -329,7 +329,7 @@ def wallet_display(wallet, gaplimit, showprivkey, displayall=False, used = 'used' if k < wallet.index[m][forchange] else 'new' if showprivkey: privkey = btc.wif_compressed_privkey( - wallet.get_key(m, forchange, k), get_p2sh_vbyte()) + wallet.get_key(m, forchange, k), get_p2pk_vbyte()) else: privkey = '' if (displayall or balance > 0 or @@ -673,7 +673,7 @@ def wallet_importprivkey(wallet, mixdepth): # TODO is there any point in only accepting wif format? check what # other wallets do privkey_bin = btc.from_wif_privkey(privkey, - vbyte=get_p2sh_vbyte()).decode('hex')[:-1] + vbyte=get_p2pk_vbyte()).decode('hex')[:-1] encrypted_privkey = encryptData(wallet.password_key, privkey_bin) if 'imported_keys' not in wallet.walletdata: wallet.walletdata['imported_keys'] = [] @@ -692,7 +692,7 @@ def wallet_dumpprivkey(wallet, hdpath): if pathlist and len(pathlist) == 5: cointype, purpose, m, forchange, k = pathlist key = wallet.get_key(m, forchange, k) - wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2sh_vbyte()) + wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte()) return wifkey else: return hdpath + " is not a valid hd wallet path" diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index e47b166..e17ba0d 100644 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -53,7 +53,7 @@ JM_CORE_VERSION = '0.3.0' JM_GUI_VERSION = '6' from jmclient import (load_program_config, get_network, SegwitWallet, - get_p2sh_vbyte, jm_single, validate_address, + get_p2sh_vbyte, get_p2pk_vbyte, jm_single, validate_address, get_log, weighted_order_choose, Taker, JMClientProtocolFactory, WalletError, start_reactor, get_schedule, get_tumble_schedule, @@ -1223,7 +1223,7 @@ class JMMainWindow(QMainWindow): priv = self.wallet.get_key_from_addr(addr) private_keys[addr] = btc.wif_compressed_privkey( priv, - vbyte=111) + vbyte=get_p2pk_vbyte()) d.emit(QtCore.SIGNAL('computing_privkeys')) d.emit(QtCore.SIGNAL('show_privkeys')) @@ -1256,7 +1256,7 @@ class JMMainWindow(QMainWindow): #sanity check if not addr == btc.pubkey_to_p2sh_p2wpkh_address( btc.privkey_to_pubkey( - btc.from_wif_privkey(pk, vbyte=111) + btc.from_wif_privkey(pk, vbyte=get_p2pk_vbyte()) ), get_p2sh_vbyte()): JMQtMessageBox(None, "Failed to create privkey export -" +\ " critical error in key parsing.", diff --git a/scripts/sendtomany.py b/scripts/sendtomany.py index 252afc7..a7c58be 100644 --- a/scripts/sendtomany.py +++ b/scripts/sendtomany.py @@ -12,23 +12,25 @@ from pprint import pformat from optparse import OptionParser import jmclient.btc as btc from jmclient import (load_program_config, estimate_tx_fee, jm_single, - get_p2pk_vbyte, validate_address, get_log, + get_p2sh_vbyte, get_p2pk_vbyte, validate_address, get_log, get_utxo_info, validate_utxo_data, quit) log = get_log() -def sign(utxo, priv, destaddrs): +def sign(utxo, priv, destaddrs, segwit=True): """Sign a tx sending the amount amt, from utxo utxo, equally to each of addresses in list destaddrs, after fees; the purpose is to create a large - number of utxos. + number of utxos. If segwit=True the (single) utxo is assumed to + be of type segwit p2sh/p2wpkh. """ - results = validate_utxo_data([(utxo, priv)], retrieve=True) + results = validate_utxo_data([(utxo, priv)], retrieve=True, segwit=segwit) if not results: return False assert results[0][0] == utxo amt = results[0][1] ins = [utxo] - estfee = estimate_tx_fee(1, len(destaddrs)) + txtype = 'p2sh-p2wpkh' if segwit else 'p2pkh' + estfee = estimate_tx_fee(1, len(destaddrs), txtype=txtype) outs = [] share = int((amt - estfee) / len(destaddrs)) fee = amt - share*len(destaddrs) @@ -37,8 +39,9 @@ def sign(utxo, priv, destaddrs): for i, addr in enumerate(destaddrs): outs.append({'address': addr, 'value': share}) unsigned_tx = btc.mktx(ins, outs) + amtforsign = amt if segwit else None return btc.sign(unsigned_tx, 0, btc.from_wif_privkey( - priv, vbyte=get_p2pk_vbyte())) + priv, vbyte=get_p2pk_vbyte()), amount=amtforsign) def main(): parser = OptionParser( @@ -77,6 +80,14 @@ def main(): help='only validate the provided utxos (file or command line), not add', default=False ) + parser.add_option( + '-n', + '--non-segwit-input', + action='store_true', + dest='nonsegwit', + help='input is p2pkh ("1" address), not segwit; if not used, input is assumed to be segwit type.', + default=False + ) (options, args) = parser.parse_args() load_program_config() if len(args) < 2: @@ -91,7 +102,7 @@ def main(): for d in destaddrs: if not validate_address(d): quit(parser, "Address was not valid; wrong network?: " + d) - txsigned = sign(u, priv, destaddrs) + txsigned = sign(u, priv, destaddrs, segwit = not options.nonsegwit) log.debug("Got signed transaction:\n" + txsigned) log.debug("Deserialized:") log.debug(pformat(btc.deserialize(txsigned)))