Skip to content

Commit 382b02d

Browse files
authored
Merge pull request #1113 from amalrajmani/ibft-clique-status-apis
Add new RPC APIs for IBFT and Clique status
2 parents f5d2182 + 80ced23 commit 382b02d

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

consensus/clique/api.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
package clique
1818

1919
import (
20+
"errors"
21+
"fmt"
22+
2023
"github.com/ethereum/go-ethereum/common"
2124
"github.com/ethereum/go-ethereum/consensus"
2225
"github.com/ethereum/go-ethereum/core/types"
@@ -117,3 +120,88 @@ func (api *API) Discard(address common.Address) {
117120

118121
delete(api.clique.proposals, address)
119122
}
123+
124+
type Status struct {
125+
InturnPercent float64 `json:"inturnPercent"`
126+
SigningStatus map[common.Address]int `json:"sealerActivity"`
127+
NumBlocks uint64 `json:"numBlocks"`
128+
}
129+
130+
// Status returns the status of the last N blocks,
131+
// - the number of active signers,
132+
// - the number of signers,
133+
// - the percentage of in-turn blocks
134+
func (api *API) Status(startBlockNum *rpc.BlockNumber, endBlockNum *rpc.BlockNumber) (*Status, error) {
135+
var (
136+
numBlocks uint64
137+
header *types.Header
138+
diff = uint64(0)
139+
optimals = 0
140+
141+
start uint64
142+
end uint64
143+
)
144+
if startBlockNum != nil && endBlockNum == nil {
145+
return nil, errors.New("pass the end block number")
146+
}
147+
148+
if startBlockNum == nil && endBlockNum != nil {
149+
return nil, errors.New("pass the start block number")
150+
}
151+
152+
if startBlockNum == nil && endBlockNum == nil {
153+
numBlocks = uint64(64)
154+
header = api.chain.CurrentHeader()
155+
end = header.Number.Uint64()
156+
start = end - numBlocks
157+
} else {
158+
end = uint64(*endBlockNum)
159+
start = uint64(*startBlockNum)
160+
if start > end {
161+
return nil, errors.New("start block number should be less than end block number")
162+
}
163+
164+
if end > api.chain.CurrentHeader().Number.Uint64() {
165+
return nil, errors.New("end block number should be less than or equal to current block height")
166+
}
167+
168+
numBlocks = end - start
169+
header = api.chain.GetHeaderByNumber(end)
170+
}
171+
172+
snap, err := api.clique.snapshot(api.chain, end, header.Hash(), nil)
173+
if err != nil {
174+
return nil, err
175+
}
176+
var (
177+
signers = snap.signers()
178+
)
179+
if numBlocks > end {
180+
start = 1
181+
numBlocks = end - start
182+
}
183+
signStatus := make(map[common.Address]int)
184+
for _, s := range signers {
185+
signStatus[s] = 0
186+
}
187+
for n := start; n < end; n++ {
188+
h := api.chain.GetHeaderByNumber(n)
189+
if h == nil {
190+
return nil, fmt.Errorf("missing block %d", n)
191+
}
192+
if h.Difficulty.Cmp(diffInTurn) == 0 {
193+
optimals++
194+
}
195+
diff += h.Difficulty.Uint64()
196+
sealer, err := api.clique.Author(h)
197+
if err != nil {
198+
return nil, err
199+
}
200+
signStatus[sealer]++
201+
}
202+
return &Status{
203+
InturnPercent: float64((100 * optimals)) / float64(numBlocks),
204+
SigningStatus: signStatus,
205+
NumBlocks: numBlocks,
206+
}, nil
207+
}

consensus/istanbul/backend/api.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package backend
1818

1919
import (
20+
"errors"
21+
2022
"github.com/ethereum/go-ethereum/common"
2123
"github.com/ethereum/go-ethereum/consensus"
2224
"github.com/ethereum/go-ethereum/core/types"
@@ -37,6 +39,11 @@ type BlockSigners struct {
3739
Committers []common.Address
3840
}
3941

42+
type Status struct {
43+
SigningStatus map[common.Address]int `json:"sealerActivity"`
44+
NumBlocks uint64 `json:"numBlocks"`
45+
}
46+
4047
// NodeAddress returns the public address that is used to sign block headers in IBFT
4148
func (api *API) NodeAddress() common.Address {
4249
return api.istanbul.Address()
@@ -176,3 +183,90 @@ func (api *API) Discard(address common.Address) {
176183

177184
delete(api.istanbul.candidates, address)
178185
}
186+
187+
func (api *API) Status(startBlockNum *rpc.BlockNumber, endBlockNum *rpc.BlockNumber) (*Status, error) {
188+
var (
189+
numBlocks uint64
190+
header = api.chain.CurrentHeader()
191+
start uint64
192+
end uint64
193+
blockNumber rpc.BlockNumber
194+
)
195+
if startBlockNum != nil && endBlockNum == nil {
196+
return nil, errors.New("pass the end block number")
197+
}
198+
199+
if startBlockNum == nil && endBlockNum != nil {
200+
return nil, errors.New("pass the start block number")
201+
}
202+
203+
if startBlockNum == nil && endBlockNum == nil {
204+
numBlocks = uint64(64)
205+
header = api.chain.CurrentHeader()
206+
end = header.Number.Uint64()
207+
start = end - numBlocks
208+
blockNumber = rpc.BlockNumber(header.Number.Int64())
209+
} else {
210+
end = uint64(*endBlockNum)
211+
start = uint64(*startBlockNum)
212+
if start > end {
213+
return nil, errors.New("start block number should be less than end block number")
214+
}
215+
216+
if end > api.chain.CurrentHeader().Number.Uint64() {
217+
return nil, errors.New("end block number should be less than or equal to current block height")
218+
}
219+
220+
numBlocks = end - start
221+
header = api.chain.GetHeaderByNumber(end)
222+
blockNumber = rpc.BlockNumber(end)
223+
}
224+
225+
signers, err := api.GetValidators(&blockNumber)
226+
227+
if err != nil {
228+
return nil, err
229+
}
230+
231+
if numBlocks >= end {
232+
start = 1
233+
if end > start {
234+
numBlocks = end - start
235+
} else {
236+
numBlocks = 0
237+
}
238+
}
239+
signStatus := make(map[common.Address]int)
240+
for _, s := range signers {
241+
signStatus[s] = 0
242+
}
243+
244+
for n := start; n < end; n++ {
245+
blockNum := rpc.BlockNumber(int64(n))
246+
s, _ := api.GetSignersFromBlock(&blockNum)
247+
signStatus[s.Author]++
248+
249+
}
250+
return &Status{
251+
SigningStatus: signStatus,
252+
NumBlocks: numBlocks,
253+
}, nil
254+
}
255+
256+
func (api *API) IsValidator(blockNum *rpc.BlockNumber) (bool, error) {
257+
var blockNumber rpc.BlockNumber
258+
if blockNum != nil {
259+
blockNumber = *blockNum
260+
} else {
261+
header := api.chain.CurrentHeader()
262+
blockNumber = rpc.BlockNumber(header.Number.Int64())
263+
}
264+
s, _ := api.GetValidators(&blockNumber)
265+
266+
for _, v := range s {
267+
if v == api.istanbul.address {
268+
return true, nil
269+
}
270+
}
271+
return false, nil
272+
}

internal/web3ext/web3ext.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ web3._extend({
107107
call: 'clique_discard',
108108
params: 1
109109
}),
110+
new web3._extend.Method({
111+
name: 'status',
112+
call: 'clique_status',
113+
params: 2,
114+
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter]
115+
}),
110116
],
111117
properties: [
112118
new web3._extend.Property({
@@ -1045,6 +1051,19 @@ web3._extend({
10451051
call: 'istanbul_getSignersFromBlockByHash',
10461052
params: 1
10471053
}),
1054+
new web3._extend.Method({
1055+
name: 'status',
1056+
call: 'istanbul_status',
1057+
params: 2,
1058+
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter]
1059+
}),
1060+
new web3._extend.Method({
1061+
name: 'isValidator',
1062+
call: 'istanbul_isValidator',
1063+
params: 1,
1064+
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
1065+
}),
1066+
10481067
],
10491068
properties:
10501069
[

0 commit comments

Comments
 (0)