Skip to content

Commit 40a55af

Browse files
committed
dgb(coin): concrete ICoinNode + minimal rpc layer for family-1 WorkView seam
Path A minimal-stub surface for the c2pool-dgb family-1 bind, mirroring the btc coin layer (2-arg no-MWEB submit shape): - rpc_data.hpp: rpc::WorkData (m_data/m_hashes/m_latency; m_txs deferred until the DGB transaction port lands with M3) - rpc.hpp: NodeRPC stub -- getwork() throws (ICoinNode no-template contract), submit_block_hex(str, bool) returns false; real transport is an M3 body-only swap - node_interface.hpp: dgb::interfaces::Node shared-state surface (work variable + new_block event) - node.hpp: per-coin Node owner (NodeRPC only; P2P deferred to M3) - coin_node.{hpp,cpp}: concrete dgb::coin::CoinNode : core::coin::ICoinNode; full WorkData retained coin-side, agnostic WorkView slice crosses the seam - template_builder.hpp: CoinNodeInterface trimmed mirror (submit_block deferred with the block.hpp port) - coin/CMakeLists.txt: dgb_coin lib staged; NOT registered -- top-level wiring follows the OBJECT-lib convention, so this commit is build-inert V36 scope: DGB validates Scrypt only; other algos accept-by-continuity or ignored. Touches src/impl/dgb/ only; zero lines of the #69 adapter/seam surface.
1 parent 48dd2bc commit 40a55af

8 files changed

Lines changed: 416 additions & 4 deletions

File tree

src/impl/dgb/coin/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# dgb_coin -- DGB coin-layer library (Path A minimal-stub surface).
2+
# Mirrors src/impl/btc/coin/CMakeLists.txt, listing only the files that exist
3+
# at this milestone. NOT yet referenced by any add_subdirectory(): top-level
4+
# registration of src/impl/dgb follows the ci-steward OBJECT-lib convention
5+
# (see ../CMakeLists.txt); staged here so that wiring is a one-line flip.
6+
7+
set(dgb_coin_impl
8+
rpc_data.hpp
9+
rpc.hpp
10+
node.hpp
11+
coin_node.hpp coin_node.cpp
12+
)
13+
14+
set(dgb_coin_interface
15+
node_interface.hpp
16+
header_chain.hpp
17+
template_builder.hpp
18+
)
19+
20+
add_library(dgb_coin ${dgb_coin_interface} ${dgb_coin_impl})
21+
22+
target_link_libraries(dgb_coin core nlohmann_json::nlohmann_json)

src/impl/dgb/coin/coin_node.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "coin_node.hpp"
2+
3+
#include <stdexcept>
4+
#include <utility>
5+
6+
namespace dgb
7+
{
8+
9+
namespace coin
10+
{
11+
12+
core::coin::WorkView CoinNode::get_work_view()
13+
{
14+
// No work source configured at all -> empty view (1:1 with the btc/ltc
15+
// reference).
16+
if (!m_embedded && !m_rpc)
17+
return {};
18+
19+
// Embedded preferred, external RPC fallback. getwork() throws
20+
// std::runtime_error when no template can be produced -- propagated to the
21+
// caller (web_server), matching the ICoinNode contract. On DGB Path A both
22+
// sources are stubs, so this path always throws until M3 lands a real one.
23+
rpc::WorkData wd = m_embedded ? m_embedded->getwork() : m_rpc->getwork();
24+
25+
// Retain the FULL WorkData coin-side. Variable::set takes its argument BY
26+
// VALUE, so this copies wd; sequenced BEFORE the std::move()s below so the
27+
// copy completes first -- never move out of wd beforehand.
28+
work.set(wd);
29+
30+
core::coin::WorkView v;
31+
v.m_data = std::move(wd.m_data);
32+
v.m_hashes = std::move(wd.m_hashes);
33+
v.m_latency = wd.m_latency;
34+
return v;
35+
}
36+
37+
bool CoinNode::submit_block_hex(const std::string& block_hex, bool ignore_failure)
38+
{
39+
// Guard sits ahead of the submit: in embedded-preferred mode m_rpc can be
40+
// null. Returning false is the correct "no RPC sink" result.
41+
if (!m_rpc)
42+
return false;
43+
44+
// DGB's NodeRPC::submit_block_hex is already the agnostic 2-arg/no-mweb
45+
// form (MWEB is LTC-specific and absent here), so we forward directly.
46+
return m_rpc->submit_block_hex(block_hex, ignore_failure);
47+
}
48+
49+
} // namespace coin
50+
51+
} // namespace dgb

