CPU coin lessons: hashrate hopping, difficulty retarget and pool bugsDisclosure: I'm the developer of ParnianCoin (PARC), a CPU-mined PascalCoin fork (RandomHash2). Everything below comes from running our own nodes and pools over the past few weeks. I'm sharing it because most of these problems apply to any small CPU-mined coin, and I wish I had read something like this before launch.
1. Hashrate hopping can stall a small network for hoursOn a small chain, a single rented or profit-switching miner can be several times larger than the entire regular hashrate.
What we observed in one day:
- Pool hashrate climbed from ~350 kH/s to over 1 MH/s within about an hour as a large worker joined.
- At the peak, around 60 blocks were found in ~2.5 hours, roughly one every 2–3 minutes (target: 5 minutes).
- Difficulty climbed ~1% per block, about 2.3x in total.
- Then the large miners left at almost the same time. Hashrate dropped to ~100 kH/s, and block times jumped to 20–60 minutes.
The hopper collects cheap blocks, then leaves everyone else to pay for the difficulty it created.
2. Your retarget algorithm decides how long the pain lastsWe inherited PascalCoin's retarget logic, which compares two windows: the last 100 blocks and the last 10 blocks.
- If both windows agree (both too fast or both too slow), difficulty moves normally: up to ~1% up or ~2% down per block.
- If they disagree, a "slow movement" mode kicks in and caps the change at ~0.5% per block.
This is designed to prevent oscillation, and on a large network it works well. But right after a hopping event, the 100-block window is still full of fast blocks ("too fast") while the last 10 blocks are 30+ minutes ("too slow"). The windows disagree, so difficulty drops only 0.5% per block.
In our case, the slow mode lasted 9 blocks (~4.7 hours). Once enough slow blocks had entered the long window, both windows agreed, and difficulty started dropping ~2% per block. About 15 hours after the hashrate left, difficulty was back to roughly half of its peak.
Lesson: if you launch a small CPU coin, think about this before launch. Options include faster-responding algorithms (e.g. LWMA-style), or an emergency rule when recent block times are several times the target. Any change here is a consensus change, so it needs a planned activation height on all nodes.
3. Test your pool with nonces above 2^31For weeks, a large share of our pool-found blocks were orphaned (over one week: ~2,650 orphans vs ~2,040 confirmed blocks). Clock sync, forks between nodes and stale jobs were all suspects. None of them was the cause.
The real cause: the node's JSON parser stored numbers in a
signed 32-bit integer. The nonce is an unsigned 32-bit value, so any valid solution with a nonce above 2,147,483,647 (about half of all solutions) raised an exception during parsing. The submission was silently dropped, while the pool logged "Block found" and later marked it orphaned.
Clues that pointed to it:
- Orphans at a given height had smaller (stronger) hashes than the block that was eventually accepted, so it was not a PoW problem.
- After "Block found", the pool kept receiving work for the same height, so the node had rejected the block, not reorged it.
- The node log showed "'2684641225' is not a valid integer value" at the exact second of each lost block.
After switching the parser to 64-bit integers: in the ~280 most recent blocks we reviewed, there was a single orphan (a duplicate solution submitted in the same second, which is expected).
Lesson: if you fork an older codebase, especially across compilers or platforms, grep for every place a nonce, timestamp or amount passes through a 32-bit signed type.
4. "CPU-only" does not automatically mean decentralizedCPU mining lowers the hardware barrier, but on a small network a few server-grade or rented machines can still hold a large share of the hashrate. Botnets are a further concern for every CPU-mineable coin. There is no perfect fix. Transparent hashrate stats and a growing base of small, independent miners are the realistic defenses.
Open question for other devs and miners:How have other small CPU coins handled hashrate hopping? Did an emergency difficulty rule or LWMA actually solve it in practice, or did it introduce new problems?