// Copyright (c) 2024-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include bool GetMuSig2KeyAggCache(const std::vector& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache) { // Parse the pubkeys std::vector secp_pubkeys; std::vector pubkey_ptrs; for (const CPubKey& pubkey : pubkeys) { if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &secp_pubkeys.emplace_back(), pubkey.data(), pubkey.size())) { return false; } } pubkey_ptrs.reserve(secp_pubkeys.size()); for (const secp256k1_pubkey& p : secp_pubkeys) { pubkey_ptrs.push_back(&p); } // Aggregate the pubkey if (!secp256k1_musig_pubkey_agg(secp256k1_context_static, nullptr, &keyagg_cache, pubkey_ptrs.data(), pubkey_ptrs.size())) { return false; } return true; } std::optional GetCPubKeyFromMuSig2KeyAggCache(secp256k1_musig_keyagg_cache& keyagg_cache) { // Get the plain aggregated pubkey secp256k1_pubkey agg_pubkey; if (!secp256k1_musig_pubkey_get(secp256k1_context_static, &agg_pubkey, &keyagg_cache)) { return std::nullopt; } // Turn into CPubKey unsigned char ser_agg_pubkey[CPubKey::COMPRESSED_SIZE]; size_t ser_agg_pubkey_len = CPubKey::COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_static, ser_agg_pubkey, &ser_agg_pubkey_len, &agg_pubkey, SECP256K1_EC_COMPRESSED); return CPubKey(ser_agg_pubkey, ser_agg_pubkey + ser_agg_pubkey_len); } std::optional MuSig2AggregatePubkeys(const std::vector& pubkeys) { secp256k1_musig_keyagg_cache keyagg_cache; if (!GetMuSig2KeyAggCache(pubkeys, keyagg_cache)) { return std::nullopt; } return GetCPubKeyFromMuSig2KeyAggCache(keyagg_cache); }