Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2ed09bf
feat(data): wire BlockDB into State — persist QCs and blocks across r…
wen-coding Jul 6, 2026
49cb596
fix: close data.State on router shutdown; guard rootify against empty…
wen-coding Jul 6, 2026
4887f74
docs: update --persistent-state-dir flag help — persistence is now re…
wen-coding Jul 6, 2026
5f57fe5
refactor: PersistentStateDir required string in consensus/avail; fix …
wen-coding Jul 6, 2026
6009978
fix: missed Option[string] call site in producer test; fix stale comm…
wen-coding Jul 6, 2026
a828ae3
fix: add PersistentStateDir to giga test helpers
wen-coding Jul 6, 2026
ebe6cb8
docs: document PruneBefore async-GC behavior; validate empty persiste…
wen-coding Jul 6, 2026
13bc4ec
test(data): add PruneBefore-without-GC recovery test; validate empty …
wen-coding Jul 6, 2026
1331181
chore(persist): remove dead noopPersister and stale None-mode comments
wen-coding Jul 6, 2026
2fa77ed
chore(persist): rename stale TestNoOp* tests; fix misplaced comment i…
wen-coding Jul 6, 2026
b5a7d61
chore: remove remaining stale no-op persister references from comments
wen-coding Jul 6, 2026
6e66336
fix: close BlockDB in router tests; simplify loadPersistedState retur…
wen-coding Jul 7, 2026
0cf1aea
chore: remove last stale no-op-mode references from test comments
wen-coding Jul 7, 2026
3ecc27c
fix: propagate data.Close() error on router shutdown
wen-coding Jul 7, 2026
db32fcb
fix(data): trim orphaned QC entries when first block is beyond QC start
wen-coding Jul 7, 2026
8b332dc
revert: restore Option[*loadedAvailState] return from loadPersistedState
wen-coding Jul 7, 2026
345d268
refactor(persist): drop Option wrapper from commitQCState.iw
wen-coding Jul 7, 2026
29d6ba4
refactor(consensus): drop Option wrapper from State.persister
wen-coding Jul 7, 2026
355838b
doc(avail): fix loadPersistedState comment — always returns Some
wen-coding Jul 7, 2026
53ea2b7
refactor(data): move BlockDB open/close into GigaRouter.Run
wen-coding Jul 7, 2026
416743a
refactor(data): change blockDB field to utils.Option[BlockDB]; restor…
wen-coding Jul 8, 2026
288c776
fix(lint): check blockDB.Close() error return in GigaRouter.Run
wen-coding Jul 8, 2026
044c7ee
fix(config): restore PersistentStateDir as Option[string]; allow empt…
wen-coding Jul 8, 2026
2ea7b94
fix(tests): wrap PersistentStateDir literals in utils.Some after Opti…
wen-coding Jul 8, 2026
c4ec2e9
fix(node): mkdir persistent state dir before constructing GigaRouter
wen-coding Jul 8, 2026
5e22de8
fix(data): always call Init; seed persisted cursors from FirstBlock i…
wen-coding Jul 8, 2026
264804b
refactor(avail): use Init(nil) in inner_test; revert state.go to main
wen-coding Jul 8, 2026
aab405d
refactor(consensus): revert state.go/inner.go to main; use Init(nil) …
wen-coding Jul 8, 2026
d3e8f77
refactor(producer): use Init(nil) in mempool_test; drop BlockDB depen…
wen-coding Jul 8, 2026
979da63
refactor(giga): use Init(nil) in data_test; drop BlockDB and persistence
wen-coding Jul 8, 2026
6ab21de
refactor(producer): drop unused t from newTestEnv
wen-coding Jul 8, 2026
408dd23
refactor(giga): drop unused t from newTestNode and newTestEnv
wen-coding Jul 8, 2026
8d7552d
revert(avail): restore state.go to origin/main (MaxLaneRangeInProposal)
wen-coding Jul 8, 2026
b70e97e
refactor(data): replace blockDBPersistedQC/Block fields with local va…
wen-coding Jul 8, 2026
b3c6242
fix(data): remove leftover blockDBPersistedQC/Block assignments in lo…
wen-coding Jul 8, 2026
290a76e
fix(giga): update avail_test.go call site for newTestEnv signature ch…
wen-coding Jul 8, 2026
c46ee9d
fix(giga): update consensus_test.go call site for newTestEnv signatur…
wen-coding Jul 8, 2026
87d6bfb
fix(data): capture persist cursors in Init to prevent PushQC startup …
wen-coding Jul 8, 2026
9311628
fix(giga): log loud warning when HashVault disabled due to missing Pe…
wen-coding Jul 8, 2026
e12bf9c
test(data,consensus): rename newTestLittDB→newTestBlockDB, use real B…
wen-coding Jul 8, 2026
6f0795f
fix(data): clarify loadFromBlockDB comment re lock usage
wen-coding Jul 8, 2026
46e6a31
refactor(data): replace iterErr pattern with IIFE, drop Close() error…
wen-coding Jul 8, 2026
3aead2c
fix(giga): update stale buildDataState comment to reflect Init+Run split
wen-coding Jul 8, 2026
53951f5
refactor(data): move BlockDB open+replay into NewState constructor
wen-coding Jul 8, 2026
df8ddcf
refactor(p2p): pass hashVault as param to executeBlock, drop struct f…
wen-coding Jul 9, 2026
344eb21
refactor(data): IIFE+defer for iterators, drop bool flags in loadFrom…
wen-coding Jul 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions sei-tendermint/internal/autobahn/avail/inner_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package avail

