|
| 1 | +// G1 greenlight-gate KAT — DGB net/consensus byte-parity vs the oracle. |
| 2 | +// |
| 3 | +// FENCED conformance test (no production code touched). This is the test-form |
| 4 | +// artifact of greenlight gate G1 (per dgb-greenlight-g0-artifact): it pins the |
| 5 | +// fully-assembled dgb::make_coin_params() output — every isolation primitive |
| 6 | +// (bucket-1: PREFIX / IDENTIFIER) and every consensus/net constant — against |
| 7 | +// values hand-transcribed from the DGB oracle frstrtr/p2pool-dgb-scrypt |
| 8 | +// (operator switch-oracle ruling 2026-06-17, Option B): |
| 9 | +// networks/digibyte.py — coin params, ports, address versions, MAX_TARGET |
| 10 | +// bitcoin/p2p.py:28 — Protocol.VERSION (advertised) = 3501 |
| 11 | +// bitcoin/networks ... — IDENTIFIER 4B62545B1A631AFE, PREFIX, SHARE_PERIOD |
| 12 | +// |
| 13 | +// NON-CIRCULAR: the expected side below is literal bytes/ints typed from the |
| 14 | +// oracle python source, NOT a second read of the same C++ SUT constant. A drift |
| 15 | +// in config_coin.hpp / config_pool.hpp that silently diverges from the oracle |
| 16 | +// fails here even though every other dgb test (which sources the same SUT |
| 17 | +// constant on both sides) stays green. |
| 18 | +// |
| 19 | +// 3-bucket posture (operator 2026-06-17): IDENTIFIER + PREFIX are bucket-1 |
| 20 | +// ISOLATION PRIMITIVES — pinned here as the per-coin/per-instance sharechain |
| 21 | +// namespacing boundary; this KAT guards them against accidental |
| 22 | +// "standardization", it does NOT propose unifying them. |
| 23 | +// |
| 24 | +// MUST appear in BOTH the ctest registration (this dir CMakeLists.txt) AND the |
| 25 | +// build.yml --target allowlist, or it becomes a #143-style NOT_BUILT sentinel. |
| 26 | + |
| 27 | +#include <impl/dgb/params.hpp> |
| 28 | + |
| 29 | +#include <core/coin_params.hpp> |
| 30 | + |
| 31 | +#include <string> |
| 32 | + |
| 33 | +#include <gtest/gtest.h> |
| 34 | + |
| 35 | +namespace { |
| 36 | + |
| 37 | +// ---- Oracle expected values (frstrtr/p2pool-dgb-scrypt, transcribed) -------- |
| 38 | + |
| 39 | +// networks/digibyte.py PARENT + pool block |
| 40 | +constexpr char ORACLE_SYMBOL[] = "DGB"; |
| 41 | +constexpr uint16_t ORACLE_P2P_PORT = 5024; // sharechain P2P |
| 42 | +constexpr uint16_t ORACLE_WORKER_PORT = 5025; // Stratum |
| 43 | +constexpr uint8_t ORACLE_ADDR_VERSION_MAIN = 30; // 0x1e, "D" |
| 44 | +constexpr uint8_t ORACLE_ADDR_P2SH_MAIN = 63; // 0x3f, "S" |
| 45 | +constexpr uint8_t ORACLE_ADDR_VERSION_TEST = 126; // 0x7e |
| 46 | +constexpr uint32_t ORACLE_SHARE_PERIOD = 15; // s |
| 47 | +constexpr uint32_t ORACLE_CHAIN_LENGTH = 2880; // 12h / 15s |
| 48 | +constexpr uint32_t ORACLE_SPREAD = 24; |
| 49 | +constexpr uint32_t ORACLE_TARGET_LOOKBEHIND = 100; |
| 50 | +constexpr uint32_t ORACLE_MIN_PROTO_VERSION = 1700; // digibyte.py NEW_MIN (accept-floor) |
| 51 | +constexpr uint32_t ORACLE_ADV_PROTO_VERSION = 3501; // p2p.py:28 Protocol.VERSION |
| 52 | +constexpr uint32_t ORACLE_SEGWIT_ACT_VERSION = 35; // digibyte.py:27 |
| 53 | +constexpr uint64_t ORACLE_DUST_THRESHOLD = 100000; // 0.001 DGB |
| 54 | + |
| 55 | +// IDENTIFIER / PREFIX — bucket-1 isolation primitives, same on both nets. |
| 56 | +constexpr char ORACLE_IDENTIFIER_HEX[] = "4b62545b1a631afe"; |
| 57 | +constexpr char ORACLE_PREFIX_HEX[] = "1c0553f23ebfcffe"; |
| 58 | + |
| 59 | +// MAX_TARGET = 2**256 // 2**20 - 1 == 2^236 - 1 (digibyte.py). |
| 60 | +// 236 one-bits = 59 'f' nibbles, with the top 20 bits (5 nibbles) zero. |
| 61 | +uint256 oracle_max_target() { |
| 62 | + uint256 t; |
| 63 | + t.SetHex(std::string(5, '0') + std::string(59, 'f')); // 5+59 = 64 nibbles |
| 64 | + return t; |
| 65 | +} |
| 66 | + |
| 67 | +TEST(G1OracleByteParity, MainnetNetConstants) { |
| 68 | + core::CoinParams p = dgb::make_coin_params(/*testnet=*/false); |
| 69 | + |
| 70 | + EXPECT_EQ(p.symbol, ORACLE_SYMBOL); |
| 71 | + EXPECT_EQ(p.p2p_port, ORACLE_P2P_PORT); |
| 72 | + EXPECT_EQ(p.worker_port, ORACLE_WORKER_PORT); |
| 73 | + EXPECT_EQ(p.address_version, ORACLE_ADDR_VERSION_MAIN); |
| 74 | + EXPECT_EQ(p.address_p2sh_version, ORACLE_ADDR_P2SH_MAIN); |
| 75 | + EXPECT_EQ(p.share_period, ORACLE_SHARE_PERIOD); |
| 76 | + EXPECT_EQ(p.chain_length, ORACLE_CHAIN_LENGTH); |
| 77 | + EXPECT_EQ(p.real_chain_length, ORACLE_CHAIN_LENGTH); |
| 78 | + EXPECT_EQ(p.spread, ORACLE_SPREAD); |
| 79 | + EXPECT_EQ(p.target_lookbehind, ORACLE_TARGET_LOOKBEHIND); |
| 80 | + EXPECT_EQ(p.minimum_protocol_version, ORACLE_MIN_PROTO_VERSION); |
| 81 | + EXPECT_EQ(p.advertised_protocol_version, ORACLE_ADV_PROTO_VERSION); |
| 82 | + EXPECT_EQ(p.segwit_activation_version, ORACLE_SEGWIT_ACT_VERSION); |
| 83 | + EXPECT_EQ(p.dust_threshold, ORACLE_DUST_THRESHOLD); |
| 84 | +} |
| 85 | + |
| 86 | +TEST(G1OracleByteParity, IsolationPrimitivesPrefixIdentifier) { |
| 87 | + // bucket-1: never standardized; pinned per-coin on both nets. |
| 88 | + core::CoinParams p = dgb::make_coin_params(/*testnet=*/false); |
| 89 | + EXPECT_EQ(p.identifier_hex, ORACLE_IDENTIFIER_HEX); |
| 90 | + EXPECT_EQ(p.prefix_hex, ORACLE_PREFIX_HEX); |
| 91 | + EXPECT_EQ(p.testnet_identifier_hex, ORACLE_IDENTIFIER_HEX); |
| 92 | + EXPECT_EQ(p.testnet_prefix_hex, ORACLE_PREFIX_HEX); |
| 93 | +} |
| 94 | + |
| 95 | +TEST(G1OracleByteParity, MaxTargetIs2Pow236Minus1) { |
| 96 | + core::CoinParams p = dgb::make_coin_params(/*testnet=*/false); |
| 97 | + EXPECT_EQ(p.max_target, oracle_max_target()); |
| 98 | +} |
| 99 | + |
| 100 | +TEST(G1OracleByteParity, TestnetAddressVersionDiverges) { |
| 101 | + // Testnet keeps its own address version but SHARES the isolation primitives. |
| 102 | + core::CoinParams p = dgb::make_coin_params(/*testnet=*/true); |
| 103 | + EXPECT_EQ(p.address_version, ORACLE_ADDR_VERSION_TEST); |
| 104 | + EXPECT_EQ(p.identifier_hex, ORACLE_IDENTIFIER_HEX); |
| 105 | + EXPECT_EQ(p.prefix_hex, ORACLE_PREFIX_HEX); |
| 106 | +} |
| 107 | + |
| 108 | +TEST(G1OracleByteParity, DonationScriptVersionGate) { |
| 109 | + // Pre-V36 share -> forrestv P2PK (67B, 0x41 ... 0xac). |
| 110 | + auto pre = dgb::PoolConfig::get_donation_script(/*share_version=*/35); |
| 111 | + ASSERT_EQ(pre.size(), 67u); |
| 112 | + EXPECT_EQ(pre.front(), 0x41); // OP_PUSHBYTES_65 |
| 113 | + EXPECT_EQ(pre.back(), 0xac); // OP_CHECKSIG |
| 114 | + EXPECT_EQ(pre[1], 0x04); // uncompressed pubkey marker |
| 115 | + |
| 116 | + // V36+ share -> combined P2SH 1-of-2 (23B, 0xa9 0x14 <20B> 0x87). |
| 117 | + auto v36 = dgb::PoolConfig::get_donation_script(/*share_version=*/36); |
| 118 | + ASSERT_EQ(v36.size(), 23u); |
| 119 | + EXPECT_EQ(v36[0], 0xa9); // OP_HASH160 |
| 120 | + EXPECT_EQ(v36[1], 0x14); // push 20 |
| 121 | + EXPECT_EQ(v36.back(), 0x87); // OP_EQUAL |
| 122 | +} |
| 123 | + |
| 124 | +} // namespace |
0 commit comments