diff --git a/dot/core/interface.go b/dot/core/interface.go index 2b4ce30c39..1accfaffae 100644 --- a/dot/core/interface.go +++ b/dot/core/interface.go @@ -66,12 +66,12 @@ type BlockState interface { FreeImportedBlockNotifierChannel(ch chan *types.Block) GetFinalisedNotifierChannel() chan *types.FinalisationInfo FreeFinalisedNotifierChannel(ch chan *types.FinalisationInfo) - HighestCommonAncestor(a, b common.Hash) (common.Hash, error) SubChain(start, end common.Hash) ([]common.Hash, error) GetBlockBody(hash common.Hash) (*types.Body, error) HandleRuntimeChanges(newState *rtstorage.TrieState, in runtime.Instance, bHash common.Hash) error GetRuntime(blockHash common.Hash) (instance runtime.Instance, err error) StoreRuntime(common.Hash, runtime.Instance) + LowestCommonAncestor(a, b common.Hash) (common.Hash, error) } // StorageState interface for storage state methods diff --git a/dot/core/mocks_test.go b/dot/core/mocks_test.go index 65914b2c5a..0dc173bd92 100644 --- a/dot/core/mocks_test.go +++ b/dot/core/mocks_test.go @@ -329,19 +329,19 @@ func (mr *MockBlockStateMockRecorder) HandleRuntimeChanges(arg0, arg1, arg2 inte return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleRuntimeChanges", reflect.TypeOf((*MockBlockState)(nil).HandleRuntimeChanges), arg0, arg1, arg2) } -// HighestCommonAncestor mocks base method. -func (m *MockBlockState) HighestCommonAncestor(arg0, arg1 common.Hash) (common.Hash, error) { +// LowestCommonAncestor mocks base method. +func (m *MockBlockState) LowestCommonAncestor(arg0, arg1 common.Hash) (common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HighestCommonAncestor", arg0, arg1) + ret := m.ctrl.Call(m, "LowestCommonAncestor", arg0, arg1) ret0, _ := ret[0].(common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } -// HighestCommonAncestor indicates an expected call of HighestCommonAncestor. -func (mr *MockBlockStateMockRecorder) HighestCommonAncestor(arg0, arg1 interface{}) *gomock.Call { +// LowestCommonAncestor indicates an expected call of LowestCommonAncestor. +func (mr *MockBlockStateMockRecorder) LowestCommonAncestor(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HighestCommonAncestor", reflect.TypeOf((*MockBlockState)(nil).HighestCommonAncestor), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LowestCommonAncestor", reflect.TypeOf((*MockBlockState)(nil).LowestCommonAncestor), arg0, arg1) } // StoreRuntime mocks base method. diff --git a/dot/core/service.go b/dot/core/service.go index e134684379..2f19279a8d 100644 --- a/dot/core/service.go +++ b/dot/core/service.go @@ -327,19 +327,19 @@ func (s *Service) handleBlocksAsync() { // handleChainReorg checks if there is a chain re-org (ie. new chain head is on a different chain than the // previous chain head). If there is a re-org, it moves the transactions that were included on the previous // chain back into the transaction pool. -func (s *Service) handleChainReorg(prev, curr common.Hash) error { - ancestor, err := s.blockState.HighestCommonAncestor(prev, curr) +func (s *Service) handleChainReorg(best, curr common.Hash) error { + ancestor, err := s.blockState.LowestCommonAncestor(best, curr) if err != nil { return err } // if the highest common ancestor of the previous chain head and current chain head is the previous chain head, // then the current chain head is the descendant of the previous and thus are on the same chain - if ancestor == prev { + if ancestor == best || ancestor == curr { return nil } - subchain, err := s.blockState.SubChain(ancestor, prev) + subchain, err := s.blockState.SubChain(ancestor, best) if err != nil { return err } diff --git a/dot/core/service_test.go b/dot/core/service_test.go index bc670c7197..9903ce9d7e 100644 --- a/dot/core/service_test.go +++ b/dot/core/service_test.go @@ -725,7 +725,7 @@ func Test_Service_handleBlocksAsync(t *testing.T) { ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) mockBlockState.EXPECT().BestBlockHash().Return(common.Hash{}) - mockBlockState.EXPECT().HighestCommonAncestor(common.Hash{}, block.Header.Hash()). + mockBlockState.EXPECT().LowestCommonAncestor(common.Hash{}, block.Header.Hash()). Return(common.Hash{}, errTestDummyError) blockAddChan := make(chan *types.Block) @@ -767,7 +767,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(common.Hash{}, errDummyErr) service := &Service{ @@ -780,7 +780,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(common.Hash{}, errDummyErr) service := &Service{ @@ -793,7 +793,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testPrevHash, nil) service := &Service{ @@ -806,7 +806,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testAncestorHash, nil) mockBlockState.EXPECT().SubChain(testAncestorHash, testPrevHash).Return([]common.Hash{}, errDummyErr) @@ -820,7 +820,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testAncestorHash, nil) mockBlockState.EXPECT().SubChain(testAncestorHash, testPrevHash).Return([]common.Hash{}, nil) @@ -834,7 +834,7 @@ func TestService_handleChainReorg(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testAncestorHash, nil) mockBlockState.EXPECT().SubChain(testAncestorHash, testPrevHash).Return(testSubChain, nil) mockBlockState.EXPECT().BestBlockHash().Return(common.Hash{1}) @@ -867,7 +867,7 @@ func TestService_handleChainReorg(t *testing.T) { }) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testAncestorHash, nil) mockBlockState.EXPECT().SubChain(testAncestorHash, testPrevHash).Return(testSubChain, nil) mockBlockState.EXPECT().BestBlockHash().Return(common.Hash{1}) @@ -906,7 +906,7 @@ func TestService_handleChainReorg(t *testing.T) { }) mockBlockState := NewMockBlockState(ctrl) - mockBlockState.EXPECT().HighestCommonAncestor(testPrevHash, testCurrentHash). + mockBlockState.EXPECT().LowestCommonAncestor(testPrevHash, testCurrentHash). Return(testAncestorHash, nil) mockBlockState.EXPECT().SubChain(testAncestorHash, testPrevHash).Return(testSubChain, nil) mockBlockState.EXPECT().BestBlockHash().Return(common.Hash{1}) diff --git a/dot/state/block.go b/dot/state/block.go index 01659f6208..d12e9b5011 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -561,9 +561,9 @@ func (bs *BlockState) IsDescendantOf(parent, child common.Hash) (bool, error) { return bs.bt.IsDescendantOf(parent, child) } -// HighestCommonAncestor returns the block with the highest number that is an ancestor of both a and b -func (bs *BlockState) HighestCommonAncestor(a, b common.Hash) (common.Hash, error) { - return bs.bt.HighestCommonAncestor(a, b) +// LowestCommonAncestor returns the lowest common ancestor between two blocks in the tree. +func (bs *BlockState) LowestCommonAncestor(a, b common.Hash) (common.Hash, error) { + return bs.bt.LowestCommonAncestor(a, b) } // Leaves returns the leaves of the blocktree as an array diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index 6b2d9ce2c2..5396f1b00a 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -4,6 +4,7 @@ package blocktree import ( + "errors" "fmt" "sync" "time" @@ -16,11 +17,14 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" ) -var leavesGauge = promauto.NewGauge(prometheus.GaugeOpts{ - Namespace: "gossamer_block", - Name: "leaves_total", - Help: "total number of blocktree leaves", -}) +var ( + leavesGauge = promauto.NewGauge(prometheus.GaugeOpts{ + Namespace: "gossamer_block", + Name: "leaves_total", + Help: "total number of blocktree leaves", + }) + errAncestorOutOfBoundsCheck = errors.New("out of bounds ancestor check") +) // Hash common.Hash type Hash = common.Hash @@ -297,29 +301,50 @@ func (bt *BlockTree) Leaves() []Hash { return la } -// HighestCommonAncestor returns the highest block that is a Ancestor to both a and b -func (bt *BlockTree) HighestCommonAncestor(a, b Hash) (Hash, error) { +// LowestCommonAncestor returns the lowest common ancestor block hash between two blocks in the tree. +func (bt *BlockTree) LowestCommonAncestor(a, b Hash) (Hash, error) { bt.RLock() defer bt.RUnlock() - an := bt.getNode(a) - if an == nil { + aNode := bt.getNode(a) + if aNode == nil { return common.Hash{}, ErrNodeNotFound } - bn := bt.getNode(b) - if bn == nil { + bNode := bt.getNode(b) + if bNode == nil { return common.Hash{}, ErrNodeNotFound } - - ancestor := an.highestCommonAncestor(bn) - if ancestor == nil { - // this case shouldn't happen - any two nodes in the blocktree must - // have a common ancestor, the lowest of which is the root node - return common.Hash{}, fmt.Errorf("%w: %s and %s", ErrNoCommonAncestor, a, b) + return lowestCommonAncestor(aNode, bNode), nil +} +func lowestCommonAncestor(aNode, bNode *node) Hash { + higherNode := bNode + lowerNode := aNode + if aNode.number > bNode.number { + higherNode = aNode + lowerNode = bNode + } + + higherNum := higherNode.number + lowerNum := lowerNode.number + diff := higherNum - lowerNum + for diff > 0 { + if higherNode.parent == nil { + panic(fmt.Errorf("%w: for block number %v", errAncestorOutOfBoundsCheck, higherNum)) + } + higherNode = higherNode.parent + diff-- } - return ancestor.hash, nil + for { + if higherNode.hash == lowerNode.hash { + return higherNode.hash + } else if higherNode.parent == nil || lowerNode.parent == nil { + panic(fmt.Errorf("%w: for block number %v", errAncestorOutOfBoundsCheck, higherNum)) + } + higherNode = higherNode.parent + lowerNode = lowerNode.parent + } } // GetAllBlocks returns all the blocks in the tree diff --git a/lib/blocktree/blocktree_test.go b/lib/blocktree/blocktree_test.go index dc5e90cddd..f25be6adb0 100644 --- a/lib/blocktree/blocktree_test.go +++ b/lib/blocktree/blocktree_test.go @@ -145,7 +145,7 @@ func createFlatTree(t *testing.T, number uint) (*BlockTree, []common.Hash) { return bt, hashes } -func TestNewBlockTreeFromNode(t *testing.T) { +func Test_NewBlockTreeFromNode(t *testing.T) { var bt *BlockTree var branches []testBranch @@ -163,7 +163,7 @@ func TestNewBlockTreeFromNode(t *testing.T) { require.ElementsMatch(t, leaves, newBt.leaves.nodes()) } -func TestBlockTree_GetBlock(t *testing.T) { +func Test_BlockTree_GetBlock(t *testing.T) { bt, hashes := createFlatTree(t, 2) n := bt.getNode(hashes[2]) @@ -177,7 +177,7 @@ func TestBlockTree_GetBlock(t *testing.T) { } -func TestBlockTree_AddBlock(t *testing.T) { +func Test_BlockTree_AddBlock(t *testing.T) { bt, hashes := createFlatTree(t, 1) header := &types.Header{ @@ -203,7 +203,7 @@ func TestBlockTree_AddBlock(t *testing.T) { } } -func TestNode_isDecendantOf(t *testing.T) { +func Test_Node_isDecendantOf(t *testing.T) { // Create tree with number 4 (with 4 nodes) bt, hashes := createFlatTree(t, 4) @@ -219,7 +219,7 @@ func TestNode_isDecendantOf(t *testing.T) { } } -func TestBlockTree_Subchain(t *testing.T) { +func Test_BlockTree_Subchain(t *testing.T) { bt, hashes := createFlatTree(t, 4) expectedPath := hashes[1:] @@ -246,7 +246,7 @@ func TestBlockTree_Subchain(t *testing.T) { } } -func TestBlockTree_Best_AllPrimary(t *testing.T) { +func Test_BlockTree_Best_AllPrimary(t *testing.T) { arrivalTime := int64(256) var expected Hash @@ -268,7 +268,7 @@ func TestBlockTree_Best_AllPrimary(t *testing.T) { require.Equal(t, expected, bt.best().hash) } -func TestBlockTree_GetNode(t *testing.T) { +func Test_BlockTree_GetNode(t *testing.T) { bt, branches := createTestBlockTree(t, testHeader, 16) for _, branch := range branches { @@ -287,7 +287,7 @@ func TestBlockTree_GetNode(t *testing.T) { require.NotNil(t, block) } -func TestBlockTree_GetAllBlocksAtNumber(t *testing.T) { +func Test_BlockTree_GetAllBlocksAtNumber(t *testing.T) { bt, _ := createTestBlockTree(t, testHeader, 8) hashes := bt.root.getNodesWithNumber(10, []common.Hash{}) @@ -347,7 +347,7 @@ func TestBlockTree_GetAllBlocksAtNumber(t *testing.T) { require.Equal(t, expected, hashes) } -func TestBlockTreeGetAllDescendants(t *testing.T) { +func Test_BlockTree_GetAllDescendants(t *testing.T) { t.Parallel() // Create tree with number 4 (with 4 nodes) @@ -358,7 +358,7 @@ func TestBlockTreeGetAllDescendants(t *testing.T) { require.Equal(t, hashes, descendants) } -func TestBlockTree_IsDecendantOf(t *testing.T) { +func Test_BlockTree_IsDecendantOf(t *testing.T) { // Create tree with number 4 (with 4 nodes) bt, hashes := createFlatTree(t, 4) @@ -371,7 +371,121 @@ func TestBlockTree_IsDecendantOf(t *testing.T) { require.False(t, isDescendant) } -func TestBlockTree_HighestCommonAncestor(t *testing.T) { +func Test_lowestCommonAncestor(t *testing.T) { + t.Parallel() + root := &node{ + hash: common.Hash{0}, + number: 0, + } + + children := []*node{ + { + hash: common.Hash{1}, + parent: root, + isPrimary: true, + number: 1, + }, + { + hash: common.Hash{2}, + parent: root, + isPrimary: false, + number: 1, + }, + } + + childrenChildren := []*node{ + { + hash: common.Hash{3}, + parent: children[0], + isPrimary: true, + number: 2, + }, + { + hash: common.Hash{4}, + parent: children[1], + isPrimary: false, + number: 2, + }, + } + finalChild := []*node{ + { + hash: common.Hash{5}, + parent: childrenChildren[1], + isPrimary: true, + number: 3, + }, + } + + type args struct { + nodeA *node + nodeB *node + } + tests := []struct { + name string + args args + expErr error + expRes Hash + }{ + { + name: "child and root", + args: args{ + nodeA: children[1], + nodeB: root, + }, + expRes: root.hash, + }, + { + name: "same node", + args: args{ + nodeA: children[1], + nodeB: children[1], + }, + expRes: children[1].hash, + }, + { + name: "siblings", + args: args{ + nodeA: children[0], + nodeB: children[1], + }, + expRes: root.hash, + }, + { + name: "child and its child", + args: args{ + nodeA: children[0], + nodeB: childrenChildren[0], + }, + expRes: children[0].hash, + }, + { + name: "root and grandchild", + args: args{ + nodeA: root, + nodeB: childrenChildren[0], + }, + expRes: root.hash, + }, + { + name: "grandchild and its siblings child", + args: args{ + nodeA: finalChild[0], + nodeB: childrenChildren[0], + }, + expRes: root.hash, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ancestor := lowestCommonAncestor(tt.args.nodeA, tt.args.nodeB) + require.Equal(t, tt.expRes, ancestor) + }) + } +} + +func Test_BlockTree_LowestCommonAncestor(t *testing.T) { var bt *BlockTree var leaves []common.Hash var branches []testBranch @@ -389,23 +503,23 @@ func TestBlockTree_HighestCommonAncestor(t *testing.T) { a := leaves[0] b := leaves[1] - p, err := bt.HighestCommonAncestor(a, b) + p, err := bt.LowestCommonAncestor(a, b) require.NoError(t, err) require.Equal(t, expected, p) } -func TestBlockTree_HighestCommonAncestor_SameNode(t *testing.T) { +func Test_BlockTree_LowestCommonAncestor_SameNode(t *testing.T) { bt, _ := createTestBlockTree(t, testHeader, 8) leaves := bt.Leaves() a := leaves[0] - p, err := bt.HighestCommonAncestor(a, a) + p, err := bt.LowestCommonAncestor(a, a) require.NoError(t, err) require.Equal(t, a, p) } -func TestBlockTree_HighestCommonAncestor_SameChain(t *testing.T) { +func Test_BlockTree_LowestCommonAncestor_SameChain(t *testing.T) { bt, _ := createTestBlockTree(t, testHeader, 8) leaves := bt.Leaves() @@ -413,12 +527,12 @@ func TestBlockTree_HighestCommonAncestor_SameChain(t *testing.T) { b := bt.getNode(a).parent.hash // b is a's parent, so their highest common Ancestor is b. - p, err := bt.HighestCommonAncestor(a, b) + p, err := bt.LowestCommonAncestor(a, b) require.NoError(t, err) require.Equal(t, b, p) } -func TestBlockTree_Prune(t *testing.T) { +func Test_BlockTree_Prune(t *testing.T) { var bt *BlockTree var branches []testBranch @@ -453,7 +567,7 @@ func TestBlockTree_Prune(t *testing.T) { } } -func TestBlockTree_GetHashByNumber(t *testing.T) { +func Test_BlockTree_GetHashByNumber(t *testing.T) { bt, _ := createTestBlockTree(t, testHeader, 8) best := bt.BestBlockHash() bn := bt.getNode(best) @@ -471,7 +585,7 @@ func TestBlockTree_GetHashByNumber(t *testing.T) { require.Error(t, err) } -func TestBlockTree_BestBlockHash_AllChainsEqual(t *testing.T) { +func Test_BlockTree_BestBlockHash_AllChainsEqual(t *testing.T) { bt := NewBlockTreeFromRoot(testHeader) previousHash := testHeader.Hash() @@ -577,7 +691,7 @@ func TestBlockTree_BestBlockHash_AllChainsEqual(t *testing.T) { require.Equal(t, hash, bt.best().hash) } -func TestBlockTree_DeepCopy(t *testing.T) { +func Test_BlockTree_DeepCopy(t *testing.T) { bt, _ := createFlatTree(t, 8) btCopy := bt.DeepCopy() @@ -614,7 +728,7 @@ func equalLeaves(t *testing.T, lm *leafMap, lmCopy *leafMap) { } } -func TestBlockTree_best(t *testing.T) { +func Test_BlockTree_best(t *testing.T) { // test basic case where two chains have different amount of primaries bt := NewEmptyBlockTree() bt.root = &node{ diff --git a/lib/blocktree/node.go b/lib/blocktree/node.go index a9c00ba3af..cacc940197 100644 --- a/lib/blocktree/node.go +++ b/lib/blocktree/node.go @@ -122,20 +122,6 @@ func (n *node) isDescendantOf(parent *node) bool { return false } -func (n *node) highestCommonAncestor(other *node) *node { - for curr := n; curr != nil; curr = curr.parent { - if curr.hash == other.hash { - return curr - } - - if other.isDescendantOf(curr) { - return curr - } - } - - return nil -} - // getLeaves returns all nodes that are leaf nodes with the current node as its ancestor func (n *node) getLeaves(leaves []*node) []*node { if n == nil { diff --git a/lib/grandpa/grandpa.go b/lib/grandpa/grandpa.go index 6dc9ba3f6c..7ae823bb2e 100644 --- a/lib/grandpa/grandpa.go +++ b/lib/grandpa/grandpa.go @@ -893,7 +893,7 @@ func (s *Service) getBestFinalCandidate() (*Vote, error) { if !isDescendant { // find common ancestor, implicitly has >2/3 votes - pred, err := s.blockState.HighestCommonAncestor(h, prevoted.Hash) + pred, err := s.blockState.LowestCommonAncestor(h, prevoted.Hash) if err != nil { return nil, err } @@ -1061,7 +1061,7 @@ func (s *Service) getPossibleSelectedAncestors(votes []Vote, curr common.Hash, } // find common ancestor, check if votes for it is >threshold or not - pred, err := s.blockState.HighestCommonAncestor(v.Hash, curr) + pred, err := s.blockState.LowestCommonAncestor(v.Hash, curr) if errors.Is(err, blocktree.ErrNodeNotFound) { continue } else if err != nil { diff --git a/lib/grandpa/grandpa_test.go b/lib/grandpa/grandpa_test.go index 26a65841a0..913d3f7e16 100644 --- a/lib/grandpa/grandpa_test.go +++ b/lib/grandpa/grandpa_test.go @@ -948,7 +948,7 @@ func TestGetBestFinalCandidate_PrecommitOnAnotherChain(t *testing.T) { } } - pred, err := st.Block.HighestCommonAncestor(voteA.Hash, voteB.Hash) + pred, err := st.Block.LowestCommonAncestor(voteA.Hash, voteB.Hash) require.NoError(t, err) bfc, err := gs.getBestFinalCandidate() @@ -1037,7 +1037,7 @@ func TestGetGrandpaGHOST_CommonAncestor(t *testing.T) { } } - pred, err := gs.blockState.HighestCommonAncestor(voteA.Hash, voteB.Hash) + pred, err := gs.blockState.LowestCommonAncestor(voteA.Hash, voteB.Hash) require.NoError(t, err) block, err := gs.getGrandpaGHOST() diff --git a/lib/grandpa/mocks_test.go b/lib/grandpa/mocks_test.go index 97ba682105..d44433c797 100644 --- a/lib/grandpa/mocks_test.go +++ b/lib/grandpa/mocks_test.go @@ -310,21 +310,6 @@ func (mr *MockBlockStateMockRecorder) HasJustification(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasJustification", reflect.TypeOf((*MockBlockState)(nil).HasJustification), arg0) } -// HighestCommonAncestor mocks base method. -func (m *MockBlockState) HighestCommonAncestor(arg0, arg1 common.Hash) (common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HighestCommonAncestor", arg0, arg1) - ret0, _ := ret[0].(common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// HighestCommonAncestor indicates an expected call of HighestCommonAncestor. -func (mr *MockBlockStateMockRecorder) HighestCommonAncestor(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HighestCommonAncestor", reflect.TypeOf((*MockBlockState)(nil).HighestCommonAncestor), arg0, arg1) -} - // IsDescendantOf mocks base method. func (m *MockBlockState) IsDescendantOf(arg0, arg1 common.Hash) (bool, error) { m.ctrl.T.Helper() @@ -354,6 +339,21 @@ func (mr *MockBlockStateMockRecorder) Leaves() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Leaves", reflect.TypeOf((*MockBlockState)(nil).Leaves)) } +// LowestCommonAncestor mocks base method. +func (m *MockBlockState) LowestCommonAncestor(arg0, arg1 common.Hash) (common.Hash, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LowestCommonAncestor", arg0, arg1) + ret0, _ := ret[0].(common.Hash) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// LowestCommonAncestor indicates an expected call of LowestCommonAncestor. +func (mr *MockBlockStateMockRecorder) LowestCommonAncestor(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LowestCommonAncestor", reflect.TypeOf((*MockBlockState)(nil).LowestCommonAncestor), arg0, arg1) +} + // SetFinalisedHash mocks base method. func (m *MockBlockState) SetFinalisedHash(arg0 common.Hash, arg1, arg2 uint64) error { m.ctrl.T.Helper() diff --git a/lib/grandpa/state.go b/lib/grandpa/state.go index d8de9bf141..da0780eb69 100644 --- a/lib/grandpa/state.go +++ b/lib/grandpa/state.go @@ -19,7 +19,7 @@ type BlockState interface { GetHeader(hash common.Hash) (*types.Header, error) GetHeaderByNumber(num uint) (*types.Header, error) IsDescendantOf(parent, child common.Hash) (bool, error) - HighestCommonAncestor(a, b common.Hash) (common.Hash, error) + LowestCommonAncestor(a, b common.Hash) (common.Hash, error) HasFinalisedBlock(round, setID uint64) (bool, error) GetFinalisedHeader(uint64, uint64) (*types.Header, error) SetFinalisedHash(common.Hash, uint64, uint64) error