@ -11,26 +11,24 @@ import jmbitcoin as btc
from jmbase import get_log , jmprint , bintohex , utxostr_to_utxo
from jmclient import load_program_config , estimate_tx_fee , jm_single , \
validate_address , get_utxo_info , add_base_options , \
validate_utxo_data , quit , BTCEngine
validate_utxo_data , quit , BTCEngine , compute_tx_locktime
log = get_log ( )
def sign ( utxo , priv , destaddrs , segwit = Tru e) :
def sign ( utxo , priv , destaddrs , utxo_address_typ e) :
""" 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 . If segwit = True the ( single ) utxo is assumed to
be of type segwit p2sh / p2wpkh .
after fees ; the purpose is to create multiple utxos .
utxo_address_type must be one of p2sh - p2wpkh / p2wpkh / p2pkh .
"""
results = validate_utxo_data ( [ ( utxo , priv ) ] , retrieve = True , segwit = segwit )
results = validate_utxo_data ( [ ( utxo , priv ) ] , retrieve = True ,
utxo_address_type = utxo_address_type )
if not results :
return False
assert results [ 0 ] [ 0 ] == utxo
amt = results [ 0 ] [ 1 ]
ins = [ utxo ]
# TODO extend to other utxo types
txtype = ' p2sh-p2wpkh ' if segwit else ' p2pkh '
estfee = estimate_tx_fee ( 1 , len ( destaddrs ) , txtype = txtype )
estfee = estimate_tx_fee ( 1 , len ( destaddrs ) , txtype = utxo_address_type )
outs = [ ]
share = int ( ( amt - estfee ) / len ( destaddrs ) )
fee = amt - share * len ( destaddrs )
@ -38,10 +36,14 @@ def sign(utxo, priv, destaddrs, segwit=True):
log . info ( " Using fee: " + str ( fee ) )
for i , addr in enumerate ( destaddrs ) :
outs . append ( { ' address ' : addr , ' value ' : share } )
tx = btc . mktx ( ins , outs )
amtforsign = amt if segwit else None
tx = btc . ma ke_shuffled_ tx ( ins , outs , version = 2 , locktime = compute_tx_locktime ( ) )
amtforsign = amt if utxo_address_type != " p2pkh " else None
rawpriv , _ = BTCEngine . wif_to_privkey ( priv )
success , msg = btc . sign ( tx , 0 , rawpriv , amount = amtforsign )
if utxo_address_type == " p2wpkh " :
native = utxo_address_type
else :
native = False
success , msg = btc . sign ( tx , 0 , rawpriv , amount = amtforsign , native = native )
assert success , msg
return tx
@ -69,28 +71,14 @@ def main():
" joinmarket.cfg for the former. "
)
parser . add_option (
' -v ' ,
' --validate-utxos ' ,
action = ' store_true ' ,
dest = ' validate ' ,
help = ' validate the utxos and pubkeys provided against the blockchain ' ,
default = False
)
parser . add_option (
' -o ' ,
' --validate-only ' ,
action = ' store_true ' ,
dest = ' vonly ' ,
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
' -t ' ,
' --utxo-address-type ' ,
action = ' store ' ,
dest = ' utxo_address_type ' ,
help = ( ' type of address of coin being spent - one of " p2pkh " , " p2wpkh " , " p2sh-p2wpkh " . '
' No other scriptpubkey types (e.g. multisig) are supported. If not set, we default '
' to what is in joinmarket.cfg. ' ) ,
default = " "
)
add_base_options ( parser )
( options , args ) = parser . parse_args ( )
@ -110,13 +98,21 @@ def main():
success , utxo = utxostr_to_utxo ( u )
if not success :
quit ( parser , " Failed to load utxo from string: " + utxo )
txsigned = sign ( utxo , priv , destaddrs , segwit = not options . nonsegwit )
if options . utxo_address_type == " " :
if jm_single ( ) . config . get ( " POLICY " , " segwit " ) == " false " :
utxo_address_type = " p2pkh "
elif jm_single ( ) . config . get ( " POLICY " , " native " ) == " false " :
utxo_address_type = " p2sh-p2wpkh "
else :
utxo_address_type = " p2wpkh "
else :
utxo_address_type = options . utxo_address_type
txsigned = sign ( utxo , priv , destaddrs , utxo_address_type )
if not txsigned :
log . info ( " Transaction signing operation failed, see debug messages for details. " )
return
log . info ( " Got signed transaction: \n " + bintohex ( txsigned . serialize ( ) ) )
log . debug ( " Deserialized: " )
log . debug ( pformat ( str ( txsigned ) ) )
log . info ( btc . human_readable_transaction ( txsigned ) )
if input ( ' Would you like to push to the network? (y/n): ' ) [ 0 ] != ' y ' :
log . info ( " You chose not to broadcast the transaction, quitting. " )
return