Bitcoin Core  31.0.0
P2P Digital Currency
bip328_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2026-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 <boost/test/unit_test.hpp>
6 
7 #include <key.h>
8 #include <key_io.h>
9 #include <musig.h>
10 #include <test/util/setup_common.h>
11 #include <util/strencodings.h>
12 #include <crypto/hex_base.h>
13 
14 #include <string>
15 #include <vector>
16 
17 namespace {
18 
19 struct BIP328TestVector {
20  std::vector<std::string> pubkeys;
21  std::string expected_aggregate_pubkey;
22  std::string expected_aggregate_xpub;
23 };
24 
26 
27 BOOST_AUTO_TEST_CASE(valid_keys)
28 {
29  // BIP 328 test vectors
30  std::vector<BIP328TestVector> test_vectors = {
31  // Test vector 0
32  {
33  .pubkeys = {
34  "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9",
35  "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9"
36  },
37  .expected_aggregate_pubkey = "0354240c76b8f2999143301a99c7f721ee57eee0bce401df3afeaa9ae218c70f23",
38  .expected_aggregate_xpub = "xpub661MyMwAqRbcFt6tk3uaczE1y6EvM1TqXvawXcYmFEWijEM4PDBnuCXwwXEKGEouzXE6QLLRxjatMcLLzJ5LV5Nib1BN7vJg6yp45yHHRbm"
39  },
40  // Test vector 1
41  {
42  .pubkeys = {
43  "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
44  "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
45  "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66"
46  },
47  .expected_aggregate_pubkey = "0290539eede565f5d054f32cc0c220126889ed1e5d193baf15aef344fe59d4610c",
48  .expected_aggregate_xpub = "xpub661MyMwAqRbcFt6tk3uaczE1y6EvM1TqXvawXcYmFEWijEM4PDBnuCXwwVk5TFJk8Tw5WAdV3DhrGfbFA216sE9BsQQiSFTdudkETnKdg8k"
49  },
50  // Test vector 2
51  {
52  .pubkeys = {
53  "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
54  "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66",
55  "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
56  "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9"
57  },
58  .expected_aggregate_pubkey = "022479f134cdb266141dab1a023cbba30a870f8995b95a91fc8464e56a7d41f8ea",
59  .expected_aggregate_xpub = "xpub661MyMwAqRbcFt6tk3uaczE1y6EvM1TqXvawXcYmFEWijEM4PDBnuCXwwUvaZYpysLX4wN59tjwU5pBuDjNrPEJbfxjLwn7ruzbXTcUTHkZ"
60  }
61  };
62 
63  // Iterate through all test vectors
64  for (int i = 0; i < (int) test_vectors.size(); ++i) {
65  const auto& test = test_vectors[i];
66 
67  // Parse public keys
68  std::vector<CPubKey> pubkeys;
69  for (const auto& hex_pubkey : test.pubkeys) {
70  std::vector<unsigned char> data = ParseHex(hex_pubkey);
71  CPubKey pubkey(data.begin(), data.end());
72  pubkeys.push_back(pubkey);
73  }
74 
75  // Aggregate public keys
76  std::optional<CPubKey> m_aggregate_pubkey = MuSig2AggregatePubkeys(pubkeys);
77  BOOST_CHECK_MESSAGE(m_aggregate_pubkey.has_value(), "Test vector " << i << ": Failed to aggregate pubkeys");
78 
79  // Check aggregate pubkey
80  std::string combined_keys = HexStr(m_aggregate_pubkey.value());
81  BOOST_CHECK_MESSAGE(combined_keys == test.expected_aggregate_pubkey, "Test vector " << i << ": Aggregate pubkey mismatch");
82 
83  // Create extended public key
84  CExtPubKey extpub = CreateMuSig2SyntheticXpub(m_aggregate_pubkey.value());
85 
86  // Check xpub
87  std::string xpub = EncodeExtPubKey(extpub);
88  BOOST_CHECK_MESSAGE(xpub == test.expected_aggregate_xpub, "Test vector " << i << ": Synthetic xpub mismatch");
89  }
90 }
91 
92 BOOST_AUTO_TEST_CASE(invalid_key)
93 {
94  std::vector<std::string> test_vectors = {
95  "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
96  "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
97  };
98 
99  // Parse public keys
100  std::vector<CPubKey> pubkeys;
101  for (const auto& hex_pubkey : test_vectors) {
102  std::vector<unsigned char> data = ParseHex(hex_pubkey);
103  CPubKey pubkey(data.begin(), data.end());
104  pubkeys.push_back(pubkey);
105  }
106 
107  // Aggregate public keys
108  std::optional<CPubKey> m_aggregate_pubkey = MuSig2AggregatePubkeys(pubkeys);
109  BOOST_CHECK_MESSAGE(!m_aggregate_pubkey.has_value(), "Aggregate key with an invalid public key is null");
110 }
111 
113 
114 }
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Definition: strencodings.h:69
Basic testing setup.
Definition: setup_common.h:64
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
An encapsulated public key.
Definition: pubkey.h:33
CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey &pubkey)
Construct the BIP 328 synthetic xpub for a pubkey.
Definition: musig.cpp:71
std::optional< CPubKey > MuSig2AggregatePubkeys(const std::vector< CPubKey > &pubkeys, secp256k1_musig_keyagg_cache &keyagg_cache, const std::optional< CPubKey > &expected_aggregate)
Compute the full aggregate pubkey from the given participant pubkeys in their current order...
Definition: musig.cpp:54
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
BOOST_AUTO_TEST_CASE(ipc_tests)
Definition: ipc_tests.cpp:13
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:30