-
Notifications
You must be signed in to change notification settings - Fork 886
feat(autobahn): multi-epoch window for CommitQC/AppQC flow (CON-358) #3736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
wen-coding
wants to merge
84
commits into
main
Choose a base branch
from
wen/autobahn_epoch_trio
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
84 commits
Select commit
Hold shift + click to select a range
e9ec936
feat(autobahn): multi-epoch Prev|Current window for CommitQC/AppQC (C…
wen-coding c12aa05
fix(autobahn): clarify restart seed when execution leads tip into N+1…
wen-coding 9dfa24c
docs(autobahn): note >1-epoch tip lead hard-fails on restart (CON-358)
wen-coding e6bfb4c
refactor(autobahn): rename waitForAppQCEpoch to waitPruneLeash (CON-358)
wen-coding 66604d6
fix(autobahn): count LaneVotes with live duo after epoch advance (CON…
wen-coding b11b749
fix(autobahn): migrate leftover tests from DataWAL to BlockDB (CON-358)
wen-coding b1ac945
refactor(autobahn): seed restart epochs from half-open CommitQC RoadR…
wen-coding b648fb7
fix(autobahn): seed epoch 1 on empty BlockDB restart (CON-358)
wen-coding 1d8bfd6
fix(autobahn): resolve AppProposal epoch by road in giga test (CON-358)
wen-coding 55a41d4
refactor(autobahn): require non-nil Current via NewEpochDuo (CON-358)
wen-coding 24057ae
fix(autobahn): enforce contiguous Prev|Current in NewEpochDuo (CON-358)
wen-coding cab435e
docs(autobahn): trim EpochDuo comments to contracts and invariants (C…
wen-coding 5db53ed
fix(autobahn): wait tip order before PushQC EpochForRoad (CON-358)
wen-coding 7badc00
fix(autobahn): no-op PushQC before-window on already-applied QC (CON-…
wen-coding 864cc31
docs(autobahn): explain epoch-0 seal prune-leash exemption (CON-358)
wen-coding 4279909
refactor(autobahn): seed restart epochs from CommitQC span only (CON-…
wen-coding 89898b9
fix(autobahn): always placeholder-seed windowLast+2 on restart (CON-358)
wen-coding a17db0a
fix(autobahn): hard-fail DuoAt when non-genesis Prev is missing (CON-…
wen-coding 6b42802
refactor(autobahn): remove unused EnsureExecTipcut (CON-358)
wen-coding e441048
refactor(autobahn): DuoAt in newInner and RoadRange.IsLastRoad (CON-358)
wen-coding d335b4c
fix(autobahn): admit-duo verify snapshot and WaitForDuo gap wake (CON…
wen-coding 5b23ec0
docs(autobahn): clarify Current-only lane vote credits (CON-358)
wen-coding 990ef87
perf(autobahn): avoid QC re-fetch on execute for AdvanceIfNeeded (CON…
wen-coding b24cd86
fix(autobahn): pass real view EpochDuo into persisted validate (CON-358)
wen-coding 912edba
refactor(autobahn): make blockVotes.reweight void (CON-358)
wen-coding c4209e1
refactor(autobahn): drop unused Epoch return from fullCommitQC (CON-358)
wen-coding 5f27858
refactor(autobahn): drop highestEpoch; SetupInitialDuo returns error …
wen-coding cfaed53
fix(autobahn): restart tip check uses avail ≥ data (CON-358)
wen-coding 4d97d68
test(autobahn): make GenRegistry duo-only and rewrite epoch fixtures …
wen-coding 5d49986
refactor(autobahn): use Option for optional nextDuo; drop internal he…
wen-coding 0ec0724
refactor(autobahn): drop unused latest; fold thin twin tests (CON-358)
wen-coding bf0ef23
refactor(autobahn): trim EpochDuo docs and inline thin helpers (CON-358)
wen-coding 489b3f0
refactor(autobahn): drop unreachable EpochForRoad after-window path (…
wen-coding ee9b912
fix(autobahn): bind AppQC to epoch and reject Prev Current-era global…
wen-coding 0b66271
fix(autobahn): tipcut AppQC matches main; harden admit and tip checks…
wen-coding 0695c33
fix(autobahn): drop avail≥data restart tip hard-fail (CON-358)
wen-coding 38f9cb5
fix(autobahn): allow tipcut AppQC Current-1 lag; require road < view …
wen-coding 858cc94
fix(autobahn): TestCommitQC AppQC uses prior tipcut road (CON-358)
wen-coding 93ebd40
fix(autobahn): prune-leash epoch 0 seal; harden tip restart paths (CO…
wen-coding 1ad962f
fix(blocksim): stamp tipcut AppQC with prior road (CON-358)
wen-coding 3e07f64
fix(autobahn): align future-AppQC fallback with sibling guards (CON-358)
wen-coding 59dd31a
docs(autobahn): clarify QC admit-then-verify; Debug stale drops (CON-…
wen-coding e9a8667
Filter tipcut AppQC to the propose epoch duo window.
wen-coding 9dfd7d8
Enforce EpochDuo Prev iff Current>0 and tighten AppQC epoch checks.
wen-coding 3f63fcc
Drop redundant road≥view AppQC clear in buildProposal.
wen-coding b6901f4
Inline avail seal leashes; drop duplicate WaitForDuo.
wen-coding 814e954
Align PushAppVote with admit-then-verify parking.
wen-coding 9f26556
Keep one LaneQC per blockVotes; drop zero-weight on reweight.
wen-coding 50b19f0
Park PushVote until Current accepts the signer.
wen-coding eb0e700
Address pompon0 avail API/structure nits.
wen-coding a1ecb40
Avoid uint64 wrap in AppQC Current-1 epoch checks.
wen-coding e55cc61
Fix seidroid blockers and AppQC lint.
wen-coding 112ef30
Remove FirstBlock/FirstTimestamp from Epoch.
wen-coding aebafda
Fix NewEpoch call sites in sei-db after Epoch floor removal.
wen-coding e291028
Wait for in-window AppQC before tipcut propose; reject stale fallback.
wen-coding c1c6afe
Park PushVote until Current accepts the signer.
wen-coding ffa0484
Index competing headers in byHash after LaneQC for reconstruction.
wen-coding e4786d1
Deduplicate AppQC window, seal, and road-wait helpers.
wen-coding 97b80e5
Narrow tipcut AppQC wait API; keep in-window comments.
wen-coding b3512c9
Share waitRoadOrDropStale for Push* admit soft-drops.
wen-coding bf0b1d3
Move road admit classification onto EpochDuo.
wen-coding 13b615d
Name Current vs Duo admit paths; seal AppQC on Current only.
wen-coding bf3c445
Share insertCommitQCAtTip for tipcut seal+insert under lock.
wen-coding 8c9299d
Address review nits on EpochDuo admit logging and App window checks.
wen-coding 3508272
Restore per-hash LaneQC without caching qc on the vote set.
wen-coding d4ab639
Restore nextBlockToPersist comment explaining persist cursor semantics.
wen-coding ad560e6
Restore trimmed main comments on errors, admit capacity, and PushBlock.
wen-coding 0febb30
Rename waitCurrentRoad/waitDuoRoad to waitForEpoch/waitForEpochDuo.
wen-coding a9922d9
Move avail epoch seal out of Push into a Run advance loop.
wen-coding 0e9caf9
Align tipcut AppQC with interlocking: optional attach, seal leashes o…
wen-coding 30f14d1
Fix flaky data client-server test isolation
wen-coding 6bec193
Drop lane votes invalidated by epoch advance
wen-coding bdb2fd3
Clarify AppQC filtering comments
wen-coding 18f657f
Harden epoch restart and persistence snapshots
wen-coding 8f3cf44
Tighten Autobahn test and error diagnostics
wen-coding 0c5dcb1
Adapt epoch recovery to unified BlockDB iterator
wen-coding 2f75f9c
Harden AppProposal and availability epoch handling
wen-coding 9a770b3
Split availability state by responsibility
wen-coding bbe37e1
Make optional AppProposal verification panic-safe
wen-coding 1c3af75
Adapt recovery tests to epoch-aware registry
wen-coding 3194e5c
Clarify availability state ownership
wen-coding a13b120
Simplify single-field progress wrappers
wen-coding 7600dca
Merge branch 'main' into wen/autobahn_epoch_trio
wen-coding 7213d04
Restore rpc import after main merge
wen-coding File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package types | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" | ||
| "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/require" | ||
| ) | ||
|
|
||
| func TestAppQCVerifyChecksEpochAndRoad(t *testing.T) { | ||
| rng := utils.TestRng() | ||
| committee, keys := GenCommittee(rng, 4) | ||
| ep := NewEpoch(1, RoadRange{First: 100, Next: 200}, committee) | ||
|
|
||
| ok := makeAppQCFor(keys, 0, 150, GenAppHash(rng), 1) | ||
| require.NoError(t, ok.Verify(ep)) | ||
|
|
||
| wrongEpoch := makeAppQCFor(keys, 0, 150, GenAppHash(rng), 0) | ||
| require.Error(t, wrongEpoch.Verify(ep)) | ||
|
|
||
| wrongRoad := makeAppQCFor(keys, 0, 50, GenAppHash(rng), 1) | ||
| require.Error(t, wrongRoad.Verify(ep)) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,51 +1,48 @@ | ||
| package types | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" | ||
| ) | ||
|
|
||
| // EpochIndex is the epoch number. | ||
| type EpochIndex uint64 | ||
|
|
||
| // RoadRange is an inclusive range of RoadIndex values [First, Last]. | ||
| // RoadRange is a half-open range of RoadIndex values [First, Next). | ||
| // Matches GlobalRange / LaneRange: Next is exclusive (Next == lastInclusive+1). | ||
| type RoadRange struct { | ||
| First RoadIndex | ||
| Last RoadIndex | ||
| Next RoadIndex | ||
| } | ||
|
|
||
| // OpenRoadRange returns a RoadRange covering all road indices from 0. | ||
| // Use in tests and genesis epochs where no upper bound is known yet. | ||
| func OpenRoadRange() RoadRange { return RoadRange{First: 0, Last: utils.Max[RoadIndex]()} } | ||
| // OpenRoadRange returns [0, Max) for tests/genesis when no upper bound is known yet. | ||
| func OpenRoadRange() RoadRange { return RoadRange{First: 0, Next: utils.Max[RoadIndex]()} } | ||
|
|
||
| func (r RoadRange) Has(idx RoadIndex) bool { return idx >= r.First && idx < r.Next } | ||
|
|
||
| // Has reports whether idx falls within this range (inclusive on both ends). | ||
| func (r RoadRange) Has(idx RoadIndex) bool { return idx >= r.First && idx <= r.Last } | ||
| // IsLastRoad is true when idx+1 == Next (same shape as GlobalRange.IsLastBlock). | ||
| func (r RoadRange) IsLastRoad(idx RoadIndex) bool { return idx+1 == r.Next } | ||
|
|
||
| // Epoch holds the complete context for a single epoch. | ||
| // Retrieved from the local Registry; never transmitted on the wire. | ||
| // | ||
| // First global block / timestamp floors are not on Epoch: they come from the | ||
| // last CommitQC of the prior epoch (or genesis GenDoc via Registry), and the | ||
| // registry does not store CommitQCs. | ||
| type Epoch struct { | ||
| utils.ReadOnly | ||
| epochIndex EpochIndex | ||
| roads RoadRange | ||
| firstTimestamp time.Time | ||
| committee *Committee | ||
| firstBlock GlobalBlockNumber | ||
| epochIndex EpochIndex | ||
| roads RoadRange | ||
| committee *Committee | ||
| } | ||
|
|
||
| // NewEpoch constructs an Epoch. | ||
| func NewEpoch(index EpochIndex, roads RoadRange, firstTimestamp time.Time, committee *Committee, firstBlock GlobalBlockNumber) *Epoch { | ||
| func NewEpoch(index EpochIndex, roads RoadRange, committee *Committee) *Epoch { | ||
| return &Epoch{ | ||
| epochIndex: index, | ||
| roads: roads, | ||
| firstTimestamp: firstTimestamp, | ||
| committee: committee, | ||
| firstBlock: firstBlock, | ||
| epochIndex: index, | ||
| roads: roads, | ||
| committee: committee, | ||
| } | ||
| } | ||
|
|
||
| func (e *Epoch) EpochIndex() EpochIndex { return e.epochIndex } | ||
| func (e *Epoch) RoadRange() RoadRange { return e.roads } | ||
| func (e *Epoch) FirstTimestamp() time.Time { return e.firstTimestamp } | ||
| func (e *Epoch) Committee() *Committee { return e.committee } | ||
| func (e *Epoch) FirstBlock() GlobalBlockNumber { return e.firstBlock } | ||
| func (e *Epoch) EpochIndex() EpochIndex { return e.epochIndex } | ||
| func (e *Epoch) RoadRange() RoadRange { return e.roads } | ||
| func (e *Epoch) Committee() *Committee { return e.committee } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| package types | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
|
|
||
| "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" | ||
| ) | ||
|
|
||
| // EpochDuo is a Prev|Current epoch window. Current is always set; Prev is | ||
| // absent iff Current is epoch 0, otherwise contiguous with Current (index | ||
| // Current-1 and Prev.Next == Current.First). | ||
| type EpochDuo struct { | ||
| Prev utils.Option[*Epoch] | ||
| Current *Epoch | ||
| } | ||
|
|
||
| // NewEpochDuo builds a Prev|Current window. Panics unless | ||
| // prev≠None ⇔ current.EpochIndex()>0, and when Prev is present it must be | ||
| // contiguous with Current. | ||
| func NewEpochDuo(current *Epoch, prev utils.Option[*Epoch]) EpochDuo { | ||
| cur := current.EpochIndex() | ||
| p, hasPrev := prev.Get() | ||
| if hasPrev != (cur > 0) { | ||
| panic(fmt.Sprintf("NewEpochDuo: Prev present=%v but Current epoch %d (want Prev iff Current>0)", | ||
| hasPrev, cur)) | ||
| } | ||
| if hasPrev { | ||
| if p.EpochIndex()+1 != cur { | ||
| panic(fmt.Sprintf("NewEpochDuo: Prev epoch %d not contiguous with Current %d", | ||
| p.EpochIndex(), cur)) | ||
| } | ||
| if got, want := p.RoadRange().Next, current.RoadRange().First; got != want { | ||
| panic(fmt.Sprintf("NewEpochDuo: Prev roads end at %d, Current starts at %d", got, want)) | ||
| } | ||
| } | ||
| return EpochDuo{Prev: prev, Current: current} | ||
| } | ||
|
|
||
| var ErrRoadBeforeWindow = errors.New("road before epoch duo window") | ||
| var ErrRoadAfterWindow = errors.New("road after epoch duo window") | ||
|
|
||
| // RoadStatus classifies a road relative to a Prev|Current window for admit waits. | ||
| type RoadStatus int | ||
|
|
||
| const ( | ||
| RoadReady RoadStatus = iota // in the admitted window | ||
| RoadStale // behind the window (soft-drop / ErrPruned) | ||
| RoadFuture // ahead of the window (backpressure wait) | ||
| ) | ||
|
|
||
| // RoadStatusCurrent classifies roadIdx against Current only (CommitQC tip). | ||
| func (w EpochDuo) RoadStatusCurrent(roadIdx RoadIndex) RoadStatus { | ||
| if w.Current.RoadRange().Has(roadIdx) { | ||
| return RoadReady | ||
| } | ||
| if roadIdx < w.Current.RoadRange().First { | ||
| return RoadStale | ||
| } | ||
| return RoadFuture | ||
| } | ||
|
|
||
| // RoadStatusDuo classifies roadIdx against Prev|Current (AppVote/AppQC). | ||
| func (w EpochDuo) RoadStatusDuo(roadIdx RoadIndex) RoadStatus { | ||
| _, err := w.EpochForRoad(roadIdx) | ||
| if err == nil { | ||
| return RoadReady | ||
| } | ||
| if errors.Is(err, ErrRoadBeforeWindow) { | ||
| return RoadStale | ||
| } | ||
| return RoadFuture | ||
| } | ||
|
|
||
| // EpochForRoad returns the epoch containing roadIdx. | ||
| // Window is [Prev.First or Current.First, Current.Next). Outside → | ||
| // ErrRoadBeforeWindow / ErrRoadAfterWindow. Under contiguous Prev|Current there | ||
| // is no gap, so a miss after the after-window check is always before-window. | ||
| func (w EpochDuo) EpochForRoad(roadIdx RoadIndex) (*Epoch, error) { | ||
| if roadIdx >= w.Current.RoadRange().Next { | ||
| return nil, fmt.Errorf("road %d after window %v: %w", roadIdx, w, ErrRoadAfterWindow) | ||
| } | ||
| if w.Current.RoadRange().Has(roadIdx) { | ||
| return w.Current, nil | ||
| } | ||
| if prev, ok := w.Prev.Get(); ok && prev.RoadRange().Has(roadIdx) { | ||
| return prev, nil | ||
| } | ||
| return nil, fmt.Errorf("road %d before window %v: %w", roadIdx, w, ErrRoadBeforeWindow) | ||
| } | ||
|
|
||
| func (w EpochDuo) String() string { | ||
| s := "epochs [" | ||
| sep := "" | ||
| // Prev then Current so a window {4,5} prints as "epochs [4, 5]". | ||
| for _, oep := range [2]utils.Option[*Epoch]{w.Prev, utils.Some(w.Current)} { | ||
| if ep, ok := oep.Get(); ok { | ||
| s += fmt.Sprintf("%s%d", sep, ep.EpochIndex()) | ||
| sep = ", " | ||
| } | ||
| } | ||
| return s + "]" | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.