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 @@ -114,7 +114,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_coinbase_muldiv 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_dash_get_work test_dash_stratum_work_source \
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_underfill_guard 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_coinbase_muldiv 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_dash_get_work test_dash_stratum_work_source \
test_multiaddress_pplns test_pplns_stress \
test_hash_link test_decay_pplns \
test_pplns_consensus \
Expand Down Expand Up @@ -272,7 +272,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_coinbase_muldiv 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_dash_get_work test_dash_stratum_work_source \
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_underfill_guard 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_coinbase_muldiv 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_dash_get_work test_dash_stratum_work_source \
test_hash_link test_decay_pplns \
test_pplns_consensus \
test_v36_script_sorting test_v36_cross_impl_refhash \
Expand Down
65 changes: 64 additions & 1 deletion src/impl/dash/coin/embedded_gbt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@
namespace dash {
namespace coin {

// ── Underfill guard (v36 cutover deploy path) ───────────────────────────────
// Port of the LTC/DOGE template-builder guard (src/impl/ltc/coin/
// template_builder.hpp, src/impl/doge/coin/template_builder.hpp) to the DASH
// embedded GBT path. Detects the "near-empty template on a non-empty mempool"
// regression: the tx selector returns almost no transactions even though the
// local mempool holds a substantial fee-paying backlog. c2pool-side
// template-fill safety net — NOT the byte-parity KAT axis; thresholds are the
// v36-native shared structure (bucket-2, standardize cross-coin) pinned to
// the legacy p2pool near-empty floor (~50 kB), identical to LTC/DOGE.
// DASH counts base_size bytes (no segwit), so "bytes" here are the same
// serialized-tx bytes the mempool byte cap and dashcore's 2 MB limit count.
inline constexpr uint64_t UNDERFILL_MIN_FILL_BYTES = 50'000ull; // < this = near-empty block
inline constexpr uint64_t UNDERFILL_BACKLOG_SLACK = 50'000ull; // unselected fee-paying material that should have filled it

/// Pure trip predicate — the exact boolean the LTC/DOGE guards evaluate.
/// Factored out so the KAT can pin it without a log scraper:
/// near_empty : template packed fewer bytes than the near-empty floor
/// has_backlog : the mempool holds fee-paying material (known fees > 0)
/// well beyond what was selected (> selected + slack)
/// Genuinely empty (or fee-unknown-only) mempools never trip.
inline bool underfill_guard_trips(uint64_t selected_bytes,
uint64_t mempool_bytes,
uint64_t mempool_known_fees)
{
const bool near_empty = selected_bytes < UNDERFILL_MIN_FILL_BYTES;
const bool has_backlog = mempool_known_fees > 0
&& mempool_bytes > selected_bytes + UNDERFILL_BACKLOG_SLACK;
return near_empty && has_backlog;
}

/// Build the GBT-equivalent fields we currently know how to compute
/// for a block at height (prev_height+1). Returns a partially-filled
/// DashWorkData; missing fields documented above.
Expand All @@ -73,7 +103,13 @@ inline DashWorkData build_embedded_workdata(
// unchanged (SAFE-ADDITIVE); the G1 golden KAT pins it, and a real
// BIP9-deployment-aware value can later be threaded in without touching
// the default header projection.
uint32_t version = 0x20000000u)
uint32_t version = 0x20000000u,
// Seam: optional underfill-guard observation point. Defaults to nullptr so
// every existing caller is byte-for-byte unchanged (SAFE-ADDITIVE); the
// guard KAT passes a bool to pin the wiring without a log scraper. The
// guard itself is log-only (WARNING), exactly like LTC/DOGE — it never
// alters the template.
bool* underfill_tripped = nullptr)
{
DashWorkData w;
w.m_height = prev_height + 1;
Expand Down Expand Up @@ -104,12 +140,39 @@ inline DashWorkData build_embedded_workdata(
w.m_txs.reserve(selected.size());
w.m_tx_hashes.reserve(selected.size());
w.m_tx_fees.reserve(selected.size());
uint64_t selected_bytes = 0; // wire bytes packed into this template (underfill guard)
for (auto& s : selected) {
selected_bytes += s.base_size;
w.m_txs.emplace_back(s.tx);
w.m_tx_hashes.push_back(dash::coin::dash_txid(s.tx));
w.m_tx_fees.push_back(s.fee);
}

// ── Underfill guard ─────────────────────────────────────────────
// Do not silently treat a near-empty DASH template as healthy when the
// DASH mempool held fee-paying backlog that should have filled it. We
// cannot fabricate transactions, so surface loudly (WARNING) for
// contabo-prod-watch / the operator rather than shipping a false-empty
// block as normal. Genuinely empty mempools never trip. Mirrors the
// LTC/DOGE TemplateBuilder guard; additive only — masternode payment /
// CbTx / superblock projection below is untouched either way.
{
const uint64_t mempool_bytes = static_cast<uint64_t>(mempool.byte_size());
const uint64_t mempool_fees = mempool.total_known_fees();
const bool tripped = underfill_guard_trips(selected_bytes,
mempool_bytes,
mempool_fees);
if (underfill_tripped) *underfill_tripped = tripped;
if (tripped) {
LOG_WARNING << "[GBT-EMB] UNDERFILL: selected "
<< selected.size() << " tx / " << selected_bytes
<< "B into template while mempool holds " << mempool.size()
<< " tx / " << mempool_bytes << "B (" << mempool_fees
<< " sat fees) — near-empty block on a non-empty "
<< "mempool; template-fill regression, gates cutover.";
}
}

// Platform Credit Pool burn (DIP-0027): emit OP_RETURN payment
// FIRST (matches dashcore GetBlockTxOuts ordering at payments.cpp:55).
// Payee uses the "!hex" raw-script convention; OP_RETURN single byte = 0x6a.
Expand Down
17 changes: 17 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,23 @@ if (BUILD_TESTING AND GTest_FOUND)
target_link_libraries(test_dash_embedded_gbt PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
gtest_add_tests(test_dash_embedded_gbt "" AUTO)

# DASH underfill guard: port of the LTC/DOGE "near-empty template on a
# non-empty mempool" template-builder guard to the DASH embedded GBT path
# (embedded_gbt.hpp), for the mining-hotel deployment. Predicate KATs at
# the pinned 50 kB floor/slack + build_embedded_workdata wiring via the
# SAFE-ADDITIVE underfill_tripped seam (log-only guard; masternode
# burn/payee projection asserted unchanged). Same link set as the
# embedded_gbt capstone.
add_executable(test_dash_underfill_guard test_dash_underfill_guard.cpp)
target_link_libraries(test_dash_underfill_guard PRIVATE
GTest::gtest_main GTest::gtest
dash_x11 core
nlohmann_json::nlohmann_json
${Boost_LIBRARIES}
)
target_link_libraries(test_dash_underfill_guard PRIVATE c2pool_payout c2pool_hashrate c2pool_merged_mining) # OBJECT-lib SCC direct-naming (#22/#39)
gtest_add_tests(test_dash_underfill_guard "" AUTO)

# DASH embedded-vs-dashd work-source selector (S8 embedded_gbt live-wire
# capstone): select_dash_work() prefers the locally-assembled embedded
# template (build_embedded_workdata) and falls back to dashd
Expand Down
Loading
Loading