diff --git a/cursor.go b/cursor.go index 30b5dcc..7e8c92d 100644 --- a/cursor.go +++ b/cursor.go @@ -27,7 +27,7 @@ var EmptyCursor = &Cursor{ } func (c *Cursor) IsOnFinalBlock() bool { - return c.Block.Num() == c.LIB.Num() && c.Step.Matches(StepIrreversible) + return c.Block.Num() == c.LIB.Num() && c.Step.Matches(StepFinal) } func (c *Cursor) ToOpaque() string { @@ -191,8 +191,8 @@ func readCursorStep(part string) (StepType, error) { if out != StepNew && out != StepUndo && - out != StepIrreversible && - out != StepNewIrreversible { + out != StepFinal && + out != StepNewFinal { return 0, fmt.Errorf("invalid step: %d", step) } diff --git a/cursor_resolver.go b/cursor_resolver.go index 263a7d6..bf64fac 100644 --- a/cursor_resolver.go +++ b/cursor_resolver.go @@ -52,7 +52,7 @@ func (f *cursorResolver) ProcessBlock(blk *Block, obj interface{}) error { if blk.Number == f.cursor.Block.Num() { f.mergedBlocksSeen = append(f.mergedBlocksSeen, &BlockWithObj{blk, obj}) if blk.Id == f.cursor.Block.ID() { - if err := f.sendMergedBlocksBetween(StepIrreversible, f.cursor.LIB.Num(), f.cursor.Block.Num()); err != nil { + if err := f.sendMergedBlocksBetween(StepFinal, f.cursor.LIB.Num(), f.cursor.Block.Num()); err != nil { return err } f.passthrough = true @@ -67,10 +67,10 @@ func (f *cursorResolver) ProcessBlock(blk *Block, obj interface{}) error { if err := f.sendUndoBlocks(undoBlocks); err != nil { return err } - if err := f.sendMergedBlocksBetween(StepIrreversible, f.cursor.LIB.Num(), continueAfter); err != nil { + if err := f.sendMergedBlocksBetween(StepFinal, f.cursor.LIB.Num(), continueAfter); err != nil { return err } - if err := f.sendMergedBlocksBetween(StepNewIrreversible, continueAfter, blk.Number); err != nil { + if err := f.sendMergedBlocksBetween(StepNewFinal, continueAfter, blk.Number); err != nil { return err } diff --git a/filesource.go b/filesource.go index a42be1a..a936277 100644 --- a/filesource.go +++ b/filesource.go @@ -502,7 +502,7 @@ func (s *FileSource) preprocess(block *Block, out chan *PreprocessedBlock) { obj = &wrappedObject{ obj: obj, cursor: &Cursor{ - Step: StepNewIrreversible, + Step: StepNewFinal, Block: block.AsRef(), LIB: block.AsRef(), HeadBlock: block.AsRef(), diff --git a/filesource_test.go b/filesource_test.go index 801699f..6aebd6f 100644 --- a/filesource_test.go +++ b/filesource_test.go @@ -120,8 +120,8 @@ func TestFileSourceFromCursor(t *testing.T) { {id: "104a", num: 104}, } expectedSteps := []StepType{ - StepIrreversible, - StepNewIrreversible, + StepFinal, + StepNewFinal, } testDone := make(chan interface{}) handlerCount := 0 @@ -138,7 +138,7 @@ func TestFileSourceFromCursor(t *testing.T) { }) fs := NewFileSourceFromCursor(bs, nil, &Cursor{ - Step: StepNewIrreversible, + Step: StepNewFinal, Block: NewBlockRef("3a", 3), HeadBlock: NewBlockRef("3a", 3), LIB: NewBlockRef("2a", 2), diff --git a/forkable/forkable.go b/forkable/forkable.go index fe86a00..40d472c 100644 --- a/forkable/forkable.go +++ b/forkable/forkable.go @@ -147,7 +147,7 @@ func (p *Forkable) blocksFromNum(num uint64) ([]*bstream.PreprocessedBlock, erro } step := bstream.StepNew if ref.Num() <= libNum { - step = bstream.StepNewIrreversible + step = bstream.StepNewFinal } out = append(out, wrapBlockForkableObject(seg[i].Object.(*ForkableBlock), step, head, lib)) } @@ -215,9 +215,9 @@ func (p *Forkable) blocksFromCursor(cursor *bstream.Cursor) ([]*bstream.Preproce // send irreversible notifications up to forkdb LIB if seg[i].BlockNum <= p.forkDB.LIBNum() { - stepType := bstream.StepIrreversible + stepType := bstream.StepFinal if seg[i].BlockNum > cursor.Block.Num() { - stepType = bstream.StepNewIrreversible + stepType = bstream.StepNewFinal } out = append(out, wrapBlockForkableObject(seg[i].Object.(*ForkableBlock), stepType, head, seg[i].AsRef())) continue @@ -360,7 +360,7 @@ func (p *Forkable) targetChainBlock(blk *bstream.Block) bstream.BlockRef { } func (p *Forkable) matchFilter(step bstream.StepType) bool { - return p.filterSteps&step != 0 + return p.filterSteps.Matches(step) } func (p *Forkable) computeNewLongestChain(ppBlk *ForkableBlock) []*Block { @@ -545,7 +545,7 @@ func (p *Forkable) ProcessBlock(blk *bstream.Block, obj interface{}) error { return err } - if err := p.processStalledSegment(stalledBlocks, ppBlk.Block); err != nil { + if err := p.processStaleSegment(stalledBlocks, ppBlk.Block); err != nil { return err } @@ -703,7 +703,7 @@ func (p *Forkable) processInitialInclusiveIrreversibleBlock(blk *bstream.Block, } func (p *Forkable) processIrreversibleSegment(irreversibleSegment []*Block, headBlock bstream.BlockRef) error { - if p.matchFilter(bstream.StepIrreversible) { + if p.matchFilter(bstream.StepFinal) { var irrGroup []*bstream.PreprocessedBlock for _, irrBlock := range irreversibleSegment { preprocBlock := irrBlock.Object.(*ForkableBlock) @@ -717,7 +717,7 @@ func (p *Forkable) processIrreversibleSegment(irreversibleSegment []*Block, head preprocBlock := irrBlock.Object.(*ForkableBlock) objWrap := &ForkableObject{ - step: bstream.StepIrreversible, + step: bstream.StepFinal, lastLIBSent: preprocBlock.Block.AsRef(), // we are that lastLIBSent Obj: preprocBlock.Obj, block: preprocBlock.Block.AsRef(), @@ -743,8 +743,8 @@ func (p *Forkable) processIrreversibleSegment(irreversibleSegment []*Block, head return nil } -func (p *Forkable) processStalledSegment(stalledBlocks []*Block, headBlock bstream.BlockRef) error { - if p.matchFilter(bstream.StepStalled) { +func (p *Forkable) processStaleSegment(stalledBlocks []*Block, headBlock bstream.BlockRef) error { + if p.matchFilter(bstream.StepStale) { var stalledGroup []*bstream.PreprocessedBlock for _, staleBlock := range stalledBlocks { preprocBlock := staleBlock.Object.(*ForkableBlock) @@ -758,7 +758,7 @@ func (p *Forkable) processStalledSegment(stalledBlocks []*Block, headBlock bstre preprocBlock := staleBlock.Object.(*ForkableBlock) objWrap := &ForkableObject{ - step: bstream.StepStalled, + step: bstream.StepStale, lastLIBSent: p.lastLIBSeen, Obj: preprocBlock.Obj, block: staleBlock.AsRef(), diff --git a/forkable/forkable_test.go b/forkable/forkable_test.go index f6fbd05..694b526 100644 --- a/forkable/forkable_test.go +++ b/forkable/forkable_test.go @@ -64,7 +64,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000003a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", headBlock: tinyBlk("00000003a"), // artificially set in forkdb block: tinyBlk("00000003a"), @@ -102,7 +102,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000003a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", headBlock: tinyBlk("00000003a"), // artificially set in forkdb block: tinyBlk("00000003a"), @@ -316,7 +316,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000001a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000002a", headBlock: tinyBlk("00000003a"), block: tinyBlk("00000002a"), @@ -355,7 +355,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000001a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000002a", headBlock: tinyBlk("00000003a"), block: tinyBlk("00000002a"), @@ -374,7 +374,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000002a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", headBlock: tinyBlk("00000004a"), block: tinyBlk("00000003a"), @@ -386,7 +386,7 @@ func TestForkable_ProcessBlock(t *testing.T) { }, }, { - step: bstream.StepStalled, + step: bstream.StepStale, Obj: "00000003b", headBlock: tinyBlk("00000004a"), block: tinyBlk("00000003b"), @@ -581,7 +581,7 @@ func TestForkable_ProcessBlock(t *testing.T) { name: "ensure all blocks are new", forkDB: fdbLinked("00000001a"), ensureAllBlocksTriggerLongestChain: true, - filterSteps: bstream.StepNew | bstream.StepIrreversible, + filterSteps: bstream.StepNew | bstream.StepFinal, protocolFirstBlock: 2, processBlocks: []*bstream.Block{ bTestBlock("00000002a", "00000001a"), @@ -643,7 +643,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000001a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, headBlock: tinyBlk("00000005b"), block: tinyBlk("00000002a"), lastLIBSent: tinyBlk("00000002a"), @@ -656,7 +656,7 @@ func TestForkable_ProcessBlock(t *testing.T) { }, }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003b", headBlock: tinyBlk("00000005b"), block: tinyBlk("00000003b"), @@ -674,7 +674,7 @@ func TestForkable_ProcessBlock(t *testing.T) { name: "ensure all blocks are new, skip block", forkDB: fdbLinked("00000001a"), ensureAllBlocksTriggerLongestChain: true, - filterSteps: bstream.StepNew | bstream.StepIrreversible, + filterSteps: bstream.StepNew | bstream.StepFinal, protocolFirstBlock: 2, processBlocks: []*bstream.Block{ bTestBlock("00000002a", "00000001a"), @@ -736,7 +736,7 @@ func TestForkable_ProcessBlock(t *testing.T) { lastLIBSent: tinyBlk("00000001a"), }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, headBlock: tinyBlk("00000006b"), block: tinyBlk("00000002a"), lastLIBSent: tinyBlk("00000002a"), @@ -749,7 +749,7 @@ func TestForkable_ProcessBlock(t *testing.T) { }, }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000004b", headBlock: tinyBlk("00000006b"), block: tinyBlk("00000004b"), @@ -866,7 +866,7 @@ func TestForkable_ProcessBlock(t *testing.T) { name: "ensure block ID goes through preceded by hole", forkDB: fdbLinked("00000001a"), ensureBlockFlows: bRef("00000004b"), - filterSteps: bstream.StepNew | bstream.StepUndo | bstream.StepStalled, + filterSteps: bstream.StepNew | bstream.StepUndo | bstream.StepStale, protocolFirstBlock: 2, processBlocks: []*bstream.Block{ bTestBlock("00000002a", "00000001a"), @@ -1069,7 +1069,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000001a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000001a", StepCount: 1, StepIndex: 0, @@ -1104,7 +1104,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000002a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000002a", StepCount: 1, StepIndex: 0, @@ -1189,9 +1189,9 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { forkDB: fdbLinkedWithoutLIB(), protocolFirstBlock: 2, processBlocks: []*bstream.Block{ - tb("00000002a", "00000001a", 1), //StepNew 00000002a, StepIrreversible 2a (firstStreamable) + tb("00000002a", "00000001a", 1), //StepNew 00000002a, StepFinal 2a (firstStreamable) tb("00000003a", "00000002a", 2), //StepNew 00000003a (2 already irr) - tb("00000004a", "00000003a", 3), //StepNew 00000004a, StepIrreversible 3a + tb("00000004a", "00000003a", 3), //StepNew 00000004a, StepFinal 3a }, expectedResult: []*ForkableObject{ { @@ -1199,7 +1199,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000002a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000002a", StepCount: 1, StepIndex: 0, @@ -1216,7 +1216,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000004a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", StepCount: 1, StepIndex: 0, @@ -1245,7 +1245,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000003a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000002a", StepCount: 1, StepIndex: 0, @@ -1258,7 +1258,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000004a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", StepCount: 1, StepIndex: 0, @@ -1267,7 +1267,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { }, }, { - step: bstream.StepStalled, + step: bstream.StepStale, Obj: "00000003b", StepCount: 1, StepIndex: 0, @@ -1327,7 +1327,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { processBlocks: []*bstream.Block{ tb("00000002b", "00000001a", 1), //StepNew 00000002a tb("00000002a", "00000001a", 1), //Nothing - tb("00000003a", "00000002a", 1), //StepNew 00000002a, StepNew 00000003a, StepIrreversible 2a + tb("00000003a", "00000002a", 1), //StepNew 00000002a, StepNew 00000003a, StepFinal 2a tb("00000004a", "00000003a", 1), //StepNew 00000004a }, expectedResult: []*ForkableObject{ @@ -1430,7 +1430,7 @@ func TestForkable_ProcessBlock_UnknownLIB(t *testing.T) { Obj: "00000005a", }, { - step: bstream.StepIrreversible, + step: bstream.StepFinal, Obj: "00000003a", StepCount: 1, StepIndex: 0, @@ -1532,7 +1532,7 @@ func TestForkable_BlocksFromIrreversibleNum(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000004", "00000003", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 4, }, { @@ -1571,23 +1571,23 @@ func TestForkable_BlocksFromIrreversibleNum(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000003", "00000002", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 3, }, { bstream.TestBlockWithLIBNum("00000004", "00000003", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 4, }, { bstream.TestBlockWithLIBNum("00000005", "00000004", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 5, // LIB set to itself }, { bstream.TestBlockWithLIBNum("00000008", "00000005", 4), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 8, // real current hub LIB }, { @@ -1726,7 +1726,7 @@ func TestForkable_BlocksFromCursor(t *testing.T) { { block: bstream.TestBlockWithLIBNum("00000004a", "00000003a", 2), cursor: &bstream.Cursor{ - Step: bstream.StepIrreversible, + Step: bstream.StepFinal, HeadBlock: bstream.NewBlockRefFromID("00000009a"), Block: bstream.NewBlockRefFromID("00000004a"), LIB: bstream.NewBlockRefFromID("00000004a"), @@ -1735,7 +1735,7 @@ func TestForkable_BlocksFromCursor(t *testing.T) { { block: bstream.TestBlockWithLIBNum("00000005a", "00000004a", 2), cursor: &bstream.Cursor{ - Step: bstream.StepNewIrreversible, + Step: bstream.StepNewFinal, HeadBlock: bstream.NewBlockRefFromID("00000009a"), Block: bstream.NewBlockRefFromID("00000005a"), LIB: bstream.NewBlockRefFromID("00000005a"), diff --git a/forkable/forkdb_test.go b/forkable/forkdb_test.go index 708ff7b..6976160 100644 --- a/forkable/forkdb_test.go +++ b/forkable/forkdb_test.go @@ -141,7 +141,7 @@ func TestIrreversibleSegment(t *testing.T) { } -func TestStalledInSegment(t *testing.T) { +func TestStaleInSegment(t *testing.T) { f := NewForkDB() f.InitLIB(bRef("00000001a")) diff --git a/forkable/gates.go b/forkable/gates.go index e435d9c..7c913e8 100644 --- a/forkable/gates.go +++ b/forkable/gates.go @@ -57,7 +57,7 @@ func (g *IrreversibleBlockNumGate) ProcessBlock(blk *bstream.Block, obj interfac } fobj := obj.(*ForkableObject) - if fobj.step != bstream.StepIrreversible { + if fobj.step != bstream.StepFinal { return nil } diff --git a/hub/hub_test.go b/hub/hub_test.go index e9e298b..0acb9cc 100644 --- a/hub/hub_test.go +++ b/hub/hub_test.go @@ -194,7 +194,7 @@ func TestForkableHub_SourceFromBlockNum(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000005", "00000004", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 5, }, @@ -230,23 +230,23 @@ func TestForkableHub_SourceFromBlockNum(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000003", "00000002", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 3, }, { bstream.TestBlockWithLIBNum("00000004", "00000003", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 4, }, { bstream.TestBlockWithLIBNum("00000005", "00000004", 2), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 5, // LIB set to itself }, { bstream.TestBlockWithLIBNum("00000008", "00000005", 4), - bstream.StepNewIrreversible, + bstream.StepNewFinal, 8, // real current hub LIB }, { @@ -343,7 +343,7 @@ func TestForkableHub_SourceFromCursor(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000004", "00000003", 2), - bstream.StepIrreversible, + bstream.StepFinal, 4, }, { @@ -406,7 +406,7 @@ func TestForkableHub_SourceFromCursor(t *testing.T) { expectBlocks: []expectedBlock{ { bstream.TestBlockWithLIBNum("00000004", "00000003", 3), - bstream.StepIrreversible, + bstream.StepFinal, 4, }, }, diff --git a/steps.go b/steps.go index 76911c7..3dc140d 100644 --- a/steps.go +++ b/steps.go @@ -22,34 +22,41 @@ type StepType int const ( StepNew = StepType(1) // First time we're seeing this block - StepUndo = StepType(2) // We are undoing this block (it was came as New previously) + StepUndo = StepType(2) // We are undoing this block (it was sent as New previously) // (deprecated values for 4, 8) - StepIrreversible = StepType(16) // This block is now final and cannot be 'Undone' anymore (irreversible) + StepFinal = StepType(16) // This block is now final and cannot be 'Undone' anymore (irreversible) - StepStalled = StepType(32) // This block passed the LIB and is definitely forked out - StepNewIrreversible = StepType(StepNew | StepIrreversible) //5 First time we're seeing this block, but we already know that it is irreversible - StepsAll = StepType(StepNew | StepUndo | StepIrreversible | StepStalled) //7 useful for filters + StepStale = StepType(32) // This block passed the LIB and is definitely forked out + StepNewFinal = StepType(StepNew | StepFinal) //5 First time we're seeing this block, but we already know that it is irreversible + StepsAll = StepType(StepNew | StepUndo | StepFinal | StepStale) //7 useful for filters ) -func (t StepType) Matches(t2 StepType) bool { - return t&t2 != 0 +const ( + StepNewString = "new" + StepUndoString = "undo" + StepFinalString = "final" + StepStaleString = "stale" +) + +func (t StepType) Matches(other StepType) bool { + return t&other != 0 } func (t StepType) String() string { var el []string if t.Matches(StepNew) { - el = append(el, "new") + el = append(el, StepNewString) } if t.Matches(StepUndo) { - el = append(el, "undo") + el = append(el, StepUndoString) } - if t.Matches(StepIrreversible) { - el = append(el, "irreversible") + if t.Matches(StepFinal) { + el = append(el, StepFinalString) } - if t.Matches(StepStalled) { - el = append(el, "stalled") + if t.Matches(StepStale) { + el = append(el, StepStaleString) } if len(el) == 0 { return "none" diff --git a/stream/stream.go b/stream/stream.go index 442c491..91f7f9a 100644 --- a/stream/stream.go +++ b/stream/stream.go @@ -110,25 +110,26 @@ func (s *Stream) createSource() (bstream.Source, error) { return nil, NewErrInvalidArg("start block %d is after stop block %d", absoluteStartBlockNum, s.stopBlockNum) } - hasCursor := !s.cursor.IsEmpty() - h := s.handler if s.stopBlockNum != 0 { h = stopBlockHandler(s.stopBlockNum, h) } + if s.finalBlocksOnly { h = finalBlocksHandler(h) } else { h = newOrUndoFilter(h) } - if s.preprocessFunc != nil { - h = bstream.NewPreprocessor(s.preprocessFunc, h) - } + hasCursor := !s.cursor.IsEmpty() if s.finalBlocksOnly && hasCursor && !s.cursor.IsOnFinalBlock() { return nil, NewErrInvalidArg("cannot stream with final-blocks-only from this non-final cursor") } + if s.preprocessFunc != nil { + h = bstream.NewPreprocessor(s.preprocessFunc, h) + } + return bstream.NewJoiningSource( s.fileSourceFactory, s.liveSourceFactory, @@ -155,7 +156,7 @@ func resolveNegativeStartBlockNum(startBlockNum int64, currentHeadGetter func() return uint64(startBlockNum), nil } -// StepNew, StepNewIrreversible and StepUndo will go through +// StepNew, StepNewFinal and StepUndo will go through func newOrUndoFilter(h bstream.Handler) bstream.Handler { return bstream.HandlerFunc(func(block *bstream.Block, obj interface{}) error { if obj.(bstream.Stepable).Step().Matches(bstream.StepNew) || obj.(bstream.Stepable).Step().Matches(bstream.StepUndo) { @@ -165,10 +166,10 @@ func newOrUndoFilter(h bstream.Handler) bstream.Handler { }) } -// StepIrreversible and StepNewIrreversible will go through +// StepFinal and StepNewFinal will go through func finalBlocksHandler(h bstream.Handler) bstream.Handler { return bstream.HandlerFunc(func(block *bstream.Block, obj interface{}) error { - if obj.(bstream.Stepable).Step().Matches(bstream.StepIrreversible) { + if obj.(bstream.Stepable).Step().Matches(bstream.StepFinal) { return h.ProcessBlock(block, obj) } return nil