Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Shielded CSV protocol specification

Authored by: https://ideal.group/ Last revised: 24 Oct 2026

Shielded CSV is a private payments protocol designed for maximum throughput and minimal latency. It moves state-transition proofs and their validation to the client, resulting in lightweight consensus. Double-spending is prevented through publication of a sigil: an object that nullifies the previous committed account state and commits to a new account state on-chain. BTC enters the system through L1 deposits: for each block, consensus finalises a public deposit account whose outgoing coins are that block’s deposits, and the owner of each deposit’s address receives its coin like any other.

This document outlines the key concepts, data structures, relations, and architecture of a minimum viable version of Shielded CSV, instantiated as a metaprotocol on Bitcoin. It treats cryptographic primitives, including zk-SNARKs, as black boxes.

Key concepts

Sigils and finalisation

Account state transitions and validity proofs are kept off-chain and periodically finalised on-chain. An outgoing coin becomes receivable only after the sender proves that the state containing it was finalised.

An account progresses through epochs. Within each epoch, it may perform multiple off-chain transitions. At the end of an epoch, it publishes a sigil committing to its final state:

Here, nullifies the previous committed account state, and commits to the state being finalised.

For one account, the off-chain state sequence is:

The state is the state committed by the published sigil. The double arrow denotes . It verifies finalisation and produces the first state of the next epoch.

Borrowing from the Tachyon design, consensus prunes historical sigil data. In other words, consensus only guarantees nullifier uniqueness only within a recent window; for older sigils, clients must obtain exclusion proofs from other services, such as a verifiable RPC (vRPC).

Payment flow

  1. The sender constructs outgoing coins using .
  2. The sender obtains an exclusion proof for its publication key through Shielded CSV height , covering the interval from its account anchor through , inclusive.
  3. The sender publishes its sigil within blocks of the exclusion proof end range, i.e. at height , where and obtains a publication proof.
  4. The sender executes , verifying publication and exclusion proofs.
  5. The sender constructs a coin proof establishing that the outgoing coin belongs to the finalised account.
  6. The sender sends the coin and its proof to the recipient out-of-band.
  7. The recipient verifies the coin proof, checks that it is addressed to him and that he has not received it before, and credits the coin’s value using .

Deposit flow

BTC enters Shielded CSV through an L1 transaction paying . Since L1 Bitcoin is also the DA layer, consensus sees the deposit in the block that confirms it. For every such block, consensus builds a deposit account whose outgoing coins are the block’s deposits, and inserts a deposit sigil finalising it. The deposit account’s key is a nothing-up-my-sleeve point, so the account is public and nobody else can publish for it.

A deposit has two roles, which may be the same party: the depositor, who pays BTC on L1, and the recipient, who owns the address the deposit names and credits the coin. The depositor needs no Shielded CSV account, only an L1 wallet that can add an output.

  1. The recipient hands the depositor a 32-byte address, through an invoice or otherwise.
  2. The depositor broadcasts a transaction with an output paying and an output carrying that address.
  3. The transaction confirms in DA block , at Shielded CSV height . From the ledger root at height and the block’s deposit outputs, consensus builds the deposit account state and places its deposit sigil first in the leaf for . The validator signs a ledger root covering that leaf.
  4. Someone rebuilds from and the block’s deposit outputs, obtains the deposit sigil’s publication proof from any full node or vRPC, and constructs the deposit coin proof for the coin.
  5. The recipient’s account verifies the coin proof and credits the coin using .

Step 4 uses only public data, so the recipient, the depositor, or a vRPC may perform it; the recipient needs only the coin proof, or only the outpoint, from which it can build the proof itself. Beyond L1 confirmation, the only latency is the validator signing the root, which it does for every block regardless.

A deposit may pay any address, including one of an existing account. The recipient retains nothing beyond its seed: it recovers a deposit from L1 data and the address opening.

is a function of public data, so a deposit sigil is publicly auditable: any party with an L1 view recomputes for a block and compares it with the sigil consensus inserted. A validator that credits a deposit L1 does not contain, inflates one, or omits one is caught by every full node, in the same way as one that accepts an invalid sigil. Anyone can also check that the total value of all deposit sigils does not exceed the total ever paid to .

Architecture

Consensus layers

ComponentResponsibility
Shielded CSV consensusValidate sigils, enforce the recent uniqueness window, insert deposit sigils, and maintain the ledger accumulator
Multisig bridgeHold BTC deposited to and handle withdrawals
L1 BitcoinHold the native BTC backing asset and carry deposit transactions
DA layerCarry published sigil bundles; L1 Bitcoin is also the DA layer, and the initial demo uses Mutinynet

