Skip to content

frstrtr/c2pool

Repository files navigation

c2pool — P2Pool rebirth in C++

CI

C++ reimplementation of forrestv/p2pool targeting the V36 share format with Litecoin + multi-chain merged mining (DOGE, PEP, BELLS, LKY, JKC, SHIC). DigiByte Scrypt support planned as an additional parent chain.

Bitcoin wiki: https://en.bitcoin.it/wiki/P2Pool
Original forum thread: https://bitcointalk.org/index.php?topic=18313


Status

Area Status
V36 share format (LTC parent chain) Active development
V36 share format (DGB Scrypt parent chain) Planned
Merged mining (DOGE, PEP, BELLS, LKY, JKC, SHIC) Working
Coin daemon RPC/P2P Hardened (softfork gate, keepalive, timeouts)
Stratum mining server Working
VARDIFF Working
Payout / PPLNS Working
Authority message blobs (V36) Working
Test suite 390 tests, all passing

Need a pool running today?
frstrtr/p2pool-merged-v36 — production Python V36 pool (LTC + DGB + DOGE, Docker, dashboard).


Quick start

# 1 — prerequisites (Ubuntu 24.04)
sudo apt-get install -y g++ cmake make libleveldb-dev libsecp256k1-dev python3-pip
pip install "conan>=2.0,<3.0" --break-system-packages
conan profile detect --force

# 2 — clone and build
git clone https://github.com/frstrtr/c2pool.git
cd c2pool && mkdir build && cd build
conan install .. --build=missing --output-folder=. --settings=build_type=Debug
cmake .. --preset conan-debug
cmake --build . --target c2pool -j$(nproc)

Full step-by-step guide: doc/build-unix.md


Running

# Integrated mode with embedded SPV (no separate LTC/DOGE daemons needed)
./src/c2pool/c2pool --integrated --net litecoin --embedded-ltc --embedded-doge \
  --address YOUR_LTC_ADDRESS

# Or with external daemons + additional merged chains
./src/c2pool/c2pool --integrated --net litecoin \
  --coind-address 127.0.0.1 --coind-rpc-port 9332 \
  --rpcuser litecoinrpc --rpcpassword RPCPASSWORD \
  --address YOUR_LTC_ADDRESS \
  --merged DOGE:98:127.0.0.1:22555:dogerpc:dogepass \
  --merged PEP:63:127.0.0.1:29377:peprpc:peppass \
  --merged LKY:8211:127.0.0.1:9916:lkyrpc:lkypass

# Testnet quick smoke-test
./src/c2pool/c2pool --integrated --testnet

# Full option reference
./src/c2pool/c2pool --help

Default ports

Port Purpose
9326 P2Pool sharechain (peer-to-peer)
9327 Stratum mining + HTTP API

Merged mining chains

LTC and DOGE have built-in embedded SPV nodes — no separate daemon required. Other chains need their daemon running externally.

Coin chain_id Daemon --merged example
DOGE 98 Embedded SPV (or external) DOGE:98:127.0.0.1:22555:user:pass
PEP 63 External (pepecoind) PEP:63:127.0.0.1:29377:user:pass
BELLS 16 External (bellsd) BELLS:16:127.0.0.1:19918:user:pass
LKY 8211 External (luckycoind) LKY:8211:127.0.0.1:9916:user:pass
JKC 8224 External (junkcoind) JKC:8224:127.0.0.1:9770:user:pass
SHIC 74 External (shibacoind) SHIC:74:127.0.0.1:33863:user:pass
DINGO 98 External (dingocoind) Cannot run with DOGE (same chain_id)

LTC and DOGE use built-in embedded SPV nodes — zero external dependencies for the core LTC+DOGE setup. External daemons use createauxblock/submitauxblock RPC.

DigiByte Scrypt is planned as a second parent chain (--net digibyte), running its own P2Pool sharechain network. DGB Scrypt produces valid Scrypt PoW, so it can also merge-mine DOGE and the other AuxPoW coins.

See deploy/DEPLOY.md for HiveOS/MinerStat/RaveOS setup.

API endpoints (integrated mode)

GET  /local_rate          local pool hashrate
GET  /global_rate         network hashrate
GET  /current_payouts     PPLNS expected payouts
GET  /recent_blocks       blocks found by pool
GET  /global_stats        comprehensive pool stats
GET  /sharechain/stats    sharechain tracker data
GET  /local_stats         p2pool-compatible local stats
POST {jsonrpc}            getinfo, getminerstats, getpayoutinfo, ...

