A study · May 2026

Three approaches to the same trick: handing someone a coin without moving it.

Statechains, Mercury Layer, and Spark each let you transfer the practical ability to spend a Bitcoin UTXO without writing the transfer to the chain. They differ in privacy, in who co-signs, and in how badly they fail when something breaks. None are trustless. All depend on old signing material being deleted at the right moment.

Statechains · 2018

The primitive. A two-of-two between you and an entity. To transfer, the entity rotates its key share so only the new owner can co-sign. Old owners hold older backup transactions that mature later than yours; you race them on chain if it ever comes to that.

Mercury Layer

A statechain implementation where the co-signing server is blind. It signs partial signatures without learning the UTXO, the public key, or the final on-chain signature. Strong privacy. Heavy validation burden on the receiver. Public repo archived in March.

Spark

A productized version with threshold operators (FROST), a tree of leaves so balances split, SSPs that route Lightning, and a token layer for stablecoins. Beta mainnet, two operators at launch. Documented incidents in the months since.

I · Statechains

The primitive: passing the parcel

Origin Ruben Somsen, 2018 Trust model Non-custodial, not trustless On-chain object 2-of-2 (user + entity)

The shape of the trick is older than its name. You and a server share a Bitcoin output that neither of you can spend alone. You hand a sealed envelope to a friend; the envelope holds the right to ask the server to co-sign with them instead of with you. Your friend does the same thing later, to someone else. The coin never moves on chain — only the right to ask the server moves, off-chain, in private.

The catch is what happens when somebody cheats. The server can refuse to play; the previous owner can collude with the server; and on Bitcoin, without an Eltoo-style update mechanism, the workaround is a chain of pre-signed backup transactions whose lock-times decrease with each transfer. Whoever holds the freshest backup wins on chain — provided they're awake when the older ones mature.

Figure 1

The lifecycle of a single statecoin

deposit → transfer → exit
Bitcoin L1 UTXO · 1.000 BTC P = User pubkey ⊕ Entity pubkey Off-chain ownership · the parcel passes Alice backup tx₁ locktime 949,451 · ~14d Bob backup tx₂ locktime 949,307 · ~13d Carol backup tx₃ locktime 949,163 · ~12d Statechain entity (co-signer) key update key update Carol's backup matures first; she races any older backup to the mempool.
An on-chain object that never moves; an off-chain history that does. Each new owner gets a fresher backup whose lock-time fires sooner than the previous one's.

Try it: a 1 BTC statecoin, four owners, and a sleeping wallet

Below is a working version of a statechain. You hold the parcel as Alice. Click transfer to send it to Bob, then to Carol, then to Dave. The current block advances; each new backup gets a slightly earlier lock-time. The bars show how much margin each owner has before their backup matures — and how much the safety window shrinks with every hop.

When you've moved it a few times, hit sleep · old owner attacks. That simulates the current owner's wallet going offline while a previous owner broadcasts an old backup. Watch the log. The race is the whole point.

Figure 2 · interactive

Pass-the-parcel

block 947,435 · ~h₀ + 2,016
current block 947,435 · deposit at 947,435 · all backups in the future

Controls

Decrement c = 144 blocks per transfer (≈ 1 day). Initial window h₀ = 2,016 blocks (≈ 14 days). Bitcoin block height advances by 144 per simulated day.

Why it isn't trustless

The hard part of a statechain isn't producing signatures. It's making sure the previous signing material is gone. If the entity keeps an old share, a former owner can come back later and ask it to co-sign a transaction spending the coin from the past. There is no cryptographic proof that a key was deleted. Mitigations exist — trusted hardware, distributed operators, public commitment trees, watchtowers, decrementing lock-times — but every one of them is an assumption.

The server cannot steal alone. But it can collude with someone who used to own the coin. That is not the same thing as trustlessness. — the gist of every statechain critique

The decrementing lock-time fix gives the current owner a small window in which their backup matures before all earlier ones. The window is c blocks, set by the protocol. In practice, with c = 144, the current owner has about a day. If they go offline for longer, an older backup can win.

II · Mercury Layer

What the server can't see

Status Public repo archived 22 Mar 2026 Architecture Client + Server + SGX enclave Trust Single blind co-signer

Mercury Layer takes the statechain pattern and makes the server blind. The server still co-signs every transfer, but it never learns the UTXO it's touching, the aggregate public key, the final signature that lands on chain, or the contents of the backup transaction. It signs partial blinded signatures; it counts how many it's signed; it knows nothing else.

That privacy comes with a trade. Because the server can't read the transaction, it can't spot a malformed one. Validation falls entirely on the client. The September 2024 disclosure by Conduition found five separate ways an honest receiver could be defrauded by a malicious sender, all of them validation gaps. The lesson was unambiguous: don't validate serialized backup transactions. Reconstruct them from a strict template, then check the signatures match the reconstruction.

Figure 3 · interactive

What the client sees vs what the server sees

blinding: on

Client — Alice's wallet

Server — co-signs blindly

Blinding: ON signatures issued 0
Click send signing request to walk through a single transfer. Toggling blinding off reveals what any non-blinded statechain server would learn — which is to say, the entire flow.

What "blindly" actually means

Blind co-signing sounds like marketing. It isn't. It's a 1982 cryptographic primitive — David Chaum's blind signature — that does precisely what the name says: a signer produces a valid signature on a message they cannot read.

The intuition. Imagine you need a notary to stamp a document but you don't want them to read it. You put the document in a sealed envelope with carbon paper between the cover sheet and the page inside. The notary stamps the envelope; the carbon transfers the stamp through to the document; the document is stamped; the notary never read a word.

Schnorr blind signing is the cryptographic version of that. The user wraps the real signing request in a secret blinding factor, sends the wrapped thing to the signer, the signer signs it without ever seeing the original, the user removes the blinding. What lands on chain is a perfectly normal Schnorr signature on the original transaction — and the signer cannot recognise it as something they helped produce.

Figure 3b

What the server learns, with and without blinding

side by side
Without blinding · any normal statechain server

What the user sends:

R = R_o + R_s
P = O + S (aggregate)
m (the transaction)
e = H(R ‖ P ‖ m) (challenge)

What the server computes:

σ_s = k_s + e · s

What the server therefore learns:

  • which UTXO this signs (from R, P)
  • the aggregate public key P
  • the transaction message m
  • the final on-chain signature it can spot
With blinding · Mercury Layer

What the user sends:

blind_request(e, R, P, m)
// the server sees a random-looking request
// the user keeps the real R, P, m to itself

What the server computes:

σ_s' = BlindSign(request, s)

What the user does locally:

