From 2320184d0ea87279558a8e6cbb3bccf5ba1bb781 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 30 Jul 2025 16:34:36 -0700 Subject: [PATCH 01/17] descriptors: Fix meaning of any_key_parsed Invert any_key_parsed so that the name matches the behavior. --- src/script/descriptor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index bd819d365ae..83a561a7e78 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -1843,20 +1843,20 @@ std::vector> ParsePubkey(uint32_t& key_exp_index bool any_ranged = false; bool all_bip32 = true; std::vector>> providers; - bool any_key_parsed = true; + bool any_key_parsed = false; size_t max_multipath_len = 0; while (expr.size()) { - if (!any_key_parsed && !Const(",", expr)) { + if (any_key_parsed && !Const(",", expr)) { error = strprintf("musig(): expected ',', got '%c'", expr[0]); return {}; } - any_key_parsed = false; auto arg = Expr(expr); auto pk = ParsePubkey(key_exp_index, arg, ParseScriptContext::MUSIG, out, error); if (pk.empty()) { error = strprintf("musig(): %s", error); return {}; } + any_key_parsed = true; any_ranged = any_ranged || pk.at(0)->IsRange(); all_bip32 = all_bip32 && pk.at(0)->IsBIP32(); @@ -1866,7 +1866,7 @@ std::vector> ParsePubkey(uint32_t& key_exp_index providers.emplace_back(std::move(pk)); key_exp_index++; } - if (any_key_parsed) { + if (!any_key_parsed) { error = "musig(): Must contain key expressions"; return {}; } From 39a63bf2e7e38dd3f30b5d1a8f6b2fff0e380d12 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 30 Jul 2025 16:36:12 -0700 Subject: [PATCH 02/17] descriptors: Add a doxygen comment for has_hardened output_parameter --- src/script/descriptor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 83a561a7e78..3a402702178 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -1647,6 +1647,7 @@ std::optional ParseKeyPathNum(std::span elem, bool& apostr * @param[out] apostrophe only updated if hardened derivation is found * @param[out] error parsing error message * @param[in] allow_multipath Allows the parsed path to use the multipath specifier + * @param[out] has_hardened Records whether the path contains any hardened derivation * @returns false if parsing failed **/ [[nodiscard]] bool ParseKeyPath(const std::vector>& split, std::vector& out, bool& apostrophe, std::string& error, bool allow_multipath, bool& has_hardened) From a4cfddda644f1fc9a815b2d16c997716cd63554a Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 30 Jul 2025 16:36:54 -0700 Subject: [PATCH 03/17] tests: Clarify why musig derivation adds a pubkey and xpub --- src/test/descriptor_tests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 4dc94134278..69ae51610eb 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -52,7 +52,7 @@ constexpr int XONLY_KEYS = 1 << 6; // X-only pubkeys are in use (and thus inferr constexpr int MISSING_PRIVKEYS = 1 << 7; // Not all private keys are available, so ToPrivateString will fail. constexpr int SIGNABLE_FAILS = 1 << 8; // We can sign with this descriptor, but actually trying to sign will fail constexpr int MUSIG = 1 << 9; // This is a MuSig so key counts will have an extra key -constexpr int MUSIG_DERIVATION = 1 << 10; // MuSig with derivation from the aggregate key +constexpr int MUSIG_DERIVATION = 1 << 10; // MuSig with BIP 328 derivation from the aggregate key constexpr int MIXED_MUSIG = 1 << 11; // Both MuSig and normal key expressions are present constexpr int UNIQUE_XPUBS = 1 << 12; // Whether the xpub count should be of unique xpubs @@ -315,6 +315,7 @@ void DoCheck(std::string prv, std::string pub, const std::string& norm_pub, int size_t num_xpubs = CountXpubs(pub1); size_t num_unique_xpubs = CountUniqueXpubs(pub1); if (flags & MUSIG_DERIVATION) { + // Deriving from the aggregate will include the synthetic xpub of the aggregate in the caches and SigningProviders. num_xpubs++; num_unique_xpubs++; } From fb8720f1e09f4e41802f07be53fb220d6f6c127f Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 5 Feb 2024 15:09:40 -0500 Subject: [PATCH 04/17] sign: Refactor Schnorr sighash computation out of CreateSchnorrSig There will be other functions within MutableTransactionSignatureCreator that need to compute the same sighash, so make it a separate member function. --- src/script/sign.cpp | 26 ++++++++++++++++++-------- src/script/sign.h | 2 ++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 33cbc38be41..1e40d5328fc 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -59,17 +59,14 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid return true; } -bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider& provider, std::vector& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const +std::optional MutableTransactionSignatureCreator::ComputeSchnorrSignatureHash(const uint256* leaf_hash, SigVersion sigversion) const { assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT); - CKey key; - if (!provider.GetKeyByXOnly(pubkey, key)) return false; - // BIP341/BIP342 signing needs lots of precomputed transaction data. While some // (non-SIGHASH_DEFAULT) sighash modes exist that can work with just some subset // of data present, for now, only support signing when everything is provided. - if (!m_txdata || !m_txdata->m_bip341_taproot_ready || !m_txdata->m_spent_outputs_ready) return false; + if (!m_txdata || !m_txdata->m_bip341_taproot_ready || !m_txdata->m_spent_outputs_ready) return std::nullopt; ScriptExecutionData execdata; execdata.m_annex_init = true; @@ -77,15 +74,28 @@ bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider& if (sigversion == SigVersion::TAPSCRIPT) { execdata.m_codeseparator_pos_init = true; execdata.m_codeseparator_pos = 0xFFFFFFFF; // Only support non-OP_CODESEPARATOR BIP342 signing for now. - if (!leaf_hash) return false; // BIP342 signing needs leaf hash. + if (!leaf_hash) return std::nullopt; // BIP342 signing needs leaf hash. execdata.m_tapleaf_hash_init = true; execdata.m_tapleaf_hash = *leaf_hash; } uint256 hash; - if (!SignatureHashSchnorr(hash, execdata, m_txto, nIn, nHashType, sigversion, *m_txdata, MissingDataBehavior::FAIL)) return false; + if (!SignatureHashSchnorr(hash, execdata, m_txto, nIn, nHashType, sigversion, *m_txdata, MissingDataBehavior::FAIL)) return std::nullopt; + return hash; +} + +bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider& provider, std::vector& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const +{ + assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT); + + CKey key; + if (!provider.GetKeyByXOnly(pubkey, key)) return false; + + std::optional hash = ComputeSchnorrSignatureHash(leaf_hash, sigversion); + if (!hash.has_value()) return false; + sig.resize(64); // Use uint256{} as aux_rnd for now. - if (!key.SignSchnorr(hash, sig, merkle_root, {})) return false; + if (!key.SignSchnorr(*hash, sig, merkle_root, {})) return false; if (nHashType) sig.push_back(nHashType); return true; } diff --git a/src/script/sign.h b/src/script/sign.h index fe2c470bc64..5af6392b128 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -45,6 +45,8 @@ class MutableTransactionSignatureCreator : public BaseSignatureCreator const MutableTransactionSignatureChecker checker; const PrecomputedTransactionData* m_txdata; + std::optional ComputeSchnorrSignatureHash(const uint256* leaf_hash, SigVersion sigversion) const; + public: MutableTransactionSignatureCreator(const CMutableTransaction& tx LIFETIMEBOUND, unsigned int input_idx, const CAmount& amount, int hash_type); MutableTransactionSignatureCreator(const CMutableTransaction& tx LIFETIMEBOUND, unsigned int input_idx, const CAmount& amount, const PrecomputedTransactionData* txdata, int hash_type); From f14876213aad0e67088b75cae24323db9f2576d8 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Tue, 16 Sep 2025 16:09:31 -0700 Subject: [PATCH 05/17] musig: Move synthetic xpub construction to its own function --- src/musig.cpp | 11 +++++++++++ src/musig.h | 3 +++ src/script/descriptor.cpp | 8 +------- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/musig.cpp b/src/musig.cpp index b3329543127..85074796cbf 100644 --- a/src/musig.cpp +++ b/src/musig.cpp @@ -51,3 +51,14 @@ std::optional MuSig2AggregatePubkeys(const std::vector& pubkey } return GetCPubKeyFromMuSig2KeyAggCache(keyagg_cache); } + +CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey) +{ + CExtPubKey extpub; + extpub.nDepth = 0; + std::memset(extpub.vchFingerprint, 0, 4); + extpub.nChild = 0; + extpub.chaincode = MUSIG_CHAINCODE; + extpub.pubkey = pubkey; + return extpub; +} diff --git a/src/musig.h b/src/musig.h index d46a67f65ec..0bc1f5ff6f1 100644 --- a/src/musig.h +++ b/src/musig.h @@ -23,4 +23,7 @@ std::optional GetCPubKeyFromMuSig2KeyAggCache(secp256k1_musig_keyagg_ca //! Compute the full aggregate pubkey from the given participant pubkeys in their current order std::optional MuSig2AggregatePubkeys(const std::vector& pubkeys); +//! Construct the BIP 328 synthetic xpub for a pubkey +CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey); + #endif // BITCOIN_MUSIG_H diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 3a402702178..d0436702124 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -641,13 +641,7 @@ public: // Make our pubkey provider if (IsRangedDerivation() || !m_path.empty()) { // Make the synthetic xpub and construct the BIP32PubkeyProvider - CExtPubKey extpub; - extpub.nDepth = 0; - std::memset(extpub.vchFingerprint, 0, 4); - extpub.nChild = 0; - extpub.chaincode = MUSIG_CHAINCODE; - extpub.pubkey = m_aggregate_pubkey.value(); - + CExtPubKey extpub = CreateMuSig2SyntheticXpub(m_aggregate_pubkey.value()); m_aggregate_provider = std::make_unique(m_expr_index, extpub, m_path, m_derive, /*apostrophe=*/false); } else { m_aggregate_provider = std::make_unique(m_expr_index, m_aggregate_pubkey.value(), /*xonly=*/false); From 4b24bfeab9d6732aae3e69efd33105792ef1198f Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 4 Mar 2024 15:40:00 -0500 Subject: [PATCH 06/17] pubkey: Return tweaks from BIP32 derivation MuSig2 needs the BIP32 derivation tweaks in order to sign with a key derived from the aggregate pubkey. --- src/pubkey.cpp | 9 ++++++--- src/pubkey.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 6041c89e7f1..264f861bc7a 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -338,13 +338,16 @@ bool CPubKey::Decompress() { return true; } -bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const { +bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, uint256* bip32_tweak_out) const { assert(IsValid()); assert((nChild >> 31) == 0); assert(size() == COMPRESSED_SIZE); unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); + if (bip32_tweak_out) { + memcpy(bip32_tweak_out->begin(), out, 32); + } secp256k1_pubkey pubkey; if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) { return false; @@ -409,13 +412,13 @@ void CExtPubKey::DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VE Decode(&code[4]); } -bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const { +bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild, uint256* bip32_tweak_out) const { if (nDepth == std::numeric_limits::max()) return false; out.nDepth = nDepth + 1; CKeyID id = pubkey.GetID(); memcpy(out.vchFingerprint, &id, 4); out.nChild = _nChild; - return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode); + return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode, bip32_tweak_out); } /* static */ bool CPubKey::CheckLowS(const std::vector& vchSig) { diff --git a/src/pubkey.h b/src/pubkey.h index 442dc2d6431..5ae7f75dde9 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -224,7 +224,7 @@ public: bool Decompress(); //! Derive BIP32 child pubkey. - [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; + [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, uint256* bip32_tweak_out = nullptr) const; }; class XOnlyPubKey @@ -379,7 +379,7 @@ struct CExtPubKey { void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const; void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]); - [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const; + [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild, uint256* bip32_tweak_out = nullptr) const; }; #endif // BITCOIN_PUBKEY_H From 9baff05e494443cd82708490f384aa3034ad43bd Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 4 Mar 2024 17:53:37 -0500 Subject: [PATCH 07/17] sign: Include taproot output key's KeyOriginInfo in sigdata --- src/script/sign.cpp | 14 +++++++++++--- src/script/sign.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 1e40d5328fc..8575c0b90da 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -355,11 +355,19 @@ static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCrea // Try key path spending. { - KeyOriginInfo info; - if (provider.GetKeyOriginByXOnly(sigdata.tr_spenddata.internal_key, info)) { + KeyOriginInfo internal_key_info; + if (provider.GetKeyOriginByXOnly(sigdata.tr_spenddata.internal_key, internal_key_info)) { auto it = sigdata.taproot_misc_pubkeys.find(sigdata.tr_spenddata.internal_key); if (it == sigdata.taproot_misc_pubkeys.end()) { - sigdata.taproot_misc_pubkeys.emplace(sigdata.tr_spenddata.internal_key, std::make_pair(std::set(), info)); + sigdata.taproot_misc_pubkeys.emplace(sigdata.tr_spenddata.internal_key, std::make_pair(std::set(), internal_key_info)); + } + } + + KeyOriginInfo output_key_info; + if (provider.GetKeyOriginByXOnly(output, output_key_info)) { + auto it = sigdata.taproot_misc_pubkeys.find(output); + if (it == sigdata.taproot_misc_pubkeys.end()) { + sigdata.taproot_misc_pubkeys.emplace(output, std::make_pair(std::set(), output_key_info)); } } diff --git a/src/script/sign.h b/src/script/sign.h index 5af6392b128..fea937108ba 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -80,7 +80,7 @@ struct SignatureData { std::map> misc_pubkeys; std::vector taproot_key_path_sig; /// Schnorr signature for key path spending std::map, std::vector> taproot_script_sigs; ///< (Partial) schnorr signatures, indexed by XOnlyPubKey and leaf_hash. - std::map, KeyOriginInfo>> taproot_misc_pubkeys; ///< Miscellaneous Taproot pubkeys involved in this input along with their leaf script hashes and key origin data. Also includes the Taproot internal key (may have no leaf script hashes). + std::map, KeyOriginInfo>> taproot_misc_pubkeys; ///< Miscellaneous Taproot pubkeys involved in this input along with their leaf script hashes and key origin data. Also includes the Taproot internal and output keys (may have no leaf script hashes). std::map tap_pubkeys; ///< Misc Taproot pubkeys involved in this input, by hash. (Equivalent of misc_pubkeys but for Taproot.) std::vector missing_pubkeys; ///< KeyIDs of pubkeys which could not be found std::vector missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found From c06a1dc86ff2347538e95041ab7b97af25342958 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 25 Mar 2024 16:13:58 -0400 Subject: [PATCH 08/17] Add MuSig2SecNonce class for secure allocation of musig nonces --- src/musig.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/musig.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/musig.cpp b/src/musig.cpp index 85074796cbf..c361a7ea890 100644 --- a/src/musig.cpp +++ b/src/musig.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include @@ -62,3 +63,43 @@ CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey) extpub.pubkey = pubkey; return extpub; } + +class MuSig2SecNonceImpl +{ +private: + //! The actual secnonce itself + secure_unique_ptr m_nonce; + +public: + MuSig2SecNonceImpl() : m_nonce{make_secure_unique()} {} + + // Delete copy constructors + MuSig2SecNonceImpl(const MuSig2SecNonceImpl&) = delete; + MuSig2SecNonceImpl& operator=(const MuSig2SecNonceImpl&) = delete; + + secp256k1_musig_secnonce* Get() const { return m_nonce.get(); } + void Invalidate() { m_nonce.reset(); } + bool IsValid() { return m_nonce != nullptr; } +}; + +MuSig2SecNonce::MuSig2SecNonce() : m_impl{std::make_unique()} {} + +MuSig2SecNonce::MuSig2SecNonce(MuSig2SecNonce&&) noexcept = default; +MuSig2SecNonce& MuSig2SecNonce::operator=(MuSig2SecNonce&&) noexcept = default; + +MuSig2SecNonce::~MuSig2SecNonce() = default; + +secp256k1_musig_secnonce* MuSig2SecNonce::Get() const +{ + return m_impl->Get(); +} + +void MuSig2SecNonce::Invalidate() +{ + return m_impl->Invalidate(); +} + +bool MuSig2SecNonce::IsValid() +{ + return m_impl->IsValid(); +} diff --git a/src/musig.h b/src/musig.h index 0bc1f5ff6f1..40da1f10b97 100644 --- a/src/musig.h +++ b/src/musig.h @@ -11,6 +11,8 @@ #include struct secp256k1_musig_keyagg_cache; +class MuSig2SecNonceImpl; +struct secp256k1_musig_secnonce; //! MuSig2 chaincode as defined by BIP 328 using namespace util::hex_literals; @@ -26,4 +28,35 @@ std::optional MuSig2AggregatePubkeys(const std::vector& pubkey //! Construct the BIP 328 synthetic xpub for a pubkey CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey); +/** + * MuSig2SecNonce encapsulates a secret nonce in use in a MuSig2 signing session. + * Since this nonce persists outside of libsecp256k1 signing code, we must handle + * its construction and destruction ourselves. + * The secret nonce must be kept a secret, otherwise the private key may be leaked. + * As such, it needs to be treated in the same way that CKeys are treated. + * So this class handles the secure allocation of the secp256k1_musig_secnonce object + * that libsecp256k1 uses, and only gives out references to this object to avoid + * any possibility of copies being made. Furthermore, objects of this class are not + * copyable to avoid nonce reuse. +*/ +class MuSig2SecNonce +{ +private: + std::unique_ptr m_impl; + +public: + MuSig2SecNonce(); + MuSig2SecNonce(MuSig2SecNonce&&) noexcept; + MuSig2SecNonce& operator=(MuSig2SecNonce&&) noexcept; + ~MuSig2SecNonce(); + + // Delete copy constructors + MuSig2SecNonce(const MuSig2SecNonce&) = delete; + MuSig2SecNonce& operator=(const MuSig2SecNonce&) = delete; + + secp256k1_musig_secnonce* Get() const; + void Invalidate(); + bool IsValid(); +}; + #endif // BITCOIN_MUSIG_H From 4d8b4f53363f013ed3972997f0b05b9c19e9db9d Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 5 Feb 2024 16:49:09 -0500 Subject: [PATCH 09/17] signingprovider: Add musig2 secnonces Adds GetMuSig2SecNonces which returns secp256k1_musig_secnonce*, and DeleteMuSig2Session which removes the MuSig2 secnonce from wherever it was retrieved. FlatSigningProvider stores it as a pointer to a map of session id to secnonce so that deletion will actually delete from the object that actually owns the secnonces. The session id is just a unique identifier for the caller to determine what secnonces have been created. --- src/script/signingprovider.cpp | 37 ++++++++++++++++++++++++++++++++++ src/script/signingprovider.h | 14 +++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp index 792796b0f14..846f0c98da2 100644 --- a/src/script/signingprovider.cpp +++ b/src/script/signingprovider.cpp @@ -58,6 +58,21 @@ std::vector HidingSigningProvider::GetMuSig2ParticipantPubkeys(const CP return m_provider->GetMuSig2ParticipantPubkeys(pubkey); } +void HidingSigningProvider::SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const +{ + m_provider->SetMuSig2SecNonce(id, std::move(nonce)); +} + +std::optional> HidingSigningProvider::GetMuSig2SecNonce(const uint256& session_id) const +{ + return m_provider->GetMuSig2SecNonce(session_id); +} + +void HidingSigningProvider::DeleteMuSig2Session(const uint256& session_id) const +{ + m_provider->DeleteMuSig2Session(session_id); +} + bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); } bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); } bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const @@ -94,6 +109,26 @@ std::vector FlatSigningProvider::GetMuSig2ParticipantPubkeys(const CPub return participant_pubkeys; } +void FlatSigningProvider::SetMuSig2SecNonce(const uint256& session_id, MuSig2SecNonce&& nonce) const +{ + if (!Assume(musig2_secnonces)) return; + musig2_secnonces->emplace(session_id, std::move(nonce)); +} + +std::optional> FlatSigningProvider::GetMuSig2SecNonce(const uint256& session_id) const +{ + if (!Assume(musig2_secnonces)) return std::nullopt; + const auto& it = musig2_secnonces->find(session_id); + if (it == musig2_secnonces->end()) return std::nullopt; + return it->second; +} + +void FlatSigningProvider::DeleteMuSig2Session(const uint256& session_id) const +{ + if (!Assume(musig2_secnonces)) return; + musig2_secnonces->erase(session_id); +} + FlatSigningProvider& FlatSigningProvider::Merge(FlatSigningProvider&& b) { scripts.merge(b.scripts); @@ -102,6 +137,8 @@ FlatSigningProvider& FlatSigningProvider::Merge(FlatSigningProvider&& b) origins.merge(b.origins); tr_trees.merge(b.tr_trees); aggregate_pubkeys.merge(b.aggregate_pubkeys); + // We shouldn't be merging 2 different sessions, just overwrite with b's sessions. + if (!musig2_secnonces) musig2_secnonces = b.musig2_secnonces; return *this; } diff --git a/src/script/signingprovider.h b/src/script/signingprovider.h index 1da58bf6f92..cc917cc6c63 100644 --- a/src/script/signingprovider.h +++ b/src/script/signingprovider.h @@ -9,11 +9,15 @@ #include #include #include +#include #include #include