Block format¶
A Navio block is a Bitcoin-shaped block with BLSCT-aware transaction bodies.
Header¶
CBlockHeader (80 bytes)
├── nVersion int32
├── hashPrevBlock 32 bytes
├── hashMerkleRoot 32 bytes
├── nTime uint32
├── nBits uint32 compact difficulty target
└── nNonce uint32 Header nonce (legacy Bitcoin field; PoPS proof lives in block.posProof, not here)
Identical to Bitcoin at the byte level. All BLSCT / PoPS blocks use the same 80-byte header shape. Consensus-critical data that cannot fit in the header (the ZK proof itself) lives in block.posProof, appended outside the header.
Block body¶
CBlock
├── Header 80 bytes
├── posProof blsct::ProofOfStake (set-membership + range proof)
├── vtx[] CTransaction[]
│ ├── vtx[0] Coinbase (zero-value output)
│ ├── vtx[1] Coinstake (zero-value marker output, then reward outputs)
│ └── vtx[2..] Regular BLSCT transactions
└── witness commitment embedded in coinbase if any segwit-style fields used
Field order per primitives/block.h: READWRITE(obj.posProof, obj.vtx) after the header.
Coinbase¶
The first transaction is the coinbase. Its single output is zero-value; the real staker reward is paid in the coinstake. vin[0].prev_out is the null marker (32 zero bytes).
During the bootstrap PoW window (heights 2..110 on mainnet), the zero-value coinbase output still carries a full Bulletproofs+ range proof and BLSCT keys — the miner constructs it with fAllowZeroValueRangeProof = true.
Why a range proof on a zero-value coinbase
Normally CreateOutput() collapses a 0 amount into an unspendable OP_RETURN with no range proof. But the coinbase still carries balance and output signatures that are folded into the block's aggregate signature check — an OP_RETURN output (no range proof, no keys) would have nothing to sign over and the aggregate verification would fail. Passing fAllowZeroValueRangeProof = true forces a proper BLSCT output so the signatures remain valid.
The block-1 coinbase mints the entire initial supply.
Coinstake (PoPS)¶
Every block carries a blsct::ProofOfStake posProof field (see primitives/block.h). Structural markers:
vtx[0] (coinbase) — null prev_out, zero-value output
vtx[1] (coinstake) — first output is zero-value nonstandard marker
block.posProof — encoded ZK proof (set-membership + range proof)
Key points about PoPS — applies to the current BLSCT networks (mainnet, testnet, and blsctregtest):
posProofdoes not identify the staker's locked UTXO. It contains a set-membership proof over the current staked-commitment set plus a range proof binding a hidden stake amount to the block's kernel-hash eligibility threshold.- Eligibility is verifiable with zero-knowledge — no validator identity, amount, or cross-block linkage is revealed.
- Coinstake outputs pay the network's current PoPS subsidy plus returned principal as BLSCT outputs addressed to sub-addresses in the staker's staking pool (account
-2).
Full math, verifier equations, serialisation, source-tree map: BLSCT → Proof-of-Private-Stake.
Fee handling¶
| Source | Fate |
|---|---|
| Regular BLSCT transaction fees | Burned |
| OP_RETURN outputs | Burned — provably unspendable |
| Community fund (legacy Navcoin at mainnet genesis) | Burned |
| Staking rewards earned on migrated supply during swap window | Burned |
See Consensus for the full economic picture.
Merkle commitment¶
Standard Bitcoin-style Merkle tree of transaction hashes, committed to in the header. BLSCT transactions hash via their canonical serialised form including BLSCT-specific fields.
Block explorer view¶
The navio-blocks indexer categorises blocks via:
BLSCT-aware outputs display as Hidden amounts. Transparent outputs (genesis-time bootstrap outputs that seed the PoPS staker set on testnet cuts, and OP_RETURN burns) show values normally. See supply tracking.
Genesis block (mainnet)¶
The mainnet genesis block (height 0) is a plain unspendable OP_RETURN coinbase — not a BLSCT output. There is no range proof or BLSCT keys, because the genesis block is never connected to the UTXO set: ConnectBlock() in validation.cpp special-cases the genesis hash and returns early, so no spendable BLSCT output is ever needed.
| Field | Value |
|---|---|
| Block hash | 0af3c23ae1ac4910693b7187ac61641d16d1cf49cba7acf8649d48e831d86b13 |
| Merkle root | 96f8dfcc3c433012bc9d4b42e85fe543936609f87fce2cc9d5484383ee2f9aaf |
nTime |
1782910800 (2026-07-01 13:00 UTC) |
nNonce |
0 |
nBits |
0x207fffff |
nVersion |
0x40000000 (BLSCT version bit) |
The coinbase scriptSig embeds a hidden message:
Both nMinimumChainWork and defaultAssumeValid are zero — this is a fresh chain with no checkpointed history.
Serialisation¶
src/primitives/block.h—CBlock,CBlockHeader.src/blsct/pos/— PoS / PoPS consensus rules.src/consensus/params.h— chain-level constants (block time, max size, activation heights).
Current chainparams: mainnet uses a bootstrap PoW window through height 110 (PoPS from height 111), then PoPS with nPosTargetSpacing = 120 and nBLSCTBlockReward = 8 NAV; testnet uses a bootstrap PoW window through height 1000, then PoPS with nPosTargetSpacing = 60 and nBLSCTBlockReward = 4 NAV.