Verified archive
Check your chain history against a signed canonical archive, repair what diverges, or restore a fresh instance from it.
| Job | Command |
|---|---|
| Check raw identity columns | sl verify raw --against <latest.json> |
| Check every published dataset | sl verify all --against <latest.json> |
| Check one decoder | sl verify decode:ft_transfer --against <latest.json> |
| Also check payload columns | sl verify --against <latest.json> --deep |
| Plan a repair | sl repair --against <archive> |
| Write the repair | sl repair --against <archive> --apply |
| Restore a fresh instance | sl bootstrap --against <archive> |
| Read the node attestation | GET attestations/<digest>/node.json |
| Read operational status | GET status.json |
<latest.json> is the signed pointer. Start there.
sl verify raw --against https://pub-08fa583203de40b2b154e6a56624adc2.r2.dev/secondlayer/mainnet/canonical/v1/latest.jsonRead-only. Digests stay on your machine. Default target is raw.
| Target | Checks |
|---|---|
raw | blocks, transactions, events |
all | Every dataset the manifest publishes |
decode:<name> | That decoder's datasets |
subgraph:<name> | That subgraph's datasets |
No matching dataset in the manifest is exit 2.
Clean output exits 0. Divergence names the ranges:
⚠ 1 of 175 ranges diverge from the archive.
RANGE DATASET STATUS EXPECTED LOCAL
----------------- ------- ------------ -------- -----
8500000-8549999 blocks data differs 50000 50000
These ranges hold different data than the signed archive.Equal row counts with differing data means the same heights hold different blocks — a fork point left on the losing branch.
Exit codes
| Code | Meaning |
|---|---|
0 | Local data matches the archive. |
1 | Divergence found; every divergent range is listed. |
2 | Unanchored — the archive was unreachable or its signature failed. |
2 is never success. Not being able to check differs from being fine.
Flags
| Flag | Effect |
|---|---|
--against <manifest> | Archive latest.json, a snapshot manifest URL, or a local path. Required. |
--quick | Identity columns only. Default. |
--deep | Also recompute semantic digests (raw_tx, event data, function_args). |
--anchor | Require a verified archive signature. |
--from-block <n> / --to-block <n> | Limit the checked range. |
--counts | Also compare transaction and event row counts. Slower. |
--semantic | Alias of --deep. |
--public-key <pem> | Pin the signing key instead of fetching it. |
--insecure | Compare without verifying the signature. Result is unverified. |
--json | Machine-readable report on stdout. |
sl repair --against <archive> # plan
sl repair --against <archive> --apply # write itDry-run by default. The plan names exact heights, not ranges:
HEIGHT ACTION LOCAL ARCHIVE
------- ------- ------------ -------
8501111 replace 0xd4deb46c6d 0xedb6ba8322Each partition is hashed against the signed digest before any row is read. One transaction per partition — an interrupted repair leaves no half-corrected range.
Heights the archive doesn't have
Local heights absent from the archive are reported, never deleted — transactions and events reference them.
Decoded rows are not rebuilt. Re-run your decoders for repaired ranges.
sl bootstrap --against <archive>Shows both timings before it starts, then restores and verifies itself:
coverage genesis → 8,745,422
signature verified
sync from genesis ~19.4 days (estimate)
restore from archive ~2.3 hoursRefuses a database that already holds blocks — use sl repair for an existing instance. --to-block <n> stops early; -y skips the prompt.
Immutable, digest-addressed Parquet partitions on R2, published from a repeatable-read snapshot of a production Stacks index. Three datasets — blocks, transactions, events — partitioned by height.
| Object | Contents |
|---|---|
latest.json | Signed pointer at the current snapshot. Start here. |
snapshots/<digest>.json | Signed manifest: coverage, counts, per-object digests, finality rule, audit. |
blocks/, transactions/, events/ | Range-partitioned Parquet, digest in the filename. |
digests/<range>-<sha16>.parquet | Per-height sidecar: one row per height with the block digest and rolled-up transaction and event digests. |
attestations/<digest>/node.json | Signed independent node audit. coverage is the attested window; stats is exact; mismatches[] is a capped sample. |
status.json | Short-cache operational state: fresh, lagging, stale, gap, failed-audit, source-unavailable. |
reports/incidents/ | Signed incident reports, newest first via index.json. |
Publishing is append-only. Each partition carries a SHA-256 over its bytes and a semantic-v1 digest over its canonical encoding. The manifest is ed25519-signed.
| Level | Means |
|---|---|
db-reconstructive | Exports from one repeatable-read snapshot restore deterministically. Does not prove no historical callback was omitted. |
node-attested | Block identities (hash, index_block_hash) also match an independently synced stacks-node for the window in node.json. Transactions and events stay db-reconstructive — the node does not expose execution raw_result or events. |
observer-attested | Digests match independently retained raw observer history. |
The manifest states its level per range. Most of the chain is db-reconstructive. A published node.json upgrades only the listed coverage window.
Not an SLA
The archive is a best-effort public utility, not a hosted service. Verification is free and always will be.
CLI for the full command set; Verification for per-transaction inclusion proofs.