src/impl/dgb/coin/coin_node.hpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#pragma once
2+
3+
// ---------------------------------------------------------------------------
4+
// dgb::coin::CoinNode -- concrete core::coin::ICoinNode for DGB (family-1 P2
5+
// WorkView seam, Path A minimal-stub). 1:1 mirror of btc::coin::CoinNode
6+
// (src/impl/btc/coin/coin_node.{hpp,cpp}), which is itself member-mapped from
7+
// the ltc::coin::CoinNode reference -- the control flow / sequencing are the
8+
// load-bearing part and are preserved verbatim:
9+
// m_embedded : CoinNodeInterface* -- embedded in-process source
10+
// m_rpc : NodeRPC* -- external coin-RPC client (STUB)
11+
// work : Variable<rpc::WorkData> -- full per-coin WorkData kept
12+
// coin-side; only the agnostic
13+
// WorkView slice crosses the seam
14+
//
15+
// DGB Path A status: both work sources behind this adapter are stubs --
16+
// NodeRPC throws on getwork() (rpc.hpp) and no EmbeddedCoinNode exists until
17+
// the M3 daemon slice -- so a wired DGB node reports "no template" loudly
18+
// through the ICoinNode contract rather than fabricating work. The adapter
19+
// itself is COMPLETE: when either source becomes real, no seam-side change
20+
// is needed.
21+
//
22+
// Build-INERT: defines the type; NOT yet wired into web_server or a
23+
// main_dgb.cpp (no such binary split exists yet). Registration follows the
24+
// ci-steward OBJECT-lib convention; see src/impl/dgb/CMakeLists.txt.
25+
// ---------------------------------------------------------------------------
26+
27+
#include <string>
28+
29+
#include <core/coin/node_iface.hpp>
30+
#include <core/coin/work_view.hpp>
31+
#include <core/events.hpp>
32+
33+
#include "rpc.hpp"
34+
#include "rpc_data.hpp"
35+
#include "template_builder.hpp"
36+
37+
namespace dgb
38+
{
39+
40+
namespace coin
41+
{
42+
43+
class CoinNode : public core::coin::ICoinNode
44+
{
45+
// Embedded in-process template source (EmbeddedCoinNode, M3). May be null
46+
// when the node runs RPC-only. is_embedded() reports its presence.
47+
CoinNodeInterface* m_embedded = nullptr;
48+
49+
// External coin-RPC client. May be null in embedded-preferred mode; it is
50+
// the sole sink for submit_block_hex(). has_rpc() reports its presence.
51+
NodeRPC* m_rpc = nullptr;
52+
53+
// Full per-coin WorkData retained coin-side via work.set(wd); only the
54+
// agnostic WorkView slice crosses the seam into core/web_server.
55+
Variable<rpc::WorkData> work;
56+
57+
public:
58+
CoinNode(CoinNodeInterface* embedded, NodeRPC* rpc)
59+
: m_embedded(embedded), m_rpc(rpc) {}
60+
61+
core::coin::WorkView get_work_view() override;
62+
bool submit_block_hex(const std::string& block_hex, bool ignore_failure) override;
63+
64+
bool is_embedded() const override { return m_embedded != nullptr; }
65+
bool has_rpc() const override { return m_rpc != nullptr; }
66+
};
67+
68+
} // namespace coin
69+
70+
} // namespace dgb

