mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Chain info: Return err if checkpoint is nil (#10729)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain/store"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
@@ -79,9 +81,9 @@ type CanonicalFetcher interface {
|
|||||||
// FinalizationFetcher defines a common interface for methods in blockchain service which
|
// FinalizationFetcher defines a common interface for methods in blockchain service which
|
||||||
// directly retrieve finalization and justification related data.
|
// directly retrieve finalization and justification related data.
|
||||||
type FinalizationFetcher interface {
|
type FinalizationFetcher interface {
|
||||||
FinalizedCheckpt() *ethpb.Checkpoint
|
FinalizedCheckpt() (*ethpb.Checkpoint, error)
|
||||||
CurrentJustifiedCheckpt() *ethpb.Checkpoint
|
CurrentJustifiedCheckpt() (*ethpb.Checkpoint, error)
|
||||||
PreviousJustifiedCheckpt() *ethpb.Checkpoint
|
PreviousJustifiedCheckpt() (*ethpb.Checkpoint, error)
|
||||||
VerifyFinalizedBlkDescendant(ctx context.Context, blockRoot [32]byte) error
|
VerifyFinalizedBlkDescendant(ctx context.Context, blockRoot [32]byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,44 +94,47 @@ type OptimisticModeFetcher interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedCheckpt returns the latest finalized checkpoint from chain store.
|
// FinalizedCheckpt returns the latest finalized checkpoint from chain store.
|
||||||
func (s *Service) FinalizedCheckpt() *ethpb.Checkpoint {
|
func (s *Service) FinalizedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
cp := s.store.FinalizedCheckpt()
|
cp, err := s.store.FinalizedCheckpt()
|
||||||
if cp == nil {
|
if err != nil {
|
||||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethpb.CopyCheckpoint(cp)
|
return ethpb.CopyCheckpoint(cp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentJustifiedCheckpt returns the current justified checkpoint from chain store.
|
// CurrentJustifiedCheckpt returns the current justified checkpoint from chain store.
|
||||||
func (s *Service) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Service) CurrentJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
cp := s.store.JustifiedCheckpt()
|
cp, err := s.store.JustifiedCheckpt()
|
||||||
if cp == nil {
|
if err != nil {
|
||||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethpb.CopyCheckpoint(cp)
|
return ethpb.CopyCheckpoint(cp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreviousJustifiedCheckpt returns the previous justified checkpoint from chain store.
|
// PreviousJustifiedCheckpt returns the previous justified checkpoint from chain store.
|
||||||
func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Service) PreviousJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
cp := s.store.PrevJustifiedCheckpt()
|
cp, err := s.store.PrevJustifiedCheckpt()
|
||||||
if cp == nil {
|
if err != nil {
|
||||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethpb.CopyCheckpoint(cp)
|
return ethpb.CopyCheckpoint(cp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BestJustifiedCheckpt returns the best justified checkpoint from store.
|
// BestJustifiedCheckpt returns the best justified checkpoint from store.
|
||||||
func (s *Service) BestJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Service) BestJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
cp := s.store.BestJustifiedCheckpt()
|
cp, err := s.store.BestJustifiedCheckpt()
|
||||||
// If there is no best justified checkpoint, return the checkpoint with root as zeros to be used for genesis cases.
|
if err != nil {
|
||||||
if cp == nil {
|
// If there is no best justified checkpoint, return the checkpoint with root as zeros to be used for genesis cases.
|
||||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
if errors.Is(err, store.ErrNilCheckpoint) {
|
||||||
|
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethpb.CopyCheckpoint(cp)
|
return ethpb.CopyCheckpoint(cp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeadSlot returns the slot of the head of the chain.
|
// HeadSlot returns the slot of the head of the chain.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain/store"
|
||||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||||
@@ -26,12 +27,6 @@ var _ ChainInfoFetcher = (*Service)(nil)
|
|||||||
var _ TimeFetcher = (*Service)(nil)
|
var _ TimeFetcher = (*Service)(nil)
|
||||||
var _ ForkFetcher = (*Service)(nil)
|
var _ ForkFetcher = (*Service)(nil)
|
||||||
|
|
||||||
func TestFinalizedCheckpt_Nil(t *testing.T) {
|
|
||||||
beaconDB := testDB.SetupDB(t)
|
|
||||||
c := setupBeaconChain(t, beaconDB)
|
|
||||||
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], c.FinalizedCheckpt().Root, "Incorrect pre chain start value")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeadRoot_Nil(t *testing.T) {
|
func TestHeadRoot_Nil(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
@@ -53,7 +48,9 @@ func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
|
|||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
||||||
|
|
||||||
assert.Equal(t, cp.Epoch, c.FinalizedCheckpt().Epoch, "Unexpected finalized epoch")
|
cp, err := c.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, cp.Epoch, cp.Epoch, "Unexpected finalized epoch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
|
func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
|
||||||
@@ -64,17 +61,22 @@ func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
|
|||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
||||||
c.originBlockRoot = genesisRoot
|
c.originBlockRoot = genesisRoot
|
||||||
assert.DeepEqual(t, c.originBlockRoot[:], c.FinalizedCheckpt().Root)
|
cp, err := c.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.DeepEqual(t, c.originBlockRoot[:], cp.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch")
|
_, err := c.CurrentJustifiedCheckpt()
|
||||||
|
require.ErrorIs(t, err, store.ErrNilCheckpoint)
|
||||||
cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||||
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
||||||
assert.Equal(t, cp.Epoch, c.CurrentJustifiedCheckpt().Epoch, "Unexpected justified epoch")
|
jp, err := c.CurrentJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, cp.Epoch, jp.Epoch, "Unexpected justified epoch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||||
@@ -85,7 +87,9 @@ func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
|||||||
cp := ðpb.Checkpoint{Root: genesisRoot[:]}
|
cp := ðpb.Checkpoint{Root: genesisRoot[:]}
|
||||||
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
||||||
c.originBlockRoot = genesisRoot
|
c.originBlockRoot = genesisRoot
|
||||||
assert.DeepEqual(t, c.originBlockRoot[:], c.CurrentJustifiedCheckpt().Root)
|
cp, err := c.CurrentJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.DeepEqual(t, c.originBlockRoot[:], cp.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
||||||
@@ -93,9 +97,12 @@ func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
cp := ðpb.Checkpoint{Epoch: 7, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
cp := ðpb.Checkpoint{Epoch: 7, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch")
|
_, err := c.PreviousJustifiedCheckpt()
|
||||||
|
require.ErrorIs(t, err, store.ErrNilCheckpoint)
|
||||||
c.store.SetPrevJustifiedCheckpt(cp)
|
c.store.SetPrevJustifiedCheckpt(cp)
|
||||||
assert.Equal(t, cp.Epoch, c.PreviousJustifiedCheckpt().Epoch, "Unexpected previous justified epoch")
|
pcp, err := c.PreviousJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, cp.Epoch, pcp.Epoch, "Unexpected previous justified epoch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||||
@@ -106,7 +113,9 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
|||||||
c := setupBeaconChain(t, beaconDB)
|
c := setupBeaconChain(t, beaconDB)
|
||||||
c.store.SetPrevJustifiedCheckpt(cp)
|
c.store.SetPrevJustifiedCheckpt(cp)
|
||||||
c.originBlockRoot = genesisRoot
|
c.originBlockRoot = genesisRoot
|
||||||
assert.DeepEqual(t, c.originBlockRoot[:], c.PreviousJustifiedCheckpt().Root)
|
pcp, err := c.PreviousJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.DeepEqual(t, c.originBlockRoot[:], pcp.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHeadSlot_CanRetrieve(t *testing.T) {
|
func TestHeadSlot_CanRetrieve(t *testing.T) {
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ package blockchain
|
|||||||
import "github.com/pkg/errors"
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// errNilJustifiedInStore is returned when a nil justified checkpt is returned from store.
|
|
||||||
errNilJustifiedInStore = errors.New("nil justified checkpoint returned from store")
|
|
||||||
// errNilBestJustifiedInStore is returned when a nil justified checkpt is returned from store.
|
|
||||||
errNilBestJustifiedInStore = errors.New("nil best justified checkpoint returned from store")
|
|
||||||
// errNilFinalizedInStore is returned when a nil finalized checkpt is returned from store.
|
// errNilFinalizedInStore is returned when a nil finalized checkpt is returned from store.
|
||||||
errNilFinalizedInStore = errors.New("nil finalized checkpoint returned from store")
|
errNilFinalizedInStore = errors.New("nil finalized checkpoint returned from store")
|
||||||
// errInvalidNilSummary is returned when a nil summary is returned from the DB.
|
// errInvalidNilSummary is returned when a nil summary is returned from the DB.
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ import (
|
|||||||
// UpdateAndSaveHeadWithBalances updates the beacon state head after getting justified balanced from cache.
|
// UpdateAndSaveHeadWithBalances updates the beacon state head after getting justified balanced from cache.
|
||||||
// This function is only used in spec-tests, it does save the head after updating it.
|
// This function is only used in spec-tests, it does save the head after updating it.
|
||||||
func (s *Service) UpdateAndSaveHeadWithBalances(ctx context.Context) error {
|
func (s *Service) UpdateAndSaveHeadWithBalances(ctx context.Context) error {
|
||||||
cp := s.store.JustifiedCheckpt()
|
cp, err := s.store.JustifiedCheckpt()
|
||||||
if cp == nil {
|
if err != nil {
|
||||||
return errors.New("no justified checkpoint")
|
return err
|
||||||
}
|
}
|
||||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(cp.Root))
|
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(cp.Root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -66,13 +66,13 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) ([32]byte,
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
// Get head from the fork choice service.
|
// Get head from the fork choice service.
|
||||||
f := s.store.FinalizedCheckpt()
|
f, err := s.store.FinalizedCheckpt()
|
||||||
if f == nil {
|
if err != nil {
|
||||||
return [32]byte{}, errNilFinalizedInStore
|
return [32]byte{}, errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
j := s.store.JustifiedCheckpt()
|
j, err := s.store.JustifiedCheckpt()
|
||||||
if j == nil {
|
if err != nil {
|
||||||
return [32]byte{}, errNilJustifiedInStore
|
return [32]byte{}, errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
// To get head before the first justified epoch, the fork choice will start with origin root
|
// To get head before the first justified epoch, the fork choice will start with origin root
|
||||||
// instead of zero hashes.
|
// instead of zero hashes.
|
||||||
|
|||||||
@@ -42,17 +42,17 @@ func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update store.justified_checkpoint if a better checkpoint on the store.finalized_checkpoint chain
|
// Update store.justified_checkpoint if a better checkpoint on the store.finalized_checkpoint chain
|
||||||
bj := s.store.BestJustifiedCheckpt()
|
bj, err := s.store.BestJustifiedCheckpt()
|
||||||
if bj == nil {
|
if err != nil {
|
||||||
return errNilBestJustifiedInStore
|
return errors.Wrap(err, "could not get best justified checkpoint")
|
||||||
}
|
}
|
||||||
j := s.store.JustifiedCheckpt()
|
j, err := s.store.JustifiedCheckpt()
|
||||||
if j == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
f := s.store.FinalizedCheckpt()
|
f, err := s.store.FinalizedCheckpt()
|
||||||
if f == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
if bj.Epoch > j.Epoch {
|
if bj.Epoch > j.Epoch {
|
||||||
finalizedSlot, err := slots.EpochStart(f.Epoch)
|
finalizedSlot, err := slots.EpochStart(f.Epoch)
|
||||||
|
|||||||
@@ -103,9 +103,17 @@ func TestService_newSlot(t *testing.T) {
|
|||||||
|
|
||||||
require.NoError(t, service.NewSlot(ctx, test.args.slot))
|
require.NoError(t, service.NewSlot(ctx, test.args.slot))
|
||||||
if test.args.shouldEqual {
|
if test.args.shouldEqual {
|
||||||
require.DeepSSZEqual(t, service.store.BestJustifiedCheckpt(), service.store.JustifiedCheckpt())
|
bcp, err := service.store.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
cp, err := service.store.JustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, bcp, cp)
|
||||||
} else {
|
} else {
|
||||||
require.DeepNotSSZEqual(t, service.store.BestJustifiedCheckpt(), service.store.JustifiedCheckpt())
|
bcp, err := service.store.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
cp, err := service.store.JustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepNotSSZEqual(t, bcp, cp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,9 +176,9 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update justified check point.
|
// Update justified check point.
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
if justified == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
currJustifiedEpoch := justified.Epoch
|
currJustifiedEpoch := justified.Epoch
|
||||||
if postState.CurrentJustifiedCheckpoint().Epoch > currJustifiedEpoch {
|
if postState.CurrentJustifiedCheckpoint().Epoch > currJustifiedEpoch {
|
||||||
@@ -187,7 +187,10 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
|
}
|
||||||
if finalized == nil {
|
if finalized == nil {
|
||||||
return errNilFinalizedInStore
|
return errNilFinalizedInStore
|
||||||
}
|
}
|
||||||
@@ -473,9 +476,9 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
|
|||||||
s.clearInitSyncBlocks()
|
s.clearInitSyncBlocks()
|
||||||
}
|
}
|
||||||
|
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
if justified == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
if jCheckpoint.Epoch > justified.Epoch {
|
if jCheckpoint.Epoch > justified.Epoch {
|
||||||
if err := s.updateJustifiedInitSync(ctx, jCheckpoint); err != nil {
|
if err := s.updateJustifiedInitSync(ctx, jCheckpoint); err != nil {
|
||||||
@@ -483,7 +486,10 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
|
}
|
||||||
if finalized == nil {
|
if finalized == nil {
|
||||||
return errNilFinalizedInStore
|
return errNilFinalizedInStore
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b interfaces.BeaconBloc
|
|||||||
func (s *Service) VerifyFinalizedBlkDescendant(ctx context.Context, root [32]byte) error {
|
func (s *Service) VerifyFinalizedBlkDescendant(ctx context.Context, root [32]byte) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "blockChain.VerifyFinalizedBlkDescendant")
|
ctx, span := trace.StartSpan(ctx, "blockChain.VerifyFinalizedBlkDescendant")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
if finalized == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||||
finalizedBlkSigned, err := s.getBlock(ctx, fRoot)
|
finalizedBlkSigned, err := s.getBlock(ctx, fRoot)
|
||||||
@@ -123,9 +123,9 @@ func (s *Service) VerifyFinalizedBlkDescendant(ctx context.Context, root [32]byt
|
|||||||
// verifyBlkFinalizedSlot validates input block is not less than or equal
|
// verifyBlkFinalizedSlot validates input block is not less than or equal
|
||||||
// to current finalized slot.
|
// to current finalized slot.
|
||||||
func (s *Service) verifyBlkFinalizedSlot(b interfaces.BeaconBlock) error {
|
func (s *Service) verifyBlkFinalizedSlot(b interfaces.BeaconBlock) error {
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
if finalized == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
finalizedSlot, err := slots.EpochStart(finalized.Epoch)
|
finalizedSlot, err := slots.EpochStart(finalized.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -166,7 +166,10 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
|||||||
if slots.SinceEpochStarts(s.CurrentSlot()) < params.BeaconConfig().SafeSlotsToUpdateJustified {
|
if slots.SinceEpochStarts(s.CurrentSlot()) < params.BeaconConfig().SafeSlotsToUpdateJustified {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "could not get justified checkpoint")
|
||||||
|
}
|
||||||
jSlot, err := slots.EpochStart(justified.Epoch)
|
jSlot, err := slots.EpochStart(justified.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -188,9 +191,9 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
cpt := state.CurrentJustifiedCheckpoint()
|
cpt := state.CurrentJustifiedCheckpoint()
|
||||||
bestJustified := s.store.BestJustifiedCheckpt()
|
bestJustified, err := s.store.BestJustifiedCheckpt()
|
||||||
if bestJustified == nil {
|
if err != nil {
|
||||||
return errNilBestJustifiedInStore
|
return errors.Wrap(err, "could not get best justified checkpoint")
|
||||||
}
|
}
|
||||||
if cpt.Epoch > bestJustified.Epoch {
|
if cpt.Epoch > bestJustified.Epoch {
|
||||||
s.store.SetBestJustifiedCheckpt(cpt)
|
s.store.SetBestJustifiedCheckpt(cpt)
|
||||||
@@ -201,9 +204,9 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
|||||||
}
|
}
|
||||||
|
|
||||||
if canUpdate {
|
if canUpdate {
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
if justified == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
s.store.SetPrevJustifiedCheckpt(justified)
|
s.store.SetPrevJustifiedCheckpt(justified)
|
||||||
h, err := s.getPayloadHash(ctx, cpt.Root)
|
h, err := s.getPayloadHash(ctx, cpt.Root)
|
||||||
@@ -220,9 +223,9 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
|||||||
// caches justified checkpoint balances for fork choice and save justified checkpoint in DB.
|
// caches justified checkpoint balances for fork choice and save justified checkpoint in DB.
|
||||||
// This method does not have defense against fork choice bouncing attack, which is why it's only recommend to be used during initial syncing.
|
// This method does not have defense against fork choice bouncing attack, which is why it's only recommend to be used during initial syncing.
|
||||||
func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpoint) error {
|
func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpoint) error {
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
if justified == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
}
|
}
|
||||||
s.store.SetPrevJustifiedCheckpt(justified)
|
s.store.SetPrevJustifiedCheckpt(justified)
|
||||||
|
|
||||||
@@ -345,9 +348,9 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
|||||||
parentRoot := bytesutil.ToBytes32(blk.ParentRoot())
|
parentRoot := bytesutil.ToBytes32(blk.ParentRoot())
|
||||||
slot := blk.Slot()
|
slot := blk.Slot()
|
||||||
// Fork choice only matters from last finalized slot.
|
// Fork choice only matters from last finalized slot.
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
if finalized == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return err
|
||||||
}
|
}
|
||||||
fSlot, err := slots.EpochStart(finalized.Epoch)
|
fSlot, err := slots.EpochStart(finalized.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -709,13 +709,17 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
|||||||
require.NoError(t, s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: r[:]}))
|
require.NoError(t, s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: r[:]}))
|
||||||
require.NoError(t, service.updateJustified(context.Background(), s))
|
require.NoError(t, service.updateJustified(context.Background(), s))
|
||||||
|
|
||||||
assert.Equal(t, s.CurrentJustifiedCheckpoint().Epoch, service.store.BestJustifiedCheckpt().Epoch, "Incorrect justified epoch in service")
|
cp, err := service.store.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, s.CurrentJustifiedCheckpoint().Epoch, cp.Epoch, "Incorrect justified epoch in service")
|
||||||
|
|
||||||
// Could not update
|
// Could not update
|
||||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}, Epoch: 2})
|
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}, Epoch: 2})
|
||||||
require.NoError(t, service.updateJustified(context.Background(), s))
|
require.NoError(t, service.updateJustified(context.Background(), s))
|
||||||
|
|
||||||
assert.Equal(t, types.Epoch(2), service.store.BestJustifiedCheckpt().Epoch, "Incorrect justified epoch in service")
|
cp, err = service.store.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, types.Epoch(2), cp.Epoch, "Incorrect justified epoch in service")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
||||||
@@ -1394,9 +1398,13 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
|||||||
|
|
||||||
require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
|
require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
|
||||||
|
|
||||||
assert.DeepSSZEqual(t, currentCp, service.PreviousJustifiedCheckpt(), "Incorrect previous justified checkpoint")
|
cp, err := service.PreviousJustifiedCheckpt()
|
||||||
assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
|
require.NoError(t, err)
|
||||||
cp, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
|
assert.DeepSSZEqual(t, currentCp, cp, "Incorrect previous justified checkpoint")
|
||||||
|
cp, err = service.CurrentJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in cache")
|
||||||
|
cp, err = service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
|
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
|
||||||
}
|
}
|
||||||
@@ -1464,16 +1472,24 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
|||||||
testState, err = service.cfg.StateGen.StateByRoot(ctx, r)
|
testState, err = service.cfg.StateGen.StateByRoot(ctx, r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch)
|
cp, err := service.CurrentJustifiedCheckpt()
|
||||||
require.Equal(t, types.Epoch(2), service.FinalizedCheckpt().Epoch)
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, types.Epoch(3), cp.Epoch)
|
||||||
|
cp, err = service.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, types.Epoch(2), cp.Epoch)
|
||||||
|
|
||||||
// The update should persist in DB.
|
// The update should persist in DB.
|
||||||
j, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
|
j, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, j.Epoch, service.CurrentJustifiedCheckpt().Epoch)
|
cp, err = service.CurrentJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, j.Epoch, cp.Epoch)
|
||||||
f, err := service.cfg.BeaconDB.FinalizedCheckpoint(ctx)
|
f, err := service.cfg.BeaconDB.FinalizedCheckpoint(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, f.Epoch, service.FinalizedCheckpt().Epoch)
|
cp, err = service.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, f.Epoch, cp.Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOnBlock_NilBlock(t *testing.T) {
|
func TestOnBlock_NilBlock(t *testing.T) {
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
f := s.FinalizedCheckpt()
|
f, err := s.FinalizedCheckpt()
|
||||||
if f == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return err
|
||||||
}
|
}
|
||||||
ss, err := slots.EpochStart(f.Epoch)
|
ss, err := slots.EpochStart(f.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,9 +152,9 @@ func (s *Service) UpdateHead(ctx context.Context) error {
|
|||||||
|
|
||||||
s.processAttestations(ctx)
|
s.processAttestations(ctx)
|
||||||
|
|
||||||
justified := s.store.JustifiedCheckpt()
|
justified, err := s.store.JustifiedCheckpt()
|
||||||
if justified == nil {
|
if err != nil {
|
||||||
return errNilJustifiedInStore
|
return err
|
||||||
}
|
}
|
||||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaco
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reports on block and fork choice metrics.
|
// Reports on block and fork choice metrics.
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
if finalized == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
||||||
|
|
||||||
@@ -106,9 +106,9 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Reports on blockCopy and fork choice metrics.
|
// Reports on blockCopy and fork choice metrics.
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
if finalized == nil {
|
if err != nil {
|
||||||
return errNilFinalizedInStore
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
}
|
}
|
||||||
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,10 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig
|
|||||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
|
}
|
||||||
if finalized == nil {
|
if finalized == nil {
|
||||||
return errNilFinalizedInStore
|
return errNilFinalizedInStore
|
||||||
}
|
}
|
||||||
@@ -169,7 +172,10 @@ func (s *Service) checkSaveHotStateDB(ctx context.Context) error {
|
|||||||
currentEpoch := slots.ToEpoch(s.CurrentSlot())
|
currentEpoch := slots.ToEpoch(s.CurrentSlot())
|
||||||
// Prevent `sinceFinality` going underflow.
|
// Prevent `sinceFinality` going underflow.
|
||||||
var sinceFinality types.Epoch
|
var sinceFinality types.Epoch
|
||||||
finalized := s.store.FinalizedCheckpt()
|
finalized, err := s.store.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if finalized == nil {
|
if finalized == nil {
|
||||||
return errNilFinalizedInStore
|
return errNilFinalizedInStore
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -277,8 +277,12 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
|
|||||||
// Test the start function.
|
// Test the start function.
|
||||||
chainService.Start()
|
chainService.Start()
|
||||||
|
|
||||||
require.DeepEqual(t, blkRoot[:], chainService.store.FinalizedCheckpt().Root, "Finalize Checkpoint root is incorrect")
|
cp, err := chainService.store.FinalizedCheckpt()
|
||||||
require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], chainService.store.JustifiedCheckpt().Root, "Justified Checkpoint root is incorrect")
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, blkRoot[:], cp.Root, "Finalize Checkpoint root is incorrect")
|
||||||
|
cp, err = chainService.store.JustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], cp.Root, "Justified Checkpoint root is incorrect")
|
||||||
|
|
||||||
require.NoError(t, chainService.Stop(), "Unable to stop chain service")
|
require.NoError(t, chainService.Stop(), "Unable to stop chain service")
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ go_library(
|
|||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/store",
|
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/store",
|
||||||
visibility = ["//beacon-chain:__subpackages__"],
|
visibility = ["//beacon-chain:__subpackages__"],
|
||||||
deps = ["//proto/prysm/v1alpha1:go_default_library"],
|
deps = [
|
||||||
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
|
"@com_github_pkg_errors//:go_default_library",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
|
|||||||
@@ -17,9 +17,19 @@ func TestNew(t *testing.T) {
|
|||||||
Root: []byte("hello"),
|
Root: []byte("hello"),
|
||||||
}
|
}
|
||||||
s := New(j, f)
|
s := New(j, f)
|
||||||
require.DeepSSZEqual(t, s.JustifiedCheckpt(), j)
|
cp, err := s.JustifiedCheckpt()
|
||||||
require.DeepSSZEqual(t, s.BestJustifiedCheckpt(), j)
|
require.NoError(t, err)
|
||||||
require.DeepSSZEqual(t, s.PrevJustifiedCheckpt(), j)
|
require.DeepSSZEqual(t, j, cp)
|
||||||
require.DeepSSZEqual(t, s.FinalizedCheckpt(), f)
|
cp, err = s.BestJustifiedCheckpt()
|
||||||
require.DeepSSZEqual(t, s.PrevFinalizedCheckpt(), f)
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, j, cp)
|
||||||
|
cp, err = s.PrevJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, j, cp)
|
||||||
|
cp, err = s.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, f, cp)
|
||||||
|
cp, err = s.PrevFinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, f, cp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,42 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNilCheckpoint = errors.New("nil checkpoint")
|
||||||
|
)
|
||||||
|
|
||||||
// PrevJustifiedCheckpt returns the previous justified checkpoint in the Store.
|
// PrevJustifiedCheckpt returns the previous justified checkpoint in the Store.
|
||||||
func (s *Store) PrevJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Store) PrevJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.prevJustifiedCheckpt
|
if s.prevJustifiedCheckpt == nil {
|
||||||
|
return nil, ErrNilCheckpoint
|
||||||
|
}
|
||||||
|
return s.prevJustifiedCheckpt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BestJustifiedCheckpt returns the best justified checkpoint in the Store.
|
// BestJustifiedCheckpt returns the best justified checkpoint in the Store.
|
||||||
func (s *Store) BestJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Store) BestJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.bestJustifiedCheckpt
|
if s.bestJustifiedCheckpt == nil {
|
||||||
|
return nil, ErrNilCheckpoint
|
||||||
|
}
|
||||||
|
return s.bestJustifiedCheckpt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JustifiedCheckpt returns the justified checkpoint in the Store.
|
// JustifiedCheckpt returns the justified checkpoint in the Store.
|
||||||
func (s *Store) JustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *Store) JustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.justifiedCheckpt
|
if s.justifiedCheckpt == nil {
|
||||||
|
return nil, ErrNilCheckpoint
|
||||||
|
}
|
||||||
|
return s.justifiedCheckpt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JustifiedPayloadBlockHash returns the justified payload block hash reflecting justified check point.
|
// JustifiedPayloadBlockHash returns the justified payload block hash reflecting justified check point.
|
||||||
@@ -31,17 +47,23 @@ func (s *Store) JustifiedPayloadBlockHash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PrevFinalizedCheckpt returns the previous finalized checkpoint in the Store.
|
// PrevFinalizedCheckpt returns the previous finalized checkpoint in the Store.
|
||||||
func (s *Store) PrevFinalizedCheckpt() *ethpb.Checkpoint {
|
func (s *Store) PrevFinalizedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.prevFinalizedCheckpt
|
if s.prevFinalizedCheckpt == nil {
|
||||||
|
return nil, ErrNilCheckpoint
|
||||||
|
}
|
||||||
|
return s.prevFinalizedCheckpt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedCheckpt returns the finalized checkpoint in the Store.
|
// FinalizedCheckpt returns the finalized checkpoint in the Store.
|
||||||
func (s *Store) FinalizedCheckpt() *ethpb.Checkpoint {
|
func (s *Store) FinalizedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.finalizedCheckpt
|
if s.finalizedCheckpt == nil {
|
||||||
|
return nil, ErrNilCheckpoint
|
||||||
|
}
|
||||||
|
return s.finalizedCheckpt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedPayloadBlockHash returns the finalized payload block hash reflecting finalized check point.
|
// FinalizedPayloadBlockHash returns the finalized payload block hash reflecting finalized check point.
|
||||||
|
|||||||
@@ -10,48 +10,63 @@ import (
|
|||||||
func Test_store_PrevJustifiedCheckpt(t *testing.T) {
|
func Test_store_PrevJustifiedCheckpt(t *testing.T) {
|
||||||
s := &Store{}
|
s := &Store{}
|
||||||
var cp *ethpb.Checkpoint
|
var cp *ethpb.Checkpoint
|
||||||
require.Equal(t, cp, s.PrevJustifiedCheckpt())
|
_, err := s.PrevJustifiedCheckpt()
|
||||||
|
require.ErrorIs(t, ErrNilCheckpoint, err)
|
||||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||||
s.SetPrevJustifiedCheckpt(cp)
|
s.SetPrevJustifiedCheckpt(cp)
|
||||||
require.Equal(t, cp, s.PrevJustifiedCheckpt())
|
got, err := s.PrevJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cp, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_store_BestJustifiedCheckpt(t *testing.T) {
|
func Test_store_BestJustifiedCheckpt(t *testing.T) {
|
||||||
s := &Store{}
|
s := &Store{}
|
||||||
var cp *ethpb.Checkpoint
|
var cp *ethpb.Checkpoint
|
||||||
require.Equal(t, cp, s.BestJustifiedCheckpt())
|
_, err := s.BestJustifiedCheckpt()
|
||||||
|
require.ErrorIs(t, ErrNilCheckpoint, err)
|
||||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||||
s.SetBestJustifiedCheckpt(cp)
|
s.SetBestJustifiedCheckpt(cp)
|
||||||
require.Equal(t, cp, s.BestJustifiedCheckpt())
|
got, err := s.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cp, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_store_JustifiedCheckpt(t *testing.T) {
|
func Test_store_JustifiedCheckpt(t *testing.T) {
|
||||||
s := &Store{}
|
s := &Store{}
|
||||||
var cp *ethpb.Checkpoint
|
var cp *ethpb.Checkpoint
|
||||||
require.Equal(t, cp, s.JustifiedCheckpt())
|
_, err := s.JustifiedCheckpt()
|
||||||
|
require.ErrorIs(t, ErrNilCheckpoint, err)
|
||||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||||
h := [32]byte{'b'}
|
h := [32]byte{'b'}
|
||||||
s.SetJustifiedCheckptAndPayloadHash(cp, h)
|
s.SetJustifiedCheckptAndPayloadHash(cp, h)
|
||||||
require.Equal(t, cp, s.JustifiedCheckpt())
|
got, err := s.JustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cp, got)
|
||||||
require.Equal(t, h, s.JustifiedPayloadBlockHash())
|
require.Equal(t, h, s.JustifiedPayloadBlockHash())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_store_FinalizedCheckpt(t *testing.T) {
|
func Test_store_FinalizedCheckpt(t *testing.T) {
|
||||||
s := &Store{}
|
s := &Store{}
|
||||||
var cp *ethpb.Checkpoint
|
var cp *ethpb.Checkpoint
|
||||||
require.Equal(t, cp, s.FinalizedCheckpt())
|
_, err := s.FinalizedCheckpt()
|
||||||
|
require.ErrorIs(t, ErrNilCheckpoint, err)
|
||||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||||
h := [32]byte{'b'}
|
h := [32]byte{'b'}
|
||||||
s.SetFinalizedCheckptAndPayloadHash(cp, h)
|
s.SetFinalizedCheckptAndPayloadHash(cp, h)
|
||||||
require.Equal(t, cp, s.FinalizedCheckpt())
|
got, err := s.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cp, got)
|
||||||
require.Equal(t, h, s.FinalizedPayloadBlockHash())
|
require.Equal(t, h, s.FinalizedPayloadBlockHash())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_store_PrevFinalizedCheckpt(t *testing.T) {
|
func Test_store_PrevFinalizedCheckpt(t *testing.T) {
|
||||||
s := &Store{}
|
s := &Store{}
|
||||||
var cp *ethpb.Checkpoint
|
var cp *ethpb.Checkpoint
|
||||||
require.Equal(t, cp, s.PrevFinalizedCheckpt())
|
_, err := s.PrevFinalizedCheckpt()
|
||||||
|
require.ErrorIs(t, ErrNilCheckpoint, err)
|
||||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||||
s.SetPrevFinalizedCheckpt(cp)
|
s.SetPrevFinalizedCheckpt(cp)
|
||||||
require.Equal(t, cp, s.PrevFinalizedCheckpt())
|
got, err := s.PrevFinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cp, got)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,18 +282,18 @@ func (s *ChainService) CurrentFork() *ethpb.Fork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedCheckpt mocks FinalizedCheckpt method in chain service.
|
// FinalizedCheckpt mocks FinalizedCheckpt method in chain service.
|
||||||
func (s *ChainService) FinalizedCheckpt() *ethpb.Checkpoint {
|
func (s *ChainService) FinalizedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
return s.FinalizedCheckPoint
|
return s.FinalizedCheckPoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentJustifiedCheckpt mocks CurrentJustifiedCheckpt method in chain service.
|
// CurrentJustifiedCheckpt mocks CurrentJustifiedCheckpt method in chain service.
|
||||||
func (s *ChainService) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *ChainService) CurrentJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
return s.CurrentJustifiedCheckPoint
|
return s.CurrentJustifiedCheckPoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreviousJustifiedCheckpt mocks PreviousJustifiedCheckpt method in chain service.
|
// PreviousJustifiedCheckpt mocks PreviousJustifiedCheckpt method in chain service.
|
||||||
func (s *ChainService) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
func (s *ChainService) PreviousJustifiedCheckpt() (*ethpb.Checkpoint, error) {
|
||||||
return s.PreviousJustifiedCheckPoint
|
return s.PreviousJustifiedCheckPoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiveAttestation mocks ReceiveAttestation method in chain service.
|
// ReceiveAttestation mocks ReceiveAttestation method in chain service.
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
|||||||
wsVerifier: wv,
|
wsVerifier: wv,
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: tt.finalizedEpoch}, [32]byte{})
|
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: tt.finalizedEpoch}, [32]byte{})
|
||||||
err = s.wsVerifier.VerifyWeakSubjectivity(context.Background(), s.store.FinalizedCheckpt().Epoch)
|
cp, err := s.store.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = s.wsVerifier.VerifyWeakSubjectivity(context.Background(), cp.Epoch)
|
||||||
if tt.wantErr == nil {
|
if tt.wantErr == nil {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -574,7 +574,10 @@ func (bs *Server) GetBlockRoot(ctx context.Context, req *ethpbv1.BlockRequest) (
|
|||||||
return nil, status.Errorf(codes.NotFound, "No head root was found")
|
return nil, status.Errorf(codes.NotFound, "No head root was found")
|
||||||
}
|
}
|
||||||
case "finalized":
|
case "finalized":
|
||||||
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
|
finalized, err := bs.ChainInfoFetcher.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not retrieve finalized checkpoint: %v", err)
|
||||||
|
}
|
||||||
root = finalized.Root
|
root = finalized.Root
|
||||||
case "genesis":
|
case "genesis":
|
||||||
blk, err := bs.BeaconDB.GenesisBlock(ctx)
|
blk, err := bs.BeaconDB.GenesisBlock(ctx)
|
||||||
@@ -725,7 +728,10 @@ func (bs *Server) blockFromBlockID(ctx context.Context, blockId []byte) (interfa
|
|||||||
return nil, errors.Wrap(err, "could not retrieve head block")
|
return nil, errors.Wrap(err, "could not retrieve head block")
|
||||||
}
|
}
|
||||||
case "finalized":
|
case "finalized":
|
||||||
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
|
finalized, err := bs.ChainInfoFetcher.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not retrieve finalized checkpoint")
|
||||||
|
}
|
||||||
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
|
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
|
||||||
blk, err = bs.BeaconDB.Block(ctx, finalizedRoot)
|
blk, err = bs.BeaconDB.Block(ctx, finalizedRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -425,17 +425,26 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
finalizedCheckpoint := bs.FinalizationFetcher.FinalizedCheckpt()
|
finalizedCheckpoint, err := bs.FinalizationFetcher.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get finalized checkpoint: %v", err)
|
||||||
|
}
|
||||||
if err := validateCP(finalizedCheckpoint, "finalized"); err != nil {
|
if err := validateCP(finalizedCheckpoint, "finalized"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
justifiedCheckpoint := bs.FinalizationFetcher.CurrentJustifiedCheckpt()
|
justifiedCheckpoint, err := bs.FinalizationFetcher.CurrentJustifiedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if err := validateCP(justifiedCheckpoint, "justified"); err != nil {
|
if err := validateCP(justifiedCheckpoint, "justified"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prevJustifiedCheckpoint := bs.FinalizationFetcher.PreviousJustifiedCheckpt()
|
prevJustifiedCheckpoint, err := bs.FinalizationFetcher.PreviousJustifiedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get previous justified checkpoint: %v", err)
|
||||||
|
}
|
||||||
if err := validateCP(prevJustifiedCheckpoint, "prev justified"); err != nil {
|
if err := validateCP(prevJustifiedCheckpoint, "prev justified"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -540,10 +540,13 @@ func (bs *Server) GetValidatorParticipation(
|
|||||||
default:
|
default:
|
||||||
return nil, status.Errorf(codes.Internal, "Invalid state type retrieved with a version of %d", beaconState.Version())
|
return nil, status.Errorf(codes.Internal, "Invalid state type retrieved with a version of %d", beaconState.Version())
|
||||||
}
|
}
|
||||||
|
cp, err := bs.FinalizationFetcher.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "Could not get finalized checkpoint: %v", err)
|
||||||
|
}
|
||||||
p := ðpb.ValidatorParticipationResponse{
|
p := ðpb.ValidatorParticipationResponse{
|
||||||
Epoch: requestedEpoch,
|
Epoch: requestedEpoch,
|
||||||
Finalized: requestedEpoch <= bs.FinalizationFetcher.FinalizedCheckpt().Epoch,
|
Finalized: requestedEpoch <= cp.Epoch,
|
||||||
Participation: ðpb.ValidatorParticipation{
|
Participation: ðpb.ValidatorParticipation{
|
||||||
// TODO(7130): Remove these three deprecated fields.
|
// TODO(7130): Remove these three deprecated fields.
|
||||||
GlobalParticipationRate: float32(b.PrevEpochTargetAttested) / float32(b.ActivePrevEpoch),
|
GlobalParticipationRate: float32(b.PrevEpochTargetAttested) / float32(b.ActivePrevEpoch),
|
||||||
|
|||||||
@@ -116,13 +116,19 @@ func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.Beacon
|
|||||||
return nil, errors.Wrap(err, "could not get genesis state")
|
return nil, errors.Wrap(err, "could not get genesis state")
|
||||||
}
|
}
|
||||||
case "finalized":
|
case "finalized":
|
||||||
checkpoint := p.ChainInfoFetcher.FinalizedCheckpt()
|
checkpoint, err := p.ChainInfoFetcher.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
|
}
|
||||||
s, err = p.StateGenService.StateByRoot(ctx, bytesutil.ToBytes32(checkpoint.Root))
|
s, err = p.StateGenService.StateByRoot(ctx, bytesutil.ToBytes32(checkpoint.Root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get finalized state")
|
return nil, errors.Wrap(err, "could not get finalized state")
|
||||||
}
|
}
|
||||||
case "justified":
|
case "justified":
|
||||||
checkpoint := p.ChainInfoFetcher.CurrentJustifiedCheckpt()
|
checkpoint, err := p.ChainInfoFetcher.CurrentJustifiedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get justified checkpoint")
|
||||||
|
}
|
||||||
s, err = p.StateGenService.StateByRoot(ctx, bytesutil.ToBytes32(checkpoint.Root))
|
s, err = p.StateGenService.StateByRoot(ctx, bytesutil.ToBytes32(checkpoint.Root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get justified state")
|
return nil, errors.Wrap(err, "could not get justified state")
|
||||||
|
|||||||
@@ -73,7 +73,11 @@ func (f *blocksFetcher) waitForMinimumPeers(ctx context.Context) ([]peer.ID, err
|
|||||||
}
|
}
|
||||||
var peers []peer.ID
|
var peers []peer.ID
|
||||||
if f.mode == modeStopOnFinalizedEpoch {
|
if f.mode == modeStopOnFinalizedEpoch {
|
||||||
headEpoch := f.chain.FinalizedCheckpt().Epoch
|
cp, err := f.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
headEpoch := cp.Epoch
|
||||||
_, peers = f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch)
|
_, peers = f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch)
|
||||||
} else {
|
} else {
|
||||||
headEpoch := slots.ToEpoch(f.chain.HeadSlot())
|
headEpoch := slots.ToEpoch(f.chain.HeadSlot())
|
||||||
|
|||||||
@@ -157,13 +157,17 @@ func (f *blocksFetcher) findFork(ctx context.Context, slot types.Slot) (*forkDat
|
|||||||
|
|
||||||
// The current slot's epoch must be after the finalization epoch,
|
// The current slot's epoch must be after the finalization epoch,
|
||||||
// triggering backtracking on earlier epochs is unnecessary.
|
// triggering backtracking on earlier epochs is unnecessary.
|
||||||
finalizedEpoch := f.chain.FinalizedCheckpt().Epoch
|
cp, err := f.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalizedEpoch := cp.Epoch
|
||||||
epoch := slots.ToEpoch(slot)
|
epoch := slots.ToEpoch(slot)
|
||||||
if epoch <= finalizedEpoch {
|
if epoch <= finalizedEpoch {
|
||||||
return nil, errors.New("slot is not after the finalized epoch, no backtracking is necessary")
|
return nil, errors.New("slot is not after the finalized epoch, no backtracking is necessary")
|
||||||
}
|
}
|
||||||
// Update slot to the beginning of the current epoch (preserve original slot for comparison).
|
// Update slot to the beginning of the current epoch (preserve original slot for comparison).
|
||||||
slot, err := slots.EpochStart(epoch)
|
slot, err = slots.EpochStart(epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -287,8 +291,13 @@ func (f *blocksFetcher) findAncestor(ctx context.Context, pid peer.ID, b interfa
|
|||||||
|
|
||||||
// bestFinalizedSlot returns the highest finalized slot of the majority of connected peers.
|
// bestFinalizedSlot returns the highest finalized slot of the majority of connected peers.
|
||||||
func (f *blocksFetcher) bestFinalizedSlot() types.Slot {
|
func (f *blocksFetcher) bestFinalizedSlot() types.Slot {
|
||||||
|
cp, err := f.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Failed to get finalized checkpoint")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
finalizedEpoch, _ := f.p2p.Peers().BestFinalized(
|
finalizedEpoch, _ := f.p2p.Peers().BestFinalized(
|
||||||
params.BeaconConfig().MaxPeersToSync, f.chain.FinalizedCheckpt().Epoch)
|
params.BeaconConfig().MaxPeersToSync, cp.Epoch)
|
||||||
return params.BeaconConfig().SlotsPerEpoch.Mul(uint64(finalizedEpoch))
|
return params.BeaconConfig().SlotsPerEpoch.Mul(uint64(finalizedEpoch))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +312,12 @@ func (f *blocksFetcher) bestNonFinalizedSlot() types.Slot {
|
|||||||
// epoch. For the latter peers supporting that target epoch are returned as well.
|
// epoch. For the latter peers supporting that target epoch are returned as well.
|
||||||
func (f *blocksFetcher) calculateHeadAndTargetEpochs() (headEpoch, targetEpoch types.Epoch, peers []peer.ID) {
|
func (f *blocksFetcher) calculateHeadAndTargetEpochs() (headEpoch, targetEpoch types.Epoch, peers []peer.ID) {
|
||||||
if f.mode == modeStopOnFinalizedEpoch {
|
if f.mode == modeStopOnFinalizedEpoch {
|
||||||
headEpoch = f.chain.FinalizedCheckpt().Epoch
|
cp, err := f.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Failed to get finalized checkpoint")
|
||||||
|
return 0, 0, peers
|
||||||
|
}
|
||||||
|
headEpoch = cp.Epoch
|
||||||
targetEpoch, peers = f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch)
|
targetEpoch, peers = f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch)
|
||||||
} else {
|
} else {
|
||||||
headEpoch = slots.ToEpoch(f.chain.HeadSlot())
|
headEpoch = slots.ToEpoch(f.chain.HeadSlot())
|
||||||
|
|||||||
@@ -1321,7 +1321,9 @@ func TestBlocksQueue_stuckWhenHeadIsSetToOrphanedBlock(t *testing.T) {
|
|||||||
|
|
||||||
require.NoError(t, queue.start())
|
require.NoError(t, queue.start())
|
||||||
isProcessedBlock := func(ctx context.Context, blk interfaces.SignedBeaconBlock, blkRoot [32]byte) bool {
|
isProcessedBlock := func(ctx context.Context, blk interfaces.SignedBeaconBlock, blkRoot [32]byte) bool {
|
||||||
finalizedSlot, err := slots.EpochStart(mc.FinalizedCheckpt().Epoch)
|
cp, err := mc.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
finalizedSlot, err := slots.EpochStart(cp.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,7 +308,12 @@ func (s *Service) updatePeerScorerStats(pid peer.ID, startSlot types.Slot) {
|
|||||||
|
|
||||||
// isProcessedBlock checks DB and local cache for presence of a given block, to avoid duplicates.
|
// isProcessedBlock checks DB and local cache for presence of a given block, to avoid duplicates.
|
||||||
func (s *Service) isProcessedBlock(ctx context.Context, blk interfaces.SignedBeaconBlock, blkRoot [32]byte) bool {
|
func (s *Service) isProcessedBlock(ctx context.Context, blk interfaces.SignedBeaconBlock, blkRoot [32]byte) bool {
|
||||||
finalizedSlot, err := slots.EpochStart(s.cfg.Chain.FinalizedCheckpt().Epoch)
|
cp, err := s.cfg.Chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("could not get finalized checkpoint: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
finalizedSlot, err := slots.EpochStart(cp.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,12 @@ func (s *Service) waitForMinimumPeers() {
|
|||||||
required = flags.Get().MinimumSyncPeers
|
required = flags.Get().MinimumSyncPeers
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
_, peers := s.cfg.P2P.Peers().BestNonFinalized(flags.Get().MinimumSyncPeers, s.cfg.Chain.FinalizedCheckpt().Epoch)
|
cp, err := s.cfg.Chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Could not retrieve finalized checkpoint")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, peers := s.cfg.P2P.Peers().BestNonFinalized(flags.Get().MinimumSyncPeers, cp.Epoch)
|
||||||
if len(peers) >= required {
|
if len(peers) >= required {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,8 +210,11 @@ func (s *Service) sendBatchRootRequest(ctx context.Context, roots [][32]byte, ra
|
|||||||
if len(roots) == 0 {
|
if len(roots) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
_, bestPeers := s.cfg.p2p.Peers().BestFinalized(maxPeerRequest, s.cfg.chain.FinalizedCheckpt().Epoch)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, bestPeers := s.cfg.p2p.Peers().BestFinalized(maxPeerRequest, cp.Epoch)
|
||||||
if len(bestPeers) == 0 {
|
if len(bestPeers) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -272,7 +275,11 @@ func (s *Service) validatePendingSlots() error {
|
|||||||
defer s.pendingQueueLock.Unlock()
|
defer s.pendingQueueLock.Unlock()
|
||||||
oldBlockRoots := make(map[[32]byte]bool)
|
oldBlockRoots := make(map[[32]byte]bool)
|
||||||
|
|
||||||
finalizedEpoch := s.cfg.chain.FinalizedCheckpt().Epoch
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
finalizedEpoch := cp.Epoch
|
||||||
if s.slotToPendingBlocks == nil {
|
if s.slotToPendingBlocks == nil {
|
||||||
return errors.New("slotToPendingBlocks cache can't be nil")
|
return errors.New("slotToPendingBlocks cache can't be nil")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,10 +131,14 @@ func (s *Service) sendRPCStatusRequest(ctx context.Context, id peer.ID) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
resp := &pb.Status{
|
resp := &pb.Status{
|
||||||
ForkDigest: forkDigest[:],
|
ForkDigest: forkDigest[:],
|
||||||
FinalizedRoot: s.cfg.chain.FinalizedCheckpt().Root,
|
FinalizedRoot: cp.Root,
|
||||||
FinalizedEpoch: s.cfg.chain.FinalizedCheckpt().Epoch,
|
FinalizedEpoch: cp.Epoch,
|
||||||
HeadRoot: headRoot,
|
HeadRoot: headRoot,
|
||||||
HeadSlot: s.cfg.chain.HeadSlot(),
|
HeadSlot: s.cfg.chain.HeadSlot(),
|
||||||
}
|
}
|
||||||
@@ -260,10 +264,14 @@ func (s *Service) respondWithStatus(ctx context.Context, stream network.Stream)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
resp := &pb.Status{
|
resp := &pb.Status{
|
||||||
ForkDigest: forkDigest[:],
|
ForkDigest: forkDigest[:],
|
||||||
FinalizedRoot: s.cfg.chain.FinalizedCheckpt().Root,
|
FinalizedRoot: cp.Root,
|
||||||
FinalizedEpoch: s.cfg.chain.FinalizedCheckpt().Epoch,
|
FinalizedEpoch: cp.Epoch,
|
||||||
HeadRoot: headRoot,
|
HeadRoot: headRoot,
|
||||||
HeadSlot: s.cfg.chain.HeadSlot(),
|
HeadSlot: s.cfg.chain.HeadSlot(),
|
||||||
}
|
}
|
||||||
@@ -284,7 +292,11 @@ func (s *Service) validateStatusMessage(ctx context.Context, msg *pb.Status) err
|
|||||||
return p2ptypes.ErrWrongForkDigestVersion
|
return p2ptypes.ErrWrongForkDigestVersion
|
||||||
}
|
}
|
||||||
genesis := s.cfg.chain.GenesisTime()
|
genesis := s.cfg.chain.GenesisTime()
|
||||||
finalizedEpoch := s.cfg.chain.FinalizedCheckpt().Epoch
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
finalizedEpoch := cp.Epoch
|
||||||
maxEpoch := slots.EpochsSinceGenesis(genesis)
|
maxEpoch := slots.EpochsSinceGenesis(genesis)
|
||||||
// It would take a minimum of 2 epochs to finalize a
|
// It would take a minimum of 2 epochs to finalize a
|
||||||
// previous epoch
|
// previous epoch
|
||||||
|
|||||||
@@ -131,7 +131,11 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
|||||||
return pubsub.ValidationIgnore, nil
|
return pubsub.ValidationIgnore, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
startSlot, err := slots.EpochStart(s.cfg.chain.FinalizedCheckpt().Epoch)
|
cp, err := s.cfg.chain.FinalizedCheckpt()
|
||||||
|
if err != nil {
|
||||||
|
return pubsub.ValidationIgnore, nil
|
||||||
|
}
|
||||||
|
startSlot, err := slots.EpochStart(cp.Epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not calculate epoch start slot")
|
log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not calculate epoch start slot")
|
||||||
return pubsub.ValidationIgnore, nil
|
return pubsub.ValidationIgnore, nil
|
||||||
|
|||||||
@@ -103,21 +103,27 @@ func (bb *Builder) Check(t testing.TB, c *Check) {
|
|||||||
Epoch: types.Epoch(c.JustifiedCheckPoint.Epoch),
|
Epoch: types.Epoch(c.JustifiedCheckPoint.Epoch),
|
||||||
Root: common.FromHex(c.JustifiedCheckPoint.Root),
|
Root: common.FromHex(c.JustifiedCheckPoint.Root),
|
||||||
}
|
}
|
||||||
require.DeepEqual(t, cp, bb.service.CurrentJustifiedCheckpt())
|
got, err := bb.service.CurrentJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, cp, got)
|
||||||
}
|
}
|
||||||
if c.BestJustifiedCheckPoint != nil {
|
if c.BestJustifiedCheckPoint != nil {
|
||||||
cp := ðpb.Checkpoint{
|
cp := ðpb.Checkpoint{
|
||||||
Epoch: types.Epoch(c.BestJustifiedCheckPoint.Epoch),
|
Epoch: types.Epoch(c.BestJustifiedCheckPoint.Epoch),
|
||||||
Root: common.FromHex(c.BestJustifiedCheckPoint.Root),
|
Root: common.FromHex(c.BestJustifiedCheckPoint.Root),
|
||||||
}
|
}
|
||||||
require.DeepEqual(t, cp, bb.service.BestJustifiedCheckpt())
|
got, err := bb.service.BestJustifiedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, cp, got)
|
||||||
}
|
}
|
||||||
if c.FinalizedCheckPoint != nil {
|
if c.FinalizedCheckPoint != nil {
|
||||||
cp := ðpb.Checkpoint{
|
cp := ðpb.Checkpoint{
|
||||||
Epoch: types.Epoch(c.FinalizedCheckPoint.Epoch),
|
Epoch: types.Epoch(c.FinalizedCheckPoint.Epoch),
|
||||||
Root: common.FromHex(c.FinalizedCheckPoint.Root),
|
Root: common.FromHex(c.FinalizedCheckPoint.Root),
|
||||||
}
|
}
|
||||||
require.DeepSSZEqual(t, cp, bb.service.FinalizedCheckpt())
|
got, err := bb.service.FinalizedCheckpt()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepSSZEqual(t, cp, got)
|
||||||
}
|
}
|
||||||
if c.ProposerBoostRoot != nil {
|
if c.ProposerBoostRoot != nil {
|
||||||
want := fmt.Sprintf("%#x", common.FromHex(*c.ProposerBoostRoot))
|
want := fmt.Sprintf("%#x", common.FromHex(*c.ProposerBoostRoot))
|
||||||
|
|||||||
Reference in New Issue
Block a user