diff --git a/src/Makefile.test.include b/src/Makefile.test.include index dd6dda7178c3..72bdc387f87d 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -306,6 +306,7 @@ test_fuzz_fuzz_SOURCES = \ test/fuzz/decode_tx.cpp \ test/fuzz/descriptor_parse.cpp \ test/fuzz/deserialize.cpp \ + test/fuzz/roundtrip_dash.cpp \ test/fuzz/eval_script.cpp \ test/fuzz/fee_rate.cpp \ test/fuzz/fees.cpp \ diff --git a/src/llmq/snapshot.h b/src/llmq/snapshot.h index d85758dd84df..18e8e1755536 100644 --- a/src/llmq/snapshot.h +++ b/src/llmq/snapshot.h @@ -76,6 +76,7 @@ class CQuorumSnapshot size_t cnt = ReadCompactSize(s); ReadFixedBitSet(s, activeQuorumMembers, cnt); + mnSkipList.clear(); cnt = ReadCompactSize(s); for ([[maybe_unused]] const auto _ : irange::range(cnt)) { int obj; diff --git a/src/test/fuzz/roundtrip_dash.cpp b/src/test/fuzz/roundtrip_dash.cpp new file mode 100644 index 000000000000..8c2c35da8b3e --- /dev/null +++ b/src/test/fuzz/roundtrip_dash.cpp @@ -0,0 +1,183 @@ +// Copyright (c) 2026 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// Roundtrip (deserialize -> serialize -> deserialize -> serialize) fuzz targets +// for Dash-specific types. + +#include +#include + +#include +#include + +// evo/ types +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// llmq/ types +#include +#include +#include +#include +#include +#include + +// governance/ types +#include + +// bls/ types +#include + +// coinjoin/ types +#include + +#include +#include +#include + +namespace { + +const BasicTestingSetup* g_setup; + +struct dash_invalid_fuzzing_input_exception : public std::exception { +}; + +template +void DashRoundtripFromFuzzingInput(FuzzBufferType buffer, T& obj) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int version; + ds >> version; + ds.SetVersion(version); + } catch (const std::ios_base::failure&) { + throw dash_invalid_fuzzing_input_exception(); + } + + try { + ds >> obj; + } catch (const std::ios_base::failure&) { + throw dash_invalid_fuzzing_input_exception(); + } + + CDataStream ds2(SER_NETWORK, ds.GetVersion()); + ds2 << obj; + + T obj2 = obj; + CDataStream ds3(Span{ds2}, SER_NETWORK, ds.GetVersion()); + try { + ds3 >> obj2; + } catch (const std::ios_base::failure&) { + assert(false); + } + + CDataStream ds4(SER_NETWORK, ds.GetVersion()); + ds4 << obj2; + + assert(MakeByteSpan(ds2) == MakeByteSpan(ds4)); +} + +template +void DashRoundtripFromFuzzingInput(FuzzBufferType buffer) +{ + T obj; + DashRoundtripFromFuzzingInput(buffer, obj); +} + +} // namespace + +void initialize_roundtrip_dash() +{ + static const auto testing_setup = MakeNoLogFileContext<>(); + g_setup = testing_setup.get(); +} + +#define FUZZ_TARGET_DASH_ROUNDTRIP(name, code) \ + FUZZ_TARGET(name, .init = initialize_roundtrip_dash) \ + { \ + try { \ + code \ + } catch (const dash_invalid_fuzzing_input_exception&) { \ + } \ + } + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_proreg_tx_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_proupserv_tx_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_proupreg_tx_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_prouprev_tx_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_asset_lock_payload_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_asset_unlock_payload_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_cbtx_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_credit_pool_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_deterministic_mn_roundtrip, { + CDeterministicMN obj(0 /* internalId, overwritten by deserialization */); + DashRoundtripFromFuzzingInput(buffer, obj); +}) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_dmn_state_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_dmn_state_diff_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_smn_list_entry_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_get_smn_list_diff_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_smn_list_diff_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_mnauth_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_mnhf_tx_payload_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_final_commitment_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_final_commitment_tx_payload_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_dkg_complaint_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_dkg_justification_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_dkg_premature_commitment_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_recovered_sig_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_sig_share_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_sig_ses_ann_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_sig_shares_inv_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_batched_sig_shares_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_quorum_data_request_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_get_quorum_rotation_info_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_quorum_snapshot_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_governance_object_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_bls_ies_encrypted_blob_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_bls_ies_multi_recipient_blobs_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) + +FUZZ_TARGET_DASH_ROUNDTRIP(dash_coinjoin_status_update_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_coinjoin_accept_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_coinjoin_entry_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_coinjoin_queue_roundtrip, { DashRoundtripFromFuzzingInput(buffer); }) +FUZZ_TARGET_DASH_ROUNDTRIP(dash_coinjoin_broadcast_tx_roundtrip, + { DashRoundtripFromFuzzingInput(buffer); }) diff --git a/test/util/data/non-backported.txt b/test/util/data/non-backported.txt index 79ba20f5ec2d..9d87e5449425 100644 --- a/test/util/data/non-backported.txt +++ b/test/util/data/non-backported.txt @@ -50,6 +50,7 @@ src/stacktraces.* src/stats/*.cpp src/stats/*.h src/test/block_reward_reallocation_tests.cpp +src/test/fuzz/roundtrip_dash.cpp src/test/bls_tests.cpp src/test/coinjoin_*.cpp src/test/dip0020opcodes_tests.cpp