σ_s = unblind(σ_s')
σ = σ_o + σ_s → posts on chain

What the server therefore learns:

  • which UTXO this signs
  • the aggregate public key P
  • the transaction message m
  • the final on-chain signature
  • a session id and the count of blinded requests it has signed
The user holds the only complete picture. The server holds only the blinded challenge and a counter. The signature posted on chain is computed by the user from the server's blinded response — the server cannot recognise it later as one they helped produce.

Why blind signing isn't free

Schnorr blind signing has a known weakness. If a signer runs many concurrent blind signing sessions, an attacker can sometimes combine several blinded responses to forge a signature on a message the signer never authorised. This is the ROS attack — Random inhomogeneities in an Overdetermined Solvable system, Wagner 2002, formalised against Schnorr by Benhamouda et al. in 2020. It's not theoretical; it's a real concern for anyone building blind-Schnorr in production.

Mercury defends two ways. First, the SGX enclave caps the number of concurrent signing sessions to a small number, so the ROS attack's required pool of blinded signatures isn't reachable. Second, the server publishes a signature counter per session — every partial it has issued is counted. The receiver, when accepting a transferred statecoin, checks that the server's counter matches the number of legitimate transfers in the statecoin's history. More signatures than transfers means the server signed something extra, which is what collusion looks like.

That counter is the only auditable thing the server publishes. The whole privacy guarantee — and the whole trust model — hinges on it being honest.

The math is small enough to fit in a paragraph

The user holds a secret share o. The server holds a secret share s. The aggregate public key is P = O + S. To transfer ownership, the new owner generates o₂; the server updates its share to s₂ = s₁ + o₁ − o₂; the aggregate stays the same: O₂ + S₂ = O₁ + S₁ = P. The on-chain Taproot output never changes. What changes is who can cooperate with the server to spend it.

o₁ + s₁ → P // owner #1 holds o₁ o₂ // owner #2 generates fresh share s₂ = s₁ + o₁ − o₂ // server rotates its share o₂ + s₂ → P // same aggregate, new owner

The server is supposed to delete s₁. Whether it actually does is the entire trust assumption.

What actually happens after Bob generates o₂

The summary above hides the orchestration. Below is a step-by-step walkthrough of exactly what each party computes, what they send to whom, and what they end up holding. The numbers below are real — fresh 256-bit scalars sampled from secp256k1's order, with t = (o₁ − o₂) mod n and s₂ = (s₁ + t) mod n computed for actual.

Click next step to advance. The active lane lights up. The fresh value at each step appears in orange. The deletion at the end is shown as a strikethrough — that's the moment the protocol either holds or fails.

Figure 4 · interactive

The key update — Alice → Bob, in 10 steps

step 1 of 10

Alice — current owner

Server — blind co-signer

Bob — new owner

step 1 of 10

STEP 1Initial state

math at this step
All scalars are sampled mod n = secp256k1's group order. Public points (capital letters) are derived as scalar·G but are shown here as truncated SHA-256 digests of the scalar bytes — the relationships between them are real, the visual hex isn't a true point computation.
flows

Deposit, transfer, and exit, in plain steps

click a tab
Deposit
Transfer
Withdraw
  1. Client and server derive the shared Taproot pubkey P = O + S.
  2. Client builds a deposit transaction paying to P.
  3. Server blindly signs a backup transaction with locktime h₀.
  4. Client verifies the backup is valid and only then broadcasts the deposit.

Order matters: if the deposit confirmed first, a refusing server could trap the funds with no exit.

  1. Bob generates owner share o₂ and sends transfer info to Alice.
  2. Alice and the server build Bob's new backup with locktime h₀ − (n−1)·c.
  3. Server updates its share: s₂ = s₁ + o₁ − o₂ and deletes s₁.
  4. Bob verifies: deposit unspent · prior backups well-formed · locktimes decrement · sigcount matches.
  5. Bob accepts ownership.
  1. Cooperative. Owner and server jointly sign a normal spend to any L1 address.
  2. Backup. If the server is gone, wait until the latest backup's locktime matures; broadcast it (CPFP if needed).
  3. After cooperative closure, the statecoin must not be transferred again — a future receiver can't tell whether an extra blind signature is hidden as a backup.
III · Spark

The productized version

Status Beta mainnet, "highly experimental" Operators at launch 2 — Lightspark, Flashnet Signing Customized FROST · Schnorr

Spark generalizes the pattern. Instead of one server it has a threshold of operators, signing FROST-style; instead of a fixed-denomination UTXO it has a tree of leaves; instead of asking users to manage Lightning channels it asks SSPs to do it for them; and on top of all of that it carries a token layer for stablecoins.

The trust model goes from "trust this one server forever" to "trust at least one of the relevant operators to delete its old key share at the moment of transfer." Better. Not equivalent to trustless. The realistic threat is correlated failure — a shared signer bug, a shared custody arrangement, a shared legal demand — not independent dishonesty.

Figure 5

FROST: one user share, a threshold of operator shares, one Schnorr signature

Y = U + S
User wallet share U always required Spark Operators · threshold t-of-n op₁ op₂ op₃ op₄ op₅ Shamir shares; t shares aggregate to S Single Schnorr sig on aggregate Y = U + S indistinguishable on chain
Operator-set compromise alone isn't enough — the user share is mandatory in every signing.

A wallet with eight leaves and a coffee to pay for

Statechains transfer a UTXO whole; a 0.5 BTC statecoin is a 0.5 BTC payment, no more, no less. Spark splits a deposit into a tree of leaves, so a wallet can pay any amount by selecting leaves that sum to it (and possibly splitting one). The trade is that small leaves can't be exited unilaterally — anything below 16,348 sats costs more in fees than it carries in value.

Below is a wallet with eight leaves and a request from Bob for 173,000 sats. Pick leaves until you cover it. The summary tells you whether you went over, what change a split would produce, and whether any selected leaf is below the unilateral exit floor.

Figure 6 · interactive

Pay Bob 173,000 sats — select leaves

click leaves to add or remove

Spark wallets run a coin-selection algorithm to pick leaves that sum to the target. If no exact match exists, an operator splits a leaf in two — one for the recipient, one for change. Below 16,348 sats, a leaf can be transferred but not unilaterally withdrawn.

paying
173,000sats

selected0
vs target−173,000
leaves below floor0

Pick leaves to start.

Floor: leaves under 16,348 sats can't be exited unilaterally — fees would exceed the leaf's value.
Figure 7

The tree under a Spark deposit

root → branches → leaves
Spark deposit tree shaped by the selected leaves in Figure 6 L1 deposit UTXO aggregate Schnorr key Branch B₁ Branch B₂ 50,000 exit ok 250,000 exit ok 10,000 below floor 100,000 exit ok 600,000 exit ok 80,000 exit ok Each leaf carries a chain of pre-signed exit transactions back through its branch to the L1 root.
Pick leaves in Figure 6 and this tree will highlight the selected leaf outputs, their branches, and any split/change output needed to pay Bob exactly.

What "pre-sign" means here

Mercury's backup transaction and Spark's branch / leaf / refund transactions are the same kind of safety object: a valid Bitcoin transaction signed now, but held off-chain and broadcast only if the cooperative path fails. Pre-signing does not move coins. It creates an already-authorized escape path.

The difference is shape. Mercury pre-signs one backup spend for a whole statecoin. Spark pre-signs a transaction tree: branch transactions split the deposit, leaf transactions isolate spendable units, and refund transactions pay the current owner after timelocks. Transfers normally update who owns the leaves and replace the per-leaf refund state; the root deposit remains where it is.

Figure 7b · interactive

Alice pays Bob: one valid Spark transfer

use the selected leaves above

Invoice at the counter

Alice is paying Bob 173,000 sats for a repair invoice. Her wallet chooses leaves, Spark operators rotate each selected leaf to Bob, and any excess becomes Alice's change. Bitcoin L1 sees no transaction.

Selected path

State updates

Resulting tree state

Use Figure 6 or the presets here. A valid route must cover Bob's 173,000-sat invoice; the walkthrough then shows the per-leaf rotations and split/change outputs.
Figure 7c · interactive scenarios

Four users on one tree: transfers and exits, step by step

click any node to inspect

A single 800,000-sat Alice deposit, fanned out into eight 100,000-sat leaves at deposit time. Over the next 23 days, three of the four users (Bob, Carol, Dave) get involved. Two of those transfers need partial amounts that don't match any subset of existing leaves — so the SDK falls back to a leaves swap with the SSP (the actual mechanism in services/leaf-manager.ts: selectLeaves first, then selectLeavesWithSwap). After a swap, the wallet holds leaves from the SSP's deposit tree, not Alice's. Carol coop-exits one of those swap leaves; Dave is forced into a unilateral exit through the SSP's pre-signed chain. Every box is clickable.

A Spark deposit tree with four owners, plus an SSP leaf pool used for partial-amount transfers
Faithful to buildonspark/spark: trees are root → branch → leaf only (no "subbranch"); branches carry no timelocks; partial-amount transfers go through an SSP leaves swap, not in-place leaf subdivision. Days 7 and 12 show leaves leaving Alice's tree to the SSP and different-denomination leaves arriving from the SSP's pool. Carol's coop-exit settles a single SSP-pool leaf to L1; Dave's unilateral exit broadcasts the SSP's tree chain (drawn abstractly because that tree's shape is opaque to this wallet). The L1 root deposit never moves through any of it.
flows

What happens on deposit, transfer, Lightning, and exit

click a tab
Deposit
Spark→Spark
Lightning
Unilateral exit
  1. Wallet derives a P2TR deposit address (aggregate of user + Spark Entity).
  2. User sends BTC to that address.
  3. User and operators pre-sign branch and per-leaf exit transactions before the deposit is treated as active.
  4. After confirmation, the deposit becomes the root of a leaf tree.
  5. Optional: 0-conf via SSP — risk shifts to the SSP, not Bitcoin.
  1. Sender selects leaves matching the amount.
  2. Wallet calls wallet.transfer({ receiverSparkAddress, amountSats }).
  3. Operators run a key update on the chosen leaves; the user co-signs.
  4. Old leaf state invalidated (key deletion at the operator threshold).
  5. Receiver records the leaves — instant, currently zero fee.
  1. Alice conditionally transfers leaves to an SSP.
  2. SSP pays the BOLT11 invoice on the Lightning network.
  3. Proof-of-payment causes Spark operators to finalize the leaf transfer to the SSP.
  4. If the conditional transfer expires, leaves unlock back to Alice.

Fee schedule: Spark→Spark BTC currently free. Spark→Lightning 0.25% + routing. Lightning→Spark free for receiver, 0.15% for sender.

  1. Wallet broadcasts the chain of pre-signed transactions from root to each owned leaf.
  2. Each tree node may need CPFP — Bitcoin Core v29 ephemeral anchors required for some flows.
  3. Wait through timelocks; claim leaf outputs to L1 addresses.

Constraints (beta): only leaves above 16,348 sats exit unilaterally; single-session process; wallet locked during exit; exact broadcast ordering required; fee UTXOs must be staged.


How Spark actually works

Spark looks simple from the SDK side — initialize a wallet, send to a Spark address, done. Underneath is a lattice of moving parts: a threshold of operators running a custom FROST signing protocol, a tree of pre-signed Bitcoin transactions extending from each on-chain deposit, Spark Service Providers that hold Lightning nodes on users' behalf, and (optionally) issuers running a token layer on top of all of it. Below is each part, in detail.

First, five concepts in plain language

If terms like "aggregate key," "threshold signature," or "pre-signed transaction" don't already feel obvious, the rest of this section will land sideways. The five blocks below are the mental models the rest depends on. Once they're in place, everything that follows is just naming parts.

1.A locked safe

┌────────────┐ │ │ ◀─── a Bitcoin UTXO │ ₿ ₿ ₿ │ │ │ to take the bitcoin out, you must │ [🔒] │ produce the right key (a digital signature) └────────────┘

