2020-02-15 21:52:24 +02:00
|
|
|
#!/usr/bin/env python3
|
2016-11-25 20:44:01 +02:00
|
|
|
"""A simple command line tool to create a bunch
|
|
|
|
|
of utxos from one (thus giving more potential commitments
|
|
|
|
|
for a Joinmarket user, although of course it may be useful
|
|
|
|
|
for other reasons).
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from optparse import OptionParser
|
2018-12-18 19:55:05 +01:00
|
|
|
import jmbitcoin as btc
|
2021-02-15 12:59:12 +00:00
|
|
|
from jmbase import (get_log, jmprint, bintohex, utxostr_to_utxo,
|
2024-02-22 20:28:18 +02:00
|
|
|
IndentedHelpFormatterWithNL, cli_prompt_user_yesno)
|
2018-10-08 00:07:28 +02:00
|
|
|
from jmclient import load_program_config, estimate_tx_fee, jm_single,\
|
2020-04-28 19:47:08 +01:00
|
|
|
validate_address, get_utxo_info, add_base_options,\
|
2020-11-13 17:33:44 +00:00
|
|
|
validate_utxo_data, quit, BTCEngine, compute_tx_locktime
|
2018-10-08 00:07:28 +02:00
|
|
|
|
2016-11-25 20:44:01 +02:00
|
|
|
log = get_log()
|
|
|
|
|
|
2020-11-13 17:33:44 +00:00
|
|
|
def sign(utxo, priv, destaddrs, utxo_address_type):
|
2016-11-25 20:44:01 +02:00
|
|
|
"""Sign a tx sending the amount amt, from utxo utxo,
|
|
|
|
|
equally to each of addresses in list destaddrs,
|
2020-11-13 17:33:44 +00:00
|
|
|
after fees; the purpose is to create multiple utxos.
|
|
|
|
|
utxo_address_type must be one of p2sh-p2wpkh/p2wpkh/p2pkh.
|
2016-11-25 20:44:01 +02:00
|
|
|
"""
|
2020-11-13 17:33:44 +00:00
|
|
|
results = validate_utxo_data([(utxo, priv)], retrieve=True,
|
|
|
|
|
utxo_address_type=utxo_address_type)
|
2016-11-25 20:44:01 +02:00
|
|
|
if not results:
|
|
|
|
|
return False
|
|
|
|
|
assert results[0][0] == utxo
|
|
|
|
|
amt = results[0][1]
|
|
|
|
|
ins = [utxo]
|
2020-11-13 17:33:44 +00:00
|
|
|
estfee = estimate_tx_fee(1, len(destaddrs), txtype=utxo_address_type)
|
2016-11-25 20:44:01 +02:00
|
|
|
outs = []
|
|
|
|
|
share = int((amt - estfee) / len(destaddrs))
|
|
|
|
|
fee = amt - share*len(destaddrs)
|
|
|
|
|
assert fee >= estfee
|
|
|
|
|
log.info("Using fee: " + str(fee))
|
|
|
|
|
for i, addr in enumerate(destaddrs):
|
|
|
|
|
outs.append({'address': addr, 'value': share})
|
2020-11-13 17:33:44 +00:00
|
|
|
tx = btc.make_shuffled_tx(ins, outs, version=2, locktime=compute_tx_locktime())
|
|
|
|
|
amtforsign = amt if utxo_address_type != "p2pkh" else None
|
python-bitcointx backend for jmbitcoin.
Replaces core transaction, address, serialization
and sign functionality for Bitcoin with
python-bitcointx backend.
Removes bech32 and btscript
modules from jmbitcoin. Removes all string,
hex, binary conversion routines. A generic
hex/binary conversion now is added to jmbase.
Removes all transaction serialization and
deserialization routines. Removes the now
irrelevant test modules.
Remaining functions in jmbitcoin remove any parsing of
hex format, requiring callers to use binary only.
One additional test added, testing the remaining
function in secp256k1_transaction.py: the signing
of transactions. Deserialized form is now
bitcointx.CMutableTransaction.
For jmbase, in addition to the above, generic conversions
for utxos to and from strings is added, and a dynamic conversion
for AMP messages to binary-only. Within the code, utxos are
now only in (binarytxid, int) form, except where converted
for communcation.
Tthe largest part of the changes are
the modifications to jmbitcoin calls in jmclient;
as well as different encapsulation with CMutableTransaction,
there is also a removal of some but not all hex parsing;
it remains for rpc calls to Core and for AMP message
parsing. Backwards compatibility must be ensured so some
joinmarket protocol messages still use hex, and it is
also preserved in persistence of PoDLE data.
As part of this, some significant simplification of
certain legacy functions within the wallet has been done.
jmdaemon is entirely unaltered (save for one test which
simulates jmclient code).
2020-02-17 14:40:31 +00:00
|
|
|
rawpriv, _ = BTCEngine.wif_to_privkey(priv)
|
2020-11-13 17:33:44 +00:00
|
|
|
if utxo_address_type == "p2wpkh":
|
|
|
|
|
native = utxo_address_type
|
|
|
|
|
else:
|
|
|
|
|
native = False
|
|
|
|
|
success, msg = btc.sign(tx, 0, rawpriv, amount=amtforsign, native=native)
|
python-bitcointx backend for jmbitcoin.
Replaces core transaction, address, serialization
and sign functionality for Bitcoin with
python-bitcointx backend.
Removes bech32 and btscript
modules from jmbitcoin. Removes all string,
hex, binary conversion routines. A generic
hex/binary conversion now is added to jmbase.
Removes all transaction serialization and
deserialization routines. Removes the now
irrelevant test modules.
Remaining functions in jmbitcoin remove any parsing of
hex format, requiring callers to use binary only.
One additional test added, testing the remaining
function in secp256k1_transaction.py: the signing
of transactions. Deserialized form is now
bitcointx.CMutableTransaction.
For jmbase, in addition to the above, generic conversions
for utxos to and from strings is added, and a dynamic conversion
for AMP messages to binary-only. Within the code, utxos are
now only in (binarytxid, int) form, except where converted
for communcation.
Tthe largest part of the changes are
the modifications to jmbitcoin calls in jmclient;
as well as different encapsulation with CMutableTransaction,
there is also a removal of some but not all hex parsing;
it remains for rpc calls to Core and for AMP message
parsing. Backwards compatibility must be ensured so some
joinmarket protocol messages still use hex, and it is
also preserved in persistence of PoDLE data.
As part of this, some significant simplification of
certain legacy functions within the wallet has been done.
jmdaemon is entirely unaltered (save for one test which
simulates jmclient code).
2020-02-17 14:40:31 +00:00
|
|
|
assert success, msg
|
|
|
|
|
return tx
|
2021-02-15 12:59:12 +00:00
|
|
|
|
|
|
|
|
description="""For creating multiple utxos from one (for commitments in JM).
|
|
|
|
|
Provide a utxo in form txid:N that has some unspent coins;
|
|
|
|
|
Specify a list of destination addresses and the coins will
|
|
|
|
|
be split equally between them (after bitcoin fees).
|
|
|
|
|
You'll be prompted to enter the private key for the utxo
|
|
|
|
|
during the run; it must be in WIF compressed format.
|
|
|
|
|
After the transaction is completed, the utxo strings for
|
|
|
|
|
the new outputs will be shown.
|
|
|
|
|
Note that these utxos will not be ready for use as external
|
|
|
|
|
commitments in Joinmarket until 5 confirmations have passed.
|
|
|
|
|
BE CAREFUL about handling private keys!
|
|
|
|
|
Don't do this in insecure environments.
|
|
|
|
|
Works only with p2pkh ('1'), p2sh-p2wpkh (segwit '3') or
|
|
|
|
|
p2wpkh ('bc1') addresses.
|
|
|
|
|
utxos - set segwit=False in the POLICY section of
|
|
|
|
|
joinmarket.cfg for the former."""
|
|
|
|
|
|
2016-11-25 20:44:01 +02:00
|
|
|
def main():
|
|
|
|
|
parser = OptionParser(
|
|
|
|
|
usage=
|
|
|
|
|
'usage: %prog [options] utxo destaddr1 destaddr2 ..',
|
2021-02-15 12:59:12 +00:00
|
|
|
description=description, formatter=IndentedHelpFormatterWithNL())
|
2016-11-25 20:44:01 +02:00
|
|
|
parser.add_option(
|
2020-11-13 17:33:44 +00:00
|
|
|
'-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=""
|
2017-09-19 14:29:09 +02:00
|
|
|
)
|
2019-12-19 17:36:29 +00:00
|
|
|
add_base_options(parser)
|
2016-11-25 20:44:01 +02:00
|
|
|
(options, args) = parser.parse_args()
|
2019-12-19 17:36:29 +00:00
|
|
|
load_program_config(config_path=options.datadir)
|
2016-11-25 20:44:01 +02:00
|
|
|
if len(args) < 2:
|
|
|
|
|
quit(parser, 'Invalid syntax')
|
|
|
|
|
u = args[0]
|
2018-11-29 06:46:15 +08:00
|
|
|
priv = input(
|
2016-11-25 20:44:01 +02:00
|
|
|
'input private key for ' + u + ', in WIF compressed format : ')
|
|
|
|
|
u, priv = get_utxo_info(','.join([u, priv]))
|
|
|
|
|
if not u:
|
|
|
|
|
quit(parser, "Failed to parse utxo info: " + u)
|
|
|
|
|
destaddrs = args[1:]
|
|
|
|
|
for d in destaddrs:
|
|
|
|
|
if not validate_address(d):
|
|
|
|
|
quit(parser, "Address was not valid; wrong network?: " + d)
|
python-bitcointx backend for jmbitcoin.
Replaces core transaction, address, serialization
and sign functionality for Bitcoin with
python-bitcointx backend.
Removes bech32 and btscript
modules from jmbitcoin. Removes all string,
hex, binary conversion routines. A generic
hex/binary conversion now is added to jmbase.
Removes all transaction serialization and
deserialization routines. Removes the now
irrelevant test modules.
Remaining functions in jmbitcoin remove any parsing of
hex format, requiring callers to use binary only.
One additional test added, testing the remaining
function in secp256k1_transaction.py: the signing
of transactions. Deserialized form is now
bitcointx.CMutableTransaction.
For jmbase, in addition to the above, generic conversions
for utxos to and from strings is added, and a dynamic conversion
for AMP messages to binary-only. Within the code, utxos are
now only in (binarytxid, int) form, except where converted
for communcation.
Tthe largest part of the changes are
the modifications to jmbitcoin calls in jmclient;
as well as different encapsulation with CMutableTransaction,
there is also a removal of some but not all hex parsing;
it remains for rpc calls to Core and for AMP message
parsing. Backwards compatibility must be ensured so some
joinmarket protocol messages still use hex, and it is
also preserved in persistence of PoDLE data.
As part of this, some significant simplification of
certain legacy functions within the wallet has been done.
jmdaemon is entirely unaltered (save for one test which
simulates jmclient code).
2020-02-17 14:40:31 +00:00
|
|
|
success, utxo = utxostr_to_utxo(u)
|
|
|
|
|
if not success:
|
|
|
|
|
quit(parser, "Failed to load utxo from string: " + utxo)
|
2020-11-13 17:33:44 +00:00
|
|
|
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)
|
2018-05-02 22:14:47 +02:00
|
|
|
if not txsigned:
|
|
|
|
|
log.info("Transaction signing operation failed, see debug messages for details.")
|
|
|
|
|
return
|
python-bitcointx backend for jmbitcoin.
Replaces core transaction, address, serialization
and sign functionality for Bitcoin with
python-bitcointx backend.
Removes bech32 and btscript
modules from jmbitcoin. Removes all string,
hex, binary conversion routines. A generic
hex/binary conversion now is added to jmbase.
Removes all transaction serialization and
deserialization routines. Removes the now
irrelevant test modules.
Remaining functions in jmbitcoin remove any parsing of
hex format, requiring callers to use binary only.
One additional test added, testing the remaining
function in secp256k1_transaction.py: the signing
of transactions. Deserialized form is now
bitcointx.CMutableTransaction.
For jmbase, in addition to the above, generic conversions
for utxos to and from strings is added, and a dynamic conversion
for AMP messages to binary-only. Within the code, utxos are
now only in (binarytxid, int) form, except where converted
for communcation.
Tthe largest part of the changes are
the modifications to jmbitcoin calls in jmclient;
as well as different encapsulation with CMutableTransaction,
there is also a removal of some but not all hex parsing;
it remains for rpc calls to Core and for AMP message
parsing. Backwards compatibility must be ensured so some
joinmarket protocol messages still use hex, and it is
also preserved in persistence of PoDLE data.
As part of this, some significant simplification of
certain legacy functions within the wallet has been done.
jmdaemon is entirely unaltered (save for one test which
simulates jmclient code).
2020-02-17 14:40:31 +00:00
|
|
|
log.info("Got signed transaction:\n" + bintohex(txsigned.serialize()))
|
2020-11-13 17:33:44 +00:00
|
|
|
log.info(btc.human_readable_transaction(txsigned))
|
2024-02-22 20:28:18 +02:00
|
|
|
if not cli_prompt_user_yesno('Would you like to push to the network?'):
|
2016-11-25 20:44:01 +02:00
|
|
|
log.info("You chose not to broadcast the transaction, quitting.")
|
|
|
|
|
return
|
python-bitcointx backend for jmbitcoin.
Replaces core transaction, address, serialization
and sign functionality for Bitcoin with
python-bitcointx backend.
Removes bech32 and btscript
modules from jmbitcoin. Removes all string,
hex, binary conversion routines. A generic
hex/binary conversion now is added to jmbase.
Removes all transaction serialization and
deserialization routines. Removes the now
irrelevant test modules.
Remaining functions in jmbitcoin remove any parsing of
hex format, requiring callers to use binary only.
One additional test added, testing the remaining
function in secp256k1_transaction.py: the signing
of transactions. Deserialized form is now
bitcointx.CMutableTransaction.
For jmbase, in addition to the above, generic conversions
for utxos to and from strings is added, and a dynamic conversion
for AMP messages to binary-only. Within the code, utxos are
now only in (binarytxid, int) form, except where converted
for communcation.
Tthe largest part of the changes are
the modifications to jmbitcoin calls in jmclient;
as well as different encapsulation with CMutableTransaction,
there is also a removal of some but not all hex parsing;
it remains for rpc calls to Core and for AMP message
parsing. Backwards compatibility must be ensured so some
joinmarket protocol messages still use hex, and it is
also preserved in persistence of PoDLE data.
As part of this, some significant simplification of
certain legacy functions within the wallet has been done.
jmdaemon is entirely unaltered (save for one test which
simulates jmclient code).
2020-02-17 14:40:31 +00:00
|
|
|
jm_single().bc_interface.pushtx(txsigned.serialize())
|
2016-11-25 20:44:01 +02:00
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|
2019-01-08 18:59:07 +01:00
|
|
|
jmprint('done', "success")
|