move xpubkey logic to keystore and fix it
This commit is contained in:
@@ -777,7 +777,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||||||
self.saved = True
|
self.saved = True
|
||||||
|
|
||||||
def new_payment_request(self):
|
def new_payment_request(self):
|
||||||
addr = self.wallet.get_unused_address(None)
|
addr = self.wallet.get_unused_address()
|
||||||
if addr is None:
|
if addr is None:
|
||||||
from electrum.wallet import Imported_Wallet
|
from electrum.wallet import Imported_Wallet
|
||||||
if isinstance(self.wallet, Imported_Wallet):
|
if isinstance(self.wallet, Imported_Wallet):
|
||||||
@@ -785,7 +785,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||||||
return
|
return
|
||||||
if not self.question(_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?")):
|
if not self.question(_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?")):
|
||||||
return
|
return
|
||||||
addr = self.wallet.create_new_address(None, False)
|
addr = self.wallet.create_new_address(False)
|
||||||
self.set_receive_address(addr)
|
self.set_receive_address(addr)
|
||||||
self.expires_label.hide()
|
self.expires_label.hide()
|
||||||
self.expires_combo.show()
|
self.expires_combo.show()
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class RequestList(MyTreeWidget):
|
|||||||
item = self.itemAt(position)
|
item = self.itemAt(position)
|
||||||
if not item:
|
if not item:
|
||||||
return
|
return
|
||||||
addr = str(item.text(2))
|
addr = str(item.text(1))
|
||||||
req = self.wallet.receive_requests[addr]
|
req = self.wallet.receive_requests[addr]
|
||||||
column = self.currentColumn()
|
column = self.currentColumn()
|
||||||
column_title = self.headerItem().text(column)
|
column_title = self.headerItem().text(column)
|
||||||
|
|||||||
@@ -216,6 +216,22 @@ class Xpub:
|
|||||||
s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (c, i)))
|
s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (c, i)))
|
||||||
return 'ff' + bitcoin.DecodeBase58Check(self.xpub).encode('hex') + s
|
return 'ff' + bitcoin.DecodeBase58Check(self.xpub).encode('hex') + s
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_xpubkey(self, pubkey):
|
||||||
|
assert pubkey[0:2] == 'ff'
|
||||||
|
pk = pubkey.decode('hex')
|
||||||
|
pk = pk[1:]
|
||||||
|
xkey = bitcoin.EncodeBase58Check(pk[0:78])
|
||||||
|
dd = pk[78:]
|
||||||
|
s = []
|
||||||
|
while dd:
|
||||||
|
n = int(bitcoin.rev_hex(dd[0:2].encode('hex')), 16)
|
||||||
|
dd = dd[2:]
|
||||||
|
s.append(n)
|
||||||
|
assert len(s) == 2
|
||||||
|
return xkey, s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
|
class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
|
||||||
|
|
||||||
@@ -429,15 +445,15 @@ class Old_KeyStore(Deterministic_KeyStore):
|
|||||||
def get_master_public_key(self):
|
def get_master_public_key(self):
|
||||||
return self.mpk.encode('hex')
|
return self.mpk.encode('hex')
|
||||||
|
|
||||||
def get_xpubkeys(self, for_change, n):
|
def get_xpubkey(self, for_change, n):
|
||||||
s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (for_change, n)))
|
s = ''.join(map(lambda x: bitcoin.int_to_hex(x,2), (for_change, n)))
|
||||||
mpk = self.mpk.encode('hex')
|
mpk = self.mpk.encode('hex')
|
||||||
x_pubkey = 'fe' + mpk + s
|
x_pubkey = 'fe' + mpk + s
|
||||||
return [ x_pubkey ]
|
return x_pubkey
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_xpubkey(self, x_pubkey):
|
def parse_xpubkey(self, x_pubkey):
|
||||||
assert is_extended_pubkey(x_pubkey)
|
assert x_pubkey[0:2] == 'fe'
|
||||||
pk = x_pubkey[2:]
|
pk = x_pubkey[2:]
|
||||||
mpk = pk[0:128]
|
mpk = pk[0:128]
|
||||||
dd = pk[128:]
|
dd = pk[128:]
|
||||||
@@ -526,6 +542,36 @@ def bip39_to_seed(mnemonic, passphrase):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# extended pubkeys
|
||||||
|
|
||||||
|
def is_xpubkey(x_pubkey):
|
||||||
|
return x_pubkey[0:2] == 'ff'
|
||||||
|
|
||||||
|
def parse_xpubkey(x_pubkey):
|
||||||
|
assert x_pubkey[0:2] == 'ff'
|
||||||
|
return BIP32_KeyStore.parse_xpubkey(x_pubkey)
|
||||||
|
|
||||||
|
def xpubkey_to_address(x_pubkey):
|
||||||
|
if x_pubkey[0:2] in ['02','03','04']:
|
||||||
|
pubkey = x_pubkey
|
||||||
|
elif x_pubkey[0:2] == 'ff':
|
||||||
|
xpub, s = BIP32_KeyStore.parse_xpubkey(x_pubkey)
|
||||||
|
pubkey = BIP32_KeyStore.derive_pubkey_from_xpub(xpub, s[0], s[1])
|
||||||
|
elif x_pubkey[0:2] == 'fe':
|
||||||
|
mpk, s = Old_KeyStore.parse_xpubkey(x_pubkey)
|
||||||
|
pubkey = Old_KeyStore.get_pubkey_from_mpk(mpk.decode('hex'), s[0], s[1])
|
||||||
|
elif x_pubkey[0:2] == 'fd':
|
||||||
|
addrtype = ord(x_pubkey[2:4].decode('hex'))
|
||||||
|
hash160 = x_pubkey[4:].decode('hex')
|
||||||
|
pubkey = None
|
||||||
|
address = hash_160_to_bc_address(hash160, addrtype)
|
||||||
|
else:
|
||||||
|
raise BaseException("Cannnot parse pubkey")
|
||||||
|
if pubkey:
|
||||||
|
address = public_key_to_bc_address(pubkey.decode('hex'))
|
||||||
|
return pubkey, address
|
||||||
|
|
||||||
|
|
||||||
keystores = []
|
keystores = []
|
||||||
|
|
||||||
def load_keystore(storage, name):
|
def load_keystore(storage, name):
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import struct
|
|||||||
import struct
|
import struct
|
||||||
import StringIO
|
import StringIO
|
||||||
import random
|
import random
|
||||||
|
from keystore import xpubkey_to_address
|
||||||
|
|
||||||
NO_SIGNATURE = 'ff'
|
NO_SIGNATURE = 'ff'
|
||||||
|
|
||||||
@@ -291,38 +292,6 @@ def parse_sig(x_sig):
|
|||||||
s.append(None)
|
s.append(None)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def is_extended_pubkey(x_pubkey):
|
|
||||||
return x_pubkey[0:2] in ['fe', 'ff']
|
|
||||||
|
|
||||||
def x_to_xpub(x_pubkey):
|
|
||||||
if x_pubkey[0:2] == 'ff':
|
|
||||||
from account import BIP32_Account
|
|
||||||
xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
|
|
||||||
return xpub
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse_xpub(x_pubkey):
|
|
||||||
if x_pubkey[0:2] in ['02','03','04']:
|
|
||||||
pubkey = x_pubkey
|
|
||||||
elif x_pubkey[0:2] == 'ff':
|
|
||||||
from account import BIP32_Account
|
|
||||||
xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
|
|
||||||
pubkey = BIP32_Account.derive_pubkey_from_xpub(xpub, s[0], s[1])
|
|
||||||
elif x_pubkey[0:2] == 'fe':
|
|
||||||
from account import OldAccount
|
|
||||||
mpk, s = OldAccount.parse_xpubkey(x_pubkey)
|
|
||||||
pubkey = OldAccount.get_pubkey_from_mpk(mpk.decode('hex'), s[0], s[1])
|
|
||||||
elif x_pubkey[0:2] == 'fd':
|
|
||||||
addrtype = ord(x_pubkey[2:4].decode('hex'))
|
|
||||||
hash160 = x_pubkey[4:].decode('hex')
|
|
||||||
pubkey = None
|
|
||||||
address = hash_160_to_bc_address(hash160, addrtype)
|
|
||||||
else:
|
|
||||||
raise BaseException("Cannnot parse pubkey")
|
|
||||||
if pubkey:
|
|
||||||
address = public_key_to_bc_address(pubkey.decode('hex'))
|
|
||||||
return pubkey, address
|
|
||||||
|
|
||||||
|
|
||||||
def parse_scriptSig(d, bytes):
|
def parse_scriptSig(d, bytes):
|
||||||
@@ -353,7 +322,7 @@ def parse_scriptSig(d, bytes):
|
|||||||
x_pubkey = decoded[1][1].encode('hex')
|
x_pubkey = decoded[1][1].encode('hex')
|
||||||
try:
|
try:
|
||||||
signatures = parse_sig([sig])
|
signatures = parse_sig([sig])
|
||||||
pubkey, address = parse_xpub(x_pubkey)
|
pubkey, address = xpubkey_to_address(x_pubkey)
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
@@ -382,7 +351,7 @@ def parse_scriptSig(d, bytes):
|
|||||||
print_error("cannot find address in input script", bytes.encode('hex'))
|
print_error("cannot find address in input script", bytes.encode('hex'))
|
||||||
return
|
return
|
||||||
x_pubkeys = map(lambda x: x[1].encode('hex'), dec2[1:-2])
|
x_pubkeys = map(lambda x: x[1].encode('hex'), dec2[1:-2])
|
||||||
pubkeys = [parse_xpub(x)[0] for x in x_pubkeys] # xpub, addr = parse_xpub()
|
pubkeys = [xpubkey_to_address(x)[0] for x in x_pubkeys]
|
||||||
redeemScript = Transaction.multisig_script(pubkeys, m)
|
redeemScript = Transaction.multisig_script(pubkeys, m)
|
||||||
# write result in d
|
# write result in d
|
||||||
d['num_sig'] = m
|
d['num_sig'] = m
|
||||||
|
|||||||
@@ -157,14 +157,13 @@ class Plugin(BasePlugin):
|
|||||||
d.cosigner_send_button.hide()
|
d.cosigner_send_button.hide()
|
||||||
|
|
||||||
def cosigner_can_sign(self, tx, cosigner_xpub):
|
def cosigner_can_sign(self, tx, cosigner_xpub):
|
||||||
from electrum.transaction import x_to_xpub
|
from electrum.keystore import is_xpubkey, parse_xpubkey
|
||||||
xpub_set = set([])
|
xpub_set = set([])
|
||||||
for txin in tx.inputs():
|
for txin in tx.inputs():
|
||||||
for x_pubkey in txin['x_pubkeys']:
|
for x_pubkey in txin['x_pubkeys']:
|
||||||
xpub = x_to_xpub(x_pubkey)
|
if is_xpubkey(x_pubkey):
|
||||||
if xpub:
|
xpub, s = parse_xpubkey(x_pubkey)
|
||||||
xpub_set.add(xpub)
|
xpub_set.add(xpub)
|
||||||
|
|
||||||
return cosigner_xpub in xpub_set
|
return cosigner_xpub in xpub_set
|
||||||
|
|
||||||
def do_send(self, tx):
|
def do_send(self, tx):
|
||||||
|
|||||||
@@ -5,15 +5,13 @@ import threading
|
|||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from electrum.account import BIP32_Account
|
|
||||||
from electrum.bitcoin import (bc_address_to_hash_160, xpub_from_pubkey,
|
from electrum.bitcoin import (bc_address_to_hash_160, xpub_from_pubkey,
|
||||||
public_key_to_bc_address, EncodeBase58Check,
|
public_key_to_bc_address, EncodeBase58Check,
|
||||||
TYPE_ADDRESS, TYPE_SCRIPT)
|
TYPE_ADDRESS, TYPE_SCRIPT)
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.plugins import BasePlugin, hook
|
from electrum.plugins import BasePlugin, hook
|
||||||
from electrum.transaction import (deserialize, is_extended_pubkey,
|
from electrum.transaction import deserialize, Transaction
|
||||||
Transaction, x_to_xpub)
|
from electrum.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey
|
||||||
from electrum.keystore import Hardware_KeyStore
|
|
||||||
|
|
||||||
from ..hw_wallet import HW_PluginBase
|
from ..hw_wallet import HW_PluginBase
|
||||||
|
|
||||||
@@ -66,9 +64,9 @@ class TrezorCompatibleKeyStore(Hardware_KeyStore):
|
|||||||
tx_hash = txin['prevout_hash']
|
tx_hash = txin['prevout_hash']
|
||||||
prev_tx[tx_hash] = txin['prev_tx']
|
prev_tx[tx_hash] = txin['prev_tx']
|
||||||
for x_pubkey in txin['x_pubkeys']:
|
for x_pubkey in txin['x_pubkeys']:
|
||||||
if not is_extended_pubkey(x_pubkey):
|
if not is_xpubkey(x_pubkey):
|
||||||
continue
|
continue
|
||||||
xpub = x_to_xpub(x_pubkey)
|
xpub, s = parse_xpubkey(x_pubkey)
|
||||||
if xpub == self.get_master_public_key():
|
if xpub == self.get_master_public_key():
|
||||||
xpub_path[xpub] = self.get_derivation()
|
xpub_path[xpub] = self.get_derivation()
|
||||||
|
|
||||||
@@ -254,13 +252,13 @@ class TrezorCompatiblePlugin(HW_PluginBase):
|
|||||||
x_pubkeys = txin['x_pubkeys']
|
x_pubkeys = txin['x_pubkeys']
|
||||||
if len(x_pubkeys) == 1:
|
if len(x_pubkeys) == 1:
|
||||||
x_pubkey = x_pubkeys[0]
|
x_pubkey = x_pubkeys[0]
|
||||||
xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
|
xpub, s = parse_xpubkey(x_pubkey)
|
||||||
xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
|
xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
|
||||||
txinputtype.address_n.extend(xpub_n + s)
|
txinputtype.address_n.extend(xpub_n + s)
|
||||||
else:
|
else:
|
||||||
def f(x_pubkey):
|
def f(x_pubkey):
|
||||||
if is_extended_pubkey(x_pubkey):
|
if is_xpubkey(x_pubkey):
|
||||||
xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
|
xpub, s = parse_xpubkey(x_pubkey)
|
||||||
else:
|
else:
|
||||||
xpub = xpub_from_pubkey(x_pubkey.decode('hex'))
|
xpub = xpub_from_pubkey(x_pubkey.decode('hex'))
|
||||||
s = []
|
s = []
|
||||||
@@ -278,8 +276,8 @@ class TrezorCompatiblePlugin(HW_PluginBase):
|
|||||||
)
|
)
|
||||||
# find which key is mine
|
# find which key is mine
|
||||||
for x_pubkey in x_pubkeys:
|
for x_pubkey in x_pubkeys:
|
||||||
if is_extended_pubkey(x_pubkey):
|
if is_xpubkey(x_pubkey):
|
||||||
xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
|
xpub, s = parse_xpubkey(x_pubkey)
|
||||||
if xpub in self.xpub_path:
|
if xpub in self.xpub_path:
|
||||||
xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
|
xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
|
||||||
txinputtype.address_n.extend(xpub_n + s)
|
txinputtype.address_n.extend(xpub_n + s)
|
||||||
|
|||||||
Reference in New Issue
Block a user