Imagine a small safe holding some bitcoin. The safe has a lock. To take the bitcoin out, you have to produce the right "key" — which in Bitcoin means a digital signature, a number only the holder of a secret value (a private key) can produce. That's a Bitcoin UTXO. Most Bitcoin lives in safes like this.

What this actually is — a Bitcoin output locked to a public key. Spending requires a signature that validates against that key. Whoever holds the matching private key can spend the output; nobody else can.

2.A safe with two locks

┌────────────┐ │ │ ◀─── a 2-of-2 aggregate key │ ₿ ₿ ₿ │ (Y = U + S on the math side) │ │ │ [🔒][🔒] │ ◀─── you hold one key, └─┬───────┬──┘ a server holds the other YOU SERVER (neither alone — both must turn at the same time)

Now imagine a safe with TWO locks instead of one. You hold the key to the first lock. A server holds the key to the second. Neither key alone opens the safe — both must turn at the same time. To produce the spending signature, you and the server must cooperate. Each of you signs a partial signature; the partials add together into one valid signature on the safe's address.

This is the basic shape of all three protocols on this site (statechains, Mercury, Spark). The user holds one lock; the server holds the other.

What this actually is — a Schnorr-aggregated public key Y = U + S, where U is the user's public point and S is the server's. Spending requires a co-signed Schnorr signature with each side contributing using its private share.

3.The second lock, split among several people

┌── op₁ ──┐ │ │ [🔒]──── ┤├── op₂ ──┤├──── ◀─── operator-side lock, YOU │ │ split into 5 fragments ├── op₃ ──┤ │ │ ├── op₄ ──┤ any 3 fragments together │ │ = "the server" └── op₅ ──┘ (1 or 2 alone = nothing)

Take the two-lock safe. Now replace the server's lock with a special arrangement: instead of one server, there are five people. Each holds a fragment of the second lock. Any THREE of them can combine their fragments to act as the server. Two alone can't. One alone definitely can't.

This is what Spark adds on top of Mercury's design. Mercury has one server (single lock). Spark distributes the second lock across multiple operators with a threshold rule. To "be the server" you need at least t of n operators cooperating. The benefit: you no longer trust a single vendor. The catch: you have to trust that at least one (or threshold-many) of those operators will honestly delete their fragment when the time comes.

What this actually is — a t-of-n threshold Schnorr signature using FROST. The operator share s is split into Shamir secret shares; any threshold subset of operators can collectively produce a valid partial signature on behalf of S. A single operator alone cannot. Distributed Key Generation (DKG) is how the shares are created without ever assembling the full s in one place.

4.Pre-signed checks with "do not cash before" dates

┌─────────── check 1 ───────────┐ do not cash before │ pay $100 to BOB │ May 21 │ signed (by you AND server) │ └───────────────────────────────┘ ┌─────────── check 2 ───────────┐ do not cash before │ pay $100 to BOB │ May 28 │ signed (by you AND server) │ └───────────────────────────────┘ ┌─────────── check 3 ───────────┐ do not cash before │ pay $100 to BOB │ Jun 04 │ signed (by you AND server) │ └───────────────────────────────┘ all signed today; each waits for its date

Imagine writing a check today, signing it, but writing on it "do not cash before May 21." Banks won't process it until May 21. Bitcoin works the same way — you can attach a timelock to a transaction so the network refuses to confirm it until the lock matures.

Now imagine signing a whole stack of these — all signed today, by all the parties who need to sign, but each one with a later "do not cash before" date than the last. The stack is your fallback plan. If the cooperative path stops working, you can broadcast each one in turn, waiting through each timelock.

This stack is what Spark calls "the tree." When you deposit, you and the operators jointly pre-sign a chain of transactions, all today. They live in your wallet. If operators ever stop cooperating, you can broadcast them in order to extract your money on chain — slowly, but unilaterally.

What this actually is — a chain of pre-signed Bitcoin transactions with relative-time locks (CSV — CheckSequenceVerify). Spark's "tree of leaves" is exactly this: a deposit, a branch transaction (CSV ~1024 blocks), a sub-branch (CSV ~512), a leaf (CSV ~256), a refund (CSV ~144). Each is signed at deposit time and held off-chain until needed.

5.Updating the locks without moving the safe

before: after: ┌────────────┐ ┌────────────┐ │ │ │ │ │ ₿ ₿ ₿ │ ──→ │ ₿ ₿ ₿ │ │ │ │ │ │ [🔒][🔒] │ │ [🔒][🔒] │ └─┬───────┬──┘ └─┬───────┬──┘ ALICE bank BOB bank version 1 version 2 same safe address Y throughout — only the locks inside change

Here's the trick that makes "transferring ownership without moving the coin" possible. The safe has an address (call it Y) printed on the outside. The address is fixed — it can't change without an on-chain transaction. But the locks inside can be quietly rearranged: the bank can swap its lock to a new one in such a way that the new owner's key, paired with the new bank-lock, still opens safe Y.

The arithmetic is a one-line trick. If old user is U₁ and old bank is S₁ with U₁ + S₁ = Y, the new state is U₂ + S₂ = Y where S₂ = S₁ + (U₁ − U₂). Same total, different decomposition. The bank's lock is rotated by exactly the difference between the old and new user keys. The address on chain doesn't change. Who can open the safe does.

The trust assumption: the bank has to actually destroy its old lock. If it keeps both old and new locks lying around, the previous user can still open the safe with the old combination. This is the unsolvable problem all three protocols carry — nothing on chain proves the old lock was destroyed. You have to trust the implementation (HSM, SGX enclave, threshold of operators) to do it.

What this actually is — additive share rotation. The aggregate Y = U + S is invariant across transfers because S is updated by the transition scalar t = u_old − u_new. The old share must be deleted; otherwise the previous owner plus the server (or threshold of operators) can co-sign on behalf of the now-stale state.

6.Aside — what Merkle trees are, and why this is not one

MERKLE TREE TRANSACTION TREE (Spark) root_hash deposit_tx ← real on-chain UTXO ╱ ╲ ╱ ╲ h_AB h_CD branch_1 branch_2 ╱ ╲ ╱ ╲ ╱ ╲ ╱ ╲ h_A h_B h_C h_D leaf₁ leaf₂ leaf₃ leaf₄ │ │ │ │ │ │ │ │ DATA DATA DATA DATA refund refund refund refund (each pre-signed Bitcoin tx) each non-leaf = HASH of its each non-leaf = a Bitcoin TRANSACTION children that spends its parent root = one fingerprint of the root = an actual on-chain UTXO whole set the rest live off-chain, pre-signed

You may have heard "Merkle tree" used in Bitcoin contexts. The trees in Spark's deposit are not Merkle trees. They share the word "tree" because of branching, but they're different objects entirely.

A Merkle tree is a hash tree. Each leaf is a piece of data; each non-leaf is the hash of its children; the root is a single fingerprint that commits to the whole set. Given the root and a small "Merkle proof" (one hash per level), you can prove a specific leaf belongs to the set without revealing the others. Merkle trees show up in Bitcoin block headers (the block commits to all its transactions via a Merkle root) and in SPV proofs.

Spark's transaction tree has nothing to do with hashing. Each non-leaf is a real Bitcoin transaction that spends its parent and creates outputs the children can spend. If you broadcast the parent, the child becomes spendable; if you broadcast the child, its child becomes spendable. The branching exists because one deposit can fund many spendable units — not because anyone wants a single hash to commit to everything.

One sentence each:

  • Merkle tree → "here is one fingerprint that proves all of these things are in the set."
  • Spark tree → "here is a hierarchy of pre-signed transactions, each consuming the previous one."

What this actually is — a distinction between a cryptographic commitment scheme (Merkle / hash tree) and a UTXO consumption hierarchy (transaction tree). If you ever encounter a Merkle tree in a statechain context, it is almost certainly a separate proof-of-publication structure (e.g. the Mainstay system in old CommerceBlock Mercury) used for audit, never for the transfer mechanism itself.

With those six blocks in place, the rest of this section is just naming parts. The "four actors" below are who holds which lock or runs which service. The "tree of leaves" is the stack of post-dated checks (block 4) — not a Merkle tree (block 6). The "threshold key" is the second lock split among operators (block 3). The Lightning section is the courier that pays invoices for you. Tokens are dust UTXOs tagged with extra data. Unilateral exit is broadcasting the post-dated checks in order. And every transfer is a lock-swap (block 5). Now back to Spark.

The four actors

Spark documentation conflates these in places. They are distinct roles with distinct trust assumptions.

Figure 8

Who does what in Spark

read across · these are not the same trust assumption
user wallet

You

holds the user share of every aggregate key

Holds

  • Identity key (per device)
  • One user share u per leaf
  • Pre-signed exit transactions
  • Statechain history for each leaf

Signs

  • Every transfer (mandatory)
  • Every cooperative spend
  • Every leaf rotation
no operator can sign without you
spark operators

Operators

jointly hold the operator share of every aggregate key

Holds

  • Operator share of S via Shamir secret sharing
  • FROST DKG state per leaf
  • Signature counter per leaf

