mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-03 03:50:58 +00:00
feat(core): Support Taproot scripts.
This commit is contained in:
parent
68ad1b07d2
commit
630c06e782
@ -14,6 +14,10 @@ if False:
|
||||
|
||||
BITCOIN_NAMES = ("Bitcoin", "Regtest", "Testnet")
|
||||
|
||||
# Signature hash type with the same semantics as the SIGHASH_ALL, but instead
|
||||
# of having to include the byte in the signature, it is implied.
|
||||
SIGHASH_ALL_TAPROOT = const(0x00)
|
||||
|
||||
# Default signature hash type in Bitcoin which signs all inputs and all outputs of the transaction.
|
||||
SIGHASH_ALL = const(0x01)
|
||||
|
||||
|
@ -240,6 +240,28 @@ def output_script_native_segwit(witver: int, witprog: bytes) -> bytearray:
|
||||
return w
|
||||
|
||||
|
||||
def parse_output_script_p2tr(script_pubkey: bytes) -> memoryview:
|
||||
# 51 20 <32-byte-taproot-output-key>
|
||||
try:
|
||||
r = utils.BufferReader(script_pubkey)
|
||||
|
||||
if r.get() != common.OP_1:
|
||||
# P2TR should be SegWit version 1
|
||||
raise ValueError
|
||||
|
||||
if r.get() != 32:
|
||||
# taproot output key should be 32 bytes
|
||||
raise ValueError
|
||||
|
||||
pubkey = r.read_memoryview(32)
|
||||
if r.remaining_count():
|
||||
raise ValueError
|
||||
except (ValueError, EOFError):
|
||||
raise wire.DataError("Invalid scriptPubKey.")
|
||||
|
||||
return pubkey
|
||||
|
||||
|
||||
# SegWit: P2WPKH nested in P2SH
|
||||
# ===
|
||||
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
|
||||
@ -381,6 +403,39 @@ def parse_witness_multisig(
|
||||
return script, signatures
|
||||
|
||||
|
||||
# Taproot: Witness getters
|
||||
# ===
|
||||
|
||||
|
||||
def write_witness_p2tr(w: Writer, signature: bytes, hash_type: int) -> None:
|
||||
# Taproot key path spending without annex.
|
||||
write_bitcoin_varint(w, 0x01) # num of segwit items
|
||||
write_signature_prefixed(w, signature, hash_type)
|
||||
|
||||
|
||||
def parse_witness_p2tr(witness: bytes) -> tuple[memoryview, int]:
|
||||
try:
|
||||
r = utils.BufferReader(witness)
|
||||
|
||||
if r.get() != 1: # Number of stack items.
|
||||
# Only Taproot key path spending without annex is supported.
|
||||
raise ValueError
|
||||
|
||||
n = read_bitcoin_varint(r)
|
||||
if n not in (64, 65):
|
||||
raise ValueError
|
||||
|
||||
signature = r.read_memoryview(64)
|
||||
hash_type = r.get() if n == 65 else common.SIGHASH_ALL_TAPROOT
|
||||
|
||||
if r.remaining_count():
|
||||
raise ValueError
|
||||
except (ValueError, EOFError):
|
||||
raise wire.DataError("Invalid witness.")
|
||||
|
||||
return signature, hash_type
|
||||
|
||||
|
||||
# Multisig
|
||||
# ===
|
||||
#
|
||||
@ -573,9 +628,14 @@ def read_bip322_signature_proof(r: utils.BufferReader) -> tuple[memoryview, memo
|
||||
|
||||
|
||||
def write_signature_prefixed(w: Writer, signature: bytes, hash_type: int) -> None:
|
||||
write_bitcoin_varint(w, len(signature) + 1)
|
||||
length = len(signature)
|
||||
if hash_type != common.SIGHASH_ALL_TAPROOT:
|
||||
length += 1
|
||||
|
||||
write_bitcoin_varint(w, length)
|
||||
write_bytes_unchecked(w, signature)
|
||||
w.append(hash_type)
|
||||
if hash_type != common.SIGHASH_ALL_TAPROOT:
|
||||
w.append(hash_type)
|
||||
|
||||
|
||||
def append_signature(w: Writer, signature: bytes, hash_type: int) -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user