Skip to content

Commit 5a978f5

Browse files
authored
Merge pull request #580 from frstrtr/dash/s8-poolnode-peer
dash: sharechain pool-peer state (S8 pool-node leaf 1)
2 parents 3c3071f + f8df04a commit 5a978f5

4 files changed

Lines changed: 157 additions & 2 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
test_threading test_weights \
8989
test_header_chain test_mempool test_template_builder \
9090
test_doge_chain test_compact_blocks test_dash_x11_kat \
91-
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_cb_payee test_dash_poolnode_messages \
91+
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_cb_payee test_dash_poolnode_messages test_dash_peer \
9292
test_multiaddress_pplns test_pplns_stress \
9393
test_hash_link test_decay_pplns \
9494
test_pplns_consensus \
@@ -238,7 +238,7 @@ jobs:
238238
test_threading test_weights \
239239
test_header_chain test_mempool test_template_builder \
240240
test_doge_chain test_compact_blocks test_dash_x11_kat \
241-
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_cb_payee test_dash_poolnode_messages \
241+
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_cb_payee test_dash_poolnode_messages test_dash_peer \
242242
test_hash_link test_decay_pplns \
243243
test_pplns_consensus \
244244
test_v36_script_sorting test_v36_cross_impl_refhash \

src/impl/dash/peer.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
// Dash p2pool sharechain pool-peer state.
4+
//
5+
// S8 pool-node leaf 1 of N. Mirrors btc::Peer / dgb::Peer: the per-peer state a
6+
// pool Node keeps for every connected p2pool share-network peer (NOT a dashd
7+
// coin-daemon peer — that layer is coin/p2p_connection.hpp). Tracks the
8+
// negotiated version/subversion/services from the `version` handshake, the
9+
// connection timestamp, and the remembered-transaction sets used by the
10+
// share-message protocol (remote_txs = hashes the peer advertises; remembered_txs
11+
// = full txs we have forwarded/learned, keyed by hash).
12+
//
13+
// Pure state struct, no socket/IO — header-only, rig-free, fenced to src/impl/dash/.
14+
15+
#include "coin/transaction.hpp"
16+
17+
#include <chrono>
18+
#include <map>
19+
#include <optional>
20+
#include <set>
21+
#include <string>
22+
23+
#include <core/uint256.hpp>
24+
25+
namespace dash
26+
{
27+
28+
struct Peer
29+
{
30+
// === negotiated via the `version` handshake ===
31+
std::optional<uint32_t> m_other_version;
32+
std::string m_other_subversion;
33+
uint64_t m_other_services{0};
34+
uint64_t m_nonce{0};
35+
36+
std::chrono::steady_clock::time_point m_connected_at{std::chrono::steady_clock::now()};
37+
38+
// === remembered-transaction protocol state ===
39+
std::set<uint256> m_remote_txs; // hashes the remote peer has advertised
40+
std::map<uint256, coin::Transaction> m_remembered_txs; // full txs keyed by hash
41+
};
42+
43+
}; // namespace dash

