|
| 1 | +// SPDX-License-Identifier: AGPL-3.0-or-later |
| 2 | +#pragma once |
| 3 | + |
| 4 | +/// Phase C-TEMPLATE step 6 (S8 embedded_gbt live-wire, follow-on to #672): |
| 5 | +/// the node-held embedded coin-state bundle that flips select_dash_work()'s |
| 6 | +/// hot arm live. |
| 7 | +/// |
| 8 | +/// #672 landed select_dash_work() (work_source.hpp) as the stable branch |
| 9 | +/// point, but every caller still presents has_state=false, so 100% of the |
| 10 | +/// running node's get_work path routes to the retained dashd |
| 11 | +/// getblocktemplate fallback. This holder is the in-process coin-state the |
| 12 | +/// DASH node maintains as mnlistdiff / mempool / header-tip updates arrive -- |
| 13 | +/// masternode list + mempool + header-tip params. make_embedded_work_inputs() |
| 14 | +/// presents it as a viable() EmbeddedWorkInputs so select_dash_work() takes |
| 15 | +/// the oracle-parity embedded path (build_embedded_workdata, pinned by |
| 16 | +/// test_dash_embedded_gbt vs frstrtr/p2pool-dash getwork()). |
| 17 | +/// |
| 18 | +/// STRICTLY single-coin: src/impl/dash/ only, no bitcoin_family / src/core |
| 19 | +/// reach. The external-daemon (dashd RPC) arm is NEVER removed -- populated() |
| 20 | +/// == false always routes there, and it remains the [GBT-XCHECK] cross-check. |
| 21 | + |
| 22 | +#include <impl/dash/coin/work_source.hpp> // EmbeddedWorkInputs, select_dash_work, WorkSelection |
| 23 | +#include <impl/dash/coin/mn_state_machine.hpp> // MnStateMachine |
| 24 | +#include <impl/dash/coin/mempool.hpp> // Mempool |
| 25 | +#include <impl/dash/coin/rpc_data.hpp> // DashWorkData |
| 26 | + |
| 27 | +#include <core/uint256.hpp> |
| 28 | + |
| 29 | +#include <cstdint> |
| 30 | +#include <functional> |
| 31 | + |
| 32 | +namespace dash { |
| 33 | +namespace coin { |
| 34 | + |
| 35 | +/// In-process coin-state the running node maintains for LOCAL template |
| 36 | +/// assembly. Non-copyable: it owns a Mempool (itself non-copyable) and is |
| 37 | +/// node-owned, never duplicated. The maintainer mutates mnstates()/mempool() |
| 38 | +/// in place and calls set_tip() once the tip advances; get_work reads it |
| 39 | +/// through select_work(). |
| 40 | +class NodeCoinState { |
| 41 | +public: |
| 42 | + NodeCoinState() = default; |
| 43 | + NodeCoinState(const NodeCoinState&) = delete; |
| 44 | + NodeCoinState& operator=(const NodeCoinState&) = delete; |
| 45 | + |
| 46 | + // Mutable accessors for the maintainer (the reception / think slices seed |
| 47 | + // these from mnlistdiff + relayed mempool txs). |
| 48 | + MnStateMachine& mnstates() { return m_mnstates; } |
| 49 | + Mempool& mempool() { return m_mempool; } |
| 50 | + |
| 51 | + /// Record the header-tip parameters and mark the bundle live. Call after |
| 52 | + /// the tip advances AND the MN list + mempool are seeded; until then the |
| 53 | + /// selector must route to the dashd fallback. curtime/version left 0 use |
| 54 | + /// build_embedded_workdata()'s own SAFE-ADDITIVE defaults. |
| 55 | + void set_tip(uint32_t prev_height, const uint256& prev_hash, |
| 56 | + uint32_t bits_for_next, uint32_t mtp_at_tip, |
| 57 | + uint8_t address_version, uint8_t address_p2sh_version, |
| 58 | + uint32_t curtime = 0, uint32_t version = 0) { |
| 59 | + m_prev_height = prev_height; |
| 60 | + m_prev_hash = prev_hash; |
| 61 | + m_bits_for_next = bits_for_next; |
| 62 | + m_mtp_at_tip = mtp_at_tip; |
| 63 | + m_address_version = address_version; |
| 64 | + m_address_p2sh_version = address_p2sh_version; |
| 65 | + m_curtime = curtime; |
| 66 | + m_version = version; |
| 67 | + m_populated = true; |
| 68 | + } |
| 69 | + |
| 70 | + /// Invalidate the bundle (reorg / mempool flush / MN list gap) so the next |
| 71 | + /// get_work falls back to dashd until the state is rebuilt. |
| 72 | + void invalidate() { m_populated = false; } |
| 73 | + |
| 74 | + bool populated() const { return m_populated; } |
| 75 | + |
| 76 | + /// Assemble the selector input. has_state is populated(); the two required |
| 77 | + /// pointers are always non-null (members), so viable() reduces to |
| 78 | + /// populated() -- exactly the semantics work_source.hpp documents. |
| 79 | + EmbeddedWorkInputs make_embedded_work_inputs() const { |
| 80 | + EmbeddedWorkInputs e; |
| 81 | + e.has_state = m_populated; |
| 82 | + e.prev_height = m_prev_height; |
| 83 | + e.prev_hash = m_prev_hash; |
| 84 | + e.mnstates = &m_mnstates; |
| 85 | + e.mempool = &m_mempool; |
| 86 | + e.bits_for_next = m_bits_for_next; |
| 87 | + e.mtp_at_tip = m_mtp_at_tip; |
| 88 | + e.address_version = m_address_version; |
| 89 | + e.address_p2sh_version = m_address_p2sh_version; |
| 90 | + e.curtime = m_curtime; |
| 91 | + e.version = m_version; |
| 92 | + return e; |
| 93 | + } |
| 94 | + |
| 95 | + /// Live get_work entry point: prefer the locally-assembled embedded |
| 96 | + /// template when this bundle is populated, else the supplied dashd |
| 97 | + /// getblocktemplate fallback. Thin wrapper over select_dash_work() so the |
| 98 | + /// node call site is one line. dashd_fallback is REQUIRED -- it is the |
| 99 | + /// always-reachable safety path and the cross-check arm. |
| 100 | + WorkSelection select_work( |
| 101 | + const std::function<DashWorkData()>& dashd_fallback) const { |
| 102 | + return select_dash_work(make_embedded_work_inputs(), dashd_fallback); |
| 103 | + } |
| 104 | + |
| 105 | +private: |
| 106 | + MnStateMachine m_mnstates; |
| 107 | + Mempool m_mempool; |
| 108 | + uint32_t m_prev_height{0}; |
| 109 | + uint256 m_prev_hash; |
| 110 | + uint32_t m_bits_for_next{0}; |
| 111 | + uint32_t m_mtp_at_tip{0}; |
| 112 | + uint8_t m_address_version{0}; |
| 113 | + uint8_t m_address_p2sh_version{0}; |
| 114 | + uint32_t m_curtime{0}; |
| 115 | + uint32_t m_version{0}; |
| 116 | + bool m_populated{false}; |
| 117 | +}; |
| 118 | + |
| 119 | +} // namespace coin |
| 120 | +} // namespace dash |
0 commit comments