Unpermissioned nodes

Light client

The light client maintains the user’s plaintext account state, proofs, and local accumulator data.

It obtains publication and exclusion proofs from vRPC or archival services, verifies them, and authenticates the ledger roots it receives.

Full node

A full node reads the DA layer and independently enforces the Shielded CSV consensus rules, including:

  • signature verification;
  • sigil anchor admissibility;
  • deterministic processing of candidate sigils;
  • nullifier uniqueness within the -block window; and
  • deposit extraction, recomputing each block’s deposit sigil directly from the L1 block.

It maintains the ledger accumulator and recent validation state. Historical proof-serving data may be pruned.

Verifiable RPC (vRPC)

A vRPC retains a range of historical sigils and corresponding accumulator data, and serves publication and exclusion proofs.

Its responses are verified by clients. No correctness assumption is placed on the service.

Archival node

An archival node retains historical sigils and the data required to serve older publication and exclusion proofs.

Permissioned parties

Validator

The validator enforces the consensus rules and signs ledger MMR roots.

Light clients relying on these signatures trust the validator to enforce the rules, construct the accumulator correctly, and not equivocate. These are safety assumptions in addition to the liveness assumption of non-censorship.

The signed roots also commit to deposit sigils. Full nodes recompute each deposit sigil from L1, so a validator that invents or omits a deposit is detected in the same way as one that accepts an invalid sigil. Light clients take deposit sigils from the signed root, which is the existing safety assumption.

Publisher

The publisher collects sigils into bundles, signs the bundles, and submits them to the DA layer.

In the initial iteration, the publisher and validator are the same party. Publisher signatures may provide preconfirmations, but do not replace the publication and exclusion evidence required by the account relations.

Wallet

The wallet is the client-side implementation of the account relations. It holds the plaintext account state and keys, and follows these rules, which are not enforced by any circuit.

Genesis key generation

The client generates and outside the circuit. It should derive from its seed and , so that no two of its accounts share a genesis key.

Deposits

A deposit is credited by whoever owns the address in its , so a wallet is involved on the receiving side even when the depositor is a plain L1 wallet. A deposit output with a malformed , or naming an address nobody owns, is unrecoverable. When the wallet is itself the depositor, it constructs the deposit transaction rather than handing the user a bridge address to pay.

A deposit is public on L1: the output value and the recipient address are visible to everyone, forever, as in any transparent-to-shielded transfer. The receiving wallet hands out a fresh diversified address for every expected deposit and never reuses it in an ordinary invoice, so that the L1 link reaches only that one address.

The receiving wallet discovers deposits by watching L1 for outputs naming its addresses, and on recovery from seed it scans for them. It can build the deposit coin proof itself, so it needs nothing from the depositor beyond the transaction.

Signing and retries

A publication key must have at most one live sigil. Retransmitting an identical signed sigil is permitted; signing a changed commitment or anchor under the same key is not, while the earlier sigil may still be accepted.

Before replacing a submitted candidate, the client establishes that:

  • the old sigil anchor is no longer admissible for the next publication block; and
  • the account’s publication key has not appeared from the account anchor through the current authenticated tip.

The client then discards the old candidate and signs the current state.

An unsuccessful publication does not itself execute an account transition. A successfully published candidate must be applied to its exact committed state.

Historical exclusion, rather than the signing policy, prevents a later publication under the same key from being accepted as another valid finalisation.

System parameters

