Skip to content

Commit e2d90ec

Browse files
authored
nmc(P1 PE): P2P-primary block-relay sink + never-silent-drop submit_block (#223)
Embedded NMC submit path now relays found aux-blocks through a settable BlockRelayFn sink (host wires it to CoinBroadcaster::submit_block_raw, decoded at the wiring site, mirroring the BTC on_block_relay seam). submit_block() no longer claims success unconditionally: an unwired relay or a 0-peer broadcast surfaces as failure (never-silent-drop, per BTC #162) while the hex is still cached for get_block_hex(). +3 KATs (relay exact-hex, no-relay fail, 0-peer fail); existing cache KAT updated to the new contract. Rides nmc_template_builder_test — no CMake/build.yml change. Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
1 parent 9b09a68 commit e2d90ec

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

src/impl/nmc/coin/aux_chain_embedded.hpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include <algorithm>
4040
#include <string>
41+
#include <functional>
4142

4243
namespace nmc {
4344
namespace coin {
@@ -118,13 +119,34 @@ class AuxChainEmbedded : public c2pool::merged::IAuxChainBackend
118119
return get_work_template();
119120
}
120121

122+
/// PE submit path: P2P-primary block-relay sink. The host wires this to
123+
/// CoinBroadcaster::submit_block_raw (the hex is decoded at the wiring site,
124+
/// mirroring the BTC on_block_relay seam). Returns the number of peers the
125+
/// block was relayed to (0 => not broadcast). When unset, submit_block()
126+
/// REFUSES to claim success (never-silent-drop, per BTC #162).
127+
using BlockRelayFn = std::function<size_t(const std::string& block_hex)>;
128+
void set_block_relay(BlockRelayFn fn) { m_block_relay = std::move(fn); }
129+
121130
bool submit_block(const std::string& block_hex) override {
122-
// Embedded mode: P2P relay handled by CoinBroadcaster. Cache for
123-
// get_block_hex() retrieval and log the 80-byte header prefix.
124-
LOG_INFO << "[MM:" << m_config.symbol << "] Embedded: block submitted ("
125-
<< block_hex.size() / 2 << " bytes)"
126-
<< " header=" << block_hex.substr(0, std::min(size_t(160), block_hex.size()));
131+
// PE: P2P relay is the primary route. Cache the hex for get_block_hex()
132+
// regardless of outcome, but NEVER silently claim success - a found
133+
// block that did not reach a peer must surface as a failure so the
134+
// caller can fall back (mirrors BTC submitblock never-silent-drop #162).
127135
m_last_block_hex = block_hex;
136+
const size_t nbytes = block_hex.size() / 2;
137+
if (!m_block_relay) {
138+
LOG_WARNING << "[MM:" << m_config.symbol << "] Embedded: submit_block with NO relay"
139+
<< " wired - block NOT broadcast (" << nbytes << " bytes)";
140+
return false;
141+
}
142+
const size_t npeers = m_block_relay(block_hex);
143+
if (npeers == 0) {
144+
LOG_WARNING << "[MM:" << m_config.symbol << "] Embedded: submit_block reached 0 peers"
145+
<< " - block NOT relayed (" << nbytes << " bytes)";
146+
return false;
147+
}
148+
LOG_INFO << "[MM:" << m_config.symbol << "] Embedded: block relayed to " << npeers
149+
<< " peer(s) (" << nbytes << " bytes)";
128150
return true;
129151
}
130152

@@ -166,6 +188,7 @@ class AuxChainEmbedded : public c2pool::merged::IAuxChainBackend
166188
c2pool::merged::AuxChainConfig m_config;
167189
EmbeddedCoinNode m_embedded;
168190
std::string m_last_block_hex; // cached for get_block_hex() after submit
191+
BlockRelayFn m_block_relay; // PE: P2P-primary relay sink (unset => never-silent fail)
169192
};
170193

171194
} // namespace coin

src/impl/nmc/test/nmc_template_builder_test.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,54 @@ TEST(NmcAuxChainEmbedded, SubmitBlockCachesHexForRetrieval)
312312

313313
EXPECT_EQ(backend.get_block_hex("any"), std::string(""));
314314
const std::string hex(200, 'a');
315-
EXPECT_TRUE(backend.submit_block(hex));
315+
// PE never-silent-drop: with no relay wired the block is NOT broadcast, so
316+
// submit_block() must report failure - but the hex is still cached for
317+
// get_block_hex() diagnostics/retrieval.
318+
EXPECT_FALSE(backend.submit_block(hex));
316319
EXPECT_EQ(backend.get_block_hex("any"), hex);
317320
// No daemon peers in embedded mode.
318321
EXPECT_TRUE(backend.getpeerinfo().empty());
319322
}
320323

324+
// PE submit path: P2P relay is primary. When a relay sink is wired and reaches
325+
// >=1 peer, submit_block() reports success and the sink receives the exact hex.
326+
TEST(NmcAuxChainEmbedded, SubmitBlockRelaysExactHexToPeers)
327+
{
328+
HeaderChain chain(params_pinned());
329+
Mempool pool;
330+
AuxChainEmbedded backend(chain, pool, params_pinned(), nmc_aux_config());
331+
332+
std::string relayed;
333+
backend.set_block_relay([&](const std::string& block_hex) -> size_t {
334+
relayed = block_hex; // capture what the broadcaster would send
335+
return 2; // pretend 2 peers received it
336+
});
337+
338+
const std::string hex(200, 'b');
339+
EXPECT_TRUE(backend.submit_block(hex)); // relayed to >=1 peer => success
340+
EXPECT_EQ(relayed, hex); // byte-exact hand-off to the sink
341+
EXPECT_EQ(backend.get_block_hex("any"), hex);
342+
}
343+
344+
// PE never-silent-drop: a relay that reaches 0 peers must NOT be reported as a
345+
// successful broadcast, even though the sink ran (mirrors BTC #162).
346+
TEST(NmcAuxChainEmbedded, SubmitBlockNeverSilentDropOnZeroPeers)
347+
{
348+
HeaderChain chain(params_pinned());
349+
Mempool pool;
350+
AuxChainEmbedded backend(chain, pool, params_pinned(), nmc_aux_config());
351+
352+
bool sink_ran = false;
353+
backend.set_block_relay([&](const std::string&) -> size_t {
354+
sink_ran = true;
355+
return 0; // no peers connected
356+
});
357+
358+
const std::string hex(200, 'c');
359+
EXPECT_FALSE(backend.submit_block(hex)); // 0 peers => not broadcast
360+
EXPECT_TRUE(sink_ran); // sink was consulted, not skipped
361+
EXPECT_EQ(backend.get_block_hex("any"), hex); // hex still cached
362+
}
363+
321364

322365
} // namespace

0 commit comments

Comments
 (0)