Integrate Autobahn with in-memory EVM-only executor - #4028
Conversation
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4028 +/- ##
==========================================
- Coverage 61.33% 60.15% -1.19%
==========================================
Files 2157 2066 -91
Lines 188986 178071 -10915
==========================================
- Hits 115918 107112 -8806
+ Misses 62235 60992 -1243
+ Partials 10833 9967 -866
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
PR SummaryMedium Risk Overview Ships the Reviewed by Cursor Bugbot for commit b97fa5b. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
A well-scoped, test-only Autobahn EVM-only in-memory executor: the app-hash derivation is deterministic (the executor's changeset is sorted before encoding), the RPC head switch to the GigaRouter is behaviour-preserving for the existing Cosmos-app path, and the docker port/env plumbing checks out. No blockers; the notes below concern failure modes of the new runtime (a tx-level execution error halts the whole cluster), an unenforced config constraint, and a few structural/robustness cleanups.
Findings: 0 blocking | 6 non-blocking | 4 posted inline
Blockers
- None at the file/PR level.
Non-blocking
- [suggestion] Layering:
evmonly_inmemory_app.golands insei-tendermint/internal/p2p, andsei-tendermint/configimports that package — so the config package now transitively depends ongiga/evmonlyand the whole go-ethereum EVM. It compiles today only because nothing undergiga/evmonlyreaches back tosei-tendermint/config; a future import there becomes a cycle. The app has no p2p concern (it is only constructed fromnode/setup.go); its own package would keep the dependency out ofconfig's import graph. - [suggestion] The block's changeset is encoded twice per block: once inside
ExecutePreparedBlock(via theWithStore(store, store.EncodeChangeSet)encoder) and again inhashEVMOnlyInMemoryResult(evmonly.EncodeMemoryStoreChangeSet(result.ChangeSet)). On the 4,000-tx blocks this harness exists to measure, that doubles changeset allocation on the hot path.result.ChangeSetis already deterministically sorted, so hashing it directly avoids the second encode. - 4 suggestion(s)/nit(s) flagged inline on specific lines.
| // EVMOnlyInMemory replaces the Cosmos application used by Autobahn with an | ||
| // ephemeral EVM-only executor. It exists only for Docker load testing and | ||
| // must not be enabled on a persistent network. | ||
| EVMOnlyInMemory bool `json:"evm_only_in_memory,omitzero"` |
There was a problem hiding this comment.
[suggestion] The doc comment says this "must not be enabled on a persistent network", but nothing enforces it: AutobahnFileConfig.Validate accepts evm_only_in_memory: true together with persistent_state_dir, and only the docker script happens to del(.persistent_state_dir). A hand-written config with both set gets persisted consensus blocks over an EVM state that resets to the funded base on every restart. Validate() is the choke point every config load passes through — rejecting the combination there makes it an invariant instead of a convention the next config author has to remember.
| return env.getHeight(env.App.Info().LastBlockHeight, heightPtr) | ||
| giga, ok := env.gigaRouter().Get() | ||
| if !ok { | ||
| panic("autobahnCheckAndGetHeight called without GigaRouter") |
There was a problem hiding this comment.
[suggestion] Both callers (Block at line 100, BlockResults at line 261) already hold the router from their own env.gigaRouter().Get() check, so this second lookup can never fail and the panic is unreachable by construction — but it is a panic on the RPC surface if that ever stops holding. Taking giga p2p.GigaRouter as a parameter removes both the redundant lookup and the panic.
| seid tendermint gen-autobahn-config $NODE_DIRS --output "$AUTOBAHN_CONFIG" | ||
| if [ "$AUTOBAHN_EVMONLY_IN_MEMORY" = "true" ]; then | ||
| AUTOBAHN_CONFIG_TMP="$AUTOBAHN_CONFIG.tmp" | ||
| jq '.evm_only_in_memory = true | del(.persistent_state_dir)' "$AUTOBAHN_CONFIG" > "$AUTOBAHN_CONFIG_TMP" |
There was a problem hiding this comment.
[suggestion] This drops the && guard the repo's other jq rewrites use (override_genesis in step2_genesis.sh:13 is jq ... > tmp && mv tmp target). The script has no set -e, so if jq fails the mv on the next line still runs and replaces autobahn.json with a truncated file, and the node fails later with an unrelated-looking config error. Chaining > "$AUTOBAHN_CONFIG_TMP" && mv ... restores the existing idiom.
| } | ||
| } | ||
|
|
||
| func evmOnlyInMemoryEnabled() bool { |
There was a problem hiding this comment.
I acknowledge that this is for integration testing, but are there facilities to auto-map env variables to the json config? I'm only seeing JSON for AutobahnFileConfig.
There was a problem hiding this comment.
There is not an automatic Autobahn JSON env mapper here, so I removed this switch from AutobahnFileConfig. It is now the test-only top-level evm-only-in-memory TOML setting beside mock-app; the Docker env variable is only the harness selector and maps into that node config.
| seid tendermint gen-autobahn-config $NODE_DIRS --output "$AUTOBAHN_CONFIG" | ||
| if [ "$AUTOBAHN_EVMONLY_IN_MEMORY" = "true" ]; then | ||
| AUTOBAHN_CONFIG_TMP="$AUTOBAHN_CONFIG.tmp" | ||
| jq '.evm_only_in_memory = true | del(.persistent_state_dir)' "$AUTOBAHN_CONFIG" > "$AUTOBAHN_CONFIG_TMP" |
There was a problem hiding this comment.
You can pass empty string to persistent_state_dir, which I think will disable persistence.
There was a problem hiding this comment.
Updated. The harness now passes --persistent-state-dir= to gen-autobahn-config, so the generator omits the persistent state directory without a follow-up jq deletion.
| return nil, nil, err | ||
| } | ||
| logger.Warn("Autobahn EVM-only in-memory execution enabled; state is ephemeral and unsafe for persistent networks") | ||
| app = p2p.NewEVMOnlyInMemoryProxy(config.AutobahnEVMOnlyInMemoryChainID, maxGas, genDoc.InitialHeight) |
There was a problem hiding this comment.
I think this only updates buildGigaRouter's local app. Maybe try to do it like MockApp, do it earlier in node.New? #3905
There was a problem hiding this comment.
Updated to the MockApp pattern. prepareApplication now replaces the app inside node.New before proxy.New, so both RPC and GigaRouter receive the same application. The EVM-only executor derives the initial height and gas limit later from InitChain.
819a564 to
83f8025
Compare
a81e71a to
0dfd46e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0dfd46e. Configure here.
359e4a7 to
d30250f
Compare
|
I mostly checked the consensus/execution API, looks good to me. |

