Skip to content

Commit

Permalink
devices/bitbox02: add taproot keypath spending support for bitbox02
Browse files Browse the repository at this point in the history
  • Loading branch information
Beerosagos committed Jun 28, 2022
1 parent 0e6934e commit 08c6896
Showing 1 changed file with 41 additions and 10 deletions.
51 changes: 41 additions & 10 deletions hwilib/devices/bitbox02.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
BitBoxNoiseConfig,
)


class BitBox02Error(UnavailableActionError):
def __init__(self, msg: str):
"""
Expand Down Expand Up @@ -603,6 +602,13 @@ def script_config_from_utxo(
),
keypath=_keypath_hardened_prefix(keypath),
)
if is_p2tr(output.scriptPubKey):
return bitbox02.btc.BTCScriptConfigWithKeypath(
script_config=bitbox02.btc.BTCScriptConfig(
simple_type=bitbox02.btc.BTCScriptConfig.P2TR
),
keypath=_keypath_hardened_prefix(keypath),
)
# Check for segwit multisig (p2wsh or p2wsh-p2sh).
is_p2wsh_p2sh = output.is_p2sh() and is_p2wsh(redeem_script)
if output.is_p2wsh() or is_p2wsh_p2sh:
Expand Down Expand Up @@ -656,7 +662,7 @@ def script_config_from_utxo(
# - https://medium.com/shiftcrypto/bitbox-app-firmware-update-6-2020-c70f733a5330
# - https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd.
# - https://github.com/zkSNACKs/WalletWasabi/pull/3822
# The BitBox02 for now requires the prevtx, at least until Taproot activates.
# The BitBox02 requires all prevtxs if not all of the inputs are taproot.

if psbt_in.non_witness_utxo:
assert psbt_in.non_witness_utxo.sha256 is not None
Expand All @@ -673,12 +679,20 @@ def script_config_from_utxo(
utxo = psbt_in.witness_utxo
if utxo is None:
raise BadArgumentError("No utxo found for input {}".format(input_index))
if prevtx is None:
raise BadArgumentError(
"Previous transaction missing for input {}".format(input_index)
)

found_pubkey, keypath = find_our_key(psbt_in.hd_keypaths)
key_origin_infos = psbt_in.hd_keypaths.copy()
if len(psbt_in.tap_internal_key) > 0:
# adding taproot keys to the keypaths to be checked
for pubkey, (leaf_hashes, key_origin_info) in psbt_in.tap_bip32_paths.items():
if len(leaf_hashes) > 0:
raise BadArgumentError(
"The BitBox02 does not support Taproot script path spending. Found leaf hashes: {}"
.format(leaf_hashes)
)
key_origin_infos.update({pubkey: key_origin_info})

found_pubkey, keypath = find_our_key(key_origin_infos)

if not found_pubkey:
raise BadArgumentError("No key found for input {}".format(input_index))
assert keypath is not None
Expand Down Expand Up @@ -732,7 +746,19 @@ def script_config_from_utxo(
for output_index, psbt_out in builtins.enumerate(psbt.outputs):
tx_out = psbt_out.get_txout()

_, keypath = find_our_key(psbt_out.hd_keypaths)
key_origin_infos = psbt_out.hd_keypaths.copy()
if len(psbt_out.tap_internal_key) > 0:
# adding taproot keys to the keypaths to be checked
for pubkey, (leaf_hashes, key_origin_info) in psbt_out.tap_bip32_paths.items():
if len(leaf_hashes) > 0:
raise BadArgumentError(
"The BitBox02 does not support Taproot script path spending. Found leaf hashes: {}"
.format(leaf_hashes)
)
key_origin_infos.update({pubkey: key_origin_info})

_, keypath = find_our_key(key_origin_infos)

is_change = keypath and keypath[-2] == 1
if is_change:
assert keypath is not None
Expand Down Expand Up @@ -798,8 +824,13 @@ def script_config_from_utxo(

for (_, sig), pubkey, psbt_in in zip(sigs, found_pubkeys, psbt.inputs):
r, s = sig[:32], sig[32:64]
# ser_sig_der() adds SIGHASH_ALL
psbt_in.partial_sigs[pubkey] = ser_sig_der(r, s)

if len(psbt_in.tap_internal_key) > 0:
#taproot keypath input
psbt_in.tap_key_sig = sig
else:
# ser_sig_der() adds SIGHASH_ALL
psbt_in.partial_sigs[pubkey] = ser_sig_der(r, s)

return psbt

Expand Down

0 comments on commit 08c6896

Please sign in to comment.