From d087f266fc24145e3a34a9f2e8f08c583f806aad Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Wed, 7 Jan 2026 22:12:08 +0100 Subject: [PATCH] refactor, key: move `CreateMuSig2Nonce` to `musig.{h,cpp}` module Nonce creation is mainly derived by randomness, and the secret key merely serves as (optional) additional data for increasing misuse-resistance, rather than being a central part that would justify an own CKey method, so move it to the musig.cpp module. Can be reviewed via the git option `--color-moved=dimmed-zebra`. --- src/key.cpp | 33 --------------------------------- src/key.h | 1 - src/musig.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/musig.h | 2 ++ src/script/sign.cpp | 2 +- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 60f6eb67c1e..c61616f1207 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 CKey::CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector& 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 out; - out.resize(MUSIG2_PUBNONCE_SIZE); - if (!secp256k1_musig_pubnonce_serialize(secp256k1_context_static, out.data(), &pubnonce)) { - return {}; - } - - return out; -} - std::optional CKey::CreateMuSig2PartialSig(const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector& pubkeys, const std::map>& pubnonces, MuSig2SecNonce& secnonce, const std::vector>& tweaks) { secp256k1_keypair keypair; diff --git a/src/key.h b/src/key.h index e2c9d82fa5f..e9f34a1ad49 100644 --- a/src/key.h +++ b/src/key.h @@ -224,7 +224,6 @@ public: */ KeyPair ComputeKeyPair(const uint256* merkle_root) const; - std::vector CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector& pubkeys); std::optional CreateMuSig2PartialSig(const uint256& hash, const CPubKey& aggregate_pubkey, const std::vector& pubkeys, const std::map>& pubnonces, MuSig2SecNonce& secnonce, const std::vector>& tweaks); }; diff --git a/src/musig.cpp b/src/musig.cpp index 706874be2cf..73089ea89a8 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 +#include +#include #include #include @@ -126,6 +128,40 @@ uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey return hasher.GetSHA256(); } +std::vector CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector& 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 out; + out.resize(MUSIG2_PUBNONCE_SIZE); + if (!secp256k1_musig_pubnonce_serialize(secp256k1_context_static, out.data(), &pubnonce)) { + return {}; + } + + return out; +} + + std::optional> CreateMuSig2AggregateSig(const std::vector& part_pubkeys, const CPubKey& aggregate_pubkey, const std::vector>& tweaks, const uint256& sighash, const std::map>& pubnonces, const std::map& partial_sigs) { if (!part_pubkeys.size()) return std::nullopt; diff --git a/src/musig.h b/src/musig.h index f518ae81ba2..e18d245015c 100644 --- a/src/musig.h +++ b/src/musig.h @@ -10,6 +10,7 @@ #include #include +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 CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector& pubkeys); 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); #endif // BITCOIN_MUSIG_H diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 6cbcf07e5e2..4386e473b3f 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -119,7 +119,7 @@ std::vector MutableTransactionSignatureCreator::CreateMuSig2Nonce(const if (!sighash.has_value()) return {}; MuSig2SecNonce secnonce; - std::vector out = key.CreateMuSig2Nonce(secnonce, *sighash, aggregate_pubkey, pubkeys); + std::vector out = ::CreateMuSig2Nonce(secnonce, *sighash, key, aggregate_pubkey, pubkeys); if (out.empty()) return {}; // Store the secnonce in the SigningProvider