mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-09-14 20:09:19 +02:00
fuzz: add a Miniscript target for string representation roundtripping
Co-authored-by: Pieter Wuille <pieter.wuille@gmail.com>
This commit is contained in:
@@ -14,6 +14,74 @@
|
||||
|
||||
namespace {
|
||||
|
||||
//! Some pre-computed data for more efficient string roundtrips.
|
||||
struct TestData {
|
||||
typedef CPubKey Key;
|
||||
|
||||
// Precomputed public keys.
|
||||
std::vector<Key> dummy_keys;
|
||||
std::map<Key, int> dummy_key_idx_map;
|
||||
std::map<CKeyID, Key> dummy_keys_map;
|
||||
|
||||
//! Set the precomputed data.
|
||||
void Init() {
|
||||
unsigned char keydata[32] = {1};
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
keydata[31] = i;
|
||||
CKey privkey;
|
||||
privkey.Set(keydata, keydata + 32, true);
|
||||
const Key pubkey = privkey.GetPubKey();
|
||||
|
||||
dummy_keys.push_back(pubkey);
|
||||
dummy_key_idx_map.emplace(pubkey, i);
|
||||
dummy_keys_map.insert({pubkey.GetID(), pubkey});
|
||||
}
|
||||
}
|
||||
} TEST_DATA;
|
||||
|
||||
/**
|
||||
* Context to parse a Miniscript node to and from Script or text representation.
|
||||
* Uses an integer (an index in the dummy keys array from the test data) as keys in order
|
||||
* to focus on fuzzing the Miniscript nodes' test representation, not the key representation.
|
||||
*/
|
||||
struct ParserContext {
|
||||
typedef CPubKey Key;
|
||||
|
||||
std::optional<std::string> ToString(const Key& key) const
|
||||
{
|
||||
auto it = TEST_DATA.dummy_key_idx_map.find(key);
|
||||
if (it == TEST_DATA.dummy_key_idx_map.end()) return {};
|
||||
uint8_t idx = it->second;
|
||||
return HexStr(Span{&idx, 1});
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
std::optional<Key> FromString(I first, I last) const {
|
||||
if (last - first != 2) return {};
|
||||
auto idx = ParseHex(std::string(first, last));
|
||||
if (idx.size() != 1) return {};
|
||||
return TEST_DATA.dummy_keys[idx[0]];
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
std::optional<Key> FromPKBytes(I first, I last) const {
|
||||
Key key;
|
||||
key.Set(first, last);
|
||||
if (!key.IsValid()) return {};
|
||||
return key;
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
std::optional<Key> FromPKHBytes(I first, I last) const {
|
||||
assert(last - first == 20);
|
||||
CKeyID keyid;
|
||||
std::copy(first, last, keyid.begin());
|
||||
const auto it = TEST_DATA.dummy_keys_map.find(keyid);
|
||||
if (it == TEST_DATA.dummy_keys_map.end()) return {};
|
||||
return it->second;
|
||||
}
|
||||
} PARSER_CTX;
|
||||
|
||||
//! Context that implements naive conversion from/to script only, for roundtrip testing.
|
||||
struct ScriptParserContext {
|
||||
//! For Script roundtrip we never need the key from a key hash.
|
||||
@@ -54,6 +122,27 @@ struct ScriptParserContext {
|
||||
}
|
||||
} SCRIPT_PARSER_CONTEXT;
|
||||
|
||||
} // namespace
|
||||
|
||||
void FuzzInit()
|
||||
{
|
||||
ECC_Start();
|
||||
TEST_DATA.Init();
|
||||
}
|
||||
|
||||
/* Fuzz tests that test parsing from a string, and roundtripping via string. */
|
||||
FUZZ_TARGET_INIT(miniscript_string, FuzzInit)
|
||||
{
|
||||
FuzzedDataProvider provider(buffer.data(), buffer.size());
|
||||
auto str = provider.ConsumeRemainingBytesAsString();
|
||||
auto parsed = miniscript::FromString(str, PARSER_CTX);
|
||||
if (!parsed) return;
|
||||
|
||||
const auto str2 = parsed->ToString(PARSER_CTX);
|
||||
assert(str2);
|
||||
auto parsed2 = miniscript::FromString(*str2, PARSER_CTX);
|
||||
assert(parsed2);
|
||||
assert(*parsed == *parsed2);
|
||||
}
|
||||
|
||||
/* Fuzz tests that test parsing from a script, and roundtripping via script. */
|
||||
|
Reference in New Issue
Block a user