UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
taproot.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_TAPROOT_HPP
2#define SECP256K1_TAPROOT_HPP
3
4// ============================================================================
5// Taproot (BIP-341 / BIP-342) -- secp256k1
6// ============================================================================
7// Implements BIP-341 key tweaking and output key derivation for Taproot.
8//
9// Taproot uses x-only (32-byte) public keys with implicit even Y.
10// A Taproot output key Q is derived from an internal key P and a tweak:
11// Q = P + t*G where t = tagged_hash("TapTweak", P.x || merkle_root)
12//
13// Key concepts:
14// - Internal key (P): the actual signer's public key
15// - Tweak (t): scalar derived from merkle root of script tree
16// - Output key (Q): the key that appears on-chain (P tweaked by t)
17// - Key-path spend: sign with tweaked private key
18// - Script-path spend: reveal internal key + merkle proof + script
19//
20// Usage:
21// // Key-path: derive tweaked keypair
22// auto [output_key, parity] = taproot_output_key(internal_key_x, merkle_root);
23// auto tweaked_sk = taproot_tweak_privkey(private_key, merkle_root);
24//
25// // Script tree construction
26// auto leaf = taproot_leaf_hash(script_bytes);
27// auto branch = taproot_branch_hash(left, right);
28// ============================================================================
29
30#include <array>
31#include <cstdint>
32#include <cstddef>
33#include <vector>
34#include "secp256k1/point.hpp"
35#include "secp256k1/scalar.hpp"
36
37namespace secp256k1 {
38
39using fast::Scalar;
40using fast::Point;
41
42// -- Taproot Tagged Hashes (BIP-341 S.5.2) -------------------------------------
43
44// TapTweak hash: t = H_TapTweak(internal_key_x || data)
45// If merkle_root is empty (key-path only), uses just internal_key_x.
46std::array<std::uint8_t, 32> taproot_tweak_hash(
47 const std::array<std::uint8_t, 32>& internal_key_x,
48 const std::uint8_t* merkle_root = nullptr,
49 std::size_t merkle_root_len = 0);
50
51// TapLeaf hash: H_TapLeaf(leaf_version || compact_size(script) || script)
52std::array<std::uint8_t, 32> taproot_leaf_hash(
53 const std::uint8_t* script, std::size_t script_len,
54 std::uint8_t leaf_version = 0xC0);
55
56// TapBranch hash: H_TapBranch(sorted(a, b))
57// Sorts the two 32-byte hashes lexicographically before hashing.
58std::array<std::uint8_t, 32> taproot_branch_hash(
59 const std::array<std::uint8_t, 32>& a,
60 const std::array<std::uint8_t, 32>& b);
61
62// -- Output Key Derivation ----------------------------------------------------
63
64// Derive Taproot output key Q = P + t*G
65// Returns {output_key_x (32 bytes), parity (0 = even, 1 = odd)}
66// merkle_root can be nullptr for key-path-only outputs.
67std::pair<std::array<std::uint8_t, 32>, int> taproot_output_key(
68 const std::array<std::uint8_t, 32>& internal_key_x,
69 const std::uint8_t* merkle_root = nullptr,
70 std::size_t merkle_root_len = 0);
71
72// -- Private Key Tweaking -----------------------------------------------------
73
74// Tweak a private key for key-path spending:
75// d' = d + t (if P has even y)
76// d' = n - d + t (if P has odd y, negate first)
77// where t = H_TapTweak(P.x || merkle_root)
78// Returns tweaked private key (zero on failure).
80 const Scalar& private_key,
81 const std::uint8_t* merkle_root = nullptr,
82 std::size_t merkle_root_len = 0);
83
84// -- Taproot Signature Validation ---------------------------------------------
85
86// Verify that output_key was correctly derived from internal_key + merkle_root.
87// This is the "control block" validation from BIP-341 S.4.2.
89 const std::array<std::uint8_t, 32>& output_key_x,
90 int output_key_parity,
91 const std::array<std::uint8_t, 32>& internal_key_x,
92 const std::uint8_t* merkle_root = nullptr,
93 std::size_t merkle_root_len = 0);
94
95// -- Script Path: Merkle Proof ------------------------------------------------
96
97// Compute merkle root from a leaf hash and proof path.
98// Each proof element is a 32-byte sibling hash. The leaf is combined
99// with each sibling in order using taproot_branch_hash.
100std::array<std::uint8_t, 32> taproot_merkle_root_from_proof(
101 const std::array<std::uint8_t, 32>& leaf_hash,
102 const std::vector<std::array<std::uint8_t, 32>>& proof);
103
104// -- TapScript Utilities ------------------------------------------------------
105
106// Construct a simple Merkle tree from a list of TapLeaf hashes.
107// Returns the Merkle root. Handles odd-count leaves by promoting the last one.
108std::array<std::uint8_t, 32> taproot_merkle_root(
109 const std::vector<std::array<std::uint8_t, 32>>& leaf_hashes);
110
111// ============================================================================
112// BIP-342: Validation of Taproot Scripts (Tapscript Sighash)
113// ============================================================================
114// Implements the signature message (SigMsg) for tapscript spending as defined
115// in BIP-342 ยง5. This is an extension of BIP-341 common signature message
116// with additional tapscript-specific fields:
117// - tapleaf_hash (tagged hash of the executed script + leaf version)
118// - key_version (0x00 for BIP-342)
119// - code_separator_position (opcode position of last OP_CODESEPARATOR)
120//
121// The epoch byte (0x00) is prepended to distinguish from future upgrades.
122
123// Input amounts and scriptPubKeys for all inputs
124// (required for BIP-341 common signature message)
126 std::uint32_t version;
127 std::uint32_t locktime;
128
129 // Per-input data
130 std::size_t input_count;
131 const std::array<std::uint8_t, 32>* prevout_txids; // input_count elements
132 const std::uint32_t* prevout_vouts; // input_count elements
133 const std::uint64_t* input_amounts; // input_count elements
134 const std::uint32_t* input_sequences; // input_count elements
135 // Per-input scriptPubKeys (for sha_scriptpubkeys)
136 const std::uint8_t* const* input_scriptpubkeys; // input_count pointers
137 const std::size_t* input_scriptpubkey_lens; // input_count lengths
138
139 // Output data
140 std::size_t output_count;
141 const std::uint64_t* output_values;
142 const std::uint8_t* const* output_scriptpubkeys;
143 const std::size_t* output_scriptpubkey_lens;
144};
145
146// Sighash types for BIP-341/342 (different encoding from legacy)
147// 0x00 = SIGHASH_DEFAULT (treated as ALL)
148// 0x01 = SIGHASH_ALL
149// 0x02 = SIGHASH_NONE
150// 0x03 = SIGHASH_SINGLE
151// 0x81 = SIGHASH_ALL|ANYONECANPAY
152// 0x82 = SIGHASH_NONE|ANYONECANPAY
153// 0x83 = SIGHASH_SINGLE|ANYONECANPAY
154
155// Compute BIP-342 tapscript signature hash.
156//
157// tx_data: Transaction data (all inputs/outputs)
158// input_index: Index of the input being signed
159// hash_type: Sighash type (0x00=DEFAULT, 0x01=ALL, etc.)
160// tapleaf_hash: H_TapLeaf(leaf_version || compact_size(script) || script)
161// key_version: 0x00 for BIP-342
162// code_separator_pos: Position of last OP_CODESEPARATOR, or 0xFFFFFFFF if none
163// annex: Optional annex data (may be nullptr if annex_len == 0)
164// annex_len: Length of annex data
165//
166// Returns: 32-byte signature hash
167std::array<std::uint8_t, 32> tapscript_sighash(
168 const TapSighashTxData& tx_data,
169 std::size_t input_index,
170 std::uint8_t hash_type,
171 const std::array<std::uint8_t, 32>& tapleaf_hash,
172 std::uint8_t key_version,
173 std::uint32_t code_separator_pos,
174 const std::uint8_t* annex = nullptr,
175 std::size_t annex_len = 0) noexcept;
176
177// Compute BIP-341 key-path signature hash.
178// Same as tapscript_sighash but without ext_flag / tapscript-specific data.
179std::array<std::uint8_t, 32> taproot_keypath_sighash(
180 const TapSighashTxData& tx_data,
181 std::size_t input_index,
182 std::uint8_t hash_type,
183 const std::uint8_t* annex = nullptr,
184 std::size_t annex_len = 0) noexcept;
185
186} // namespace secp256k1
187
188#endif // SECP256K1_TAPROOT_HPP
std::array< std::uint8_t, 32 > taproot_keypath_sighash(const TapSighashTxData &tx_data, std::size_t input_index, std::uint8_t hash_type, const std::uint8_t *annex=nullptr, std::size_t annex_len=0) noexcept
Scalar taproot_tweak_privkey(const Scalar &private_key, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
std::array< std::uint8_t, 32 > taproot_merkle_root_from_proof(const std::array< std::uint8_t, 32 > &leaf_hash, const std::vector< std::array< std::uint8_t, 32 > > &proof)
std::array< std::uint8_t, 32 > tapscript_sighash(const TapSighashTxData &tx_data, std::size_t input_index, std::uint8_t hash_type, const std::array< std::uint8_t, 32 > &tapleaf_hash, std::uint8_t key_version, std::uint32_t code_separator_pos, const std::uint8_t *annex=nullptr, std::size_t annex_len=0) noexcept
std::array< std::uint8_t, 32 > taproot_leaf_hash(const std::uint8_t *script, std::size_t script_len, std::uint8_t leaf_version=0xC0)
std::array< std::uint8_t, 32 > taproot_tweak_hash(const std::array< std::uint8_t, 32 > &internal_key_x, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
std::pair< std::array< std::uint8_t, 32 >, int > taproot_output_key(const std::array< std::uint8_t, 32 > &internal_key_x, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
bool taproot_verify_commitment(const std::array< std::uint8_t, 32 > &output_key_x, int output_key_parity, const std::array< std::uint8_t, 32 > &internal_key_x, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
std::array< std::uint8_t, 32 > taproot_merkle_root(const std::vector< std::array< std::uint8_t, 32 > > &leaf_hashes)
std::array< std::uint8_t, 32 > taproot_branch_hash(const std::array< std::uint8_t, 32 > &a, const std::array< std::uint8_t, 32 > &b)
const std::uint8_t *const * input_scriptpubkeys
Definition taproot.hpp:136
const std::uint64_t * input_amounts
Definition taproot.hpp:133
const std::uint8_t *const * output_scriptpubkeys
Definition taproot.hpp:142
const std::size_t * output_scriptpubkey_lens
Definition taproot.hpp:143
const std::array< std::uint8_t, 32 > * prevout_txids
Definition taproot.hpp:131
const std::uint64_t * output_values
Definition taproot.hpp:141
const std::uint32_t * input_sequences
Definition taproot.hpp:134
const std::size_t * input_scriptpubkey_lens
Definition taproot.hpp:137
const std::uint32_t * prevout_vouts
Definition taproot.hpp:132