Skip to content

Commit d5879c9

Browse files
authored
Merge pull request #145 from frstrtr/dgb/land-phaseB-batch
dgb: Phase-B batch land — #132->#142 + test fixtures onto master (CI: -DCOIN_DGB=ON + dgb_share_test)
2 parents bb7ef22 + 7e86ad5 commit d5879c9

16 files changed

Lines changed: 4472 additions & 91 deletions

.github/workflows/build.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
run: conan install . --build=missing --output-folder=build_ci --settings=build_type=Release
4545

4646
- name: Configure
47-
run: cmake -S . -B build_ci -DCMAKE_TOOLCHAIN_FILE=build_ci/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
47+
run: cmake -S . -B build_ci -DCMAKE_TOOLCHAIN_FILE=build_ci/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCOIN_DGB=ON
4848

4949
- name: Build
5050
run: cmake --build build_ci --target c2pool -j$(nproc)
@@ -67,7 +67,7 @@ jobs:
6767
test_phase4_embedded \
6868
test_mweb_builder \
6969
test_address_resolution test_compute_share_target \
70-
test_utxo test_dgb_subsidy \
70+
test_utxo test_dgb_subsidy dgb_share_test \
7171
v37_test \
7272
-j$(nproc)
7373
@@ -171,6 +171,7 @@ jobs:
171171
cmake -S . -B build_asan \
172172
-DCMAKE_TOOLCHAIN_FILE=build_asan/conan_toolchain.cmake \
173173
-DCMAKE_BUILD_TYPE=Release \
174+
-DCOIN_DGB=ON \
174175
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-sanitize=vptr -fno-omit-frame-pointer -fno-sanitize-recover=undefined -g" \
175176
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined -fno-sanitize=vptr" \
176177
-DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=address,undefined -fno-sanitize=vptr"
@@ -193,7 +194,7 @@ jobs:
193194
test_phase4_embedded \
194195
test_mweb_builder \
195196
test_address_resolution test_compute_share_target \
196-
test_utxo test_dgb_subsidy \
197+
test_utxo test_dgb_subsidy dgb_share_test \
197198
test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \
198199
v37_test \
199200
-j$(nproc)

