diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b135ad0e4..9d71bd27f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -84,7 +84,7 @@ jobs: dgb_gentx_coinbase_test dgb_connection_coinbase_test dgb_pplns_payout_split_test nmc_auxpow_merkle_test nmc_template_builder_test nmc_auxpow_wire_test nmc_reconstruct_won_block_test nmc_mempool_name_test nmc_block_broadcast_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \ dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test \ rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \ - dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_naughty_propagation_test v37_test \ + dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_redistribute_delegate_ghal_test dgb_naughty_propagation_test v37_test \ -j$(nproc) - name: Run tests @@ -216,7 +216,7 @@ jobs: dgb_gentx_coinbase_test dgb_connection_coinbase_test dgb_pplns_payout_split_test nmc_auxpow_merkle_test nmc_template_builder_test nmc_auxpow_wire_test nmc_reconstruct_won_block_test nmc_mempool_name_test nmc_block_broadcast_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \ dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test \ rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \ - dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_naughty_propagation_test test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \ + dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_redistribute_delegate_ghal_test dgb_naughty_propagation_test test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \ v37_test \ -j$(nproc) diff --git a/src/impl/dgb/redistribute.hpp b/src/impl/dgb/redistribute.hpp index d86916d58..cd0b42732 100644 --- a/src/impl/dgb/redistribute.hpp +++ b/src/impl/dgb/redistribute.hpp @@ -22,6 +22,7 @@ #include "config_pool.hpp" #include "share_tracker.hpp" #include "share_check.hpp" +#include "coin/get_height_and_last_endpoints.hpp" #include #include @@ -450,8 +451,8 @@ class Redistributor return; auto [height, last] = tracker.chain.get_height_and_last(best); - int32_t depth = std::min(height, static_cast(PoolConfig::real_chain_length())); - if (depth < 1) + int32_t depth = dgb::pplns_window_depth(height, static_cast(PoolConfig::real_chain_length())); + if (!dgb::pplns_window_active(depth)) return; struct AccumEntry { std::vector script; uint160 hash; uint8_t type; uint64_t weight; }; diff --git a/src/impl/dgb/test/CMakeLists.txt b/src/impl/dgb/test/CMakeLists.txt index 98a0ec45e..020115c25 100644 --- a/src/impl/dgb/test/CMakeLists.txt +++ b/src/impl/dgb/test/CMakeLists.txt @@ -795,6 +795,18 @@ if (BUILD_TESTING AND GTest_FOUND) core c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage) gtest_add_tests(dgb_get_height_and_last_endpoints_test "" AUTO) + + # dgb_redistribute_delegate_ghal_test: FENCED, additive byte-identity proof + # that redistribute.hpp's PPLNS-window guard was rewired onto the SSOT + # coin/get_height_and_last_endpoints.hpp with NO value change. Non-circular: + # re-derives the inline std::min/(depth<1) directly. MUST also be in the + # build.yml --target allowlist (#143 NOT_BUILT trap). + add_executable(dgb_redistribute_delegate_ghal_test redistribute_delegate_ghal_test.cpp) + target_link_libraries(dgb_redistribute_delegate_ghal_test PRIVATE + GTest::gtest_main GTest::gtest + core + c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage) + gtest_add_tests(dgb_redistribute_delegate_ghal_test "" AUTO) # dgb_pool_efficiency_test: FENCED, additive KAT pinning the pool # EFFICIENCY / REAL-HASHRATE diagnostics arithmetic in pool_efficiency.hpp vs # the p2pool main.py status-loop oracle (stale_prop = (orphan+doa)/total; diff --git a/src/impl/dgb/test/redistribute_delegate_ghal_test.cpp b/src/impl/dgb/test/redistribute_delegate_ghal_test.cpp new file mode 100644 index 000000000..9dea81c68 --- /dev/null +++ b/src/impl/dgb/test/redistribute_delegate_ghal_test.cpp @@ -0,0 +1,75 @@ +// dgb redistribute -> get_height_and_last SSOT byte-identity DELEGATION KAT. +// +// FENCED, additive. Pins the runtime rewire of redistribute.hpp:454-455 +// (refresh_pplns_cache PPLNS-window guard) onto the SSOT free functions in +// coin/get_height_and_last_endpoints.hpp. The SSOT itself is proven against the +// p2pool-dgb-scrypt oracle by dgb_get_height_and_last_endpoints_test; this slice +// proves only that swapping the inline expression for the SSOT call changed +// NOTHING -- i.e. the rewire is value-identical, no reward-distribution drift. +// +// PRE-delegation inline (verbatim, from git history of redistribute.hpp): +// int32_t depth = std::min(height, static_cast(real_chain_length())); +// if (depth < 1) return; // early-out: window inactive +// POST-delegation (current redistribute.hpp:454-455): +// int32_t depth = dgb::pplns_window_depth(height, real_chain_length()); +// if (!dgb::pplns_window_active(depth)) return; +// +// NON-CIRCULAR: the "expected" side below recomputes std::min(...)/(depth < 1) +// directly from the operands -- it does NOT call the SSOT under test. We then +// assert the SSOT call reproduces that inline result across a height matrix that +// straddles every boundary (negative, 0, 1, REAL_CHAIN_LENGTH-1/=/+1). +// MUST appear in BOTH this dir CMakeLists.txt AND the build.yml --target +// allowlist, or it becomes a #143 NOT_BUILT sentinel. + +#include + +#include +#include +#include + +using namespace dgb; + +static constexpr int32_t CL_MAIN = 2880; // REAL_CHAIN_LENGTH mainnet +static constexpr int32_t CL_TEST = 400; // REAL_CHAIN_LENGTH testnet + +// The verbatim pre-delegation inline expression, re-implemented here so the +// expectation is independent of the code under test. +static int32_t inline_depth(int32_t height, int32_t rcl) { + return std::min(height, static_cast(rcl)); +} +static bool inline_early_return(int32_t depth) { + return depth < 1; +} + +static void check_one(int32_t height, int32_t rcl) { + const int32_t want_depth = inline_depth(height, rcl); + const bool want_ret = inline_early_return(want_depth); + + const int32_t got_depth = pplns_window_depth(height, rcl); + const bool got_ret = !pplns_window_active(got_depth); + + EXPECT_EQ(got_depth, want_depth) + << "depth diverged at height=" << height << " rcl=" << rcl; + EXPECT_EQ(got_ret, want_ret) + << "early-return diverged at height=" << height << " rcl=" << rcl; +} + +TEST(DgbRedistributeDelegateGhal, DepthMatchesInlineMainnet) { + for (int32_t h : {-5, -1, 0, 1, 2, 10, 1440, CL_MAIN - 1, CL_MAIN, CL_MAIN + 1, 100000}) + check_one(h, CL_MAIN); +} + +TEST(DgbRedistributeDelegateGhal, DepthMatchesInlineTestnet) { + for (int32_t h : {-5, -1, 0, 1, 2, 10, 200, CL_TEST - 1, CL_TEST, CL_TEST + 1, 100000}) + check_one(h, CL_TEST); +} + +// Boundary spot-checks pinned to absolute values (no SSOT call on the expected +// side) -- the window is INACTIVE iff clamped depth < 1, ACTIVE from height 1 up. +TEST(DgbRedistributeDelegateGhal, ActivationBoundaryAbsolute) { + EXPECT_TRUE (!pplns_window_active(pplns_window_depth(0, CL_MAIN))); // depth 0 -> inactive + EXPECT_FALSE(!pplns_window_active(pplns_window_depth(1, CL_MAIN))); // depth 1 -> active + EXPECT_FALSE(!pplns_window_active(pplns_window_depth(CL_MAIN, CL_MAIN))); // clamped, active + EXPECT_TRUE (!pplns_window_active(pplns_window_depth(-3, CL_MAIN))); // negative -> inactive + EXPECT_EQ(pplns_window_depth(CL_MAIN + 50, CL_MAIN), CL_MAIN); // clamp to RCL +}