Reference

Reference

Definitions, indexing behaviour, sizing, limits and the checklist an implementation should be able to answer yes to.

Terminology

Circle
One confirmed Bitcoin transaction that satisfies every rule in section 6 of the specification. It is the whole protocol object; there is no separate registration.
Marker
The 42 byte scriptPubKey at output 0: OP_RETURN PUSH40 followed by the 40 byte WITC payload. Value must be zero.
Context hash
SHA-256 of the RFC 8785 serialization of the context manifest. Committed in the marker; the manifest itself never has to be published.
Participant count (N)
Declared in the marker and equal to the input count. Two to sixteen inclusive.
Slot
The zero-based position of a participant after inputs are sorted by display txid then vout. Slots determine successor vout and fee remainder assignment.
Successor
Output slot + 1, carrying the exact scriptPubKey of the corresponding input and the input value minus that slot's fee share.
Shard
A successor output tracked in protocol state. A shard is active until something spends it.
Lineage
The chain of shards that starts at a participant's first Circle input. Identified by SHA256("WITC/lineage/v1" || wire_outpoint) of the genesis outpoint. A lineage is active or closed, never merged.
Continuation edge
A recorded link from an earlier Circle to a later one, for one lineage, through the shard the later Circle spent.
Ordinary spend
Any confirmed transaction that spends an active shard without being a valid Circle. It closes that lineage.
Revision
A counter that increments once per confirmed transaction that applies a Circle or closes at least one active lineage. Rollback decrements it by restoring the prior snapshot.
State hash
SHA256(UTF8(RFC8785(snapshot))) over the exact snapshot object, with the ordering rules of section 11 applied first.

Indexer semantics

Confirmation

A Circle becomes authoritative at one confirmation in the best chain. There is no maturity period, no second protocol state, and no probabilistic threshold in the protocol itself. A product may render six confirmations as a settled display state, but that is presentation, not a transition. Nothing in the state snapshot changes between confirmation one and confirmation six.

An indexer applies confirmed transactions in the order they appear in the block, inside one database transaction per block. Jobs must be idempotent by block hash, txid and parser version.

Mempool

Mempool observations are provisional and node-local. Two honest nodes can disagree about them at the same instant, so they are not protocol state.

  • An indexer MAY expose pending valid candidates, conflicts, replacements and eviction.
  • These projections MUST live in separate tables or namespaces and MUST be removable without editing confirmed state.
  • A pending candidate never contributes to the state hash and never advances a revision.
  • Because a Circle signals opt-in RBF, a replacement is possible, but it requires fresh signatures from every participant. A single participant cannot replace, cancel, or fee-bump the transaction alone, and there is no CPFP workflow.

Reorganizations

An indexer MUST persist block hashes and enough undo information to reverse what it applied. On detecting that the indexed tip no longer matches Bitcoin Core:

  1. Reverse confirmed transitions in reverse transaction order, block by block, until the common ancestor.
  2. Each reversal restores the exact prior snapshot, so the state hash after reversing to a given point equals the state hash that was published at that point.
  3. Ingest the new branch in block order, then in the order transactions appear within each block.

The reference engine implements this as a journal of prior snapshots with rollbackLast(expectedTxid), which refuses to roll back a transaction other than the journal tip. The published lifecycle vector commits all three rollback roots, so a reorganization implementation can be tested without a chain.

The rule that catches people out. A transaction that spends an active shard but fails Circle validation still closes that lineage, as an ordinary spend. This is deliberate: it makes lineage closure a property of the UTXO set rather than of parser opinion, so a later parser correction cannot resurrect a closed lineage. It also applies to a transaction using an unknown future protocol version.

Determinism obligations

  • Never accept validity supplied by a frontend, and never let optional manifest fields enter state.
  • Verify the golden vector at startup and expose the parser version in status responses.
  • Cache keys should include network, indexed tip, parser version and query parameters.
  • A parser upgrade is replayed into shadow tables and compared by checksum before cutover. Historical meaning is never changed silently.

Fees and sizes for every participant count

All values assume 64 byte SIGHASH_DEFAULT signatures. Explicit SIGHASH_ALL adds one witness byte per such input, which can add at most one virtual byte for every four such inputs.

