forked from prysmaticlabs/prysm
/
node.go
137 lines (126 loc) · 3.73 KB
/
node.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package evaluators
import (
"bytes"
"context"
"fmt"
ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/endtoend/types"
"google.golang.org/grpc"
)
// PeersConnect checks all beacon nodes and returns whether they are connected to each other as peers.
var PeersConnect = types.Evaluator{
Name: "peers_connect_epoch_%d",
Policy: onEpoch(0),
Evaluation: peersConnect,
}
// FinishedSyncing returns whether the beacon node with the given rpc port has finished syncing.
var FinishedSyncing = types.Evaluator{
Name: "finished_syncing",
Policy: func(currentEpoch uint64) bool { return true },
Evaluation: finishedSyncing,
}
// AllNodesHaveSameHead ensures all nodes have the same head epoch. Checks finality and justification as well.
// Not checking head block root as it may change irregularly for the validator connected nodes.
var AllNodesHaveSameHead = types.Evaluator{
Name: "all_nodes_have_same_head",
Policy: func(currentEpoch uint64) bool { return true },
Evaluation: allNodesHaveSameHead,
}
func onEpoch(epoch uint64) func(uint64) bool {
return func(currentEpoch uint64) bool {
return currentEpoch == epoch
}
}
func peersConnect(conns ...*grpc.ClientConn) error {
if len(conns) == 1 {
return nil
}
ctx := context.Background()
for _, conn := range conns {
nodeClient := eth.NewNodeClient(conn)
peersResp, err := nodeClient.ListPeers(ctx, &ptypes.Empty{})
if err != nil {
return err
}
expectedPeers := len(conns) - 1
if expectedPeers != len(peersResp.Peers) {
return fmt.Errorf("unexpected amount of peers, expected %d, received %d", expectedPeers, len(peersResp.Peers))
}
}
return nil
}
func finishedSyncing(conns ...*grpc.ClientConn) error {
conn := conns[0]
syncNodeClient := eth.NewNodeClient(conn)
syncStatus, err := syncNodeClient.GetSyncStatus(context.Background(), &ptypes.Empty{})
if err != nil {
return err
}
if syncStatus.Syncing {
return errors.New("expected node to have completed sync")
}
return nil
}
func allNodesHaveSameHead(conns ...*grpc.ClientConn) error {
headEpochs := make([]uint64, len(conns))
justifiedRoots := make([][]byte, len(conns))
prevJustifiedRoots := make([][]byte, len(conns))
finalizedRoots := make([][]byte, len(conns))
for i, conn := range conns {
beaconClient := eth.NewBeaconChainClient(conn)
chainHead, err := beaconClient.GetChainHead(context.Background(), &ptypes.Empty{})
if err != nil {
return err
}
headEpochs[i] = chainHead.HeadEpoch
justifiedRoots[i] = chainHead.JustifiedBlockRoot
prevJustifiedRoots[i] = chainHead.PreviousJustifiedBlockRoot
finalizedRoots[i] = chainHead.FinalizedBlockRoot
if err := conn.Close(); err != nil {
return err
}
}
for i, epoch := range headEpochs {
if headEpochs[0] != epoch {
return fmt.Errorf(
"received conflicting head epochs on node %d, expected %d, received %d",
i,
headEpochs[0],
epoch,
)
}
}
for i, root := range justifiedRoots {
if !bytes.Equal(justifiedRoots[0], root) {
return fmt.Errorf(
"received conflicting justified block roots on node %d, expected %#x, received %#x",
i,
justifiedRoots[0],
root,
)
}
}
for i, root := range prevJustifiedRoots {
if !bytes.Equal(prevJustifiedRoots[0], root) {
return fmt.Errorf(
"received conflicting previous justified block roots on node %d, expected %#x, received %#x",
i,
prevJustifiedRoots[0],
root,
)
}
}
for i, root := range finalizedRoots {
if !bytes.Equal(finalizedRoots[0], root) {
return fmt.Errorf(
"received conflicting finalized epoch roots on node %d, expected %#x, received %#x",
i,
finalizedRoots[0],
root,
)
}
}
return nil
}