From d00d95437dd113a23ccd556c25a77bb04bce23f7 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 22 Jan 2024 15:18:28 -0500 Subject: [PATCH] Add MuSig2 Keyagg Cache helper functions secp256k1 provides us secp256k1_musig_keyagg_cache objects which we are used as part of session info and to get the aggregate pubkey. These helper functions help us convert to/from the secp256k1 C objects into the Bitcoin Core C++ objects. --- src/CMakeLists.txt | 1 + src/musig.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++ src/musig.h | 22 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 src/musig.cpp create mode 100644 src/musig.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1099ed39218..1dbabb57d67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -161,6 +161,7 @@ add_library(bitcoin_common STATIC EXCLUDE_FROM_ALL key.cpp key_io.cpp merkleblock.cpp + musig.cpp net_permissions.cpp net_types.cpp netaddress.cpp diff --git a/src/musig.cpp b/src/musig.cpp new file mode 100644 index 00000000000..b3329543127 --- /dev/null +++ b/src/musig.cpp @@ -0,0 +1,53 @@ +// 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); +} diff --git a/src/musig.h b/src/musig.h new file mode 100644 index 00000000000..91aab1d3364 --- /dev/null +++ b/src/musig.h @@ -0,0 +1,22 @@ +// Copyright (c) 2024-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_MUSIG_H +#define BITCOIN_MUSIG_H + +#include + +#include +#include + +struct secp256k1_musig_keyagg_cache; + +//! Create a secp256k1_musig_keyagg_cache from the pubkeys in their current order. This is necessary for most MuSig2 operations +bool GetMuSig2KeyAggCache(const std::vector& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache); +//! Retrieve the full aggregate pubkey from the secp256k1_musig_keyagg_cache +std::optional GetCPubKeyFromMuSig2KeyAggCache(secp256k1_musig_keyagg_cache& cache); +//! Compute the full aggregate pubkey from the given participant pubkeys in their current order +std::optional MuSig2AggregatePubkeys(const std::vector& pubkeys); + +#endif // BITCOIN_MUSIG_H