mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-12 14:16:06 +00:00
multisig: compute dummy chaincode based on pubkeys
Compute a dummy xpub to use as the internal pubkey for taproot multisig. Sort and remove duplicates of all xpub pubkeys, concatenate and compute sha256 hash. The result is the chaincode, and the pubkey is the NUMS point.
This commit is contained in:
parent
0bddc028c5
commit
d06623218f
@ -59,13 +59,9 @@ def validate_multisig(multisig: MultisigRedeemScriptType) -> None:
|
||||
|
||||
def multisig_pubkey_index(multisig: MultisigRedeemScriptType, pubkey: bytes) -> int:
|
||||
validate_multisig(multisig)
|
||||
if multisig.nodes:
|
||||
for i, hd_node in enumerate(multisig.nodes):
|
||||
if multisig_get_pubkey(hd_node, multisig.address_n) == pubkey:
|
||||
return i
|
||||
else:
|
||||
for i, hd in enumerate(multisig.pubkeys):
|
||||
if multisig_get_pubkey(hd.node, hd.address_n) == pubkey:
|
||||
pubkeys = multisig_get_pubkeys(multisig)
|
||||
for i, derived_pubkey in enumerate(pubkeys):
|
||||
if derived_pubkey == pubkey:
|
||||
return i
|
||||
raise DataError("Pubkey not found in multisig script")
|
||||
|
||||
@ -85,19 +81,44 @@ def multisig_get_pubkey(n: HDNodeType, p: paths.Bip32Path) -> bytes:
|
||||
return node.public_key()
|
||||
|
||||
|
||||
def compute_taproot_dummy_chaincode(multisig: MultisigRedeemScriptType) -> bytes:
|
||||
from trezor.crypto.hashlib import sha256
|
||||
from trezor.utils import HashWriter
|
||||
|
||||
from .writers import write_bytes_fixed
|
||||
|
||||
if len(multisig.address_n) != 2:
|
||||
raise DataError("Taproot multisig must use xpub derivation depth of 2")
|
||||
|
||||
if multisig.nodes:
|
||||
pubkeys = [hd.public_key for hd in multisig.nodes]
|
||||
else:
|
||||
pubkeys = [hd.public_key for hd in multisig.pubkeys]
|
||||
pubkeys.sort()
|
||||
h = HashWriter(sha256())
|
||||
prev = None
|
||||
for pubkey in pubkeys:
|
||||
if prev == pubkey:
|
||||
continue
|
||||
prev = pubkey
|
||||
write_bytes_fixed(h, pubkey, 33)
|
||||
|
||||
return h.get_digest()
|
||||
|
||||
|
||||
def multisig_get_dummy_pubkey(multisig: MultisigRedeemScriptType) -> bytes:
|
||||
from trezor.crypto import bip32
|
||||
|
||||
# The following encodes this xpub into an HDNode. It is the NUMS point suggested
|
||||
# in BIP341, with a chaincode of 32 0 bytes. Deriving a pubkey from this node
|
||||
# results in a provably unspendable pubkey.
|
||||
# in BIP341, with a chaincode derived from the sha256 of the sorted public keys with duplicates removed.
|
||||
# Deriving a pubkey from this node results in a provably unspendable pubkey.
|
||||
# https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304
|
||||
# xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6QgnecKFpJFPpdzxKrwoaZoV44qAJewsc4kX9vGaCaBExuvJH57
|
||||
node = bip32.HDNode(
|
||||
depth=0,
|
||||
fingerprint=2084970077,
|
||||
child_num=0,
|
||||
chain_code=b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
chain_code=compute_taproot_dummy_chaincode(multisig),
|
||||
public_key=b"\x02P\x92\x9bt\xc1\xa0IT\xb7\x8bK`5\xe9z^\x07\x8aZ\x0f(\xec\x96\xd5G\xbf\xee\x9a\xce\x80:\xc0",
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user