A Shielded CSV block corresponds to a DA block containing at least one sigil accepted under the Shielded CSV consensus rules. A DA block with at least one deposit output always qualifies, since consensus inserts its deposit sigil. DA blocks containing no accepted sigil do not advance Shielded CSV height.

  • : The L1 output script that receives deposits. Consensus turns every deposit output paying it into a deposit coin, as described under deposit coins.
  • (MAX_ANCHOR_AGE): The maximum anchor age, in Shielded CSV blocks. A sigil published in block , with anchor at height , is admissible only if its anchor is a ledger prefix and:
  • (UNIQUENESS_WINDOW): The nullifier uniqueness window, in Shielded CSV blocks: a nullifier accepted in block is refused in blocks and admissible again from block .
  • : Lifetime uniqueness does not depend on , but two other properties require , and both hold at :
    • A sigil accepted in block with anchor height and included again in a later block , as after a DA reorganisation, is refused as spent while and as stale once . Since , every is covered if and only if .
    • A sigil anchored at the root its exclusion evidence ends at is admissible while , and its publication composes with that evidence only while . With an admitted sigil could require fresher exclusion evidence before it can be ratcheted. The bound guarantees that the original evidence remains usable through the last admissible publication block; it does not assert that a later publication is permanently unratchetable.
  • (retention): A node-local storage bound, not a consensus parameter. In the retained-block implementation, keeping exactly blocks suffices to maintain and restore the live uniqueness window. Larger retention permits rebuilding older window snapshots; it does not change sigil acceptance or ledger roots. Historical proof availability depends on retaining each snapshot’s whole -block window or storing snapshots separately, so retained blocks do not imply blocks of historical snapshot availability.
  • : The maximum amount in satoshis that an account’s balance can contain.
  • Amounts: Unsigned 64-bit integers, additionally constrained to .
  • Accumulator lengths and indices: Unsigned 64-bit integers. Appends must not overflow the length.

Balance arithmetic is integer arithmetic without modular wraparound. Every output balance is range-checked. These bounds do not replace bridge issuance accounting.

Data structures

Account

The plaintext account state is not published on-chain. A hiding, binding commitment to the complete account state is published as part of its sigil. Commitment openings, including blinding randomness, remain private.

An account contains:

  • : The long-lived account identifier.
  • Key information:
    • : The ephemeral public key used for the account’s next finalisation.
    • : The ephemeral public key that becomes after the next successful finalisation. Fresh nullifier keys are generated by the client. Random sampling is a key-generation requirement, not a property established by a circuit.
  • Ledger information:
    • : The ledger root at the account’s most recent successful finalisation. Before the first finalisation, it equals the ledger root bound by .
    • : The latest ledger root incorporated into the account’s proved state.
  • Balance and coin information:
    • : The account’s integer balance, bounded by .
    • : An authenticated map of received coins, keyed by . The account stores its root; the client retains the data needed to construct non-inclusion and update proofs.
    • : An append-only accumulator of outgoing coins, in sending order. Its authenticated descriptor binds both its contents and its length . For an MMR, this descriptor includes the leaf count and peaks. The client retains the coins and membership-proof data. A leaf never changes after it is appended.
    • : The number of leading entries of that have been finalised. Entries with zero-based index are finalised; the remaining entries are pending. Every valid account state satisfies: sets to . All other transitions preserve it.

ID

An account ID is:

using a domain-separated hash. Here, is the ledger root at which the account is created, is its genesis publication key, and is a secret.

The ledger root binds the account to a point in ledger history. The genesis key fixes the account’s first nullifier. The salt prevents recovering the ID from the published key and the public ledger roots.

Address

An address is a hiding, binding commitment to an account ID. Multiple diversified addresses may commit to the same ID using different blinding randomness.

To receive a coin, the recipient proves that its address opens to the receiving account’s ID.

Coin

A coin contains:

  • : A 32-byte identifier chosen by the sender, unique among the coins it sends to one recipient. It need not be globally unique and may be negotiated by sender and recipient.
  • : An integer amount in satoshis, bounded by . Zero is permitted.
  • : The recipient’s address.
  • : The identifier under which the recipient records the coin, derived from by the coin proof. This field is absent from the immutable outgoing leaf.
  • : A ledger root under which the coin is proved finalised. This field is absent from the immutable outgoing leaf and supplied by the coin proof.

The immutable outgoing leaf consists of:

The coin proof derives under a domain separator that names the kind of coin it proves:

The domains are disjoint, so a coin sent by an account never carries the ID of a deposit coin, whatever its sender chose. Without this, anyone who learns a pending deposit’s outpoint could send a coin with the deposit’s ID to its recipient and make the deposit unreceivable.

The coin proof supplies the sender account’s anchor. This may be later than the publication that first finalised the coin, since finalised outgoing entries remain in the account’s accumulator.

The receiver records the supplied anchor, but replay protection uses only : that is, a later proof of the same coin ID under a different anchor does not make it receivable again.

Deposit coin

A deposit output is an output paying in an L1 transaction that carries a well-formed : exactly one output whose data is a single 32-byte push, an address committing to the recipient’s account ID. An output paying in a transaction without one is not a deposit output, and its funds cannot be credited.

Each deposit output at outpoint , of satoshis, becomes the deposit coin with leaf

using a domain-separated hash, so that distinct outpoints give distinct tags. Its is . The deposit coins of a DA block are ordered by (transaction index, ).

Deposit account

