From b3c397a435b892543cad8a7ba4c84a4f71488521 Mon Sep 17 00:00:00 2001 From: frstrtr Date: Sat, 4 Jul 2026 00:24:08 +0000 Subject: [PATCH] =?UTF-8?q?test(dash):=20G1=20difficulty/vardiff=20parity?= =?UTF-8?q?=20KAT=20=E2=80=94=20share-diff=20floor=20+=20per-share=20min?= =?UTF-8?q?=5Fwork=20oracle=20pin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pins dash::SharechainConfig::max_target() byte-exactness (mainnet 0xFFFF*2**208, testnet 2**256//2**20-1) and chain::target_to_average_attempts(floor) per-share min_work (mainnet 4295032833, testnet 1048576) to oracle-independent values derived from frstrtr/p2pool-dash bitcoin/data.py, plus the min_work accumulation identity and floor bits roundtrip. Pure/socket-free; 6/6 on Linux x86_64 ctest. Consensus-neutral (read-only difficulty accounting), independently-landable. --- .github/workflows/build.yml | 4 +- test/CMakeLists.txt | 14 ++++ test/test_dash_difficulty_parity.cpp | 110 +++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 test/test_dash_difficulty_parity.cpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63b0a02b..421bd140 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,7 +102,7 @@ jobs: core_test sharechain_test share_test btc_share_test \ test_threading test_weights \ test_header_chain test_mempool test_template_builder \ - test_doge_chain test_compact_blocks test_dash_x11_kat test_dash_header_chain test_dash_block_replay test_dash_conformance test_dash_subsidy test_dash_mempool test_dash_simplifiedmns test_dash_quorum test_dash_quorum_root test_dash_mn_state test_dash_embedded_gbt test_dash_smldiff test_dash_p2p_messages test_dash_p2p_connection test_dash_p2p_node test_dash_node_interface test_dash_config test_dash_broadcaster test_dash_broadcaster_full test_dash_share_hash_link test_dash_block_relay test_dash_rpc_request test_dash_rpc_conf test_dash_block_producer test_dash_embedded_relay_e2e test_dash_block_relay_plan test_dash_version_activation_latch test_dash_block_relay_binding test_dash_block_relay_dual_arm test_dash_coinbase_parity test_dash_donation_combined test_dash_g3_assembled test_dash_work_target test_dash_work_job_targets test_dash_stratum_binding test_dash_job_notify_roundtrip test_dash_cb_payee test_dash_stratum_notify_roundtrip test_dash_poolnode_messages test_dash_peer test_dash_share_tracker test_dash_node test_dash_share_messages test_dash_stratum_extranonce_split test_dash_stratum_submit_reassembly \ + test_doge_chain test_compact_blocks test_dash_x11_kat test_dash_header_chain test_dash_block_replay test_dash_conformance test_dash_subsidy test_dash_mempool test_dash_simplifiedmns test_dash_quorum test_dash_quorum_root test_dash_mn_state test_dash_embedded_gbt test_dash_smldiff test_dash_p2p_messages test_dash_p2p_connection test_dash_p2p_node test_dash_node_interface test_dash_config test_dash_broadcaster test_dash_broadcaster_full test_dash_share_hash_link test_dash_block_relay test_dash_rpc_request test_dash_rpc_conf test_dash_block_producer test_dash_embedded_relay_e2e test_dash_block_relay_plan test_dash_version_activation_latch test_dash_block_relay_binding test_dash_block_relay_dual_arm test_dash_coinbase_parity test_dash_donation_combined test_dash_g3_assembled test_dash_work_target test_dash_work_job_targets test_dash_stratum_binding test_dash_job_notify_roundtrip test_dash_cb_payee test_dash_stratum_notify_roundtrip test_dash_poolnode_messages test_dash_peer test_dash_share_tracker test_dash_node test_dash_share_messages test_dash_stratum_extranonce_split test_dash_stratum_submit_reassembly test_dash_difficulty_parity \ test_multiaddress_pplns test_pplns_stress \ test_hash_link test_decay_pplns \ test_pplns_consensus \ @@ -252,7 +252,7 @@ jobs: test_threading test_weights \ test_header_chain test_mempool test_template_builder \ test_doge_chain test_compact_blocks test_dash_x11_kat \ - test_dash_header_chain test_dash_block_replay test_dash_conformance test_dash_subsidy test_dash_mempool test_dash_simplifiedmns test_dash_quorum test_dash_quorum_root test_dash_mn_state test_dash_embedded_gbt test_dash_smldiff test_dash_p2p_messages test_dash_p2p_connection test_dash_p2p_node test_dash_node_interface test_dash_config test_dash_broadcaster test_dash_broadcaster_full test_dash_share_hash_link test_dash_block_relay test_dash_rpc_request test_dash_rpc_conf test_dash_block_producer test_dash_embedded_relay_e2e test_dash_block_relay_plan test_dash_version_activation_latch test_dash_block_relay_binding test_dash_block_relay_dual_arm test_dash_coinbase_parity test_dash_donation_combined test_dash_g3_assembled test_dash_work_target test_dash_work_job_targets test_dash_stratum_binding test_dash_job_notify_roundtrip test_dash_cb_payee test_dash_stratum_notify_roundtrip test_dash_poolnode_messages test_dash_peer test_dash_share_tracker test_dash_node test_dash_share_messages test_dash_stratum_extranonce_split test_dash_stratum_submit_reassembly \ + test_dash_header_chain test_dash_block_replay test_dash_conformance test_dash_subsidy test_dash_mempool test_dash_simplifiedmns test_dash_quorum test_dash_quorum_root test_dash_mn_state test_dash_embedded_gbt test_dash_smldiff test_dash_p2p_messages test_dash_p2p_connection test_dash_p2p_node test_dash_node_interface test_dash_config test_dash_broadcaster test_dash_broadcaster_full test_dash_share_hash_link test_dash_block_relay test_dash_rpc_request test_dash_rpc_conf test_dash_block_producer test_dash_embedded_relay_e2e test_dash_block_relay_plan test_dash_version_activation_latch test_dash_block_relay_binding test_dash_block_relay_dual_arm test_dash_coinbase_parity test_dash_donation_combined test_dash_g3_assembled test_dash_work_target test_dash_work_job_targets test_dash_stratum_binding test_dash_job_notify_roundtrip test_dash_cb_payee test_dash_stratum_notify_roundtrip test_dash_poolnode_messages test_dash_peer test_dash_share_tracker test_dash_node test_dash_share_messages test_dash_stratum_extranonce_split test_dash_stratum_submit_reassembly test_dash_difficulty_parity \ test_hash_link test_decay_pplns \ test_pplns_consensus \ test_v36_script_sorting test_v36_cross_impl_refhash \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dbca4a9d..d6d9f93d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -347,6 +347,20 @@ if (BUILD_TESTING AND GTest_FOUND) target_link_libraries(test_dash_stratum_binding PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39) gtest_add_tests(test_dash_stratum_binding "" AUTO) + # DASH G1 difficulty / vardiff PARITY KAT: share-diff floor byte-exactness + + # per-share min_work (target_to_average_attempts) oracle pin. Header-only over + # core/target_utils + config_pool; pure, socket-free. Mirrors the work_target + # link set. + add_executable(test_dash_difficulty_parity test_dash_difficulty_parity.cpp) + target_link_libraries(test_dash_difficulty_parity PRIVATE + GTest::gtest_main GTest::gtest + dash_x11 core + nlohmann_json::nlohmann_json + ${Boost_LIBRARIES} + ) + target_link_libraries(test_dash_difficulty_parity PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39) + gtest_add_tests(test_dash_difficulty_parity "" AUTO) + # share_init_verify gentx hash_link byte-parity vs oracle (coinbase_payload # VarStr prefix). Header-only over the dash_x11 + core link set; mirrors the # test_dash_conformance link set. diff --git a/test/test_dash_difficulty_parity.cpp b/test/test_dash_difficulty_parity.cpp new file mode 100644 index 00000000..10828be0 --- /dev/null +++ b/test/test_dash_difficulty_parity.cpp @@ -0,0 +1,110 @@ +// DASH G1 difficulty / vardiff PARITY KAT. +// +// Pins the DASH sharechain difficulty floor and its per-share work accounting +// to oracle-EXACT arithmetic from frstrtr/p2pool-dash (networks/dash.py + +// bitcoin/data.py). Two independent surfaces: +// +// 1. dash::SharechainConfig::max_target() — the share-diff floor (easiest allowed +// share target). Byte-exact to the oracle _DIFF1_TARGET (mainnet) and the +// 2**256//2**20-1 testnet floor. +// 2. chain::target_to_average_attempts(target) == 2**256 // (target+1) — the +// per-share MINIMUM work that ShareIndex accumulates from m_max_bits +// (share_chain.hpp:228). This is the quantity that drives cumulative-work +// / APS retarget parity across the chain. +// +// Every expected value is derived INDEPENDENTLY from the oracle integer formula +// (see the derive comment on each vector), NOT read back from the SUT — a true +// byte-parity pin, not a tautology. The cross-coin APS-over-chain accumulation +// is already pinned LTC-instantiated in test_compute_share_target.cpp; this KAT +// pins the DASH-specific config floor + the min_work-per-share derivation those +// oracle numbers differ on (p2pool-dash, not p2pool-ltc). +// +// Pure / socket-free / node-free: no VM200/201 dashd, no live sharechain. +// Runs on every Linux x86_64 ctest. + +#include + +#include +#include +#include + +namespace { +uint288 U288(const char* h) { uint288 t; t.SetHex(h); return t; } +} // namespace + +// ── 1. share-diff floor byte-exactness (networks/dash.py SHARE_MAX_TARGET) ── + +// mainnet floor == 0xFFFF * 2**208 (standard bdiff difficulty-1 target). +TEST(DashDifficultyParity, MainnetMaxTargetFloorExact) +{ + dash::SharechainConfig::is_testnet = false; + EXPECT_EQ(dash::SharechainConfig::max_target().GetHex(), + "00000000ffff0000000000000000000000000000000000000000000000000000"); +} + +// testnet floor == 2**256 // 2**20 - 1. Derive (python3): +// "%064x" % (2**256 // 2**20 - 1) +TEST(DashDifficultyParity, TestnetMaxTargetFloorExact) +{ + dash::SharechainConfig::is_testnet = true; + EXPECT_EQ(dash::SharechainConfig::max_target().GetHex(), + "00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + dash::SharechainConfig::is_testnet = false; +} + +// ── 2. per-share min_work = target_to_average_attempts(floor) ─────────────── +// +// ShareIndex(share).min_work = target_to_average_attempts(bits_to_target( +// m_max_bits)) (share_chain.hpp:228). At the difficulty floor that reduces +// to target_to_average_attempts(max_target()). + +// mainnet: attempts = 2**256 // (0xFFFF*2**208 + 1). Derive (python3): +// (2**256)//(0xFFFF*(2**208)+1) == 4295032833 == 0x100010001 +TEST(DashDifficultyParity, MainnetPerShareMinWorkExact) +{ + dash::SharechainConfig::is_testnet = false; + uint288 attempts = chain::target_to_average_attempts(dash::SharechainConfig::max_target()); + EXPECT_EQ(attempts.GetHex(), U288("100010001").GetHex()); + EXPECT_TRUE(attempts == static_cast(4295032833ULL)); +} + +// testnet: attempts = 2**256 // (2**256//2**20). Derive (python3): +// (2**256)//((2**256//2**20-1)+1) == 1048576 == 2**20 == 0x100000 +TEST(DashDifficultyParity, TestnetPerShareMinWorkExact) +{ + dash::SharechainConfig::is_testnet = true; + uint288 attempts = chain::target_to_average_attempts(dash::SharechainConfig::max_target()); + EXPECT_EQ(attempts.GetHex(), U288("100000").GetHex()); + EXPECT_TRUE(attempts == static_cast(1048576ULL)); + dash::SharechainConfig::is_testnet = false; +} + +// ── 3. ShareIndex min_work accumulation identity (dash floor) ─────────────── +// +// Over N equal-floor shares the accumulated min_work == per_share * N, the same +// identity DeltaCache maintains (test_compute_share_target DeltaCacheAfterPruning, +// LTC). Pinned here with DASH-floor numbers so a config-floor regression is +// caught in the DASH lane directly. +TEST(DashDifficultyParity, MainnetMinWorkAccumulationIdentity) +{ + dash::SharechainConfig::is_testnet = false; + uint288 per_share = chain::target_to_average_attempts(dash::SharechainConfig::max_target()); + // N=199 (default real_chain window sample). Derive (python3): + // 4295032833 * 199 == 854711533767 + uint288 acc = per_share * static_cast(199); + EXPECT_TRUE(acc == static_cast(854711533767ULL)); +} + +// ── 4. floor bits roundtrip (m_max_bits <-> floor target) ─────────────────── +// +// ShareIndex derives min_work from m_max_bits via bits_to_target; the floor +// must survive the compact encode/decode used to carry it on the wire. +TEST(DashDifficultyParity, MainnetFloorBitsRoundtrip) +{ + dash::SharechainConfig::is_testnet = false; + uint256 floor = dash::SharechainConfig::max_target(); + uint32_t bits = chain::target_to_bits_upper_bound(floor); + uint256 decoded = chain::bits_to_target(bits); + EXPECT_EQ(decoded, floor); // exact roundtrip at the standard floor + EXPECT_EQ(bits >> 24, 0x1du); // 0xFFFF*2**208 -> exponent 0x1d (29 bytes) +}