7575#include < impl/dash/coin/tip_ingest.hpp> // wire_tip_ingest (leg 2)
7676#include < impl/dash/coin/block_connect_ingest.hpp> // wire_block_connect_ingest (leg 3)
7777#include < impl/dash/coin/mn_list_ingest.hpp> // wire_mn_list_ingest (leg 4)
78+ #include < impl/dash/coin/govsync_ingest.hpp> // wire_govobject_ingest / wire_govvote_ingest (E-SUPERBLOCK)
79+ #include < impl/dash/coin/superblock.hpp> // get_superblock_payments / superblock_budget (E-SUPERBLOCK)
7880#include < impl/dash/coin/mn_seed.hpp> // E2c: RPC protx-list MN-set seed (parse_protx_list_seed)
7981#include < impl/dash/node.hpp> // dash::Node — sharechain pool-node (NodeBridge<NodeImpl,Legacy,Actual>)
8082#include < impl/dash/config.hpp> // dash::Config (PoolConfig/CoinConfig)
@@ -436,7 +438,8 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
436438 const std::string& external_ip,
437439 const std::string& coin_p2p_magic_hex,
438440 bool force_won_block,
439- const std::string& operator_message_blob_hex)
441+ const std::string& operator_message_blob_hex,
442+ bool embedded_superblock)
440443{
441444 namespace io = boost::asio;
442445
@@ -2202,6 +2205,17 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
22022205 coin_feed_subs.push_back (
22032206 c2pool::dash::wire_mnlistdiff_ingest (coin_state, *maintainer));
22042207
2208+ // Legs 6-7 (E-SUPERBLOCK — DAEMONLESS SUPERBLOCK PAYEE SOURCING): the
2209+ // governance-object + vote feed off the coin-P2P govsync leg. govobj
2210+ // triggers advance the GovernanceStore (winning-trigger schedule);
2211+ // govobjvote funding votes feed the tally (counted only when verified —
2212+ // see the vote-verifier seam below). This is what lets the embedded arm
2213+ // serve a SUPERBLOCK height daemonlessly instead of falling back.
2214+ coin_feed_subs.push_back (
2215+ c2pool::dash::wire_govobject_ingest (coin_state, *maintainer));
2216+ coin_feed_subs.push_back (
2217+ c2pool::dash::wire_govvote_ingest (coin_state, *maintainer));
2218+
22052219 // getmnlistd base tracker: the block hash the local SML is current at.
22062220 // Cold start = ZERO (full snapshot). Each accepted mnlistdiff advances
22072221 // it to diff.blockHash so the NEXT request is an incremental diff off
@@ -2356,6 +2370,78 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
23562370 [sb_cycle](uint32_t next_height) {
23572371 return dash::coin::is_superblock_height (next_height, sb_cycle);
23582372 });
2373+
2374+ // E-SUPERBLOCK: daemonless superblock payee provider. At a superblock
2375+ // height the provider resolves the winning governance trigger's
2376+ // budget-valid (script, amount) schedule from the GovernanceStore the
2377+ // govsync legs (6-7) feed, so the embedded arm can serve the correct
2378+ // superblock coinbase WITHOUT dashd. superblock_schedule() returns
2379+ // nullopt when there is no trigger-confident winner (unfunded OR
2380+ // under-synced OR over-budget OR the R6 desync latch fired) — the
2381+ // NodeCoinState guard then FAILS CLOSED to the reward-safe dashd
2382+ // fallback (never guesses payees).
2383+ //
2384+ // Enabled ONLY under --embedded-superblock (opt-in, default OFF). With
2385+ // it OFF, set_require_superblock_provider(false) preserves the prior
2386+ // reward-safe behaviour EXACTLY (every superblock height falls back).
2387+ //
2388+ // FAIL-CLOSED BY CONSTRUCTION until vote-verify lands, TRIPLY:
2389+ // 1. the funding tally counts only votes the maintainer's
2390+ // vote-verifier accepts — and that verifier is UNSET here.
2391+ // (Follow-up contract: BLS by the voting MN's OPERATOR key
2392+ // over govvote_signature_hash — dashcore verifies TRIGGER
2393+ // funding votes against pubKeyOperator, NOT the
2394+ // ECDSA/keyIDVoting path, which is proposal-only. See
2395+ // CoinStateMaintainer::set_vote_verifier.)
2396+ // 2. the weighted tally needs the vote-weight/membership seam
2397+ // (GovernanceStore::set_vote_weight_fn) — also UNSET here
2398+ // (the DIP-4 SML lacks collateral outpoints; needs the full
2399+ // DMN view).
2400+ // 3. the R5 govsync-completeness gate
2401+ // (set_superblock_sync_complete_fn) is NOT wired — the
2402+ // NodeCoinState guard refuses the serve path structurally,
2403+ // so landing vote-verify alone can never open it.
2404+ // The parse/selection/template-emit logic is proven by the KATs;
2405+ // flipping this fully live is gated on vote-verify + completeness
2406+ // + a funded-superblock soak.
2407+ {
2408+ const int64_t budget_cycle = sb_cycle;
2409+ // Chain-strict trigger parsing + dashcore threshold inputs:
2410+ // min-quorum is chainparams nGovernanceMinQuorum; the
2411+ // threshold itself re-derives from the weighted SML count on
2412+ // every accepted mnlistdiff (maintainer reseed — dashcore
2413+ // nAbsVoteReq = max(minQuorum, weighted/10)). Cross-checkable
2414+ // against dashd getgovernanceinfo.fundingthreshold.
2415+ maintainer->set_gov_params (
2416+ testnet, testnet ? dash::coin::DASH_GOV_MIN_QUORUM_TESTNET
2417+ : dash::coin::DASH_GOV_MIN_QUORUM_MAINNET );
2418+ // Superblock ctx for the R6 coinbase cross-check + executed-
2419+ // cycle pruning on the block-connect leg.
2420+ maintainer->set_superblock_ctx (
2421+ [sb_cycle](uint32_t h) {
2422+ return dash::coin::is_superblock_height (h, sb_cycle);
2423+ },
2424+ [budget_cycle](uint32_t h) {
2425+ return dash::coin::superblock_budget (
2426+ h, static_cast <int >(budget_cycle));
2427+ });
2428+ node_coin_state.set_superblock_provider (
2429+ [maint = maintainer.get ()](uint32_t next_height)
2430+ -> std::optional<std::vector<dash::coin::SuperblockPayment>> {
2431+ return maint->superblock_schedule (next_height);
2432+ });
2433+ node_coin_state.set_require_superblock_provider (embedded_superblock);
2434+ // NOTE deliberately NOT set: set_superblock_sync_complete_fn
2435+ // (R5). Until a govsync-completeness proof exists, superblock
2436+ // heights refuse the embedded arm even with the flag on.
2437+ if (embedded_superblock)
2438+ LOG_INFO << " [E-SUPERBLOCK] daemonless superblock arm ENABLED "
2439+ " (--embedded-superblock); superblock heights served "
2440+ " from govsync triggers when trigger-confident, else "
2441+ " fail closed to dashd. Vote-verify (BLS operator) + "
2442+ " completeness gate pending => currently fails "
2443+ " closed until pinned." ;
2444+ }
23592445 }
23602446
23612447 // E4 re-soak fix (constant −66,966,830-duff creditPool bias): the
@@ -2767,6 +2853,18 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
27672853 auto tip_entry = hc->tip ();
27682854 const uint256 tip = tip_entry ? tip_entry->hash : uint256::ZERO ;
27692855 cp->send_getmnlistd (*sml_base, tip);
2856+ // E-SUPERBLOCK: prime the governance object/vote sync (triggers
2857+ // + funding votes) so a superblock height can be served
2858+ // daemonlessly. Zero nProp + empty filter => request all.
2859+ // Handshake-only today — there is NO tip-change re-prime yet.
2860+ // KNOWN GAP (pre-enable requirement): dashcore answers govsync
2861+ // with INVENTORY (MSG_GOVERNANCE_OBJECT/_VOTE invs), not
2862+ // direct govobj/govobjvote messages, and our inv handler does
2863+ // not getdata governance types — so this leg is currently
2864+ // INERT (an extra fail-closed layer: the store stays empty).
2865+ // The inv-driven getdata + per-object vote sync + periodic
2866+ // re-prime co-land with vote-verify before any enable.
2867+ cp->send_govsync ();
27702868 });
27712869
27722870 std::cout << " [run] E2a live-feed wired: header-chain(" << hdr_db
@@ -3430,6 +3528,7 @@ int main(int argc, char** argv)
34303528 bool embedded_mainnet = false ; // --embedded-mainnet: gate-lift, allow the daemonless embedded template arm on MAINNET (byte-parity proven; default OFF = dashd fallback)
34313529 std::string coin_p2p_magic = " " ; // --coin-p2p-magic HEX: override the embedded CoinClient wire magic (e.g. regtest fcc1b7dc); default mainnet/testnet
34323530 bool force_won_block = false ; // --regtest-force-won-block: fail-closed regtest E5 harness (drive one real won block through the run-path dual-path)
3531+ bool embedded_superblock = false ; // --embedded-superblock: OPT-IN daemonless superblock payee sourcing via govsync (E-SUPERBLOCK); default OFF = superblock heights fall back to dashd (reward-safe)
34333532 std::string stratum_host = " 0.0.0.0" ; // --stratum [HOST:]PORT bind interface (default all)
34343533 uint16_t stratum_port = 0 ; // 0 disables the Stratum accept-loop; --stratum sets it
34353534 bool embedded_utxo = false ; // --embedded-utxo: arm the E2b UTXO/fee lane (opt-in)
@@ -3500,6 +3599,8 @@ int main(int argc, char** argv)
35003599 coin_p2p_magic = argv[++i];
35013600 else if (std::strcmp (argv[i], " --regtest-force-won-block" ) == 0 )
35023601 force_won_block = true ;
3602+ else if (std::strcmp (argv[i], " --embedded-superblock" ) == 0 )
3603+ embedded_superblock = true ;
35033604 else if (std::strcmp (argv[i], " --embedded-utxo" ) == 0 )
35043605 embedded_utxo = true ;
35053606 else if ((std::strcmp (argv[i], " --give-author" ) == 0 ||
@@ -3620,7 +3721,7 @@ int main(int argc, char** argv)
36203721 coin_zmq_hashblock,
36213722 external_ip,
36223723 coin_p2p_magic, force_won_block,
3623- operator_message_blob_hex);
3724+ operator_message_blob_hex, embedded_superblock );
36243725 }
36253726 return run_selftest ();
36263727}
0 commit comments