Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions src/c2pool/c2pool_refactored.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@
std::cout << " Nonzero: creates a private sharechain. P2P prefix\n";
std::cout << " and THE metadata will carry this ID on the blockchain.\n";
std::cout << " Genesis shares are created automatically when chain is empty.\n";
std::cout << " Full 8 bytes (up to 16 hex chars) are used, not truncated.\n";
std::cout << " --prefix HEX Explicit P2P transport-framing prefix (hex, up to 8 bytes).\n";
std::cout << " Independent of --network-id; defaults to the compiled\n";
std::cout << " per-network constant. Must match across all peers.\n";
std::cout << " --startup-mode MODE Sharechain startup behavior:\n";
std::cout << " auto — wait for peers (60s), then genesis if none (default)\n";
std::cout << " genesis — create new chain immediately, don't wait for peers\n";
Expand Down Expand Up @@ -642,7 +646,8 @@
std::string coinbase_text; // --coinbase-text (replaces /c2pool/ tag)

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

// Startup mode: wait (default, p2pool persist=true), genesis, auto
enum class StartupMode { AUTO, GENESIS, WAIT };
Expand Down Expand Up @@ -960,9 +965,14 @@
cli_explicit.insert("coinbase_text");
}
else if ((arg == "--network-id" || arg == "--chain-id") && i + 1 < argc) {
network_id = static_cast<uint32_t>(std::stoul(argv[++i], nullptr, 16));
// Full 8-byte identifier: parse as 64-bit, never truncate to 32 bits
network_id = std::stoull(argv[++i], nullptr, 16);

Check notice

Code scanning / CodeQL

For loop variable changed in body Note

Loop counters should not be modified in the body of the
loop
.
cli_explicit.insert("network_id");
}
else if (arg == "--prefix" && i + 1 < argc) {
prefix_override_hex = argv[++i];

Check notice

Code scanning / CodeQL

For loop variable changed in body Note

Loop counters should not be modified in the body of the
loop
.
cli_explicit.insert("prefix");
}
else if (arg == "--startup-mode" && i + 1 < argc) {
std::string mode = argv[++i];
if (mode == "genesis") startup_mode = StartupMode::GENESIS;
Expand Down Expand Up @@ -2530,11 +2540,14 @@
// Private chain: override IDENTIFIER and PREFIX before any P2P or share ops
if (network_id != 0) {
std::ostringstream hex;
hex << std::hex << std::setfill('0') << std::setw(8) << network_id;
// Pad to 16 hex chars (8 bytes) for full IDENTIFIER
hex << std::hex << std::setfill('0') << std::setw(16) << network_id; // full 8-byte IDENTIFIER, no truncation
// setw(16) already produced the full 8-byte IDENTIFIER
std::string id_hex = hex.str();
while (id_hex.size() < 16) id_hex += "00";
ltc::PoolConfig::set_network_id(id_hex);
// PREFIX is independent: compiled per-network default unless
// explicitly overridden via --prefix (never derived from the ID)
if (!prefix_override_hex.empty())
ltc::PoolConfig::set_prefix(prefix_override_hex);
LOG_INFO << "[Private] Network ID: " << ltc::PoolConfig::identifier_hex()
<< " (PREFIX: " << ltc::PoolConfig::prefix_hex() << ")";
}
Expand Down
28 changes: 13 additions & 15 deletions src/impl/ltc/config_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class PoolConfig : protected core::Fileconfig
static inline std::string override_prefix_hex;

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

override_identifier_hex = padded;
}

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

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

auto pfx_bytes = ParseHex(override_prefix_hex);
auto pfx_bytes = ParseHex(prefix_hex()); // effective prefix (override or compiled default)
auto id_bytes = ParseHex(override_identifier_hex);
std::vector<unsigned char> preimage;
preimage.reserve(pfx_bytes.size() + id_bytes.size());
Expand Down
Loading