fix(splitstore): fix a panic on revert-only head changes
Calling, e.g., `lotus chain sethead` on an ancestor tipset won't apply any new blocks, it'll just revert a bunch. This will lead to HeadChange calls with no new blocks to apply. fixes #6125
This commit is contained in:
parent
4688da5178
commit
63db9e1633
@ -406,6 +406,11 @@ func (s *SplitStore) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SplitStore) HeadChange(_, apply []*types.TipSet) error {
|
func (s *SplitStore) HeadChange(_, apply []*types.TipSet) error {
|
||||||
|
// Revert only.
|
||||||
|
if len(apply) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
s.mx.Lock()
|
s.mx.Lock()
|
||||||
curTs := apply[len(apply)-1]
|
curTs := apply[len(apply)-1]
|
||||||
epoch := curTs.Height()
|
epoch := curTs.Height()
|
||||||
|
@ -27,7 +27,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSplitStore(t *testing.T, cfg *Config) {
|
func testSplitStore(t *testing.T, cfg *Config) {
|
||||||
chain := &mockChain{}
|
chain := &mockChain{t: t}
|
||||||
// genesis
|
// genesis
|
||||||
genBlock := mock.MkBlock(nil, 0, 0)
|
genBlock := mock.MkBlock(nil, 0, 0)
|
||||||
genTs := mock.TipSet(genBlock)
|
genTs := mock.TipSet(genBlock)
|
||||||
@ -169,6 +169,9 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
|
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we can revert without panicing.
|
||||||
|
chain.revert(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitStoreSimpleCompaction(t *testing.T) {
|
func TestSplitStoreSimpleCompaction(t *testing.T) {
|
||||||
@ -191,6 +194,8 @@ func TestSplitStoreFullCompactionWithGC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type mockChain struct {
|
type mockChain struct {
|
||||||
|
t testing.TB
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
tipsets []*types.TipSet
|
tipsets []*types.TipSet
|
||||||
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
||||||
@ -204,7 +209,26 @@ func (c *mockChain) push(ts *types.TipSet) {
|
|||||||
if c.listener != nil {
|
if c.listener != nil {
|
||||||
err := c.listener(nil, []*types.TipSet{ts})
|
err := c.listener(nil, []*types.TipSet{ts})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("mockchain: error dispatching listener: %s", err)
|
c.t.Errorf("mockchain: error dispatching listener: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockChain) revert(count int) {
|
||||||
|
c.Lock()
|
||||||
|
revert := make([]*types.TipSet, count)
|
||||||
|
if count > len(c.tipsets) {
|
||||||
|
c.Unlock()
|
||||||
|
c.t.Fatalf("not enough tipsets to revert")
|
||||||
|
}
|
||||||
|
copy(revert, c.tipsets[len(c.tipsets)-count:])
|
||||||
|
c.tipsets = c.tipsets[:len(c.tipsets)-count]
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
|
if c.listener != nil {
|
||||||
|
err := c.listener(revert, nil)
|
||||||
|
if err != nil {
|
||||||
|
c.t.Errorf("mockchain: error dispatching listener: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user