mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
3 Commits
rc5
...
v4.0.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cb46eb29a | ||
|
|
abe9e7fa7e | ||
|
|
3536669a70 |
10
WORKSPACE
10
WORKSPACE
@@ -205,7 +205,7 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.3.0-rc.4"
|
||||
consensus_spec_version = "v1.3.0-rc.5"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -221,7 +221,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "519da3cbb181fe927e41b0d13c3aaad5f5f38fe0ba87ca51bd09a661c738bd6c",
|
||||
sha256 = "266006512e71e62396e8f31be01639560c9d59a93c38220fd8f51fabefc8f5f3",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -237,7 +237,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "894404302d3d4b0f3080d3221204c19de4e837f1b129f468a66747103174412e",
|
||||
sha256 = "2ebf483830165909cb7961562fd369dedf079997a4832cc215a543898a73aa46",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -253,7 +253,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "ca7a594a2f4be1103e01b5a1416f75a328b7555eae8b26308c07f80fa6d0f255",
|
||||
sha256 = "333718ba5c907e0a99580caa8d28dd710543b3b271e4251581006d0e101fbce9",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -268,7 +268,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "b4ed6c077c5f0857361412515b319fc8b26730c7d701d3245b5e6849b3974a4f",
|
||||
sha256 = "78b6925b5a4208e32385fa4387d2c27b381a8ddd18d66d5a7787e7846b86bfc8",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -28,6 +28,15 @@ type ChainInfoFetcher interface {
|
||||
CanonicalFetcher
|
||||
ForkFetcher
|
||||
HeadDomainFetcher
|
||||
ForkchoiceFetcher
|
||||
}
|
||||
|
||||
// ForkchoiceFetcher defines a common interface for methods that access directly
|
||||
// forkchoice information. These typically require a lock and external callers
|
||||
// are requested to call methods within this blockchain package that takes care
|
||||
// of locking forkchoice
|
||||
type ForkchoiceFetcher interface {
|
||||
Ancestor(context.Context, []byte, primitives.Slot) ([]byte, error)
|
||||
}
|
||||
|
||||
// HeadUpdater defines a common interface for methods in blockchain service
|
||||
@@ -436,6 +445,41 @@ func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool,
|
||||
return !isCanonical, nil
|
||||
}
|
||||
|
||||
// Ancestor returns the block root of an ancestry block from the input block root.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
// def get_ancestor(store: Store, root: Root, slot: Slot) -> Root:
|
||||
// block = store.blocks[root]
|
||||
// if block.slot > slot:
|
||||
// return get_ancestor(store, block.parent_root, slot)
|
||||
// elif block.slot == slot:
|
||||
// return root
|
||||
// else:
|
||||
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot
|
||||
// return root
|
||||
func (s *Service) Ancestor(ctx context.Context, root []byte, slot primitives.Slot) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestor")
|
||||
defer span.End()
|
||||
|
||||
r := bytesutil.ToBytes32(root)
|
||||
// Get ancestor root from fork choice store instead of recursively looking up blocks in DB.
|
||||
// This is most optimal outcome.
|
||||
s.ForkChoicer().RLock()
|
||||
ar, err := s.cfg.ForkChoiceStore.AncestorRoot(ctx, r, slot)
|
||||
s.ForkChoicer().RUnlock()
|
||||
if err != nil {
|
||||
// Try getting ancestor root from DB when failed to retrieve from fork choice store.
|
||||
// This is the second line of defense for retrieving ancestor root.
|
||||
ar, err = s.ancestorByDB(ctx, r, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ar[:], nil
|
||||
}
|
||||
|
||||
// SetGenesisTime sets the genesis time of beacon chain.
|
||||
func (s *Service) SetGenesisTime(t time.Time) {
|
||||
s.genesisTime = t
|
||||
|
||||
@@ -146,39 +146,6 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// ancestor returns the block root of an ancestry block from the input block root.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
// def get_ancestor(store: Store, root: Root, slot: Slot) -> Root:
|
||||
// block = store.blocks[root]
|
||||
// if block.slot > slot:
|
||||
// return get_ancestor(store, block.parent_root, slot)
|
||||
// elif block.slot == slot:
|
||||
// return root
|
||||
// else:
|
||||
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot
|
||||
// return root
|
||||
func (s *Service) ancestor(ctx context.Context, root []byte, slot primitives.Slot) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestor")
|
||||
defer span.End()
|
||||
|
||||
r := bytesutil.ToBytes32(root)
|
||||
// Get ancestor root from fork choice store instead of recursively looking up blocks in DB.
|
||||
// This is most optimal outcome.
|
||||
ar, err := s.cfg.ForkChoiceStore.AncestorRoot(ctx, r, slot)
|
||||
if err != nil {
|
||||
// Try getting ancestor root from DB when failed to retrieve from fork choice store.
|
||||
// This is the second line of defense for retrieving ancestor root.
|
||||
ar, err = s.ancestorByDB(ctx, r, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ar[:], nil
|
||||
}
|
||||
|
||||
// This retrieves an ancestor root using DB. The look up is recursively looking up DB. Slower than `ancestorByForkChoiceStore`.
|
||||
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot primitives.Slot) (root [32]byte, err error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByDB")
|
||||
|
||||
@@ -600,14 +600,14 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
||||
}
|
||||
|
||||
// Slots 100 to 200 are skip slots. Requesting root at 150 will yield root at 100. The last physical block.
|
||||
r, err := service.ancestor(context.Background(), r200[:], 150)
|
||||
r, err := service.Ancestor(context.Background(), r200[:], 150)
|
||||
require.NoError(t, err)
|
||||
if bytesutil.ToBytes32(r) != r100 {
|
||||
t.Error("Did not get correct root")
|
||||
}
|
||||
|
||||
// Slots 1 to 100 are skip slots. Requesting root at 50 will yield root at 1. The last physical block.
|
||||
r, err = service.ancestor(context.Background(), r200[:], 50)
|
||||
r, err = service.Ancestor(context.Background(), r200[:], 50)
|
||||
require.NoError(t, err)
|
||||
if bytesutil.ToBytes32(r) != r1 {
|
||||
t.Error("Did not get correct root")
|
||||
@@ -648,7 +648,7 @@ func TestAncestor_CanUseForkchoice(t *testing.T) {
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot))
|
||||
}
|
||||
|
||||
r, err := service.ancestor(context.Background(), r200[:], 150)
|
||||
r, err := service.Ancestor(context.Background(), r200[:], 150)
|
||||
require.NoError(t, err)
|
||||
if bytesutil.ToBytes32(r) != r100 {
|
||||
t.Error("Did not get correct root")
|
||||
@@ -696,7 +696,7 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot))
|
||||
|
||||
r, err := service.ancestor(context.Background(), r200[:], 150)
|
||||
r, err := service.Ancestor(context.Background(), r200[:], 150)
|
||||
require.NoError(t, err)
|
||||
if bytesutil.ToBytes32(r) != r100 {
|
||||
t.Error("Did not get correct root")
|
||||
|
||||
@@ -56,7 +56,7 @@ func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestat
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r, err := s.ancestor(ctx, a.Data.BeaconBlockRoot, targetSlot)
|
||||
r, err := s.Ancestor(ctx, a.Data.BeaconBlockRoot, targetSlot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ type ChainService struct {
|
||||
ReceiveBlockMockErr error
|
||||
OptimisticCheckRootReceived [32]byte
|
||||
FinalizedRoots map[[32]byte]bool
|
||||
OptimisticRoots map[[32]byte]bool
|
||||
}
|
||||
|
||||
// ForkChoicer mocks the same method in the chain service
|
||||
@@ -74,6 +75,11 @@ func (s *ChainService) ForkChoicer() forkchoice.ForkChoicer {
|
||||
return s.ForkChoiceStore
|
||||
}
|
||||
|
||||
func (s *ChainService) Ancestor(ctx context.Context, root []byte, slot primitives.Slot) ([]byte, error) {
|
||||
r, err := s.ForkChoicer().AncestorRoot(ctx, bytesutil.ToBytes32(root), slot)
|
||||
return r[:], err
|
||||
}
|
||||
|
||||
// StateNotifier mocks the same method in the chain service.
|
||||
func (s *ChainService) StateNotifier() statefeed.Notifier {
|
||||
if s.stateNotifier == nil {
|
||||
@@ -457,7 +463,7 @@ func (s *ChainService) InForkchoice(_ [32]byte) bool {
|
||||
// IsOptimisticForRoot mocks the same method in the chain service.
|
||||
func (s *ChainService) IsOptimisticForRoot(_ context.Context, root [32]byte) (bool, error) {
|
||||
s.OptimisticCheckRootReceived = root
|
||||
return s.Optimistic, nil
|
||||
return s.OptimisticRoots[root], nil
|
||||
}
|
||||
|
||||
// UpdateHead mocks the same method in the chain service.
|
||||
|
||||
@@ -520,8 +520,10 @@ func TestServer_GetBlindedBlock(t *testing.T) {
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -734,8 +736,10 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) {
|
||||
Block: chainBlk,
|
||||
Root: headBlock.BlockRoot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
|
||||
@@ -471,6 +471,9 @@ func TestServer_GetBlockHeader(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -634,6 +637,9 @@ func TestServer_ListBlockHeaders(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(blkContainers[30].BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -1666,6 +1672,9 @@ func TestServer_GetBlockV2(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -1927,6 +1936,9 @@ func TestServer_GetBlockSSZV2(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -2098,6 +2110,9 @@ func TestServer_GetBlockRoot(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
@@ -2494,6 +2509,9 @@ func TestServer_ListBlockAttestations(t *testing.T) {
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
|
||||
Optimistic: true,
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
OptimisticRoots: map[[32]byte]bool{
|
||||
bytesutil.ToBytes32(headBlock.BlockRoot): true,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
|
||||
@@ -71,7 +71,7 @@ func (bs *Server) GetStateRoot(ctx context.Context, req *ethpb.StateRequest) (*e
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
|
||||
}
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -100,7 +100,7 @@ func (bs *Server) GetStateFork(ctx context.Context, req *ethpb.StateRequest) (*e
|
||||
return nil, helpers.PrepareStateFetchGRPCError(err)
|
||||
}
|
||||
fork := st.Fork()
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (bs *Server) GetFinalityCheckpoints(ctx context.Context, req *ethpb.StateRe
|
||||
if err != nil {
|
||||
return nil, helpers.PrepareStateFetchGRPCError(err)
|
||||
}
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func (bs *Server) GetRandao(ctx context.Context, req *eth2.RandaoRequest) (*eth2
|
||||
return nil, status.Errorf(codes.Internal, "Could not get randao mix at index %d", idx)
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func TestGetStateRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
resp, err := server.GetStateRoot(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -121,7 +121,7 @@ func TestGetStateRoot(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetStateRoot(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -155,7 +155,7 @@ func TestGetStateRoot(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetStateRoot(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -189,7 +189,7 @@ func TestGetStateFork(t *testing.T) {
|
||||
}
|
||||
|
||||
resp, err := server.GetStateFork(ctx, ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -218,7 +218,7 @@ func TestGetStateFork(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetStateFork(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -251,7 +251,7 @@ func TestGetStateFork(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetStateFork(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -292,7 +292,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
|
||||
}
|
||||
|
||||
resp, err := server.GetFinalityCheckpoints(ctx, ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -323,7 +323,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetFinalityCheckpoints(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -356,7 +356,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetFinalityCheckpoints(context.Background(), ð.StateRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -398,17 +398,17 @@ func TestGetRandao(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("no epoch requested", func(t *testing.T) {
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: make([]byte, 0)})
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: []byte("head")})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, mixCurrent, resp.Data.Randao)
|
||||
})
|
||||
t.Run("current epoch requested", func(t *testing.T) {
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: make([]byte, 0), Epoch: &epochCurrent})
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: []byte("head"), Epoch: &epochCurrent})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, mixCurrent, resp.Data.Randao)
|
||||
})
|
||||
t.Run("old epoch requested", func(t *testing.T) {
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: make([]byte, 0), Epoch: &epochOld})
|
||||
resp, err := server.GetRandao(ctx, ð2.RandaoRequest{StateId: []byte("head"), Epoch: &epochOld})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, mixOld, resp.Data.Randao)
|
||||
})
|
||||
@@ -450,7 +450,7 @@ func TestGetRandao(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetRandao(context.Background(), ð2.RandaoRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -482,7 +482,7 @@ func TestGetRandao(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetRandao(context.Background(), ð2.RandaoRequest{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
|
||||
@@ -91,7 +91,7 @@ func (bs *Server) ListSyncCommittees(ctx context.Context, req *ethpbv2.StateSync
|
||||
return nil, status.Errorf(codes.Internal, "Could not extract sync subcommittees: %v", err)
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,8 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
db := dbTest.SetupDB(t)
|
||||
|
||||
chainService := &mock.ChainService{}
|
||||
stSlot := st.Slot()
|
||||
chainService := &mock.ChainService{Slot: &stSlot}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
Genesis: time.Now(),
|
||||
@@ -173,6 +174,7 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
BeaconDB: db,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
req := ðpbv2.StateSyncCommitteesRequest{StateId: stRoot[:]}
|
||||
resp, err := s.ListSyncCommittees(ctx, req)
|
||||
@@ -205,7 +207,8 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
chainService := &mock.ChainService{Optimistic: true}
|
||||
stSlot := st.Slot()
|
||||
chainService := &mock.ChainService{Optimistic: true, Slot: &stSlot}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
Genesis: time.Now(),
|
||||
@@ -217,6 +220,7 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
BeaconDB: db,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
resp, err := s.ListSyncCommittees(ctx, req)
|
||||
require.NoError(t, err)
|
||||
@@ -234,10 +238,12 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
|
||||
headerRoot, err := st.LatestBlockHeader().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
stSlot := st.Slot()
|
||||
chainService := &mock.ChainService{
|
||||
FinalizedRoots: map[[32]byte]bool{
|
||||
headerRoot: true,
|
||||
},
|
||||
Slot: &stSlot,
|
||||
}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
@@ -250,6 +256,7 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
BeaconDB: db,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
resp, err := s.ListSyncCommittees(ctx, req)
|
||||
require.NoError(t, err)
|
||||
@@ -310,7 +317,7 @@ func TestListSyncCommitteesFuture(t *testing.T) {
|
||||
FinalizationFetcher: chainService,
|
||||
BeaconDB: db,
|
||||
}
|
||||
req := ðpbv2.StateSyncCommitteesRequest{}
|
||||
req := ðpbv2.StateSyncCommitteesRequest{StateId: []byte("head")}
|
||||
epoch := 2 * params.BeaconConfig().EpochsPerSyncCommitteePeriod
|
||||
req.Epoch = &epoch
|
||||
_, err := s.ListSyncCommittees(ctx, req)
|
||||
|
||||
@@ -57,7 +57,7 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
|
||||
return nil, status.Error(codes.NotFound, "Could not find validator")
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
|
||||
return nil, handleValContainerErr(err)
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -155,7 +155,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato
|
||||
}
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
@@ -220,7 +220,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
|
||||
}
|
||||
}
|
||||
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.BeaconState
|
||||
if err != nil {
|
||||
return nil, helpers.PrepareStateFetchGRPCError(err)
|
||||
}
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, beaconSt, ds.OptimisticModeFetcher)
|
||||
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, ds.OptimisticModeFetcher, ds.StateFetcher, ds.ChainInfoFetcher, ds.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -55,7 +55,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -73,7 +73,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -91,7 +91,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -117,7 +117,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -150,7 +150,7 @@ func TestGetBeaconStateV2(t *testing.T) {
|
||||
BeaconDB: db,
|
||||
}
|
||||
resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.BeaconStateRequestV2{
|
||||
StateId: make([]byte, 0),
|
||||
StateId: []byte("head"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
@@ -293,7 +293,13 @@ func TestListForkChoiceHeadsV2(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("optimistic head", func(t *testing.T) {
|
||||
chainService := &blockchainmock.ChainService{Optimistic: true}
|
||||
chainService := &blockchainmock.ChainService{
|
||||
Optimistic: true,
|
||||
OptimisticRoots: make(map[[32]byte]bool),
|
||||
}
|
||||
for _, sr := range expectedSlotsAndRoots {
|
||||
chainService.OptimisticRoots[sr.Root] = true
|
||||
}
|
||||
server := &Server{
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
|
||||
@@ -18,4 +18,5 @@ type Server struct {
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
}
|
||||
|
||||
@@ -12,13 +12,16 @@ go_library(
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/rpc/statefetcher:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//status:go_default_library",
|
||||
@@ -35,12 +38,21 @@ go_test(
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/rpc/testutil:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/migration:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/api/grpc"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -53,26 +56,126 @@ func ValidateSync(
|
||||
return status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
// IsOptimistic checks whether the latest block header of the passed in beacon state is the header of an optimistic block.
|
||||
func IsOptimistic(ctx context.Context, st state.BeaconState, optimisticModeFetcher blockchain.OptimisticModeFetcher) (bool, error) {
|
||||
header := st.LatestBlockHeader()
|
||||
// This happens when the block at the state's slot is not missing.
|
||||
if bytes.Equal(header.StateRoot, params.BeaconConfig().ZeroHash[:]) {
|
||||
root, err := st.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not get state root")
|
||||
// IsOptimistic checks whether the beacon state's block is optimistic.
|
||||
func IsOptimistic(
|
||||
ctx context.Context,
|
||||
stateId []byte,
|
||||
optimisticModeFetcher blockchain.OptimisticModeFetcher,
|
||||
stateFetcher statefetcher.Fetcher,
|
||||
chainInfo blockchain.ChainInfoFetcher,
|
||||
database db.ReadOnlyDatabase,
|
||||
) (bool, error) {
|
||||
stateIdString := strings.ToLower(string(stateId))
|
||||
switch stateIdString {
|
||||
case "head":
|
||||
return optimisticModeFetcher.IsOptimistic(ctx)
|
||||
case "genesis":
|
||||
return false, nil
|
||||
case "finalized":
|
||||
fcp := chainInfo.FinalizedCheckpt()
|
||||
if fcp == nil {
|
||||
return true, errors.New("received nil finalized checkpoint")
|
||||
}
|
||||
return optimisticModeFetcher.IsOptimisticForRoot(ctx, bytesutil.ToBytes32(fcp.Root))
|
||||
case "justified":
|
||||
jcp := chainInfo.CurrentJustifiedCheckpt()
|
||||
if jcp == nil {
|
||||
return true, errors.New("received nil justified checkpoint")
|
||||
}
|
||||
return optimisticModeFetcher.IsOptimisticForRoot(ctx, bytesutil.ToBytes32(jcp.Root))
|
||||
default:
|
||||
if len(stateId) == 32 {
|
||||
return isStateRootOptimistic(ctx, stateId, optimisticModeFetcher, stateFetcher, chainInfo, database)
|
||||
} else {
|
||||
optimistic, err := optimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not check optimistic status")
|
||||
}
|
||||
if !optimistic {
|
||||
return false, nil
|
||||
}
|
||||
slotNumber, parseErr := strconv.ParseUint(stateIdString, 10, 64)
|
||||
if parseErr != nil {
|
||||
// ID format does not match any valid options.
|
||||
e := statefetcher.NewStateIdParseError(parseErr)
|
||||
return true, &e
|
||||
}
|
||||
fcp := chainInfo.FinalizedCheckpt()
|
||||
if fcp == nil {
|
||||
return true, errors.New("received nil finalized checkpoint")
|
||||
}
|
||||
finalizedSlot, err := slots.EpochStart(fcp.Epoch)
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not get head state's finalized slot")
|
||||
}
|
||||
lastValidatedCheckpoint, err := database.LastValidatedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not get last validated checkpoint")
|
||||
}
|
||||
validatedSlot, err := slots.EpochStart(lastValidatedCheckpoint.Epoch)
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not get last validated slot")
|
||||
}
|
||||
if primitives.Slot(slotNumber) <= validatedSlot {
|
||||
return false, nil
|
||||
}
|
||||
// if the finalized checkpoint is higher than the last
|
||||
// validated checkpoint, we are syncing and have synced
|
||||
// a finalization being optimistic
|
||||
if validatedSlot < finalizedSlot {
|
||||
return true, nil
|
||||
}
|
||||
if primitives.Slot(slotNumber) == chainInfo.HeadSlot() {
|
||||
// We know the head is optimistic because we checked it above.
|
||||
return true, nil
|
||||
}
|
||||
headRoot, err := chainInfo.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not get head root")
|
||||
}
|
||||
r, err := chainInfo.Ancestor(ctx, headRoot, primitives.Slot(slotNumber))
|
||||
if err != nil {
|
||||
return true, errors.Wrap(err, "could not get ancestor root")
|
||||
}
|
||||
return optimisticModeFetcher.IsOptimisticForRoot(ctx, bytesutil.ToBytes32(r))
|
||||
}
|
||||
header.StateRoot = root[:]
|
||||
}
|
||||
headRoot, err := header.HashTreeRoot()
|
||||
}
|
||||
|
||||
func isStateRootOptimistic(
|
||||
ctx context.Context,
|
||||
stateId []byte,
|
||||
optimisticModeFetcher blockchain.OptimisticModeFetcher,
|
||||
stateFetcher statefetcher.Fetcher,
|
||||
chainInfo blockchain.ChainInfoFetcher,
|
||||
database db.ReadOnlyDatabase,
|
||||
) (bool, error) {
|
||||
st, err := stateFetcher.State(ctx, stateId)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not get header root")
|
||||
return true, errors.Wrap(err, "could not fetch state")
|
||||
}
|
||||
isOptimistic, err := optimisticModeFetcher.IsOptimisticForRoot(ctx, headRoot)
|
||||
if st.Slot() == chainInfo.HeadSlot() {
|
||||
return optimisticModeFetcher.IsOptimistic(ctx)
|
||||
}
|
||||
has, roots, err := database.BlockRootsBySlot(ctx, st.Slot())
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not check if block is optimistic")
|
||||
return true, errors.Wrapf(err, "could not get block roots for slot %d", st.Slot())
|
||||
}
|
||||
return isOptimistic, nil
|
||||
if !has {
|
||||
return true, errors.New("no block roots returned from the database")
|
||||
}
|
||||
for _, r := range roots {
|
||||
b, err := database.Block(ctx, r)
|
||||
if err != nil {
|
||||
return true, errors.Wrapf(err, "could not obtain block")
|
||||
}
|
||||
if bytesutil.ToBytes32(stateId) != b.Block().StateRoot() {
|
||||
continue
|
||||
}
|
||||
return optimisticModeFetcher.IsOptimisticForRoot(ctx, r)
|
||||
}
|
||||
// No block matching requested state root, return true.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SyncDetailsJson contains information about node sync status.
|
||||
|
||||
@@ -2,14 +2,26 @@ package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
grpcutil "github.com/prysmaticlabs/prysm/v4/api/grpc"
|
||||
chainmock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
|
||||
dbtest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
|
||||
syncmock "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/util"
|
||||
@@ -62,44 +74,257 @@ func TestValidateSync(t *testing.T) {
|
||||
|
||||
func TestIsOptimistic(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("optimistic", func(t *testing.T) {
|
||||
mockOptSyncFetcher := &chainmock.ChainService{Optimistic: true}
|
||||
o, err := IsOptimistic(ctx, st, mockOptSyncFetcher)
|
||||
t.Run("head optimistic", func(t *testing.T) {
|
||||
cs := &chainmock.ChainService{Optimistic: true}
|
||||
o, err := IsOptimistic(ctx, []byte("head"), cs, nil, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("not optimistic", func(t *testing.T) {
|
||||
mockOptSyncFetcher := &chainmock.ChainService{Optimistic: false}
|
||||
o, err := IsOptimistic(ctx, st, mockOptSyncFetcher)
|
||||
t.Run("head not optimistic", func(t *testing.T) {
|
||||
cs := &chainmock.ChainService{Optimistic: false}
|
||||
o, err := IsOptimistic(ctx, []byte("head"), cs, nil, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("zero state root", func(t *testing.T) {
|
||||
zeroRootSt, err := util.NewBeaconState()
|
||||
t.Run("genesis", func(t *testing.T) {
|
||||
o, err := IsOptimistic(ctx, []byte("genesis"), nil, nil, nil, nil)
|
||||
require.NoError(t, err)
|
||||
h := zeroRootSt.LatestBlockHeader()
|
||||
h.StateRoot = make([]byte, 32)
|
||||
require.NoError(t, zeroRootSt.SetLatestBlockHeader(h))
|
||||
mockOptSyncFetcher := &chainmock.ChainService{}
|
||||
_, err = IsOptimistic(ctx, st, mockOptSyncFetcher)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(
|
||||
t,
|
||||
[32]byte{0xfc, 0x0, 0xe9, 0x6d, 0xb, 0x8b, 0x2, 0x2f, 0x61, 0xeb, 0x92, 0x10, 0xfd, 0x80, 0x84, 0x2b, 0x26, 0x61, 0xdc, 0x94, 0x5f, 0x7a, 0xf0, 0x0, 0xbc, 0x38, 0x6, 0x38, 0x71, 0x95, 0x43, 0x1},
|
||||
mockOptSyncFetcher.OptimisticCheckRootReceived,
|
||||
)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("non-zero state root", func(t *testing.T) {
|
||||
mockOptSyncFetcher := &chainmock.ChainService{}
|
||||
_, err = IsOptimistic(ctx, st, mockOptSyncFetcher)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(
|
||||
t,
|
||||
[32]byte{0xfc, 0x0, 0xe9, 0x6d, 0xb, 0x8b, 0x2, 0x2f, 0x61, 0xeb, 0x92, 0x10, 0xfd, 0x80, 0x84, 0x2b, 0x26, 0x61, 0xdc, 0x94, 0x5f, 0x7a, 0xf0, 0x0, 0xbc, 0x38, 0x6, 0x38, 0x71, 0x95, 0x43, 0x1},
|
||||
mockOptSyncFetcher.OptimisticCheckRootReceived,
|
||||
)
|
||||
t.Run("finalized", func(t *testing.T) {
|
||||
t.Run("finalized checkpoint is optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: ð.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("finalized checkpoint is not optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: ð.Checkpoint{}}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
})
|
||||
t.Run("justified", func(t *testing.T) {
|
||||
t.Run("justified checkpoint is optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: ð.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("justified checkpoint is not optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: ð.Checkpoint{}}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
})
|
||||
t.Run("root", func(t *testing.T) {
|
||||
t.Run("is head and head is optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: true}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("is head and head is not optimistic", func(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{Optimistic: false}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("root is optimistic", func(t *testing.T) {
|
||||
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
b.SetStateRoot(bytesutil.PadTo([]byte("root"), 32))
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveBlock(ctx, b))
|
||||
fetcherSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
chainSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
|
||||
bRoot, err := b.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
cs := &chainmock.ChainService{State: chainSt, OptimisticRoots: map[[32]byte]bool{bRoot: true}}
|
||||
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
|
||||
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("root is not optimistic", func(t *testing.T) {
|
||||
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
b.SetStateRoot(bytesutil.PadTo([]byte("root"), 32))
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveBlock(ctx, b))
|
||||
fetcherSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
chainSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
|
||||
cs := &chainmock.ChainService{State: chainSt}
|
||||
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
|
||||
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("no canonical blocks", func(t *testing.T) {
|
||||
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveBlock(ctx, b))
|
||||
fetcherSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
chainSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
|
||||
cs := &chainmock.ChainService{Optimistic: false, State: chainSt, CanonicalRoots: map[[32]byte]bool{}}
|
||||
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
|
||||
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), nil, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
})
|
||||
t.Run("slot", func(t *testing.T) {
|
||||
t.Run("head is not optimistic", func(t *testing.T) {
|
||||
cs := &chainmock.ChainService{Optimistic: false}
|
||||
o, err := IsOptimistic(ctx, []byte("0"), cs, nil, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("is before validated slot when head is optimistic", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: ð.Checkpoint{Epoch: 1}}
|
||||
o, err := IsOptimistic(ctx, []byte("0"), cs, nil, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("is equal to validated slot when head is optimistic", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: ð.Checkpoint{Epoch: 1}}
|
||||
o, err := IsOptimistic(ctx, []byte("32"), cs, nil, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
t.Run("is after validated slot and validated slot is before finalized slot", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: ð.Checkpoint{Epoch: 2}}
|
||||
o, err := IsOptimistic(ctx, []byte("33"), cs, nil, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("is head", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
fetcherSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
chainSt, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch*2))
|
||||
cs := &chainmock.ChainService{Optimistic: true, State: chainSt, FinalizedCheckPoint: ð.Checkpoint{Epoch: 0}}
|
||||
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
|
||||
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("ancestor is optimistic", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
r := bytesutil.ToBytes32([]byte("root"))
|
||||
fcs := doublylinkedtree.New()
|
||||
finalizedCheckpt := ð.Checkpoint{Epoch: 0}
|
||||
st, root, err := prepareForkchoiceState(fieldparams.SlotsPerEpoch*2, r, [32]byte{}, [32]byte{}, finalizedCheckpt, finalizedCheckpt)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
headRoot := [32]byte{'r'}
|
||||
st, root, err = prepareForkchoiceState(fieldparams.SlotsPerEpoch*2+1, headRoot, r, [32]byte{}, finalizedCheckpt, finalizedCheckpt)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: true}, FinalizedCheckPoint: finalizedCheckpt}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, o)
|
||||
})
|
||||
t.Run("ancestor is not optimistic", func(t *testing.T) {
|
||||
db := dbtest.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ð.StateSummary{Slot: fieldparams.SlotsPerEpoch, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ð.Checkpoint{Epoch: 1, Root: []byte("root")}))
|
||||
r := bytesutil.ToBytes32([]byte("root"))
|
||||
fcs := doublylinkedtree.New()
|
||||
finalizedCheckpt := ð.Checkpoint{Epoch: 0}
|
||||
st, root, err := prepareForkchoiceState(fieldparams.SlotsPerEpoch*2, r, [32]byte{}, [32]byte{}, finalizedCheckpt, finalizedCheckpt)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
headRoot := [32]byte{'r'}
|
||||
st, root, err = prepareForkchoiceState(fieldparams.SlotsPerEpoch*2+1, headRoot, r, [32]byte{}, finalizedCheckpt, finalizedCheckpt)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: false}, FinalizedCheckPoint: finalizedCheckpt}
|
||||
mf := &testutil.MockFetcher{BeaconState: st}
|
||||
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, o)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// prepareForkchoiceState prepares a beacon state with the given data to mock
|
||||
// insert into forkchoice
|
||||
func prepareForkchoiceState(
|
||||
slot primitives.Slot,
|
||||
blockRoot [32]byte,
|
||||
parentRoot [32]byte,
|
||||
payloadHash [32]byte,
|
||||
justified *eth.Checkpoint,
|
||||
finalized *eth.Checkpoint,
|
||||
) (state.BeaconState, [32]byte, error) {
|
||||
blockHeader := ð.BeaconBlockHeader{
|
||||
ParentRoot: parentRoot[:],
|
||||
}
|
||||
|
||||
executionHeader := &enginev1.ExecutionPayloadHeader{
|
||||
BlockHash: payloadHash[:],
|
||||
}
|
||||
|
||||
base := ð.BeaconStateBellatrix{
|
||||
Slot: slot,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
BlockRoots: make([][]byte, 1),
|
||||
CurrentJustifiedCheckpoint: justified,
|
||||
FinalizedCheckpoint: finalized,
|
||||
LatestExecutionPayloadHeader: executionHeader,
|
||||
LatestBlockHeader: blockHeader,
|
||||
}
|
||||
|
||||
base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...)
|
||||
st, err := state_native.InitializeFromProtoBellatrix(base)
|
||||
return st, blockRoot, err
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
|
||||
@@ -3,6 +3,7 @@ package validator
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
|
||||
@@ -26,4 +27,6 @@ type Server struct {
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
V1Alpha1Server *v1alpha1validator.Server
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
}
|
||||
|
||||
@@ -278,7 +278,14 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
|
||||
return nil, status.Errorf(codes.Internal, "Could not get duties: %v", err)
|
||||
}
|
||||
|
||||
isOptimistic, err := rpchelpers.IsOptimistic(ctx, st, vs.OptimisticModeFetcher)
|
||||
isOptimistic, err := rpchelpers.IsOptimistic(
|
||||
ctx,
|
||||
[]byte(strconv.FormatUint(uint64(slot), 10)),
|
||||
vs.OptimisticModeFetcher,
|
||||
vs.StateFetcher,
|
||||
vs.ChainInfoFetcher,
|
||||
vs.BeaconDB,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
@@ -466,7 +466,6 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
|
||||
}
|
||||
require.NoError(t, st.SetNextSyncCommittee(nextCommittee))
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
mockChainService := &mockChain.ChainService{Genesis: genesisTime}
|
||||
vs := &Server{
|
||||
@@ -636,6 +635,10 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("execution optimistic", func(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
require.NoError(t, db.SaveStateSummary(ctx, ðpbalpha.StateSummary{Slot: 0, Root: []byte("root")}))
|
||||
require.NoError(t, db.SaveLastValidatedCheckpoint(ctx, ðpbalpha.Checkpoint{Epoch: 0, Root: []byte("root")}))
|
||||
|
||||
parentRoot := [32]byte{'a'}
|
||||
blk := util.NewBeaconBlock()
|
||||
blk.Block.ParentRoot = parentRoot[:]
|
||||
@@ -644,16 +647,34 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
mockChainService := &mockChain.ChainService{Genesis: genesisTime, Optimistic: true}
|
||||
slot, err := slots.EpochStart(1)
|
||||
require.NoError(t, err)
|
||||
|
||||
state, err := util.NewBeaconStateBellatrix()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(slot))
|
||||
|
||||
mockChainService := &mockChain.ChainService{
|
||||
Genesis: genesisTime,
|
||||
Optimistic: true,
|
||||
Slot: &slot,
|
||||
FinalizedCheckPoint: ðpbalpha.Checkpoint{
|
||||
Root: root[:],
|
||||
Epoch: 1,
|
||||
},
|
||||
State: state,
|
||||
}
|
||||
vs := &Server{
|
||||
StateFetcher: &testutil.MockFetcher{BeaconState: st},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
HeadFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
ChainInfoFetcher: mockChainService,
|
||||
BeaconDB: db,
|
||||
}
|
||||
req := ðpbv2.SyncCommitteeDutiesRequest{
|
||||
Epoch: 0,
|
||||
Epoch: 1,
|
||||
Index: []primitives.ValidatorIndex{1},
|
||||
}
|
||||
resp, err := vs.GetSyncCommitteeDuties(ctx, req)
|
||||
|
||||
@@ -244,6 +244,8 @@ func (s *Service) Start() {
|
||||
},
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
}
|
||||
|
||||
nodeServer := &nodev1alpha1.Server{
|
||||
@@ -362,6 +364,7 @@ func (s *Service) Start() {
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
}
|
||||
ethpbv1alpha1.RegisterDebugServer(s.grpcServer, debugServer)
|
||||
ethpbservice.RegisterBeaconDebugServer(s.grpcServer, debugServerV1)
|
||||
|
||||
@@ -100,6 +100,7 @@ type blockchainService interface {
|
||||
blockchain.CanonicalFetcher
|
||||
blockchain.OptimisticModeFetcher
|
||||
blockchain.SlashingReceiver
|
||||
blockchain.ForkchoiceFetcher
|
||||
}
|
||||
|
||||
// Service is responsible for handling all run time p2p related operations as the
|
||||
|
||||
@@ -1286,12 +1286,17 @@ func Test_validateBellatrixBeaconBlockParentValidation(t *testing.T) {
|
||||
msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx])
|
||||
require.NoError(t, err)
|
||||
|
||||
blk, err := blocks.NewSignedBeaconBlock(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
chainService := &mock.ChainService{Genesis: time.Unix(int64(beaconState.GenesisTime()), 0),
|
||||
Optimistic: true,
|
||||
OptimisticRoots: make(map[[32]byte]bool),
|
||||
FinalizedCheckPoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
}}
|
||||
|
||||
chainService.OptimisticRoots[blk.Block().ParentRoot()] = true
|
||||
r := &Service{
|
||||
cfg: &config{
|
||||
beaconDB: db,
|
||||
@@ -1304,9 +1309,6 @@ func Test_validateBellatrixBeaconBlockParentValidation(t *testing.T) {
|
||||
seenBlockCache: lruwrpr.New(10),
|
||||
badBlockCache: lruwrpr.New(10),
|
||||
}
|
||||
|
||||
blk, err := blocks.NewSignedBeaconBlock(msg)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "parent of the block is optimistic", r.validateBellatrixBeaconBlock(ctx, beaconState, blk.Block()))
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
BellatrixForkVersion: []byte{2, 0, 0, 0},
|
||||
BellatrixForkEpoch: mainnetBellatrixForkEpoch,
|
||||
CapellaForkVersion: []byte{3, 0, 0, 0},
|
||||
CapellaForkEpoch: math.MaxUint64,
|
||||
CapellaForkEpoch: 194048,
|
||||
|
||||
// New values introduced in Altair hard fork 1.
|
||||
// Participation flag indices.
|
||||
|
||||
Reference in New Issue
Block a user