Archive
Signed chain history. Check yours against it, repair what diverges, or boot a fresh instance from it.
Bootstrap reads the before a single row, restores , and does it in .
Bootstrap refuses a database that already holds blocks; use secondlayer repair for an existing instance.
| Flag | Effect |
|---|---|
--to-block <n> | Stop early |
-y | Skip the prompt |
--from-block <n> restores forward-only: whole partitions at or after that block. Everything below is declared out of scope rather than missing, so verify doesn't read it as divergence. The tradeoff: the disk floor at boot is still the full-history one.
Dry-run by default. The plan names exact heights, not ranges:
Each partition is hashed against the signed digest before any row is read. A replaced block's transactions, events and state writes are rewritten with it. One transaction per partition, so an interrupted repair leaves no half-corrected range.
Heights the archive doesn't have
Local heights absent from the archive are reported, never deleted, because transactions and events reference them.
Decoded rows are not rebuilt. Re-run your decoders for repaired ranges.
Read-only; digests stay on your machine. The archive is a best-effort public utility, not a hosted service. Verification is free and always will be. A range that diverges looks like this:
Verify then names each diverging block and what differs in it, read free from the archive's per-block digests, and prints a repair command for every diverging range. --json lists every height under divergent_heights; older snapshots report ranges only.
| Job | Command |
|---|---|
| Check raw identity columns | secondlayer verify raw --against <latest.json> |
| Check every published dataset | secondlayer verify all --against <latest.json> |
| Also check payload columns | secondlayer verify --against <latest.json> --deep |
| Plan a repair | secondlayer repair --against <archive> |
| Write the repair | secondlayer repair --against <archive> --apply |
| Restore a fresh instance | secondlayer bootstrap --against <archive> |
| Price a hosted fetch | secondlayer archive quote --against <archive> |
| Check from your instance's API | POST /v1/archive/verify |
| Read the archive tip | secondlayer archive latest |
| Read the node attestation | GET attestations/<digest>/node.json |
| Read operational status | GET status.json |
<latest.json> is the signed pointer. Start there.
Each also lives under archive; examples use the short form.
| Short | Same as |
|---|---|
secondlayer verify | secondlayer archive verify |
secondlayer repair | secondlayer archive repair |
secondlayer bootstrap | secondlayer archive bootstrap |
| Target | Checks |
|---|---|
raw | blocks, transactions, events, state_writes |
all | Every dataset the manifest publishes |
The archive publishes digests for the raw datasets only.
decode:<name>andsubgraph:<name>parse, but have nothing to compare against yet: exit2.- To check subgraph rows, run
secondlayer verify subgraph <name> --replay.
Clean output exits 0. Divergence names the ranges, as in Check it.
Equal row counts with differing data means the same heights hold different blocks: a fork point left on the losing branch.
| 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.
| 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 a signing key. Default is the archive key built into the CLI release, or ARCHIVE_SIGNING_PUBLIC_KEY when set. |
--insecure | Compare without verifying the signature. Result is unverified. |
--json | Machine-readable report on stdout. |
POST /v1/archive/verify runs the same raw-identity check on the instance itself, read-only, with the archive URL in the body. Body fields and responses: API reference.
| Answer | Means |
|---|---|
clean | Local data matches the archive |
diverged | Divergence found |
unanchored | The archive was unreachable or its signature failed |
A failed signature is a 200 unanchored, never clean.
The tradeoff against the CLI: identity digests only. --deep is CLI-only.
What the archive costs, what it is, and how much each range is worth.
Credits
Bootstrap, backfill, and reindex fetch from the archive metered per partition bundle, quoted against your balance before anything is charged; verification is free.
secondlayer archive quote --against <archive> prices a fetch without charging. It exits 2 when your balance falls short.
| Flag | Effect |
|---|---|
--from-block / --to-block | Narrow the fetch |
--flow repair | Price a repair |
Buy with secondlayer credits buy. Packs, balance, and how the quote/confirm flow works: credits.
What the archive is
Immutable, digest-addressed Parquet partitions on R2, published from a repeatable-read snapshot of a production Stacks index, one partition per 50,000 blocks.
| Dataset | One row per |
|---|---|
blocks | Canonical block |
transactions | Transaction, in block order |
events | Event, in block order |
state_writes | Clarity state change a block made, named per key, so each can be checked against the block's state root |
state_writesappears once the archive is exported from a stack that holds it from genesis, after the December 2026 cutover.- Until then a manifest simply leaves it out. That means not published, never empty, and bootstrap, verify and repair skip it.
| 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/, state_writes/ | Range-partitioned Parquet, digest in the filename. Served only through the fetch gate (presigned URLs, see Credits); every other object here is public. |
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. source.decoder_head is the running Index decoder; archive.coverage_to_block is the last signed publish; next_publish_at is when the next one starts (UTC). |
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.
Assurance levels
The manifest states one assurance level per range:
db-reconstructivenode-attestedobserver-attested
What each means: Verify.
CLI for the full command set; Verify for everything else you can check, from a transaction to a block.
Edit on GitHub