refactor, key: move `CreateMuSig2Nonce` to `musig.{h,cpp}` module
What changed, and why it matters
This commit is a code cleanup: it moves a function that creates MuSig2 cryptographic nonces from the CKey class into a dedicated musig module. The actual logic and security behavior are unchanged; only where the code lives and how callers reference it are modified.
No security action required. Treat as ordinary code-quality review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors CreateMuSig2Nonce. It removes the method from CKey (key.h/key.cpp) and adds it as a free function in musig.cpp/musig.h, passing the secret key as an explicit parameter instead of using this. The implementation remains functionally identical: it still aggregates pubkeys, parses the participant pubkey, draws strong randomness via GetStrongRandBytes, calls secp256k1_musig_nonce_gen with the same arguments, and serializes the pubnonce. The single caller in script/sign.cpp is updated to use the free function. No security-sensitive behavior changes.
Changed components
src/key.cppsrc/key.hsrc/musig.cppsrc/musig.hsrc/script/sign.cppInspect captured patch +39 / −35
diff --git a/src/key.cpp b/src/key.cpp
index 60f6eb67..c61616f1 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -350,39 +350,6 @@ KeyPair CKey::ComputeKeyPair(const uint256* merkle_root) const
return KeyPair(*this, merkle_root);
}
-std::vector<uint8_t> CKey::CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys)
-{
- // Get the keyagg cache and aggregate pubkey
- secp256k1_musig_keyagg_cache keyagg_cache;
- if (!MuSig2AggregatePubkeys(pubkeys, keyagg_cache, aggregate_pubkey)) return {};
-
- // Parse participant pubkey
- CPubKey our_pubkey = GetPubKey();
- secp256k1_pubkey pubkey;
- if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, our_pubkey.data(), our_pubkey.size())) {
- return {};
- }
-
- // Generate randomness for nonce
- uint256 rand;
- GetStrongRandBytes(rand);
-
- // Generate nonce
- secp256k1_musig_pubnonce pubnonce;
- if (!secp256k1_musig_nonce_gen(secp256k1_context_sign, secnonce.Get(), &pubnonce, rand.data(), UCharCast(begin()), &pubkey, sighash.data(), &keyagg_cache, nullptr)) {
- return {};
- }
-
- // Serialize pubnonce
- std::vector<uint8_t> out;
- out.resize(MUSIG2_PUBNONCE_SIZE);
- if (!secp256k1_musig_pubnonce_serialize(secp256k1_context_static, out.data(), &pubnonce)) {
- return {};
- }
-
- return out;
-}
-
std::optional<uint256> CKey::CreateMuSig2PartialSig(const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, MuSig2SecNonce& secnonce, const std::vector<std::pair<uint256, bool>>& tweaks)
{
secp256k1_keypair keypair;
diff --git a/src/key.h b/src/key.h
index e2c9d82f..e9f34a1a 100644
--- a/src/key.h
+++ b/src/key.h
@@ -224,7 +224,6 @@ public:
*/
KeyPair ComputeKeyPair(const uint256* merkle_root) const;
- std::vector<uint8_t> CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys);
std::optional<uint256> CreateMuSig2PartialSig(const uint256& hash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, MuSig2SecNonce& secnonce, const std::vector<std::pair<uint256, bool>>& tweaks);
};
diff --git a/src/musig.cpp b/src/musig.cpp
index 706874be..73089ea8 100644
--- a/src/musig.cpp
+++ b/src/musig.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <musig.h>
+#include <key.h>
+#include <random.h>
#include <support/allocators/secure.h>
#include <secp256k1_musig.h>
@@ -126,6 +128,40 @@ uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey
return hasher.GetSHA256();
}
+std::vector<uint8_t> CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys)
+{
+ // Get the keyagg cache and aggregate pubkey
+ secp256k1_musig_keyagg_cache keyagg_cache;
+ if (!MuSig2AggregatePubkeys(pubkeys, keyagg_cache, aggregate_pubkey)) return {};
+
+ // Parse participant pubkey
+ CPubKey our_pubkey = our_seckey.GetPubKey();
+ secp256k1_pubkey pubkey;
+ if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, our_pubkey.data(), our_pubkey.size())) {
+ return {};
+ }
+
+ // Generate randomness for nonce
+ uint256 rand;
+ GetStrongRandBytes(rand);
+
+ // Generate nonce
+ secp256k1_musig_pubnonce pubnonce;
+ if (!secp256k1_musig_nonce_gen(GetSecp256k1SignContext(), secnonce.Get(), &pubnonce, rand.data(), UCharCast(our_seckey.begin()), &pubkey, sighash.data(), &keyagg_cache, nullptr)) {
+ return {};
+ }
+
+ // Serialize pubnonce
+ std::vector<uint8_t> out;
+ out.resize(MUSIG2_PUBNONCE_SIZE);
+ if (!secp256k1_musig_pubnonce_serialize(secp256k1_context_static, out.data(), &pubnonce)) {
+ return {};
+ }
+
+ return out;
+}
+
+
std::optional<std::vector<uint8_t>> CreateMuSig2AggregateSig(const std::vector<CPubKey>& part_pubkeys, const CPubKey& aggregate_pubkey, const std::vector<std::pair<uint256, bool>>& tweaks, const uint256& sighash, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, const std::map<CPubKey, uint256>& partial_sigs)
{
if (!part_pubkeys.size()) return std::nullopt;
diff --git a/src/musig.h b/src/musig.h
index f518ae81..e18d2450 100644
--- a/src/musig.h
+++ b/src/musig.h
@@ -10,6 +10,7 @@
#include <optional>
#include <vector>
+class CKey;
struct secp256k1_musig_keyagg_cache;
class MuSig2SecNonceImpl;
struct secp256k1_musig_secnonce;
@@ -58,6 +59,7 @@ public:
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash);
+std::vector<uint8_t> CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys);
std::optional<std::vector<uint8_t>> CreateMuSig2AggregateSig(const std::vector<CPubKey>& participants, const CPubKey& aggregate_pubkey, const std::vector<std::pair<uint256, bool>>& tweaks, const uint256& sighash, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, const std::map<CPubKey, uint256>& partial_sigs);
#endif // BITCOIN_MUSIG_H
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 6cbcf07e..4386e473 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -119,7 +119,7 @@ std::vector<uint8_t> MutableTransactionSignatureCreator::CreateMuSig2Nonce(const
if (!sighash.has_value()) return {};
MuSig2SecNonce secnonce;
- std::vector<uint8_t> out = key.CreateMuSig2Nonce(secnonce, *sighash, aggregate_pubkey, pubkeys);
+ std::vector<uint8_t> out = ::CreateMuSig2Nonce(secnonce, *sighash, key, aggregate_pubkey, pubkeys);
if (out.empty()) return {};
// Store the secnonce in the SigningProvider
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.