Mining Pool Behavior during Forks
Monday, July 15, 2024I have recently been looking at mining pool behavior during forks. Which block does a pool choose to mine on during a fork? Do they behave rationally and mine on their own block? In this post, I’ll detail the mining pool behavior during forks and give some recent examples of pool behavior.
I’ve also published a short-form video1 on this topic on Twitter and YouTube.
In Bitcoin, a blockchain fork usually happens when two mining pools find a block based on the same previous block at roughly the same time. The fork is usually resolved with the next block building on top of one of the two fork-blocks. One block becomes part of the active chain (wins) while the other one becomes stale (loses).
During a fork, the game theory is as follows: Pools that mined one of the fork blocks always want to mine on their own block and never on the competing fork-block. The chance of finding a block is equal to the share of network hashrate the pool has, and does not depend on who found the previous block. A pool with 5% of the network hashrate has a 5% chance to find a block on the competing pool’s block and a 5% chance of finding a block on his own block. However, mining on its own block, the pool can find the winning block and yield two blocks, the fork-block and the winning-block. Mining on the competing block, it can only yield the winning-block.
Pools that mined neither of the fork-blocks can freely choose which block to build on. By default, they usually end up mining on the block they validate first. Their chance to find a block is equal to their network hashrate. It does not matter which fork-block other pools are mining on.
Recent Examples
The block pools are mining on is sent along with the mining jobs the pools public stratum servers publish. To analyze pool behavior, I’ve been recording the stratum jobs during forks. Note that there are possibly multiple public or even private stratum endpoints that could publish different jobs. The data I have might be incomplete and not show the full picture.
ViaBTC and AntPool at height 848860
Originally posted here.
During the fork at height 848860 between ViaBTC and AntPool, AntPool started off by briefly mining an empty-block-job2, a mining job with no transactions in the block, on their own block but then switched to mining on ViaBTC’s block. By switching to ViaBTC’s block they abandoned their block and lost the chance to find the fork- and the winning-block. However, it turned out that Foundry was mining on the AntPool block and found a block on it. Despite abandoning its block, AntPool was able to include one block in the active chain.
AntPool and Foundry at height 848968
Originally posted here.
108 blocks later, AntPool and Foundry both mined a block at height 848968 resulting in another fork. Again, AntPool started off with an empty-block-job mining on their own block before switching to Foundry’s block 2. Foundry found a block 848969 causing AntPool’s block 848968 to become stale.
AntPool and Foundry at height 851170
Originally posted here.
Similarly, both Foundry and AntPool found a block at height 851170 and AntPool starts off with an empty-block-job2 on its own block before switching to Foundry’s block. AntPool ended up finding a block on top of Foundry’s block and both AntPool and Foundry end up with one block each. If AntPool had stayed on their own block, they could have ended up mining both blocks.
Foundry and AntPool at height 848477
Originally posted here.
The fork at height 848477 between Foundry and AntPool was different. All pools, including Foundry, started mining on top of AntPool’s block 848477. About 30 seconds3 in, Foundry switched to a different block at height 848477 mined by Foundry, and they end up finding block 848478 building on top of it. In this case, Foundry successfully switched to their own block, yielding two blocks in the active-chain while AntPool’s block became stale.
Why isn’t AntPool mining on their own blocks?
The question of why AntPool, who have been around since 2015 and have
mined 10% of all Bitcoin blocks in existence, are not switching to their own
blocks during forks remains open. Aren’t forks frequent enough to bother?
Probably, calling preciousblock
along with the submitblock
RPC when submitting a newly found block to their nodes would do the trick.
Maybe some part of their pool software is incompatible with this?
2024-08-05: A previous version of this blog post was called “Mining Pool Game Theory during Forks”. I’ve since changed the title to “Mining Pool Behavior during Forks” as I think this better reflects the contents.
- ↩︎
AntPool often mines an empty-block-job for 30 seconds after a new block. These empty jobs aren’t based on a block template generated by a Bitcoin Core node and probably originate from a custom mining job creation software. When the job creation software learns about a new AntPool block, it immediately publishes an empty-block-job for it and the block is probably submitted to a Bitcoin Core node. Probably at around the same time, the Foundry block arrives and is validated on the Bitcoin Core node. A Bitcoin Core node, by default, will mine on the block it validated first. This means that if they don’t manually switch, Foundry’s blocks must have reached the nodes first. ↩︎ ↩︎ ↩︎
Foundry implemented a “switch-to-own-block” logic and my guess is that they didn’t bother, or forgot, to implement sending a new mining job for it. The switch happened with the next job update they sent out. Foundry’s job updates happen every 30 seconds. ↩︎