mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Restore forkchoice dump endpoint. (#11312)
* Restore forkchoice dump endpoint. Only working on doubly-linked-tree. * unit test * revert proto changes * protoarray * Deepsource * shut up! Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -18,6 +18,7 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -612,3 +612,52 @@ func (f *ForkChoice) JustifiedPayloadBlockHash() [32]byte {
|
||||
}
|
||||
return node.payloadHash
|
||||
}
|
||||
|
||||
// ForkchoiceDump returns a full dump of forkhoice.
|
||||
func (f *ForkChoice) ForkChoiceDump(ctx context.Context) (*ethpb.ForkChoiceResponse, error) {
|
||||
jc := ðpb.Checkpoint{
|
||||
Epoch: f.store.justifiedCheckpoint.Epoch,
|
||||
Root: f.store.justifiedCheckpoint.Root[:],
|
||||
}
|
||||
bjc := ðpb.Checkpoint{
|
||||
Epoch: f.store.bestJustifiedCheckpoint.Epoch,
|
||||
Root: f.store.bestJustifiedCheckpoint.Root[:],
|
||||
}
|
||||
ujc := ðpb.Checkpoint{
|
||||
Epoch: f.store.unrealizedJustifiedCheckpoint.Epoch,
|
||||
Root: f.store.unrealizedJustifiedCheckpoint.Root[:],
|
||||
}
|
||||
fc := ðpb.Checkpoint{
|
||||
Epoch: f.store.finalizedCheckpoint.Epoch,
|
||||
Root: f.store.finalizedCheckpoint.Root[:],
|
||||
}
|
||||
ufc := ðpb.Checkpoint{
|
||||
Epoch: f.store.unrealizedFinalizedCheckpoint.Epoch,
|
||||
Root: f.store.unrealizedFinalizedCheckpoint.Root[:],
|
||||
}
|
||||
nodes := make([]*ethpb.ForkChoiceNode, 0, f.NodeCount())
|
||||
var err error
|
||||
if f.store.treeRootNode != nil {
|
||||
nodes, err = f.store.treeRootNode.nodeTreeDump(ctx, nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var headRoot [32]byte
|
||||
if f.store.headNode != nil {
|
||||
headRoot = f.store.headNode.root
|
||||
}
|
||||
resp := ðpb.ForkChoiceResponse{
|
||||
JustifiedCheckpoint: jc,
|
||||
BestJustifiedCheckpoint: bjc,
|
||||
UnrealizedJustifiedCheckpoint: ujc,
|
||||
FinalizedCheckpoint: fc,
|
||||
UnrealizedFinalizedCheckpoint: ufc,
|
||||
ProposerBoostRoot: f.store.proposerBoostRoot[:],
|
||||
PreviousProposerBoostRoot: f.store.previousProposerBoostRoot[:],
|
||||
HeadRoot: headRoot[:],
|
||||
ForkchoiceNodes: nodes,
|
||||
}
|
||||
return resp, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// depth returns the length of the path to the root of Fork Choice
|
||||
@@ -126,3 +127,37 @@ func (n *Node) setNodeAndParentValidated(ctx context.Context) error {
|
||||
}
|
||||
return n.parent.setNodeAndParentValidated(ctx)
|
||||
}
|
||||
|
||||
// nodeTreeDump appends to the given list all the nodes descending from this one
|
||||
func (n *Node) nodeTreeDump(ctx context.Context, nodes []*ethpb.ForkChoiceNode) ([]*ethpb.ForkChoiceNode, error) {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
var parentRoot [32]byte
|
||||
if n.parent != nil {
|
||||
parentRoot = n.parent.root
|
||||
}
|
||||
thisNode := ðpb.ForkChoiceNode{
|
||||
Slot: n.slot,
|
||||
Root: n.root[:],
|
||||
ParentRoot: parentRoot[:],
|
||||
JustifiedEpoch: n.justifiedEpoch,
|
||||
FinalizedEpoch: n.finalizedEpoch,
|
||||
UnrealizedJustifiedEpoch: n.unrealizedJustifiedEpoch,
|
||||
UnrealizedFinalizedEpoch: n.unrealizedFinalizedEpoch,
|
||||
Balance: n.balance,
|
||||
Weight: n.weight,
|
||||
ExecutionOptimistic: n.optimistic,
|
||||
ExecutionPayload: n.payloadHash[:],
|
||||
}
|
||||
|
||||
nodes = append(nodes, thisNode)
|
||||
var err error
|
||||
for _, child := range n.children {
|
||||
nodes, err = child.nodeTreeDump(ctx, nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
)
|
||||
@@ -206,6 +207,8 @@ func TestNode_LeadsToViableHead(t *testing.T) {
|
||||
func TestNode_SetFullyValidated(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
storeNodes := make([]*Node, 6)
|
||||
storeNodes[0] = f.store.treeRootNode
|
||||
// insert blocks in the fork pattern (optimistic status in parenthesis)
|
||||
//
|
||||
// 0 (false) -- 1 (false) -- 2 (false) -- 3 (true) -- 4 (true)
|
||||
@@ -215,20 +218,25 @@ func TestNode_SetFullyValidated(t *testing.T) {
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
storeNodes[1] = f.store.nodeByRoot[blkRoot]
|
||||
require.NoError(t, f.SetOptimisticToValid(ctx, params.BeaconConfig().ZeroHash))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
storeNodes[2] = f.store.nodeByRoot[blkRoot]
|
||||
require.NoError(t, f.SetOptimisticToValid(ctx, indexToHash(1)))
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
storeNodes[3] = f.store.nodeByRoot[blkRoot]
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
storeNodes[4] = f.store.nodeByRoot[blkRoot]
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
storeNodes[5] = f.store.nodeByRoot[blkRoot]
|
||||
|
||||
opt, err := f.IsOptimistic(indexToHash(5))
|
||||
require.NoError(t, err)
|
||||
@@ -253,4 +261,21 @@ func TestNode_SetFullyValidated(t *testing.T) {
|
||||
opt, err = f.IsOptimistic(indexToHash(3))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, opt)
|
||||
|
||||
respNodes := make([]*ethpb.ForkChoiceNode, 0)
|
||||
respNodes, err = f.store.treeRootNode.nodeTreeDump(ctx, respNodes)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(respNodes), f.NodeCount())
|
||||
|
||||
for i, respNode := range respNodes {
|
||||
require.Equal(t, storeNodes[i].slot, respNode.Slot)
|
||||
require.DeepEqual(t, storeNodes[i].root[:], respNode.Root)
|
||||
require.Equal(t, storeNodes[i].balance, respNode.Balance)
|
||||
require.Equal(t, storeNodes[i].weight, respNode.Weight)
|
||||
require.Equal(t, storeNodes[i].optimistic, respNode.ExecutionOptimistic)
|
||||
require.Equal(t, storeNodes[i].justifiedEpoch, respNode.JustifiedEpoch)
|
||||
require.Equal(t, storeNodes[i].unrealizedJustifiedEpoch, respNode.UnrealizedJustifiedEpoch)
|
||||
require.Equal(t, storeNodes[i].finalizedEpoch, respNode.FinalizedEpoch)
|
||||
require.Equal(t, storeNodes[i].unrealizedFinalizedEpoch, respNode.UnrealizedFinalizedEpoch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// ForkChoicer represents the full fork choice interface composed of all the sub-interfaces.
|
||||
@@ -62,6 +63,7 @@ type Getter interface {
|
||||
NodeCount() int
|
||||
HighestReceivedBlockSlot() types.Slot
|
||||
ReceivedBlocksLastEpoch() (uint64, error)
|
||||
ForkChoiceDump(context.Context) (*ethpb.ForkChoiceResponse, error)
|
||||
}
|
||||
|
||||
// Setter allows to set forkchoice information
|
||||
|
||||
@@ -1079,3 +1079,7 @@ func (f *ForkChoice) ReceivedBlocksLastEpoch() (uint64, error) {
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (*ForkChoice) ForkChoiceDump(_ context.Context) (*ethpb.ForkChoiceResponse, error) {
|
||||
return nil, errors.New("ForkChoiceDump is not supported by protoarray")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"block.go",
|
||||
"forkchoice.go",
|
||||
"p2p.go",
|
||||
"server.go",
|
||||
"state.go",
|
||||
@@ -38,6 +39,7 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"block_test.go",
|
||||
"forkchoice_test.go",
|
||||
"p2p_test.go",
|
||||
"state_test.go",
|
||||
],
|
||||
@@ -46,6 +48,8 @@ go_test(
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/forkchoice/types:go_default_library",
|
||||
"//beacon-chain/p2p/testing:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/state/stategen/mock:go_default_library",
|
||||
|
||||
13
beacon-chain/rpc/prysm/v1alpha1/debug/forkchoice.go
Normal file
13
beacon-chain/rpc/prysm/v1alpha1/debug/forkchoice.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// GetForkChoice returns a dump fork choice store.
|
||||
func (ds *Server) GetForkChoice(ctx context.Context, _ *empty.Empty) (*pbrpc.ForkChoiceResponse, error) {
|
||||
return ds.ForkFetcher.ForkChoicer().ForkChoiceDump(ctx)
|
||||
}
|
||||
28
beacon-chain/rpc/prysm/v1alpha1/debug/forkchoice_test.go
Normal file
28
beacon-chain/rpc/prysm/v1alpha1/debug/forkchoice_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/types"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
)
|
||||
|
||||
func TestServer_GetForkChoice(t *testing.T) {
|
||||
store := doublylinkedtree.New()
|
||||
fRoot := [32]byte{'a'}
|
||||
jRoot := [32]byte{'b'}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 2, Root: fRoot}
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 3, Root: jRoot}
|
||||
require.NoError(t, store.UpdateFinalizedCheckpoint(fc))
|
||||
require.NoError(t, store.UpdateJustifiedCheckpoint(jc))
|
||||
bs := &Server{ForkFetcher: &mock.ChainService{ForkChoiceStore: store}}
|
||||
res, err := bs.GetForkChoice(context.Background(), &empty.Empty{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Epoch(3), res.JustifiedCheckpoint.Epoch, "Did not get wanted justified epoch")
|
||||
require.Equal(t, types.Epoch(2), res.FinalizedCheckpoint.Epoch, "Did not get wanted finalized epoch")
|
||||
}
|
||||
@@ -28,6 +28,7 @@ type Server struct {
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
StateGen *stategen.State
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
PeerManager p2p.PeerManager
|
||||
PeersFetcher p2p.PeersProvider
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
|
||||
@@ -336,6 +336,7 @@ func (s *Service) Start() {
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
StateGen: s.cfg.StateGen,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
ReplayerBuilder: ch,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: ad51a4b973de342442a318504b01cb08f7a593b3fbf85ba975661d30f9fab45b
|
||||
// Hash: 63cd476809ef83858e4cec3d59394a44f6ca0b3d7f00ad5a1307cb4bcbf8f1e1
|
||||
package v1
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 963b5caa78ce8e108d0839e5e6555aef3b6ae2f0deae5b5eac6b47a36683506c
|
||||
// Hash: ae3cb8e10550566178c17ab0fda3b1391784159840f50d8dee9e66f45e4c3041
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
883
proto/prysm/v1alpha1/debug.pb.go
generated
883
proto/prysm/v1alpha1/debug.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import "proto/prysm/v1alpha1/node.proto";
|
||||
import "proto/prysm/v1alpha1/p2p_messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "proto/prysm/v1alpha1/attestation.proto";
|
||||
|
||||
option csharp_namespace = "Ethereum.Eth.V1alpha1";
|
||||
option go_package = "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1;eth";
|
||||
@@ -97,6 +98,54 @@ message LoggingLevelRequest {
|
||||
Level level = 1;
|
||||
}
|
||||
|
||||
message ForkChoiceResponse {
|
||||
// Latest justified checkpoint in forkchoice store.
|
||||
Checkpoint justified_checkpoint = 1;
|
||||
// Latest finalized checkpoint in forkchoice store.
|
||||
Checkpoint finalized_checkpoint = 2;
|
||||
// Best justified checkpoint in forkchoice store.
|
||||
Checkpoint best_justified_checkpoint = 3;
|
||||
// Unrealized justified checkpoint in forkchoice store.
|
||||
Checkpoint unrealized_justified_checkpoint = 4;
|
||||
// Unrealized finalized checkpoint in forkchoice store.
|
||||
Checkpoint unrealized_finalized_checkpoint = 5;
|
||||
// Proposer Boost Root in forkchoice store.
|
||||
bytes proposer_boost_root = 6 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
// Previous proposer Boost Root in forkchoice store.
|
||||
bytes previous_proposer_boost_root = 7 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
// Head root in forkchoice store.
|
||||
bytes head_root = 8 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
|
||||
// The list of the forkchoice nodes in store.
|
||||
repeated ForkChoiceNode forkchoice_nodes = 9;
|
||||
}
|
||||
|
||||
message ForkChoiceNode {
|
||||
// Slot of the forkchoice node.
|
||||
uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.Slot"];
|
||||
// Root of the forkchoice node.
|
||||
bytes root = 2 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
// Parent root of the forkchoice node.
|
||||
bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
// Justified epoch of the current forkchoice node.
|
||||
uint64 justified_epoch = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.Epoch"];
|
||||
// finalized epoch of the current forkchoice node.
|
||||
uint64 finalized_epoch = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.Epoch"];
|
||||
// Unrealized justified epoch of the current forkchoice node.
|
||||
uint64 unrealized_justified_epoch = 6 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.Epoch"];
|
||||
// Unrealized finalized epoch of the current forkchoice node.
|
||||
uint64 unrealized_finalized_epoch = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives.Epoch"];
|
||||
// Current balance of the current forkchoice node.
|
||||
uint64 balance = 8;
|
||||
// Current weight of the current forkchoice node.
|
||||
uint64 weight = 9;
|
||||
// Optimistic status of the current forkchoice node.
|
||||
bool execution_optimistic = 10;
|
||||
// Execution payload block hash of the current forkchoice node.
|
||||
bytes execution_payload = 11 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
}
|
||||
|
||||
|
||||
message DebugPeerResponses {
|
||||
repeated DebugPeerResponse responses = 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 5e2a4b9f444ea4a724365be701c6d0b8e40c0d4c5cd2d7dd9f9fddad02c8928d
|
||||
// Hash: 069828a9448f866cb491192b13a4ab076a2510e07c3fa8031de0507240bd6bb5
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
Reference in New Issue
Block a user