Skip to content
LogoLogo

Pool welds

Per transition the pool verifies the main proof and, for classes 0 and 1, the wrapper proof, then checks by plain equality on publics:

  • payment_root equal across main proof, wrapper, and (class 1) the hold.
  • time_bucket ∈ {now, now − 1} where now = block.timestamp / BUCKET (BUCKET = 300 s). The wrapper never sees raw time, which keeps policies coarse and lets a proof straddle a bucket boundary.
  • registry_root ∈ Registry.recentRoots() and !Registry.revoked(fi_index).
  • state_in == fiState[fi_index]; after success the pool writes fiState[fi_index] = state_out.
  • Class 0 (initiate): counterparty_fi_index == recipient_fi_index (a public of the initiate circuit); attestation_in == 0; the pool stores sender_fi_index = fi_index, recipient_fi_index, deadline_bucket, attestation = attestation_out, and the envelope in the hold.
  • Class 1 (resolve): hold.status == open; fi_index == hold.recipient_fi_index; counterparty_fi_index == hold.sender_fi_index; attestation_in == hold.attestation; the pool records attestation_out in the closed hold for audit and appends the output commitment.
  • Reclaim: hold.status == open; time_bucket > hold.deadline_bucket; no wrapper proof; appends the refund commitment.

State concurrency: a stateful FI's transitions are serialized by state_in; two proofs against the same state_in cannot both land. FI backends must serialize proving per FI. Stateless FIs (fiState = 0 forever) have no ordering constraint. Sharded state roots are an open question (§12).

State at phase 0 is provisional by design: a velocity ledger counts a hold that later rejects or is reclaimed. The sender FI never runs again for that hold in v1; an optional settle callback is deferred (§12).