For a DA block with at least one deposit output, confirming at Shielded CSV height , let be the ledger root at height . The block’s deposit account state is a function of and the block’s deposit outputs alone:

  • , a nothing-up-my-sleeve point obtained by a standard hash-to-curve of under a protocol domain separator, so that no party can know its discrete logarithm. Nobody can therefore sign for the deposit account. The key is computed from , by consensus and inside the coin proof alike; it is never a free witness. The account is never ratcheted, so its is unused.
  • , where is a protocol constant.
  • .
  • and the canonical empty root.
  • contains the block’s deposit coins in order, with their number, and .

Its commitment uses a protocol-constant blinding, so every party computes the same value. The deposit account is public: its state hides nothing, and anyone can prove its coins. No account-validity proof exists for it, and none is needed: it is never the input of a transition, and the deposit coin proof establishes it through the deposit sigil instead.

Deposit sigil

Consensus finalises the deposit account by inserting the deposit sigil

as the first accepted sigil of block . It carries no signature: consensus produces it from the L1 block instead of accepting it from a publisher, and every full node recomputes it. Its anchor is the root at height , so it satisfies the anchor-age rule, and its nullifier is specific to , so it never collides within the uniqueness window. Consensus accepts no other sigil with a deposit key as nullifier, and none can exist, since no signature can be produced for it.

Ledger

The ledger is an append-only sequence of Shielded CSV blocks. Each block contains the accepted sigils of one DA block, led by its deposit sigil if the block has deposit outputs, and enforces nullifier uniqueness over the -block window defined below.

Sigil bundle

A sigil bundle contains sigils annotated with the address of the publisher that submitted them to the DA layer.

Sigil

A sigil commits to an account state and contains:

  • : The publication key .
  • : The hiding, binding commitment .
  • : A recent ledger root satisfying the anchor-age rule (, see System parameters).
  • : A Schnorr signature by the key over the account commitment and sigil anchor.

The publication key was stored as in the previous finalised state. The first publication instead uses the genesis key bound by the account ID. A deposit sigil uses the deposit key bound by the deposit account’s ID and carries no signature.

The sigil anchor and the account anchor are distinct:

  • The sigil anchor limits when consensus may accept a signed publication.
  • The account anchor is the starting range of the sigil nullifier’s exclusion proof.

Signature

Sigils use BIP340 signatures:

Here, denotes the BIP340 nonce-point encoding. The signed message canonically encodes the account commitment and sigil anchor, with a protocol-specific domain separator.

Consensus verifies the BIP340 signature of every published sigil; the deposit sigil it inserts itself has none. The publication proof binds the account to the exact sigil accepted by consensus.

Ledger accumulator

Consensus maintains an MMR with one leaf per Shielded CSV block.

Ledger accumulator

Each leaf is:

  • is the height of the DA block carrying the accepted sigils.
  • commits to the set of nullifiers in the most recent Shielded CSV blocks.
  • commits to the ordered list of accepted sigils in the current block, the deposit sigil first.

The Shielded CSV height is the leaf’s zero-based MMR index.

The MMR starts with a genesis leaf at height containing no sigils:

Accumulator encodings must bind their structure, lengths, and indices. Empty leaves, occupied leaves, and internal nodes must have unambiguous encodings.

Invoice format/Payment requests

Invoices are modeled after Taproot Asset addresses as a bech32m string whose human-readable part names the network:

  • scsv (mainnet)
  • tscsv (test networks)
  • rscsv (a local, in-memory ledger)

The data part is a TLV stream, where each record is type ‖ length ‖ value with type and length in Lightning’s BigSize.

TypeFieldValue
0versionu8, required, 0
2address32 bytes, required: the payee’s diversified address
3courieroptional UTF-8 http(s) URL: where the payer delivers the coin proof
5amountoptional u64 big-endian; absent means the payer chooses
7memooptional UTF-8

Types appear in strictly increasing order, once each.

An unknown even type is refused and an unknown odd type skipped, so later versions can add optional fields.

Every request may run to bech32m’s 1023 characters, however note that this reduces the checksum guarantees slightly (compared to staying below the 90 character limit).

A payer refuses a request for another network and also accepts a bare 64-hex address as a request with no courier, amount or memo.

Without a courier the payer hands the coin proof over itself.

Relations

Ledger notation and consensus rules

Let denote the height of the newest MMR leaf in ledger root .

The SMT at height contains nullifiers from blocks

When validating a sigil in block , consensus rejects its nullifier if it appears in a prior block in that interval or in an earlier accepted sigil in block .

