Use this skill when a user wants to generate, boot, verify, or extend a state-actor-produced Ethereum database. Covers --client, --spec, --target-size, per-client boot recipes (geth / reth / besu / nethermind / ethrex / erigon), and the canonical 29-entity spec fixture.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Use this skill when a user wants to generate, boot, verify, or extend a state-actor-produced Ethereum database. Covers --client, --spec, --target-size, per-client boot recipes (geth / reth / besu / nethermind / ethrex / erigon), and the canonical 29-entity spec fixture.
SKILL.md — how to use state-actor
This is the canonical "how to use this lib" doc for agents. The root AGENTS.md is a pointer that points here.
state-actor generates client-ready Ethereum databases for geth, reth, besu, nethermind, ethrex, and erigon without going through each client's init path. You point it at a --db path, choose a --client, optionally pass a --spec declaring concrete entities, and it writes a database the client can boot against directly.
Read these first
Read these in this order. The first one is load-bearing — read it before you read any prose about specs.
examples/full-matrix-spec-feature.yaml — the canonical syntax reference for --spec. CI-pinned, 29 entities, every feature. Read this file before reading any other doc about specs; see the Canonical spec reference section below for an intent → entity-# index.
SPEC.md — the schema reference (parser rules, validation errors, address-resolution algorithm, approximate_size_bytes semantics). Read alongside the fixture.
Which client format to write (geth, reth, besu, nethermind, ethrex, erigon)
--spec
Path to a YAML file declaring concrete entities (EOAs, contracts, ERC-20s, EIP-7702 delegations)
--target-size
Advisory budget that sizes the auto-fill of synthetic state. Not a hard on-disk cap — actual size may vary per client.
Everything else has a sane default. Run state-actor --help for the full list (22 flags).
Canonical spec reference
The single source of truth for what a --spec YAML can express is examples/full-matrix-spec-feature.yaml. Read that file before reading anything else about specs. It is exhaustive (29 entities, every feature), self-documenting (six section banners + per-entity comments), and CI keeps it correct.
The CI guarantees that hold this file as the canonical reference:
internal/specbuild/full_matrix_test.go (TestBuildFullMatrix) pins the entity count at 29 and asserts the cross-client PreAlloc count equality. The unit-level drift gate — byte-identity is enforced downstream by the cross-client-genesis-root aggregator job.
internal/e2e_testing/spec_setup.go (LoadCISpec) loads the fixture with seed=0 + sizecal.NewFixed(64) so every client sees the same input.
The cross-client · genesis state-root invariant aggregator job in .github/workflows/ci.yml refuses to merge a PR whose four clients produce different genesis roots from this fixture.
The fixture is organised into six labelled sections; each one pins a feature cluster:
Section banner (in the YAML)
Entities
Feature pinned
1. Spamoor sender
1
Anvil dev-account-0 EOA with high balance
2-7. ERC-20 flavor coverage
2-7
All three address modes × bulk-fill × storage-bloat × nonce override × skeleton
8-9. Explicit-owners + allowances coverage
8-9
Granular owners list, explicit + bulk allowances
10-12. Raw bytecode flavors
10-12
kind: contract + code: (no template); large code; storage synth
Edit the load-bearing fields for your case — addresses, balances, template parameters, approximate_size_bytes. The field-by-field cheatsheet in examples/README.md lists exactly which fields control what and what the constraints are (e.g. decimals must be 18 for the erc20 template).
Address mode: explicit (address: is set), name-derived (name: only), or position-derived (neither). The mode determines stability of the resulting address; see SPEC.md § Address resolution for the algorithm.
Omit --target-size when running --spec alone — that way no auto-fill runs on top, eliminating the collision risk between random EOAs and spec-derived addresses. Set --target-size only when you intentionally want auto-fill to pad the headroom.
Verify the entities landed at the addresses you expect: cast code 0x<derived-address> returns the bytecode (contracts) or 0x plus the delegation marker (7702 EOAs); cast balance 0x<address> returns the spec's balance.
For the schema-level details the fixture's per-entity comments don't cover — parser rules, validation errors, the address-derivation algorithm, approximate_size_bytes resolution semantics — read SPEC.md. It's the schema reference; the fixture is the syntax reference; you typically need both. Internal references: internal/spec/doc.go (parser + validator), internal/specbuild/doc.go (entity resolution), internal/templates/doc.go (template registry).
Common tasks
Generate a geth DB
go run . --db=/tmp/sa-geth/geth/chaindata --client=geth --target-size=100MB
Auto-fill emits mainnet-shaped state (20 % account-trie / 10 % bytecode / 70 % contract storage) up to the --target-size cap, with a deterministic seed. Output is a Pebble database geth can boot with --db.engine=pebble. The /geth/chaindata suffix is mandatory — geth appends it to --datadir.
go run . --db=/tmp/sa-reth --client=reth --target-size=100MB # MDBX + RocksDB + static files
go run . --db=/tmp/sa-besu --client=besu --target-size=100MB # single RocksDB, 17 Bonsai CFs
go run . --db=/tmp/sa-neth --client=nethermind --target-size=100MB # 7 RocksDB + flat column DB
go run . --db=/tmp/sa-ethrex --client=ethrex --target-size=100MB # single RocksDB, 22 CFs
go run . --db=/tmp/sa-erigon --client=erigon --target-size=100MB # Erigon v3 flat .kv snapshots + minimal MDBX
Recipes (state-actor invocation + docker boot command + verification) live in RUNBOOK.md, one section per client.
Verify a generated DB
Recommended: run the per-client end-to-end suite. The Go oracle exercises CheckChainID, CheckCanonicalSyscontracts, CheckChainAdvanced, CheckBeaconRootsRingBuffer, and CheckInjections (see internal/e2e_testing/):
go test ./client/geth/... # or ./client/reth/... ./client/besu/... ./client/nethermind/...
Every run drops a state-actor-manifest.json at the datadir root (two levels up from --db for geth; the --db dir itself for the other clients) recording everything needed to reproduce it: the resolved flags — note the resolved seed (--seed=0 expands to a wall-clock seed) and the resolved fork (empty --fork resolves to the client's max) — the build version + git revision, the run's state root, and, when --spec is used, a content-addressed state-actor-spec-<sha256>.yaml sidecar written alongside it.
Re-run it into a fresh directory with the reproduce subcommand:
go run . reproduce --manifest /tmp/sa-geth/state-actor-manifest.json --db /tmp/sa-geth-repro/geth/chaindata
It replays the manifest's resolved flags (reading any spec from the sidecar — whose sha256 is verified first — not the original path), regenerates into --db (which must be a fresh, empty or nonexistent directory, distinct from the original), and verifies the new state root against the recorded one — exiting non-zero on mismatch. This works even for runs created with --seed=0, since the manifest captured the concrete seed. The reproduced datadir gets its own manifest too, with a reproduced_from field pointing back at the source manifest.
Reproduce a CI failure locally
CI loads examples/full-matrix-spec-feature.yaml on top of --seed=42 --target-size=100MB (mirrored across all five TestE2ESuite constants). The auto-fill (mainnet-shaped 20 / 10 / 70 split) emits synthetic state to fill the headroom between the spec's projected cost and --target-size — the spec entities are written first, the auto-fill fills the gap. Re-run:
go test -run TestE2ESuite ./client/<client>/... -v
Diagnose "wrong state root"
The cross-client genesis-root invariant says: same --seed, same spec, same client-policy → identical state root across all six MPT clients. If it diverges, see ARCHITECTURE.md#cross-client-determinism for the full check-list (per-client calibration in internal/sizecal/doc.go; canonical syscontract preamble; CI keystone job).
Constraints & gotchas
Besu / reth / nethermind / ethrex / erigon require Docker for the writer side (cgo dependencies; no native build on macOS). Only geth has a pure-Go writer.
--seed=0 is a footgun: main.go rewrites it to time.Now().UnixNano(), i.e. randomises. For determinism use any non-zero seed. Bench convention is --seed=42.
--target-size is required when --spec is not set: drives the mainnet-shaped auto-fill (20 % account-trie / 10 % bytecode / 70 % storage) over the whole budget. With --spec, spec entities count first; the auto-fill fills the headroom on top. If the spec alone exceeds the budget, internal/specbuild truncates the entity list to the longest prefix that fits and emits a --target-size … truncated spec at entity[N] warning to stderr; no auto-fill runs in that case.
--archive is geth/reth only: rejected for besu, nethermind, and ethrex; accepted but a no-op for erigon.
--binary-trie is geth-only (EIP-7864).
When using --spec alone, omit --target-size — that way no auto-fill runs on top and random EOAs can't collide with spec-derived addresses. Set both only when you want the auto-fill to pad the headroom.
Nethermind boot needs a JSON boot.cfg pointing at the chainspec + datadir (see client/nethermind/e2e_test.go's nethermindE2EConfigTemplate). The other clients accept boot flags directly.
Testing
go test ./... # full suite
go test -run TestE2ESuite ./client/... # per-client end-to-end
go test -short ./... # skip the e2e suites
CI matrix lives in .github/workflows/ci.yml.
When asked to extend state-actor
The entry points cluster by the kind of extension:
Implement Template in a new file in internal/templates/; Register(yourTemplate) in init(); add a section to SPEC.md; add a covering entity to examples/full-matrix-spec-feature.yaml so CI exercises it. Mirror erc20.go's shape.
Add client/<name>/ with a Run (or RunCgo) entry point, a doc.go documenting on-disk layout + pinned upstream version, and a TestE2ESuite driving Docker boot + the shared e2e.RunSuitePhases oracle. Wire into internal/clientpolicy/policy.go.