Skip to content

Commit 820e37c

Browse files
committed
Private sharechain identity: --chain-id, --chain-prefix, --no-persist
Add chain identity to THE metadata for private sharechain support: metadata[8-11] = chain_id (0 = public p2pool network) metadata[12-15] = chain_prefix (P2P magic, 0 = default for coin) New CLI flags: --chain-id ID Private chain identifier (hex, e.g. DEADBEEF) --chain-prefix PFX P2P magic prefix (4 hex bytes) --no-persist Create genesis share immediately (for new chains) Chain identity is embedded in every found block's THE metadata, allowing blockchain scanners to distinguish between: - Public p2pool network (chain_id=0) - Private mining pools (chain_id=nonzero) - Multiple private chains (different chain_ids) TheCheckpoint now stores chain_id_val and chain_prefix_val alongside sharechain state for checkpoint attribution. TheMetadata layout updated: [0] version [1-4] sharechain_height [5-6] miner_count [7] hashrate_class [8-11] chain_id (NEW) [12-15] chain_prefix (NEW, was pool_aps) [16-17] share_period [18-19] verified_length
1 parent fd11df9 commit 820e37c

3 files changed

Lines changed: 44 additions & 10 deletions

File tree

src/c2pool/c2pool_refactored.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ void print_help() {
220220
std::cout << " Max 20 chars with merged mining, 64 without\n";
221221
std::cout << " Default: /c2pool/ (c2pool always identified by donation address)\n\n";
222222

223+
std::cout << "PRIVATE SHARECHAIN:\n";
224+
std::cout << " --chain-id ID Private chain identifier (hex, e.g. DEADBEEF)\n";
225+
std::cout << " Default: 0 (public p2pool network)\n";
226+
std::cout << " --chain-prefix PREFIX P2P magic prefix (4 hex bytes, e.g. C2C2C2C2)\n";
227+
std::cout << " Default: standard p2pool prefix for the coin\n";
228+
std::cout << " --no-persist Create genesis share immediately (don't wait for peers)\n";
229+
std::cout << " Required when starting a new private chain\n\n";
230+
223231
std::cout << "V36 SHARE MESSAGE BLOB (CLI operator control):\n";
224232
std::cout << " --message-blob-hex HEX Encrypted authority-signed message_data blob\n";
225233
std::cout << " to embed in locally created V36 shares\n\n";
@@ -378,6 +386,11 @@ int main(int argc, char* argv[]) {
378386
// Coinbase scriptSig customization
379387
std::string coinbase_text; // --coinbase-text (replaces /c2pool/ tag)
380388

389+
// Private sharechain
390+
uint32_t chain_id = 0; // 0 = public p2pool network
391+
uint32_t chain_prefix = 0; // 0 = use default p2pool prefix
392+
bool no_persist = false; // create genesis share immediately
393+
381394
// Track which options were explicitly set via CLI so that --config file
382395
// values only fill in gaps (CLI always wins).
383396
std::set<std::string> cli_explicit;
@@ -635,6 +648,18 @@ int main(int argc, char* argv[]) {
635648
coinbase_text = argv[++i];
636649
cli_explicit.insert("coinbase_text");
637650
}
651+
else if (arg == "--chain-id" && i + 1 < argc) {
652+
chain_id = static_cast<uint32_t>(std::stoul(argv[++i], nullptr, 16));
653+
cli_explicit.insert("chain_id");
654+
}
655+
else if (arg == "--chain-prefix" && i + 1 < argc) {
656+
chain_prefix = static_cast<uint32_t>(std::stoul(argv[++i], nullptr, 16));
657+
cli_explicit.insert("chain_prefix");
658+
}
659+
else if (arg == "--no-persist") {
660+
no_persist = true;
661+
cli_explicit.insert("no_persist");
662+
}
638663
// Legacy support for old --port option
639664
else if (arg == "--port" && i + 1 < argc) {
640665
p2p_port = std::stoi(argv[++i]);
@@ -1249,7 +1274,7 @@ int main(int argc, char* argv[]) {
12491274
return arr;
12501275
},
12511276
[](const uint256&, uint32_t) -> bool { return true; },
1252-
[the_store, mi](const std::string& chain, uint64_t height,
1277+
[the_store, mi, chain_id, chain_prefix](const std::string& chain, uint64_t height,
12531278
const std::string& hash, uint64_t ts) {
12541279
c2pool::storage::TheCheckpoint cp;
12551280
cp.chain = chain; cp.block_height = height;
@@ -1259,6 +1284,8 @@ int main(int argc, char* argv[]) {
12591284
cp.sharechain_height = work.sharechain_height;
12601285
cp.miner_count = work.miner_count;
12611286
cp.hashrate_class = c2pool::TheMetadata::encode_hashrate(work.pool_hashrate);
1287+
cp.chain_id_val = chain_id;
1288+
cp.chain_prefix_val = chain_prefix;
12621289
the_store->store(cp);
12631290
LOG_INFO << "[THE] Checkpoint: " << chain << " height=" << height
12641291
<< " miners=" << cp.miner_count

src/c2pool/storage/the_checkpoint.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ struct TheCheckpoint {
4141
std::string block_hash; // blockchain block hash
4242
uint64_t timestamp{0}; // when found
4343
uint8_t status{0}; // 0=pending, 1=verified, 2=mismatch
44+
uint32_t chain_id_val{0}; // 0 = public network, nonzero = private chain
45+
uint32_t chain_prefix_val{0}; // P2P magic prefix (0 = default)
4446

4547
std::vector<uint8_t> serialize() const {
4648
std::vector<uint8_t> out;

src/core/coinbase_builder.hpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,20 @@ static constexpr size_t MAX_OPERATOR_TEXT_MM = 20;
6262
// Maximum operator text without merged mining
6363
static constexpr size_t MAX_OPERATOR_TEXT_SOLO = 64;
6464

65+
// Public p2pool network chain_id (default — no private chain)
66+
static constexpr uint32_t PUBLIC_CHAIN_ID = 0;
67+
static constexpr uint32_t PUBLIC_CHAIN_PREFIX = 0;
68+
6569
/// THE metadata — compact pool state for on-chain commitment
6670
struct TheMetadata {
6771
uint8_t version = C2POOL_PROTOCOL_VERSION;
6872
uint32_t sharechain_height = 0; // share chain height at block-find
6973
uint16_t miner_count = 0; // unique miners in PPLNS window
7074
uint8_t hashrate_class = 0; // log2(pool_hashrate_in_h_per_s)
75+
uint32_t chain_id = PUBLIC_CHAIN_ID; // 0 = public network, nonzero = private chain
76+
uint32_t chain_prefix = PUBLIC_CHAIN_PREFIX; // P2P magic prefix (0 = default)
7177
uint16_t share_period = 0; // current share period (seconds)
7278
uint16_t verified_length = 0; // verified chain length
73-
uint32_t pool_aps_compressed = 0; // compressed pool attempts/s
7479
uint32_t reserved = 0; // future: THE temporal layer flags
7580

7681
/// Pack into bytes (up to max_bytes, truncated from end)
@@ -93,10 +98,10 @@ struct TheMetadata {
9398
push32(sharechain_height); // [1-4]
9499
push16(miner_count); // [5-6]
95100
push8(hashrate_class); // [7]
96-
push16(share_period); // [8-9]
97-
push16(verified_length); // [10-11]
98-
push32(pool_aps_compressed); // [12-15]
99-
push32(reserved); // [16-19]
101+
push32(chain_id); // [8-11] 0 = public network
102+
push32(chain_prefix); // [12-15] P2P magic prefix
103+
push16(share_period); // [16-17]
104+
push16(verified_length); // [18-19]
100105
return out;
101106
}
102107

@@ -107,10 +112,10 @@ struct TheMetadata {
107112
if (len >= 5) m.sharechain_height = data[1] | (data[2]<<8) | (data[3]<<16) | (data[4]<<24);
108113
if (len >= 7) m.miner_count = data[5] | (data[6]<<8);
109114
if (len >= 8) m.hashrate_class = data[7];
110-
if (len >= 10) m.share_period = data[8] | (data[9]<<8);
111-
if (len >= 12) m.verified_length = data[10] | (data[11]<<8);
112-
if (len >= 16) m.pool_aps_compressed = data[12] | (data[13]<<8) | (data[14]<<16) | (data[15]<<24);
113-
if (len >= 20) m.reserved = data[16] | (data[17]<<8) | (data[18]<<16) | (data[19]<<24);
115+
if (len >= 12) m.chain_id = data[8] | (data[9]<<8) | (data[10]<<16) | (data[11]<<24);
116+
if (len >= 16) m.chain_prefix = data[12] | (data[13]<<8) | (data[14]<<16) | (data[15]<<24);
117+
if (len >= 18) m.share_period = data[16] | (data[17]<<8);
118+
if (len >= 20) m.verified_length = data[18] | (data[19]<<8);
114119
return m;
115120
}
116121

0 commit comments

Comments
 (0)