support for multisig functions
This commit is contained in:
parent
f971c80d58
commit
972ba397d1
58
electrum
58
electrum
|
@ -91,6 +91,10 @@ options:\n --fee, -f: set transaction fee\n --fromaddr, -s: send from address
|
||||||
'unfreeze':'',
|
'unfreeze':'',
|
||||||
'prioritize':'',
|
'prioritize':'',
|
||||||
'unprioritize':'',
|
'unprioritize':'',
|
||||||
|
'createmultisig':'similar to bitcoind\'s command',
|
||||||
|
'createrawtransaction':'similar to bitcoind\'s command',
|
||||||
|
'decoderawtransaction':'similar to bitcoind\'s command',
|
||||||
|
'signrawtransaction':'similar to bitcoind\'s command',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,10 +107,12 @@ offline_commands = [ 'password', 'mktx', 'signtx',
|
||||||
'importprivkey', 'seed',
|
'importprivkey', 'seed',
|
||||||
'deseed','reseed',
|
'deseed','reseed',
|
||||||
'freeze','unfreeze',
|
'freeze','unfreeze',
|
||||||
'prioritize','unprioritize']
|
'prioritize','unprioritize',
|
||||||
|
'createmultisig', 'createrawtransaction', 'decoderawtransaction', 'signrawtransaction'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage' ]
|
protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage', 'signrawtransaction' ]
|
||||||
|
|
||||||
# get password routine
|
# get password routine
|
||||||
def prompt_password(prompt, confirm=True):
|
def prompt_password(prompt, confirm=True):
|
||||||
|
@ -690,5 +696,53 @@ if __name__ == '__main__':
|
||||||
print_msg(wallet.unprioritize(addr))
|
print_msg(wallet.unprioritize(addr))
|
||||||
|
|
||||||
|
|
||||||
|
elif cmd == 'createmultisig':
|
||||||
|
import ast
|
||||||
|
from lib.bitcoin import *
|
||||||
|
num = int(args[1])
|
||||||
|
pubkeys = ast.literal_eval(args[2])
|
||||||
|
assert isinstance(pubkeys,list)
|
||||||
|
s = multisig_script(pubkeys, num)
|
||||||
|
out = { "address": hash_160_to_bc_address(hash_160(s.decode('hex')), 5), "redeemScript":s }
|
||||||
|
print_json(out)
|
||||||
|
|
||||||
|
|
||||||
|
elif cmd == 'createrawtransaction':
|
||||||
|
import ast
|
||||||
|
inputs = ast.literal_eval(args[1])
|
||||||
|
outputs = ast.literal_eval(args[2])
|
||||||
|
inputs = map(lambda x: (None, None, x["txid"], x["vout"], None, None), inputs)
|
||||||
|
outputs = map(lambda x: (x[0],int(x[1]*1e8)), outputs.items())
|
||||||
|
tx = raw_tx(inputs, outputs, for_sig = -1) # for_sig=-1 means do not sign
|
||||||
|
print_msg( tx )
|
||||||
|
|
||||||
|
|
||||||
|
elif cmd == 'decoderawtransaction':
|
||||||
|
print_json( bitcoin.deserialize(args[1]) )
|
||||||
|
|
||||||
|
|
||||||
|
elif cmd == 'signrawtransaction':
|
||||||
|
d = bitcoin.deserialize(args[1])
|
||||||
|
txouts = args[2] if len(args)>2 else []
|
||||||
|
private_keys = args[3] if len(args)>3 else []
|
||||||
|
|
||||||
|
inputs = []
|
||||||
|
for x in d['inputs']:
|
||||||
|
txid = x["prevout_hash"]
|
||||||
|
nout = x["prevout_n"]
|
||||||
|
tx = wallet.transactions.get(txid)
|
||||||
|
txout = tx['outputs'][nout]
|
||||||
|
addr = txout['address']
|
||||||
|
v = txout['value']
|
||||||
|
inputs.append( (addr, v, txid, nout, txout['raw_output_script'], [(None,None)] ) )
|
||||||
|
|
||||||
|
outputs = map(lambda x: (x['address'],x['value']), d['outputs'])
|
||||||
|
print_error("inputs", inputs)
|
||||||
|
print_error("outputs", outputs)
|
||||||
|
|
||||||
|
tx = wallet.signed_tx( inputs, outputs, password )
|
||||||
|
print_msg(tx)
|
||||||
|
|
||||||
|
|
||||||
if cmd not in offline_commands and not options.offline:
|
if cmd not in offline_commands and not options.offline:
|
||||||
synchronizer.stop()
|
synchronizer.stop()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from version import ELECTRUM_VERSION
|
from version import ELECTRUM_VERSION
|
||||||
from util import format_satoshis, print_msg, print_error, set_verbosity
|
from util import format_satoshis, print_msg, print_json, print_error, set_verbosity
|
||||||
from i18n import set_language
|
from i18n import set_language
|
||||||
from wallet import WalletSynchronizer
|
from wallet import WalletSynchronizer
|
||||||
from wallet_factory import WalletFactory as Wallet
|
from wallet_factory import WalletFactory as Wallet
|
||||||
|
|
|
@ -378,14 +378,33 @@ def raw_tx( inputs, outputs, for_sig = None ):
|
||||||
s += var_int( len(tx_filter(script))/2 ) # script length
|
s += var_int( len(tx_filter(script))/2 ) # script length
|
||||||
s += script # script
|
s += script # script
|
||||||
s += int_to_hex(0,4) # lock time
|
s += int_to_hex(0,4) # lock time
|
||||||
if for_sig is not None: s += int_to_hex(1, 4) # hash type
|
if for_sig is not None and for_sig != 1: s += int_to_hex(1, 4) # hash type
|
||||||
return tx_filter(s)
|
return tx_filter(s)
|
||||||
|
|
||||||
|
|
||||||
def multisig_script(public_keys):
|
def deserialize(raw_tx):
|
||||||
|
import deserialize
|
||||||
|
vds = deserialize.BCDataStream()
|
||||||
|
vds.write(raw_tx.decode('hex'))
|
||||||
|
return deserialize.parse_Transaction(vds)
|
||||||
|
|
||||||
|
|
||||||
|
def multisig_script(public_keys, num=None):
|
||||||
# supports only "2 of 2", and "2 of 3" transactions
|
# supports only "2 of 2", and "2 of 3" transactions
|
||||||
n = len(public_keys)
|
n = len(public_keys)
|
||||||
|
|
||||||
|
if num is None:
|
||||||
|
num = n
|
||||||
|
|
||||||
|
assert num <= n and n <= 3 and n >= 2
|
||||||
|
|
||||||
|
if num==2:
|
||||||
s = '52'
|
s = '52'
|
||||||
|
elif num == 3:
|
||||||
|
s = '53'
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
for k in public_keys:
|
for k in public_keys:
|
||||||
s += var_int(len(k)/2)
|
s += var_int(len(k)/2)
|
||||||
s += k
|
s += k
|
||||||
|
|
|
@ -22,6 +22,12 @@ def print_msg(*args):
|
||||||
sys.stdout.write(" ".join(args) + "\n")
|
sys.stdout.write(" ".join(args) + "\n")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def print_json(obj):
|
||||||
|
import json
|
||||||
|
s = json.dumps(obj,sort_keys = True, indent = 4)
|
||||||
|
sys.stdout.write(s + "\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
def check_windows_wallet_migration():
|
def check_windows_wallet_migration():
|
||||||
if os.path.exists(os.path.join(os.environ["LOCALAPPDATA"], "Electrum")):
|
if os.path.exists(os.path.join(os.environ["LOCALAPPDATA"], "Electrum")):
|
||||||
|
|
Loading…
Reference in New Issue