Implements parsing of BIP 390 musig()
descriptors.
Depends on #31243
Split from #29675
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31244.
See the guideline for information on the review process.
Type | Reviewers |
---|---|
Concept ACK | theStack |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Reviewers, this pull request conflicts with the following ones:
XOnlyPubKey::GetKeyIDs()
to return a pair of pubkeys by w0xlt)If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
Possible typos and grammar issues:
0$ echo "cGsobXVzaWcoZGR9dXVlLzAwLylrKA==" | base64 --decode > mocked_descriptor_parse_1.crash
1$ FUZZ=mocked_descriptor_parse fuzz mocked_descriptor_parse_1.crash
2script/descriptor.cpp:1838 ParsePubkey: Assertion `Func("musig", expr)' failed.
3
4$ echo "dHIobXVzaWcoICAgICB0dXVzKG9sZGVwayhnZylnZ2dnZmdnKTwseigoKCgoKCgoKCgoKCgoKCgoKCgoKHN0KQ==" | base64 --decode > mocked_descriptor_parse_2.crash
5$ FUZZ=mocked_descriptor_parse fuzz mocked_descriptor_parse_2.crash
6script/descriptor.cpp:1833 ParsePubkey: Assertion `split.size() <= 2' failed.
0$ echo "dHIobXVzaWcoJTIyLzMzMmgpSigoKChhZGRyKEJjdXUp" | base64 --decode > mocked_descriptor_parse_3.crash
1$ FUZZ=mocked_descriptor_parse fuzz mocked_descriptor_parse_3.crash
2script/descriptor.cpp:632 GetPubKey: Assertion `pubkey.has_value()' failed.
0$ echo "dHIobXVzaWcoKS8wMDAwMTEp" | base64 --decode > descriptor_parse_1.crash
1$ FUZZ=descriptor_parse fuzz descriptor_parse_1.crash
2[libsecp256k1] illegal argument: pubkeys != NULL
0$ echo "dHIobXVzaWcoJWU5LzwwOzAwMDAwMzU7MDYwOzM7MDY+KS82Nik=" | base64 --decode > mocked_descriptor_parse_4.crash
1$ FUZZ=mocked_descriptor_parse fuzz mocked_descriptor_parse_4.crash
2fuzz: script/descriptor.cpp:1942: std::vector<std::unique_ptr<PubkeyProvider>> (anonymous namespace)::ParsePubkey(uint32_t &, const Span<const char> &, ParseScriptContext, FlatSigningProvider &, std::string &): Assertion `pub.size() == 1' failed.
🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/34992034826
Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:
Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.
An intermittent issue.
Leave a comment here, if you need help tracking down a confusing failure.
🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/40357481289
Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:
Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.
An intermittent issue.
Leave a comment here, if you need help tracking down a confusing failure.
We need to retrieve the even and odd compressed pubkeys for xonly
pubkeys, so add a function to do that. Also reuse it in GetKeyIDs.
When splitting a string, sometimes the separator needs to be included.
Split will now optionally include the separator on the left side of the
splits, i.e. it appears at the end of the splits, except for the last
one.
- MuSig2KeyAggCache contains a MuSig2KeyAggCacheImpl which has the
secp256ke_musig_keyagg_cache object to avoid having to link libsecp256k1
everywhere.
- GetMuSig2KeyAggCache creates the MuSig2KeyAggCache from a
std::vector<CPubKey>
- GetCPubKeyFromMuSig2KeyAggCache creates a CPubKey from a cache created
with GetMuSig2KeyAggCache
- MuSig2AggregatePubKeys does the two above functions together.
86@@ -82,13 +87,21 @@ bool FlatSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, Tapro
87 return LookupHelper(tr_trees, output_key, builder);
88 }
89
90+std::vector<CPubKey> FlatSigningProvider::GetAggregateParticipantPubkeys(const CPubKey& pubkey) const
91+{
92+ const auto& it = aggregate_pubkeys.find(pubkey);
93+ if (it == aggregate_pubkeys.end()) return {};
94+ return it->second;
nit: could use LookupHelper
here (for slightly better readability imho)
0 std::vector<CPubKey> participant_pubkeys;
1 LookupHelper(aggregate_pubkeys, pubkey, participant_pubkeys);
2 return participant_pubkeys;
5+#ifndef BITCOIN_MUSIG_H
6+#define BITCOIN_MUSIG_H
7+
8+#include <pubkey.h>
9+
10+#include <vector>
nit: should also include <optional>
, since it’s used for the return types below
0#include <optional>
1#include <vector>
598+ bool IsRangedParticipants() const
599+ {
600+ for (const auto& pubkey : m_participants) {
601+ if (pubkey->IsRange()) return true;
602+ }
603+ return false;
std::any_of
788+ // musig() can only be a BIP 32 key if all participants are bip32 too
789+ bool all_bip32 = true;
790+ for (const auto& pk : m_participants) {
791+ all_bip32 &= pk->IsBIP32();
792+ }
793+ return all_bip32;
std::all_of
Concept ACK
Seems like the commit message for 2e6dcdbc8055660a2e20ba81b62b7d26ae0ccb05 (“Add MuSig2 Keyagg Cache class and functions”) is out-of-sync, as there is no such class added and also the mentioned MuSig2KeyAggCacheImpl
doesn’t exist.
For the newly introduced parameters of the Const
and Split
functions (commits fe02d7cb237c00de6abe1776b3101342ffddf757 and 4a1eeee27a64c4be7293740f8fff839879b88d86), it would be nice to have unit test coverage, but this can be also done in a follow-up.