test/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,16 @@ if (BUILD_TESTING AND GTest_FOUND)
500500
target_link_libraries(test_dash_config PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
501501
gtest_add_tests(test_dash_config "" AUTO)
502502

503+
add_executable(test_dash_peer test_dash_peer.cpp)
504+
target_link_libraries(test_dash_peer PRIVATE
505+
GTest::gtest_main GTest::gtest
506+
dash_x11 core
507+
nlohmann_json::nlohmann_json
508+
${Boost_LIBRARIES}
509+
)
510+
target_link_libraries(test_dash_peer PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
511+
gtest_add_tests(test_dash_peer "" AUTO)
512+
503513
# additive: pure persisted activation-latch (header-only version_activation_latch.hpp);
504514
# mirrors the test_dash_config link set (nlohmann_json + core), no ltc/pool SCC dependency.
505515
add_executable(test_dash_version_activation_latch test_dash_version_activation_latch.cpp)

test/test_dash_peer.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/// Phase S8 — Dash sharechain pool-node leaf 1: per-peer state (src/impl/dash/peer.hpp).
2+
///
3+
/// dash::Peer is the analog of btc::Peer / dgb::Peer: the state a pool Node holds
4+
/// for each connected p2pool share-network peer. The pool-node bridge (node.hpp,
5+
/// a later leaf) keys a Peer off every connection and drives it from the share
6+
/// message handlers. This KAT pins the observable contract those handlers read:
7+
///
8+
/// (a) fresh-peer defaults — no negotiated version yet, empty subversion,
9+
/// zeroed services/nonce, empty remember-sets, connection time stamped.
10+
/// (b) version-handshake fields round-trip (what the `version` handler writes).
11+
/// (c) the remembered-tx protocol state: m_remote_txs is a dedup hash set and
12+
/// m_remembered_txs maps hash -> full coin::Transaction with erase.
13+
/// (d) connection timestamps are monotonic across successive peers.
14+
15+
#include <impl/dash/peer.hpp>
16+
#include <impl/dash/coin/transaction.hpp>
17+
18+
#include <core/uint256.hpp>
19+
20+
#include <gtest/gtest.h>
21+
22+
#include <chrono>
23+
24+
using dash::Peer;
25+
26+
namespace
27+
{
28+
uint256 H(uint8_t b)
29+
{
30+
uint256 h;
31+
h.begin()[0] = b;
32+
return h;
33+
}
34+
} // namespace
35+
36+
TEST(DashPeer, FreshDefaultsAreSane)
37+
{
38+
Peer p;
39+
EXPECT_FALSE(p.m_other_version.has_value());
40+
EXPECT_TRUE(p.m_other_subversion.empty());
41+
EXPECT_EQ(p.m_other_services, 0u);
42+
EXPECT_EQ(p.m_nonce, 0u);
43+
EXPECT_TRUE(p.m_remote_txs.empty());
44+
EXPECT_TRUE(p.m_remembered_txs.empty());
45+
EXPECT_LE(p.m_connected_at, std::chrono::steady_clock::now());
46+
}
47+
48+
TEST(DashPeer, VersionHandshakeRoundTrip)
49+
{
50+
Peer p;
51+
p.m_other_version = 70238u; // dashd-aligned proto seen on the wire
52+
p.m_other_subversion = "/c2pool-dash:0.1/";
53+
p.m_other_services = 0x9u;
54+
p.m_nonce = 0xdeadbeefull;
55+
56+
ASSERT_TRUE(p.m_other_version.has_value());
57+
EXPECT_EQ(*p.m_other_version, 70238u);
58+
EXPECT_EQ(p.m_other_subversion, "/c2pool-dash:0.1/");
59+
EXPECT_EQ(p.m_other_services, 0x9u);
60+
EXPECT_EQ(p.m_nonce, 0xdeadbeefull);
61+
}
62+
63+
TEST(DashPeer, RemoteTxSetDedups)
64+
{
65+
Peer p;
66+
p.m_remote_txs.insert(H(1));
67+
p.m_remote_txs.insert(H(2));
68+
p.m_remote_txs.insert(H(1)); // duplicate advertise
69+
EXPECT_EQ(p.m_remote_txs.size(), 2u);
70+
EXPECT_EQ(p.m_remote_txs.count(H(1)), 1u);
71+
EXPECT_EQ(p.m_remote_txs.count(H(9)), 0u);
72+
}
73+
74+
TEST(DashPeer, RememberedTxRoundTripAndErase)
75+
{
76+
Peer p;
77+
78+
dash::coin::MutableTransaction mtx;
79+
mtx.version = 2;
80+
mtx.type = 5; // DIP4 CBTX
81+
mtx.locktime = 99;
82+
dash::coin::Transaction tx(mtx);
83+
84+
const uint256 key = H(7);
85+
p.m_remembered_txs.emplace(key, tx);
86+
87+
auto it = p.m_remembered_txs.find(key);
88+
ASSERT_NE(it, p.m_remembered_txs.end());
89+
EXPECT_EQ(it->second.version, 2);
90+
EXPECT_EQ(it->second.type, 5);
91+
EXPECT_EQ(it->second.locktime, 99u);
92+
93+
EXPECT_EQ(p.m_remembered_txs.erase(key), 1u);
94+
EXPECT_TRUE(p.m_remembered_txs.empty());
95+
}
96+
97+
TEST(DashPeer, ConnectedAtMonotonicAcrossPeers)
98+
{
99+
Peer a;
100+
Peer b;
101+
EXPECT_LE(a.m_connected_at, b.m_connected_at);
102+
}

0 commit comments

Comments
 (0)