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")
|
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.
|
# Default signature hash type in Bitcoin which signs all inputs and all outputs of the transaction.
|
||||||
SIGHASH_ALL = const(0x01)
|
SIGHASH_ALL = const(0x01)
|
||||||
|
|
||||||
|
@ -240,6 +240,28 @@ def output_script_native_segwit(witver: int, witprog: bytes) -> bytearray:
|
|||||||
return w
|
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
|
# SegWit: P2WPKH nested in P2SH
|
||||||
# ===
|
# ===
|
||||||
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
|
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
|
||||||
@ -381,6 +403,39 @@ def parse_witness_multisig(
|
|||||||
return script, signatures
|
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
|
# 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:
|
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)
|
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:
|
def append_signature(w: Writer, signature: bytes, hash_type: int) -> None:
|
||||||
|
Loading…
Reference in New Issue
Block a user