Skip to content

Storage model

The gateway persists application state in SQLite. Storage::new configures WAL journal mode, synchronous=NORMAL, a five-connection pool, and a five- second busy timeout. Embedded migrations run on startup and are forward-only.

Core records

Record / table Role
attestations Canonical hash, timestamp, network, sequence, job status, lease and retry fields
signatures Individual Ed25519 witness signatures keyed by hash and witness ID
aggregated_signatures One BLS aggregate per hash
aggregated_signers Ordered signer IDs for a BLS aggregate
sequences Per-network next sequence allocator
batches Batch ID, network, period, count, and Merkle root
batch_attestations Batch membership and Merkle index
signed_tree_heads RFC 9162 tree size, root, timestamp, batch, and signed envelope
log_state Cached current log root and size for STH computation
cross_anchors Peer network and serialized peer signed attestation for a batch
external_anchor_proofs Provider, timestamp, provider JSON, and optional anchored bytes

The schema also retains compatibility migration logic for legacy BLS rows. New BLS data uses the dedicated aggregate tables.

Job state

 pending ---> confirmed
    |             ^
    v             |
 retryable ------+
    |
    +-----------> failed

hash is the canonical primary key. network_id and sequence are also unique as a tuple. Reservation allocates the sequence and inserts the job in a single transaction. Claiming adds an expiring lease; completion is allowed only for the current live lease and matching tuple.

The gateway reads signature rows in the same SQLite snapshot as the job state and exposes signatures only for confirmed jobs. The durable job fields include attempt count, next attempt time, bounded last error, lease token, lease expiry, and completion time.

Batch and log state

batch_attestations.merkle_index records the position of each attestation hash inside its batch. The batch root is built with the RFC 9162 domain-separated Merkle algorithm. signed_tree_heads stores the global log commitment after a batch closes. log_state is a cache used for efficient current-root calculation; the persisted batch and membership records remain the source for reconstructing the log.

Local-disk requirement

gateway process
      |
      +--> gateway.db
      +--> gateway.db-wal
      +--> gateway.db-shm
             |
             v
       reliable local disk

Keep the database and its WAL/SHM files on reliable persistent local storage. Do not put this SQLite database on a network filesystem. A restart can recover ordinary in-progress jobs and confirmed records, but SQLite does not protect against host loss, disk failure, operator compromise, or a malicious rewrite of the database.

Use a persistent directory rather than /tmp, restrict its permissions, and back up the database and deployment configuration. Test restoration. A backup is not an independent proof of gateway honesty; signed attestations, retained proofs, STH consistency checks, and an auditor serve that purpose.

Migration posture

Migrations are compiled into the gateway and applied in order at startup. They are forward-only. Operators should take a verified backup and test an upgrade against a copy. Downgrading requires a compatible pre-upgrade backup and the older binary; migrations are not automatically reversed.