Why a pool needs its own identity, not each miner's
Quantum-Lattice just shipped a mining pool, and the core design decision worth writing about is one that isn't obvious until you actually try to build it: a pool can't simply "collect" rewards on behalf of whoever finds them.
The proof-of-work hash includes the miner's own public key as an input:
sha3_256(version, previous_block_hash, merkle_root, block_height, miner_pubkey, nonce)
That means a winning nonce is cryptographically tied to whichever address was hashed with it. If each connected contributor searched using their own address, a share that happened to also satisfy the real network difficulty would be a valid block — but only under that specific miner's identity. The pool could never swap in its own address afterward and resubmit; changing the address changes the hash entirely.
The actual fix
The pool builds one template using its own address, and hands that exact template out to everyone connected. Every contributor searches for a nonce against a header that already has the pool's identity baked in — their own wallet address is only ever used separately, for bookkeeping, never inside the actual hash.
Concretely:
- Pool fetches a real template from the node (block height, previous hash, merkle root, real difficulty)
- Pool constructs a candidate header using its own address as the "miner" field
- Pool hands this out to connected miners, at a deliberately easier, pool-set difficulty
- A miner finds a nonce meeting the easier target, submits
{their own address (for credit), nonce} - Pool checks: does this nonce, on the header with the pool's own address, also satisfy the real difficulty?
- If yes — genuine block, submitted under the pool's identity, real reward earned
- Pool signs and sends individual payouts to every contributor, proportional to shares submitted since the last win
A real bug this design surfaced
The first version of the payout logic assumed the pool had just earned a full 48 QL block reward, and split that fixed amount. During testing — funding the pool with a smaller, deliberate test amount to verify the split logic without waiting on real network odds — it tried to sign a payout for more than the pool's actual balance.
The fix: query the pool's real, current balance from the node immediately before calculating any payout, rather than assuming a fixed reward amount. Obvious in hindsight, but a good reminder that "we know what triggered this" doesn't mean "we know how much is actually available" — those are separate facts, and only one of them is safe to assume.
Testing it properly before shipping
Two independent machines contributed real, different amounts of work. The pool was funded with a small, real amount specifically to test the payout mechanism without waiting on genuine 38-bit network odds. The trigger produced two separate signed transactions, correctly proportional to each machine's actual share count, and both wallets showed the correct, confirmed balance increase shortly after.
That's the difference between "the logic looks right" and "the logic is right" — worth the extra step before anything goes live.
What's next
Difficulty is currently one fixed value for every connected contributor. A meaningfully better version adjusts difficulty per miner, based on their individual submission rate — so a high-end machine and a modest laptop both get a similarly steady rhythm of shares, rather than one flooding the pool and the other waiting a long time between confirmations. Real, valuable improvement, not yet built.
Code: https://github.com/AlthaafM/Quantum-Lattice
Try it: https://quantum-lattice.futuristicai.co.za
Top comments (0)