src/c2pool/CMakeLists.txt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,27 @@ target_link_libraries(c2pool-btc
170170
# stratum_server.o, which reference merged/payout/hashrate/ltc symbols (the
171171
# self-link tangle that forces c2pool-btc to drag in ltc/payout/merged) and
172172
# would pull Phase B forward. We therefore add ONLY yaml-cpp (header path).
173-
# Link deps stay at yaml-cpp + json + Boost until Phase B.
173+
# EXE-WIRE slice: main_dgb.cpp drives the LIVE header-only chain-score path
174+
# (dgb::ShareTracker::score, #132/#134) + make_coin_params; it never constructs
175+
# the abstract dgb::NodeImpl, so node.cpp (the run-loop TU that references core
176+
# web_server/stratum -> payout/merged/hashrate/ltc, i.e. the Phase B self-link
177+
# tangle AND merged-mining = DOGE aux, which is NOT in the V36 default DGB
178+
# build) is intentionally NOT compiled in. core is an OBJECT lib (links ALL its
179+
# objects unconditionally, incl. web_server/stratum), so linking it forces that
180+
# whole tangle; we therefore do NOT link core. We compile ONLY core/uint256.cpp
181+
# directly (base_uint symbols the header-only ScoreT/hashrate-hex path needs) -
182+
# additive, no other target touched - and link nothing beyond yaml-cpp(header)/
183+
# json/Boost. Per-coin isolation held. The embedded run-loop (NodeBridge over
184+
# digibyted P2P + Stratum) and its pool-runtime link land in a later Phase B
185+
# slice.
174186
add_executable(c2pool-dgb
175187
main_dgb.cpp
176-
${CMAKE_SOURCE_DIR}/src/impl/dgb/node.cpp
188+
${CMAKE_SOURCE_DIR}/src/core/uint256.cpp
177189
)
178190
target_compile_definitions(c2pool-dgb PRIVATE C2POOL_VERSION="${C2POOL_GIT_VERSION}")
179191
target_link_libraries(c2pool-dgb
180-
yaml-cpp::yaml-cpp # include dir only: config_{coin,pool}.hpp -> core/netaddress.hpp -> <yaml-cpp/yaml.h>
192+
btclibs # STATIC util lib: HexStr/HexDigit (strencodings) for base_uint hex - pure utility, no pool runtime
193+
yaml-cpp::yaml-cpp # config_{coin,pool}.hpp -> core/netaddress.hpp -> <yaml-cpp/yaml.h>
181194
nlohmann_json::nlohmann_json
182195
${Boost_LIBRARIES}
183196
)

src/c2pool/main_dgb.cpp

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,112 @@
11
// c2pool-dgb — DigiByte Scrypt-only (V36) p2pool node entry point.
22
//
3-
// SLICE #4 (Option B): genuinely minimal COMPILING SKELETON. This wires the
4-
// CMake c2pool-dgb target so the binary builds + links off master; it does
5-
// NOT yet run a node. The embedded-daemon + pool/sharechain body is M3 /
6-
// Phase B (DGB = PORT-not-activation; Phase A p2p+mempool already landed under
7-
// impl/dgb/coin/). When the pool-pillars node.cpp lands it replaces the
8-
// skeleton via a clean dgb-only re-cut off master.
3+
// Wires the real dgb sharechain/pool TU (pool pillars + score path, ported from
4+
// LTC under impl/dgb/ across PRs #112/#113/#115/#121/#129/#131/#132/#134) into
5+
// the c2pool-dgb executable. This is the exe-wire slice: it replaces the
6+
// slice-#4 skeleton entry (dgb::run_skeleton/network_summary, removed when #134
7+
// dropped the real node.cpp in) and drives the LIVE chain-score path at
8+
// startup, so the coin smoke gate exercises share_tracker::score() rather than
9+
// merely linking it. node.cpp (the concrete dgb::NodeImpl) is compiled into the
10+
// target so the real node TU links; its full run-loop (NodeBridge over the
11+
// embedded digibyted P2P + Stratum) is a later Phase B slice — dgb::NodeImpl is
12+
// abstract (ICommunicator::handle is supplied by the NodeBridge wrapper), so a
13+
// bare node is not stood up here. The score path lives on dgb::ShareTracker,
14+
// which we drive directly (header-only, no network / no LevelDB).
915
//
1016
// V36 scope: Scrypt blocks validated; the other 4 DGB algos (SHA256d, Skein,
11-
// Qubit, Odocrypt) are accept-by-continuity / ignored — full 5-algo support
12-
// is V37. Compatibility target: frstrtr/p2pool-merged-v36 (share format,
13-
// sharechain rules, PPLNS, Stratum, block submission). See
14-
// c2pool-dgb-embedded-impl-plan.md (frstrtr/the docs/v36).
15-
//
16-
// Mirrors src/c2pool/main_btc.cpp's target shape, pruned to a stub entry.
17+
// Qubit, Odocrypt) are accept-by-continuity / ignored — full 5-algo support is
18+
// V37. Conformance oracle: frstrtr/p2pool-dgb-scrypt (DGB-Scrypt standalone
19+
// parent; merged-v36 byte-compat WAIVED for DGB per operator 2026-06-17).
20+
// CoinParams are oracle-sourced via dgb::make_coin_params (no hardcoded bytes).
21+
// Mirrors src/c2pool/main_btc.cpp's target shape.
1722

1823
#include <impl/dgb/node.hpp>
1924

25+
#include <cstdint>
2026
#include <cstring>
2127
#include <iostream>
28+
#include <string>
2229

2330
#ifndef C2POOL_VERSION
2431
#define C2POOL_VERSION "dev"
2532
#endif
2633

2734
namespace {
2835

29-
void print_banner(const char* argv0)
36+
// Live network summary sourced from the oracle-populated CoinParams
37+
// (make_coin_params) — never a hardcoded string. These are the exact constants
38+
// the sharechain score() consumes (block_period etc.).
39+
std::string network_summary(const core::CoinParams& p)
40+
{
41+
return "DigiByte (Scrypt-only) — identifier=" + p.active_identifier_hex()
42+
+ " prefix=" + p.active_prefix_hex()
43+
+ " block_period=" + std::to_string(p.block_period) + "s"
44+
+ " share_period=" + std::to_string(p.share_period) + "s"
45+
+ " chain_length=" + std::to_string(p.chain_length);
46+
}
47+
48+
void print_banner(const char* argv0, const core::CoinParams& p)
3049
{
3150
std::cout
3251
<< "c2pool-dgb " << C2POOL_VERSION << " — DigiByte Scrypt-only (V36)\n\n"
33-
<< "Usage: " << argv0 << " [--version] [--help]\n\n"
34-
<< "Status: skeleton (slice #4). The node run-loop (embedded daemon +\n"
35-
<< " pool pillars) lands in M3 / Phase B.\n"
36-
<< "Network: " << dgb::network_summary() << "\n";
52+
<< "Usage: " << argv0 << " [--version] [--help] [--selftest]\n\n"
53+
<< "Status: pool/sharechain pillars live (Phase B). The embedded-daemon\n"
54+
<< " run-loop (digibyted P2P + Stratum) lands in a later slice;\n"
55+
<< " external digibyted RPC stays as a fallback.\n"
56+
<< "Network: " << network_summary(p) << "\n";
57+
}
58+
59+
// Drive the LIVE chain-score path: dgb::ShareTracker::score() derives time_span
60+
// from CoinParams::block_period (PR #132) and total_work from the verified
61+
// chain. On an empty verified set score() takes its short-chain early-return,
62+
// but the call EXECUTES the real score() body compiled from the #132/#134
63+
// sharechain TU (not just links it) and reports the oracle block_period it
64+
// consumes. The deep block_period multiply (time_span = confirmations *
65+
// block_period) runs once a verified chain >= chain_length exists — exercised
66+
// by the Phase B share fixtures, not standable-up in a startup smoke.
67+
int run_selftest(const core::CoinParams& params)
68+
{
69+
dgb::ShareTracker tracker;
70+
tracker.m_params = &params; // wiring NodeImpl does at ctor time
71+
72+
// No embedded daemon wired here → block height is "unknown" (0), which
73+
// routes score() through its 1e6-confirmation * block_period fallback.
74+
auto block_rel_height = [](uint256) -> std::int32_t { return 0; };
75+
76+
auto s = tracker.score(uint256::ZERO, block_rel_height);
77+
std::cout << "[selftest] live dgb::ShareTracker constructed; score() driven\n"
78+
<< "[selftest] score(ZERO) -> chain_len=" << s.chain_len
79+
<< " hashrate=" << (s.hashrate.IsNull() ? std::string("0")
80+
: s.hashrate.GetHex()) << "\n"
81+
<< "[selftest] time_span basis block_period=" << params.block_period
82+
<< "s (oracle PARENT.BLOCK_PERIOD, #132 SSOT)\n"
83+
<< "[selftest] OK\n";
84+
return 0;
3785
}
3886

3987
} // namespace
4088

4189
int main(int argc, char** argv)
4290
{
91+
bool want_help = false;
92+
bool want_selftest = false;
4393
for (int i = 1; i < argc; ++i) {
4494
if (std::strcmp(argv[i], "--version") == 0) {
4595
std::cout << "c2pool-dgb " << C2POOL_VERSION << "\n";
4696
return 0;
4797
}
48-
if (std::strcmp(argv[i], "--help") == 0) {
49-
print_banner(argv[0]);
50-
return 0;
51-
}
98+
if (std::strcmp(argv[i], "--help") == 0) want_help = true;
99+
if (std::strcmp(argv[i], "--selftest") == 0) want_selftest = true;
52100
}
53101

54-
print_banner(argv[0]);
55-
return dgb::run_skeleton();
102+
const core::CoinParams params = dgb::make_coin_params(/*testnet=*/false);
103+
print_banner(argv[0], params);
104+
105+
if (want_help)
106+
return 0;
107+
108+
// --selftest, or a bare invocation (no run-loop yet): drive the live score
109+
// path so the binary exercises real consensus code, then exit cleanly.
110+
(void)want_selftest;
111+
return run_selftest(params);
56112
}

src/impl/dgb/CMakeLists.txt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,23 @@
1717
# slice under daemon/. Top-level add_subdirectory(src/impl/dgb) registration
1818
# follows the OBJECT-lib convention PR; held ~2-3 heartbeats, not raced here.
1919
if(COIN_DGB)
20-
message(STATUS "c2pool: DGB Scrypt-only coin module enabled (skeleton)")
20+
message(STATUS "c2pool: DGB Scrypt-only coin module enabled")
2121
add_subdirectory(coin)
2222
# add_subdirectory(daemon)
23-
# add_subdirectory(test)
23+
add_subdirectory(test)
24+
25+
# dgb -- DGB Scrypt pool-layer OBJECT lib. Mirrors the ltc OBJECT lib
26+
# (src/impl/ltc/CMakeLists.txt): compiles the real NodeImpl translation unit
27+
# (node.cpp + protocol handlers) so share_tracker.hpp / share_check.hpp are
28+
# pulled into a compiled TU. Links the shared core / pool / sharechain base
29+
# plus dgb_coin (embedded P2P+mempool) and c2pool_storage (LevelDB sharechain).
30+
add_library(dgb OBJECT
31+
config_coin.hpp config_coin.cpp config_pool.hpp config_pool.cpp
32+
node.hpp node.cpp
33+
peer.hpp
34+
protocol_actual.cpp protocol_legacy.cpp
35+
messages.hpp
36+
share_types.hpp share.hpp
37+
)
38+
target_link_libraries(dgb core pool sharechain dgb_coin btclibs c2pool_storage ${SECP256K1_LIBRARIES})
2439
endif()

src/impl/dgb/config_coin.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "config_coin.hpp"
2+
3+
#include <btclibs/util/strencodings.h>
4+
5+
namespace dgb
6+
{
7+
8+
std::ofstream& CoinConfig::get_default(std::ofstream& file)
9+
{
10+
YAML::Node out;
11+
12+
out["symbol"] = "defaultNet";
13+
out["p2p"] = config::P2PData();
14+
out["rpc"] = config::RPCData();
15+
out["share_period"] = 0;
16+
out["testnet"] = false;
17+
18+
file << out;
19+
return file;
20+
}
21+
22+
void CoinConfig::load()
23+
{
24+
YAML::Node node = YAML::LoadFile(m_filepath.string());
25+
26+
PARSE_CONFIG(node, symbol, std::string);
27+
28+
m_p2p = node["p2p"].as<config::P2PData>();
29+
m_rpc = node["rpc"].as<config::RPCData>();
30+
31+
PARSE_CONFIG(node, share_period, int);
32+
PARSE_CONFIG(node, testnet, bool);
33+
}
34+
35+
} // namespace dgb

src/impl/dgb/config_coin.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#include <core/fileconfig.hpp>
55
#include <core/netaddress.hpp>
66

7+
#include <yaml-cpp/yaml.h>
8+
#include <btclibs/util/strencodings.h>
9+
710
#include <cstdint>
811
#include <algorithm>
912

@@ -25,6 +28,49 @@ namespace config
2528
};
2629

