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