Within a DA block, candidate sigils are processed in a deterministic order. Only accepted sigils enter and the nullifier set.

Consensus accepts a sigil from a bundle only with a valid signature. The only unsigned sigil in any block is the deposit sigil, which consensus constructs from the L1 block itself and never takes from a bundle; a bundled sigil whose nullifier is a deposit key is rejected like any other unsigned one.

A ledger-history proof establishes that one root is a prefix of another. Prefix proofs may be reflexive: a root is a prefix of itself.

Root authentication

A history proof establishes extension, not consensus validity. Clients authenticate an adopted ledger root using the validator’s signature, and authenticate earlier roots through history proofs linking them to that adopted root.

Account proofs bind their to their proof statement. Clients must not treat an account proof as anchored to an authenticated ledger unless that bound root is authenticated or proved to be a prefix of an authenticated root.

Coin proofs bind the supplied coin anchor to the proven finalisation. The relation establishes that this anchor lies in the receiving account’s updated ledger history.

Account-proof binding

Each account-validity proof binds the complete account state through a hiding, binding state commitment:

It also binds any exposed account fields, including its ledger root, to that same state.

Every non-genesis transition:

  1. recursively verifies a predecessor account-validity proof;
  2. checks that its private input account state opens the commitment certified by that proof;
  3. enforces the transition’s constraints; and
  4. produces a proof attesting to the validity of the complete output state.

is the only account-validity base case. The deposit account has no account-validity proof; a deposit coin is proved through the deposit sigil by the coin proof’s deposit case.

additionally verifies a coin proof bound to the exact incoming coin.

The predecessor proofs and commitment-opening witnesses are implicit in the relation inputs below. A coin-proof wrapper may keep account-proof statements and witnesses private while exposing the coin and its anchor.

Subroutines

a)

After , this is the only subroutine that changes an account’s ledger root. Its callers specify which other fields change or remain equal.

Constraints:

  • Verify that is a prefix of .
  • Set .

b)

Checks that is the first publication of the account’s publication key at or after its account anchor and commits to the exact state .

Constraints:

  • .
  • , using the private commitment opening.
  • proves inclusion of the exact sigil in the at height , where
  • proves that is absent from SMT snapshots at heights The snapshots cover the interval from the account anchor through , inclusive: Each snapshot is authenticated under a ledger root of which is an extension, shown by a consistency proof; a snapshot authenticated under itself needs no consistency proof.
  • The publication block follows the exclusion endpoint by at most blocks: In other words, the client’s exclusion interval and consensus’s uniqueness window together cover all possible earlier publications from the account anchor through publication.

c)

uses this subroutine.

Constraints:

  • Execute .
  • Execute
  • Set .
  • Set .
  • Set to a newly generated ephemeral public key.
  • Set .
  • Preserve , , , and the complete descriptor.

The input must be the exact state committed by the published sigil. Changes to a candidate state require a different commitment; they cannot be applied under an existing signature.

0. Genesis

requires no on-chain publication. The account may receive coins before its first finalisation.

Private inputs:

  • Genesis ledger root .
  • Genesis publication key .
  • Salt .
  • Newly generated next nullifier key.
  • Output account state .

Constraints:

  • Set .
  • Set .
  • Set .
  • Set .
  • Set .
  • Set to the supplied next key.
  • Set to its canonical empty root.
  • Set to its canonical empty descriptor, with .
  • Set .

No other transition changes or , and only changes . Hence the ID fixes both the account’s first publication key and the start of its first exclusion interval.

Soundness note. Two genesis states with the same ID carry the same publication key and account anchor . The first publication of at or after excludes every later one via , so at most one of them is finalised. A coin credited to both is therefore spent at most once. may have been published before . Every sigil committing to this account binds through and hence , so it is published after . A publication under another ID commits to a different state and cannot be applied here.

1. Update ledger state

Private inputs:

  • Account state .
  • Ledger root .
  • History proof .
  • Output state .

Constraints:

  • Execute .
  • Preserve all other account fields.

2. Ratchet

applies a successful publication.

Private inputs:

  • Input account state .
  • Sigil .
  • Publication, exclusion, and history proofs.
  • Publication ledger root .
  • Output state .

Constraints:

  • Execute .

3. Receive incoming coin

Private inputs:

  • Account state .
  • Incoming coin and coin proof .
  • Opening of the recipient address to .
  • Ledger-history proof , when needed.
  • Non-inclusion proof for .
  • Output state .

