Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- A live stream starting at a block number with no block (a missed or skipped slot) now starts at the next block instead of waiting for the merged bundle containing it.
- `hub.ForkableHub` no longer breaks when its one-block bootstrap races with the merger deleting the files of a bundle it just merged. Concretely: bootstrap retries a few times when the listing comes back with a gap or a listed file is gone by the time it is opened (both expected during that race), a failed bootstrap no longer leaves the forkable holding a bogus LIB it then can't reconcile with live blocks (the hub now only swaps in the forkable it built once bootstrap actually succeeds, falling back to a fresh one otherwise), and `cannot link block after reconnection` is only fatal once the hub has actually been ready — before that, an unlinkable block is handled like any other, already subject to `WithMaxConsecutiveUnlinkableBlocks`. Previously a consumer starting or restarting during that race could see the hub die or never become ready.
- The hub no longer walks the one-block store for a block it already has below LIB. With redundant live sources, a source re-sending a final block that the hub still keeps below LIB (the lowest one, whose parent was already pruned) triggered a store lookup and a `block not linkable after one-block lookup` warning, even though the forkable drops blocks below LIB anyway. The hub now compares against LIB instead of the lowest kept block. `Forkable.LIBNum` is added for this.
- `hub.WithMaxConsecutiveUnlinkableBlocks` now counts blocks rather than messages: an intermediate flash block — `PartialIndex != 0` without `LastPartial` — no longer advances the counter. Every partial of a block fails the same link check, so on a chain delivering four per block the hub gave up after a quarter of the blocks the limit names. A plain block and a block's final partial still count, and any linkable block still resets the count.
Expand Down
2 changes: 1 addition & 1 deletion forkable/forkable.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (p *Forkable) blocksFromNum(num uint64) ([]*bstream.PreprocessedBlock, erro
var seenBlock bool
for i := range seg {
ref := seg[i].AsRef()
if !seenBlock && ref.Num() == num {
if !seenBlock && ref.Num() >= num {
seenBlock = true
}

Expand Down
21 changes: 21 additions & 0 deletions forkable/forkable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1910,6 +1910,27 @@ func TestForkable_BlocksFromIrreversibleNum(t *testing.T) {
},
},
},
{
name: "missing block number starts at the next block",
forkdbBlocks: []*pbbstream.Block{
bstream.TestBlockWithLIBNum("00000005", "00000004", 2),
bstream.TestBlockWithLIBNum("00000008", "00000005", 4),
bstream.TestBlockWithLIBNum("00000009", "00000008", 5),
},
requestBlock: 6,
expectBlocks: []expectedBlock{
{
bstream.TestBlockWithLIBNum("00000008", "00000005", 4),
bstream.StepNew,
5,
},
{
bstream.TestBlockWithLIBNum("00000009", "00000008", 5),
bstream.StepNew,
5,
},
},
},
{
name: "no source",
forkdbBlocks: []*pbbstream.Block{
Expand Down
Loading