How Proof of Feed Works: A Technical Walkthrough
Proof of Feed is not a metaphor. It is a precise, five-phase protocol that runs on every block. This post walks through each phase in detail — the data structures, the cryptographic commitments, the verification logic, and the economic consequences of failure.
The problem Proof of Feed solves
Before the protocol, the problem. A blockchain needs a way to decide who gets to produce the next block. Bitcoin uses hashcash. Ethereum uses staked capital. Both systems work, but neither requires the block producer to do anything useful for the world.
Proof of Feed changes the constraint. To produce a block, a miner must prove that they ran real AI inference through a live Blazil engine. The proof is not self-reported — it is anchored in TigerBeetle, a distributed ledger that no single party controls.
If you cannot run Blazil, you cannot mine. If you fake the proof, you get slashed. The incentives are aligned with real work from the first block.
Phase 1: Commit
The first thing a miner does when it receives a data chunk is compute a commitment and broadcast it to the network.
chunk_hash = BLAKE3_domain(CHUNK, chunk_data)
transfer_id = BLAKE3_domain(TRANSFER_ID,
chunk_hash ++ block_height_le64 ++ miner_pubkey)[0..16]
intent = Intent { transfer_id, chunk_hash, block_height, miner_pubkey }
The Intent is broadcast to the P2P network before any inference happens. This is the anti-front-run mechanism. Once the Intent is gossiped, no other miner can claim the same TransferId for the same block height. The commitment is public and timestamped by the gossip layer.
The BLAKE3 domain separation is important. Every hash in the protocol uses a different domain tag. This prevents length-extension attacks and makes each hash type semantically distinct. The fc-crypto crate enforces this at the type level.
Phase 2: Feed
With the Intent broadcast, the miner submits the data chunk to Blazil via Aeron IPC.
Aeron uses memory-mapped files on /dev/shm for zero-copy transport between the miner process and the Blazil process on the same machine. The stream ID is determined by the SLA tier:
Critical (<1ms): publish=100, subscribe=101
High (<5ms): publish=200, subscribe=201
Normal (<50ms): publish=300, subscribe=301
Blazil receives the chunk, routes it through the LMAX Disruptor ring buffer, and runs inference via the Tract ONNX runtime. The Disruptor operates at 84ns P99 — faster than a CPU cache miss. The entire inference pipeline is zero-copy from IPC handoff to output.
Phase 3: Anchor
After inference completes, Blazil commits a TransferId to TigerBeetle VSR.
TigerBeetle is a distributed financial ledger built for deterministic, fault-tolerant operation. VSR (Viewstamped Replication) provides Byzantine fault tolerance across the cluster. A commit to TigerBeetle is final the moment it is acknowledged — there is no probabilistic confirmation.
The transfer uses code=1, ledger=1 — a memo transfer with amount=0. It records that inference happened, not money movement. The TigerBeetle response has two valid outcomes:
Ok(()) // new transfer committed
Ok(()) // transfer already exists (idempotent — both are valid proof)
Err(e) // genuine error — not a valid proof
The Exists case is intentional. Network retries may cause a duplicate commit attempt. Both outcomes are valid proof. Only a genuine error invalidates the anchor.
Phase 4: Receipt
With the TigerBeetle commit confirmed, the miner constructs a FeedReceipt:
pub struct FeedReceipt {
pub transfer_id: u128,
pub chunk_hash: [u8; 32],
pub block_height: u64,
pub miner_pubkey: [u8; 32],
pub blazil_node_id: [u8; 16],
pub inference_cid: [u8; 32],
pub latency_ms: u32,
pub timestamp: u64,
}
The miner signs this with their Ed25519 private key using a domain-separated tag. The signature covers all fields — any tampering invalidates it.
The signed FeedReceipt becomes a FeedProof, which is included in the block candidate. The miner broadcasts the candidate to the validator set.
Phase 5: Verify and Finalize
Validators receive the block candidate and perform three checks in order:
- Verify Ed25519 signature on FeedProof
- Verify block_height matches the current expected height
- Query TigerBeetle: does transfer_id exist?
Step 3 is the real proof. Steps 1 and 2 are pre-filters that avoid wasting TigerBeetle lookups on obviously invalid blocks. A validator that finds the TransferId votes to accept the block. One that does not immediately rejects it and triggers a slash proposal.
Once 2/3 of the validator set (weighted by staked F) has precommitted, the block is finalized. The BFT round completes in approximately 7 seconds worst-case (3s propose + 2s prevote + 2s precommit), with a target of 10s per block.
On our 3-node devnet, we measured 66µs from proposal to finality. This will increase as the validator set grows, but the deterministic nature of BFT finality means there is no confirmation waiting — the block is final the moment the quorum is reached.
What happens when things go wrong
The protocol has explicit handling for every failure mode.
Invalid proof: TransferId not found in TigerBeetle. Block rejected. Miner's 10% stake slashed. The slash is executed atomically via TigerBeetle linked transfers — if the slash transfer fails, the rejection also fails, maintaining consistent state.
SLA violation: If the measured latency_ms exceeds the committed SLA tier:
actual <= committed: normal rewardcommitted < actual <= 2x: 50% fee refund to requester from miner stakeactual > 2x committed: 100% fee refund plus 0.05% stake slash
Challenge protocol: 5% of inference jobs per epoch are randomly re-verified. The challenge seed is derived from a future block hash, which the miner cannot predict at job acceptance time. If the re-run output diverges beyond the model-specific threshold, the original miner is slashed 100%.
The numbers from devnet
On our local 3-node devnet running on an Apple M4:
- Inference latency: 1.335ms for a 1,595-byte request
- BFT finality: 66µs from proposal to all-nodes confirmed
- Block height reached: 20 (genesis + 20 PoF blocks)
- Proof validity rate: 100% (no slash events)
The 66µs finality is a local measurement with no network overhead. Production finality will be higher, bounded by validator network latency. We expect 200-500ms on a well-connected global validator set of 21 nodes.
The full specification is at github.com/feedable-network-lab/feedable-blockchain-coin.