Skip to content

Commit da8a240

Browse files
authored
Grandpa Prove Finality RPC (#1379)
1 parent cae3e8c commit da8a240

File tree

15 files changed

+159
-6
lines changed

15 files changed

+159
-6
lines changed

chain/gssmr/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ nomdns = false
3333
enabled = false
3434
port = 8545
3535
host = "localhost"
36-
modules = ["system", "author", "chain", "state", "rpc"]
36+
modules = ["system", "author", "chain", "state", "rpc", "grandpa"]
3737
ws-port = 8546

chain/gssmr/defaults.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ var (
7979
// DefaultRPCHTTPPort rpc port
8080
DefaultRPCHTTPPort = uint32(8545)
8181
// DefaultRPCModules rpc modules
82-
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc"}
82+
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa"}
8383
// DefaultRPCWSPort rpc websocket port
8484
DefaultRPCWSPort = uint32(8546)
8585
)

chain/ksmcc/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ enabled = false
3434
external = false
3535
port = 8545
3636
host = "localhost"
37-
modules = ["system", "author", "chain", "state", "rpc"]
37+
modules = ["system", "author", "chain", "state", "rpc", "grandpa"]
3838
ws-port = 8546
3939
ws = false
4040
ws-external = false

chain/ksmcc/defaults.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ var (
7575
// DefaultRPCHTTPPort rpc port
7676
DefaultRPCHTTPPort = uint32(8545)
7777
// DefaultRPCModules rpc modules
78-
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc"}
78+
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa"}
7979
// DefaultRPCWSPort rpc websocket port
8080
DefaultRPCWSPort = uint32(8546)
8181
)

chain/polkadot/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ nomdns = false
3333
enabled = false
3434
port = 8545
3535
host = "localhost"
36-
modules = ["system", "author", "chain", "state", "rpc"]
36+
modules = ["system", "author", "chain", "state", "rpc", "grandpa"]
3737
ws-port = 8546

chain/polkadot/defaults.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ var (
7979
// DefaultRPCHTTPPort rpc port
8080
DefaultRPCHTTPPort = uint32(8545)
8181
// DefaultRPCModules rpc modules
82-
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc"}
82+
DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa"}
8383
// DefaultRPCWSPort rpc websocket port
8484
DefaultRPCWSPort = uint32(8546)
8585
)

dot/rpc/http.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ func (h *HTTPServer) RegisterModules(mods []string) {
109109
srvc = modules.NewAuthorModule(h.logger, h.serverConfig.CoreAPI, h.serverConfig.RuntimeAPI, h.serverConfig.TransactionQueueAPI)
110110
case "chain":
111111
srvc = modules.NewChainModule(h.serverConfig.BlockAPI)
112+
case "grandpa":
113+
srvc = modules.NewGrandpaModule(h.serverConfig.BlockAPI)
112114
case "state":
113115
srvc = modules.NewStateModule(h.serverConfig.NetworkAPI, h.serverConfig.StorageAPI, h.serverConfig.CoreAPI)
114116
case "rpc":

dot/rpc/modules/api.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ type BlockAPI interface {
2929
GetBlockByHash(hash common.Hash) (*types.Block, error)
3030
GetBlockHash(blockNumber *big.Int) (*common.Hash, error)
3131
GetFinalizedHash(uint64, uint64) (common.Hash, error)
32+
HasJustification(hash common.Hash) (bool, error)
33+
GetJustification(hash common.Hash) ([]byte, error)
3234
RegisterImportedChannel(ch chan<- *types.Block) (byte, error)
3335
UnregisterImportedChannel(id byte)
3436
RegisterFinalizedChannel(ch chan<- *types.Header) (byte, error)
3537
UnregisterFinalizedChannel(id byte)
38+
SubChain(start, end common.Hash) ([]common.Hash, error)
3639
}
3740

3841
// NetworkAPI interface for network state methods

dot/rpc/modules/dev.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the gossamer library. If not, see <http://www.gnu.org/licenses/>.
16+
1617
package modules
1718

1819
import (

dot/rpc/modules/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the gossamer library. If not, see <http://www.gnu.org/licenses/>.
16+
1617
package modules
1718

1819
import "errors"

dot/rpc/modules/grandpa.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2020 ChainSafe Systems (ON) Corp.
2+
// This file is part of gossamer.
3+
//
4+
// The gossamer library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The gossamer library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the gossamer library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package modules
18+
19+
import (
20+
"net/http"
21+
22+
"github.com/ChainSafe/gossamer/lib/common"
23+
)
24+
25+
// GrandpaModule init parameters
26+
type GrandpaModule struct {
27+
blockAPI BlockAPI
28+
}
29+
30+
// NewGrandpaModule creates a new Grandpa rpc module.
31+
func NewGrandpaModule(api BlockAPI) *GrandpaModule {
32+
return &GrandpaModule{
33+
blockAPI: api,
34+
}
35+
}
36+
37+
// ProveFinalityRequest request struct
38+
type ProveFinalityRequest struct {
39+
blockHashStart common.Hash
40+
blockHashEnd common.Hash
41+
authorityID uint64
42+
}
43+
44+
// ProveFinalityResponse is an optional SCALE encoded proof array
45+
type ProveFinalityResponse [][]byte
46+
47+
// ProveFinality for the provided block range. Returns NULL if there are no known finalized blocks in the range. If no authorities set is provided, the current one will be attempted.
48+
func (gm *GrandpaModule) ProveFinality(r *http.Request, req *ProveFinalityRequest, res *ProveFinalityResponse) error {
49+
blocksToCheck, err := gm.blockAPI.SubChain(req.blockHashStart, req.blockHashEnd)
50+
if err != nil {
51+
return err
52+
}
53+
54+
// Leaving check in for linter
55+
if req.authorityID != uint64(0) {
56+
// TODO: #1404 Check if functionality relevant
57+
}
58+
59+
for _, block := range blocksToCheck {
60+
hasJustification, _ := gm.blockAPI.HasJustification(block)
61+
if !hasJustification {
62+
continue
63+
}
64+
65+
justification, err := gm.blockAPI.GetJustification(block)
66+
if err != nil {
67+
continue
68+
}
69+
*res = append(*res, justification)
70+
}
71+
72+
return nil
73+
}

dot/rpc/modules/grandpa_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2020 ChainSafe Systems (ON) Corp.
2+
// This file is part of gossamer.
3+
//
4+
// The gossamer library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The gossamer library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the gossamer library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package modules
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
"github.com/ChainSafe/gossamer/dot/state"
24+
)
25+
26+
func TestGrandpaProveFinality(t *testing.T) {
27+
testStateService := newTestStateService(t)
28+
29+
state.AddBlocksToState(t, testStateService.Block, 3)
30+
bestBlock, err := testStateService.Block.BestBlock()
31+
32+
if err != nil {
33+
t.Errorf("Fail: bestblock failed")
34+
}
35+
36+
gmSvc := NewGrandpaModule(testStateService.Block)
37+
38+
testStateService.Block.SetJustification(bestBlock.Header.ParentHash, make([]byte, 10))
39+
testStateService.Block.SetJustification(bestBlock.Header.Hash(), make([]byte, 11))
40+
41+
var expectedResponse ProveFinalityResponse
42+
expectedResponse = append(expectedResponse, make([]byte, 10), make([]byte, 11))
43+
44+
res := new(ProveFinalityResponse)
45+
err = gmSvc.ProveFinality(nil, &ProveFinalityRequest{
46+
blockHashStart: bestBlock.Header.ParentHash,
47+
blockHashEnd: bestBlock.Header.Hash(),
48+
}, res)
49+
50+
if err != nil {
51+
t.Fatal(err)
52+
}
53+
54+
if !reflect.DeepEqual(*res, expectedResponse) {
55+
t.Errorf("Fail: expected: %+v got: %+v\n", res, &expectedResponse)
56+
}
57+
}

dot/rpc/modules/rpc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the gossamer library. If not, see <http://www.gnu.org/licenses/>.
16+
1617
package modules
1718

1819
import "net/http"

dot/rpc/websocket_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@ func (m *MockBlockAPI) RegisterFinalizedChannel(ch chan<- *types.Header) (byte,
120120
}
121121
func (m *MockBlockAPI) UnregisterFinalizedChannel(id byte) {}
122122

123+
func (m *MockBlockAPI) GetJustification(hash common.Hash) ([]byte, error) {
124+
return make([]byte, 10), nil
125+
}
126+
127+
func (m *MockBlockAPI) HasJustification(hash common.Hash) (bool, error) {
128+
return true, nil
129+
}
130+
131+
func (m *MockBlockAPI) SubChain(start, end common.Hash) ([]common.Hash, error) {
132+
return make([]common.Hash, 0), nil
133+
}
134+
123135
type MockStorageAPI struct{}
124136

125137
func (m *MockStorageAPI) GetStorage(_ *common.Hash, key []byte) ([]byte, error) {

tests/utils/rpc_methods.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,7 @@ var (
3333

3434
// DEV METHODS
3535
DevControl = "dev_control"
36+
37+
// GRANDPA
38+
GrandpaProveFinality = "grandpa_proveFinality"
3639
)

0 commit comments

Comments
 (0)