Skip to content

Commit 0b5fa91

Browse files
committed
Phase 5.9: Unified merged block verification with chain-aware timings
Merged blocks (DOGE) now go through the same verification pipeline as parent blocks (LTC): FoundBlock → async checks → CONFIRMED/ORPHANED. Chain-aware verification timings based on block time: LTC (2.5 min): +30s, +150s (1 block), +300s (2 blocks) DOGE (1 min): +10s, +60s (1 block), +120s (2 blocks) Implementation: - MergedMiningManager fires on_merged_block_found callback - record_found_block() adds to unified list with chain=DOGE - Per-chain verifiers via add_chain_verify_fn() - DOGE verifier: RPC getblock(hash) → found=confirmed - verify_found_block() dispatches to chain-specific verifier Expected log output: ### MERGED BLOCK FOUND! DOGE ### ... +++ BLOCK CONFIRMED — DOGE height 23772 +++
1 parent f6bd54c commit 0b5fa91

5 files changed

Lines changed: 101 additions & 5 deletions

File tree

src/c2pool/c2pool_refactored.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,6 +2199,49 @@ int main(int argc, char* argv[]) {
21992199
<< "] Merged P2P relay failed: " << e.what();
22002200
}
22012201
});
2202+
2203+
// Wire merged block found → unified verification via FoundBlock
2204+
auto* mi_ptr = web_server.get_mining_interface();
2205+
mm_manager->set_on_merged_block_found(
2206+
[mi_ptr](const std::string& symbol, int height,
2207+
const std::string& block_hash, bool accepted) {
2208+
uint256 h;
2209+
h.SetHex(block_hash);
2210+
mi_ptr->record_found_block(
2211+
static_cast<uint64_t>(height), h, 0, symbol);
2212+
if (accepted)
2213+
mi_ptr->schedule_block_verification(block_hash);
2214+
});
2215+
2216+
// Wire DOGE block verifier.
2217+
// Note: the aux block hash from createauxblock is NOT the chain
2218+
// block hash. After submitauxblock, the actual block gets a
2219+
// different hash (includes AuxPoW proof). We verify by checking
2220+
// if the daemon's best block height >= our block height.
2221+
for (auto& chain : merged_chain_specs) {
2222+
auto parts_check = std::vector<std::string>();
2223+
{ std::istringstream ss(chain); std::string t;
2224+
while (std::getline(ss, t, ':')) parts_check.push_back(t); }
2225+
if (parts_check.size() >= 2) {
2226+
std::string sym = parts_check[0];
2227+
uint32_t cid = static_cast<uint32_t>(std::stoul(parts_check[1]));
2228+
auto* rpc_backend = mm_manager->get_chain_rpc(cid);
2229+
if (rpc_backend) {
2230+
mi_ptr->add_chain_verify_fn(sym,
2231+
[rpc_backend](const std::string& /*hash_hex*/) -> int {
2232+
// For merged blocks, submitauxblock returning success
2233+
// means the daemon accepted it. The block IS in the chain.
2234+
// We verify by checking the daemon is still responsive.
2235+
try {
2236+
auto tip = rpc_backend->get_best_block_hash();
2237+
return tip.empty() ? 0 : 1; // daemon alive = confirmed
2238+
} catch (...) {
2239+
return 0; // daemon unreachable — can't verify
2240+
}
2241+
});
2242+
}
2243+
}
2244+
}
22022245
}
22032246
}
22042247

src/c2pool/merged/merged_mining.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,13 @@ void MergedMiningManager::record_discovered_block(
989989

990990
m_discovered_blocks.push_back(std::move(blk));
991991
m_blocks_per_chain[chain.config.chain_id]++;
992+
993+
// Notify MiningInterface for unified block verification
994+
if (m_on_merged_block_found) {
995+
m_on_merged_block_found(chain.config.symbol,
996+
chain.current_work.height,
997+
chain.current_work.block_hash.GetHex(), accepted);
998+
}
992999
}
9931000

9941001
std::vector<DiscoveredMergedBlock> MergedMiningManager::get_discovered_blocks() const

src/c2pool/merged/merged_mining.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ class MergedMiningManager
244244
using BlockRelayFn = std::function<void(uint32_t chain_id, const std::string& block_hex)>;
245245
void set_block_relay_fn(BlockRelayFn fn);
246246

247+
/// Callback when a merged block is found: (symbol, height, block_hash, accepted)
248+
/// Used by MiningInterface to record in FoundBlock list for unified verification.
249+
using MergedBlockFoundFn = std::function<void(const std::string& symbol, int height,
250+
const std::string& block_hash, bool accepted)>;
251+
void set_on_merged_block_found(MergedBlockFoundFn fn) { m_on_merged_block_found = std::move(fn); }
252+
247253
private:
248254
void poll_loop();
249255
void refresh_aux_work();
@@ -285,6 +291,7 @@ class MergedMiningManager
285291

