descriptor.cpp
1 // Copyright (c) 2023-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 <test/fuzz/util/descriptor.h> 6 7 void MockedDescriptorConverter::Init() { 8 // The data to use as a private key or a seed for an xprv. 9 std::array<std::byte, 32> key_data{std::byte{1}}; 10 // Generate keys of all kinds and store them in the keys array. 11 for (size_t i{0}; i < TOTAL_KEYS_GENERATED; i++) { 12 key_data[31] = std::byte(i); 13 14 // If this is a "raw" key, generate a normal privkey. Otherwise generate 15 // an extended one. 16 if (IdIsCompPubKey(i) || IdIsUnCompPubKey(i) || IdIsXOnlyPubKey(i) || IdIsConstPrivKey(i)) { 17 CKey privkey; 18 privkey.Set(UCharCast(key_data.begin()), UCharCast(key_data.end()), !IdIsUnCompPubKey(i)); 19 if (IdIsCompPubKey(i) || IdIsUnCompPubKey(i)) { 20 CPubKey pubkey{privkey.GetPubKey()}; 21 keys_str[i] = HexStr(pubkey); 22 } else if (IdIsXOnlyPubKey(i)) { 23 const XOnlyPubKey pubkey{privkey.GetPubKey()}; 24 keys_str[i] = HexStr(pubkey); 25 } else { 26 keys_str[i] = EncodeSecret(privkey); 27 } 28 } else { 29 CExtKey ext_privkey; 30 ext_privkey.SetSeed(key_data); 31 if (IdIsXprv(i)) { 32 keys_str[i] = EncodeExtKey(ext_privkey); 33 } else { 34 const CExtPubKey ext_pubkey{ext_privkey.Neuter()}; 35 keys_str[i] = EncodeExtPubKey(ext_pubkey); 36 } 37 } 38 } 39 } 40 41 std::optional<uint8_t> MockedDescriptorConverter::IdxFromHex(std::string_view hex_characters) const { 42 if (hex_characters.size() != 2) return {}; 43 auto idx = ParseHex(hex_characters); 44 if (idx.size() != 1) return {}; 45 return idx[0]; 46 } 47 48 std::optional<std::string> MockedDescriptorConverter::GetDescriptor(std::string_view mocked_desc) const { 49 // The smallest fragment would be "pk(%00)" 50 if (mocked_desc.size() < 7) return {}; 51 52 // The actual descriptor string to be returned. 53 std::string desc; 54 desc.reserve(mocked_desc.size()); 55 56 // Replace all occurrences of '%' followed by two hex characters with the corresponding key. 57 for (size_t i = 0; i < mocked_desc.size();) { 58 if (mocked_desc[i] == '%') { 59 if (i + 3 >= mocked_desc.size()) return {}; 60 if (const auto idx = IdxFromHex(mocked_desc.substr(i + 1, 2))) { 61 desc += keys_str[*idx]; 62 i += 3; 63 } else { 64 return {}; 65 } 66 } else { 67 desc += mocked_desc[i++]; 68 } 69 } 70 71 return desc; 72 } 73 74 bool HasDeepDerivPath(const FuzzBufferType& buff, const int max_depth) 75 { 76 auto depth{0}; 77 for (const auto& ch: buff) { 78 if (ch == ',') { 79 // A comma is always present between two key expressions, so we use that as a delimiter. 80 depth = 0; 81 } else if (ch == '/') { 82 if (++depth > max_depth) return true; 83 } 84 } 85 return false; 86 }