src/impl/dgb/coin/node.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#pragma once
2+
3+
// ---------------------------------------------------------------------------
4+
// dgb::coin::Node -- per-coin node owner (Path A minimal-stub). TRIMMED mirror
5+
// of src/impl/btc/coin/node.hpp: owns the NodeRPC client and inherits the
6+
// dgb::interfaces::Node shared-state surface (work variable + new_block
7+
// event) that NodeRPC and the seam-side CoinNode bind against.
8+
//
9+
// Deliberately ABSENT until M3 (each needs a port dgb does not have yet):
10+
// - NodeP2P / p2p_connection (coin P2P block relay; btc's p2p_node.hpp)
11+
// - init_rpc() transport connect (NodeRPC is a stub with no transport)
12+
// - submit_block_p2p / send_getheaders / handshake surface
13+
// The ctor keeps btc's (context, config) shape via auto params (no boost
14+
// include needed in the stub) so M3 restores the body without re-typing
15+
// construction sites.
16+
// ---------------------------------------------------------------------------
17+
18+
#include <memory>
19+
20+
#include "node_interface.hpp"
21+
#include "rpc.hpp"
22+
23+
namespace dgb
24+
{
25+
26+
namespace coin
27+
{
28+
29+
template <typename ConfigType>
30+
class Node : public dgb::interfaces::Node
31+
{
32+
using config_t = ConfigType;
33+
34+
config_t* m_config = nullptr;
35+
36+
std::unique_ptr<NodeRPC> m_rpc;
37+
38+
public:
39+
Node(auto* /*context*/, auto* config) : m_config(config)
40+
{
41+
}
42+
43+
void run()
44+
{
45+
// Stub NodeRPC: constructed so has-rpc presence wiring can be
46+
// exercised, but no transport connect until M3.
47+
m_rpc = std::make_unique<NodeRPC>(this);
48+
}
49+
50+
NodeRPC* rpc() { return m_rpc.get(); }
51+
};
52+
53+
} // namespace coin
54+
55+
} // namespace dgb
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
// ---------------------------------------------------------------------------
4+
// dgb::interfaces::Node -- coin-node shared-state surface (Path A
5+
// minimal-stub). Mirrors src/impl/btc/coin/node_interface.hpp TRIMMED to the
6+
// members the family-1 ICoinNode seam actually binds today:
7+
//
8+
// work : Variable<rpc::WorkData> -- get_work result (NodeRPC fills,
9+
// CoinNode retains coin-side per the WorkView seam contract)
10+
// new_block : Event<uint256> -- block-hash announce (header-chain
11+
// feed; uint256 only, no per-coin type needed)
12+
//
13+
// Deliberately ABSENT until the M3 type ports land (each pulls a type dgb
14+
// does not have yet): Event<Transaction> new_tx, Event<vector<
15+
// BlockHeaderType>> new_headers, Event<BlockType> full_block, TXIDCache
16+
// txidcache, known_txs map. Restoring them is additive; nothing in the seam
17+
// depends on their absence.
18+
// ---------------------------------------------------------------------------
19+
20+
#include <core/events.hpp>
21+
#include <core/uint256.hpp>
22+
23+
#include "rpc_data.hpp"
24+
25+
namespace dgb
26+
{
27+
28+
namespace interfaces
29+
{
30+
31+
struct Node
32+
{
33+
Variable<dgb::coin::rpc::WorkData> work; // get_work result
34+
Event<uint256> new_block; // block_hash
35+
};
36+
37+
} // namespace interfaces
38+
39+
} // namespace dgb

