Skip to content

docs(specs): contract registry and transaction outcome tracking specs - #65

Closed
bdchatham wants to merge 1 commit into
mainfrom
brandon2/spec-contract-deployment-registry
Closed

docs(specs): contract registry and transaction outcome tracking specs#65
bdchatham wants to merge 1 commit into
mainfrom
brandon2/spec-contract-deployment-registry

Conversation

@bdchatham

Copy link
Copy Markdown
Contributor

Two specifications. Neither changes any code.

Contract registry — ready to implement

specs/contract-deployment-registry/ carries the full Spec Kit cycle: spec.md, plan.md, data-model.md, contracts/registry-api.md, quickstart.md, tasks.md.

The problem. A contract scenario deploys its contract at the start of every run. That is correct on a fresh chain and wrong on every long-lived one. Each run against arctic-1, atlantic-2 or pacific-1 leaves another copy behind, and every restart of the prod canary moves its contract to a new address — so a metric series spanning two restarts describes two different contracts, and nothing says the address changed.

sei-load already has the mechanism. AttachScenario binds a scenario to an existing address and every contract scenario implements it, but only the unit-test path calls it and config.Scenario has no address field. The capability exists and no profile can reach it.

What the spec settles. 23 requirements (CDR-001 to CDR-023), 10 acceptance scenarios (AS-1.1 to AS-3.3), and 10 success criteria (SC-001 to SC-010) each carrying a verifier command.

Requirements come first. The design and its eight tradeoffs follow, so a reader sees what the system must do before reading how it does it.

One one-way door. The chain file format:

{
  "chainId": 713715,
  "chainName": "arctic-1",
  "genesisHash": "",
  "genesisS3URI": "s3://…",
  "contracts": [ { "name": "storagerw", "address": "0x…", "codeHash": "0x…" } ]
}

Once a committed chain file exists, changing its shape is a migration. Approved 2026-08-22, reopened once on review to make contracts a named list.

Only chainId and genesisHash are matched on. chainName and genesisS3URI exist for a human reading a failure. codeHash is Keccak-256 because the EVM defines an account's code hash that way; genesisHash stays SHA-256 because the controller owns it.

Two properties worth protecting. The registry imports no sei-load package but the bindings (CDR-017), asserted by a test — a scenario receives a bound contract and never an address (CDR-021), which is what keeps later extraction a move rather than a refactor. And every failure stops the run before it sends a transaction: an EVM chain id does not identify a chain instance, so a re-genesised devnet keeps its id while its recorded addresses go stale.

Tickets PLT-1055 to PLT-1059 source every acceptance criterion from an AS or SC ID here rather than inventing one.

Transaction outcome tracking — DRAFT

specs/transaction-outcome-tracking/spec.md. 16 requirements (TOT-001 to TOT-016). Included because PLT-1058 references it, and because it explains why a stale registry entry is invisible today.

The problem. sei-load reports how many transactions it offered and how many reached a block. It does not report how many did what the workload asked. A run can report a million accepted, near-perfect inclusion, and a healthy p99 while every transaction reverted.

Two properties of the design cause that. stats.Collector counts submissions and stats.InclusionTracker counts arrivals, and nothing joins them. And Included derives from block transaction hashes, which carry no execution status — so it covers a transaction that committed and one that reverted and burned its gas.

Why it stays DRAFT. Its clarification session settled the three open decisions, and this commit records them as made rather than leaving them contradicting the section below. Two questions remain, both about the hand-off channel: its queue depth, and whether a drop voids the run. It still needs acceptance scenarios and criteria IDs before it can carry tickets.

Scope of this PR

Specs only. The .specify/ scaffolding and the speckit-* skills stay out.

Verification

vale specs/ — 0 errors, 0 warnings across 7 files. The 50 remaining suggestions are noun-cluster hits on task IDs (T024 [P]) and on the anchor list, which are identifiers rather than prose.

🤖 Generated with Claude Code

The contract registry spec is complete and ready to implement: 23
requirements CDR-001 to CDR-023, 10 acceptance scenarios AS-1.1 to
AS-3.3, and 10 success criteria SC-001 to SC-010, each carrying a
verifier command. Requirements come first; the design and its tradeoffs
follow, so a reader sees what the system must do before how it does it.

Beside them sit plan.md, data-model.md, contracts/registry-api.md,
quickstart.md, and tasks.md. Tickets PLT-1055 to PLT-1059 source every
acceptance criterion from an AS or SC ID in this spec.

The transaction outcome tracking spec stays DRAFT. Its clarification
session settled the three open decisions, so this commit records them as
made and names the alternatives they rejected. Two questions remain, both
about the hand-off channel: its queue depth, and whether a drop voids the
run. It still needs acceptance scenarios and criteria IDs before it can
carry tickets.

Verifier: vale specs/ reports 0 errors and 0 warnings across 7 files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 24, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Documentation-only; no runtime, auth, or data-path changes. Residual risk is locking the chain-file format and a few internal inconsistencies (list vs map) before implementation.

Overview
Adds two DRAFT specifications and no runtime code.

Contract registry (specs/contract-deployment-registry/) is a full Spec Kit set: requirements CDR-001–023, data model, exported registry API, plan, quickstart, and tasks T001–T029. It specifies lookup of named contracts by chain id + genesis hash, verify-before-bind via runtime codeHash, fail-closed on mismatch (no silent redeploy), and a leaf registry package that scenarios never see as addresses. The JSON chain-file shape is called out as the one-way door.

Transaction outcome tracking (specs/transaction-outcome-tracking/spec.md) is requirements-only (TOT-001–016). It requires splitting committed vs reverted via eth_getBlockReceipts, feeding the collector, and a non-blocking channel hand-off from sender to tracker. Queue depth and whether a drop voids a run stay open.

quickstart.md still shows contracts: {} and map[Role]Deployment while the signed format is a []Contract list.

Reviewed by Cursor Bugbot for commit 909fb75. Bugbot is set up for automated code reviews on this repo. Configure here.

@bdchatham

Copy link
Copy Markdown
Contributor Author

Closing this for now — not abandoning it.

The question is upstream of the content: we are not yet sure Spec Kit is the standard going forward, and committing specs/ into the repo makes it one by default. A directory on main sets a convention that every later feature either follows or explains away.

Nothing is lost. The branch brandon2/spec-contract-deployment-registry stays pushed, and both specs stay readable as published artifacts, which is where review comments have actually been landing.

PLT-1055 (#66) is unaffected. It carries its own rationale, and its commit message and PR body state what it closes.

Reopen this when we have decided whether specs live in the repo.

@bdchatham bdchatham closed this Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant