mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-01 09:45:18 +00:00
minor fixes for prev
use TxOutputHwInfo namedtuple warn user if device is set to wrong chain undo parts of prev re testnet. fix p2wpkh. testnet support. and minor stuff
This commit is contained in:
parent
0bcea80bdf
commit
04c1b522d6
3 changed files with 35 additions and 16 deletions
|
@ -626,6 +626,9 @@ def serialize_xpub(xtype, c, cK, depth=0, fingerprint=b'\x00'*4,
|
||||||
return EncodeBase58Check(xpub)
|
return EncodeBase58Check(xpub)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidMasterKeyVersionBytes(BitcoinException): pass
|
||||||
|
|
||||||
|
|
||||||
def deserialize_xkey(xkey, prv, *, net=None):
|
def deserialize_xkey(xkey, prv, *, net=None):
|
||||||
if net is None:
|
if net is None:
|
||||||
net = constants.net
|
net = constants.net
|
||||||
|
@ -640,8 +643,8 @@ def deserialize_xkey(xkey, prv, *, net=None):
|
||||||
header = int('0x' + bh2u(xkey[0:4]), 16)
|
header = int('0x' + bh2u(xkey[0:4]), 16)
|
||||||
headers = net.XPRV_HEADERS if prv else net.XPUB_HEADERS
|
headers = net.XPRV_HEADERS if prv else net.XPUB_HEADERS
|
||||||
if header not in headers.values():
|
if header not in headers.values():
|
||||||
raise BitcoinException('Invalid extended key format: {}'
|
raise InvalidMasterKeyVersionBytes('Invalid extended key format: {}'
|
||||||
.format(hex(header)))
|
.format(hex(header)))
|
||||||
xtype = list(headers.keys())[list(headers.values()).index(header)]
|
xtype = list(headers.keys())[list(headers.values()).index(header)]
|
||||||
n = 33 if prv else 32
|
n = 33 if prv else 32
|
||||||
K_or_k = xkey[13+n:]
|
K_or_k = xkey[13+n:]
|
||||||
|
|
|
@ -8,10 +8,12 @@ import os, sys, time, io
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from electrum import bitcoin
|
from electrum import bitcoin
|
||||||
|
from electrum.bitcoin import serialize_xpub, deserialize_xpub, InvalidMasterKeyVersionBytes
|
||||||
|
from electrum import constants
|
||||||
from electrum.bitcoin import TYPE_ADDRESS, int_to_hex
|
from electrum.bitcoin import TYPE_ADDRESS, int_to_hex
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.plugin import BasePlugin, Device
|
from electrum.plugin import BasePlugin, Device
|
||||||
from electrum.keystore import Hardware_KeyStore, xpubkey_to_pubkey
|
from electrum.keystore import Hardware_KeyStore, xpubkey_to_pubkey, Xpub
|
||||||
from electrum.transaction import Transaction
|
from electrum.transaction import Transaction
|
||||||
from electrum.wallet import Standard_Wallet
|
from electrum.wallet import Standard_Wallet
|
||||||
from electrum.crypto import hash_160
|
from electrum.crypto import hash_160
|
||||||
|
@ -85,7 +87,8 @@ class CKCCClient:
|
||||||
# Challenge: I haven't found anywhere that defines a base class for this 'client',
|
# Challenge: I haven't found anywhere that defines a base class for this 'client',
|
||||||
# nor an API (interface) to be met. Winging it. Gets called from lib/plugins.py mostly?
|
# nor an API (interface) to be met. Winging it. Gets called from lib/plugins.py mostly?
|
||||||
|
|
||||||
def __init__(self, handler, dev_path, is_simulator=False):
|
def __init__(self, plugin, handler, dev_path, is_simulator=False):
|
||||||
|
self.device = plugin.device
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
|
|
||||||
# if we know what the (xfp, xpub) "should be" then track it here
|
# if we know what the (xfp, xpub) "should be" then track it here
|
||||||
|
@ -183,9 +186,19 @@ class CKCCClient:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_xpub(self, bip32_path, xtype):
|
def get_xpub(self, bip32_path, xtype):
|
||||||
# TODO: xtype? .. might not be able to support anything but classic p2pkh?
|
assert xtype in ColdcardPlugin.SUPPORTED_XTYPES
|
||||||
print_error('[coldcard]', 'Derive xtype = %r' % xtype)
|
print_error('[coldcard]', 'Derive xtype = %r' % xtype)
|
||||||
return self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000)
|
xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000)
|
||||||
|
# TODO handle timeout?
|
||||||
|
# change type of xpub to the requested type
|
||||||
|
try:
|
||||||
|
__, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub)
|
||||||
|
except InvalidMasterKeyVersionBytes:
|
||||||
|
raise Exception(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.')
|
||||||
|
.format(self.device)) from None
|
||||||
|
if xtype != 'standard':
|
||||||
|
xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
|
||||||
|
return xpub
|
||||||
|
|
||||||
def ping_check(self):
|
def ping_check(self):
|
||||||
# check connection is working
|
# check connection is working
|
||||||
|
@ -435,7 +448,11 @@ class Coldcard_KeyStore(Hardware_KeyStore):
|
||||||
|
|
||||||
|
|
||||||
# global section: just the unsigned txn
|
# global section: just the unsigned txn
|
||||||
unsigned = bfh(tx.serialize_to_network(blank_scripts=True))
|
class CustomTXSerialization(Transaction):
|
||||||
|
@classmethod
|
||||||
|
def input_script(cls, txin, estimate_size=False):
|
||||||
|
return ''
|
||||||
|
unsigned = bfh(CustomTXSerialization(tx.serialize()).serialize_to_network(witness=False))
|
||||||
write_kv(PSBT_GLOBAL_UNSIGNED_TX, unsigned)
|
write_kv(PSBT_GLOBAL_UNSIGNED_TX, unsigned)
|
||||||
|
|
||||||
# end globals section
|
# end globals section
|
||||||
|
@ -457,13 +474,13 @@ class Coldcard_KeyStore(Hardware_KeyStore):
|
||||||
out_fd.write(b'\x00')
|
out_fd.write(b'\x00')
|
||||||
|
|
||||||
# outputs section
|
# outputs section
|
||||||
for _type, address, amount in tx.outputs():
|
for o in tx.outputs():
|
||||||
# can be empty, but must be present, and helpful to show change inputs
|
# can be empty, but must be present, and helpful to show change inputs
|
||||||
# wallet.add_hw_info() adds some data about change outputs into tx.output_info
|
# wallet.add_hw_info() adds some data about change outputs into tx.output_info
|
||||||
if address in tx.output_info:
|
if o.address in tx.output_info:
|
||||||
# this address "is_mine" but might not be change (I like to sent to myself)
|
# this address "is_mine" but might not be change (I like to sent to myself)
|
||||||
#
|
output_info = tx.output_info.get(o.address)
|
||||||
index, xpubs, _multisig = tx.output_info.get(address)
|
index, xpubs = output_info.address_index, output_info.sorted_xpubs
|
||||||
|
|
||||||
if index[0] == 1 and len(index) == 2:
|
if index[0] == 1 and len(index) == 2:
|
||||||
# it is a change output (based on our standard derivation path)
|
# it is a change output (based on our standard derivation path)
|
||||||
|
@ -581,7 +598,6 @@ class ColdcardPlugin(HW_PluginBase):
|
||||||
SUPPORTED_XTYPES = ('standard', 'p2wpkh')
|
SUPPORTED_XTYPES = ('standard', 'p2wpkh')
|
||||||
|
|
||||||
def __init__(self, parent, config, name):
|
def __init__(self, parent, config, name):
|
||||||
self.segwit = config.get("segwit")
|
|
||||||
HW_PluginBase.__init__(self, parent, config, name)
|
HW_PluginBase.__init__(self, parent, config, name)
|
||||||
|
|
||||||
if self.libraries_available:
|
if self.libraries_available:
|
||||||
|
@ -608,11 +624,11 @@ class ColdcardPlugin(HW_PluginBase):
|
||||||
# Not sure why not we aren't just given a HID library handle, but
|
# Not sure why not we aren't just given a HID library handle, but
|
||||||
# the 'path' is unabiguous, so we'll use that.
|
# the 'path' is unabiguous, so we'll use that.
|
||||||
try:
|
try:
|
||||||
rv = CKCCClient(handler, device.path,
|
rv = CKCCClient(self, handler, device.path,
|
||||||
is_simulator=(device.product_key[1] == CKCC_SIMULATED_PID))
|
is_simulator=(device.product_key[1] == CKCC_SIMULATED_PID))
|
||||||
return rv
|
return rv
|
||||||
except:
|
except:
|
||||||
print_error('[coldcard]', 'late failure connecting to device?')
|
self.print_error('late failure connecting to device?')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def setup_device(self, device_info, wizard, purpose):
|
def setup_device(self, device_info, wizard, purpose):
|
||||||
|
|
|
@ -1030,12 +1030,12 @@ class Transaction:
|
||||||
else:
|
else:
|
||||||
return network_ser
|
return network_ser
|
||||||
|
|
||||||
def serialize_to_network(self, estimate_size=False, witness=True, blank_scripts=False):
|
def serialize_to_network(self, estimate_size=False, witness=True):
|
||||||
nVersion = int_to_hex(self.version, 4)
|
nVersion = int_to_hex(self.version, 4)
|
||||||
nLocktime = int_to_hex(self.locktime, 4)
|
nLocktime = int_to_hex(self.locktime, 4)
|
||||||
inputs = self.inputs()
|
inputs = self.inputs()
|
||||||
outputs = self.outputs()
|
outputs = self.outputs()
|
||||||
txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.input_script(txin, estimate_size) if not blank_scripts else '') for txin in inputs)
|
txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.input_script(txin, estimate_size)) for txin in inputs)
|
||||||
txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs)
|
txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs)
|
||||||
use_segwit_ser_for_estimate_size = estimate_size and self.is_segwit(guess_for_address=True)
|
use_segwit_ser_for_estimate_size = estimate_size and self.is_segwit(guess_for_address=True)
|
||||||
use_segwit_ser_for_actual_use = not estimate_size and \
|
use_segwit_ser_for_actual_use = not estimate_size and \
|
||||||
|
|
Loading…
Add table
Reference in a new issue