Skip to content
Merged
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_dash_min_protocol_gate test_dash_work_source test_dash_node_coin_state test_dash_coin_state_maintainer test_dash_node_embedded_wire \
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_dash_work_source test_dash_node_coin_state test_dash_coin_state_maintainer test_dash_node_embedded_wire test_dash_node_reception_wire \
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_min_protocol_gate test_dash_work_source test_dash_node_coin_state test_dash_coin_state_maintainer test_dash_node_embedded_wire \
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_dash_work_source test_dash_node_coin_state test_dash_coin_state_maintainer test_dash_node_embedded_wire test_dash_node_reception_wire \
test_hash_link test_decay_pplns \
test_pplns_consensus \
test_v36_script_sorting test_v36_cross_impl_refhash \
Expand Down
61 changes: 61 additions & 0 deletions src/impl/dash/coin/block_connect_ingest.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#pragma once
// ===========================================================================
// dash reception wire (leg 3 of 4) -- interfaces::Node::block_connected ->
// maintainer.
//
// #672..#685 landed the node-held embedded coin-state bundle + its async
// CoinStateMaintainer; leg 1 (wire_mempool_ingest) subscribed the mempool-relay
// event and leg 2 (wire_tip_ingest) the header/think TIP-ADVANCE event. This
// leg subscribes the BLOCK-CONNECT event: every connected block is routed to
// CoinStateMaintainer::on_block_connected(), which folds the block's DIP3
// special txs into the DMN set incrementally (MnStateMachine::apply_block),
// keeping the masternode set the embedded coinbase pays current BETWEEN full
// mnlistdiff snapshots. A block that empties the set (all collateral spent)
// clears MN-readiness and demotes the bundle to the retained dashd getblock-
// template fallback rather than backing a template with a phantom payee.
//
// PAYLOAD: a bare full_block carries the block body but NOT its height, and
// apply_block needs the connected height (DIP3 special-tx chain position). So
// this leg subscribes block_connected, which pairs (block, height) -- the
// interface-shape addition this leg makes, mirroring leg 2's TipAdvance, kept to
// the dash interface only (single-coin, purely additive). on_mn_list_update
// remains the authoritative bulk resync (leg 4, mnlistdiff source event).
//
// LIFETIME: the handler captures maint by reference, so maint (and the
// NodeCoinState it drives) MUST outlive node. The returned EventDisposable lets
// a caller tear the subscription down explicitly; it does NOT auto-dispose on
// drop -- identical contract to wire_mempool_ingest / wire_tip_ingest.
//
// SCC: pulls node_interface.hpp (transaction/block codec via BlockConnected),
// so include this header ONLY from a TU that already links the full dash codec
// (main_dash + this leg KAT), never a guard-weight TU.
// ===========================================================================
#include <memory>

#include <core/events.hpp>

#include "node_interface.hpp" // dash::interfaces::Node (block_connected feed) + BlockConnected
#include "coin_state_maintainer.hpp" // dash::coin::CoinStateMaintainer::on_block_connected

namespace c2pool::dash
{

// Subscribe maint to node.block_connected: every connected block folds its DIP3
// special txs into the DMN set via on_block_connected(block, height). The
// maintainer refreshes MN-readiness from the post-apply set size -- a block that
// empties the set demotes the node-held bundle to the dashd fallback; otherwise
// it republishes with the freshened MN set. Returns the subscription handle so
// the caller controls teardown.
inline std::shared_ptr<EventDisposable>
wire_block_connect_ingest(::dash::interfaces::Node& node,
::dash::coin::CoinStateMaintainer& maint)
{
return node.block_connected.subscribe(
[&maint](const ::dash::interfaces::BlockConnected& bc)
{
maint.on_block_connected(bc.block, bc.height);
});
}

} // namespace c2pool::dash
68 changes: 68 additions & 0 deletions src/impl/dash/coin/mempool_ingest.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#pragma once
// ===========================================================================
// dash reception wire (leg 1 of 4) -- interfaces::Node::new_tx -> maintainer.
//
// #672..#685 landed the node-held embedded coin-state bundle plus its async
// CoinStateMaintainer, and proved that DRIVING the maintainer's on_*() methods
// flips select_work() to the embedded arm. But nothing in a LIVE NodeImpl ever
// subscribed the coin interface's reception events to that maintainer, so in a
// running node the arm could never flip on its own -- the maintainer sat idle.
// This is the first of the four reception legs
// (on_mempool_tx / on_block_connected / on_new_tip / on_mn_list_update): the
// mempool-relay leg, wired exactly as the dgb sibling (wire_mempool_ingest)
// but routed through the maintainer's on_mempool_tx() so the readiness /
// republish bookkeeping stays in one place.
//
// PAYLOAD-COMPLETE TODAY: interfaces::Node::new_tx carries a whole
// coin::Transaction, and on_mempool_tx() never gates publication (an empty
// mempool still yields a valid coinbase-only template), so this leg needs no
// chain context. The other three legs are NOT wired here: on_block_connected
// needs the connected block's HEIGHT (full_block carries none -- see bch's
// block_connector deriving it from the chain tip), on_new_tip needs
// bits/mtp/address-version params a bare best_block_hash does not carry, and
// on_mn_list_update has no source event on interfaces::Node at all. Those are
// their own slices; opening them touches the interface shape and is a design
// decision surfaced to the integrator, not guessed here.
//
// LIFETIME: the handler captures `maint` by reference, so `maint` (and the
// NodeCoinState it drives) MUST outlive `node`. The returned EventDisposable
// lets a caller tear the subscription down explicitly; EventDisposable does
// NOT auto-dispose on destruction, so if the handle is dropped the
// subscription persists for the node's life.
//
// SCC (#143 / #22 / #39): pulls transaction.hpp (the tx serialization codec),
// so include this header ONLY from a TU that already links the full dash codec
// (main_dash + this leg's KAT), never a guard-weight TU -- identical to the
// dgb mempool_ingest / embedded_tx_select btclibs-SCC trap.
// ===========================================================================
#include <memory>

