Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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_dash_difficulty_parity test_dash_auto_ratchet \
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_dash_auto_ratchet test_dash_min_protocol_gate \
test_multiaddress_pplns test_pplns_stress \
test_hash_link test_decay_pplns \
test_pplns_consensus \
Expand Down Expand Up @@ -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_difficulty_parity test_dash_auto_ratchet \
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_dash_auto_ratchet test_dash_min_protocol_gate \
test_hash_link test_decay_pplns \
test_pplns_consensus \
test_v36_script_sorting test_v36_cross_impl_refhash \
Expand Down
53 changes: 53 additions & 0 deletions src/impl/dash/min_protocol_gate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

// DASH sharechain minimum-protocol-version gate (v36 min-proto ratchet, #643).
//
// SCOPE: a parameterized, per-instance policy for the reject-if-proto<floor
// decision at the version handshake. This leaf carries ONLY the policy object
// and its accept/reject predicate; the LIVE call site in NodeImpl::handle_version
// is the reception/handshake slice (B) and is deliberately out of scope here.
//
// RATCHET SEMANTICS (operator #643, integrator-concurred 2026-07-06 option a):
// - The floor defaults to dash::SharechainConfig::MINIMUM_PROTOCOL_VERSION
// (1700), which is the current DASH oracle accept-all floor. At the default
// this gate is a NO-OP: a peer advertising protocol=1700 MUST be accepted.
// - The floor is a per-instance MEMBER, not a baked-in constant, so the actual
// v36 ratchet value is a one-line operator knob set at G2-migration time.
// This leaf commits NO premature v36 constant (DASH share ver 16->36 is
// older-than-v35; the floor is a chosen constant, not an oracle-derived one).
//
// ISOLATION: fenced to src/impl/dash/. Touches NO shared bitcoin_family / core
// version-handshake types (per-coin isolation primitive boundary).

#include <cstdint>

#include "config_pool.hpp"

namespace dash
{

// Per-instance minimum-protocol-version policy. Default-constructed it holds the
// oracle accept-all floor (1700) and accepts every peer at or above it.
struct MinProtocolGate
{
// The rejection floor. A peer is admitted iff peer_protocol >= min_version.
uint32_t min_version = SharechainConfig::MINIMUM_PROTOCOL_VERSION;

MinProtocolGate() = default;
explicit MinProtocolGate(uint32_t floor) : min_version(floor) {}

// reject-if-proto<floor predicate. True => admit the peer.
// At the default floor (1700) this is accept-all for every real DASH peer.
[[nodiscard]] bool accepts(uint32_t peer_protocol) const
{
return peer_protocol >= min_version;
}

// Convenience inverse for handshake sites that branch on rejection.
[[nodiscard]] bool rejects(uint32_t peer_protocol) const
{
return !accepts(peer_protocol);
}
};

} // namespace dash
12 changes: 12 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,18 @@ if (BUILD_TESTING AND GTest_FOUND)
target_link_libraries(test_dash_conformance PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39): core stratum/web_server TUs
gtest_add_tests(test_dash_conformance "" AUTO)

# DASH min-protocol-version ratchet gate KAT (#643, option a): pure, header-only
# policy object; no socket/ltc/pool dependency. Mirrors the test_dash_conformance link set.
add_executable(test_dash_min_protocol_gate test_dash_min_protocol_gate.cpp)
target_link_libraries(test_dash_min_protocol_gate PRIVATE
GTest::gtest_main GTest::gtest
dash_x11 core
nlohmann_json::nlohmann_json
${Boost_LIBRARIES}
)
target_link_libraries(test_dash_min_protocol_gate PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39): core stratum/web_server TUs
gtest_add_tests(test_dash_min_protocol_gate "" AUTO)

# DASH S8 pool-node leaf 4 — share_tracker.hpp KAT: DensePPLNSWindow decayed
# weight ring buffer (compute_v36_weights), decay table, donation split,
# window slides. PoW-independent consensus core; socket-free, chain-free.
Expand Down
64 changes: 64 additions & 0 deletions test/test_dash_min_protocol_gate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// KAT for the DASH min-protocol-version ratchet gate (#643, option a).
//
// Pins the two invariants integrator required for the SAFE-ADDITIVE leaf:
// 1. NO-OP AT DEFAULT: a default-constructed gate carries the oracle floor
// (1700) and MUST admit a peer at protocol=1700. Nobody may later read the
// landed leaf as an already-live ratchet.
// 2. PARAMETERIZED, NOT BAKED: the floor is a per-instance member, so raising
// it rejects below-floor peers -- proving the ratchet MECHANISM works while
// the default stays inert.

#include <gtest/gtest.h>

#include "impl/dash/config_pool.hpp"
#include "impl/dash/min_protocol_gate.hpp"

using dash::MinProtocolGate;
using dash::SharechainConfig;

// (1) Default gate == oracle accept-all floor, and it is a genuine no-op there.
TEST(DashMinProtocolGate, DefaultFloorIsOracleAcceptAll)
{
MinProtocolGate gate;
EXPECT_EQ(gate.min_version, SharechainConfig::MINIMUM_PROTOCOL_VERSION);
EXPECT_EQ(gate.min_version, 1700u);

// A peer AT the floor MUST be accepted -- this is the no-op assertion.
EXPECT_TRUE(gate.accepts(1700u));
EXPECT_FALSE(gate.rejects(1700u));

// Real DASH peers advertise >= 1700, so the default admits every one.
EXPECT_TRUE(gate.accepts(1700u));
EXPECT_TRUE(gate.accepts(1800u));
EXPECT_TRUE(gate.accepts(70210u));
}

// (2) Below the default floor is rejected -- boundary is >=, not >.
TEST(DashMinProtocolGate, BelowDefaultFloorRejected)
{
MinProtocolGate gate;
EXPECT_FALSE(gate.accepts(1699u));
EXPECT_TRUE(gate.rejects(1699u));
EXPECT_FALSE(gate.accepts(0u));
// Exact boundary: floor-1 out, floor in.
EXPECT_FALSE(gate.accepts(gate.min_version - 1));
EXPECT_TRUE(gate.accepts(gate.min_version));
}

// (3) The floor is a settable per-instance member -- the ratchet mechanism.
// Raising it to a hypothetical v36 value rejects the old-floor peer, but
// this is a per-instance choice, NOT a committed constant.
TEST(DashMinProtocolGate, RatchetIsParameterizedNotBaked)
{
// Operator knob: raise the floor at G2-migration time.
MinProtocolGate ratcheted(1800u);
EXPECT_EQ(ratcheted.min_version, 1800u);
EXPECT_FALSE(ratcheted.accepts(1700u)); // old-floor peer now rejected
EXPECT_TRUE(ratcheted.accepts(1800u)); // at-new-floor peer admitted

// The default gate is UNAFFECTED -- proving the ratchet is per-instance and
// the leaf commits no premature v36 constant.
MinProtocolGate defaulted;
EXPECT_TRUE(defaulted.accepts(1700u));
EXPECT_EQ(defaulted.min_version, 1700u);
}
Loading