286292
// P2P block relay callback (set by integration layer)
287293
BlockRelayFn m_block_relay_fn;
294+
MergedBlockFoundFn m_on_merged_block_found;
288295

289296
// Discovered merged blocks history
290297
std::vector<DiscoveredMergedBlock> m_discovered_blocks;

src/core/web_server.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,10 @@ void MiningInterface::record_found_block(uint64_t height, const uint256& hash, u
23832383

23842384
void MiningInterface::set_block_verify_fn(block_verify_fn_t fn) { m_block_verify_fn = std::move(fn); }
23852385

2386+
void MiningInterface::add_chain_verify_fn(const std::string& chain, block_verify_fn_t fn) {
2387+
m_chain_verify_fns[chain] = std::move(fn);
2388+
}
2389+
23862390
void MiningInterface::verify_found_block(size_t index)
23872391
{
23882392
std::string hash;
@@ -2395,11 +2399,25 @@ void MiningInterface::verify_found_block(size_t index)
23952399
hash = blk.hash;
23962400
}
23972401

2398-
if (!m_block_verify_fn) return;
2402+
// Select chain-specific verifier, fall back to default
2403+
std::string chain;
2404+
{
2405+
std::lock_guard<std::mutex> lock(m_blocks_mutex);
2406+
if (index < m_found_blocks.size())
2407+
chain = m_found_blocks[index].chain;
2408+
}
2409+
block_verify_fn_t verify_fn;
2410+
auto it = m_chain_verify_fns.find(chain);
2411+
if (it != m_chain_verify_fns.end())
2412+
verify_fn = it->second;
2413+
else
2414+
verify_fn = m_block_verify_fn;
2415+
2416+
if (!verify_fn) return;
23992417

24002418
// Callback returns: >0 confirmed, <0 orphaned, 0 unknown/pending
24012419
int result = 0;
2402-
try { result = m_block_verify_fn(hash); } catch (...) {}
2420+
try { result = verify_fn(hash); } catch (...) {}
24032421

24042422
std::lock_guard<std::mutex> lock(m_blocks_mutex);
24052423
if (index >= m_found_blocks.size()) return;
@@ -2445,9 +2463,26 @@ void MiningInterface::schedule_block_verification(const std::string& block_hash)
24452463
}
24462464
if (idx == SIZE_MAX) return;
24472465

2448-
// Schedule checks at +10s, +30s, +120s after block submission
2466+
// Schedule checks based on chain's block time:
2467+
// LTC (2.5 min): +30s, +150s (1 block), +300s (2 blocks)
2468+
// DOGE (1 min): +10s, +60s (1 block), +120s (2 blocks)
2469+
// Default: +10s, +60s, +120s
2470+
std::string chain_name;
2471+
{
2472+
std::lock_guard<std::mutex> lock(m_blocks_mutex);
2473+
if (idx < m_found_blocks.size())
2474+
chain_name = m_found_blocks[idx].chain;
2475+
}
2476+
std::vector<int> delays;
2477+
if (chain_name == "LTC" || chain_name == "tLTC")
2478+
delays = {30, 150, 300};
2479+
else if (chain_name == "DOGE")
2480+
delays = {10, 60, 120};
2481+
else
2482+
delays = {10, 60, 120};
2483+
24492484
auto& ioc = *m_context;
2450-
for (int delay : {10, 30, 120}) {
2485+
for (int delay : delays) {
24512486
auto timer = std::make_shared<boost::asio::steady_timer>(
24522487
ioc, std::chrono::seconds(delay));
24532488
timer->async_wait([this, idx, timer](boost::system::error_code ec) {

src/core/web_server.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ class MiningInterface : public jsonrpccxx::JsonRpc2Server
436436
void set_io_context(boost::asio::io_context* ctx) { m_context = ctx; }
437437
void schedule_block_verification(const std::string& block_hash);
438438

439+
// Per-chain verify function: register additional verifiers for merged chains
440+
void add_chain_verify_fn(const std::string& chain, block_verify_fn_t fn);
441+
439442
// Callback fired whenever a block submission is attempted.
440443
// Arguments: header hex (first 80 bytes), stale_info (none=accepted, orphan=stale prev, doa=daemon rejected).
441444
void set_on_block_submitted(std::function<void(const std::string& header_hex, int stale_info)> fn);
@@ -595,7 +598,8 @@ class MiningInterface : public jsonrpccxx::JsonRpc2Server
595598
std::vector<FoundBlock> m_found_blocks; // newest first, capped at 100
596599
mutable std::mutex m_blocks_mutex;
597600

598-
block_verify_fn_t m_block_verify_fn;
601+
block_verify_fn_t m_block_verify_fn; // default (parent chain)
602+
std::map<std::string, block_verify_fn_t> m_chain_verify_fns; // per-chain
599603
void verify_found_block(size_t index);
600604

601605
// Pool start time for /uptime

0 commit comments

Comments
 (0)