From bb05986c0a8e2814554156b96f49358cbb2628fa Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 11 May 2026 19:04:49 -0700 Subject: [PATCH] musig: Include pubnonce in session id Multiple signing sessions over the same message are allowed. Including the pubnonce in the session id allows distinguishing the signing sessions. This should be safe as a new secret nonce is used for each signing session, and after the nonce is used, it is still deleted from memory in order to avoid reuse. --- src/musig.cpp | 4 ++-- src/musig.h | 6 +++++- src/script/sign.cpp | 6 ++++-- src/wallet/scriptpubkeyman.h | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/musig.cpp b/src/musig.cpp index 706874be2cf..4031b87d06d 100644 --- a/src/musig.cpp +++ b/src/musig.cpp @@ -119,10 +119,10 @@ bool MuSig2SecNonce::IsValid() return m_impl->IsValid(); } -uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash) +uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash, const std::vector& pubnonce) { HashWriter hasher; - hasher << script_pubkey << part_pubkey << sighash; + hasher << script_pubkey << part_pubkey << sighash << pubnonce; return hasher.GetSHA256(); } diff --git a/src/musig.h b/src/musig.h index f518ae81ba2..1b86d116701 100644 --- a/src/musig.h +++ b/src/musig.h @@ -56,7 +56,11 @@ public: bool IsValid(); }; -uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash); +/** + * Computes an arbitrary unique session ID to identify ongoing signing sessions. + * It is the SHA256 of the aggregate xonly key, the participant pubkey, the sighash, and the pubnonce + */ +uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash, const std::vector& pubnonce); std::optional> CreateMuSig2AggregateSig(const std::vector& participants, const CPubKey& aggregate_pubkey, const std::vector>& tweaks, const uint256& sighash, const std::map>& pubnonces, const std::map& partial_sigs); diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 6cbcf07e5e2..372ed03d8d9 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -123,7 +123,7 @@ std::vector MutableTransactionSignatureCreator::CreateMuSig2Nonce(const if (out.empty()) return {}; // Store the secnonce in the SigningProvider - provider.SetMuSig2SecNonce(MuSig2SessionID(script_pubkey, part_pubkey, *sighash), std::move(secnonce)); + provider.SetMuSig2SecNonce(MuSig2SessionID(script_pubkey, part_pubkey, *sighash, out), std::move(secnonce)); return out; } @@ -156,7 +156,9 @@ bool MutableTransactionSignatureCreator::CreateMuSig2PartialSig(const SigningPro if (!sighash.has_value()) return false; // Retrieve the secnonce - uint256 session_id = MuSig2SessionID(script_pubkey, part_pubkey, *sighash); + auto part_pubnonce_it = pubnonces.find(part_pubkey); + if (part_pubnonce_it == pubnonces.end()) return false; + uint256 session_id = MuSig2SessionID(script_pubkey, part_pubkey, *sighash, part_pubnonce_it->second); std::optional> secnonce = provider.GetMuSig2SecNonce(session_id); if (!secnonce || !secnonce->get().IsValid()) return false; diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 1bc5249ca81..06ee020a79c 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -299,7 +299,7 @@ private: * must be done in order to prevent nonce reuse. * * The session id is an arbitrary value set by the signer in order for the signing logic - * to find ongoing signing sessions. It is the SHA256 of aggregate xonly key, + participant pubkey + sighash. + * to find ongoing signing sessions, see MuSig2SessionID. */ mutable std::map m_musig2_secnonces;