Skip to main content

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에서 보기