§ 08

§ 08 · Mining

Pools

Shares, a gateway that proves, and who mines Pearl today

At the difficulty of 20 October 2026, a single H100 GPU mining alone would find a block about once every 218 days, on average, and it could easily wait twice that. Most people can’t live with that kind of lottery.

So, as in Bitcoin, miners join a mining pool. Everyone mines for the pool, the pool wins blocks far more often than any one member could, and it splits the rewards by how much work each member did. Pearl adds one twist: the pool’s software also has to turn each winning ticket into the block’s zero-knowledge certificate.

Try it

Enter a GPU’s speed to see how long it would take to find a block on its own.

Mining odds

How long one GPU would wait, on average, for a block

Total: 600 TMAC/s

Average wait for one block

218 d 1 h

1.13 × 10²² multiply-accumulates per block (difficulty × 2.815 × 10¹⁴) ÷ 600 TMAC/s

Chance of at least one block in…

a day 0.46%
a week 3.16%
a month 12.9%
a year 81.2%
Network, by design
445 blocks/day
one every 194 s
Network rate
64.9 EMAC/s
snapshot, Oct 20, 2026
Your share
0.00092%
≈ 0.0041 blocks/day

Estimate, not advice Averages only: a block is luck, so the real wait can be much shorter or longer. GPU speeds are rough figures from pool data (arXiv 2606.04819), not benchmarks. This ignores pools, costs and prices. Many miners join a pool for small, steady payouts instead.

Runs in your browser · asks PRLScan only if you press “Use live” src/data/facts.ts · MINING.macsPerDifficulty

What is a share?

A share is a ticket that beats an easier target, one the pool sets low enough that each member finds shares regularly. Shares don’t win blocks; they’re evidence of work. The pool counts them to decide each member’s cut. Now and then a share also beats the network’s real bar, and that one wins a block.

On Pearl, the checking happens in layers:

  1. On the GPU

    Every ticket is compared on the chip with the job’s target, which the gateway has already converted to the rank-penalized form. Almost all are discarded.

  2. At the pool

    A ticket that passes is sent as a plain proof: the sizes, the rank, and the tile’s real rows of A and columns of B, as the 1 KiB chunks that contain them, plus Merkle paths to the matrix fingerprints. The pool verifies the paths, regenerates the noise, recomputes the tile’s diary and ticket, and compares it with the share target. Pearl’s verifier has a parameter for exactly this, an override target to use instead of the block’s.

  3. For a block

    If the ticket also beats the network’s bar, the pool proves it in zero knowledge, sets the header’s proof commitment, builds the certificate and submits the block to a node.

GPU minerGPU minerGPU minerpool / gatewaycheck share vs easy targetwinner? prove it (seconds)set proof commitmentbuild certificate + blockpearldverifies, relayssharesblocktemplatesjobs
How a Pearl pool works. Templates flow from a node to the pool and out to miners as jobs; shares flow back as plain proofs; only a winning share is proven and becomes a block.

Checking a share costs the pool one tile’s worth of arithmetic: at k = 8,192 and a 2 × 64 tile, about a million multiply-accumulates, plus regenerating that tile’s noise. Proving a winning share takes seconds of CPU, but only once per block.

What is the gateway?

pearl-gateway is Pearl’s reference software for the middle box in the picture. Pearl’s miner README calls it the bridge between a Pearl full node and the miner process: it fetches block templates from the node, hands jobs to the GPU miner, checks plain proofs, turns a winning one into a zero-knowledge certificate, and submits the block.

Its job targets are already adjusted for the rank penalty: it refuses a rank below 128 and scales the target by 128/r before the GPU sees it, so the GPU’s on-chip check already follows the rule the network will apply.

Can I mine solo?

Yes. Solo mining means running the whole stack yourself: your own pearld node, the gateway, and a GPU miner. Pearl’s official Docker image for the vLLM miner does exactly this: it starts pearl-gateway in the background, points it at a pearld node’s RPC address, then starts serving the model. Every block you win pays its whole reward to you, and every block you win takes as long as the lottery says.

Pearl also ships a simple CPU miner inside its proof-of-work library. Its own documentation calls it a naive implementation for completeness and testing, not for production.

Who mines Pearl?

The chain itself shows a few things.

Pool tags in coinbases. A coinbase’s input script is free-form space, and pools often sign their blocks there. Block 130,825’s coinbase reads, after the block height and a timestamp, /pool.kryptex.com/, followed by 12 bytes of extranonce:

Coinbase of block 130,825 216 bytes
02000000 00 01 01 0000000000000000000000000000000000000000000000000000000000000000 ffffffff 27 0309ff01048393d76a2f706f6f6c2e6b7279707465782e636f6d2f1550cad31e016e7bf00f2ecb ffffffff 02 cc84ce1d34000000 22 5120e31e8032a67b9af27dc279f448c003457bae6c5d28de7ee719bc87b6801ede17 0000000000000000 26 6a24aa21a9ed78cc1a61dcfcee9c59ddd9f4d56a98764c071e077bcc36fe9d1cf0aad50ebac3 01 20 0000000000000000000000000000000000000000000000000000000000000000 00000000
Field Bytes Value
Version version 4 @0 2 int32 little-endian. Pearl wallets and pearld coinbases use version 1; relay policy accepts 1-2.
Marker marker 1 @4 0x00 Segwit marker (BIP-144): says witness data follows the outputs.
Flag flag 1 @5 0x01 Witness flag; 0x01 is the only value Pearl accepts.
Input count vin.length 1 @6 1 CompactSize number of inputs.
Previous txid vin[0].txid 32 @7 0000000000000000000000000000000000000000000000000000000000000000 All zeros: this input creates new coins (coinbase).
Output index vin[0].vout 4 @39 0xffffffff 0xffffffff together with a zero txid marks a coinbase.
scriptSig length vin[0].scriptSig.length 1 @43 39 CompactSize length of the scriptSig.
Coinbase script vin[0].scriptSig 39 @44 0309ff01048393d76a2f706f6f6c2e6b7279707465782e636f6d2f1550cad31e016e7bf00f2ecb Coinbase data. It starts with the block height 130825 (BIP-34, required in every Pearl block), then anything the miner likes.
Sequence vin[0].sequence 4 @83 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this.
Output count vout.length 1 @87 2 CompactSize number of outputs.
Amount vout[0].value 8 @88 223,838,373,068 grains (2238.38373068 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains).
Script length vout[0].scriptPubKey.length 1 @96 34 CompactSize length of the locking script.
Locking script vout[0].scriptPubKey 34 @97 prl1puv0gqv4x0wd0ylwz086y3sqrg4a6umza9r08aecehjrmdqq7mctsmqaqsh OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output.
Amount vout[1].value 8 @131 0 grains (0.00000000 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains).
Script length vout[1].scriptPubKey.length 1 @139 38 CompactSize length of the locking script.
Locking script vout[1].scriptPubKey 38 @140 witness commitment 78cc1a61dcfcee9c59ddd9f4d56a98764c071e077bcc36fe9d1cf0aad50ebac3 OP_RETURN aa21a9ed ‖ SHA256d(witness Merkle root ‖ nonce): the BIP-141 witness commitment.
Witness items witness[0].length 1 @178 1 Number of witness stack items for input 0.
Witness reserved value length witness[0][0].length 1 @179 32 CompactSize length of this witness item.
Witness reserved value witness[0][0] 32 @180 0000000000000000000000000000000000000000000000000000000000000000 The coinbase witness is one 32-byte value (the witness-commitment nonce); pearld uses zeros.
Locktime locktime 4 @212 0 0: no time lock.
txid
0a2acb6004406b21252d1578585dec84efd7e7547f1bca19c30c17538c51caa0
Size
216 bytes · 189 vbytes
Block
130,825

Its single paying output, 2,238.38373068 PRL, is exactly that block’s subsidy plus the fees of its other 114 transactions. PRLScan labels the block’s miner as Kryptex.

Merged-mining tags. The coinbase of block 130,792 carries the text NOCKCHAIN-AI-POW-AUX and a 32-byte value, and an extra OP_RETURN output starting with the ASCII NAC*. That looks like merged mining: the same work also committed to another chain. That block split its reward 99% / 1% between two Taproot outputs. In a 200-block sample, the eight coinbase-only blocks that left out the witness commitment all came from this miner.

Independent counts. Sites such as MiningBoard and PRLScan publish pool statistics. A 2026 study (Basu, arXiv 2606.04819) used pool data to list per-GPU rates, about 500–700 TH/s for an H100, and reported that the most widely used third-party miner contains no AI inference code. That study’s measurement covers one pool.

Make a guess

A pool member's GPU finds a ticket that beats the network's bar. Who gets the block reward?

Think of your answer first, then check it.

Answer Whoever the coinbase pays: the pool.

The pool built the template, so the pool chose the coinbase outputs, and the certificate is bound to the template’s first 76 bytes, Merkle root included. The member can’t redirect the reward without changing the coinbase, which would change the job key, the noise and the ticket. How the pool then shares the reward with its members is its own business, off-chain.

Code: checking a share against the pool's target

From verify.rs (zk-pow/src/api/verify.rs:96-134 at v1.5.2, on GitHub). The comment names its use: a pool’s share difficulty.

zk-pow/src/api/verify.rs Rust
/// `nbits_override`: when set (e.g. pool share difficulty from `mining.set_difficulty`),
/// jackpot difficulty is checked against this compact target instead of `block_header.nbits`.
pub fn verify_plain_proof(
    block_header: &IncompleteBlockHeader,
    plain_proof: &PlainProof,
    nbits_override: Option<u32>,
    seed_derivation: SeedDerivation,
) -> Result<()> {
    let (private_params, mut public_params) = plain_proof.parse_proof(*block_header, seed_derivation)?;
    public_params.sanity_check()?;
    // … every revealed entry must be in [-64, 64] …
    let compiled = CompiledPublicParams::from(&public_params);
    let noise = compute_noise(&compiled);
    let jackpot = compute_jackpot(&compiled, &private_params.s_a, &private_params.s_b, &noise);
    public_params.hash_jackpot = compute_jackpot_hash(&jackpot, compiled.a_noise_seed());
    check_jackpot_against_nbits(&public_params, nbits_override)?;
    Ok(())
}

The gateway’s rank-penalized target is computed in adjust_target (miner/pearl-gateway/src/pearl_gateway/comm/dataclasses.py:212-225 at v1.5.2, on GitHub).

The codex

Suggested

Up and down arrows move through the results, Enter opens one, Escape closes. Anywhere on the site, slash or Command K opens this search, and the square brackets [ and ] go to the previous and next page.