The xOne team measures fair mint on XDC net2040 in three steps. It reads the miner of every canonical block from an archive node. It counts the blocks of each seat in a window. It divides the blocks in the window by the seats to get the fair share. For the numbers, see Four xOne clients minting fair share on XDC net2040.
net2040 is a public devnet of chain 2040 (follow guide). The xOneTS repository is private.
How is fair mint measured on net2040?
The count comes from the Rust archive node. For every canonical block in a window, the team reads the miner and adds one to that seat (xOneRS#140, comment of 2026-11-14T16:55Z). Two more checks sit beside the count: the leader formula says whose turn it is, and the mint gate checks that a seal is real.
Which windows does the count use?
The team reports three windows: the last 7,000 blocks, the last 24 hours, and the era since the seat set changed. The fair share depends on the seats in the window.
| Window | Blocks | Seats | Fair share |
|---|---|---|---|
| Last 7,000 blocks, 3.9 h, ending at block 839,216 | 7,000 | 14 | 500 blocks (7.14%) |
| Last 24 h, ending at block 839,283 | 43,200 | 13, then 14 from epoch 814,798 | a single figure is not given |
| Era from epoch 814,798 to block 840,174, 14.1 h | 25,377 | 14 | 1,813 blocks (7.14%) |
Sources: the comments of 16:55Z and 17:55Z on xOneRS#140.
The era window is the cleanest, because the seat count is constant in it. The range is inclusive: 840,174 minus 814,798, plus one, gives 25,377 blocks. Divided by 14 seats, that is 1,813 blocks, as the comment states it.
How do you read a window when the set changed?
Count only the blocks since the seat joined, and compare with the fair share for that span. In the 24 h window, the TypeScript seat sealed 1,742 blocks (4.03%). The seat joined the set at epoch 814,798, 18,700 blocks into the window. Over the 24,485 blocks since then, its expected count is 1,749. It sealed 99.6% of that.
How does the leader formula set the turns?
In V2, the leader of round r is masternodes[r % epoch % len]. The list is the list of the round: the new list when the block opens an epoch, else the parent's list (producer schedule spec).
The mint gate writes it as round % 900 % N on net2040: N is the list size and one epoch is 900 rounds (mint gate). The rounds where a seat leads are its eligible turns.
How does the mint gate check one seal?
The gate accepts a seal only if it passes three checks. It also records every miss with a cause (mint gate).
- Timestamp: the block is stamped after the flip. A block sealed before the flip does not count.
- Child link: the next block's parent hash is this block, and the block is canonical on an independent node.
- Own log: the client's log has the
sealed and sentline with the same number and hash (xOneTS net2040 mint run).
A miss is an eligible turn without a seal. The causes are candidate fault, network or peer, other validator, host or environment, and unknown. A miss with cause unknown blocks the gate.
Zero misses is an observation, not a guarantee. With n eligible turns and no misses, the 95% upper bound on the true miss rate is about 3/n. For 200 turns, that is near 1.5%.
How can I repeat a count with public JSON-RPC?
Read the miner field of eth_getBlockByNumber over a block range, then count the values. This is an example, not a script from the repository. It needs a node that holds the range and an RPC URL.
RPC=<rpc-url>
FROM=814798
TO=840174
for n in $(seq "$FROM" "$TO"); do
curl -s -H 'content-type: application/json' \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getBlockByNumber\",\"params\":[\"$(printf '0x%x' "$n")\",false]}" \
"$RPC" | jq -r '.result.miner'
done | sort | uniq -c | sort -rn
The loop makes one eth_getBlockByNumber call per block. The era window of 25,377 blocks therefore means 25,377 calls; run it against a node you operate.
The output has one line for each seat: a count and a lower-case address. xOneRS writes miner from the header coinbase (json.rs).
To get the seats, call XDPoS_getMasternodesByNumber with the hex block number and count the addresses. The method name is case-exact. See the RPC surface and the RPC docs.
Divide the blocks in your range by the seats to get the fair share. Check the seat list at the first and last block of the range. If the lists differ, the set changed inside your range.
What does the method not capture?
It does not capture turns that did not end in a block, and it does not capture set changes inside a window.
- Turns and blocks differ. The formula picks a leader for a round. When a round times out, the nodes form a timeout certificate and enter the next round (timeouts spec). A block count shows only the rounds that ended in a block. The mint gate counts turns, from the formula.
- Outages move blocks to other seats. The comment of 17:55Z says two geth seats at 7.24% took the turns that the Python seat lost in its 27-minute outage.
- Set changes inside a window. A seat that joins mid-window shows a low raw share, as the TypeScript seat did in the 24 h window. Use the era window or the expected count since the join.
How do other clients report fair share?
The XDC geth fork and erigon-xdc published a fair share on 7-member sets. Compare each with the ideal share of its own set, not with 7.14%.
| Client | Set | What the release states | xOne on net2040 |
|---|---|---|---|
| XDC geth fork, v-xdc-geth-mint-20260727 | 7-member private net | 128 of 900 blocks (14.2%) in V1 and V2, 2026-07-27 | 14 seats, fair share 7.14% |
| erigon-xdc, v-xdc-erigon-mint-20260727 (private repository) | 7-member set | Fair share 14.2%, ideal 14.29%, 2026-07-27 | 14 seats, fair share 7.14% |
For the networks, see the network list.
Frequently asked questions
How is the fair share computed?
It is the blocks in a window divided by the seats. For the era of 25,377 blocks and 14 seats, the comment states 1,813 blocks, or 7.14%.
Does a block count equal the number of turns?
No. The leader formula is per round. A round that times out ends with a timeout certificate, so the count of blocks can be lower than the count of turns.
Can I repeat the count myself?
Yes. Read miner with eth_getBlockByNumber over a block range, as in the example above.
Sources
- xOneRS#140: comments of 2026-11-14T16:55Z (windows, archive count) and 17:55Z (era window).
- Producer schedule spec
- V2 timeouts and SyncInfo spec
- xone-rpc json.rs and net2040 follow guide
- Mint gate and net2040 mint run, xOneTS (private repository)
- XDC geth fork mint release and erigon-xdc
This article describes the source and evidence at its review date. Check the linked repository for current implementation and qualification status.
Explore the engineering evidenceEdit this page on GitHub opens the Markdown source (content/blog/fair-mint-measurement/index.md). GitHub may ask you to sign in. Report a correction opens a prefilled GitHub issue for this page.