Does

  • Co-signs transfers (with the user)
  • Rotates shares on transfer
  • Validates token operations
  • Gossips state via the GossipService
launch set: 2 — Lightspark, Flashnet
SSP

Spark Service Provider

routes Lightning, absorbs 0-conf risk, takes a fee

Holds

  • A Lightning node with channels and liquidity
  • Float to absorb 0-conf deposits
  • Routing tables

Does

  • Pays Lightning invoices on user behalf
  • Receives Lightning payments → credits Spark leaves
  • Risk-scores incoming deposits for 0-conf
launch SSP: Lightspark
issuer (optional)

Token Issuer

creates and controls a BTKN-issued asset

Holds

  • Issuer signing key
  • Token metadata (name, supply, decimals)
  • Reserves (for stablecoins)

Can

  • Mint new units
  • Burn (with consent or by policy)
  • Freeze a user's holdings
a separate trust layer from BTC
"Spark Entity" in the docs is not a fifth actor — it's shorthand for "the threshold of operators acting as a unit." A signing request goes user ↔ operators (FROST). Lightning goes user ↔ operators ↔ SSP ↔ Lightning network. Tokens go user ↔ operators ↔ issuer (for any policy operation).

The threshold key — DKG and customized FROST

Before a deposit can be received, the operators run a Distributed Key Generation ceremony. The output is an aggregate operator public key S whose corresponding private key s exists nowhere — it's threshold-shared across operators using Shamir secret sharing. Any t-of-n operators can collectively sign on behalf of S; fewer than t can't.

When a user deposits, the wallet generates its own user secret u, computes U = u·G, and the deposit address is the Taproot output corresponding to Y = U + S. To spend, the user contributes a partial signature using u, and a threshold of operators contributes the operator side using their Shamir shares of s. The result is a single Schnorr signature on Y — indistinguishable on chain from any other Taproot spend.

Spark's docs emphasize "customized" FROST. The customization buys three properties standard FROST doesn't quite give:

  • Tweakability. Taproot key-tweaking has to compose with the threshold signing — you can't just bolt FROST onto a Taproot output without care.
  • Additive aggregation. Required for the leaf-rotation trick. When ownership of a leaf changes, the operator share rotates by a delta; the user side rotates correspondingly. Same arithmetic shape as Mercury's s₂ = s₁ + t, just distributed across operators.
  • Mandatory user signing. The operator threshold alone cannot produce a signature — the user share is structurally required. This is why operator-set compromise alone isn't theft. (It is when combined with a previous owner.)

The leaf tree, with real timelock structure

A Spark deposit isn't just a UTXO. It's the root of a tree of pre-signed Bitcoin transactions, signed at deposit time and held off-chain. Each transaction in the tree is a normal Bitcoin transaction that could be broadcast unilaterally; in practice, almost none ever are.

The tree typically has three levels: root → branch → leaf. Each level has its own timelock that the next layer down has to beat. The structure encodes the unilateral exit path: to claim a specific leaf without operator help, you broadcast the chain of pre-signed transactions from the root down to that leaf, waiting through each timelock in turn.

Figure 9

One leaf's exit chain — pre-signed transactions and their timelocks

numbers illustrative · actual values per protocol parameters
Depth Transaction What it does Relative timelock
L1 root deposit_tx The Taproot output users actually send BTC to. Locked to Y = U + S. — on chain —
Branch branch_tx Spends the deposit; outputs are sub-aggregate keys for each branch. Pre-signed at deposit time by user + operators. CSV 1024
Sub-branch subbranch_tx Splits a branch into smaller leaf groups. Pre-signed. CSV 512
Leaf leaf_tx The final spendable unit. Output value = leaf size in sats. Spendable by current owner via the operator-cooperated key, or unilaterally after the chain matures. CSV 256
Refund refund_tx Per-leaf "exit" transaction. Pays the current owner's L1 address. Pre-signed at every transfer (with a fresh timelock that decrements per transfer, like a statechain). CSV 144
CSV = "CheckSequenceVerify", a relative-time lock. Each level matures a configurable interval after the previous one is broadcast. The numbers above are illustrative; Spark's actual parameters are tuned for safety margin vs. exit speed. The deeper your leaf is in the tree, the longer your unilateral exit takes.

Two consequences of this structure worth flagging.

Multiplicity is a knob with two ends. A wallet can ask for "more leaves, smaller each" — useful for fast small payments, since a transfer doesn't have to split. The trade is that more leaves means a deeper tree and more pre-signed transactions per deposit, which inflates the data the wallet must keep, and pushes some leaves below the 16,348-sat exit floor where unilateral withdrawal stops being economic.

Refund timelocks decrement on transfer. Just like Mercury's backup transactions, each new owner of a leaf gets a fresh refund transaction with a slightly earlier locktime than the previous owner's. The newest owner's refund matures first, so if any older owner tries to broadcast their stale refund, the current owner has a window to publish theirs and win the race on chain.

Lightning via SSP — the HODL invoice trick

The user's Spark wallet doesn't run a Lightning node. There are no channels, no liquidity to manage, no rebalancing. When a user wants to pay a Lightning invoice, an SSP does it on their behalf — and the atomicity comes from a HODL-invoice construction that ties the Spark leaf transfer to the Lightning payment's preimage.

Figure 10

Spark → Lightning: how a payment without channels actually settles

HODL invoice atomicity
Alice (Spark) Spark Operators SSP (Lightning node) LN recipient ① Alice scans BOLT11 invoice (preimage hash H, amount, expiry) ② conditional leaf transfer (release on preimage H) leaves locked, awaiting H ③ SSP pays invoice on LN ④ recipient releases preimage (settles invoice) ⑤ SSP presents preimage P (verifies H = hash(P)) ⑥ leaves finalized to SSP (key rotation completes) If invoice expires or recipient never settles, the conditional transfer unwinds — leaves return to Alice.
The atomicity comes from the preimage. The conditional transfer to the SSP is contingent on the SSP producing the preimage that hashes to H. The SSP can only produce that preimage by actually paying the invoice. So either the invoice settles and the SSP earns the leaves, or it expires and Alice gets her leaves back. No trust on either side beyond the operators honoring the conditional rotation.

Receiving Lightning payments works in reverse. The user generates an invoice, the SSP holds the channel and receives the payment; once the SSP has the preimage, the operators rotate fresh leaves to the user. The receiver never had a Lightning node, never had channels, never paid for inbound liquidity.

Fees as published: Spark→Lightning 0.25% of the amount plus the LN routing fee paid by the SSP; Lightning→Spark free for the receiver, 0.15% from the sender via route hint pricing. Spark→Spark in BTC is currently free. The fee structure is expected to change.

The token layer (BTKN)

