Skip to content

evmonly: revert the background receipt/state pipeline (#4264, #4266) - #4268

Merged
bdchatham merged 2 commits into
giga-1from
devin/1789922027-revert-receipt-pipeline
Sep 20, 2026
Merged

bdchatham merged 2 commits into
giga-1from
devin/1789922027-revert-receipt-pipeline

Conversation

@bdchatham

Copy link
Copy Markdown
Contributor

Describe your changes and provide context

Reverts #4264 (receipts and state encoding persisted behind the block, Commit waits for receipts) and #4266 (receipt write started right after execution) on top of #4265 and #4267, which stay.

On testnet-2 the pair never beat the pre-#4264 image: #4264 warmed at ~86.8k tx/s vs ~96k before it (Commit's receipt wait, app_commit 0.16 s/s, cost more loop time than the encodes it removed), and #4266 moved that wait off app_commit but vault_commit rose from ~0.05 to ~0.18 s/s and stayed there for the whole run (~89k tx/s). The likely reason is the FlatKV WAL fsync now coinciding with the HashVault fsync for the same block, but rather than tune a pipeline that has not paid for itself, this returns the executor to the path that measured 96k.

State after this PR (giga/evmonly/giga_store.go, executePreparedBlockWithStore):

execute → [await previous commit if encoding reads the store]
        → encode state changesets (+ block encoder)
        → encode receipts → SetReceipts            (on the loop, skipped without a receipt store)
        → await previous commit → start state commit in the background

Not a pure git revert because #4265 landed on top of both commits: the 12 files #4264/#4266 touched were restored from 9a731d5 and the #4265/#4267 hunks re-applied by 3-way merge; the only hand-resolved hunk is the nil-store guard around the receipt write above.

Testing performed to validate your change

  • scripts/ramtest.sh ./giga/evmonly/... ./sei-db/ledger_db/receipt/... -race — green.
  • go test -race -count=2 ./internal/evmonlyapp/ (sei-tendermint) — green; go vet on evmonlyapp, node.
  • golangci-lint run ./giga/evmonly/... 0 issues; make fmtcheck clean.
  • Rollout: image bump only, no config change; receipts stay enabled on the 40 validators.

Link to Devin session: https://app.devin.ai/sessions/ff612badcded4aa5914ea408dbb41888
Open in Devin Desktop: https://app.devin.ai/desktop/session/ff612badcded4aa5914ea408dbb41888?variant=devin
Requested by: @bdchatham

Reverts 5c37395 and 187cd78 on top of #4265 and #4267. Receipts are encoded and
written on the block loop before the state commit again, and Commit no longer waits
for them. The #4265 nil receipt store is kept: the executor skips the receipt write.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@cursor

cursor Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes ordering and durability visibility for block execution, state commits, and receipts on validators—intentional revert to a previously measured-good path, but RPC can briefly miss the newest block's receipts after Commit.

Overview
Rolls back the pipelined persistence from #4264/#4266 after testnet showed lower throughput and heavier commit/fsync overlap than the pre-pipeline path.

Executor block tail is back on the block loop: optionally await the prior state commit when encoding reads the store, encode state (+ block) changesets while the execution snapshot is still open, encode and SetReceipts synchronously (skipped when no receipt store), then await the prior commit if needed and start only the state commit in the background. Background receipt writes, AwaitReceipts, and the extra pipeline/receipt phase timers are removed; encodingReadsTheStore again gates whether encoding can overlap the in-flight commit.

Failure and visibility semantics change: encode/receipt/state errors return without handing results to ResultSink; a receipt failure no longer permanently blocks later blocks. evmOnlyApplication.Commit no longer waits for receipts, so latest height can briefly lead receipt reads when the litt store queues writes asynchronously. WaitForPendingWrites and per-write landed tracking are dropped from the async receipt store.

Docs and tests are updated to match (including removing Commit-must-have-receipts assertions and most pipeline ordering tests).

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

@github-actions

github-actions Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedSep 20, 2026, 4:48 PM

@codecov

codecov Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 86.41%. Comparing base (7e3ca24) to head (e1e27fe).
⚠️ Report is 48 commits behind head on giga-1.

Files with missing lines Patch % Lines
giga/evmonly/giga_store.go 96.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           giga-1    #4268       +/-   ##
===========================================
+ Coverage   65.55%   86.41%   +20.86%     
===========================================
  Files        2081       35     -2046     
  Lines      157460     4793   -152667     
===========================================
- Hits       103222     4142    -99080     
+ Misses      54097      650    -53447     
+ Partials      141        1      -140     
Flag Coverage Δ
sei-chain ?
sei-chain-pr 86.41% <96.66%> (?)
sei-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
giga/evmonly/executor.go 91.25% <100.00%> (+0.04%) ⬆️
sei-db/ledger_db/receipt/litt_receipt_store.go 88.19% <100.00%> (+4.73%) ⬆️
sei-db/ledger_db/receipt/receipt_store.go 74.87% <ø> (+1.77%) ⬆️
sei-tendermint/internal/evmonlyapp/app.go 87.00% <ø> (+5.23%) ⬆️
giga/evmonly/giga_store.go 92.00% <96.00%> (-1.11%) ⬇️

... and 2056 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A faithful, well-scoped revert of the #4264/#4266 receipt/state pipeline back to the measured-faster synchronous path, keeping #4265's optional receipt store and #4267's timers; the code, tests, docs and metric removals are all consistent with no dangling references. The only notes are about the durability/read-your-writes window that the removed waits used to close.

Findings: 0 blocking | 3 non-blocking | 1 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • [suggestion] evmOnlyApplication.Commit no longer waits for the block's receipts, so RPC advances latest to height N while N's receipts may still be in the receipt store's async queue. giga/evmonly/rpc/tx.go serves eth_getTransactionReceipt from that store, so a client that reads the head and immediately asks for a receipt in it can get not-found for a short window. This is the pre-#4264 behaviour and polling clients tolerate it, but the guarantee that TestEVMOnlyApplicationCommitReturnsWithTheBlocksReceiptsReadable pinned is now gone with nothing recording the weaker contract — worth a line in giga/evmonly/README.md or the Commit godoc so the next reader does not re-derive it.
  • 1 suggestion(s)/nit(s) flagged inline on specific lines.
  • 1 non-blocking pre-existing issue(s) listed below under pre-existing issues.

Pre-existing issues

  • [suggestion] recoveryTarget in sei-db/bootstrap/recovery.go:181 deliberately ignores a receipt head of 0 so newly-enabled receipts do not drag the target down. That also means a node whose receipt store is genuinely empty while the block store and state WAL hold blocks recovers to min(block, state) and never regenerates receipts for those blocks — the one case where a receipt/state head divergence is silently accepted rather than replayed.

Comment thread giga/evmonly/giga_store.go
…en the state head advances

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@bdchatham
bdchatham enabled auto-merge September 20, 2026 16:48
@bdchatham
bdchatham added this pull request to the merge queue Sep 20, 2026
Merged via the queue into giga-1 with commit b4bb4e5 Sep 20, 2026
68 checks passed
@bdchatham
bdchatham deleted the devin/1789922027-revert-receipt-pipeline branch September 20, 2026 17:08
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