Skip to content

Claim Burn

  • What a burn claim is and why it exists.
  • The three pieces of a claim proof: a burn commitment, an ownership proof and a burn output inclusion proof.
  • How validators scan Minotari block headers so that a proof can be checked without a base node.
  • How a claim is executed by the engine and how double claims are prevented.

The Ootle has no minting mechanism of its own. Every tTARI/$TARI on the Ootle got there by being burned on the Minotari base layer (L1) and then claimed on the Ootle (L2). This is a one-way peg: L1 supply decreases by exactly the amount that L2 supply increases.

Minotari (L1) Ootle (L2)
┌──────────────────────────┐ ┌──────────────────────────┐
│ Burn transaction │ claim proof │ ClaimBurn instruction │
│ • burn output │ ──────────────▶ │ • verify proof │
│ • commitment C = vH+kG │ │ • write tombstone │
│ • ownership proof │ │ • mint stealth UTXO │
└──────────────────────────┘ └──────────────────────────┘
value leaves L1 value appears on L2

A burn is addressed to a specific L2 claimant at the time of the burn. Only the holder of that claimant’s key can turn the burn into spendable funds.


When a Minotari wallet burns funds for the Ootle it produces a burn output: an output of type Burn whose commitment C = v·H + k·G commits to the burned value v with blinding factor k. The burn is bound to an L2 claimant with a stealth claim key:

p, P = p·G claimant's Ootle account key (secret, public)
r, R = r·G one-time nonce chosen by the L1 burner
s = H(r·P) + p stealth claim secret, known only to the claimant
S = s·G stealth claim public key, computable by the burner as H(r·P)·G + P

The output carries S in its ConfidentialOutput sidechain feature. The burner then signs an ownership proof: a Schnorr signature under the blinding factor k over the message H(C ‖ S ‖ sidechain_id). This proves knowledge of the commitment opening and binds the burn to both the claimant S and the target sidechain.

The sidechain id identifies which Minotari sidechain the burn is for. It is the public key of the sidechain’s L1 deployment key, and every validator on that sidechain is configured with the same value. The Ootle itself uses a blank sidechain id, so a burn with no sidechain id is a burn for the Ootle. Other sidechains built on Minotari each bind burns to their own key, and L1 checks that the deployment key signed S. A validator only accepts a burn output tagged with its own sidechain id: a burn with no ConfidentialOutput feature is never claimable.

The wallet bundles everything the Ootle needs into a claim proof:

FieldPurpose
commitmentThe burn commitment C
valueThe burned amount v (revealed; needed to check C)
ownership_proofSchnorr signature over H(C ‖ S ‖ sidechain_id)
outputThe burn output’s hashed fields: its features (with S), the nonce R, and the rest as L1 encodes them
inclusion_proofThe L1 block hash and a two-level MMR proof of the output hash in that block

The Minotari wallet fetches the inclusion proof from its base node as soon as the burn confirms, and saves it in the burn proof file. Building the proof needs the full block, which a pruned base node discards once the block falls behind its pruning horizon. To regenerate a proof later, for example after losing the proof file or restoring a wallet from its seed words, connect the wallet to an archival base node.


Validators must decide whether a claim proof refers to a real burn on the canonical L1 chain. Doing this by querying a base node per claim would be slow, non-deterministic and a trust dependency. Instead, every validator keeps a compact local copy of the L1 block headers and verifies proofs against those.

Validators already scan the L1 chain to derive epochs and validator set changes. With header sync enabled, the scanner stores a minimal record of every header it crosses, keyed by epoch:

L1 chain (lagged by the confirmation window)
───┬────────┬────────┬────────┬────────┬────────┬───▶
│ h=1000 │ h=1001 │ h=1002 │ h=1003 │ h=1004 │
└────┬───┴────┬───┴────┬───┴────┬───┴────┬───┘
▼ ▼ ▼ ▼ ▼
┌────────────────────────────────────────────────────┐
│ Validator header store (per epoch) │
│ block_hash → { height, block_output_mr, ... } │
└────────────────────────────────────────────────────┘