BTKN is Spark's token standard. It's a successor to LRC20 (a Bitcoin tokenization scheme that embedded data in script outputs). Where BTKN differs is that token data lives in two places: the Bitcoin address itself (via a small tweak that's invisible to non-token-aware wallets), and in metadata that Spark Operators validate.

Figure 11

The anatomy of a token UTXO vs. a BTC UTXO

on-chain vs Spark-managed

Plain BTC leaf

scriptP2TR · pays to Y = U + S
value100,000 sats
metadatanone — value is the value
issuer— none —
freezableno
backed byBitcoin consensus

BTKN-issued leaf (e.g. a stablecoin)

scriptP2TR · tweaked to encode token id
value (sats)dust (e.g. 546 sats)
value (token)100.00 USDx
issuerissuer signing key
freezableyes — issuer policy
backed byissuer reserves + policy
A BTKN leaf occupies a real Bitcoin output (so it's anchored to the chain) but the on-chain value is dust — the actual economic value sits in the token metadata that operators validate. The trust model accordingly: BTC behaviour is enforced by Bitcoin consensus; token behaviour is enforced by issuer policy and operator validation.

What this means in practice: a stablecoin holder is exposed to three trust layers stacked on top of each other.

  • Bitcoin. The leaf UTXO must remain valid on chain. Standard Bitcoin assumptions apply.
  • Spark operators. They must honestly delete old shares on transfer (the same statechain trust assumption that affects BTC leaves).
  • Issuer. Reserves must back the supply; the issuer must not freeze your address; redemption must remain available. None of this is enforced by Bitcoin.

The Issuer SDK exposes mint, burn, and freeze as first-class operations. Freeze is not a bug; it's a feature that compliance-focused issuers want. Holders should know they hold it.

Unilateral exit, as it actually works

The cooperative exit is uneventful: user and operators jointly sign a normal transaction sending funds to the user's chosen L1 address. Fee per the formula 250 × sat/vB + 750. Done in seconds.

The unilateral exit is the test case. It's beta. Reading the docs carefully, the actual procedure is roughly this:

  1. The wallet identifies which leaves it owns and constructs the broadcast plan: for each leaf, the chain of pre-signed transactions from the root down to the refund_tx.
  2. The wallet stages a separate fee UTXO (the user must already hold confirmed BTC outside the Spark deposit, just for fee bumping).
  3. The branch transaction broadcasts first. It's expected to confirm with low fees because of the staged fee UTXO via CPFP — but Spark's flow specifically requires Bitcoin Core v29's ephemeral anchors for some configurations, which means a wallet running an older node may simply fail at this step.
  4. The CSV timer on the branch starts ticking. The wallet must wait — usually days — before the next layer can be broadcast.
  5. The sub-branch broadcasts. Wait again.
  6. The leaf transaction broadcasts. Wait again.
  7. Finally the refund transaction broadcasts to the user's L1 address. The funds are now on chain.

The whole sequence is "single-session" — the wallet has to complete it without losing state. There's no resume; if the wallet gets reinstalled mid-exit and the broadcast plan is lost, the user is in trouble. And throughout the exit window, the wallet is locked — no transfers, no payments. For a 4-level tree at 1024/512/256/144 CSV blocks, that's ~13 days of locked wallet plus L1 confirmation time per layer.

This is why "unilateral exit" is real but operationally heavy. The cooperative path exists for a reason.

What's actually broken: the public incident log

Spark publishes a status page. The incidents on it are the closest thing to a public reliability dataset. A selection from the past year:

9 Apr 2026 operatorpartial outage. One operator unreachable; threshold still met, signing continued but with degraded redundancy. 30 min
30 Mar 2026 operatordegraded performance — signing latency rose; some transfers timed out and required client retry. 1h 56m
2 Feb 2026 SSPmajor outage on the launch SSP (Lightspark). Lightning send/receive unavailable; Spark→Spark transfers continued. 3h 45m
15–17 Dec 2025 leavesrenewal stuck. Some leaves whose refund transactions needed re-signing on schedule got stuck in a renewal state for ~2 days. ~ 48 h

What this dataset actually shows. Liveness incidents are common but bounded. No theft, no permanent loss, no integrity compromise reported in any of the above. The pattern is operational degradation that the user experiences as "the app doesn't work right now," sometimes for a few hours. The launch SSP is a single point of failure. When Lightspark's SSP went down for nearly four hours, Lightning stopped working for everyone. A second SSP would help. Leaves can get stuck. The Dec 2025 incident is the most worrying because it's not just liveness — leaves in a renewal state can't be transferred or exited until the operators resolve the underlying state inconsistency.

Beta means this category of incident is expected. The question is how the rate trends as the protocol matures.


A complete worked example: Alice's 100,000 sats over 60 days

To make all of the above concrete: a single Spark cycle with real numbers — every block height, every locktime, every scalar relationship. Alice opens a wallet, deposits 100,000 sats, pays Bob, Bob receives a Lightning payment, and eventually exits to L1. (Alternative ending: what unilateral exit would have cost.) Numbers are illustrative — block heights match the rest of the site at 947,435 baseline; CSV values match Figure 9.

Figure 11b · interactive sequence

One leaf's full lifecycle on a chain — from deposit to exit

read top to bottom
on chain deposit_tx 100,000 sats → Y_A block 947,435 pre-signed off-chain at deposit time, never broadcast unless needed branch_tx 100k → 4 × 25k CSV 1024 ≈ 7 days leaf_tx (one leaf) 25,000 sats CSV 256 ≈ 1.8 days refund_tx 24,800 → owner_L1 CSV 144 ≈ 1 day cooperative path (default — operators co-sign a single L1 tx) cooperative_withdraw ~3,250 sats fee at 10 sat/vB if operators are responsive, the entire pre-signed chain above is bypassed
The pre-signed chain only matters if operators stop cooperating. In the normal path, none of branch_tx / leaf_tx / refund_tx ever broadcasts — the wallet just calls cooperativeWithdraw and a single L1 transaction settles in one block. The pre-signed chain is the user's independent escape hatch.

Day 0 — the deposit

block 947,435 · multiplicity = 4 leaves

Alice installs the wallet. It generates an identity key and a fresh user secret u_A. Operators run distributed key generation; the resulting operator share S exists nowhere as one secret — only as Shamir shares across operators. Alice gets a deposit address corresponding to Y_A = U_A + S. She sends 100,000 sats to that address. The block confirms.

In parallel with the on-chain confirmation, the wallet and operators jointly pre-sign a four-leaf tree. Every transaction in the tree is signed at this moment; none will be broadcast unless cooperative recovery fails.

deposit_tx 947,435 100,000 sats → Y_A (on chain) branch_tx (off) 100,000 → 4 × 25,000 CSV 1024 leaf_tx 1..4 (off) 25,000 each CSV 256 refund_tx 1..4 (off) 24,800 → Alice_L1 CSV 144 Alice holds: u_A, plus per-leaf user shares u_A_1 .. u_A_4 Operators: one Shamir share each of the operator-side S Sig counter: 0 (per leaf)

invariant: U_A + S = Y_A, and the deposit UTXO matches Y_A on chain.

Day 7 — Alice pays Bob 25,000 sats (one leaf)

block 948,443 · 1,008 blocks later · ~zero fee, ~one second

Bob installs a wallet, generates an identity key, sends Alice his Spark address (a public derivation of his identity key — not a Bitcoin address; nothing about it appears on chain). Alice's wallet calls wallet.transfer({ receiver: bob, amountSats: 25000 }). Coin selection picks leaf 1 — exact match, no split needed.

The per-leaf rotation runs:

1. Bob generates u_B, computes U_B = u_B · G, sends U_B → Alice 2. Alice encrypts u_A_1 to Bob's identity key, sends ciphertext c → Bob 3. Bob decrypts c, recovers u_A_1 4. Bob computes t = u_A_1 − u_B 5. Bob sends t → Operators (not blinded; Spark sees metadata) 6. Each operator updates its Shamir share by adding t (after reconstruction: s' = s + t) 7. New refund_tx signed: pays Bob_L1, CSV 143 (was 144 — decremented by 1) 8. Operators delete old share contributions 9. Sig counter for leaf 1: 0 → 1

invariant: U_B + S' = U_B + (S + t·G) = U_B + S + (U_A_1 − U_B) = U_A_1 + S = Y_1. The leaf's on-chain key is unchanged.

From Alice's view: balance −25,000. From Bob's view: balance +25,000. From Bitcoin's view: nothing happened. From the operators' view: leaf 1 rotated, sig counter incremented, old share destroyed.

Day 14 — Bob receives a 50,000-sat Lightning payment

block 949,451 · involves the SSP · 0.15% sender-side fee

A friend pays Bob a Lightning invoice. Bob doesn't run a Lightning node — the SSP holds the channel. The invoice was generated against the SSP's node, with a route hint pointing at Bob's Spark identity. The payment lands at the SSP; the SSP gets the preimage; Bob's wallet learns the preimage; operators rotate fresh leaves to Bob to match the amount minus fees.

SSP receives 50,000 sats on Lightning (preimage P released) operators split a larger SSP-controlled leaf: → 50,000 to Bob (new aggregate Y_5 = U_B + S') → change to SSP (whatever's left) sig counter[Y_5]: 0 (fresh leaf) Bob's wallet now: 25,000 (from Alice) + 50,000 (from LN) = 75,000 sats spread across 2 leaves

The 50,000-sat leaf is structurally identical to a normal Spark leaf — it has its own pre-signed exit chain back to L1, its own refund_tx paying Bob's L1 address, its own CSV-locked timelocks. The only thing "Lightning" about it is its provenance.

Day 60 — Bob exits cooperatively to L1

block 956,075 · single Bitcoin transaction · ~3,250 sats fee

Bob calls wallet.cooperativeWithdraw({ destination: bc1q…, leafIds: [leaf_1_alice, leaf_5_lightning] }). The operators respond, co-sign a single Bitcoin transaction spending both leaves' Taproot outputs to Bob's L1 address. Wallet broadcasts.

cooperative_withdraw_tx inputs: leaf_1 (25,000) leaf_5 (50,000) total 75,000 sats outputs: Bob_L1 71,750 sats fee: 3,250 sats (= 250 × 10 sat/vB + 750) signed: Bob (u_B for both leaves) + threshold of operators confirms: block 956,076 (~10 minutes later) operators: delete shares for both leaves; tree is dissolved.

Done. Bob is back on L1 with 71,750 sats in his chosen address. The pre-signed exit chains for these leaves are now historical artifacts — the on-chain UTXOs they referenced are spent.

Day 60 alternative — what if Bob had to exit unilaterally?

starts block 956,075 · ends ~block 957,499 · ~10 days locked

Suppose the operators stop responding. Bob has to broadcast the pre-signed chain himself, level by level, waiting through each CSV timer. For one leaf (the 25,000-sat one):

block 956,075 broadcast branch_tx (CPFP from staged 5,000-sat fee UTXO) fee bump cost: ~600 sats wait for 1 confirmation, then start CSV timer block 957,099 CSV 1024 elapsed (≈ 7 days, give or take fee market) broadcast leaf_tx wait CSV 256 block 957,355 CSV 256 elapsed (≈ 1.8 days) broadcast refund_tx wait CSV 144 block 957,499 CSV 144 elapsed (≈ 1 day) refund_tx confirms; 24,800 sats land at Bob_L1 ──────────────────────────────────────── wall-clock total: ~10 days wallet locked throughout fees absorbed: ~1,200 sats over the chain

For the 50,000-sat leaf: same procedure, possibly sharing branch_tx if it's already been broadcast. Both leaves exit eventually but the wallet is unusable for ~10 days. And if either leaf had been below 16,348 sats, the per-level fees would have exceeded the leaf value — at which point unilateral exit isn't economic, and the user is genuinely stuck unless cooperative recovery resumes.

cost of an uncooperative operator set: ~10 days, ~1,200 sats overhead, and a wallet you can't use.

That's a single-leaf exit. A wallet with many leaves repeats the leaf and refund stages per leaf (or batches them where the protocol allows). The key insight from the alternative ending: cooperative exit is so much faster and cheaper that operators have enormous practical leverage over users — even when the unilateral path technically exists.

IV · Ark

A coin you own but never put on chain

Primitive VTXOs inside one shared Bitcoin output Ark Labs builds Arkade Second builds bark

Ark answers a different question than the statechains before it. Mercury and Spark ask "how do two people pass one on-chain coin back and forth without touching the chain?" Ark asks "how do a thousand strangers share one on-chain coin at the same time, each able to leave alone?" The answer is a VTXO — a virtual UTXO — and the entire protocol is the machinery that keeps a VTXO spendable off chain while never taking away its owner's right to walk it back onto Bitcoin without anyone's permission.

It becomes legible once you separate two clocks. On the fast clock, users hand VTXOs around off chain at the speed of an operator signature. On the Bitcoin clock, those VTXOs are periodically anchored, renewed, or exited through real on-chain transactions. Almost every confusion about Ark comes from collapsing those two clocks into one.

Fast clock

Preconfirmed

The operator co-signs a virtual transaction. The receiver can spend the new VTXO immediately, before any Bitcoin transaction confirms.

Trust: the operator does not co-sign a conflicting spend of the same coin.
Bitcoin clock

Settled / refreshed

A round commits a fresh tree of VTXOs to Bitcoin in one transaction. The receiver gets a new exit path; the old VTXO is forfeited atomically.

Cost: on-chain fees, operator liquidity, time, and an expiry you must beat.
Mental model

A VTXO is a spendable coin bolted to an escape kit

what the wallet actually holds
value 50,000 sats sitting in a virtual output — a slice of a shared on-chain UTXO, not a UTXO of its own
cooperative path a Taproot key path the owner and operator sign together: the normal, instant spend
exit path pre-signed branch and leaf transactions the owner can broadcast alone, no operator required, after a timelock
expiry a block height after which the wallet must have refreshed, spent, or exited — or the operator may sweep
A normal UTXO gives you direct L1 spend rights. A VTXO gives you off-chain spend rights plus a prebuilt route back to L1. The route is what makes Ark self-custodial; the expiry is what makes wallet liveness non-optional. The official docs put it plainly: each VTXO "is backed by a presigned, unbroadcast Bitcoin transaction… and can be broadcast at any time to move your funds onchain."

One on-chain output, a thousand owners

Here is the trick the marketing words ("Virtual Mempool", "batch swap") hide. The operator does not create one on-chain UTXO per user. It creates one on-chain output and hangs a whole tree of pre-signed transactions off it. The root is the single output that lands on Bitcoin. Intermediate transactions split it into branches. The leaves are the individual VTXOs. Thousands of independent ownership claims share one Bitcoin transaction output — and because of Taproot and MuSig, that output looks on chain like an ordinary single-signature payment.

To get your money out without the operator, you don't get to spend the shared output directly. You broadcast your branch of the tree, transaction by transaction, from the root down to your leaf. That is the whole design in one sentence: shared on chain, individual off chain, and a pre-signed ladder connecting the two.

Figure 12

The VTXO tree under one commitment output

root on chain · branches & leaves pre-signed, off chain
commitment / round tx ON CHAIN · one Taproot output branch tx · CLTV branch tx · CLTV leaf · VTXO CSV · Alice leaf · VTXO CSV · Bob leaf · VTXO CSV · Carol leaf · VTXO CSV · Dave to exit alone, Dave broadcasts root → his branch → his leaf, in order
Level Transaction What it does Timelock
Root commitment_tx The one transaction that actually lands on Bitcoin. Its single output funds the entire tree and is locked to an n-of-n key over everyone in the round. Ark Labs calls this the commitment transaction; Second calls it the round transaction. — on chain —
Branch branch_tx Pre-signed, off chain. Splits the output into sub-groups (Second fans out four ways per node). Carries an absolute timelock so the operator can reclaim the whole subtree once the round expires. CLTV (absolute)
Leaf leaf_tx The individual VTXO. A Taproot output with two paths: the cooperative key path (owner + operator), and the unilateral exit path the owner can take alone after a relative delay. CSV (relative)
Every VTXO in one round shares the same absolute expiry — the root and branch CLTV timelocks all mature together, which is how the operator can recycle a whole round's liquidity at once. The relative CSV on the leaf is the cooling-off period an exiting owner must sit through before the coin is finally theirs on L1. Exact block counts are per-operator policy, not protocol constants.

Why everyone has to pre-sign the tree

There is a hole in the plan above, and it is the most important thing about Ark. For your unilateral exit to be safe, the branch and leaf transactions must be fixed — the operator must not be able to rewrite the tree after the fact and strand your coin. The clean way to enforce that would be a covenant: a Bitcoin opcode (Jeremy Rubin's OP_CHECKTEMPLATEVERIFY) that says "this output may only be spent by this exact pre-committed transaction." Bitcoin does not have that opcode today. So covenantless Ark — the only kind running on mainnet — fakes it.

Figure 13

The covenant Ark wants vs. the covenant it can have

CTV dream · MuSig2 reality
Covenant Ark · needs a soft fork

How the tree is fixed:

OP_CHECKTEMPLATEVERIFY
// Bitcoin Script itself enforces
// "spend only to this exact tx"

Who must be online to build a round:

  • nobody — the operator can commit the tree unilaterally

On-chain footprint:

  • tiny — exits split into very few outputs

Status:

not deployable — CTV is not in Bitcoin
Covenantless Ark · works today

How the tree is fixed:

n-of-n MuSig2 pre-signing
// every participant signs every tx
// in the tree, then deletes the key

Who must be online to build a round:

  • everyone in that round — all must co-sign live

On-chain footprint:

  • heavier — more pre-signed transactions per exit

Status:

running on mainnet — no fork required
The substitute for a covenant is a promise that everyone made and then made unbreakable by throwing away the key. The cost is interactivity: you can only be packed into a round you were online for.

The round: how VTXOs get anchored to Bitcoin

Because the tree needs everyone's live signature (§6), settlement happens in rounds. The operator runs them on a cadence — Second targets one every 1–2 hours; Ark Labs frames the same act as a batch swap that produces a new commitment transaction. Whatever the name, the shape is identical: gather the participants, build and co-sign one tree, put its root on chain, and hand everyone a fresh VTXO with a reset expiry.

Figure 14

One round, four moves

Second's terms · Arkade's are noted inline
1

Submit intent

Each wallet comes online and tells the operator which VTXOs it wants to refresh (or which fresh funds it wants to board). In Arkade this is a signed RegisterIntent PSBT.

2

Build & co-sign the tree

The operator lays out the VTXO tree. Every participant MuSig2-signs their branch and exit transactions — the n-of-n pre-signing from §4 — and deletes their ephemeral key.

3

Broadcast the root

The operator broadcasts the single on-chain transaction — the round / commitment transaction. Once it confirms, every VTXO in the tree has Bitcoin-level finality.

4

Forfeit & claim

Each user signs a forfeit handing their old VTXO to the operator, tied to a connector so it only takes effect if step 3 landed. The new VTXO is now live.

Step 4 is the subtle one, and it is where most "explanations" of Ark quietly stop. Refreshing into a new VTXO without giving up the old one would let you spend the same money twice — once in the new tree, once by exiting the old leaf you still hold. Forfeit transactions and connectors are how Ark closes that hole.

Forfeit transactions and connectors

When you refresh, your old VTXO does not vanish — you still physically hold its pre-signed exit ladder, and that ladder is still valid on Bitcoin. So Ark makes you sign a forfeit transaction: a transaction that hands the old VTXO to the operator. The operator keeps it as insurance. If you ever try to exit a VTXO you already refreshed away, the operator broadcasts your forfeit and claws the coin back — you burn your own fees and gain nothing.

But a forfeit creates its own danger: what if you sign the forfeit and the operator pockets your old coin without ever putting your new one on chain? That is what connectors prevent. The forfeit transaction is built to require a connector output as a second input — and that connector only comes into existence when the new round transaction confirms. So the forfeit is unspendable until your new VTXO is real. Either both happen or neither does.

Figure 15

Why the forfeit can't be used against you

the connector makes it atomic
Forfeit alone · broken

You sign:

forfeit_tx: old_VTXO → operator

The operator can now:

  • take your old VTXO immediately
  • never broadcast your new VTXO
  • leave you with nothing
// you've paid before you were paid
Forfeit + connector · atomic

You sign:

forfeit_tx: old_VTXO + connector → operator
// note the second input

The connector exists only if:

  • the round / commitment tx confirmed
  • …which is the same tx that creates your new VTXO
// no new coin ⇒ no connector ⇒ forfeit invalid
The connector is a tiny output the round transaction mints, one per forfeited VTXO. Because your forfeit must spend it, the forfeit is physically impossible to broadcast until your replacement coin exists on chain. Second adds a hash-lock on top, so a misbehaving operator that withholds a preimage still can't strand you — you keep your unilateral exit.

The liquidity engine nobody mentions

Here is the cost that explains why VTXOs expire at all. When the operator broadcasts a round, the root output is funded with the operator's own bitcoin. Your old VTXOs are forfeited to it in exchange — but the operator can't actually spend those forfeited coins until their round's timelock expires. So at any moment the operator has real capital locked up, fronting the new round while waiting weeks to recover the old one.

That float isn't free, and you pay for it. Refresh fees include a liquidity charge that scales with how much runway you're asking the operator to cover:

liquidity_cost ≈ amount × (expiry_delta ÷ 365 days) × rate

Refreshing a coin that still has weeks of life costs more than one about to expire, because you're asking the operator to carry more time. This is also why expiry exists in the first place: it is the clock on which the operator gets its capital back. Ark is, underneath, a liquidity-provision business wearing a payments protocol.

Out-of-round payments — Ark's statechain moment

Rounds are slow (hours) and need everyone online, which would make Ark useless for actual payments. So between rounds, Alice can pay Bob now: she and the operator co-sign a new spend VTXO that chains directly off Alice's existing leaf. Bob can spend it instantly. Second brands this arkoor — literally ark out-of-round; Ark Labs routes it through the Virtual Mempool, where independent VTXO spends form a DAG and execute in parallel.

Figure 16

Alice pays Bob, and what each party now believes

preconfirm first · harden later
Alice

Spends a VTXO

Alice signs a virtual transaction spending her VTXO, creating a new spend VTXO for Bob plus her change.

Operator

Co-signs it

The operator co-signs and promises not to co-sign a conflicting spend of Alice's input. No round, no on-chain transaction.

Bob

Holds a spend VTXO

Usable instantly. But until he refreshes it into a round, Bob is trusting that Alice and the operator don't collude to double-spend.

Bitcoin

Sees nothing

No L1 transaction has happened. The chain only learns of it later, if Bob refreshes, offboards, or exits.

This is the exact moment Ark touches the statechain family. A fresh out-of-round VTXO carries a temporary "trust the sender + operator not to collude" assumption — the same flavour of trust a statechain transfer carries before the receiver locks it in. Refreshing into a round removes it: the docs are blunt that "the adjusted security model is only ever temporary."

The receiver's decision tree

Use it immediately. For small amounts, Bob can treat a spend VTXO like pocket cash. He can even pass it onward — but each hop lengthens the chain and widens the set of past parties he's implicitly trusting not to collude.

Refresh it. For larger amounts, Bob joins the next round. That converts the payment into a refresh VTXO with a clean unilateral exit, a reset expiry, and zero dependence on Alice behaving later. Change he receives from his own refresh is trustless from the start — he can't collude against himself.

Offboard or exit. To get real L1 bitcoin, Bob cooperatively offboards with the operator (cheap, atomic). If the operator is gone or hostile, he broadcasts his pre-signed exit ladder himself. That is the emergency path, not the everyday one.

flows

The five things you can do with a VTXO

click a tab
Board
Pay (out of round)
Refresh (in a round)
Offboard
Emergency exit
  1. You co-sign a funding transaction with the operator and broadcast it to L1.
  2. You wait for on-chain confirmations — but not for a round.
  3. You now hold a board VTXO with a direct, trustless unilateral exit. You can also receive spend VTXOs from others before you've boarded anything yourself.

Boarding is the one VTXO whose exit is just two transactions deep — it hasn't been folded into a deep tree yet.

  1. You and the operator co-sign a new spend VTXO chaining off one of yours.
  2. The operator promises not to co-sign a conflicting spend of that input.
  3. The receiver can use it instantly, carrying the temporary "no sender + operator collusion" trust until they refresh.

No liquidity, no on-chain footprint, near-instant. This is the fast clock.

  1. You come online during a round and submit the VTXOs you want to refresh.
  2. You MuSig2-sign the new tree's branch and exit transactions, then delete your ephemeral key.
  3. You sign a forfeit (bound to a connector) handing over the old VTXO.
  4. Once the round transaction confirms, the new VTXO is live with a reset expiry and a clean exit.

Refreshing is how a spend VTXO becomes trustless again — and how you beat the expiry clock.

  1. You cooperate with the operator to forfeit your VTXO in exchange for a normal L1 output to an address you choose.
  2. Like most Ark operations, the offboard is atomic.
  3. This is the efficient, everyday way to leave — far cheaper than an emergency exit.

Use this whenever the operator is cooperative. The emergency exit exists for when it isn't.

  1. Broadcast the first branch transaction on your VTXO's path from the root.
  2. When it confirms, broadcast the next branch, and so on down the tree — each must confirm before the next.
  3. Broadcast your leaf's exit transaction, then wait out its relative CSV timelock.
  4. Broadcast a claim transaction. Your bitcoin is now on L1 and will never expire.

Unilateral and unstoppable — no one can prevent it. But it costs one on-chain transaction per level, so deep trees and small VTXOs make it expensive, even uneconomic when fees spike.

One quietly elegant property: an emergency exit broadcasts shared branch transactions. If Alice exits first, she puts the upper branches on chain — and Bob, Carol, and Dave, who sit under the same branches, now have less of the tree left to broadcast. Early exiters subsidise later ones. A bank-run on an Ark operator gets cheaper per user as it proceeds.

Interactive · play the protocol

Run a four-user Ark yourself

board · round · arkoor · refresh · exit — hover any node

Everything above — the VTXO tree (Fig. 12), covenantless pre-signing (Fig. 13), the round with its forfeit + connector (Figs. 14–15), arkoor (Fig. 16) and the liquidity clock — wired into one sandbox. Each moment is shown two ways, side by side: an ownership tree (who holds what, and the exit ladder) and a full transaction graph (every transaction — boardings, the round tx, the pre-signed tree txs, the connectors, forfeits, arkoor and exits — with each output linked to the input that spends it). Take the guided tour for the canonical story, or free-play: board users, run a round to mint the tree, pay out-of-round, refresh to settle, or walk a coin back to L1 with a unilateral exit. Watch the on-chain footprint stay tiny while four people transact.

A teaching model, not a wallet: block counts and the liquidity fee are illustrative (≈ amount × expiry_delta ÷ 365 × rate), and one round mints one block here. The mechanics are faithful — one on-chain root per round, n-of-n pre-signing with key deletion, connector-gated forfeits, the arkoor trust window, a shared absolute expiry, and CSV exits.

Two implementations of the same idea

Ark is a protocol shape, not a product. Two teams ship it with different surfaces and different bets. Both run covenantless, both use the round + forfeit + connector machinery above — they diverge on what they optimise the rest of the stack for.

Ark Labs · Arkade

A programmable execution layer

Ark Labs frames Arkade as "a programmable execution layer for Bitcoin" — an operating system for money, where VTXO transactions run in a Virtual Mempool and settle to Bitcoin through batch swaps.

Fast clock The Virtual Mempool: an off-chain execution engine where transactions form a DAG and independent VTXO branches execute in parallel without blocking each other.
Hardening Batch swap → commitment transaction. New VTXOs and the connector outputs are created atomically, so forfeits are only valid once settlement confirms.
Operator constraint The Arkade Signer is split off from the operator and runs inside a TEE. Remote attestation lets anyone verify it runs only audited open-source code; users reach it over encrypted channels. The operator can't extract the signing key or quietly censor.
Optimised for Apps: payments, assets, swaps, smart contracts, programmable spending rules, delegation — driven by a TypeScript/Go SDK and an experimental Bitcoin-native scripting layer.
Second · bark

A payment-first Ark wallet

Second ships bark, an open-source Ark wallet, behind a "painless API" for adding Ark, Lightning, and on-chain payments to an app. The protocol is described through plain wallet operations.

Fast clock Arkoor: out-of-round payments that mint a spend VTXO instantly — no liquidity cost, works even to offline receivers.
Hardening Rounds roughly every 1–2 hours. A spend VTXO refreshed in a round becomes a refresh VTXO — same trustless exit as a freshly boarded coin, with a reset ~30-day lifetime.
Operator constraint Board and refresh VTXOs have direct pre-signed exits from the moment they're made. Hash-locked forfeits + connectors keep refreshes atomic; a withholding server still can't block your unilateral exit.
Optimised for Wallet rails: Ark payments, a Lightning gateway (the server runs the LN node, so users need no channels), cooperative offboarding, and practical fee/liquidity policy.
Comparison

Arkade vs. bark, in one table

same protocol family, different surface
Dimension Ark Labs · Arkade Second · bark
Public nameArkade, by Ark Labsbark, by Second
Settlement termBatch swap → commitment transactionRound → round transaction
Fast pathVirtual Mempool preconfirmation (DAG)Arkoor out-of-round payments
Round cadenceContinuous batch swaps~1–2 hours (configurable)
VTXO lifetimePer-operator policy; renew before batch expiry~30 days, server-configurable
Operator trustTEE-isolated Arkade Signer + remote attestationHash-locked forfeits; trustless exits on board/refresh
Best fitProgrammable off-chain Bitcoin applicationsWallets & payment apps wanting Ark + Lightning + L1

What Ark gives up

Ark is not a rollup and not a sidechain. There is no separate consensus system proving every virtual transaction to Bitcoin. The fast path is operator-coordinated preconfirmation; the safety net is simply that you already hold Bitcoin-valid transactions that unroll your claim back to L1.

That net is real but not free. Exit depth grows with tree depth and with chained off-chain spends, so a small VTXO can become uneconomic to exit when fees spike. The interactivity requirement (§6) means you can only settle in a round you were online for. And expiry turns liveness into a hard requirement: if your wallet doesn't refresh in time, the operator's right to recycle that liquidity becomes part of your security story. Ark therefore shifts the central UX question from "can I exit?" to "will my wallet keep my VTXOs fresh and exit-ready without me thinking about it?"

Sources: Arkade overview, Arkade VTXOs, Arkade Virtual Mempool, Arkade Signer / security, Second intro, Second VTXO types, Second rounds, Second forfeits & connectors, Second liquidity, Second exit, covenantless Ark (clArk), connectors, Bitcoin Optech: Ark.

V · Lineage

What each one inherited and what each one changed

In 2018 Ruben Somsen sketched the first statechain. A 2-of-2 between a user and an entity holds a Bitcoin UTXO. The user has a transitory key — a private key whose corresponding public point sits inside the 2-of-2. To transfer ownership, the current owner simply gives the transitory key to the new owner. The entity promises to only ever co-sign with the holder of the latest transitory key, and that promise is enforced cryptographically: every transfer carries an adaptor signature binding the entity's secret. If the entity ever co-signs with two different owners on the same UTXO, anyone watching can subtract the two adaptor signatures and recover the entity's private key. Cheating is punished by losing all funds the entity controls.

That is the original. It is elegant, and it makes three assumptions that turn out to be load-bearing:

  1. That Bitcoin will eventually have eltoo / LN-Symmetry, so "latest state wins" can be a consensus rule rather than a foot race.
  2. That the entity may freely see everything — the UTXO it co-signs, the transactions, the eventual on-chain signature.
  3. That a statecoin transfers at whole-UTXO granularity — a 1 BTC statecoin pays exactly 1 BTC, no more, no less.

Mercury Layer and Spark are each a renegotiation of some subset of those assumptions. Each fixes one or two and inherits the rest. The grid below reads dimension-by-dimension; the tag on each cell says how that design choice relates to the original.

Figure 12

Three designs, eight dimensions

read across each row
2018 · primitive

Original

Key model 2-of-2 multisig with a single transitory key that the current owner hands forward to the next.
Cheating accountability Adaptor signatures: if the entity equivocates, its secret leaks and anyone can take the funds.
Server visibility Entity sees the UTXO, the transactions it co-signs, the final signature.
Operator topology A single statechain entity. One vendor, one point of failure.
Transfer granularity Whole UTXO. A 1 BTC statecoin transfers 1 BTC — period.
Eltoo dependency Required by the design. "Latest state wins" assumes a consensus rule Bitcoin doesn't have. required
Lightning Out of scope. (Statechains and Lightning are complementary in theory.)
Tokens None. The primitive transfers BTC only.
2020–2024 · privacy first

Mercury Layer

Key model No more transitory key. Each new owner picks a fresh o; the server rotates its s so the aggregate P is unchanged. (Figure 4.) ↻ changed
Cheating accountability Adaptor-sig accountability is dropped. Substituted with a server-published signature counter + optional SGX enclave. ↓ dropped
Server visibility Blinded co-signing. Server signs partial sigs without learning the UTXO, the public key, or the on-chain signature. ✓ improved
Operator topology Still a single entity. Just blind to what it's signing. = inherited
Transfer granularity Still whole UTXO. Lightning Latch pairs a statecoin with a Lightning payment for partial-amount sales. = inherited
Eltoo dependency Replaced by decrementing backup locktimes: each transfer cuts c = 144 blocks. The newest owner races any older backup on chain. ↻ workaround
Lightning Lightning Latch — sells a statecoin atomically against a HODL invoice. + added
Tokens None. = inherited
2024–2025 · operations first

Spark

Key model Same rotation idea, but the server share is split across n operators using FROST. t of them must cooperate to sign or rotate. ↻ changed
Cheating accountability Adaptor-sig accountability is dropped. Substituted with the threshold itself: cheat requires t-of-n operator collusion + a previous owner. ↓ dropped
Server visibility Operators see metadata — which leaves, which transfers. Privacy is not Spark's pitch. = inherited
Operator topology Threshold of operators (FROST DKG, Shamir shares). Reduces single-vendor risk; introduces correlated-failure risk. ✓ improved
Transfer granularity Tree of leaves. A deposit splits into many spendable units; a payment is a leaf selection. Floor: leaves under 16,348 sats can't be exited unilaterally. ✓ improved
Eltoo dependency Replaced by per-leaf pre-signed exit transactions, signed at deposit time before the deposit becomes active. ↻ workaround
Lightning Built into the protocol via SSPs that hold a Lightning node and pay invoices on the user's behalf. + added
Tokens BTKN issuer SDK — stablecoins, mint/burn/freeze. Outside the original's scope entirely. + added
improved vs. original regressed vs. original added (new capability) dropped (lost a guarantee) changed approach inherited unchanged

What was given up

The most important thing the original had — and the most important thing both derivatives gave up — is the adaptor-signature accountability. In Somsen's design, cheating is cryptographically punished: equivocate, your key leaks, your funds become anyone's. There is no "trust the operator to delete its share." There is "if the operator misbehaves, it loses everything."

Mercury and Spark replaced that mechanism with operational ones — a published signature counter, an SGX enclave attestation, a threshold of operators, watchtowers, decrementing locktimes. Each is plausible. None is a cryptographic guarantee. They are deployable on Bitcoin today, which the original strictly speaking is not (without eltoo, the original's "latest state wins" loses its teeth too).

Mercury improved privacy and lost cryptographic accountability. Spark improved topology and granularity, lost privacy, and lost cryptographic accountability. Neither solved the deletion problem; both made it more deployable.

That's the whole picture in two sentences. Each derivative is the original minus a cryptographic guarantee, plus a different operational property. There is no free lunch — only different lunches.

VI · Side by side

What you give up, in exchange for what

Dimension Statechains Mercury Layer Spark Ark
On-chain objectLocked UTXO, 2-of-2Taproot shared-key UTXOTree of leaves under L1 rootBatch output with VTXO tree
Transfer granularityWhole UTXOWhole UTXOPartial — leaves split & mergeUTXO-like VTXOs
Server / operatorSingle co-signerSingle blind co-signerThreshold operators + SSPsArk operator / Arkade signer
CustodyCannot spend aloneCannot spend aloneCannot spend without userPre-signed exits preserve user claim
Trust at transferNo collusion with old ownerServer / HSM deletes old share≥ 1 (or threshold) operators deleteOperator does not double-sign preconfirmed VTXOs
Privacy from serverDesign-dependentStrong — blinded co-signingOperators see metadataImplementation-dependent
Exit pathCooperative · pre-signed backupCooperative · timelocked backupCooperative · branch & leaf chainCooperative offboard · branch & leaf exit
Works on today's BitcoinSome variantsYesYesYes
LightningComplementaryLightning Latch (HODL invoice)Built-in via SSPInterop via swaps / Bark rails
TokensNoneNot primaryBTKN + Issuer SDKArkade assets
Main weaknessWhole-UTXO, key deletionSingle server, validation burden, archivedBeta, small operator set, exit complexityOperator preconfirm trust, expiry, exit cost

Read across each row, not down the columns. A statechain isn't a worse Spark — it's the primitive both others descend from. Each makes the same trade in a different place.

VII · Concrete failures

How it actually breaks

Three real failures, scrubbed forward in time. Pick a scenario; drag the playhead across the timeline; watch the events fire and the loss accumulate.

Figure 13 · interactive

Three failures, on a timeline

drag to scrub
Statechain · missed dispute window
Mercury · sequence 0xFFFFFFFF
Spark · branch republished

Time elapsed

0 h

Last event

— none yet —

Loss to date

$0

No theft yet.

All three timelines use the same horizontal scale. The scrubber is the playhead; events fire as you cross them. Loss is recorded only after the on-chain confirmation that finalises the attacker's transaction.

A few specific numbers

Concrete losses behave the same in every system: the entire UTXO or leaf, minus the attacker's fee. The numbers below come from documented protocol limits, observed Spark incidents, and the September 2024 Mercury disclosure.

Failure System Direct theft? Temporary lock? What to watch
Old owner + entity collusionAllYesFull UTXO / leaf value
Mercury sequence 0xFFFFFFFF bugMercuryYesFull statecoin value
Missed dispute windowAllYesWindow (often hours, sometimes minutes)
Timelock exhaustionStatechains, MercuryPossiblyYesRemaining blocks before backup matures
Server / operator liveness failureAllYesBackup delay · exit complexity
Spark leaves below 16,348 satsSparkYesLeaf size, not total balance
High L1 exit feesAllsat/vB × number of exits
Whole-UTXO mismatchStatechains, MercuryUTXO denomination vs payment
Token freeze / depegSpark tokensPossiblyPossiblyIssuer policy / reserves
The sharpest failures are the ones where the user believes they own a coin off-chain, but an older state can still win on chain. The loss is simple: the entire UTXO or leaf, minus whatever fee the attacker paid.