diff --git a/chain/store/index.go b/chain/store/index.go index 15d5d7025..8747c79c6 100644 --- a/chain/store/index.go +++ b/chain/store/index.go @@ -97,9 +97,15 @@ func (ci *ChainIndex) fillCache(tsk types.TipSetKey) (*lbEntry, error) { rheight -= ci.skipLength - skipTarget, err := ci.walkBack(parent, rheight) - if err != nil { - return nil, err + var skipTarget *types.TipSet + if parent.Height() < rheight { + skipTarget = parent + + } else { + skipTarget, err = ci.walkBack(parent, rheight) + if err != nil { + return nil, xerrors.Errorf("fillCache walkback: %w", err) + } } lbe := &lbEntry{ diff --git a/chain/store/index_test.go b/chain/store/index_test.go new file mode 100644 index 000000000..6b97a8614 --- /dev/null +++ b/chain/store/index_test.go @@ -0,0 +1,76 @@ +package store_test + +import ( + "bytes" + "context" + "testing" + + "github.com/filecoin-project/lotus/chain/gen" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/specs-actors/actors/abi" + datastore "github.com/ipfs/go-datastore" + syncds "github.com/ipfs/go-datastore/sync" + blockstore "github.com/ipfs/go-ipfs-blockstore" + "github.com/stretchr/testify/assert" +) + +func TestIndexSeeks(t *testing.T) { + cg, err := gen.NewGenerator() + if err != nil { + t.Fatal(err) + } + + gencar, err := cg.GenesisCar() + if err != nil { + t.Fatal(err) + } + + gen := cg.Genesis() + + ctx := context.TODO() + + nbs := blockstore.NewBlockstore(syncds.MutexWrap(datastore.NewMapDatastore())) + cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil) + + _, err = cs.Import(bytes.NewReader(gencar)) + if err != nil { + t.Fatal(err) + } + + cur := mock.TipSet(gen) + if err := cs.PutTipSet(ctx, mock.TipSet(gen)); err != nil { + t.Fatal(err) + } + cs.SetGenesis(gen) + + for i := 0; i < 100; i++ { + nextts := mock.TipSet(mock.MkBlock(cur, 1, 1)) + + if err := cs.PutTipSet(ctx, nextts); err != nil { + t.Fatal(err) + } + cur = nextts + } + + skip := mock.MkBlock(cur, 1, 1) + skip.Height += 50 + + skipts := mock.TipSet(skip) + + if err := cs.PutTipSet(ctx, skipts); err != nil { + t.Fatal(err) + } + + ts, err := cs.GetTipsetByHeight(ctx, skip.Height-10, skipts, false) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, abi.ChainEpoch(151), ts.Height()) + + ts2, err := cs.GetTipsetByHeight(ctx, 90, skipts, false) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, abi.ChainEpoch(90), ts2.Height()) +} diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index 5154ab115..00d0eecc9 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -49,6 +49,11 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types panic(err) } + pstateRoot := c + if parents != nil { + pstateRoot = parents.Blocks()[0].ParentStateRoot + } + var pcids []cid.Cid var height abi.ChainEpoch weight := types.NewInt(weightInc) @@ -72,7 +77,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types ParentWeight: weight, Messages: c, Height: height, - ParentStateRoot: c, + ParentStateRoot: pstateRoot, BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")}, } }