Browse Source

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
3.2.x
SomberNight 6 years ago
parent
commit
04c1b522d6
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 7
      electrum/bitcoin.py
  2. 40
      electrum/plugins/coldcard/coldcard.py
  3. 4
      electrum/transaction.py

7
electrum/bitcoin.py

@ -626,6 +626,9 @@ def serialize_xpub(xtype, c, cK, depth=0, fingerprint=b'\x00'*4,
return EncodeBase58Check(xpub)
class InvalidMasterKeyVersionBytes(BitcoinException): pass
def deserialize_xkey(xkey, prv, *, net=None):
if net is None:
net = constants.net
@ -640,8 +643,8 @@ def deserialize_xkey(xkey, prv, *, net=None):
header = int('0x' + bh2u(xkey[0:4]), 16)
headers = net.XPRV_HEADERS if prv else net.XPUB_HEADERS
if header not in headers.values():
raise BitcoinException('Invalid extended key format: {}'
.format(hex(header)))
raise InvalidMasterKeyVersionBytes('Invalid extended key format: {}'
.format(hex(header)))
xtype = list(headers.keys())[list(headers.values()).index(header)]
n = 33 if prv else 32
K_or_k = xkey[13+n:]

40
electrum/plugins/coldcard/coldcard.py

@ -8,10 +8,12 @@ import os, sys, time, io
import traceback
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.i18n import _
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.wallet import Standard_Wallet
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',
# 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
# if we know what the (xfp, xpub) "should be" then track it here
@ -183,9 +186,19 @@ class CKCCClient:
return False
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)
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):
# check connection is working
@ -435,7 +448,11 @@ class Coldcard_KeyStore(Hardware_KeyStore):
# 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)
# end globals section
@ -457,13 +474,13 @@ class Coldcard_KeyStore(Hardware_KeyStore):
out_fd.write(b'\x00')
# 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
# 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)
#
index, xpubs, _multisig = tx.output_info.get(address)
output_info = tx.output_info.get(o.address)
index, xpubs = output_info.address_index, output_info.sorted_xpubs
if index[0] == 1 and len(index) == 2:
# it is a change output (based on our standard derivation path)
@ -581,7 +598,6 @@ class ColdcardPlugin(HW_PluginBase):
SUPPORTED_XTYPES = ('standard', 'p2wpkh')
def __init__(self, parent, config, name):
self.segwit = config.get("segwit")
HW_PluginBase.__init__(self, parent, config, name)
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
# the 'path' is unabiguous, so we'll use that.
try:
rv = CKCCClient(handler, device.path,
rv = CKCCClient(self, handler, device.path,
is_simulator=(device.product_key[1] == CKCC_SIMULATED_PID))
return rv
except:
print_error('[coldcard]', 'late failure connecting to device?')
self.print_error('late failure connecting to device?')
return None
def setup_device(self, device_info, wizard, purpose):

4
electrum/transaction.py

@ -1030,12 +1030,12 @@ class Transaction:
else:
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)
nLocktime = int_to_hex(self.locktime, 4)
inputs = self.inputs()
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)
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 \

Loading…
Cancel
Save