offline wallets sign transactions using KeyID
This commit is contained in:
parent
c4f7ce6bae
commit
b8a71ff00c
52
electrum
52
electrum
|
@ -636,7 +636,11 @@ if __name__ == '__main__':
|
||||||
r, h = wallet.sendtx( tx )
|
r, h = wallet.sendtx( tx )
|
||||||
print_msg(h)
|
print_msg(h)
|
||||||
else:
|
else:
|
||||||
print_json({"hex":str(tx), "complete":tx.is_complete})
|
out = {"hex":str(tx), "complete":tx.is_complete}
|
||||||
|
if not tx.is_complete:
|
||||||
|
import json
|
||||||
|
out['input_info'] = repr(tx.inputs_info).replace(' ','')
|
||||||
|
print_json(out)
|
||||||
|
|
||||||
if is_temporary:
|
if is_temporary:
|
||||||
wallet.imported_keys.pop(from_addr)
|
wallet.imported_keys.pop(from_addr)
|
||||||
|
@ -732,41 +736,55 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
elif cmd == 'signrawtransaction':
|
elif cmd == 'signrawtransaction':
|
||||||
tx = Transaction(args[1])
|
tx = Transaction(args[1])
|
||||||
txouts = ast.literal_eval(args[2]) if len(args)>2 else []
|
inputs_info = ast.literal_eval(args[2]) if len(args)>2 else []
|
||||||
private_keys = ast.literal_eval(args[3]) if len(args)>3 else {}
|
private_keys = ast.literal_eval(args[3]) if len(args)>3 else {}
|
||||||
unspent_coins = wallet.get_unspent_coins()
|
unspent_coins = wallet.get_unspent_coins()
|
||||||
|
|
||||||
|
# convert private_keys to dict
|
||||||
|
pk = {}
|
||||||
|
for sec in private_keys:
|
||||||
|
address = bitcoin.address_from_private_key(sec)
|
||||||
|
pk[address] = sec
|
||||||
|
private_keys = pk
|
||||||
|
|
||||||
for txin in tx.inputs:
|
for txin in tx.inputs:
|
||||||
# convert to own format
|
# convert to own format
|
||||||
txin['tx_hash'] = txin['prevout_hash']
|
txin['tx_hash'] = txin['prevout_hash']
|
||||||
txin['index'] = txin['prevout_n']
|
txin['index'] = txin['prevout_n']
|
||||||
|
|
||||||
for txout in txouts:
|
for item in inputs_info:
|
||||||
if txout.get('txid') == txin['tx_hash'] and txout.get('vout') == txin['index']:
|
if item.get('txid') == txin['tx_hash'] and item.get('vout') == txin['index']:
|
||||||
txin['raw_output_script'] = txout['scriptPubKey']
|
txin['raw_output_script'] = item['scriptPubKey']
|
||||||
txin['redeemScript'] = txout['redeemScript']
|
txin['redeemScript'] = item.get('redeemScript')
|
||||||
|
txin['electrumKeyID'] = item.get('electrumKeyID')
|
||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for item in unspent_coins:
|
for item in unspent_coins:
|
||||||
if txin['tx_hash'] == item['tx_hash'] and txin['index'] == item['index']:
|
if txin['tx_hash'] == item['tx_hash'] and txin['index'] == item['index']:
|
||||||
txin['address'] = item['address']
|
|
||||||
txin['raw_output_script'] = item['raw_output_script']
|
txin['raw_output_script'] = item['raw_output_script']
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# if neither, we might want to get it from the server..
|
# if neither, we might want to get it from the server..
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if not private_keys:
|
# find the address:
|
||||||
for txin in tx.inputs:
|
from lib import deserialize
|
||||||
addr = txin['address']
|
if txin.get('electrumKeyID'):
|
||||||
private_keys[addr] = wallet.get_private_key(addr, password)
|
n, for_change = txin.get('electrumKeyID')
|
||||||
else:
|
sec = wallet.sequence.get_private_key(n, for_change, seed)
|
||||||
pk = {}
|
|
||||||
for sec in private_keys:
|
|
||||||
address = bitcoin.address_from_private_key(sec)
|
address = bitcoin.address_from_private_key(sec)
|
||||||
pk[address] = sec
|
txin['address'] = address
|
||||||
private_keys = pk
|
private_keys[address] = sec
|
||||||
|
|
||||||
|
elif txin.get("redeemScript"):
|
||||||
|
txin['address'] = hash_160_to_bc_address(hash_160(txin.get("redeemScript").decode('hex')), 5)
|
||||||
|
|
||||||
|
elif txin.get("raw_output_script"):
|
||||||
|
addr = deserialize.get_address_from_output_script(txin.get("raw_output_script").decode('hex'))
|
||||||
|
sec = wallet.get_private_key(addr, password)
|
||||||
|
if sec:
|
||||||
|
private_keys[addr] = sec
|
||||||
|
txin['address'] = addr
|
||||||
|
|
||||||
tx.sign( private_keys )
|
tx.sign( private_keys )
|
||||||
print_json({ "hex":str(tx),"complete":tx.is_complete})
|
print_json({ "hex":str(tx),"complete":tx.is_complete})
|
||||||
|
|
|
@ -479,6 +479,12 @@ class Transaction:
|
||||||
self.is_complete = False
|
self.is_complete = False
|
||||||
self.inputs = inputs
|
self.inputs = inputs
|
||||||
self.outputs = outputs
|
self.outputs = outputs
|
||||||
|
extras = []
|
||||||
|
for i in self.inputs:
|
||||||
|
print i
|
||||||
|
e = { 'txid':i['tx_hash'], 'vout':i['index'],'scriptPubKey':i['raw_output_script'] }
|
||||||
|
extras.append(e)
|
||||||
|
self.inputs_info = extras
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -190,7 +190,7 @@ class Wallet:
|
||||||
def get_master_public_key(self):
|
def get_master_public_key(self):
|
||||||
return self.sequence.master_public_key
|
return self.sequence.master_public_key
|
||||||
|
|
||||||
def get_public_key(self, address):
|
def get_address_index(self, address):
|
||||||
if address in self.imported_keys.keys():
|
if address in self.imported_keys.keys():
|
||||||
raise BaseException("imported key")
|
raise BaseException("imported key")
|
||||||
|
|
||||||
|
@ -200,7 +200,10 @@ class Wallet:
|
||||||
elif address in self.change_addresses:
|
elif address in self.change_addresses:
|
||||||
n = self.change_addresses.index(address)
|
n = self.change_addresses.index(address)
|
||||||
for_change = True
|
for_change = True
|
||||||
|
return n,for_change
|
||||||
|
|
||||||
|
def get_public_key(self, address):
|
||||||
|
n, for_change = self.get_address_index(address)
|
||||||
return self.sequence.get_pubkey(n, for_change)
|
return self.sequence.get_pubkey(n, for_change)
|
||||||
|
|
||||||
|
|
||||||
|
@ -666,6 +669,11 @@ class Wallet:
|
||||||
outputs = self.add_tx_change(outputs, amount, fee, total, change_addr)
|
outputs = self.add_tx_change(outputs, amount, fee, total, change_addr)
|
||||||
|
|
||||||
tx = Transaction.from_io(inputs, outputs)
|
tx = Transaction.from_io(inputs, outputs)
|
||||||
|
for i in range(len(tx.inputs)):
|
||||||
|
addr = tx.inputs[i]['address']
|
||||||
|
n, is_change = self.get_address_index(addr)
|
||||||
|
tx.inputs_info[i]['electrumKeyID'] = (n, is_change)
|
||||||
|
|
||||||
if not self.seed:
|
if not self.seed:
|
||||||
return tx
|
return tx
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue