Skip to content

Commit e7749cf

Browse files
authored
fix(dot/rpc/modules): grandpa.proveFinality update parameters, fix bug (#2576)
1 parent 0fcde63 commit e7749cf

12 files changed

Lines changed: 2970 additions & 556 deletions

dot/rpc/modules/api_mocks.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ func NewMockStorageAPI() *modulesmocks.StorageAPI {
2727
return m
2828
}
2929

30-
// NewMockBlockAPI creates and return an rpc BlockAPI interface mock
31-
func NewMockBlockAPI() *modulesmocks.BlockAPI {
30+
// NewMockeryBlockAPI creates and return an rpc BlockAPI interface mock
31+
func NewMockeryBlockAPI() *modulesmocks.BlockAPI {
3232
m := new(modulesmocks.BlockAPI)
3333
m.On("GetHeader", mock.AnythingOfType("common.Hash")).Return(nil, nil)
3434
m.On("BestBlockHash").Return(common.Hash{})

dot/rpc/modules/grandpa.go

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package modules
55

66
import (
7+
"fmt"
78
"net/http"
89

910
"github.com/ChainSafe/gossamer/lib/common"
@@ -48,39 +49,35 @@ type RoundStateResponse struct {
4849

4950
// ProveFinalityRequest request struct
5051
type ProveFinalityRequest struct {
51-
blockHashStart common.Hash
52-
blockHashEnd common.Hash
53-
authorityID uint64
52+
BlockNumber uint32 `json:"blockNumber"`
5453
}
5554

5655
// ProveFinalityResponse is an optional SCALE encoded proof array
57-
type ProveFinalityResponse [][]byte
56+
type ProveFinalityResponse []string
5857

59-
// ProveFinality for the provided block range. Returns NULL if there are no known finalised blocks in the range.
60-
// If no authorities set is provided, the current one will be attempted.
58+
// ProveFinality for the provided block number, the Justification for the last block in the set is written to the
59+
// response. The response is a SCALE encoded proof array. The proof array is empty if the block number is
60+
// not finalized.
61+
// Returns error which are included in the response if they occur.
6162
func (gm *GrandpaModule) ProveFinality(r *http.Request, req *ProveFinalityRequest, res *ProveFinalityResponse) error {
62-
blocksToCheck, err := gm.blockAPI.SubChain(req.blockHashStart, req.blockHashEnd)
63+
blockHash, err := gm.blockAPI.GetHashByNumber(uint(req.BlockNumber))
6364
if err != nil {
6465
return err
6566
}
66-
67-
// Leaving check in for linter
68-
if req.authorityID != uint64(0) {
69-
// TODO: Check if functionality relevant (#1404)
67+
hasJustification, err := gm.blockAPI.HasJustification(blockHash)
68+
if err != nil {
69+
return fmt.Errorf("checking for justification: %w", err)
7070
}
7171

72-
for _, block := range blocksToCheck {
73-
hasJustification, _ := gm.blockAPI.HasJustification(block)
74-
if !hasJustification {
75-
continue
76-
}
77-
78-
justification, err := gm.blockAPI.GetJustification(block)
79-
if err != nil {
80-
continue
81-
}
82-
*res = append(*res, justification)
72+
if !hasJustification {
73+
*res = append(*res, "GRANDPA prove finality rpc failed: Block not covered by authority set changes")
74+
return nil
75+
}
76+
justification, err := gm.blockAPI.GetJustification(blockHash)
77+
if err != nil {
78+
return fmt.Errorf("getting justification: %w", err)
8379
}
80+
*res = append(*res, common.BytesToHex(justification))
8481

8582
return nil
8683
}

dot/rpc/modules/grandpa_integration_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
package modules
77

88
import (
9-
"reflect"
109
"testing"
1110

1211
"github.com/ChainSafe/gossamer/dot/state"
1312
"github.com/ChainSafe/gossamer/dot/types"
1413
"github.com/ChainSafe/gossamer/lib/crypto/ed25519"
1514
"github.com/ChainSafe/gossamer/lib/grandpa"
1615
"github.com/ChainSafe/gossamer/lib/keystore"
16+
"github.com/stretchr/testify/assert"
1717
"github.com/stretchr/testify/require"
1818

1919
rpcmocks "github.com/ChainSafe/gossamer/dot/rpc/modules/mocks"
@@ -36,22 +36,18 @@ func TestGrandpaProveFinality(t *testing.T) {
3636
testStateService.Block.SetJustification(bestBlock.Header.ParentHash, make([]byte, 10))
3737
testStateService.Block.SetJustification(bestBlock.Header.Hash(), make([]byte, 11))
3838

39-
var expectedResponse ProveFinalityResponse
40-
expectedResponse = append(expectedResponse, make([]byte, 10), make([]byte, 11))
39+
expectedResponse := &ProveFinalityResponse{"0x0000000000000000000000"}
4140

4241
res := new(ProveFinalityResponse)
4342
err = gmSvc.ProveFinality(nil, &ProveFinalityRequest{
44-
blockHashStart: bestBlock.Header.ParentHash,
45-
blockHashEnd: bestBlock.Header.Hash(),
43+
BlockNumber: uint32(bestBlock.Header.Number),
4644
}, res)
4745

4846
if err != nil {
4947
t.Fatal(err)
5048
}
5149

52-
if !reflect.DeepEqual(*res, expectedResponse) {
53-
t.Errorf("Fail: expected: %+v got: %+v\n", res, &expectedResponse)
54-
}
50+
assert.Equal(t, *expectedResponse, *res)
5551
}
5652

5753
func TestRoundState(t *testing.T) {

dot/rpc/modules/grandpa_test.go

Lines changed: 66 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,126 +14,99 @@ import (
1414
"github.com/ChainSafe/gossamer/lib/crypto/ed25519"
1515
"github.com/ChainSafe/gossamer/lib/grandpa"
1616
"github.com/ChainSafe/gossamer/lib/keystore"
17-
17+
"github.com/golang/mock/gomock"
1818
"github.com/stretchr/testify/assert"
1919
)
2020

2121
func TestGrandpaModule_ProveFinality(t *testing.T) {
22-
testHash := common.NewHash([]byte{0x01, 0x02})
23-
testHashSlice := []common.Hash{testHash, testHash, testHash}
24-
25-
mockBlockFinalityAPI := new(mocks.BlockFinalityAPI)
26-
mockBlockAPI := new(mocks.BlockAPI)
27-
mockBlockAPI.On("SubChain", testHash, testHash).Return(testHashSlice, nil)
28-
mockBlockAPI.On("HasJustification", testHash).Return(true, nil)
29-
mockBlockAPI.On("GetJustification", testHash).Return([]byte("test"), nil)
22+
t.Parallel()
3023

31-
mockBlockAPIHasJustErr := new(mocks.BlockAPI)
32-
mockBlockAPIHasJustErr.On("SubChain", testHash, testHash).Return(testHashSlice, nil)
33-
mockBlockAPIHasJustErr.On("HasJustification", testHash).Return(false, nil)
24+
mockError := errors.New("test mock error")
3425

35-
mockBlockAPIGetJustErr := new(mocks.BlockAPI)
36-
mockBlockAPIGetJustErr.On("SubChain", testHash, testHash).Return(testHashSlice, nil)
37-
mockBlockAPIGetJustErr.On("HasJustification", testHash).Return(true, nil)
38-
mockBlockAPIGetJustErr.On("GetJustification", testHash).Return(nil, errors.New("GetJustification error"))
39-
40-
mockBlockAPISubChainErr := new(mocks.BlockAPI)
41-
mockBlockAPISubChainErr.On("SubChain", testHash, testHash).Return(nil, errors.New("SubChain error"))
42-
43-
grandpaModule := NewGrandpaModule(mockBlockAPISubChainErr, mockBlockFinalityAPI)
44-
type fields struct {
45-
blockAPI BlockAPI
46-
blockFinalityAPI BlockFinalityAPI
47-
}
48-
type args struct {
49-
r *http.Request
50-
req *ProveFinalityRequest
51-
}
52-
tests := []struct {
53-
name string
54-
fields fields
55-
args args
56-
expErr error
57-
exp ProveFinalityResponse
26+
tests := map[string]struct {
27+
blockAPIBuilder func(ctrl *gomock.Controller) BlockAPI
28+
request *ProveFinalityRequest
29+
expErr error
30+
exp ProveFinalityResponse
5831
}{
59-
{
60-
name: "SubChain Err",
61-
fields: fields{
62-
grandpaModule.blockAPI,
63-
grandpaModule.blockFinalityAPI,
32+
"error during get hash by number": {
33+
blockAPIBuilder: func(ctrl *gomock.Controller) BlockAPI {
34+
mockBlockAPI := NewMockBlockAPI(ctrl)
35+
mockBlockAPI.EXPECT().GetHashByNumber(uint(1)).Return(common.Hash{}, mockError)
36+
return mockBlockAPI
6437
},
65-
args: args{
66-
req: &ProveFinalityRequest{
67-
blockHashStart: testHash,
68-
blockHashEnd: testHash,
69-
authorityID: uint64(21),
70-
},
38+
request: &ProveFinalityRequest{
39+
BlockNumber: 1,
7140
},
72-
expErr: errors.New("SubChain error"),
41+
expErr: mockError,
7342
},
74-
{
75-
name: "OK Case",
76-
fields: fields{
77-
mockBlockAPI,
78-
mockBlockFinalityAPI,
43+
"error during has justification": {
44+
blockAPIBuilder: func(ctrl *gomock.Controller) BlockAPI {
45+
mockBlockAPI := NewMockBlockAPI(ctrl)
46+
mockBlockAPI.EXPECT().GetHashByNumber(uint(2)).Return(common.Hash{2}, nil)
47+
mockBlockAPI.EXPECT().HasJustification(common.Hash{2}).Return(false, mockError)
48+
return mockBlockAPI
7949
},
80-
args: args{
81-
req: &ProveFinalityRequest{
82-
blockHashStart: testHash,
83-
blockHashEnd: testHash,
84-
authorityID: uint64(21),
85-
},
50+
request: &ProveFinalityRequest{
51+
BlockNumber: 2,
8652
},
87-
exp: ProveFinalityResponse{
88-
[]uint8{0x74, 0x65, 0x73, 0x74},
89-
[]uint8{0x74, 0x65, 0x73, 0x74},
90-
[]uint8{0x74, 0x65, 0x73, 0x74}},
53+
expErr: mockError,
9154
},
92-
{
93-
name: "HasJustification Error",
94-
fields: fields{
95-
mockBlockAPIHasJustErr,
96-
mockBlockFinalityAPI,
55+
"has justification is false": {
56+
blockAPIBuilder: func(ctrl *gomock.Controller) BlockAPI {
57+
mockBlockAPI := NewMockBlockAPI(ctrl)
58+
mockBlockAPI.EXPECT().GetHashByNumber(uint(2)).Return(common.Hash{2}, nil)
59+
mockBlockAPI.EXPECT().HasJustification(common.Hash{2}).Return(false, nil)
60+
return mockBlockAPI
9761
},
98-
args: args{
99-
req: &ProveFinalityRequest{
100-
blockHashStart: testHash,
101-
blockHashEnd: testHash,
102-
authorityID: uint64(21),
103-
},
62+
request: &ProveFinalityRequest{
63+
BlockNumber: 2,
10464
},
105-
exp: ProveFinalityResponse(nil),
65+
exp: ProveFinalityResponse{"GRANDPA prove finality rpc failed: Block not covered by authority set changes"},
10666
},
107-
{
108-
name: "GetJustification Error",
109-
fields: fields{
110-
mockBlockAPIGetJustErr,
111-
mockBlockFinalityAPI,
67+
"error during getJustification": {
68+
blockAPIBuilder: func(ctrl *gomock.Controller) BlockAPI {
69+
mockBlockAPI := NewMockBlockAPI(ctrl)
70+
mockBlockAPI.EXPECT().GetHashByNumber(uint(3)).Return(common.Hash{3}, nil)
71+
mockBlockAPI.EXPECT().HasJustification(common.Hash{3}).Return(true, nil)
72+
mockBlockAPI.EXPECT().GetJustification(common.Hash{3}).Return(nil, mockError)
73+
return mockBlockAPI
11274
},
113-
args: args{
114-
req: &ProveFinalityRequest{
115-
blockHashStart: testHash,
116-
blockHashEnd: testHash,
117-
authorityID: uint64(21),
118-
},
75+
request: &ProveFinalityRequest{
76+
BlockNumber: 3,
77+
},
78+
expErr: mockError,
79+
},
80+
"happy path": {
81+
blockAPIBuilder: func(ctrl *gomock.Controller) BlockAPI {
82+
mockBlockAPI := NewMockBlockAPI(ctrl)
83+
mockBlockAPI.EXPECT().GetHashByNumber(uint(4)).Return(common.Hash{4}, nil)
84+
mockBlockAPI.EXPECT().HasJustification(common.Hash{4}).Return(true, nil)
85+
mockBlockAPI.EXPECT().GetJustification(common.Hash{4}).Return([]byte(`justification`), nil)
86+
return mockBlockAPI
87+
},
88+
request: &ProveFinalityRequest{
89+
BlockNumber: 4,
11990
},
120-
exp: ProveFinalityResponse(nil),
91+
exp: ProveFinalityResponse{common.BytesToHex([]byte(`justification`))},
12192
},
12293
}
123-
for _, tt := range tests {
124-
t.Run(tt.name, func(t *testing.T) {
94+
for name, tt := range tests {
95+
tt := tt
96+
t.Run(name, func(t *testing.T) {
97+
t.Parallel()
98+
ctrl := gomock.NewController(t)
12599
gm := &GrandpaModule{
126-
blockAPI: tt.fields.blockAPI,
127-
blockFinalityAPI: tt.fields.blockFinalityAPI,
100+
blockAPI: tt.blockAPIBuilder(ctrl),
128101
}
129102
res := ProveFinalityResponse(nil)
130-
err := gm.ProveFinality(tt.args.r, tt.args.req, &res)
103+
err := gm.ProveFinality(nil, tt.request, &res)
104+
assert.Equal(t, tt.exp, res)
131105
if tt.expErr != nil {
132-
assert.EqualError(t, err, tt.expErr.Error())
106+
assert.ErrorContains(t, err, tt.expErr.Error())
133107
} else {
134108
assert.NoError(t, err)
135109
}
136-
assert.Equal(t, tt.exp, res)
137110
})
138111
}
139112
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2021 ChainSafe Systems (ON)
2+
// SPDX-License-Identifier: LGPL-3.0-only
3+
4+
package modules
5+
6+
//go:generate mockgen -destination=mocks_test.go -package=$GOPACKAGE . BlockAPI

0 commit comments

Comments
 (0)