Skip to content

Commit

Permalink
bump coinkite-tap-protocol version to 1.1.0
Browse files Browse the repository at this point in the history
get_sighash_tuples moved to PSBT class (bitbox01 and tapsigner are using it -> blind signing)
HWI exception handling for tapsigner
remove unnecessary method from tapsigner
remove duplicate doc strings from tapsigner functions
  • Loading branch information
scgbckbone committed Jul 19, 2022
1 parent 7cd4632 commit 1a0c197
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 271 deletions.
2 changes: 1 addition & 1 deletion hwilib/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def enumerate(password: str = "") -> List[Dict[str, Any]]:
for module in all_devs:
try:
imported_dev = importlib.import_module('.devices.' + module, __package__)
result.extend(imported_dev.enumerate(password)) # type: ignore
result.extend(imported_dev.enumerate(password)) # type: ignore
except ImportError as e:
# Warn for ImportErrors, but largely ignore them to allow users not install
# all device dependencies if only one or some devices are wanted.
Expand Down
117 changes: 4 additions & 113 deletions hwilib/devices/digitalbitbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,10 @@
from ..key import (
ExtendedKey,
)
from .._script import (
is_p2pk,
is_p2pkh,
is_p2sh,
is_p2wpkh,
is_p2wsh,
is_witness,
)
from ..psbt import PSBT
from .._serialize import (
ser_sig_der,
ser_sig_compact,
ser_string,
ser_compact_size,
)

Expand Down Expand Up @@ -387,111 +378,11 @@ def get_pubkey_at_path(self, path: str) -> ExtendedKey:

@digitalbitbox_exception
def sign_tx(self, tx: PSBT) -> PSBT:

# Create a transaction with all scriptsigs blanked out
blank_tx = tx.get_unsigned_tx()

# Get the master key fingerprint
master_fp = self.get_master_fingerprint()

# create sighashes
sighash_tuples = []
for txin, psbt_in, i_num in zip(blank_tx.vin, tx.inputs, range(len(blank_tx.vin))):
sighash = b""
utxo = None
if psbt_in.witness_utxo:
utxo = psbt_in.witness_utxo
if psbt_in.non_witness_utxo:
if txin.prevout.hash != psbt_in.non_witness_utxo.sha256:
raise BadArgumentError('Input {} has a non_witness_utxo with the wrong hash'.format(i_num))
utxo = psbt_in.non_witness_utxo.vout[txin.prevout.n]
if utxo is None:
continue
scriptcode = utxo.scriptPubKey

# Check if P2SH
p2sh = False
if is_p2sh(scriptcode):
# Look up redeemscript
if len(psbt_in.redeem_script) == 0:
continue
scriptcode = psbt_in.redeem_script
p2sh = True

is_wit, _, _ = is_witness(scriptcode)

# Check if P2WSH
if is_p2wsh(scriptcode):
# Look up witnessscript
if len(psbt_in.witness_script) == 0:
continue
scriptcode = psbt_in.witness_script

if not is_wit:
if p2sh or is_p2pkh(scriptcode) or is_p2pk(scriptcode):
# Add to blank_tx
txin.scriptSig = scriptcode
# We don't know what this is, skip it
else:
continue

# Serialize and add sighash ALL
ser_tx = blank_tx.serialize_without_witness()
ser_tx += b"\x01\x00\x00\x00"

# Hash it
sighash += hash256(ser_tx)
txin.scriptSig = b""
else:
assert psbt_in.witness_utxo is not None
# Calculate hashPrevouts and hashSequence
prevouts_preimage = b""
sequence_preimage = b""
for inputs in blank_tx.vin:
prevouts_preimage += inputs.prevout.serialize()
sequence_preimage += struct.pack("<I", inputs.nSequence)
hashPrevouts = hash256(prevouts_preimage)
hashSequence = hash256(sequence_preimage)

# Calculate hashOutputs
outputs_preimage = b""
for output in blank_tx.vout:
outputs_preimage += output.serialize()
hashOutputs = hash256(outputs_preimage)

# Check if scriptcode is p2wpkh
if is_p2wpkh(scriptcode):
_, _, wit_prog = is_witness(scriptcode)
scriptcode = b"\x76\xa9\x14" + wit_prog + b"\x88\xac"

# Make sighash preimage
preimage = b""
preimage += struct.pack("<i", blank_tx.nVersion)
preimage += hashPrevouts
preimage += hashSequence
preimage += txin.prevout.serialize()
preimage += ser_string(scriptcode)
preimage += struct.pack("<q", psbt_in.witness_utxo.nValue)
preimage += struct.pack("<I", txin.nSequence)
preimage += hashOutputs
preimage += struct.pack("<I", blank_tx.nLockTime)
preimage += b"\x01\x00\x00\x00"

# hash it
sighash = hash256(preimage)

# Figure out which keypath thing is for this input
for pubkey, keypath in psbt_in.hd_keypaths.items():
if master_fp == keypath.fingerprint:
# Add the keypath strings
keypath_str = keypath.get_derivation_path()

# Create tuples and add to List
tup = (binascii.hexlify(sighash).decode(), keypath_str, i_num, pubkey)
sighash_tuples.append(tup)

# Return early if nothing to do
if len(sighash_tuples) == 0:
sighash_tuples = tx.get_sighash_tuples(master_fp=master_fp)
if sighash_tuples is None:
return tx

for i in range(0, len(sighash_tuples), 15):
Expand All @@ -501,9 +392,9 @@ def sign_tx(self, tx: PSBT) -> PSBT:
to_send = '{"sign":{"data":['
for tup in tups:
to_send += '{"hash":"'
to_send += tup[0]
to_send += binascii.hexlify(tup[0]).decode()
to_send += '","keypath":"'
to_send += tup[1]
to_send += tup[1].get_derivation_path()
to_send += '"},'
if to_send[-1] == ',':
to_send = to_send[:-1]
Expand Down

0 comments on commit 1a0c197

Please sign in to comment.