Describe your changes and provide context
This PR builds on the EVM-only Giga store merged in #3864 and is rebased onto that merge commit.
evm-only-in-memorynode setting that replaces the Cosmos ABCI application beforeproxy.New, so Autobahn and the executor share the same application.InitChain, accept protected raw Ethereum transactions on chain ID 1337, and execute finalized blocks with a deterministic app hash.eth_sendRawTransaction. It validates Ethereum encoding, routes by Autobahn EVM shard ownership, submits through the in-process mempool, and returns the Ethereum transaction hash.--persistent-state-dir=.make autobahn-evmonly-integration-test, which submits 4,000 signed transfers through EVM JSON-RPC, asserts Tendermint RPC is unavailable, and uses internal Prometheus execution counters to wait for every validator.autobahn-e2ecluster manager withdeploy,list,forward, andteardownsubcommands for local Docker or a managed EC2 host.listobtains height from internal Prometheus metrics and does not depend on Tendermint RPC.Testing performed to validate your change
make autobahn-evmonly-integration-test(4,000 raw transfers through EVM JSON-RPC; all four validators executed through height 8; 5,010 tx/s observed locally; Tendermint RPC unavailable)autobahn-e2elocal lifecycle: deploy four nodes, list live status/Prometheus heights, forward node 2 to127.0.0.1:18545, call the EVM RPC through the tunnel, confirm Tendermint/statusresets, then teardown all containers and the networkgo test -count=1 ./cmd/autobahn-e2ego test -count=1 -run "^TestEVMOnlyRPC" ./sei-tendermint/nodego test -c -tags autobahn_integration ./integration_test/autobahngo vet ./sei-tendermint/node ./cmd/autobahn-e2ego vet -tags autobahn_integration ./integration_test/autobahn--build-tags autobahn_integration(0 issues)fmt --diffacross the repositorysh -n docker/localnode/scripts/step4_config_override.sh docker/localnode/scripts/step5_start_sei.shgit diff --check