import (
pb "github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/pb"
"testing"

pb "github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/pb"

"github.com/sei-protocol/sei-chain/sei-tendermint/autobahn/types"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/consensus/persist"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/data"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/stretchr/testify/require"
)

func newTestDataState(t testing.TB, cfg *data.Config) *data.State {
s, err := data.NewState(cfg, utils.None[types.BlockDB]())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

didn't you say that you will use the real BlockDB in tests though?

if err != nil {
t.Fatalf("data.NewState: %v", err)
}
return s
}

func TestPruneMismatchedIndices(t *testing.T) {
rng := utils.TestRng()
committee, keys := types.GenCommittee(rng, 4)
Expand All @@ -35,17 +44,17 @@ func TestPruneMismatchedIndices(t *testing.T) {
qc1 := makeCommitQC(utils.Some(qc0))

t.Logf("test State.PushAppQC")
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
state, err := NewState(keys[0], ds, utils.None[string]())
ds := newTestDataState(t, &data.Config{Committee: committee})
state, err := NewState(keys[0], ds, utils.Some(t.TempDir()))
require.NoError(t, err)
require.Error(t, state.PushAppQC(makeAppQC(qc0, qc0), qc1), "bad range, bad index should fail")
require.Error(t, state.PushAppQC(makeAppQC(qc1, qc0), qc1), "good range, bad index should fail")
require.Error(t, state.PushAppQC(makeAppQC(qc0, qc1), qc1), "bad range, good index should fail")
require.NoError(t, state.PushAppQC(makeAppQC(qc1, qc1), qc1), "good range, good index should succeed")

t.Logf("test inner.prune")
ds = utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
state, err = NewState(keys[0], ds, utils.None[string]())
ds = newTestDataState(t, &data.Config{Committee: committee})
state, err = NewState(keys[0], ds, utils.Some(t.TempDir()))
require.NoError(t, err)
for inner := range state.inner.Lock() {
_, err := inner.prune(committee, makeAppQC(qc1, qc0), qc1)
Expand Down
5 changes: 2 additions & 3 deletions sei-tendermint/internal/autobahn/avail/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,8 @@ func (s *State) PushCommitQC(ctx context.Context, qc *types.CommitQC) error {
}
inner.commitQCs.pushBack(qc)
metrics.ObserveCommitQC(committee, qc)
// The persist goroutine publishes latestCommitQC after writing to disk
// (or immediately for no-op persisters), so consensus won't advance
// until the CommitQC is durable.
// The persist goroutine publishes latestCommitQC after writing to disk,
// so consensus won't advance until the CommitQC is durable.
ctrl.Updated()
return nil
}
Expand Down
44 changes: 18 additions & 26 deletions sei-tendermint/internal/autobahn/avail/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ func testState(t *testing.T, stateDir utils.Option[string]) {
committee, keys := types.GenCommittee(rng, 3)

if err := scope.Run(ctx, func(ctx context.Context, s scope.Scope) error {
ds := utils.OrPanic1(data.NewState(&data.Config{
Committee: committee,
}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})
s.SpawnBgNamed("data.State.Run()", func() error {
return utils.IgnoreCancel(ds.Run(ctx))
})
Expand Down Expand Up @@ -236,7 +234,7 @@ func TestStateRestartFromPersisted(t *testing.T) {
var wantNextBlocks map[types.LaneID]types.BlockNumber

require.NoError(t, scope.Run(t.Context(), func(ctx context.Context, s scope.Scope) error {
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})
s.SpawnBgNamed("data.Run", func() error {
return utils.IgnoreCancel(ds.Run(ctx))
})
Expand Down Expand Up @@ -311,7 +309,7 @@ func TestStateRestartFromPersisted(t *testing.T) {
}))

// Phase 2: Restart from the same directory.
ds2 := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds2 := newTestDataState(t, &data.Config{Committee: committee})
state2, err := NewState(keys[0], ds2, utils.Some(dir))
require.NoError(t, err)

Expand All @@ -335,10 +333,8 @@ func TestStateMismatchedQCs(t *testing.T) {
committee, keys := types.GenCommittee(rng, 4)
initialBlock := committee.FirstBlock()

ds := utils.OrPanic1(data.NewState(&data.Config{
Committee: committee,
}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
state, err := NewState(keys[0], ds, utils.None[string]())
ds := newTestDataState(t, &data.Config{Committee: committee})
state, err := NewState(keys[0], ds, utils.Some(t.TempDir()))
require.NoError(t, err)

// Helper to create a CommitQC for a specific index
Expand Down Expand Up @@ -393,10 +389,8 @@ func TestPushBlockRejectsBadParentHash(t *testing.T) {
rng := utils.TestRng()
committee, keys := types.GenCommittee(rng, 3)

ds := utils.OrPanic1(data.NewState(&data.Config{
Committee: committee,
}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
state := utils.OrPanic1(NewState(keys[0], ds, utils.None[string]()))
ds := newTestDataState(t, &data.Config{Committee: committee})
state := utils.OrPanic1(NewState(keys[0], ds, utils.Some(t.TempDir())))

// Produce a valid first block on our lane.
_, err := state.ProduceLocalBlock(state.NextBlock(keys[0].Public()), types.GenPayload(rng))
Expand All @@ -418,10 +412,8 @@ func TestPushBlockRejectsWrongSigner(t *testing.T) {
rng := utils.TestRng()
committee, keys := types.GenCommittee(rng, 3)

ds := utils.OrPanic1(data.NewState(&data.Config{
Committee: committee,
}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
state := utils.OrPanic1(NewState(keys[0], ds, utils.None[string]()))
ds := newTestDataState(t, &data.Config{Committee: committee})
state := utils.OrPanic1(NewState(keys[0], ds, utils.Some(t.TempDir())))

// Create a block on keys[0]'s lane but sign it with keys[1].
lane := keys[0].Public()
Expand All @@ -439,7 +431,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("empty dir loads fresh state", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

state, err := NewState(keys[0], ds, utils.Some(dir))
require.NoError(t, err)
Expand All @@ -452,7 +444,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("loads persisted AppQC", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

roadIdx := types.RoadIndex(7)
globalNum := types.GlobalBlockNumber(50)
Expand Down Expand Up @@ -493,7 +485,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("loads persisted blocks", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})
lane := keys[0].Public()

// Persist blocks using BlockPersister.
Expand All @@ -517,7 +509,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("loads persisted AppQC and blocks together", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})
lane := keys[0].Public()

roadIdx := types.RoadIndex(2)
Expand Down Expand Up @@ -570,7 +562,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("loads persisted commitQCs", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

// Persist CommitQCs to disk.
cp, _, err := persist.NewCommitQCPersister(utils.Some(dir))
Expand All @@ -595,7 +587,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("loads persisted commitQCs with AppQC", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

// Persist AppQC at road index 1.
roadIdx := types.RoadIndex(1)
Expand Down Expand Up @@ -668,7 +660,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("anchor past all persisted commitQCs truncates WAL", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

// Build a chain of 10 CommitQCs (indices 0-9).
qcs := make([]*types.CommitQC, 10)
Expand Down Expand Up @@ -711,7 +703,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("anchor past all persisted blocks truncates lane WAL", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})
lane := keys[0].Public()

// Persist commitQCs 0-9 and blocks 0-2 for one lane.
Expand Down Expand Up @@ -759,7 +751,7 @@ func TestNewStateWithPersistence(t *testing.T) {

t.Run("corrupt AppQC data returns error", func(t *testing.T) {
dir := t.TempDir()
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
ds := newTestDataState(t, &data.Config{Committee: committee})

// Create a throwaway persister to discover the A/B filenames,
// then corrupt them so NewState fails on load.
Expand Down
37 changes: 34 additions & 3 deletions sei-tendermint/internal/autobahn/consensus/inner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package consensus
import (
"context"
"errors"
"fmt"
"path/filepath"
"testing"
"time"

"github.com/sei-protocol/sei-chain/sei-db/ledger_db/block/littblock"
"github.com/sei-protocol/sei-chain/sei-tendermint/autobahn/types"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/consensus/persist"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/data"
Expand All @@ -15,6 +18,28 @@ import (
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/require"
)

func newTestBlockDB(t *testing.T, dir string) types.BlockDB {
t.Helper()
cfg, err := littblock.DefaultConfig(dir)
if err != nil {
t.Fatalf("littblock.DefaultConfig: %v", err)
}
db, err := littblock.NewBlockDB(cfg)
if err != nil {
t.Fatalf("littblock.NewBlockDB: %v", err)
}
t.Cleanup(func() { _ = db.Close() })
return db
}
Comment thread
wen-coding marked this conversation as resolved.

func newTestDataState(committee *types.Committee) *data.State {
s, err := data.NewState(&data.Config{Committee: committee}, utils.None[types.BlockDB]())
if err != nil {
panic(fmt.Sprintf("data.NewState: %v", err))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

seem kind of inconsistent that you use panic in some helpers and t.Fatalf in others (t.Fatalf won't work in non-main goroutine).

}
return s
}

// seedPersistedInner is a test helper that persists a persistedInner using the public API.
func seedPersistedInner(dir string, state *persistedInner) {
p, _, err := persist.NewPersister[*pb.PersistedInner](utils.Some(dir), innerFile)
Expand Down Expand Up @@ -923,15 +948,21 @@ func (f failPersister[T]) Persist(T) error { return f.err }
func TestRunOutputsPersistErrorPropagates(t *testing.T) {
// Verify that a persist error in runOutputs propagates
// and terminates the consensus component (instead of panicking).
dir := t.TempDir()
rng := utils.TestRng()
committee, keys := types.GenCommittee(rng, 4)
ds := utils.OrPanic1(data.NewState(&data.Config{Committee: committee}, utils.OrPanic1(data.NewDataWAL(utils.None[string](), committee))))
db := newTestBlockDB(t, filepath.Join(dir, "blockdb"))
ds, err := data.NewState(&data.Config{Committee: committee}, utils.Some[types.BlockDB](db))
if err != nil {
t.Fatalf("data.NewState: %v", err)
}

wantErr := errors.New("disk on fire")
pers := utils.Some[persist.Persister[*pb.PersistedInner]](failPersister[*pb.PersistedInner]{err: wantErr})
cs, err := newState(&Config{
Key: keys[0],
ViewTimeout: func(types.View) time.Duration { return time.Hour },
Key: keys[0],
ViewTimeout: func(types.View) time.Duration { return time.Hour },
PersistentStateDir: utils.Some(dir),
}, ds, pers, utils.None[*pb.PersistedInner]())
require.NoError(t, err)

Expand Down
Loading