Skip to content

Commit 662eab0

Browse files
committed
bitbox: Update to inspect scriptcode for signature type
Rather than relying on the utxos given to determine the signature type, inspect the scripts.
1 parent 249825d commit 662eab0

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

hwilib/devices/digitalbitbox.py

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@
3131
CTransaction,
3232
ExtendedKey,
3333
hash256,
34+
is_p2pk,
35+
is_p2pkh,
36+
is_p2sh,
37+
is_p2wpkh,
38+
is_p2wsh,
39+
is_witness,
3440
ser_sig_der,
3541
ser_sig_compact,
42+
ser_string,
3643
ser_compact_size,
3744
)
3845
from ..base58 import (
@@ -365,18 +372,39 @@ def sign_tx(self, tx):
365372
sighash_tuples = []
366373
for txin, psbt_in, i_num in zip(blank_tx.vin, tx.inputs, range(len(blank_tx.vin))):
367374
sighash = b""
375+
utxo = None
376+
if psbt_in.witness_utxo:
377+
utxo = psbt_in.witness_utxo
368378
if psbt_in.non_witness_utxo:
379+
if txin.prevout.hash != psbt_in.non_witness_utxo.sha256:
380+
raise BadArgumentError('Input {} has a non_witness_utxo with the wrong hash'.format(i_num))
369381
utxo = psbt_in.non_witness_utxo.vout[txin.prevout.n]
382+
if utxo is None:
383+
continue
384+
scriptcode = utxo.scriptPubKey
385+
386+
# Check if P2SH
387+
p2sh = False
388+
if is_p2sh(scriptcode):
389+
# Look up redeemscript
390+
if len(psbt_in.redeem_script) == 0:
391+
continue
392+
scriptcode = psbt_in.redeem_script
393+
p2sh = True
394+
395+
is_wit, _, _ = is_witness(scriptcode)
396+
397+
# Check if P2WSH
398+
if is_p2wsh(scriptcode):
399+
# Look up witnessscript
400+
if len(psbt_in.witness_script) == 0:
401+
continue
402+
scriptcode = psbt_in.witness_script
370403

371-
# Check if P2SH
372-
if utxo.is_p2sh():
373-
# Look up redeemscript
374-
redeemscript = psbt_in.redeem_script
404+
if not is_wit:
405+
if p2sh or is_p2pkh(scriptcode) or is_p2pk(scriptcode):
375406
# Add to blank_tx
376-
txin.scriptSig = redeemscript
377-
# Check if P2PKH
378-
elif utxo.is_p2pkh() or utxo.is_p2pk():
379-
txin.scriptSig = psbt_in.non_witness_utxo.vout[txin.prevout.n].scriptPubKey
407+
txin.scriptSig = scriptcode
380408
# We don't know what this is, skip it
381409
else:
382410
continue
@@ -388,7 +416,7 @@ def sign_tx(self, tx):
388416
# Hash it
389417
sighash += hash256(ser_tx)
390418
txin.scriptSig = b""
391-
elif psbt_in.witness_utxo:
419+
else:
392420
# Calculate hashPrevouts and hashSequence
393421
prevouts_preimage = b""
394422
sequence_preimage = b""
@@ -404,33 +432,18 @@ def sign_tx(self, tx):
404432
outputs_preimage += output.serialize()
405433
hashOutputs = hash256(outputs_preimage)
406434

407-
# Get the scriptCode
408-
scriptCode = b""
409-
witness_program = b""
410-
if psbt_in.witness_utxo.is_p2sh():
411-
# Look up redeemscript
412-
redeemscript = psbt_in.redeem_script
413-
witness_program = redeemscript
414-
else:
415-
witness_program = psbt_in.witness_utxo.scriptPubKey
416-
417-
# Check if witness_program is script hash
418-
if len(witness_program) == 34 and witness_program[0] == 0x00 and witness_program[1] == 0x20:
419-
# look up witnessscript and set as scriptCode
420-
witnessscript = psbt_in.witness_script
421-
scriptCode += ser_compact_size(len(witnessscript)) + witnessscript
422-
else:
423-
scriptCode += b"\x19\x76\xa9\x14"
424-
scriptCode += witness_program[2:]
425-
scriptCode += b"\x88\xac"
435+
# Check if scriptcode is p2wpkh
436+
if is_p2wpkh(scriptcode):
437+
_, _, wit_prog = is_witness(scriptcode)
438+
scriptcode = b"\x76\xa9\x14" + wit_prog + b"\x88\xac"
426439

427440
# Make sighash preimage
428441
preimage = b""
429442
preimage += struct.pack("<i", blank_tx.nVersion)
430443
preimage += hashPrevouts
431444
preimage += hashSequence
432445
preimage += txin.prevout.serialize()
433-
preimage += scriptCode
446+
preimage += ser_string(scriptcode)
434447
preimage += struct.pack("<q", psbt_in.witness_utxo.nValue)
435448
preimage += struct.pack("<I", txin.nSequence)
436449
preimage += hashOutputs

0 commit comments

Comments
 (0)