#include <core/events.hpp>

#include "node_interface.hpp" // dash::interfaces::Node (new_tx feed)
#include "coin_state_maintainer.hpp" // dash::coin::CoinStateMaintainer::on_mempool_tx
#include "transaction.hpp" // dash::coin::Transaction -> MutableTransaction

namespace c2pool::dash
{

// Subscribe `maint` to `node.new_tx`: every relayed tx is folded into the
// maintainer's mempool via on_mempool_tx (fee_known=false until a UTXO view
// feeds it, matching the embedded shaper's conservative default -- a P2P-fed
// mempool cannot desync coinbasevalue versus a daemon's GBT). The mempool leg
// never gates publication, so a rejected tx (bad utxo ref / already-in) is a
// no-op here, not a demotion. Returns the subscription handle so the caller
// controls teardown.
inline std::shared_ptr<EventDisposable>
wire_mempool_ingest(::dash::interfaces::Node& node,
::dash::coin::CoinStateMaintainer& maint)
{
return node.new_tx.subscribe(
[&maint](const ::dash::coin::Transaction& tx)
{
maint.on_mempool_tx(::dash::coin::MutableTransaction(tx));
});
}

} // namespace c2pool::dash
22 changes: 22 additions & 0 deletions src/impl/dash/coin/node_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ struct TipAdvance
uint32_t version{0};
};

/// Header/think path payload: a block was connected to the active chain. The
/// bare full_block carries the block body but NOT the height CoinStateMaintainer
/// ::on_block_connected needs to drive MnStateMachine::apply_block (the DIP3
/// special-tx height is a chain-position input apply_block cannot recover from
/// the block alone). block_connected pairs the two so the reception wire feeds
/// apply_block the exact (block, height) apply_block expects -- purely additive,
/// dash interface only (leg 2's new_tip added TipAdvance for the same reason a
/// bare best_block_hash was insufficient).
struct BlockConnected
{
coin::BlockType block;
uint32_t height{0};
};

struct Node
{
Variable<uint256> best_block_hash;
Expand All @@ -48,6 +62,14 @@ struct Node
// tip-readiness prerequisite without a direct poke.
Event<TipAdvance> new_tip;

// Header/think path: fires when a block is connected to the active chain,
// carrying (block, height) (see BlockConnected). The reception wire
// subscribes CoinStateMaintainer::on_block_connected to this so the DMN set
// the embedded coinbase pays auto-maintains incrementally between full
// mnlistdiff snapshots -- a block that empties the set demotes to the dashd
// fallback rather than backing a template with a phantom payee.
Event<BlockConnected> block_connected;

// SPV A1 (parity audit): fires when dashd announces a ChainLock has
// been aggregated for a block. Carries {block_hash, height}.
// Consumers (e.g. block-find submit handler) can consult
Expand Down
15 changes: 15 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,21 @@ if (BUILD_TESTING AND GTest_FOUND)
target_link_libraries(test_dash_node_embedded_wire PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining c2pool_storage pool) # OBJECT-lib SCC direct-naming (#22/#39)
gtest_add_tests(test_dash_node_embedded_wire "" AUTO)

# Reception wire (legs 1-3): interfaces::Node reception Events ->
# CoinStateMaintainer. Proves the wire_*_ingest() subscriptions fold off the
# real Events (no direct poke), honour dispose(), and reach the embedded
# template. Same header-only link set as the maintainer suite (no NodeImpl
# -> no pool/storage dep).
add_executable(test_dash_node_reception_wire test_dash_node_reception_wire.cpp)
target_link_libraries(test_dash_node_reception_wire PRIVATE
GTest::gtest_main GTest::gtest
dash_x11 core
nlohmann_json::nlohmann_json
${Boost_LIBRARIES}
)
target_link_libraries(test_dash_node_reception_wire PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
gtest_add_tests(test_dash_node_reception_wire "" AUTO)

# DASH CSimplifiedMNListDiff (mnlistdiff wire, S8.1 leaf): vendored diff
# round-trip + dashcore field-layout pin + apply_diff semantics. Header-only
# over the SimplifiedMNList leaf + coin/transaction; no ltc/pool SCC dep.
Expand Down
Loading
Loading