Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
f7d5ac1
feat(autobahn): introduce epoch.Registry as single source of truth fo…
wen-coding Jun 24, 2026
29bbe85
feat(autobahn): bake firstBlock into Proposal so GlobalRange() is abs…
wen-coding Jun 24, 2026
44a64af
fix(autobahn): reproposal must use epoch firstBlock, not GlobalRange(…
wen-coding Jun 24, 2026
4a229bf
nit: inline GlobalFirst alloc, fix error message, randomize firstBloc…
wen-coding Jun 25, 2026
b7c404d
refactor(epoch): introduce Epoch type with index/start/end/timestamp,…
wen-coding Jun 25, 2026
c48ac8c
fix: replace remaining LatestCommittee() call sites with LatestEpoch(…
wen-coding Jun 25, 2026
16b592b
refactor(types): add EpochTimestamp to ViewSpec; drop genesisTimestam…
wen-coding Jun 25, 2026
007cbba
fix: update blocksim NewProposal call site for new signature
wen-coding Jun 25, 2026
4525d76
fix: gofmt proposal_test.go alignment
wen-coding Jun 25, 2026
b131531
refactor(types): introduce EpochInfo; remove epoch fields from ViewSpec
wen-coding Jun 25, 2026
5e333d0
fix: update blocksim and proto format for EpochInfo refactor
wen-coding Jun 25, 2026
5018935
chore(proto): regenerate wireguard for Proposal fields 7+8
wen-coding Jun 25, 2026
70550fd
chore(proto): fix cascading MaxSize in autobahn.wireguard.go
wen-coding Jun 25, 2026
93e1d0c
refactor(types): fold flat epoch fields into epochInfo EpochInfo on P…
wen-coding Jun 25, 2026
5224d3b
chore(proto): regenerate autobahn.pb.go with buf v1.58.0
wen-coding Jun 25, 2026
7384fa1
refactor(types): move Epoch into types pkg; fold into ViewSpec and Pr…
wen-coding Jun 25, 2026
d6c48c2
refactor(types): move Epoch struct to its own file epoch.go
wen-coding Jun 25, 2026
b3880ab
refactor(epoch): make Epoch.FirstBlock the first block of each epoch
wen-coding Jun 25, 2026
00a7b13
docs(types): remove redundant wire comment from ViewSpec
wen-coding Jun 25, 2026
293f53b
refactor(types): drop Start/End from wireEpoch in newProposal
wen-coding Jun 25, 2026
854d64f
refactor(types): remove wireEpoch copy in newProposal
wen-coding Jun 25, 2026
66c6b13
refactor(types): rename vs → viewSpec in NewProposal and Verify
wen-coding Jun 25, 2026
7ea9e48
refactor(types): rename viewSpec → vs in FullProposal.Verify
wen-coding Jun 25, 2026
a849604
simplify: use DecodeReq for epoch_timestamp in ProposalConv.Decode
wen-coding Jun 25, 2026
9e2dabb
revert: simplify block vote accumulation back to single-committee
wen-coding Jun 25, 2026
582e42d
fix(avail): compare CommitQCs by proto encoding in tests
wen-coding Jun 25, 2026
6aadef5
simplify: drop unused firstBlock param from inner.prune
wen-coding Jun 25, 2026
43c8b8b
simplify: drop redundant firstBlock param from newInner
wen-coding Jun 25, 2026
395d4b1
simplify: hoist ep := data.Registry().LatestEpoch() in NewState
wen-coding Jun 25, 2026
c3f163c
feat(consensus): cache ep in inner, populate ViewSpec.Epoch from it
wen-coding Jun 25, 2026
3a7ab7f
fix(persist): replace go-cmp CommitQC comparison with proto.Equal
wen-coding Jun 26, 2026
3d4ca8b
fix(giga): compare FullCommitQC via proto.Equal in TestDataClientServer
wen-coding Jun 26, 2026
139c114
fix(types): add Equal methods to CommitQC, FullCommitQC, Proposal for…
wen-coding Jun 26, 2026
4773c02
fix(utils): export all unexported fields in TestDiff to avoid panic
wen-coding Jun 26, 2026
b0bb2e8
revert(types): remove Equal methods from CommitQC, FullCommitQC, Prop…
wen-coding Jun 26, 2026
412ea86
refactor(consensus): use cached Epoch.Committee instead of Registry.C…
wen-coding Jun 26, 2026
250cf6e
refactor(epoch): ReadOnly Epoch type, RoadRange, utils.RWMutex, drop …
wen-coding Jun 26, 2026
68d56dd
refactor(proposal): store epochIndex/firstBlock as wire fields, not *…
wen-coding Jun 26, 2026
afb324c
refactor(types): Proposal.Verify(ep), ProposalAt, GenEpochWithCommitt…
wen-coding Jun 26, 2026
68d4631
fix(types): restore MaxLaneRangeInProposal check in FullProposal.Verify
wen-coding Jun 26, 2026
b8700e8
chore: remove committed test binary and ignore *.test files
wen-coding Jun 26, 2026
5828931
refactor(proto): rename global_first → first_block in Proposal
wen-coding Jun 26, 2026
56d67e2
doc(types): clarify why Proposal.Verify skips lane-range checks
wen-coding Jun 26, 2026
66934ec
doc(epoch): explain epoch window concept in VerifyInWindow
wen-coding Jun 26, 2026
35dcdeb
refactor(epoch): replace EpochFor(roadIndex) with EpochForProposal(p)
wen-coding Jun 26, 2026
d399716
regen(wireguard): update StreamAppQCsResp MaxSize after first_block r…
wen-coding Jun 26, 2026
d886dcd
nit(data): drop unused registry param from globalBlockAt
wen-coding Jun 26, 2026
7c8bf25
feat(autobahn): add epoch_index to AppProposal, LaneQC, TimeoutVote
wen-coding Jun 26, 2026
6e91151
refactor(epoch): drop EpochFor, fix nil QC guard in PushBlock
wen-coding Jun 26, 2026
e2361ca
doc(autobahn): mark LaneQC.epochIndex as advisory, verified in FullPr…
wen-coding Jun 26, 2026
b98c4b0
fix(avail): cross-check AppProposal epoch_index against CommitQC in P…
wen-coding Jun 26, 2026
ed2a4a6
fix(epoch): remove dead makeRegistry helper from registry_test.go
wen-coding Jun 26, 2026
b8a2664
fix(autobahn): tighten epoch_index validation in proposal and QC decode
wen-coding Jun 26, 2026
538de3f
fix(autobahn): reject TimeoutVote on decode when epoch_index is missing
wen-coding Jun 26, 2026
d460c75
fix(autobahn): strengthen epoch_index cross-validation across verify …
wen-coding Jun 26, 2026
176ad8a
fix(proto): remove advisory comment from autobahn.proto to keep pb.go…
wen-coding Jun 26, 2026
32c6c22
fix(data): skip redundant block.Verify when authoritative epoch alrea…
wen-coding Jun 26, 2026
9bb19e1
fix(data): reject block if authoritative epoch not in pre-lock verifi…
wen-coding Jun 26, 2026
3316902
fix(blocksim): use OpenRoadRange() instead of zero RoadRange in build…
wen-coding Jun 26, 2026
e057aa8
fix(testonly): delete dead isReadOnly, document unconditional cmp exp…
wen-coding Jun 26, 2026
9423daa
fix(epoch): trim VerifyInWindow doc to match implementation; note har…
wen-coding Jun 26, 2026
f3ebc6f
fix(epoch): note missing committed-road-watermark check in AddEpoch
wen-coding Jun 26, 2026
ae92ce1
revert(testonly): restore isReadOnly exporter to match main
wen-coding Jun 26, 2026
a4f736c
fix(proposal): add structural lane-range checks to Proposal.Verify
wen-coding Jun 27, 2026
d0e59a6
fix(testonly): derive epochIndex from Epoch in TestCommitQC instead o…
wen-coding Jun 27, 2026
aef198e
test(epoch): move NewCommittee test to types pkg, add Registry coverage
wen-coding Jun 27, 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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ sei-db/state_db/bench/cryptosim/data/**
sei-db/state_db/bench/cryptosim/bin/
sei-db/state_db/bench/cryptosim/logs/
sei-db/ledger_db/block/blocksim/bin/
sei-db/db_engine/litt/bin/
sei-db/db_engine/litt/bin/*.test
71 changes: 23 additions & 48 deletions sei-db/ledger_db/block/block_db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func testPruneStraddleRetainsQC(t *testing.T, build builder) {
require.NoError(t, err)
got, ok := opt.Get()
require.True(t, ok, "straddling QC must be retained")
require.Equal(t, straddled.first, got.QC().GlobalRange(committee).First)
require.Equal(t, straddled.first, got.QC().GlobalRange().First)
}

// testPruneIdempotentMonotonic asserts PruneBefore is idempotent and the
Expand Down Expand Up @@ -485,7 +485,7 @@ func testReverseIteratorOrdering(t *testing.T, build builder) {
}
qc, err := qcIt.QC()
require.NoError(t, err)
first := qc.QC().GlobalRange(committee).First
first := qc.QC().GlobalRange().First
if qcCount == 0 {
require.Equal(t, lastFirst, first, "reverse QCs must surface the last QC first")
}
Expand Down Expand Up @@ -525,8 +525,8 @@ func testResumeAfterRestart(t *testing.T, build builder) {

prevQC, ok := recoverLastQC(t, db)
require.True(t, ok)
require.Equal(t, last.first, prevQC.GlobalRange(committee).First, "recovered QC must be the last persisted QC")
require.Equal(t, last.next, prevQC.GlobalRange(committee).Next)
require.Equal(t, last.first, prevQC.GlobalRange().First, "recovered QC must be the last persisted QC")
require.Equal(t, last.next, prevQC.GlobalRange().Next)

// The recovered QC's upper bound is exactly where the continuation begins;
// writing the next contiguous batch must be accepted.
Expand Down Expand Up @@ -712,7 +712,7 @@ func TestMemblockPruneRemovesBelowWatermark(t *testing.T) {
}
fqc, err := qcIt.QC()
require.NoError(t, err)
require.GreaterOrEqual(t, fqc.QC().GlobalRange(committee).First, watermark,
require.GreaterOrEqual(t, fqc.QC().GlobalRange().First, watermark,
"QC iterator must not surface pruned QCs")
}
require.NoError(t, qcIt.Close())
Expand Down Expand Up @@ -842,13 +842,13 @@ func assertBlocksReadable(t *testing.T, db types.BlockDB, batches []batch) {

func assertQCsReadable(t *testing.T, db types.BlockDB, committee *types.Committee, batches []batch) {
for _, b := range batches {
r := b.qc.QC().GlobalRange(committee)
r := b.qc.QC().GlobalRange()
for n := r.First; n < r.Next; n++ {
opt, err := db.ReadQCByBlockNumber(n)
require.NoError(t, err)
got, ok := opt.Get()
require.True(t, ok, "QC covering %d should exist", n)
gr := got.QC().GlobalRange(committee)
gr := got.QC().GlobalRange()
require.Equal(t, r.First, gr.First)
require.Equal(t, r.Next, gr.Next)
require.Len(t, got.Headers(), len(b.qc.Headers()), "QC must round-trip its full header set")
Expand Down Expand Up @@ -902,7 +902,7 @@ func assertIterators(t *testing.T, db types.BlockDB, committee *types.Committee,
}
qc, err := qcIt.QC()
require.NoError(t, err)
first := qc.QC().GlobalRange(committee).First
first := qc.QC().GlobalRange().First
if haveQC {
require.Greater(t, first, prevFirst, "QCs must iterate ascending by First")
}
Expand Down Expand Up @@ -960,7 +960,7 @@ func buildCommittee() (*types.Committee, []types.SecretKey) {
keys[i] = types.GenSecretKey(rng)
replicas[i] = keys[i].Public()
}
committee := utils.OrPanic1(types.NewRoundRobinElection(replicas, 0, genesisTime))
committee := utils.OrPanic1(types.NewRoundRobinElection(replicas))
return committee, keys
}

Expand All @@ -972,7 +972,7 @@ func generateBatches(committee *types.Committee, keys []types.SecretKey) []batch
batches := make([]batch, 0, numBatches)
for range numBatches {
fqc, blocks := buildFullCommitQC(rng, committee, keys, prev)
r := fqc.QC().GlobalRange(committee)
r := fqc.QC().GlobalRange()
batches = append(batches, batch{first: r.First, next: r.Next, blocks: blocks, qc: fqc})
prev = utils.Some(fqc.QC())
}
Expand All @@ -991,68 +991,43 @@ func buildFullCommitQC(
parent := bs[len(bs)-1]
return types.NewBlock(producer, parent.Header().Next(), parent.Header().Hash(), types.GenPayload(rng))
}
return types.NewBlock(
producer,
types.LaneRangeOpt(prev, producer).Next(),
types.GenBlockHeaderHash(rng),
types.GenPayload(rng),
)
return types.NewBlock(producer, types.LaneRangeOpt(prev, producer).Next(), types.GenBlockHeaderHash(rng), types.GenPayload(rng))
}
for range blocksPerQC {
producer := committee.Lanes().At(rng.Intn(committee.Lanes().Len()))
blocks[producer] = append(blocks[producer], makeBlock(producer))
}

laneQCs := map[types.LaneID]*types.LaneQC{}
var headers []*types.BlockHeader
var blockList []*types.Block
for lane := range committee.Lanes().All() {
if bs := blocks[lane]; len(bs) > 0 {
laneQCs[lane] = testLaneQC(keys, bs[len(bs)-1].Header())
laneQCs[lane] = testLaneQC(keys, bs[len(bs)-1].Header(), 0)
for _, b := range bs {
headers = append(headers, b.Header())
blockList = append(blockList, b)
}
}
}

viewSpec := types.ViewSpec{CommitQC: prev}
leader := committee.Leader(viewSpec.View())
var leaderKey types.SecretKey
for _, k := range keys {
if k.Public() == leader {
leaderKey = k
break
}
}
proposal := utils.OrPanic1(types.NewProposal(
leaderKey,
committee,
viewSpec,
genesisTime,
laneQCs,
func() utils.Option[*types.AppQC] {
if n := types.GlobalRangeOpt(prev, committee).Next; n > 0 {
p := types.NewAppProposal(n-1, viewSpec.View().Index, types.GenAppHash(rng))
return utils.Some(testAppQC(keys, p))
}
return utils.None[*types.AppQC]()
}(),
))
votes := make([]*types.Signed[*types.CommitVote], 0, len(keys))
for _, k := range keys {
votes = append(votes, types.Sign(k, types.NewCommitVote(proposal.Proposal().Msg())))
var appQC utils.Option[*types.AppQC]
if cqc, ok := prev.Get(); ok {
vs := types.ViewSpec{CommitQC: prev}
p := types.NewAppProposal(cqc.GlobalRange().Next-1, vs.View().Index, types.GenAppHash(rng), cqc.Proposal().EpochIndex())
appQC = utils.Some(testAppQC(keys, p))
} else {
appQC = utils.None[*types.AppQC]()
}
return types.NewFullCommitQC(types.NewCommitQC(votes), headers), blockList
cqc := types.BuildCommitQC(committee, keys, prev, 0, genesisTime, laneQCs, appQC)
return types.NewFullCommitQC(cqc, headers), blockList
}

func testLaneQC(keys []types.SecretKey, header *types.BlockHeader) *types.LaneQC {
func testLaneQC(keys []types.SecretKey, header *types.BlockHeader, epochIndex uint64) *types.LaneQC {
vote := types.NewLaneVote(header)
votes := make([]*types.Signed[*types.LaneVote], 0, len(keys))
for _, k := range keys {
votes = append(votes, types.Sign(k, vote))
}
return types.NewLaneQC(votes)
return types.NewLaneQC(votes, epochIndex)
}

func testAppQC(keys []types.SecretKey, proposal *types.AppProposal) *types.AppQC {
Expand Down
16 changes: 8 additions & 8 deletions sei-db/ledger_db/block/blocksim/block_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (g *BlockGenerator) mainLoop() {

func (g *BlockGenerator) buildBatch() *generatedBatch {
fqc, blocks := g.buildFullCommitQC()
r := fqc.QC().GlobalRange(g.committee)
r := fqc.QC().GlobalRange()
g.prev = utils.Some(fqc.QC())
return &generatedBatch{first: r.First, next: r.Next, blocks: blocks, qc: fqc}
}
Expand Down Expand Up @@ -124,15 +124,15 @@ func (g *BlockGenerator) buildFullCommitQC() (*types.FullCommitQC, []*types.Bloc
var blockList []*types.Block
for lane := range committee.Lanes().All() {
if bs := blocks[lane]; len(bs) > 0 {
laneQCs[lane] = testLaneQC(keys, bs[len(bs)-1].Header())
laneQCs[lane] = testLaneQC(keys, bs[len(bs)-1].Header(), 0)
for _, b := range bs {
headers = append(headers, b.Header())
blockList = append(blockList, b)
}
}
}

viewSpec := types.ViewSpec{CommitQC: prev}
viewSpec := types.ViewSpec{CommitQC: prev, Epoch: types.NewEpoch(0, types.OpenRoadRange(), genesisTime, committee, 0)}
leader := committee.Leader(viewSpec.View())
var leaderKey types.SecretKey
for _, k := range keys {
Expand All @@ -143,13 +143,13 @@ func (g *BlockGenerator) buildFullCommitQC() (*types.FullCommitQC, []*types.Bloc
}
proposal := utils.OrPanic1(types.NewProposal(
leaderKey,
committee,
viewSpec,
time.Now(),
laneQCs,
func() utils.Option[*types.AppQC] {
if n := types.GlobalRangeOpt(prev, committee).Next; n > 0 {
p := types.NewAppProposal(n-1, viewSpec.View().Index, types.GenAppHash(rng))
if cqc, ok := prev.Get(); ok {
n := cqc.GlobalRange().Next
Comment thread
cursor[bot] marked this conversation as resolved.
p := types.NewAppProposal(n-1, viewSpec.View().Index, types.GenAppHash(rng), viewSpec.Epoch.EpochIndex())
return utils.Some(testAppQC(keys, p))
}
return utils.None[*types.AppQC]()
Expand All @@ -162,13 +162,13 @@ func (g *BlockGenerator) buildFullCommitQC() (*types.FullCommitQC, []*types.Bloc
return types.NewFullCommitQC(types.NewCommitQC(votes), headers), blockList
}

func testLaneQC(keys []types.SecretKey, header *types.BlockHeader) *types.LaneQC {
func testLaneQC(keys []types.SecretKey, header *types.BlockHeader, epochIndex uint64) *types.LaneQC {
vote := types.NewLaneVote(header)
votes := make([]*types.Signed[*types.LaneVote], 0, len(keys))
for _, k := range keys {
votes = append(votes, types.Sign(k, vote))
}
return types.NewLaneQC(votes)
return types.NewLaneQC(votes, epochIndex)
}

func testAppQC(keys []types.SecretKey, proposal *types.AppProposal) *types.AppQC {
Expand Down
4 changes: 2 additions & 2 deletions sei-db/ledger_db/block/blocksim/blocksim.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func NewBlockSim(
// last QC's range — the next batch then appends contiguously. Block bytes
// are irrelevant here (this is a DB stress test), so the backfill writes
// freshly generated blocks under the already-persisted QC.
qcRange := prevQC.GlobalRange(committee)
qcRange := prevQC.GlobalRange()
lastQCNext := uint64(qcRange.Next)
firstMissing := uint64(qcRange.First)
if h, ok := highestOpt.Get(); ok {
Expand Down Expand Up @@ -263,7 +263,7 @@ func buildCommittee(rng tmutils.Rng, size int) (*types.Committee, []types.Secret
keys[i] = types.GenSecretKey(rng)
replicas[i] = keys[i].Public()
}
committee, err := types.NewRoundRobinElection(replicas, 0, genesisTime)
committee, err := types.NewRoundRobinElection(replicas)
if err != nil {
return nil, nil, fmt.Errorf("failed to build committee: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions sei-db/ledger_db/block/blocksim/resume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ func TestRecoverResumeState(t *testing.T) {

prevQC, ok := prev.Get()
require.True(t, ok, "recovered prev QC must be present")
require.Equal(t, last.first, prevQC.GlobalRange(committee).First, "recovered QC must be the last persisted QC")
require.Equal(t, last.next, prevQC.GlobalRange(committee).Next)
require.Equal(t, last.first, prevQC.GlobalRange().First, "recovered QC must be the last persisted QC")
require.Equal(t, last.next, prevQC.GlobalRange().Next)

// Empty-store sanity: a fresh dir recovers nothing.
empty, err := openBlockDB(&BlocksimConfig{Backend: "litt", DataDir: t.TempDir(), LittRetentionSeconds: 1})
Expand Down
18 changes: 15 additions & 3 deletions sei-tendermint/autobahn/types/app_proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ type AppProposal struct {
globalNumber GlobalBlockNumber
roadIndex RoadIndex
appHash AppHash
epochIndex uint64
}

// NewAppProposal creates a new AppProposal.
func NewAppProposal(globalNumber GlobalBlockNumber, roadIndex RoadIndex, appHash AppHash) *AppProposal {
return &AppProposal{globalNumber: globalNumber, roadIndex: roadIndex, appHash: appHash}
func NewAppProposal(globalNumber GlobalBlockNumber, roadIndex RoadIndex, appHash AppHash, epochIndex uint64) *AppProposal {
return &AppProposal{globalNumber: globalNumber, roadIndex: roadIndex, appHash: appHash, epochIndex: epochIndex}
}

// GlobalNumber .
Expand All @@ -34,6 +35,9 @@ func (m *AppProposal) RoadIndex() RoadIndex { return m.roadIndex }
// AppHash .
func (m *AppProposal) AppHash() AppHash { return m.appHash }

// EpochIndex returns the epoch this proposal belongs to.
func (m *AppProposal) EpochIndex() uint64 { return m.epochIndex }

// Next is the next global block number to compute AppHash for.
func (m *AppProposal) Next() RoadIndex {
return m.RoadIndex() + 1
Expand All @@ -44,9 +48,12 @@ func (m *AppProposal) Verify(c *Committee, qc *CommitQC) error {
if got, want := m.RoadIndex(), qc.Proposal().Index(); got != want {
return fmt.Errorf("roadIndex() = %v, want %v", got, want)
}
if got, want := m.GlobalNumber(), qc.GlobalRange(c); got < want.First || got >= want.Next {
if got, want := m.GlobalNumber(), qc.GlobalRange(); got < want.First || got >= want.Next {
Comment thread
cursor[bot] marked this conversation as resolved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[suggestion] AppProposal.Verify checks roadIndex and global-number range against the CommitQC but does not bind the epoch. In PushAppVote the committee is selected from the vote's self-declared EpochIndex(), so once more than one epoch exists a vote signed under the wrong (e.g. outgoing) epoch could still be accepted and counted toward an AppQC for a CommitQC from a different epoch whenever road/global numbers line up — and that AppQC then drives pruning. Not exploitable today (registry only ever holds epoch 0), but per this PR's stated intent of surfacing such bugs at the call site, add a check here (or in PushAppVote) that m.EpochIndex() == qc.Proposal().EpochIndex(). (Codex finding #1.)

return fmt.Errorf("globalNumber() = %v, want in range [%v,%v)", got, want.First, want.Next)
}
if got, want := m.EpochIndex(), qc.Proposal().EpochIndex(); got != want {
return fmt.Errorf("epoch_index = %d, want %d", got, want)
}
return nil
}

Expand All @@ -57,6 +64,7 @@ var AppProposalConv = protoutils.Conv[*AppProposal, *pb.AppProposal]{
GlobalNumber: utils.Alloc(uint64(m.globalNumber)),
RoadIndex: utils.Alloc(uint64(m.roadIndex)),
AppHash: m.appHash,
EpochIndex: utils.Alloc(m.epochIndex),
}
},
Decode: func(m *pb.AppProposal) (*AppProposal, error) {
Expand All @@ -66,10 +74,14 @@ var AppProposalConv = protoutils.Conv[*AppProposal, *pb.AppProposal]{
if m.RoadIndex == nil {
return nil, fmt.Errorf("RoadIndex: missing")
}
if m.EpochIndex == nil {
return nil, fmt.Errorf("EpochIndex: missing")
}
return &AppProposal{
globalNumber: GlobalBlockNumber(*m.GlobalNumber),
roadIndex: RoadIndex(*m.RoadIndex),
appHash: AppHash(m.AppHash),
epochIndex: *m.EpochIndex,
}, nil
},
}
30 changes: 19 additions & 11 deletions sei-tendermint/autobahn/types/commit_qc.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,21 @@ func (m *CommitQC) LaneRange(lane LaneID) *LaneRange {
}

// GlobalRange returns the finalized global block range.
func (m *CommitQC) GlobalRange(c *Committee) GlobalRange {
return m.Proposal().GlobalRange(c)
func (m *CommitQC) GlobalRange() GlobalRange {
return m.Proposal().GlobalRange()
}

// Verify verifies the CommitQC against the committee.
// Currently it doesn't require the previous CommitQC.
func (m *CommitQC) Verify(c *Committee) error {
// Verify verifies the CommitQC against the epoch.
func (m *CommitQC) Verify(ep *Epoch) error {
p := m.Proposal()
if err := p.Verify(ep); err != nil {
return err
}
roads := ep.Roads()
if p.Index() < roads.First || p.Index() > roads.Last {
return fmt.Errorf("road_index %v not in epoch roads [%v, %v]", p.Index(), roads.First, roads.Last)
}
c := ep.Committee()
Comment thread
cursor[bot] marked this conversation as resolved.
return m.vote.verifyQC(c, c.CommitQuorum(), m.sigs)
}

Expand All @@ -60,7 +68,7 @@ type FullCommitQC struct {

// NewFullCommitQC constructs a new FullCommitQC.
func NewFullCommitQC(qc *CommitQC, headers []*BlockHeader) *FullCommitQC {
if got, want := len(headers), int(qc.Proposal().globalRangeWithoutOffset.Len()); got != want { //nolint:gosec // total lane range len is a small bounded value representing block count in a QC
if got, want := len(headers), int(qc.GlobalRange().Len()); got != want { //nolint:gosec // total lane range len is a small bounded value representing block count in a QC
panic(fmt.Sprintf("headers length %d != finalized blocks %d", got, want))
}
return &FullCommitQC{qc: qc, headers: headers}
Expand All @@ -77,16 +85,16 @@ func (m *FullCommitQC) Index() RoadIndex {
return m.qc.Index()
}

// Verify verifies the FullCommitQC against the committee.
func (m *FullCommitQC) Verify(c *Committee) error {
if err := m.qc.Verify(c); err != nil {
// Verify verifies the FullCommitQC against the epoch.
func (m *FullCommitQC) Verify(ep *Epoch) error {
if err := m.qc.Verify(ep); err != nil {
return fmt.Errorf("qC: %w", err)
}
n := uint64(0)
if want, got := int(m.qc.GlobalRange(c).Len()), len(m.headers); want != got { //nolint:gosec // global range len is a small bounded value representing block count in a QC
if want, got := int(m.qc.GlobalRange().Len()), len(m.headers); want != got { //nolint:gosec // global range len is a small bounded value representing block count in a QC
return fmt.Errorf("len(headers) = %d, want %d", got, want)
}
for lane := range c.Lanes().All() {
for lane := range ep.Committee().Lanes().All() {
lr := m.qc.LaneRange(lane)
if lr.Len() == 0 {
continue
Expand Down
Loading
Loading