Skip to content

Commit 96b22ad

Browse files
authored
ltc: fix private-net IDENTIFIER truncation + independent PREFIX (V36 ship-blocker)
Fixes private-net IDENTIFIER truncation and derives PREFIX independently of network-id. Unblocks c2pool<->p2pool framing parity for the V36 crossing testbed. CI all green (16 checks).
1 parent e967221 commit 96b22ad

2 files changed

Lines changed: 31 additions & 20 deletions

File tree

src/c2pool/c2pool_refactored.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ void print_help() {
442442
std::cout << " Nonzero: creates a private sharechain. P2P prefix\n";
443443
std::cout << " and THE metadata will carry this ID on the blockchain.\n";
444444
std::cout << " Genesis shares are created automatically when chain is empty.\n";
445+
std::cout << " Full 8 bytes (up to 16 hex chars) are used, not truncated.\n";
446+
std::cout << " --prefix HEX Explicit P2P transport-framing prefix (hex, up to 8 bytes).\n";
447+
std::cout << " Independent of --network-id; defaults to the compiled\n";
448+
std::cout << " per-network constant. Must match across all peers.\n";
445449
std::cout << " --startup-mode MODE Sharechain startup behavior:\n";
446450
std::cout << " auto — wait for peers (60s), then genesis if none (default)\n";
447451
std::cout << " genesis — create new chain immediately, don't wait for peers\n";
@@ -642,7 +646,8 @@ int main(int argc, char* argv[]) {
642646
std::string coinbase_text; // --coinbase-text (replaces /c2pool/ tag)
643647

644648
// Private sharechain
645-
uint32_t network_id = 0; // 0 = public p2pool network, nonzero = private
649+
uint64_t network_id = 0; // 0 = public p2pool network, nonzero = private (full 8 bytes)
650+
std::string prefix_override_hex; // explicit --prefix; empty = compiled per-network default
646651

647652
// Startup mode: wait (default, p2pool persist=true), genesis, auto
648653
enum class StartupMode { AUTO, GENESIS, WAIT };
@@ -960,9 +965,14 @@ int main(int argc, char* argv[]) {
960965
cli_explicit.insert("coinbase_text");
961966
}
962967
else if ((arg == "--network-id" || arg == "--chain-id") && i + 1 < argc) {
963-
network_id = static_cast<uint32_t>(std::stoul(argv[++i], nullptr, 16));
968+
// Full 8-byte identifier: parse as 64-bit, never truncate to 32 bits
969+
network_id = std::stoull(argv[++i], nullptr, 16);
964970
cli_explicit.insert("network_id");
965971
}
972+
else if (arg == "--prefix" && i + 1 < argc) {
973+
prefix_override_hex = argv[++i];
974+
cli_explicit.insert("prefix");
975+
}
966976
else if (arg == "--startup-mode" && i + 1 < argc) {
967977
std::string mode = argv[++i];
968978
if (mode == "genesis") startup_mode = StartupMode::GENESIS;
@@ -2530,11 +2540,14 @@ int main(int argc, char* argv[]) {
25302540
// Private chain: override IDENTIFIER and PREFIX before any P2P or share ops
25312541
if (network_id != 0) {
25322542
std::ostringstream hex;
2533-
hex << std::hex << std::setfill('0') << std::setw(8) << network_id;
2534-
// Pad to 16 hex chars (8 bytes) for full IDENTIFIER
2543+
hex << std::hex << std::setfill('0') << std::setw(16) << network_id; // full 8-byte IDENTIFIER, no truncation
2544+
// setw(16) already produced the full 8-byte IDENTIFIER
25352545
std::string id_hex = hex.str();
2536-
while (id_hex.size() < 16) id_hex += "00";
25372546
ltc::PoolConfig::set_network_id(id_hex);
2547+
// PREFIX is independent: compiled per-network default unless
2548+
// explicitly overridden via --prefix (never derived from the ID)
2549+
if (!prefix_override_hex.empty())
2550+
ltc::PoolConfig::set_prefix(prefix_override_hex);
25382551
LOG_INFO << "[Private] Network ID: " << ltc::PoolConfig::identifier_hex()
25392552
<< " (PREFIX: " << ltc::PoolConfig::prefix_hex() << ")";
25402553
}

src/impl/ltc/config_pool.hpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class PoolConfig : protected core::Fileconfig
142142
static inline std::string override_prefix_hex;
143143

144144
/// Set private network identity. IDENTIFIER is the consensus secret
145-
/// (hashed into ref_hash). PREFIX is derived from it for transport framing.
145+
/// (hashed into ref_hash). PREFIX is NOT derived from it (see set_prefix).
146146
/// Call once at startup before any P2P or share operations.
147147
static void set_network_id(const std::string& network_id_hex) {
148148
if (network_id_hex.empty() || network_id_hex == "0" || network_id_hex == "00000000")
@@ -154,20 +154,18 @@ class PoolConfig : protected core::Fileconfig
154154
if (padded.size() > 16) padded = padded.substr(0, 16);
155155

156156
override_identifier_hex = padded;
157+
}
157158

158-
// Derive PREFIX from IDENTIFIER using simple XOR mixing
159-
// PREFIX = IDENTIFIER bytes XOR-rotated (fast, deterministic, non-reversible enough
160-
// for transport framing — the real security is in IDENTIFIER via ref_hash)
161-
auto id_bytes = ParseHex(padded);
162-
static const char* HEX = "0123456789abcdef";
163-
override_prefix_hex.clear();
164-
override_prefix_hex.reserve(16);
165-
for (size_t i = 0; i < 8 && i < id_bytes.size(); ++i) {
166-
// XOR with rotated byte + constant to ensure PREFIX != IDENTIFIER
167-
uint8_t b = id_bytes[i] ^ id_bytes[(i + 3) % id_bytes.size()] ^ 0x5A;
168-
override_prefix_hex += HEX[b >> 4];
169-
override_prefix_hex += HEX[b & 0x0f];
170-
}
159+
/// Set an explicit transport-framing PREFIX for a private chain (--prefix).
160+
/// Independent of IDENTIFIER; when unset, prefix_hex() falls back to the
161+
/// compiled per-network constant. All peers on the chain must agree on it.
162+
static void set_prefix(const std::string& prefix_hex_in) {
163+
if (prefix_hex_in.empty() || prefix_hex_in == "0")
164+
return;
165+
std::string padded = prefix_hex_in;
166+
while (padded.size() < 16) padded = "0" + padded;
167+
if (padded.size() > 16) padded = padded.substr(padded.size() - 16);
168+
override_prefix_hex = padded;
171169
}
172170

173171
static const std::string& identifier_hex() {
@@ -191,7 +189,7 @@ class PoolConfig : protected core::Fileconfig
191189
if (override_identifier_hex.empty())
192190
return 0; // public network
193191

194-
auto pfx_bytes = ParseHex(override_prefix_hex);
192+
auto pfx_bytes = ParseHex(prefix_hex()); // effective prefix (override or compiled default)
195193
auto id_bytes = ParseHex(override_identifier_hex);
196194
std::vector<unsigned char> preimage;
197195
preimage.reserve(pfx_bytes.size() + id_bytes.size());

0 commit comments

Comments
 (0)