2730
} // config
31+
} // namespace dgb
32+
33+
namespace YAML
34+
{
35+
template<> struct convert<dgb::config::P2PData>
36+
{
37+
static Node encode(const dgb::config::P2PData& rhs)
38+
{
39+
Node node;
40+
node["prefix"] = HexStr(rhs.prefix);
41+
node["address"] = rhs.address;
42+
return node;
43+
}
44+
45+
static bool decode(const Node& node, dgb::config::P2PData& rhs)
46+
{
47+
rhs.prefix = ParseHexBytes(node["prefix"].as<std::string>());
48+
rhs.address = node["address"].as<NetService>();
49+
return true;
50+
}
51+
};
52+
53+
template<> struct convert<dgb::config::RPCData>
54+
{
55+
static Node encode(const dgb::config::RPCData& rhs)
56+
{
57+
Node node;
58+
node["address"] = rhs.address;
59+
node["userpass"] = rhs.userpass;
60+
return node;
61+
}
62+
63+
static bool decode(const Node& node, dgb::config::RPCData& rhs)
64+
{
65+
rhs.address = node["address"].as<NetService>();
66+
rhs.userpass = node["userpass"].as<std::string>();
67+
return true;
68+
}
69+
};
70+
}
71+
72+
namespace dgb
73+
{
2874

2975
/// DigiByte Scrypt coin parameters.
3076
/// Source of truth: p2pool-dgb-scrypt oracle bitcoin/networks/digibyte.py

src/impl/dgb/config_pool.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "config_pool.hpp"
2+
3+
#include <btclibs/util/strencodings.h>
4+
#include <yaml-cpp/yaml.h>
5+
6+
namespace dgb
7+
{
8+
9+
std::ofstream& PoolConfig::get_default(std::ofstream& file)
10+
{
11+
YAML::Node out;
12+
13+
// Use the canonical LTC p2pool mainnet prefix when no prefix is set yet
14+
out["prefix"] = m_prefix.empty() ? DEFAULT_PREFIX_HEX : HexStr(m_prefix);
15+
out["worker"] = m_worker;
16+
17+
YAML::Node addrs_node;
18+
for (const auto& host : DEFAULT_BOOTSTRAP_HOSTS)
19+
addrs_node.push_back(host + ":" + std::to_string(P2P_PORT));
20+
out["bootstrap_addrs"] = addrs_node;
21+
22+
file << out;
23+
return file;
24+
}
25+
26+
void PoolConfig::load()
27+
{
28+
YAML::Node node = YAML::LoadFile(m_filepath.string());
29+
30+
// prefix
31+
m_prefix = ParseHexBytes(node["prefix"].as<std::string>());
32+
33+
PARSE_CONFIG(node, worker, std::string);
34+
35+
// Bootstrap addresses: load from YAML if present, otherwise use hardcoded defaults
36+
if (node["bootstrap_addrs"] && node["bootstrap_addrs"].IsSequence())
37+
{
38+
for (const auto& item : node["bootstrap_addrs"])
39+
m_bootstrap_addrs.emplace_back(item.as<std::string>());
40+
}
41+
else
42+
{
43+
for (const auto& host : DEFAULT_BOOTSTRAP_HOSTS)
44+
m_bootstrap_addrs.emplace_back(host + ":" + std::to_string(P2P_PORT));
45+
}
46+
}
47+
48+
} // namespace dgb

0 commit comments

Comments
 (0)