Change an account. Don’t corrupt the chain.
layoutd diffs two versions of your on-chain account layout, generates provably-safe migration code, and blocks the unsafe upgrade in CI — without ever touching the blockchain.
The problem
Silent corruption is the default.
When your program upgrades, old accounts keep their original byte layout. The chain has no schema registry — no runtime awareness that your struct changed shape.
Your new code reads those old accounts through a modified struct. The deserializer silently interprets the wrong bytes.
V1 account layout (live on chain)
Insert a field →
One new field shifts every field after it to the wrong byte offset.
Anchor v1.0 introduced a Migration<From, To> runtime gate. The gate exists. The layer that writes the migration and proves it safe did not. layoutd is that layer.
Live output
See every finding, live.
V1 · UserState
V2 · UserState
Three commands
The entire surface area of layoutd.
layoutd diff
--v1 state_v1.rs --v2 state_v2.rs
What changed, and what's risky.
Parses two Anchor account structs, computes byte-level offsets, and classifies every field change as Safe · Review · Danger. Outputs a human-readable report and machine-readable SARIF.
layoutd gen
--v1 state_v1.rs --v2 state_v2.rs --out migration.rs
Write the safe migration for me.
Emits a complete, compilable Anchor migration instruction for provably-safe cases. Scaffolds dangerous ones behind an explicit acknowledgement. Each output carries a proof annotation.
layoutd check
--v1 state_v1.rs --v2 state_v2.rs
CI gate. Exit code. No drama.
Produces a SARIF 2.1.0 report and exits non-zero on any Danger verdict. Renders inline as GitHub PR annotations. The official GitHub Action wraps this for two-line CI adoption.
The risk model
Three tiers. No grey area.
layoutd never refuses to help —
it refuses to let danger be silent.
Proven. Auto-generated.
A provably-correct transformation exists. layoutd emits complete migration logic — no human input required, no offset math to verify.
- Field appended at struct end
- Field renamed — same type and position
- Zero byte shift on existing fields
Probably safe. Human eyes needed.
Migration code is generated with a warning. Correctness depends on context the tool cannot see — CI policy decides whether to auto-pass or require approval.
- Type widened — u8 → u16, same signedness
- Mid-struct insert — Borsh, matched by name
- Field reordered — Borsh only
No provable path. Fails CI.
No automatically-correct transformation exists. CI fails by default. Shipping requires an explicit, recorded acknowledgement naming the exact field and change.
- Field removed — data lost, offsets shift
- Mid-struct insert — zero-copy alignment required
- Type reinterpreted — bytes change meaning
Shipping danger requires acknowledgement
A DANGER verdict fails CI by default. To override, the CI config must explicitly name the exact field and change being acknowledged. The danger cannot be silent — it becomes a permanent, audited decision in your version history.
How it works
Five deterministic steps. Zero RPC calls.
01
Parse
Read IDL or raw Rust source for V1 and V2. No network, no RPC, no runtime.
02
Layout
Compute byte offsets, sizes, and alignment padding for every field in both versions.
03
Diff
Produce a structured field-level diff with full offset provenance.
04
Classify
Assign each change Safe, Review, or Danger using the deterministic risk model.
05
Emit
Output a human report, SARIF 2.1.0 file, and migration code.
All steps are pure functions of the two input structs. Fully reproducible offline. No secrets, no network access, no side-effects.
Why it’s trustworthy
Six promises.
All of them structural.
Trust in a security tool isn’t built from copy — it’s built from constraints. layoutd earns trust by refusing to operate outside provable bounds, not by asserting that it’s trustworthy.
Models bytes, not intent
Computes exact byte offsets and alignment padding for every field. Not a guess from names — a proof from layout.
Zero false-safe verdicts
If layoutd cannot prove a migration is safe, it classifies DANGER. Silence is never safe. There are no optimistic assumptions.
Deterministic + version-pinned
The same two structs always produce the same verdict on the same version. Verdicts never change silently across releases.
SARIF 2.1.0 + GitHub Action
Outputs SARIF consumed by GitHub's code scanning pipeline. The official Action wraps check for two-line CI adoption — no YAML plumbing required.
Narrow on purpose
Does one thing: prove whether an account layout migration is safe. Never touches the blockchain. Never holds keys. Never emits transactions.
Danger requires acknowledgement
Shipping a known DANGER requires naming that exact change in CI config. The danger can never be silent again — it becomes an explicit, audited decision.