musig.cpp
1 // Copyright (c) 2024-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <musig.h> 6 #include <support/allocators/secure.h> 7 8 #include <secp256k1_musig.h> 9 10 //! MuSig2 chaincode as defined by BIP 328 11 using namespace util::hex_literals; 12 constexpr uint256 MUSIG_CHAINCODE{ 13 // Use immediate lambda to work around GCC-14 bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117966 14 []() consteval { return uint256{"868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965"_hex_u8}; }(), 15 }; 16 17 static bool GetMuSig2KeyAggCache(const std::vector<CPubKey>& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache) 18 { 19 // Parse the pubkeys 20 std::vector<secp256k1_pubkey> secp_pubkeys; 21 std::vector<const secp256k1_pubkey*> pubkey_ptrs; 22 for (const CPubKey& pubkey : pubkeys) { 23 if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &secp_pubkeys.emplace_back(), pubkey.data(), pubkey.size())) { 24 return false; 25 } 26 } 27 pubkey_ptrs.reserve(secp_pubkeys.size()); 28 for (const secp256k1_pubkey& p : secp_pubkeys) { 29 pubkey_ptrs.push_back(&p); 30 } 31 32 // Aggregate the pubkey 33 if (!secp256k1_musig_pubkey_agg(secp256k1_context_static, nullptr, &keyagg_cache, pubkey_ptrs.data(), pubkey_ptrs.size())) { 34 return false; 35 } 36 return true; 37 } 38 39 static std::optional<CPubKey> GetCPubKeyFromMuSig2KeyAggCache(secp256k1_musig_keyagg_cache& keyagg_cache) 40 { 41 // Get the plain aggregated pubkey 42 secp256k1_pubkey agg_pubkey; 43 if (!secp256k1_musig_pubkey_get(secp256k1_context_static, &agg_pubkey, &keyagg_cache)) { 44 return std::nullopt; 45 } 46 47 // Turn into CPubKey 48 unsigned char ser_agg_pubkey[CPubKey::COMPRESSED_SIZE]; 49 size_t ser_agg_pubkey_len = CPubKey::COMPRESSED_SIZE; 50 secp256k1_ec_pubkey_serialize(secp256k1_context_static, ser_agg_pubkey, &ser_agg_pubkey_len, &agg_pubkey, SECP256K1_EC_COMPRESSED); 51 return CPubKey(ser_agg_pubkey, ser_agg_pubkey + ser_agg_pubkey_len); 52 } 53 54 std::optional<CPubKey> MuSig2AggregatePubkeys(const std::vector<CPubKey>& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache, const std::optional<CPubKey>& expected_aggregate) 55 { 56 if (!GetMuSig2KeyAggCache(pubkeys, keyagg_cache)) { 57 return std::nullopt; 58 } 59 std::optional<CPubKey> agg_key = GetCPubKeyFromMuSig2KeyAggCache(keyagg_cache); 60 if (!agg_key.has_value()) return std::nullopt; 61 if (expected_aggregate.has_value() && expected_aggregate != agg_key) return std::nullopt; 62 return agg_key; 63 } 64 65 std::optional<CPubKey> MuSig2AggregatePubkeys(const std::vector<CPubKey>& pubkeys) 66 { 67 secp256k1_musig_keyagg_cache keyagg_cache; 68 return MuSig2AggregatePubkeys(pubkeys, keyagg_cache, std::nullopt); 69 } 70 71 CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey) 72 { 73 CExtPubKey extpub; 74 extpub.nDepth = 0; 75 std::memset(extpub.vchFingerprint, 0, 4); 76 extpub.nChild = 0; 77 extpub.chaincode = MUSIG_CHAINCODE; 78 extpub.pubkey = pubkey; 79 return extpub; 80 } 81 82 class MuSig2SecNonceImpl 83 { 84 private: 85 //! The actual secnonce itself 86 secure_unique_ptr<secp256k1_musig_secnonce> m_nonce; 87 88 public: 89 MuSig2SecNonceImpl() : m_nonce{make_secure_unique<secp256k1_musig_secnonce>()} {} 90 91 // Delete copy constructors 92 MuSig2SecNonceImpl(const MuSig2SecNonceImpl&) = delete; 93 MuSig2SecNonceImpl& operator=(const MuSig2SecNonceImpl&) = delete; 94 95 secp256k1_musig_secnonce* Get() const { return m_nonce.get(); } 96 void Invalidate() { m_nonce.reset(); } 97 bool IsValid() { return m_nonce != nullptr; } 98 }; 99 100 MuSig2SecNonce::MuSig2SecNonce() : m_impl{std::make_unique<MuSig2SecNonceImpl>()} {} 101 102 MuSig2SecNonce::MuSig2SecNonce(MuSig2SecNonce&&) noexcept = default; 103 MuSig2SecNonce& MuSig2SecNonce::operator=(MuSig2SecNonce&&) noexcept = default; 104 105 MuSig2SecNonce::~MuSig2SecNonce() = default; 106 107 secp256k1_musig_secnonce* MuSig2SecNonce::Get() const 108 { 109 return m_impl->Get(); 110 } 111 112 void MuSig2SecNonce::Invalidate() 113 { 114 return m_impl->Invalidate(); 115 } 116 117 bool MuSig2SecNonce::IsValid() 118 { 119 return m_impl->IsValid(); 120 } 121 122 uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash) 123 { 124 HashWriter hasher; 125 hasher << script_pubkey << part_pubkey << sighash; 126 return hasher.GetSHA256(); 127 } 128 129 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) 130 { 131 if (!part_pubkeys.size()) return std::nullopt; 132 133 // Get the keyagg cache and aggregate pubkey 134 secp256k1_musig_keyagg_cache keyagg_cache; 135 if (!MuSig2AggregatePubkeys(part_pubkeys, keyagg_cache, aggregate_pubkey)) return std::nullopt; 136 137 // Check if enough pubnonces and partial sigs 138 if (pubnonces.size() != part_pubkeys.size()) return std::nullopt; 139 if (partial_sigs.size() != part_pubkeys.size()) return std::nullopt; 140 141 // Parse the pubnonces and partial sigs 142 std::vector<std::tuple<secp256k1_pubkey, secp256k1_musig_pubnonce, secp256k1_musig_partial_sig>> signers_data; 143 std::vector<const secp256k1_musig_pubnonce*> pubnonce_ptrs; 144 std::vector<const secp256k1_musig_partial_sig*> partial_sig_ptrs; 145 for (const CPubKey& part_pk : part_pubkeys) { 146 const auto& pn_it = pubnonces.find(part_pk); 147 if (pn_it == pubnonces.end()) return std::nullopt; 148 const std::vector<uint8_t> pubnonce = pn_it->second; 149 if (pubnonce.size() != MUSIG2_PUBNONCE_SIZE) return std::nullopt; 150 const auto& it = partial_sigs.find(part_pk); 151 if (it == partial_sigs.end()) return std::nullopt; 152 const uint256& partial_sig = it->second; 153 154 auto& [secp_pk, secp_pn, secp_ps] = signers_data.emplace_back(); 155 156 if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &secp_pk, part_pk.data(), part_pk.size())) { 157 return std::nullopt; 158 } 159 160 if (!secp256k1_musig_pubnonce_parse(secp256k1_context_static, &secp_pn, pubnonce.data())) { 161 return std::nullopt; 162 } 163 164 if (!secp256k1_musig_partial_sig_parse(secp256k1_context_static, &secp_ps, partial_sig.data())) { 165 return std::nullopt; 166 } 167 } 168 pubnonce_ptrs.reserve(signers_data.size()); 169 partial_sig_ptrs.reserve(signers_data.size()); 170 for (auto& [_, pn, ps] : signers_data) { 171 pubnonce_ptrs.push_back(&pn); 172 partial_sig_ptrs.push_back(&ps); 173 } 174 175 // Aggregate nonces 176 secp256k1_musig_aggnonce aggnonce; 177 if (!secp256k1_musig_nonce_agg(secp256k1_context_static, &aggnonce, pubnonce_ptrs.data(), pubnonce_ptrs.size())) { 178 return std::nullopt; 179 } 180 181 // Apply tweaks 182 for (const auto& [tweak, xonly] : tweaks) { 183 if (xonly) { 184 if (!secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_context_static, nullptr, &keyagg_cache, tweak.data())) { 185 return std::nullopt; 186 } 187 } else if (!secp256k1_musig_pubkey_ec_tweak_add(secp256k1_context_static, nullptr, &keyagg_cache, tweak.data())) { 188 return std::nullopt; 189 } 190 } 191 192 // Create musig_session 193 secp256k1_musig_session session; 194 if (!secp256k1_musig_nonce_process(secp256k1_context_static, &session, &aggnonce, sighash.data(), &keyagg_cache)) { 195 return std::nullopt; 196 } 197 198 // Verify partial sigs 199 for (const auto& [pk, pb, ps] : signers_data) { 200 if (!secp256k1_musig_partial_sig_verify(secp256k1_context_static, &ps, &pb, &pk, &keyagg_cache, &session)) { 201 return std::nullopt; 202 } 203 } 204 205 // Aggregate partial sigs 206 std::vector<uint8_t> sig; 207 sig.resize(64); 208 if (!secp256k1_musig_partial_sig_agg(secp256k1_context_static, sig.data(), &session, partial_sig_ptrs.data(), partial_sig_ptrs.size())) { 209 return std::nullopt; 210 } 211 212 return sig; 213 }