state-actor
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 33-entity spec fixture.
소스 정보
- 저장소
- ethereum/state-actor
- 최근 소스 활동
- 2026년 9월 17일 10:35
- 감지된 SKILL.md 언어
- 영어
- 스타
- 12
- 포크
- 11
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
파일 탐색기
6 개 파일SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- state-actor
- description
- 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 33-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`](../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.
1. [`examples/full-matrix-spec-feature.yaml`](../examples/full-matrix-spec-feature.yaml) — **the canonical syntax reference for `--spec`**. CI-pinned, 33 entities, every feature. Read this file before reading any other doc about specs; see the [Canonical spec reference](#canonical-spec-reference) section below for an intent → entity-# index.
2. [`SPEC.md`](SPEC.md) — the schema reference (parser rules, validation errors, address-resolution algorithm, `approximate_size_bytes` semantics). Read alongside the fixture.
3. [`RUNBOOK.md`](RUNBOOK.md) — per-client boot recipes (geth / reth / besu / nethermind / ethrex / erigon).
4. [`ARCHITECTURE.md`](ARCHITECTURE.md) — internal architecture; cross-client determinism; per-client writer differences.
## Three load-bearing flags
| Flag | What it controls |
|---|---|
| `--client` | 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`](../examples/full-matrix-spec-feature.yaml).** Read that file before reading anything else about specs. It is exhaustive (33 entities, every feature), self-documenting (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`](../internal/specbuild/full_matrix_test.go) (`TestBuildFullMatrix`) pins the entity count at 33 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`](../internal/e2e_testing/spec_setup.go) (`LoadCISpec`) loads the fixture with `seed=0` + `sizecal.NewFixed(64)` so every client sees the same input.
- Per-client `TestE2ESuite` (in [`client/geth/e2e_test.go`](../client/geth/e2e_test.go), [`client/besu/e2e_test.go`](../client/besu/e2e_test.go), [`client/nethermind/e2e_test.go`](../client/nethermind/e2e_test.go), [`client/reth/oracle_test.go`](../client/reth/oracle_test.go) for reth, [`client/ethrex/e2e_test.go`](../client/ethrex/e2e_test.go) for ethrex, and [`client/erigon/e2e_test.go`](../client/erigon/e2e_test.go) for erigon) boots a real client against state-actor's output, runs spamoor, and verifies every entity via the Go oracle.
- The `cross-client · genesis state-root invariant` aggregator job in [`.github/workflows/ci.yml`](../.github/workflows/ci.yml) refuses to merge a PR whose four clients produce different genesis roots from this fixture.
The fixture is organised into 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 |
| `13-15. EIP-7702 EOA flavors` | 13-15 | `0xef0100<delegate>` delegation marker × address modes × storage bloat |
| `16-22. Plain EOA flavors` | 16-22 | All address modes, zero balance, hex-form balance, default-nonce, storage on EOA |
| `23-29. PR 76 repricing-benchmark templates` | 23-29 | `storage_pattern`, `create2_factory`, `create2_deploys` (literal and fixed `code_pattern`), `create_preimage_deploys`, `sequential_eoas`, `sequential_pkey_eoas` |
| `30-33. Size-adjustable code patterns` | 30-33 | `code_size:` on `unique_jumpdest` / `max_same` / `max_diff`, including the EIP-7954 64 KiB limit, and on `sequential_pkey_delegations` |
### Intent → entity-# index
| To declare … | Look at fixture entity # | Section |
|---|---|---|
| Plain EOA at explicit address | 1, 16 | Spamoor sender / Plain EOA flavors |
| Plain EOA, name-derived address | 17 | Plain EOA flavors |
| Plain EOA, position-derived address | 18 | Plain EOA flavors |
| Zero-balance or hex-form balance EOA | 20, 21 | Plain EOA flavors |
| Plain EOA with synthesized storage | 19 | Plain EOA flavors |
| EIP-7702 delegating EOA | 13, 14, 15 | EIP-7702 EOA flavors |
| EIP-7702 EOA + storage bloat | 14 (`bloated-validator`) | EIP-7702 EOA flavors |
| ERC-20 at explicit address with bulk fill | 2 | ERC-20 flavor coverage |
| ERC-20 name-derived | 3 | ERC-20 flavor coverage |
| ERC-20 position-derived | 4 | ERC-20 flavor coverage |
| ERC-20 skeleton (no holders) | 5 | ERC-20 flavor coverage |
| ERC-20 with explicit `nonce` override | 6 | ERC-20 flavor coverage |
| ERC-20 with `approximate_size_bytes` (template + bloat) | 7 | ERC-20 flavor coverage |
| ERC-20 with explicit `owners` and `allowances` | 8 | Explicit-owners + allowances |
| ERC-20 explicit + bulk combined | 9 | Explicit-owners + allowances |
| Raw bytecode contract | 10, 11, 12 | Raw bytecode flavors |
| Plain EOA with omitted-nonce default (0) | 22 | Plain EOA flavors |
| CREATE2 deployments at derived addresses | 25, 29 | PR 76 templates |
| A 24 KiB fixed-size code pattern | 29 | PR 76 templates |
| A code pattern at a chosen `code_size` | 30-33 | Size-adjustable code patterns |
| A 64 KiB (EIP-7954) contract runtime | 31 | Size-adjustable code patterns |
| EIP-7702 authorities delegating to planted contracts | 33 | Size-adjustable code patterns |
### How to adapt the fixture to a new spec
1. **Find the entity that matches your intent** using the index above; jump to that entity in [`examples/full-matrix-spec-feature.yaml`](../examples/full-matrix-spec-feature.yaml).
2. **Copy the entity block** into your new YAML.
3. **Edit the load-bearing fields** for your case — addresses, balances, template parameters, `approximate_size_bytes`. The field-by-field cheatsheet in [`examples/README.md`](../examples/README.md#field-by-field-cheatsheet) lists exactly which fields control what and what the constraints are (e.g. `decimals` must be 18 for the `erc20` template).
4. **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](SPEC.md#address-resolution-three-deterministic-modes) for the algorithm.
5. **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.
6. **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`](SPEC.md). It's the schema reference; the fixture is the syntax reference; you typically need both. Internal references: [`internal/spec/doc.go`](../internal/spec/doc.go) (parser + validator), [`internal/specbuild/doc.go`](../internal/specbuild/doc.go) (entity resolution), [`internal/templates/doc.go`](../internal/templates/doc.go) (template registry).
## Common tasks
### Generate a geth DB
```bash
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`.
See [`RUNBOOK.md#geth`](RUNBOOK.md#geth) for the boot command, and [`client/geth/doc.go`](../client/geth/doc.go) for the on-disk layout and writer details.
### Generate a DB for a specific client
```bash
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
```
`besu`, `nethermind`, `reth`, `ethrex`, and `erigon` require cgo (RocksDB / MDBX bindings). On macOS, build via Docker — the repo ships per-client Dockerfiles. The per-client on-disk layout and pinned upstream version live in [`client/reth/doc.go`](../client/reth/doc.go), [`client/besu/doc.go`](../client/besu/doc.go), [`client/nethermind/doc.go`](../client/nethermind/doc.go), [`client/ethrex/doc.go`](../client/ethrex/doc.go), [`client/erigon/doc.go`](../client/erigon/doc.go).
### Boot a generated DB on a client
Recipes (state-actor invocation + docker boot command + verification) live in [`RUNBOOK.md`](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/`](../internal/e2e_testing/)):
```bash
go test ./client/geth/... # or ./client/reth/... ./client/besu/... ./client/nethermind/...
```
**Manual**: boot the client per [`RUNBOOK.md`](RUNBOOK.md), then:
```bash
cast chain-id --rpc-url http://localhost:8545 # → 0x539 (1337)
cast balance 0x<a-known-spec-address> --rpc-url ... # → the spec's balance
cast code 0x<a-known-spec-contract> --rpc-url ... # → the spec's bytecode
```
### Reproduce a run from its manifest
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:
```bash
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:
```bash
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`](ARCHITECTURE.md#cross-client-determinism) for the full check-list (per-client calibration in [`internal/sizecal/doc.go`](../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`.
GitHub에서 보기이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기