Web dashboard — served by default from web-static/:

# Built-in dashboard
xdg-open http://localhost:8080/

# Custom dashboard directory
./src/c2pool/c2pool --dashboard-dir /path/to/my-dashboard ...

See docs/DASHBOARD_INTEGRATION.md for the complete API reference and custom dashboard development guide.


Authority message blobs (V36)

Node operators distributing upgrade signals or pool announcements use the standalone Python 3 CLI in util/:

# authority key holder — create transition signal
python3 util/create_transition_message.py create \
    --privkey <64-hex> \
    --from 36 --to 37 --msg "Upgrade to V37" --urgency recommended

# node operator — pass blob at startup
./src/c2pool/c2pool ... --message-blob-hex 01a2b3c4...

See util/README.md for full documentation.


Configuration

c2pool supports configuration via CLI arguments, YAML config file, or both. CLI arguments always take priority over YAML values.

# Use a YAML config file
./src/c2pool/c2pool --config config/c2pool_testnet.yaml

# Or pass everything via CLI
./src/c2pool/c2pool --integrated --testnet --net litecoin \
    --p2pool-port 19338 -w 19327 --web-port 8080 ...

Configuration reference

CLI flag YAML key Default Description
--net Blockchain: litecoin, bitcoin, dogecoin
--testnet off Enable testnet mode
--p2pool-port port 9326 P2P sharechain port
-w / --worker-port stratum_port 9327 Stratum mining port
--web-port http_port 8080 HTTP API / dashboard port
--http-host http_host 0.0.0.0 HTTP bind address
--coind-address ltc_rpc_host 127.0.0.1 Coin daemon RPC host
--coind-rpc-port ltc_rpc_port auto Coin daemon RPC port
--rpcuser ltc_rpc_user RPC username
--rpcpassword ltc_rpc_password RPC password
--address Payout address
--give-author donation_percentage 0 Developer donation %
-f / --fee node_owner_fee 0 Node owner fee %
--node-owner-address node_owner_address Node owner payout addr
--redistribute redistribute pplns Mode: pplns/fee/boost/donate
--max-conns 8 Target outbound P2P peers
--stratum-min-diff min_difficulty 0.001 Vardiff floor
--stratum-max-diff max_difficulty 65536 Vardiff ceiling
--stratum-target-time target_time 10 Seconds between pseudoshares
--no-vardiff vardiff_enabled true Disable auto-difficulty
--max-coinbase-outputs max_coinbase_outputs 4000 Max coinbase outputs
--log-file log_file debug.log Log filename
--log-level log_level trace trace/debug/info/warning/error
--log-rotation-mb log_rotation_size_mb 10 Log rotation threshold (MB)
--log-max-mb log_max_total_mb 50 Max rotated log space (MB)
--p2p-max-peers p2p_max_peers 30 Max total P2P peers
--ban-duration ban_duration 300 P2P ban duration (seconds)
--rss-limit-mb rss_limit_mb 4000 RSS memory abort limit (MB)
--cors-origin cors_origin * CORS Allow-Origin header
--payout-window payout_window_seconds 86400 PPLNS window (seconds)
--storage-save-interval storage_save_interval 300 Sharechain save interval
--dashboard-dir dashboard_dir web-static Static dashboard directory
--coinbase-text coinbase_text Custom coinbase scriptSig text (see below)
--message-blob-hex V36 authority message blob
--embedded-ltc off Use embedded SPV for LTC (no litecoind needed)
--network-id network_id 0 Private chain identifier (hex, see below)

See config/c2pool_testnet.yaml for a complete example.


Coinbase customization

Every block found by c2pool embeds structured data in the coinbase scriptSig. The 100-byte scriptSig is partitioned as follows:

┌─────────────────────────────────────────────────────────────────┐
│ [4]  BIP34 block height (consensus required)                    │
│ [44] AuxPoW merged mining commitment (when merged mining active)│
│ [N]  Tag or operator text (see below)                           │
│ [32] THE state root (sharechain state commitment)               │
│ [M]  THE metadata (pool analytics, fills remaining space)       │
└─────────────────────────────────────────────────────────────────┘
  Total: 100 bytes (Bitcoin consensus limit)

Operator text (--coinbase-text)

By default, c2pool uses /c2pool/ (8 bytes) as the tag. Node operators can replace this with custom text via --coinbase-text:

# Default: "/c2pool/" tag
./src/c2pool/c2pool --integrated ...