NWeightVirtual bytesFee at 1 sat/vBFee at 10 sat/vBPer member at 10 sat/vB
21,0502632632,6301,315
31,4523633633,6301,210
41,8544644644,6401,160
52,2565645645,6401,128
62,6586656656,6501,109 or 1,108
73,0607657657,6501,093 or 1,092
83,4628668668,6601,083 or 1,082
93,8649669669,6601,074 or 1,073
104,2661,0671,06710,6701,067
114,6681,1671,16711,6701,061 or 1,060
125,0701,2681,26812,6801,057 or 1,056
135,4721,3681,36813,6801,053 or 1,052
145,8741,4691,46914,6901,050 or 1,049
156,2761,5691,56915,6901,046
166,6781,6701,67016,7001,044 or 1,043

Minimum viable input value is the fee share plus 1,000 sats. At 10 sat/vB in a sixteen member Circle that is 1,044 + 1,000 = 2,044 sats, so small inputs are usable, but a fee spike can push a planned Circle under the dust rule and the planner will refuse it rather than produce an invalid transaction.

Limitations

  • No privacy. A Circle deliberately links every participating input, and every same-key continuation, in public forever. This is the feature and the risk.
  • No identity. One person can hold sixteen keys. Nothing in the protocol can detect that, and no application should claim otherwise.
  • No fee bump. No CPFP workflow, no unilateral RBF, no cancellation after broadcast.
  • No relay guarantee. Policy acceptance is a Bitcoin Core question. Call testmempoolaccept before broadcasting.
  • No mainnet creation. The reference planner and marker encoder fail closed outside Signet and regtest.
  • No asset. No token, balance, supply, price, transfer, deposit or market. Active shards must never be treated as exchange deposit identifiers or listable items.
  • No second operation. Only CIRCLE exists. Refuel, rekey, transfer and governance operations are reserved and must be rejected, not guessed.
  • Sixteen participants maximum. The count is a single payload byte bounded at 16, and the transaction cost grows linearly with it.

Security considerations

For participants

  • Every input you contribute is permanently and publicly associated with every other input in the Circle, including any later Circle that continues one of those lineages.
  • A signature commits to all inputs and all outputs. Verify the whole transaction, not just your own row, before signing.
  • Verify the fee share and the total fee against your own caps. The protocol defines no maximum fee.
  • An invitation is a capability, not an identity. Bind it to session, slot, outpoint, context hash and fee caps, and let it expire.

For wallets

  • Rebuild or decode the unsigned transaction locally. Do not trust a coordinator's summary.
  • Compare the frozen unsigned transaction against the invitation fingerprint before displaying anything.
  • Disclose Taproot key origin data only for the owner's own input. Never attach a global xpub.
  • Return a non-finalized PSBT_IN_TAP_KEY_SIG. Wallets that auto-finalize or hide outputs are unsafe here until tested.
  • Protect active shards from automatic coin selection.

For indexers and applications

  • Treat manifest titles, aliases, descriptions and renderer strings as untrusted input. Escape them. Never interpret an alias as an identity.
  • Do not log authorization capabilities, full participant PSBTs, derivation paths, seeds or keys.
  • Bound and paginate graph traversal over lineages and edges; a Circle graph is attacker-influenceable in size.
  • Compare state hashes between independent instances and alert on disagreement.
  • A coordinator must never store a private key or seed phrase.

Report vulnerabilities privately through GitHub private vulnerability reporting on the owning repository. Do not open a public issue for an unpatched fund-loss finding.

Implementation checklist

An implementation that can answer yes to all of these interoperates with the reference.

Parser

  • Rejects PUSHDATA1 markers with AMBIGUOUS_ENCODING rather than accepting them.
  • Enforces minimal CompactSize on every count and length.
  • Rejects trailing bytes after the locktime with TRAILING_DATA.
  • Rejects a SegWit marker and flag when no input carries witness data.
  • Rejects a zero context hash and any operation byte other than 0x01.

Validator

  • Checks all seventeen grammar rules and reports the same verdict as the reference on every published vector.
  • Verifies each BIP340 key-path signature against the BIP341 message for its input.
  • Accepts a 65 byte signature only when the final byte is exactly 0x01.
  • Recomputes the fee allocation instead of trusting output values.
  • Uses checked integer arithmetic and enforces MAX_MONEY on individual and aggregate values.

State

  • Derives lineage identifiers from the genesis outpoint in wire form.
  • Applies the ordering rules of section 11 before hashing.
  • Reproduces the empty-state hash and all three published transition hashes.
  • Reproduces all three published rollback roots in reverse order.
  • Closes a lineage on any confirmed non-Circle spend of an active shard.
  • Keeps mempool projections outside the hashed snapshot.

Product

  • Displays the claim boundary wherever a Circle is presented.
  • Escapes every manifest string before rendering.
  • Provides a text alternative for every circle visualization.
  • Exposes the parser version alongside any derived state.