Only the fields needed for verification are kept, so the proof-of-work data is discarded right after hashing. The scanner runs a fixed number of blocks behind the L1 tip, and if a reorg is detected the orphaned headers are deleted and the affected range is rescanned, so the store converges on the canonical chain.

A claim is accepted when all of the following hold:

claim proof
│
├─▶ 1. Burn output rules
│ the output's sidechain id == this chain's sidechain id
│
├─▶ 2. Ownership proof
│ k·G = C − v·H (recover the "public key" of the blinding factor)
│ verify Schnorr(k·G, H(C ‖ S ‖ sidechain_id))
│ where S = the claim key the burn output names
│
├─▶ 3. Output inclusion proof
│ look up header by block_hash (epoch < current)
│ hash the output: type Burn, a ConfidentialOutput feature naming S, commitment C
│ fold the hash to the normal output MMR root, then that root (the last leaf) to header.block_output_mr
│
└─▶ 4. Claim key signs
S is among the transaction's signers

Ownership proof. The verifier recomputes the challenge from the output’s claim key S and its own configured sidechain id, and checks the signature against C − v·H. A proof signed for a different claimant or a different sidechain fails here.

Output inclusion proof. The verifier hashes the burn output the way L1 does, with its type fixed to Burn, its sidechain feature fixed to a ConfidentialOutput naming S, and C as its commitment. It then checks the hash is in the block: the block output MMR has the block’s coinbases as leaves and, as its last leaf, the root of an MMR of every other output. Since the hash fixes the type, the feature and the commitment, a proof of any other output does not verify. If the header is not in the store the claim is rejected, which also covers burns newer than the validator’s scan position.

Claim key signs. The burner also knows k, so it can make an ownership proof for any key. The engine therefore requires S to sign the transaction, as its sealer or as one of its signers. Only the holder of the stealth claim secret s can claim the burn, even when someone else seals and pays the fee.

The verifier’s checks use only the proof and the local header store. No L1 network access happens at execution time, and every validator in the committee reaches the same verdict from the same inputs.


ClaimBurn is a transaction instruction. It may appear in the fee instructions, which lets a brand-new account pay its first fee from the funds it is claiming. On success the engine writes two substates:

ClaimBurn { claim_proof, output_data }
│
├─▶ verify (see above)
│
├─▶ ClaimedOutputTombstone @ address(C) { value }
│
└─▶ Utxo @ address(TARI, C) stealth UTXO worth v,
spendable by the claim key S

The UTXO is minted directly into the genesis TARI resource with the claim key S as the spend authorization, so the claimant alone can spend it, whoever sealed the claim. A typical claim transaction immediately spends it in a stealth transfer: a small revealed amount pays the fee and the remainder becomes a stealth output owned by the claiming account.

fee instructions:
ClaimBurn(proof, output_data) mint UTXO(C) owned by S
StealthTransfer { input: UTXO(C),
reveal: max_fee, → bucket used to pay the fee
output: stealth → account }

The tombstone is the anti-replay record. Its address is derived from the burn commitment C, so a given burn maps to exactly one substate id, and creating it is what makes the claim consume the burn.

first claim of C second claim of C
┌─────────────────────────┐ ┌─────────────────────────┐
│ output: tombstone(C) │ │ output: tombstone(C) │
│ substate does not exist │ │ substate already exists │
│ ✔ lock OUTPUT, commit │ │ ✘ lock conflict, abort │
└─────────────────────────┘ └─────────────────────────┘

This works at the consensus layer rather than in the engine:

  • The tombstone address is computable from the transaction alone, so validators know before execution which tombstones a claim will create. A claim transaction is routed to the shard group that owns that address.
  • On prepare, the committee takes an OUTPUT lock on the tombstone id. An output lock asserts that the substate does not yet exist; if it does, or if another in-flight transaction already holds an output lock on it, the transaction aborts.
  • Two claims for the same burn in the same block are serialised by the same lock: the first wins, the second aborts.

Because the sidechain id is part of the signed ownership message, a burn addressed to one sidechain cannot be claimed on another, and a burn claimed once on the Ootle leaves a permanent tombstone that no later claim can overwrite.