§ 07 · Blocks
Version
Four bytes inherited from Bitcoin that Pearl never checks
On this page 6 sections
The version is the first field of every Pearl header: 4 bytes holding a number.
In Bitcoin, that number is how miners vote for upgrades. Pearl copied the format along with the rest of Bitcoin’s header, but it never uses it for anything. No rule checks it, and none of Pearl’s upgrades was voted in this way.
So this page is short, and mostly a history lesson. It’s still worth knowing, because explorers show the version on every block, and one stretch of Pearl’s history has an odd value that looks meaningful but isn’t.
Try it
The converter starts at 536,870,912, which is 0x20000000. Look at its 4 bytes in little-endian order: they’re the first 4 bytes of almost every Pearl header.
What does it look like?
- Size
- 4 bytes
- Type
- Signed integer (int32)
- Format
- Little-endian
- Range
- Any value; not checked
| Field | Bytes | Value |
|---|---|---|
| Version header.version | 4 @0 | 0x20000000 int32 LE. BIP-9 style 0x20000000 since block 1; no consensus meaning in Pearl. |
| Previous block header.prevBlock | 32 @4 | eb555c52c695cfa0b2ad27f0d1f96ca55f1dc32d864e13218b4bd9041b969c99 Hash of the parent block, stored byte-reversed; shown in display order. |
| Merkle root header.merkleRoot | 32 @36 | c6c21c0c4204b9f39e17d7f79811aff53eac88ea0d80fcdeffdad96ba3fa8963 Root of the SHA256d Merkle tree of this block’s txids, stored byte-reversed. |
| Time header.timestamp | 4 @68 | 1792513562 (2026-10-20 16:26:02 UTC) uint32 LE Unix seconds. Must be at least 1 s after the parent and at most 5 min in the future. |
| Bits header.bits | 4 @72 | 0x176af3a6 Compact target. Difficulty 40157376.49334089. The certificate's jackpot hash (not this header's hash) must meet it. |
| Proof commitment header.proofCommitment | 32 @76 | 49e67ac73638201f2815a24689b8b1df672f9176df2ee232b00c1632fda3524d SHA256d(LE32(certificate version) ‖ public data). Replaces Bitcoin’s nonce: Pearl headers have no nonce. |
Block 130,827’s header starts with 00 00 00 20. Integers are stored little-endianLittle-endian: Storing a number that spans several bytes with its smallest byte first. Pearl, like Bitcoin, stores numbers this way, and shows hashes with their bytes reversed., smallest byte first, so you read the bytes backwards: 20 00 00 00, the number 0x20000000 (536,870,912 in decimal).
Pearl’s chain has used three values:
| Blocks | Version | Bytes in the header |
|---|---|---|
| Genesis (block 0) | 1 | 01000000 |
| 1 onward, normally | 0x20000000 | 00000020 |
| About 2,100 to 100,799 | 0x20400000 | 00004020 |
Why 0x20000000?
Because of Bitcoin’s version bitsVersion bits: Bitcoin’s scheme for miners to signal support for an upgrade by setting bits in the header’s version field. Pearl inherited the machinery but upgrades at fixed heights instead, so the bits mean nothing. scheme, BIP 9. Written in binary, the version splits into two parts:
- The top three bits are
001. That says “this block uses version bits”. It’s what makes every version start with hex digit 2. - The other 29 bits are signals. Each proposed upgrade (a deployment) is given one bit. A miner who supports it sets that bit. If enough blocks in a 2,016-block window signal, the upgrade locks in.
With no signals set, you get exactly 0x20000000. Pearl’s node builds every block template’s version this way, starting from those top bits and adding the bit of any deployment currently being voted on.
What was 0x20400000 about?
For most of Pearl’s first 100,000 blocks, the version was 0x20400000: the same number plus bit 22. It looked like a vote for something. It wasn’t, really.
Pearl’s mainnet settings define only three deployments, all test dummies left in from the btcd code Pearl is built on, on bits 28, 22 and 30. Nothing in the code depends on any of them. The bit-22 dummy is a “speedy trial” deployment that can only activate after block 100,000.
The chain data fits this story, though the exact history is an inference, not something the code records. The dummy was switched on soon after launch, so templates set bit 22 from roughly block 2,100. It then locked in and waited for its minimum height. It became active at block 100,800, the first 2,016-block boundary after 100,000. Once active, a deployment stops being signalled, so templates went back to plain 0x20000000.
The bit never had any consensus effect.
Does anything check the version?
No. Pearl’s node has an error code for “block version too old”, inherited from btcd, but the block validation code never raises it. As far as Pearl’s consensus rules go, the version can be any 4 bytes.
That makes the version a rare thing in a Pearl header: data that is hashed into the block’s ID, but means nothing.
How does Pearl upgrade instead?
At fixed heights, written into the node software. Each fork switches on at a set block number, and the two hard forks also changed the certificate version that blocks must carry:
| Height | Fork | Kind | What changed |
|---|---|---|---|
| 71,935 | MoE hard fork | hard | Blocks must carry a V2 certificate, which adds support for Mixture-of-Experts proofs. |
| 91,630 | Dense-only soft fork | soft | Mixture-of-Experts proofs are rejected again; only dense proofs count. |
| 96,251 | Rank-penalty soft fork | soft | Noise rank must be at least 128, and a higher rank makes the winning bar stricter in proportion. |
| 99,000 | Salted noise-seed hard fork | hard | Blocks must carry a V3 certificate: the noise seeds now also commit to the matrix sizes. |
Code: the top bits and the template version
From calcNextBlockVersion (node/blockchain/versionbits.go:278-296 at v1.5.2, on GitHub): start from the top
bits, then add the bit of every deployment that is being voted on or is locked in.
vbTopBits = 0x20000000
expectedVersion := uint32(vbTopBits)
for id := 0; id < len(b.chainParams.Deployments); id++ {
deployment := &b.chainParams.Deployments[id]
state, err := b.thresholdState(prevNode, checker, cache)
if state == ThresholdStarted || state == ThresholdLockedIn {
expectedVersion |= uint32(1) << deployment.BitNumber
}
} The three test deployments, including DeploymentTestDummyMinActivation on bit 22 with
MinActivationHeight: 100000, are in params.go (node/chaincfg/params.go:398-429 at v1.5.2, on GitHub).