|
| 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