diff --git a/src/key.cpp b/src/key.cpp index 01fa3d270e3..023983326c0 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -349,6 +350,39 @@ 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; +} + CKey GenerateRandomKey(bool compressed) noexcept { CKey key; diff --git a/src/key.h b/src/key.h index 22f96880b7b..97ed27ccfc0 100644 --- a/src/key.h +++ b/src/key.h @@ -7,6 +7,7 @@ #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H +#include #include #include #include @@ -220,6 +221,8 @@ public: * Merkle root of the script tree). */ KeyPair ComputeKeyPair(const uint256* merkle_root) const; + + std::vector CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector& pubkeys); }; CKey GenerateRandomKey(bool compressed = true) noexcept; diff --git a/src/musig.cpp b/src/musig.cpp index 7ebb8e55258..5cf638d50b7 100644 --- a/src/musig.cpp +++ b/src/musig.cpp @@ -111,3 +111,10 @@ bool MuSig2SecNonce::IsValid() { return m_impl->IsValid(); } + +uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash) +{ + HashWriter hasher; + hasher << script_pubkey << part_pubkey << sighash; + return hasher.GetSHA256(); +} diff --git a/src/musig.h b/src/musig.h index bb469df4a9a..03324fc454a 100644 --- a/src/musig.h +++ b/src/musig.h @@ -18,6 +18,8 @@ struct secp256k1_musig_secnonce; using namespace util::hex_literals; constexpr uint256 MUSIG_CHAINCODE{"868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965"_hex_u8}; +constexpr size_t MUSIG2_PUBNONCE_SIZE{66}; + //! Compute the full aggregate pubkey from the given participant pubkeys in their current order. //! Outputs the secp256k1_musig_keyagg_cache and validates that the computed aggregate pubkey matches an expected aggregate pubkey. //! This is necessary for most MuSig2 operations. @@ -58,4 +60,6 @@ public: bool IsValid(); }; +uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash); + #endif // BITCOIN_MUSIG_H diff --git a/src/psbt.h b/src/psbt.h index f8098b04503..f0de079f7b4 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -794,7 +794,7 @@ struct PSBTInput std::vector pubnonce; s >> pubnonce; - if (pubnonce.size() != 66) { + if (pubnonce.size() != MUSIG2_PUBNONCE_SIZE) { throw std::ios_base::failure("Input musig2 pubnonce value is not 66 bytes"); } diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 8575c0b90da..5ca3f98814e 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include #include