Skip to content

fix: autobahn InitChain height and GetValidators panic (CON-249)#3243

Open
wen-coding wants to merge 4 commits intomainfrom
wen/fix-autobahn-initchain-height
Open

fix: autobahn InitChain height and GetValidators panic (CON-249)#3243
wen-coding wants to merge 4 commits intomainfrom
wen/fix-autobahn-initchain-height

Conversation

@wen-coding
Copy link
Copy Markdown
Contributor

@wen-coding wen-coding commented Apr 14, 2026

Summary

Fixes two bugs in autobahn's runExecute InitChain flow:

  1. Height mismatch: After InitChain, runExecute called Commit which advanced the app to InitialHeight. The next FinalizeBlock at InitialHeight then failed with "invalid height: N; expected: N+1". Fix: remove the Commit after InitChain — the SDK expects the first FinalizeBlock at InitialHeight using the deliverState set up by InitChain.

  2. GetValidators panic: Without Commit, the committed store is empty (staking params not persisted). GetValidators reading from committed store panics with "UnmarshalJSON cannot decode empty bytes". Fix: read committed store first (normal path), fall back to DeliverContext only when committed store returns no validators (autobahn-only genesis path).

Why the testApp Committed field was removed

The original testApp had a Committed bool field set by both InitChain and Commit, with FinalizeBlock checking if !state.Committed { error }. This conflated two states — "post-InitChain" and "post-Commit" — into one flag.

For autobahn's flow (InitChain → FinalizeBlock → Commit), InitChain set Committed=true. After the first FinalizeBlock set it to false, Commit correctly set it back to true. But if InitChain set Committed=true and then Commit was called (CometBFT flow), it would fail with "double commit" — not because there was actually a double commit, but because the flag was already true.

The real app guards against actual double commit structurally: Commit() sets deliverState = nil, so a second Commit() panics on nil pointer dereference. The testApp is too simple to replicate that mechanism and doesn't need to — it only tracks blocks and txs for test assertions.

Changes

  • sei-tendermint/internal/p2p/giga_router.go: Remove Commit after InitChain; set next = InitialHeight (not +1)
  • app/app.go: GetValidators() reads committed store first, falls back to DeliverContext only when empty (autobahn genesis path)
  • sei-cosmos/baseapp/test_helpers.go: Add DeliverContext() accessor for reading uncommitted state
  • sei-tendermint/internal/p2p/giga_router_test.go: Remove Committed field from testApp; add TestInitChainCommitThenFinalize test

Test plan

  • TestInitChainCommitThenFinalize passes — verifies InitChain → FinalizeBlock → Commit flow
  • TestGigaRouter_FinalizeBlocks — pre-broken on main (times out, caused by Made autobahn producer use TxMempool #3224), not affected by this change
  • Docker integration test with AUTOBAHN=true cluster

🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 14, 2026

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

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedApr 15, 2026, 5:34 AM

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

❌ Patch coverage is 0% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.26%. Comparing base (9795d18) to head (5982d5f).

Files with missing lines Patch % Lines
sei-cosmos/baseapp/test_helpers.go 0.00% 4 Missing ⚠️
app/app.go 0.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3243      +/-   ##
==========================================
- Coverage   59.26%   59.26%   -0.01%     
==========================================
  Files        2070     2070              
  Lines      169788   169791       +3     
==========================================
  Hits       100631   100631              
- Misses      60358    60362       +4     
+ Partials     8799     8798       -1     
Flag Coverage Δ
sei-chain-pr 60.97% <0.00%> (?)
sei-db 70.41% <ø> (ø)

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

Files with missing lines Coverage Δ
sei-tendermint/internal/p2p/giga_router.go 68.75% <ø> (+1.67%) ⬆️
app/app.go 68.90% <0.00%> (-0.14%) ⬇️
sei-cosmos/baseapp/test_helpers.go 66.66% <0.00%> (-10.26%) ⬇️
🚀 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.

@pompon0
Copy link
Copy Markdown
Contributor

pompon0 commented Apr 14, 2026

this pr seems to be a noop, no?

@wen-coding
Copy link
Copy Markdown
Contributor Author

this pr seems to be a noop, no?

Sorry, still working on it, Claude pushed before it's ready. I'll ping you when it's ready for review.

@wen-coding wen-coding force-pushed the wen/fix-autobahn-initchain-height branch 2 times, most recently from d272836 to 85e690c Compare April 14, 2026 18:14
@wen-coding wen-coding changed the title fix: add Commit after InitChain in autobahn runExecute (CON-249) fix: autobahn InitChain height mismatch and testApp height tracking (CON-249) Apr 14, 2026
Without Commit after InitChain, the staking params are not persisted
to the committed store. When executeBlock calls app.GetValidators(),
it reads from the committed store and panics with
"UnmarshalJSON cannot decode empty bytes".

Also removes the testApp Committed check in FinalizeBlock since the
extra Commit after InitChain changes the Committed state flow.

Note: TestGigaRouter_FinalizeBlocks is pre-broken on main (times out
at 120s) — this is not caused by this change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wen-coding wen-coding force-pushed the wen/fix-autobahn-initchain-height branch from 85e690c to 8be74ab Compare April 14, 2026 19:05
@wen-coding wen-coding changed the title fix: autobahn InitChain height mismatch and testApp height tracking (CON-249) fix: autobahn InitChain height and GetValidators panic (CON-249) Apr 14, 2026
wen-coding and others added 3 commits April 14, 2026 20:43
GetValidators now reads from the committed store first and only falls
back to DeliverContext when the committed store is empty (autobahn-only
path after InitChain before first Commit). This avoids changing the
code path for CometBFT consensus.

Remove the Committed field from testApp. The original boolean conflated
two states: "post-InitChain" and "post-Commit". It blocked autobahn's
valid flow (InitChain → FinalizeBlock without intermediate Commit)
because InitChain set Committed=true, causing the next Commit after
FinalizeBlock to fail with "double commit". The real app guards against
actual double commit structurally (deliverState becomes nil after Commit,
so a second Commit panics on nil pointer) — not via a boolean flag.
The testApp is too simple to replicate that mechanism and doesn't need to.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The CometBFT handshaker (consensus/replay.go) always calls InitChain
when appHeight==0. Having runExecute also call InitChain caused a
double-init that corrupted state. Now runExecute skips InitChain and
relies on the handshaker having already set up deliverState.

GetValidators: at height 0, read from DeliverContext first since the
committed store is empty (staking params panic on MaxValidators).
After the first Commit, the committed store has the params and the
normal path is used.

Test: simulate the handshaker by calling InitChain before router.Run().

Verified with docker AUTOBAHN=true cluster: all 4 nodes produce blocks,
bank transfer works, fault tolerance (1-down continues, 2-down halts).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Match the real SDK behavior: InitChain without Commit leaves
LastBlockHeight=0. Previously the testApp returned InitialHeight-1
after InitChain with 0 blocks, causing runExecute to enter the
restart path and call PushAppHash with a block number below
the data layer's starting point.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants