Skip to content

Commit 2fe5ef7

Browse files
authored
test(dash): G1 difficulty/vardiff parity KAT — share-diff floor + per-share min_work oracle pin (#628)
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. Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
1 parent c08c87f commit 2fe5ef7

3 files changed

Lines changed: 126 additions & 2 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ jobs:
102102
core_test sharechain_test share_test btc_share_test \
103103
test_threading test_weights \
104104
test_header_chain test_mempool test_template_builder \
105-
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 \
105+
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 \
106106
test_multiaddress_pplns test_pplns_stress \
107107
test_hash_link test_decay_pplns \
108108
test_pplns_consensus \
@@ -252,7 +252,7 @@ jobs:
252252
test_threading test_weights \
253253
test_header_chain test_mempool test_template_builder \
254254
test_doge_chain test_compact_blocks test_dash_x11_kat \
255-
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 \
255+
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 \
256256
test_hash_link test_decay_pplns \
257257
test_pplns_consensus \
258258
test_v36_script_sorting test_v36_cross_impl_refhash \

test/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,20 @@ if (BUILD_TESTING AND GTest_FOUND)
347347
target_link_libraries(test_dash_stratum_binding PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
348348
gtest_add_tests(test_dash_stratum_binding "" AUTO)
349349

350+
# DASH G1 difficulty / vardiff PARITY KAT: share-diff floor byte-exactness +
351+
# per-share min_work (target_to_average_attempts) oracle pin. Header-only over
352+
# core/target_utils + config_pool; pure, socket-free. Mirrors the work_target
353+
# link set.
354+
add_executable(test_dash_difficulty_parity test_dash_difficulty_parity.cpp)
355+
target_link_libraries(test_dash_difficulty_parity PRIVATE
356+
GTest::gtest_main GTest::gtest
357+
dash_x11 core
358+
nlohmann_json::nlohmann_json
359+
${Boost_LIBRARIES}
360+
)
361+
target_link_libraries(test_dash_difficulty_parity PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
362+
gtest_add_tests(test_dash_difficulty_parity "" AUTO)
363+
350364
# share_init_verify gentx hash_link byte-parity vs oracle (coinbase_payload
351365
# VarStr prefix). Header-only over the dash_x11 + core link set; mirrors the
352366
# test_dash_conformance link set.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// DASH G1 difficulty / vardiff PARITY KAT.
2+
//
3+
// Pins the DASH sharechain difficulty floor and its per-share work accounting
4+
// to oracle-EXACT arithmetic from frstrtr/p2pool-dash (networks/dash.py +
5+
// bitcoin/data.py). Two independent surfaces:
6+
//
7+
// 1. dash::SharechainConfig::max_target() — the share-diff floor (easiest allowed
8+
// share target). Byte-exact to the oracle _DIFF1_TARGET (mainnet) and the
9+
// 2**256//2**20-1 testnet floor.
10+
// 2. chain::target_to_average_attempts(target) == 2**256 // (target+1) — the
11+
// per-share MINIMUM work that ShareIndex accumulates from m_max_bits
12+
// (share_chain.hpp:228). This is the quantity that drives cumulative-work
13+
// / APS retarget parity across the chain.
14+
//
15+
// Every expected value is derived INDEPENDENTLY from the oracle integer formula
16+
// (see the derive comment on each vector), NOT read back from the SUT — a true
17+
// byte-parity pin, not a tautology. The cross-coin APS-over-chain accumulation
18+
// is already pinned LTC-instantiated in test_compute_share_target.cpp; this KAT
19+
// pins the DASH-specific config floor + the min_work-per-share derivation those
20+
// oracle numbers differ on (p2pool-dash, not p2pool-ltc).
21+
//
22+
// Pure / socket-free / node-free: no VM200/201 dashd, no live sharechain.
23+
// Runs on every Linux x86_64 ctest.
24+
25+
#include <gtest/gtest.h>
26+
27+
#include <core/target_utils.hpp>
28+
#include <core/uint256.hpp>
29+
#include <impl/dash/config_pool.hpp>
30+
31+
namespace {
32+
uint288 U288(const char* h) { uint288 t; t.SetHex(h); return t; }
33+
} // namespace
34+
35+
// ── 1. share-diff floor byte-exactness (networks/dash.py SHARE_MAX_TARGET) ──
36+
37+
// mainnet floor == 0xFFFF * 2**208 (standard bdiff difficulty-1 target).
38+
TEST(DashDifficultyParity, MainnetMaxTargetFloorExact)
39+
{
40+
dash::SharechainConfig::is_testnet = false;
41+
EXPECT_EQ(dash::SharechainConfig::max_target().GetHex(),
42+
"00000000ffff0000000000000000000000000000000000000000000000000000");
43+
}
44+
45+
// testnet floor == 2**256 // 2**20 - 1. Derive (python3):
46+
// "%064x" % (2**256 // 2**20 - 1)
47+
TEST(DashDifficultyParity, TestnetMaxTargetFloorExact)
48+
{
49+
dash::SharechainConfig::is_testnet = true;
50+
EXPECT_EQ(dash::SharechainConfig::max_target().GetHex(),
51+
"00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
52+
dash::SharechainConfig::is_testnet = false;
53+
}
54+
55+
// ── 2. per-share min_work = target_to_average_attempts(floor) ───────────────
56+
//
57+
// ShareIndex(share).min_work = target_to_average_attempts(bits_to_target(
58+
// m_max_bits)) (share_chain.hpp:228). At the difficulty floor that reduces
59+
// to target_to_average_attempts(max_target()).
60+
61+
// mainnet: attempts = 2**256 // (0xFFFF*2**208 + 1). Derive (python3):
62+
// (2**256)//(0xFFFF*(2**208)+1) == 4295032833 == 0x100010001
63+
TEST(DashDifficultyParity, MainnetPerShareMinWorkExact)
64+
{
65+
dash::SharechainConfig::is_testnet = false;
66+
uint288 attempts = chain::target_to_average_attempts(dash::SharechainConfig::max_target());
67+
EXPECT_EQ(attempts.GetHex(), U288("100010001").GetHex());
68+
EXPECT_TRUE(attempts == static_cast<uint64_t>(4295032833ULL));
69+
}
70+
71+
// testnet: attempts = 2**256 // (2**256//2**20). Derive (python3):
72+
// (2**256)//((2**256//2**20-1)+1) == 1048576 == 2**20 == 0x100000
73+
TEST(DashDifficultyParity, TestnetPerShareMinWorkExact)
74+
{
75+
dash::SharechainConfig::is_testnet = true;
76+
uint288 attempts = chain::target_to_average_attempts(dash::SharechainConfig::max_target());
77+
EXPECT_EQ(attempts.GetHex(), U288("100000").GetHex());
78+
EXPECT_TRUE(attempts == static_cast<uint64_t>(1048576ULL));
79+
dash::SharechainConfig::is_testnet = false;
80+
}
81+
82+
// ── 3. ShareIndex min_work accumulation identity (dash floor) ───────────────
83+
//
84+
// Over N equal-floor shares the accumulated min_work == per_share * N, the same
85+
// identity DeltaCache maintains (test_compute_share_target DeltaCacheAfterPruning,
86+
// LTC). Pinned here with DASH-floor numbers so a config-floor regression is
87+
// caught in the DASH lane directly.
88+
TEST(DashDifficultyParity, MainnetMinWorkAccumulationIdentity)
89+
{
90+
dash::SharechainConfig::is_testnet = false;
91+
uint288 per_share = chain::target_to_average_attempts(dash::SharechainConfig::max_target());
92+
// N=199 (default real_chain window sample). Derive (python3):
93+
// 4295032833 * 199 == 854711533767
94+
uint288 acc = per_share * static_cast<uint64_t>(199);
95+
EXPECT_TRUE(acc == static_cast<uint64_t>(854711533767ULL));
96+
}
97+
98+
// ── 4. floor bits roundtrip (m_max_bits <-> floor target) ───────────────────
99+
//
100+
// ShareIndex derives min_work from m_max_bits via bits_to_target; the floor
101+
// must survive the compact encode/decode used to carry it on the wire.
102+
TEST(DashDifficultyParity, MainnetFloorBitsRoundtrip)
103+
{
104+
dash::SharechainConfig::is_testnet = false;
105+
uint256 floor = dash::SharechainConfig::max_target();
106+
uint32_t bits = chain::target_to_bits_upper_bound(floor);
107+
uint256 decoded = chain::bits_to_target(bits);
108+
EXPECT_EQ(decoded, floor); // exact roundtrip at the standard floor
109+
EXPECT_EQ(bits >> 24, 0x1du); // 0xFFFF*2**208 -> exponent 0x1d (29 bytes)
110+
}

0 commit comments

Comments
 (0)