# Custom: your node name
./src/c2pool/c2pool --integrated --coinbase-text "EU-Node1" ...

# Custom: pool branding
./src/c2pool/c2pool --integrated --coinbase-text "MyPool.io" ...

Size limits (enforced at startup):

Mode Max text Reason
With merged mining 20 bytes AuxPoW commitment uses 44 bytes
Without merged mining 64 bytes No AuxPoW overhead

c2pool is always identified by the combined donation address in coinbase outputs (visible in any block explorer) — the scriptSig tag is optional branding, not the primary identifier.

THE state root (32 bytes, always present)

Commits the sharechain state at block-find time:

  • PPLNS weight distribution snapshot
  • Sharechain height and chain parameters
  • Epoch metadata (difficulty, pool hashrate)

This enables trustless checkpoints: any c2pool node can verify that a found block's PPLNS distribution matches the committed state root.

THE metadata (variable, fills remaining space after tag)

Byte Field Description
0 version Protocol version (0x01 = V36)
1-4 sharechain_height Share chain height at block-find
5-6 miner_count Unique miners in PPLNS window
7 hashrate_class log2(pool hashrate in H/s)
8-15 chain_fingerprint 0=public, SHA256d(PREFIX||IDENTIFIER)[0:8]=private
16-17 share_period Current share period (seconds)
18-19 verified_length Verified chain length

Metadata is truncated from the end when space is limited (e.g., long operator text reduces metadata space).


Private sharechains

c2pool supports private sharechains for isolated mining networks.

# Start a private chain (operator)
./src/c2pool/c2pool --integrated --network-id DEADBEEF12345678 \
  --net litecoin --address YOUR_LTC_ADDRESS ...

# Join the same private chain (miner)
./src/c2pool/c2pool --integrated --network-id DEADBEEF12345678 \
  -n OPERATOR_IP:9326 ...

How it works:

The --network-id overrides the IDENTIFIER used in share consensus verification. p2pool uses two-layer network isolation:

Layer Value Security
Transport PREFIX (derived from network-id) Filters connections — visible on wire
Consensus IDENTIFIER (= network-id) Hashed into every share's ref_hashsecret

A node that doesn't know the network-id cannot forge valid shares because the IDENTIFIER is hashed into every share's verification hash. Sharing the network-id with a miner grants them sharechain access.

Genesis behavior: When the chain is empty, c2pool automatically creates genesis shares — no special flag needed. The first miner solution becomes the genesis share, and the chain grows from there. Peers that connect later download shares from the genesis node.

Security: The IDENTIFIER is never stored raw on the blockchain — it is the consensus secret. The chain_fingerprint in THE metadata is SHA256d(PREFIX || IDENTIFIER)[0:4] — a 4-byte cryptographic fingerprint using Bitcoin's standard double-SHA256. Even if the PREFIX is sniffed from network traffic, the IDENTIFIER half requires 2^64 brute force to recover. Blockchain scanners can group blocks by fingerprint without learning the secret needed to join the chain.

Default --network-id 0 = public p2pool network (standard IDENTIFIER).


Build targets

Target Description
c2pool Primary binary
test_hardening Softfork gate + reply-matcher regression tests
test_share_messages V36 authority message decrypt/verify tests
test_coin_broadcaster Coin peer-manager and broadcaster tests

Run all tests:

cd build && ctest --output-on-failure -j$(nproc)

Community


Donations

PayPal

Donate


Install guides


API endpoints

See docs/DASHBOARD_INTEGRATION.md for the complete HTTP API reference, including:

  • Native c2pool endpoints (hashrate, payouts, stats, blocks, miners)
  • p2pool legacy endpoints (local_stats, web/version, etc.)
  • Merged mining endpoints (merged_stats, recent_merged_blocks, discovered_merged_blocks, current_merged_payouts, etc.)
  • JSON-RPC methods (getinfo, getminerstats, getpayoutinfo, submitblock, etc.)

Merged mining endpoints:

Endpoint Description
/merged_stats Merged mining block statistics
/current_merged_payouts Current merged mining payouts
/recent_merged_blocks Recent merged-mined blocks
/all_merged_blocks All merged-mined blocks
/discovered_merged_blocks Merged block proofs
/broadcaster_status Parent chain broadcaster status
/merged_broadcaster_status Merged chain broadcaster status
/network_difficulty Historical network difficulty

For full field details and dashboard integration, see docs/DASHBOARD_INTEGRATION.md.