Constraints:

  • Recursively verify , bound to the exact coin and supplied anchor.
  • Verify that opens to .
  • Verify that is absent from .
  • Merge the ledger views:
    • If the account ledger root is a proper prefix of the coin anchor, invoke with the coin anchor as target.
    • If the coin anchor is a proper prefix of the account ledger root, verify that history proof and preserve .
    • If the roots are equal, preserve .
  • Insert at key by recomputing the authenticated-map root using the same path that established non-inclusion.
  • Constrain .
  • Set: without wraparound and with the result at most .
  • Preserve all other account fields.

The history check always places the coin anchor in the history of the output account’s ledger root. Only the first case changes that root.

4. Send outgoing coin

Private inputs:

  • Account state .
  • Outgoing coin , with no anchor.
  • Accumulator append witness, if required.
  • Output state .

Constraints:

  • Constrain .
  • Check .
  • Check that is unset.
  • Set
  • Prove that the outgoing coin is appended at index to , preserving every existing leaf.
  • Set the new authenticated length to , without overflow.
  • Preserve all other account fields, including .

Sender-side avoidance of duplicate coin tags towards one recipient is a wallet responsibility. Such duplicates cannot both be consumed by the recipient.

Publication proofs

A publication proof authenticates:

  1. the exact sigil as a leaf of a block’s ; and
  2. that block’s MMR leaf as the newest leaf under .

A lookup intended to finalise an account specifies both its publication key and its account anchor. The service returns the first publication at or after that anchor.

Service behaviour is not trusted: the client verifies publication and exclusion proofs. Returning a later publication cannot bypass .

Exclusion proofs

For a publication key and requested interval, the vRPC selects authenticated SMT snapshots whose windows cover that interval and proves non-membership in each snapshot.

The client checks snapshot heights, coverage, and authentication under a ledger root that the publication ledger root extends.

Coin proofs

A coin proof is a wrapper whose public statement is the coin’s , , , and supplied . Every other input is private, and the recipient learns neither which case was proved nor any inner witness. verifies the wrapper under a single verification key. The wrapper proves one of the two cases below; each derives from the opened leaf’s under its own domain separator, so the two cases can never expose the same .

a) Finalised account coin.

Private inputs: account-validity proof, opening of , the descriptor, membership path, and index .

Constraints:

  • Verify the account-validity proof of a sender account state , bound to its complete state commitment.
  • Verify membership of the immutable outgoing leaf at zero-based index under .
  • Set .
  • Check the accumulator’s authenticated length : is obtained from the private accumulator descriptor or membership witness and checked against the authenticated accumulator commitment, and need not be an additional public input.
  • Constrain
  • Check that the supplied anchor equals .

Since only advances , every coin accepted in this case belongs to a prefix committed by a successfully finalised account state.

b) Deposit coin.

Private inputs: ledger root , the deposit outputs of one DA block in order, index , publication ledger root , and publication proof .

Constraints:

  • Compute and from and the deposit outputs, as given under the deposit account.
  • Verify that places the sigil in the at height .
  • Check that is the leaf of the -th deposit coin, with .
  • Set .
  • Constrain .
  • Check that the supplied anchor equals .

No account-validity proof and no exclusion proof are involved. The sigil’s nullifier is a point nobody can sign for, so the only way it enters a is consensus inserting it from the L1 block; and consensus inserts one deposit sigil per block under a key specific to that block’s , so the question ’s exclusion proof answers, whether an earlier publication of the same key exists, does not arise.

Soundness note. A list of deposit outputs other than the one consensus extracted from L1 yields a different , hence a sigil in no , since the commitment is binding and the blinding is fixed. The proof therefore shows that the coin is one of the deposits consensus recorded for that block, and nothing more: whether consensus extracted L1 faithfully is the audit described under the deposit flow. A deposit coin’s ID is unique to its outpoint and lies in a domain no sent coin can reach, so the recipient’s credits it at most once and nobody can pre-empt it.

Future work

  • Fork recovery and account migration between ledger histories.
  • Removing the trusted validator by replacing root-signature trust with chain-state proofs.
  • Post-quantum nullifier schemes and analysis of their security properties.
  • BTC-collateralised flatcoins and a BitVM Argo bridge.
  • Formal verification, including Lean.
  • Atomic swaps, payment channels, and timelocks.
  • Pre-confirmations via Bitcoin staking
  • Reduce onchain footprint of sigils:
    • Add half aggregation
    • Add compact anchors
  • Multisig via FROST