src/impl/dgb/coin/rpc.hpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
3+
// ---------------------------------------------------------------------------
4+
// dgb::coin::NodeRPC -- external coin-RPC client STUB (Path A minimal-stub,
5+
// "rpc stubs" scope item).
6+
//
7+
// btc/ltc NodeRPC is a boost::beast + jsonrpccxx HTTP JSON-RPC client whose
8+
// header drags in block.hpp / transaction.hpp -- types dgb does not port
9+
// until M3. This stub keeps the call surface coin_node.cpp and coin/node.hpp
10+
// consume, with no transport behind it:
11+
//
12+
// getwork() -> throws std::runtime_error. This is the ICoinNode
13+
// contract for "no template available" -- web_server
14+
// already handles the throw, so a wired-but-stub DGB
15+
// node degrades loudly, not silently.
16+
// submit_block_hex() -> false ("no RPC sink"; the same result the null-
17+
// m_rpc guard in CoinNode::submit_block_hex yields).
18+
// check() -> false (never connected).
19+
//
20+
// connect()/reconnect()/the RPC method set (getblocktemplate etc.) arrive
21+
// with the real transport in M3 as a body-only swap mirroring
22+
// src/impl/btc/coin/rpc.{hpp,cpp}; DGB's getblocktemplate call passes
23+
// rules=["scrypt"] per the Scrypt GBT filter point (template_builder.hpp,
24+
// impl plan section 3) so only Scrypt-eligible templates are returned.
25+
// ---------------------------------------------------------------------------
26+
27+
#include <stdexcept>
28+
#include <string>
29+
30+
#include "node_interface.hpp"
31+
#include "rpc_data.hpp"
32+
33+
namespace dgb
34+
{
35+
36+
namespace coin
37+
{
38+
39+
class NodeRPC
40+
{
41+
// Shared-state surface the real client fills (work variable); the stub
42+
// holds the pointer so the M3 swap does not change construction sites.
43+
dgb::interfaces::Node* m_coin = nullptr;
44+
45+
public:
46+
explicit NodeRPC(dgb::interfaces::Node* coin = nullptr) : m_coin(coin) {}
47+
48+
// Never connected: no transport in the stub.
49+
bool check() const { return false; }
50+
51+
rpc::WorkData getwork()
52+
{
53+
throw std::runtime_error(
54+
"dgb: NodeRPC is a Path A stub -- no external RPC transport until M3");
55+
}
56+
57+
bool submit_block_hex(const std::string& /*block_hex*/, bool /*ignore_failure*/)
58+
{
59+
return false;
60+
}
61+
};
62+
63+
} // namespace coin
64+
65+
} // namespace dgb

src/impl/dgb/coin/rpc_data.hpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
3+
// ---------------------------------------------------------------------------
4+
// dgb::coin::rpc::WorkData -- per-coin work payload for the family-1 P2
5+
// WorkView seam (Path A minimal-stub).
6+
//
7+
// Mirrors src/impl/btc/coin/rpc_data.hpp with ONE deliberate trim: btc's
8+
// WorkData carries std::vector<Transaction> m_txs, but DGB has no
9+
// coin/transaction.{hpp,cpp} port yet -- that lands with the M3 embedded
10+
// daemon slice. The ICoinNode seam contract makes the trim safe: web_server
11+
// consumes ONLY the agnostic slice (m_data/m_hashes/m_latency); the full
12+
// per-coin WorkData (incl. txs) never crosses the seam
13+
// (src/core/coin/node_iface.hpp). When the DGB transaction port lands, m_txs
14+
// is restored here and the coin-side work.set(wd) retention in
15+
// CoinNode::get_work_view() carries it without any seam change.
16+
//
17+
// V36 master compat: field semantics match p2pool-merged-v36 getwork result
18+
// (data / txhashes / latency); impl plan section 3 (frstrtr/the, 8ef8d2d).
19+
// ---------------------------------------------------------------------------
20+
21+
#include <ctime>
22+
#include <utility>
23+
#include <vector>
24+
25+
#include <core/uint256.hpp>
26+
27+
#include <nlohmann/json.hpp>
28+
29+
namespace dgb
30+
{
31+
32+
namespace coin
33+
{
34+
35+
namespace rpc
36+
{
37+
38+
struct WorkData
39+
{
40+
nlohmann::json m_data;
41+
std::vector<uint256> m_hashes; // transaction hashes
42+
time_t m_latency = 0;
43+
44+
// TODO(M3): std::vector<Transaction> m_txs once coin/transaction.{hpp,cpp}
45+
// is ported (DGB txs are bitcoin-family; expected near-verbatim from btc's
46+
// port). Kept out of the stub so the rpc chain compiles without the
47+
// Transaction/Block types dgb does not have yet.
48+
49+
WorkData() {}
50+
WorkData(nlohmann::json data, std::vector<uint256> txhashes, time_t latency)
51+
: m_data(std::move(data)), m_hashes(std::move(txhashes)), m_latency(latency)
52+
{
53+
}
54+
55+
bool operator==(const WorkData& rhs) const { return m_data == rhs.m_data; }
56+
bool operator!=(const WorkData& rhs) const { return !(*this == rhs); }
57+
};
58+
59+
} // namespace rpc
60+
61+
} // namespace coin
62+
63+
} // namespace dgb

0 commit comments

Comments
 (0)