Bitcoin Core  26.1.0
P2P Digital Currency
signingprovider.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <script/keyorigin.h>
7 #include <script/interpreter.h>
9 
10 #include <logging.h>
11 
13 
14 template<typename M, typename K, typename V>
15 bool LookupHelper(const M& map, const K& key, V& value)
16 {
17  auto it = map.find(key);
18  if (it != map.end()) {
19  value = it->second;
20  return true;
21  }
22  return false;
23 }
24 
25 bool HidingSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const
26 {
27  return m_provider->GetCScript(scriptid, script);
28 }
29 
30 bool HidingSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const
31 {
32  return m_provider->GetPubKey(keyid, pubkey);
33 }
34 
35 bool HidingSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const
36 {
37  if (m_hide_secret) return false;
38  return m_provider->GetKey(keyid, key);
39 }
40 
42 {
43  if (m_hide_origin) return false;
44  return m_provider->GetKeyOrigin(keyid, info);
45 }
46 
48 {
49  return m_provider->GetTaprootSpendData(output_key, spenddata);
50 }
52 {
53  return m_provider->GetTaprootBuilder(output_key, builder);
54 }
55 
56 bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
57 bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
59 {
60  std::pair<CPubKey, KeyOriginInfo> out;
61  bool ret = LookupHelper(origins, keyid, out);
62  if (ret) info = std::move(out.second);
63  return ret;
64 }
65 bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
67 {
68  TaprootBuilder builder;
69  if (LookupHelper(tr_trees, output_key, builder)) {
70  spenddata = builder.GetSpendData();
71  return true;
72  }
73  return false;
74 }
75 bool FlatSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const
76 {
77  return LookupHelper(tr_trees, output_key, builder);
78 }
79 
81 {
82  scripts.merge(b.scripts);
83  pubkeys.merge(b.pubkeys);
84  keys.merge(b.keys);
85  origins.merge(b.origins);
86  tr_trees.merge(b.tr_trees);
87  return *this;
88 }
89 
91 {
93  CKeyID key_id = pubkey.GetID();
94  // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
95  // outputs. Technically P2WPKH outputs don't have a redeemscript to be
96  // spent. However, our current IsMine logic requires the corresponding
97  // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept
98  // payment even to P2WPKH outputs.
99  // Also note that having superfluous scripts in the keystore never hurts.
100  // They're only used to guide recursion in signing and IsMine logic - if
101  // a script is present but we can't do anything with it, it has no effect.
102  // "Implicitly" refers to fact that scripts are derived automatically from
103  // existing keys, and are present in memory, even without being explicitly
104  // loaded (e.g. from a file).
105  if (pubkey.IsCompressed()) {
107  // This does not use AddCScript, as it may be overridden.
108  CScriptID id(script);
109  mapScripts[id] = std::move(script);
110  }
111 }
112 
113 bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
114 {
115  CKey key;
116  if (!GetKey(address, key)) {
117  return false;
118  }
119  vchPubKeyOut = key.GetPubKey();
120  return true;
121 }
122 
123 bool FillableSigningProvider::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
124 {
125  LOCK(cs_KeyStore);
126  mapKeys[pubkey.GetID()] = key;
128  return true;
129 }
130 
131 bool FillableSigningProvider::HaveKey(const CKeyID &address) const
132 {
133  LOCK(cs_KeyStore);
134  return mapKeys.count(address) > 0;
135 }
136 
137 std::set<CKeyID> FillableSigningProvider::GetKeys() const
138 {
139  LOCK(cs_KeyStore);
140  std::set<CKeyID> set_address;
141  for (const auto& mi : mapKeys) {
142  set_address.insert(mi.first);
143  }
144  return set_address;
145 }
146 
147 bool FillableSigningProvider::GetKey(const CKeyID &address, CKey &keyOut) const
148 {
149  LOCK(cs_KeyStore);
150  KeyMap::const_iterator mi = mapKeys.find(address);
151  if (mi != mapKeys.end()) {
152  keyOut = mi->second;
153  return true;
154  }
155  return false;
156 }
157 
159 {
160  if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
161  return error("FillableSigningProvider::AddCScript(): redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
162 
163  LOCK(cs_KeyStore);
164  mapScripts[CScriptID(redeemScript)] = redeemScript;
165  return true;
166 }
167 
169 {
170  LOCK(cs_KeyStore);
171  return mapScripts.count(hash) > 0;
172 }
173 
174 std::set<CScriptID> FillableSigningProvider::GetCScripts() const
175 {
176  LOCK(cs_KeyStore);
177  std::set<CScriptID> set_script;
178  for (const auto& mi : mapScripts) {
179  set_script.insert(mi.first);
180  }
181  return set_script;
182 }
183 
184 bool FillableSigningProvider::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
185 {
186  LOCK(cs_KeyStore);
187  ScriptMap::const_iterator mi = mapScripts.find(hash);
188  if (mi != mapScripts.end())
189  {
190  redeemScriptOut = (*mi).second;
191  return true;
192  }
193  return false;
194 }
195 
197 {
198  // Only supports destinations which map to single public keys:
199  // P2PKH, P2WPKH, P2SH-P2WPKH, P2TR
200  if (auto id = std::get_if<PKHash>(&dest)) {
201  return ToKeyID(*id);
202  }
203  if (auto witness_id = std::get_if<WitnessV0KeyHash>(&dest)) {
204  return ToKeyID(*witness_id);
205  }
206  if (auto script_hash = std::get_if<ScriptHash>(&dest)) {
207  CScript script;
208  CScriptID script_id = ToScriptID(*script_hash);
209  CTxDestination inner_dest;
210  if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
211  if (auto inner_witness_id = std::get_if<WitnessV0KeyHash>(&inner_dest)) {
212  return ToKeyID(*inner_witness_id);
213  }
214  }
215  }
216  if (auto output_key = std::get_if<WitnessV1Taproot>(&dest)) {
217  TaprootSpendData spenddata;
218  CPubKey pub;
219  if (store.GetTaprootSpendData(*output_key, spenddata)
220  && !spenddata.internal_key.IsNull()
221  && spenddata.merkle_root.IsNull()
222  && store.GetPubKeyByXOnly(spenddata.internal_key, pub)) {
223  return pub.GetID();
224  }
225  }
226  return CKeyID();
227 }
228 
229 void MultiSigningProvider::AddProvider(std::unique_ptr<SigningProvider> provider)
230 {
231  m_providers.push_back(std::move(provider));
232 }
233 
234 bool MultiSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const
235 {
236  for (const auto& provider: m_providers) {
237  if (provider->GetCScript(scriptid, script)) return true;
238  }
239  return false;
240 }
241 
242 bool MultiSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const
243 {
244  for (const auto& provider: m_providers) {
245  if (provider->GetPubKey(keyid, pubkey)) return true;
246  }
247  return false;
248 }
249 
250 
252 {
253  for (const auto& provider: m_providers) {
254  if (provider->GetKeyOrigin(keyid, info)) return true;
255  }
256  return false;
257 }
258 
259 bool MultiSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const
260 {
261  for (const auto& provider: m_providers) {
262  if (provider->GetKey(keyid, key)) return true;
263  }
264  return false;
265 }
266 
268 {
269  for (const auto& provider: m_providers) {
270  if (provider->GetTaprootSpendData(output_key, spenddata)) return true;
271  }
272  return false;
273 }
274 
276 {
277  for (const auto& provider: m_providers) {
278  if (provider->GetTaprootBuilder(output_key, builder)) return true;
279  }
280  return false;
281 }
282 
284 {
285  NodeInfo ret;
286  /* Iterate over all tracked leaves in a, add b's hash to their Merkle branch, and move them to ret. */
287  for (auto& leaf : a.leaves) {
288  leaf.merkle_branch.push_back(b.hash);
289  ret.leaves.emplace_back(std::move(leaf));
290  }
291  /* Iterate over all tracked leaves in b, add a's hash to their Merkle branch, and move them to ret. */
292  for (auto& leaf : b.leaves) {
293  leaf.merkle_branch.push_back(a.hash);
294  ret.leaves.emplace_back(std::move(leaf));
295  }
296  ret.hash = ComputeTapbranchHash(a.hash, b.hash);
297  return ret;
298 }
299 
301 {
302  // TODO: figure out how to better deal with conflicting information
303  // being merged.
304  if (internal_key.IsNull() && !other.internal_key.IsNull()) {
305  internal_key = other.internal_key;
306  }
307  if (merkle_root.IsNull() && !other.merkle_root.IsNull()) {
308  merkle_root = other.merkle_root;
309  }
310  for (auto& [key, control_blocks] : other.scripts) {
311  scripts[key].merge(std::move(control_blocks));
312  }
313 }
314 
316 {
317  assert(depth >= 0 && (size_t)depth <= TAPROOT_CONTROL_MAX_NODE_COUNT);
318  /* We cannot insert a leaf at a lower depth while a deeper branch is unfinished. Doing
319  * so would mean the Add() invocations do not correspond to a DFS traversal of a
320  * binary tree. */
321  if ((size_t)depth + 1 < m_branch.size()) {
322  m_valid = false;
323  return;
324  }
325  /* As long as an entry in the branch exists at the specified depth, combine it and propagate up.
326  * The 'node' variable is overwritten here with the newly combined node. */
327  while (m_valid && m_branch.size() > (size_t)depth && m_branch[depth].has_value()) {
328  node = Combine(std::move(node), std::move(*m_branch[depth]));
329  m_branch.pop_back();
330  if (depth == 0) m_valid = false; /* Can't propagate further up than the root */
331  --depth;
332  }
333  if (m_valid) {
334  /* Make sure the branch is big enough to place the new node. */
335  if (m_branch.size() <= (size_t)depth) m_branch.resize((size_t)depth + 1);
336  assert(!m_branch[depth].has_value());
337  m_branch[depth] = std::move(node);
338  }
339 }
340 
341 /*static*/ bool TaprootBuilder::ValidDepths(const std::vector<int>& depths)
342 {
343  std::vector<bool> branch;
344  for (int depth : depths) {
345  // This inner loop corresponds to effectively the same logic on branch
346  // as what Insert() performs on the m_branch variable. Instead of
347  // storing a NodeInfo object, just remember whether or not there is one
348  // at that depth.
349  if (depth < 0 || (size_t)depth > TAPROOT_CONTROL_MAX_NODE_COUNT) return false;
350  if ((size_t)depth + 1 < branch.size()) return false;
351  while (branch.size() > (size_t)depth && branch[depth]) {
352  branch.pop_back();
353  if (depth == 0) return false;
354  --depth;
355  }
356  if (branch.size() <= (size_t)depth) branch.resize((size_t)depth + 1);
357  assert(!branch[depth]);
358  branch[depth] = true;
359  }
360  // And this check corresponds to the IsComplete() check on m_branch.
361  return branch.size() == 0 || (branch.size() == 1 && branch[0]);
362 }
363 
364 TaprootBuilder& TaprootBuilder::Add(int depth, Span<const unsigned char> script, int leaf_version, bool track)
365 {
366  assert((leaf_version & ~TAPROOT_LEAF_MASK) == 0);
367  if (!IsValid()) return *this;
368  /* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
369  NodeInfo node;
370  node.hash = ComputeTapleafHash(leaf_version, script);
371  // due to bug in clang-tidy-17:
372  // NOLINTNEXTLINE(modernize-use-emplace)
373  if (track) node.leaves.emplace_back(LeafInfo{std::vector<unsigned char>(script.begin(), script.end()), leaf_version, {}});
374  /* Insert into the branch. */
375  Insert(std::move(node), depth);
376  return *this;
377 }
378 
380 {
381  if (!IsValid()) return *this;
382  /* Construct NodeInfo object with the hash directly, and insert it into the branch. */
383  NodeInfo node;
384  node.hash = hash;
385  Insert(std::move(node), depth);
386  return *this;
387 }
388 
390 {
391  /* Can only call this function when IsComplete() is true. */
392  assert(IsComplete());
393  m_internal_key = internal_key;
394  auto ret = m_internal_key.CreateTapTweak(m_branch.size() == 0 ? nullptr : &m_branch[0]->hash);
395  assert(ret.has_value());
396  std::tie(m_output_key, m_parity) = *ret;
397  return *this;
398 }
399 
401 
403 {
404  assert(IsComplete());
406  TaprootSpendData spd;
407  spd.merkle_root = m_branch.size() == 0 ? uint256() : m_branch[0]->hash;
408  spd.internal_key = m_internal_key;
409  if (m_branch.size()) {
410  // If any script paths exist, they have been combined into the root m_branch[0]
411  // by now. Compute the control block for each of its tracked leaves, and put them in
412  // spd.scripts.
413  for (const auto& leaf : m_branch[0]->leaves) {
414  std::vector<unsigned char> control_block;
415  control_block.resize(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * leaf.merkle_branch.size());
416  control_block[0] = leaf.leaf_version | (m_parity ? 1 : 0);
417  std::copy(m_internal_key.begin(), m_internal_key.end(), control_block.begin() + 1);
418  if (leaf.merkle_branch.size()) {
419  std::copy(leaf.merkle_branch[0].begin(),
420  leaf.merkle_branch[0].begin() + TAPROOT_CONTROL_NODE_SIZE * leaf.merkle_branch.size(),
421  control_block.begin() + TAPROOT_CONTROL_BASE_SIZE);
422  }
423  spd.scripts[{leaf.script, leaf.leaf_version}].insert(std::move(control_block));
424  }
425  }
426  return spd;
427 }
428 
429 std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output)
430 {
431  // Verify that the output matches the assumed Merkle root and internal key.
432  auto tweak = spenddata.internal_key.CreateTapTweak(spenddata.merkle_root.IsNull() ? nullptr : &spenddata.merkle_root);
433  if (!tweak || tweak->first != output) return std::nullopt;
434  // If the Merkle root is 0, the tree is empty, and we're done.
435  std::vector<std::tuple<int, std::vector<unsigned char>, int>> ret;
436  if (spenddata.merkle_root.IsNull()) return ret;
437 
439  struct TreeNode {
441  uint256 hash;
443  std::unique_ptr<TreeNode> sub[2];
446  const std::pair<std::vector<unsigned char>, int>* leaf = nullptr;
448  bool explored = false;
450  bool inner;
452  bool done = false;
453  };
454 
455  // Build tree from the provided branches.
456  TreeNode root;
457  root.hash = spenddata.merkle_root;
458  for (const auto& [key, control_blocks] : spenddata.scripts) {
459  const auto& [script, leaf_ver] = key;
460  for (const auto& control : control_blocks) {
461  // Skip script records with nonsensical leaf version.
462  if (leaf_ver < 0 || leaf_ver >= 0x100 || leaf_ver & 1) continue;
463  // Skip script records with invalid control block sizes.
464  if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE ||
465  ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) continue;
466  // Skip script records that don't match the control block.
467  if ((control[0] & TAPROOT_LEAF_MASK) != leaf_ver) continue;
468  // Skip script records that don't match the provided Merkle root.
469  const uint256 leaf_hash = ComputeTapleafHash(leaf_ver, script);
470  const uint256 merkle_root = ComputeTaprootMerkleRoot(control, leaf_hash);
471  if (merkle_root != spenddata.merkle_root) continue;
472 
473  TreeNode* node = &root;
474  size_t levels = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
475  for (size_t depth = 0; depth < levels; ++depth) {
476  // Can't descend into a node which we already know is a leaf.
477  if (node->explored && !node->inner) return std::nullopt;
478 
479  // Extract partner hash from Merkle branch in control block.
480  uint256 hash;
481  std::copy(control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - 1 - depth) * TAPROOT_CONTROL_NODE_SIZE,
482  control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - depth) * TAPROOT_CONTROL_NODE_SIZE,
483  hash.begin());
484 
485  if (node->sub[0]) {
486  // Descend into the existing left or right branch.
487  bool desc = false;
488  for (int i = 0; i < 2; ++i) {
489  if (node->sub[i]->hash == hash || (node->sub[i]->hash.IsNull() && node->sub[1-i]->hash != hash)) {
490  node->sub[i]->hash = hash;
491  node = &*node->sub[1-i];
492  desc = true;
493  break;
494  }
495  }
496  if (!desc) return std::nullopt; // This probably requires a hash collision to hit.
497  } else {
498  // We're in an unexplored node. Create subtrees and descend.
499  node->explored = true;
500  node->inner = true;
501  node->sub[0] = std::make_unique<TreeNode>();
502  node->sub[1] = std::make_unique<TreeNode>();
503  node->sub[1]->hash = hash;
504  node = &*node->sub[0];
505  }
506  }
507  // Cannot turn a known inner node into a leaf.
508  if (node->sub[0]) return std::nullopt;
509  node->explored = true;
510  node->inner = false;
511  node->leaf = &key;
512  node->hash = leaf_hash;
513  }
514  }
515 
516  // Recursive processing to turn the tree into flattened output. Use an explicit stack here to avoid
517  // overflowing the call stack (the tree may be 128 levels deep).
518  std::vector<TreeNode*> stack{&root};
519  while (!stack.empty()) {
520  TreeNode& node = *stack.back();
521  if (!node.explored) {
522  // Unexplored node, which means the tree is incomplete.
523  return std::nullopt;
524  } else if (!node.inner) {
525  // Leaf node; produce output.
526  ret.emplace_back(stack.size() - 1, node.leaf->first, node.leaf->second);
527  node.done = true;
528  stack.pop_back();
529  } else if (node.sub[0]->done && !node.sub[1]->done && !node.sub[1]->explored && !node.sub[1]->hash.IsNull() &&
530  ComputeTapbranchHash(node.sub[1]->hash, node.sub[1]->hash) == node.hash) {
531  // Whenever there are nodes with two identical subtrees under it, we run into a problem:
532  // the control blocks for the leaves underneath those will be identical as well, and thus
533  // they will all be matched to the same path in the tree. The result is that at the location
534  // where the duplicate occurred, the left child will contain a normal tree that can be explored
535  // and processed, but the right one will remain unexplored.
536  //
537  // This situation can be detected, by encountering an inner node with unexplored right subtree
538  // with known hash, and H_TapBranch(hash, hash) is equal to the parent node (this node)'s hash.
539  //
540  // To deal with this, simply process the left tree a second time (set its done flag to false;
541  // noting that the done flag of its children have already been set to false after processing
542  // those). To avoid ending up in an infinite loop, set the done flag of the right (unexplored)
543  // subtree to true.
544  node.sub[0]->done = false;
545  node.sub[1]->done = true;
546  } else if (node.sub[0]->done && node.sub[1]->done) {
547  // An internal node which we're finished with.
548  node.sub[0]->done = false;
549  node.sub[1]->done = false;
550  node.done = true;
551  stack.pop_back();
552  } else if (!node.sub[0]->done) {
553  // An internal node whose left branch hasn't been processed yet. Do so first.
554  stack.push_back(&*node.sub[0]);
555  } else if (!node.sub[1]->done) {
556  // An internal node whose right branch hasn't been processed yet. Do so first.
557  stack.push_back(&*node.sub[1]);
558  }
559  }
560 
561  return ret;
562 }
563 
564 std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> TaprootBuilder::GetTreeTuples() const
565 {
566  assert(IsComplete());
567  std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> tuples;
568  if (m_branch.size()) {
569  const auto& leaves = m_branch[0]->leaves;
570  for (const auto& leaf : leaves) {
571  assert(leaf.merkle_branch.size() <= TAPROOT_CONTROL_MAX_NODE_COUNT);
572  uint8_t depth = (uint8_t)leaf.merkle_branch.size();
573  uint8_t leaf_ver = (uint8_t)leaf.leaf_version;
574  tuples.emplace_back(depth, leaf_ver, leaf.script);
575  }
576  }
577  return tuples;
578 }
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
int ret
bool GetPubKey(const CKeyID &keyid, CPubKey &pubkey) const override
AssertLockHeld(pool.cs)
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
assert(!tx.IsCoinBase())
bool GetPubKeyByXOnly(const XOnlyPubKey &pubkey, CPubKey &out) const
bool IsNull() const
Test whether this is the 0 key (the result of default construction).
Definition: pubkey.h:249
constexpr C * end() const noexcept
Definition: span.h:175
const SigningProvider * m_provider
RecursiveMutex cs_KeyStore
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:188
std::map< CKeyID, CKey > keys
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
virtual bool AddCScript(const CScript &redeemScript)
Information associated with a node in the Merkle tree.
TaprootBuilder & AddOmitted(int depth, const uint256 &hash)
Like Add(), but for a Merkle node with a given hash to the tree.
virtual std::set< CScriptID > GetCScripts() const
std::vector< std::unique_ptr< SigningProvider > > m_providers
virtual std::set< CKeyID > GetKeys() const
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const override
std::vector< std::tuple< uint8_t, uint8_t, std::vector< unsigned char > > > GetTreeTuples() const
Returns a vector of tuples representing the depth, leaf version, and script.
static constexpr size_t TAPROOT_CONTROL_BASE_SIZE
Definition: interpreter.h:231
void AddProvider(std::unique_ptr< SigningProvider > provider)
bool GetCScript(const CScriptID &scriptid, CScript &script) const override
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
constexpr unsigned char * begin()
Definition: uint256.h:68
std::vector< std::optional< NodeInfo > > m_branch
The current state of the builder.
static constexpr size_t TAPROOT_CONTROL_NODE_SIZE
Definition: interpreter.h:232
std::optional< std::vector< std::tuple< int, std::vector< unsigned char >, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
XOnlyPubKey m_internal_key
The internal key, set when finalizing.
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
const unsigned char * begin() const
Definition: pubkey.h:290
std::map< std::pair< std::vector< unsigned char >, int >, std::set< std::vector< unsigned char >, ShortestVectorFirstComparator > > scripts
Map from (script, leaf_version) to (sets of) control blocks.
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
std::map< CScriptID, CScript > scripts
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
#define LOCK(cs)
Definition: sync.h:258
bool GetPubKey(const CKeyID &keyid, CPubKey &pubkey) const override
const SigningProvider & DUMMY_SIGNING_PROVIDER
static constexpr uint8_t TAPROOT_LEAF_MASK
Definition: interpreter.h:229
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
XOnlyPubKey m_output_key
The output key, computed when finalizing.
An encapsulated public key.
Definition: pubkey.h:33
bool GetKey(const CKeyID &keyid, CKey &key) const override
std::map< CKeyID, CPubKey > pubkeys
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
void ImplicitlyLearnRelatedKeyScripts(const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
uint256 ComputeTaprootMerkleRoot(Span< const unsigned char > control, const uint256 &tapleaf_hash)
Compute the BIP341 taproot script tree Merkle root from control block and leaf hash.
uint256 merkle_root
The Merkle root of the script tree (0 if no scripts).
constexpr bool IsNull() const
Definition: uint256.h:42
static constexpr size_t TAPROOT_CONTROL_MAX_SIZE
Definition: interpreter.h:234
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
uint256 ComputeTapleafHash(uint8_t leaf_version, Span< const unsigned char > script)
Compute the BIP341 tapleaf hash from leaf version & script.
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:214
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
FlatSigningProvider & Merge(FlatSigningProvider &&b) LIFETIMEBOUND
TaprootSpendData GetSpendData() const
Compute spending data (after Finalize()).
Definition: init.h:25
bool GetTaprootBuilder(const XOnlyPubKey &output_key, TaprootBuilder &builder) const override
Utility class to construct Taproot outputs from internal key and script tree.
bool m_parity
The tweak parity, computed when finalizing.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:129
constexpr C * begin() const noexcept
Definition: span.h:174
void Insert(NodeInfo &&node, int depth)
Insert information about a node at a certain depth, and propagate information up. ...
256-bit opaque blob.
Definition: uint256.h:106
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
Definition: interpreter.h:233
bool GetCScript(const CScriptID &scriptid, CScript &script) const override
Map from output key to Taproot tree (which can then make the TaprootSpendData.
bool GetKey(const CKeyID &keyid, CKey &key) const override
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
bool GetTaprootBuilder(const XOnlyPubKey &output_key, TaprootBuilder &builder) const override
An interface to be implemented by keystores that support signing.
bool error(const char *fmt, const Args &... args)
Definition: logging.h:262
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:412
XOnlyPubKey internal_key
The BIP341 internal key.
bool GetTaprootBuilder(const XOnlyPubKey &output_key, TaprootBuilder &builder) const override
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
TaprootBuilder & Add(int depth, Span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:26
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
uint256 ComputeTapbranchHash(Span< const unsigned char > a, Span< const unsigned char > b)
Compute the BIP341 tapbranch hash from two branches.
virtual bool HaveCScript(const CScriptID &hash) const override
CScriptID ToScriptID(const ScriptHash &script_hash)
Definition: addresstype.cpp:39
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:581
size_type size() const
Definition: prevector.h:291
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
An encapsulated private key.
Definition: key.h:32
bool GetKey(const CKeyID &keyid, CKey &key) const override
static NodeInfo Combine(NodeInfo &&a, NodeInfo &&b)
Combine information about a parent Merkle tree node from its child nodes.
bool IsValid() const
Return true if so far all input was valid.
const unsigned char * end() const
Definition: pubkey.h:291
std::optional< std::pair< XOnlyPubKey, bool > > CreateTapTweak(const uint256 *merkle_root) const
Construct a Taproot tweaked output point with this point as internal key.
Definition: pubkey.cpp:249
bool LookupHelper(const M &map, const K &key, V &value)
virtual bool GetTaprootBuilder(const XOnlyPubKey &output_key, TaprootBuilder &builder) const
bool GetPubKey(const CKeyID &keyid, CPubKey &pubkey) const override
bool GetCScript(const CScriptID &scriptid, CScript &script) const override
Information about a tracked leaf in the Merkle tree.
bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const override
CKeyID ToKeyID(const PKHash &key_hash)
Definition: addresstype.cpp:29
std::map< XOnlyPubKey, TaprootBuilder > tr_trees
void Merge(TaprootSpendData other)
Merge other TaprootSpendData (for the same scriptPubKey) into this.
bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const override
bool m_valid
Whether the builder is in a valid state so far.
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:204
virtual bool HaveKey(const CKeyID &address) const override