mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-11 06:18:05 -05:00
Compare commits
10 Commits
builder-te
...
update-spe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7068684ee2 | ||
|
|
c2f3717f63 | ||
|
|
237807b248 | ||
|
|
bcd75adedd | ||
|
|
0c981e8853 | ||
|
|
6be2b2071a | ||
|
|
e7991b9d7b | ||
|
|
244e670b71 | ||
|
|
dc5fb92b28 | ||
|
|
a2db03b9e9 |
10
WORKSPACE
10
WORKSPACE
@@ -215,7 +215,7 @@ filegroup(
|
||||
url = "https://github.com/eth-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.1.10"
|
||||
consensus_spec_version = "v1.2.0-rc.1"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -231,7 +231,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "28043009cc2f6fc9804e73c8c1fc2cb27062f1591e6884f3015ae1dd7a276883",
|
||||
sha256 = "57120e8e2d5aaec956fc6a25ddc58fae2477f5b3ac7789174cf5ac1106dcc151",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -247,7 +247,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "bc1a283ca068f310f04d70c4f6a8eaa0b8f7e9318073a8bdc2ee233111b4e339",
|
||||
sha256 = "aa46676b26c173274ec8ea8756ae3072474b73ef7ccc7414d4026884810d8de2",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -263,7 +263,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "bbabb482c229ff9d4e2c7b77c992edb452f9d0af7c6d8dd4f922f06a7b101e81",
|
||||
sha256 = "d7dba93110cf35d9575ce21af6b7c3989f4aba621a9749bc090bca216e0345f7",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -278,7 +278,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "408a5524548ad3fcf387f65ac7ec52781d9ee899499720bb12451b48a15818d4",
|
||||
sha256 = "0a9c110305cbd6ebbe0d942f0f33e6ce22dd484ce4ceed277bf185a091941cde",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -66,6 +66,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
|
||||
@@ -283,8 +283,7 @@ func TestService_HeadGenesisValidatorsRoot(t *testing.T) {
|
||||
}
|
||||
func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0,
|
||||
params.BeaconConfig().ZeroHash)}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}}
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
@@ -380,7 +379,7 @@ func TestService_IsOptimistic_ProtoArray(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
|
||||
@@ -415,7 +414,7 @@ func TestService_IsOptimisticBeforeBellatrix(t *testing.T) {
|
||||
|
||||
func TestService_IsOptimisticForRoot_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
|
||||
@@ -438,7 +437,7 @@ func TestService_IsOptimisticForRoot_DoublyLinkedTree(t *testing.T) {
|
||||
func TestService_IsOptimisticForRoot_DB_ProtoArray(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 10
|
||||
|
||||
@@ -3,15 +3,30 @@ package blockchain
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
var (
|
||||
// ErrInvalidPayload is returned when the payload is invalid
|
||||
ErrInvalidPayload = errors.New("recevied an INVALID payload from execution engine")
|
||||
// ErrUndefinedExecutionEngineError is returned when the execution engine returns an error that is not defined
|
||||
ErrUndefinedExecutionEngineError = errors.New("received an undefined ee error")
|
||||
// errNilFinalizedInStore is returned when a nil finalized checkpt is returned from store.
|
||||
errNilFinalizedInStore = errors.New("nil finalized checkpoint returned from store")
|
||||
// errNilFinalizedCheckpoint is returned when a nil finalized checkpt is returned from a state.
|
||||
errNilFinalizedCheckpoint = errors.New("nil finalized checkpoint returned from state")
|
||||
// errNilJustifiedCheckpoint is returned when a nil justified checkpt is returned from a state.
|
||||
errNilJustifiedCheckpoint = errors.New("nil finalized checkpoint returned from state")
|
||||
// errInvalidNilSummary is returned when a nil summary is returned from the DB.
|
||||
errInvalidNilSummary = errors.New("nil summary returned from the DB")
|
||||
// errWrongBlockCount is returned when the wrong number of blocks or
|
||||
// block roots is used
|
||||
// errWrongBlockCount is returned when the wrong number of blocks or block roots is used
|
||||
errWrongBlockCount = errors.New("wrong number of blocks or block roots")
|
||||
// block is not a valid optimistic candidate block
|
||||
errNotOptimisticCandidate = errors.New("block is not suitable for optimistic sync")
|
||||
// errBlockNotFoundInCacheOrDB is returned when a block is not found in the cache or DB.
|
||||
errBlockNotFoundInCacheOrDB = errors.New("block not found in cache or db")
|
||||
// errNilStateFromStategen is returned when a nil state is returned from the state generator.
|
||||
errNilStateFromStategen = errors.New("justified state can't be nil")
|
||||
// errWSBlockNotFound is returned when a block is not found in the WS cache or DB.
|
||||
errWSBlockNotFound = errors.New("weak subjectivity root not found in db")
|
||||
// errWSBlockNotFoundInEpoch is returned when a block is not found in the WS cache or DB within epoch.
|
||||
errWSBlockNotFoundInEpoch = errors.New("weak subjectivity root not found in db within epoch")
|
||||
)
|
||||
|
||||
// An invalid block is the block that fails state transition based on the core protocol rules.
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -24,11 +25,6 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidPayload = errors.New("recevied an INVALID payload from execution engine")
|
||||
ErrUndefinedExecutionEngineError = errors.New("received an undefined ee error")
|
||||
)
|
||||
|
||||
// notifyForkchoiceUpdateArg is the argument for the forkchoice update notification `notifyForkchoiceUpdate`.
|
||||
type notifyForkchoiceUpdateArg struct {
|
||||
headState state.BeaconState
|
||||
@@ -168,7 +164,7 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
|
||||
if blocks.IsPreBellatrixVersion(postStateVersion) {
|
||||
return true, nil
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blk); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
return false, err
|
||||
}
|
||||
body := blk.Block().Body()
|
||||
|
||||
@@ -43,7 +43,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, altairBlk))
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -305,7 +305,7 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
||||
fcs.ProcessAttestation(ctx, []uint64{0}, brd, 1)
|
||||
fcs.ProcessAttestation(ctx, []uint64{1}, brf, 1)
|
||||
fcs.ProcessAttestation(ctx, []uint64{2}, brg, 1)
|
||||
headRoot, err := fcs.Head(ctx, 0, bra, []uint64{50, 100, 200}, 0)
|
||||
headRoot, err := fcs.Head(ctx, bra, []uint64{50, 100, 200})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brg, headRoot)
|
||||
|
||||
@@ -326,7 +326,7 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
||||
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
||||
require.ErrorIs(t, ErrInvalidPayload, err)
|
||||
// Ensure Head is D
|
||||
headRoot, err = fcs.Head(ctx, 0, bra, service.justifiedBalances.balances, 0)
|
||||
headRoot, err = fcs.Head(ctx, bra, service.justifiedBalances.balances)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brd, headRoot)
|
||||
|
||||
@@ -343,7 +343,7 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -555,7 +555,7 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -598,7 +598,7 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -800,7 +800,7 @@ func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
stateGen := stategen.New(beaconDB)
|
||||
fcs := protoarray.New(0, 0, [32]byte{})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stateGen),
|
||||
@@ -897,7 +897,7 @@ func TestService_removeInvalidBlockAndState(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, [32]byte{})),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
@@ -953,7 +953,7 @@ func TestService_getPayloadHash(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, [32]byte{})),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
@@ -27,13 +28,14 @@ import (
|
||||
// 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.
|
||||
func (s *Service) UpdateAndSaveHeadWithBalances(ctx context.Context) error {
|
||||
cp, err := s.store.JustifiedCheckpt()
|
||||
jp, err := s.store.JustifiedCheckpt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(jp.Root))
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("could not read balances for state w/ justified checkpoint %#x", cp.Root)
|
||||
msg := fmt.Sprintf("could not read balances for state w/ justified checkpoint %#x", jp.Root)
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
headRoot, err := s.updateHead(ctx, balances)
|
||||
@@ -93,14 +95,14 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) ([32]byte,
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
s.cfg.ForkChoiceStore = doublylinkedtree.New(j.Epoch, f.Epoch)
|
||||
} else {
|
||||
s.cfg.ForkChoiceStore = protoarray.New(j.Epoch, f.Epoch, bytesutil.ToBytes32(f.Root))
|
||||
s.cfg.ForkChoiceStore = protoarray.New(j.Epoch, f.Epoch)
|
||||
}
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, jb.Block(), headStartRoot, f, j); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return s.cfg.ForkChoiceStore.Head(ctx, j.Epoch, headStartRoot, balances, f.Epoch)
|
||||
return s.cfg.ForkChoiceStore.Head(ctx, headStartRoot, balances)
|
||||
}
|
||||
|
||||
// This saves head info to the local service cache, it also saves the
|
||||
@@ -117,7 +119,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte, headBlock int
|
||||
if headRoot == bytesutil.ToBytes32(r) {
|
||||
return nil
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(headBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(headBlock); err != nil {
|
||||
return err
|
||||
}
|
||||
if headState == nil || headState.IsNil() {
|
||||
@@ -190,7 +192,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte, headBlock int
|
||||
// root in DB. With the inception of initial-sync-cache-state flag, it uses finalized
|
||||
// check point as anchors to resume sync therefore head is no longer needed to be saved on per slot basis.
|
||||
func (s *Service) saveHeadNoDB(ctx context.Context, b interfaces.SignedBeaconBlock, r [32]byte, hs state.BeaconState) error {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
cachedHeadRoot, err := s.HeadRoot(ctx)
|
||||
|
||||
@@ -4,12 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
)
|
||||
|
||||
var errBlockNotFoundInCacheOrDB = errors.New("block not found in cache or db")
|
||||
|
||||
// This saves a beacon block to the initial sync blocks cache.
|
||||
func (s *Service) saveInitSyncBlock(r [32]byte, b interfaces.SignedBeaconBlock) {
|
||||
s.initSyncBlocksLock.Lock()
|
||||
@@ -49,7 +47,7 @@ func (s *Service) getBlock(ctx context.Context, r [32]byte) (interfaces.SignedBe
|
||||
return nil, errors.Wrap(err, "could not retrieve block from db")
|
||||
}
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, errBlockNotFoundInCacheOrDB
|
||||
}
|
||||
return b, nil
|
||||
|
||||
@@ -54,25 +54,33 @@ func logStateTransitionData(b interfaces.BeaconBlock) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
|
||||
func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justified, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
|
||||
startTime, err := slots.ToTime(genesisTime, block.Slot())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot(),
|
||||
"slotInEpoch": block.Slot() % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": slots.ToEpoch(block.Slot()),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]),
|
||||
"version": version.String(block.Version()),
|
||||
}).Info("Synced new block")
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot,
|
||||
"sinceSlotStartTime": prysmTime.Now().Sub(startTime),
|
||||
"chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime),
|
||||
}).Debug("Sync new block times")
|
||||
level := log.Logger.GetLevel()
|
||||
if level >= logrus.DebugLevel {
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot(),
|
||||
"slotInEpoch": block.Slot() % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": slots.ToEpoch(block.Slot()),
|
||||
"justifiedEpoch": justified.Epoch,
|
||||
"justifiedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(justified.Root)[:8]),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]),
|
||||
"version": version.String(block.Version()),
|
||||
"sinceSlotStartTime": prysmTime.Now().Sub(startTime),
|
||||
"chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime),
|
||||
}).Debug("Synced new block")
|
||||
} else {
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot(),
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": slots.ToEpoch(block.Slot()),
|
||||
}).Info("Synced new block")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
func testServiceOptsWithDB(t *testing.T) []Option {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
return []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
// if ancestor_at_finalized_slot == store.finalized_checkpoint.root:
|
||||
// store.justified_checkpoint = store.best_justified_checkpoint
|
||||
func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
||||
|
||||
// Reset proposer boost root in fork choice.
|
||||
if err := s.cfg.ForkChoiceStore.ResetBoostedProposerRoot(ctx); err != nil {
|
||||
return errors.Wrap(err, "could not reset boosted proposer root in fork choice")
|
||||
@@ -69,6 +68,9 @@ func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(bj, h)
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(bj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
func TestService_newSlot(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
// # Check if `pow_block` is a valid terminal PoW block
|
||||
// assert is_valid_terminal_pow_block(pow_block, pow_parent)
|
||||
func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.SignedBeaconBlock) error {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
payload, err := b.Block().Body().ExecutionPayload()
|
||||
|
||||
@@ -109,7 +109,7 @@ func Test_validateMergeBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -152,7 +152,7 @@ func Test_validateMergeBlock(t *testing.T) {
|
||||
func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/async"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
@@ -80,7 +80,7 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Block().Slot() > data.Slot {
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestStore_OnAttestation_ErrorConditions_ProtoArray(t *testing.T) {
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, [32]byte{})),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
@@ -250,7 +250,7 @@ func TestStore_OnAttestation_Ok_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -483,7 +483,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -602,7 +602,7 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, b32.Block.Slot, r32, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, b33.Block.Slot, r33, r32, params.BeaconConfig().ZeroHash, 0, 0))
|
||||
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, 0, r32, []uint64{}, 0)
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, r32, []uint64{})
|
||||
require.NoError(t, err)
|
||||
err = service.VerifyFinalizedConsistency(context.Background(), r33[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
@@ -92,7 +93,7 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
|
||||
func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onBlock")
|
||||
defer span.End()
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return invalidBlock{err}
|
||||
}
|
||||
b := signed.Block()
|
||||
@@ -181,7 +182,12 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
return errors.Wrap(err, "could not get justified checkpoint")
|
||||
}
|
||||
currJustifiedEpoch := justified.Epoch
|
||||
if postState.CurrentJustifiedCheckpoint().Epoch > currJustifiedEpoch {
|
||||
psj := postState.CurrentJustifiedCheckpoint()
|
||||
if psj == nil {
|
||||
return errNilJustifiedCheckpoint
|
||||
}
|
||||
|
||||
if psj.Epoch > currJustifiedEpoch {
|
||||
if err := s.updateJustified(ctx, postState); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -194,22 +200,32 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
if finalized == nil {
|
||||
return errNilFinalizedInStore
|
||||
}
|
||||
newFinalized := postState.FinalizedCheckpointEpoch() > finalized.Epoch
|
||||
psf := postState.FinalizedCheckpoint()
|
||||
if psf == nil {
|
||||
return errNilFinalizedCheckpoint
|
||||
}
|
||||
|
||||
newFinalized := psf.Epoch > finalized.Epoch
|
||||
if newFinalized {
|
||||
s.store.SetPrevFinalizedCheckpt(finalized)
|
||||
cp := postState.FinalizedCheckpoint()
|
||||
h, err := s.getPayloadHash(ctx, cp.Root)
|
||||
h, err := s.getPayloadHash(ctx, psf.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(cp, h)
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(psf, h)
|
||||
s.store.SetPrevJustifiedCheckpt(justified)
|
||||
cp = postState.CurrentJustifiedCheckpoint()
|
||||
h, err = s.getPayloadHash(ctx, cp.Root)
|
||||
h, err = s.getPayloadHash(ctx, psj.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h)
|
||||
// Update Forkchoice checkpoints
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(psj); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(psf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
||||
@@ -330,7 +346,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
return nil, nil, errWrongBlockCount
|
||||
}
|
||||
|
||||
if err := helpers.BeaconBlockIsNil(blks[0]); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(blks[0]); err != nil {
|
||||
return nil, nil, invalidBlock{err}
|
||||
}
|
||||
b := blks[0].Block()
|
||||
|
||||
@@ -214,6 +214,10 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(cpt, h)
|
||||
// Update forkchoice's justified checkpoint
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(cpt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestStore_OnBlock_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -268,8 +268,7 @@ func TestStore_OnBlock_ProposerBoostEarly(t *testing.T) {
|
||||
SecondsIntoSlot: 0,
|
||||
}
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.BoostProposerRoot(ctx, args))
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, 0,
|
||||
params.BeaconConfig().ZeroHash, []uint64{}, 0)
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
require.ErrorContains(t, "could not apply proposer boost score: invalid proposer boost root", err)
|
||||
}
|
||||
|
||||
@@ -294,7 +293,7 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -504,7 +503,7 @@ func TestShouldUpdateJustified_ReturnFalse_ProtoArray(t *testing.T) {
|
||||
opts := testServiceOptsWithDB(t)
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
lastJustifiedBlk := util.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||
@@ -584,7 +583,7 @@ func TestCachedPreState_CanGetFromStateSummary_ProtoArray(t *testing.T) {
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -655,7 +654,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -686,7 +685,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, [32]byte{})),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
@@ -732,7 +731,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
@@ -823,7 +822,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
@@ -921,7 +920,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
// Set finalized epoch to 1.
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{})
|
||||
|
||||
@@ -1145,7 +1144,7 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1234,7 +1233,7 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1294,7 +1293,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1439,7 +1438,7 @@ func TestHandleEpochBoundary_UpdateFirstSlot(t *testing.T) {
|
||||
func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1495,7 +1494,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
func TestOnBlock_NilBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1514,7 +1513,7 @@ func TestOnBlock_NilBlock(t *testing.T) {
|
||||
func TestOnBlock_InvalidSignature(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1555,7 +1554,7 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1793,7 +1792,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1921,7 +1920,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
||||
func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1972,7 +1971,7 @@ func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
||||
func TestOnBlock_ProcessBlocksParallel(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -2044,7 +2043,7 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) {
|
||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r2))
|
||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r3))
|
||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r4))
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'a'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2052,7 +2051,7 @@ func Test_verifyBlkFinalizedSlot_invalidBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
fcs := protoarray.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -59,14 +59,18 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaco
|
||||
}
|
||||
|
||||
// Reports on block and fork choice metrics.
|
||||
justified, err := s.store.JustifiedCheckpt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finalized, err := s.store.FinalizedCheckpt()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||
return errNilFinalizedInStore
|
||||
}
|
||||
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
||||
|
||||
// Log block sync status.
|
||||
if err := logBlockSyncStatus(blockCopy.Block(), blockRoot, finalized, receivedTime, uint64(s.genesisTime.Unix())); err != nil {
|
||||
if err := logBlockSyncStatus(blockCopy.Block(), blockRoot, justified, finalized, receivedTime, uint64(s.genesisTime.Unix())); err != nil {
|
||||
return err
|
||||
}
|
||||
// Log state transition data.
|
||||
|
||||
@@ -127,7 +127,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, genesisBlockRoot)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithAttestationPool(attestations.NewPool()),
|
||||
WithExitPool(voluntaryexits.NewPool()),
|
||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||
@@ -168,7 +168,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot))
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, genesisBlockRoot)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithAttestationPool(attestations.NewPool()),
|
||||
WithExitPool(voluntaryexits.NewPool()),
|
||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||
@@ -246,11 +246,9 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
genesisBlockRoot, err := genesis.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, genesisBlockRoot)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
@@ -198,7 +199,7 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
forkChoicer = doublylinkedtree.New(justified.Epoch, finalized.Epoch)
|
||||
} else {
|
||||
forkChoicer = protoarray.New(justified.Epoch, finalized.Epoch, fRoot)
|
||||
forkChoicer = protoarray.New(justified.Epoch, finalized.Epoch)
|
||||
}
|
||||
s.cfg.ForkChoiceStore = forkChoicer
|
||||
fb, err := s.getBlock(s.ctx, s.ensureRootNotZeros(fRoot))
|
||||
@@ -270,7 +271,7 @@ func (s *Service) originRootFromSavedState(ctx context.Context) ([32]byte, error
|
||||
if err != nil {
|
||||
return originRoot, errors.Wrap(err, "could not get genesis block from db")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(genesisBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(genesisBlock); err != nil {
|
||||
return originRoot, err
|
||||
}
|
||||
genesisBlkRoot, err := genesisBlock.Block().HashTreeRoot()
|
||||
|
||||
@@ -130,7 +130,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
WithAttestationPool(attestations.NewPool()),
|
||||
WithP2PBroadcaster(&mockBroadcaster{}),
|
||||
WithStateNotifier(&mockBeaconNode{}),
|
||||
WithForkChoiceStore(protoarray.New(0, 0, params.BeaconConfig().ZeroHash)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithAttestationService(attService),
|
||||
WithStateGen(stateGen),
|
||||
}
|
||||
@@ -505,7 +505,7 @@ func TestHasBlock_ForkChoiceAndDB_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
@@ -599,7 +599,7 @@ func BenchmarkHasBlockForkChoiceStore_ProtoArray(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
s := &Service{
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
)
|
||||
|
||||
var errNilStateFromStategen = errors.New("justified state can't be nil")
|
||||
|
||||
type stateBalanceCache struct {
|
||||
sync.Mutex
|
||||
balances []uint64
|
||||
|
||||
@@ -13,9 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
var errWSBlockNotFound = errors.New("weak subjectivity root not found in db")
|
||||
var errWSBlockNotFoundInEpoch = errors.New("weak subjectivity root not found in db within epoch")
|
||||
|
||||
type weakSubjectivityDB interface {
|
||||
HasBlock(ctx context.Context, blockRoot [32]byte) bool
|
||||
BlockRoots(ctx context.Context, f *filters.QueryFilter) ([][32]byte, error)
|
||||
|
||||
2
beacon-chain/cache/sync_committee.go
vendored
2
beacon-chain/cache/sync_committee.go
vendored
@@ -123,7 +123,7 @@ func (s *SyncCommitteeCache) idxPositionInCommittee(
|
||||
// UpdatePositionsInCommittee updates caching of validators position in sync committee in respect to
|
||||
// current epoch and next epoch. This should be called when `current_sync_committee` and `next_sync_committee`
|
||||
// change and that happens every `EPOCHS_PER_SYNC_COMMITTEE_PERIOD`.
|
||||
func (s *SyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, st state.BeaconStateAltair) error {
|
||||
func (s *SyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, st state.BeaconState) error {
|
||||
csc, err := st.CurrentSyncCommittee()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -28,6 +28,6 @@ func (s *FakeSyncCommitteeCache) NextPeriodIndexPosition(root [32]byte, valIdx t
|
||||
}
|
||||
|
||||
// UpdatePositionsInCommittee -- fake.
|
||||
func (s *FakeSyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, state state.BeaconStateAltair) error {
|
||||
func (s *FakeSyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, state state.BeaconState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -25,7 +26,7 @@ func ProcessAttestationsNoVerifySignature(
|
||||
beaconState state.BeaconState,
|
||||
b interfaces.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
@@ -46,10 +47,10 @@ func ProcessAttestationsNoVerifySignature(
|
||||
// method is used to validate attestations whose signatures have already been verified or will be verified later.
|
||||
func ProcessAttestationNoVerifySignature(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconStateAltair,
|
||||
beaconState state.BeaconState,
|
||||
att *ethpb.Attestation,
|
||||
totalBalance uint64,
|
||||
) (state.BeaconStateAltair, error) {
|
||||
) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "altair.ProcessAttestationNoVerifySignature")
|
||||
defer span.End()
|
||||
|
||||
@@ -262,7 +263,7 @@ func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposer
|
||||
// participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
|
||||
//
|
||||
// return participation_flag_indices
|
||||
func AttestationParticipationFlagIndices(beaconState state.BeaconStateAltair, data *ethpb.AttestationData, delay types.Slot) (map[uint8]bool, error) {
|
||||
func AttestationParticipationFlagIndices(beaconState state.BeaconState, data *ethpb.AttestationData, delay types.Slot) (map[uint8]bool, error) {
|
||||
currEpoch := time.CurrentEpoch(beaconState)
|
||||
var justifiedCheckpt *ethpb.Checkpoint
|
||||
if data.Target.Epoch == currEpoch {
|
||||
|
||||
@@ -44,7 +44,7 @@ import (
|
||||
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||
// else:
|
||||
// decrease_balance(state, participant_index, participant_reward)
|
||||
func ProcessSyncAggregate(ctx context.Context, s state.BeaconStateAltair, sync *ethpb.SyncAggregate) (state.BeaconStateAltair, error) {
|
||||
func ProcessSyncAggregate(ctx context.Context, s state.BeaconState, sync *ethpb.SyncAggregate) (state.BeaconState, error) {
|
||||
votedKeys, votedIndices, didntVoteIndices, err := FilterSyncCommitteeVotes(s, sync)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -58,7 +58,7 @@ func ProcessSyncAggregate(ctx context.Context, s state.BeaconStateAltair, sync *
|
||||
}
|
||||
|
||||
// FilterSyncCommitteeVotes filters the validator public keys and indices for the ones that voted and didn't vote.
|
||||
func FilterSyncCommitteeVotes(s state.BeaconStateAltair, sync *ethpb.SyncAggregate) (
|
||||
func FilterSyncCommitteeVotes(s state.BeaconState, sync *ethpb.SyncAggregate) (
|
||||
votedKeys []bls.PublicKey,
|
||||
votedIndices []types.ValidatorIndex,
|
||||
didntVoteIndices []types.ValidatorIndex,
|
||||
@@ -100,7 +100,7 @@ func FilterSyncCommitteeVotes(s state.BeaconStateAltair, sync *ethpb.SyncAggrega
|
||||
}
|
||||
|
||||
// VerifySyncCommitteeSig verifies sync committee signature `syncSig` is valid with respect to public keys `syncKeys`.
|
||||
func VerifySyncCommitteeSig(s state.BeaconStateAltair, syncKeys []bls.PublicKey, syncSig []byte) error {
|
||||
func VerifySyncCommitteeSig(s state.BeaconState, syncKeys []bls.PublicKey, syncSig []byte) error {
|
||||
ps := slots.PrevSlot(s.Slot())
|
||||
d, err := signing.Domain(s.Fork(), slots.ToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorsRoot())
|
||||
if err != nil {
|
||||
@@ -126,7 +126,7 @@ func VerifySyncCommitteeSig(s state.BeaconStateAltair, syncKeys []bls.PublicKey,
|
||||
}
|
||||
|
||||
// ApplySyncRewardsPenalties applies rewards and penalties for proposer and sync committee participants.
|
||||
func ApplySyncRewardsPenalties(ctx context.Context, s state.BeaconStateAltair, votedIndices, didntVoteIndices []types.ValidatorIndex) (state.BeaconStateAltair, error) {
|
||||
func ApplySyncRewardsPenalties(ctx context.Context, s state.BeaconState, votedIndices, didntVoteIndices []types.ValidatorIndex) (state.BeaconState, error) {
|
||||
activeBalance, err := helpers.TotalActiveBalance(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
// ProcessDeposits processes validator deposits for beacon state Altair.
|
||||
func ProcessDeposits(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconStateAltair,
|
||||
beaconState state.BeaconState,
|
||||
deposits []*ethpb.Deposit,
|
||||
) (state.BeaconStateAltair, error) {
|
||||
) (state.BeaconState, error) {
|
||||
batchVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -34,7 +34,7 @@ func ProcessDeposits(
|
||||
}
|
||||
|
||||
// ProcessDeposit processes validator deposit for beacon state Altair.
|
||||
func ProcessDeposit(ctx context.Context, beaconState state.BeaconStateAltair, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconStateAltair, error) {
|
||||
func ProcessDeposit(ctx context.Context, beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, error) {
|
||||
beaconState, isNewValidator, err := blocks.ProcessDeposit(beaconState, deposit, verifySignature)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// InitializePrecomputeValidators precomputes individual validator for its attested balances and the total sum of validators attested balances of the epoch.
|
||||
func InitializePrecomputeValidators(ctx context.Context, beaconState state.BeaconStateAltair) ([]*precompute.Validator, *precompute.Balance, error) {
|
||||
func InitializePrecomputeValidators(ctx context.Context, beaconState state.BeaconState) ([]*precompute.Validator, *precompute.Balance, error) {
|
||||
_, span := trace.StartSpan(ctx, "altair.InitializePrecomputeValidators")
|
||||
defer span.End()
|
||||
vals := make([]*precompute.Validator, beaconState.NumValidators())
|
||||
@@ -208,10 +208,10 @@ func ProcessEpochParticipation(
|
||||
// ProcessRewardsAndPenaltiesPrecompute processes the rewards and penalties of individual validator.
|
||||
// This is an optimized version by passing in precomputed validator attesting records and and total epoch balances.
|
||||
func ProcessRewardsAndPenaltiesPrecompute(
|
||||
beaconState state.BeaconStateAltair,
|
||||
beaconState state.BeaconState,
|
||||
bal *precompute.Balance,
|
||||
vals []*precompute.Validator,
|
||||
) (state.BeaconStateAltair, error) {
|
||||
) (state.BeaconState, error) {
|
||||
// Don't process rewards and penalties in genesis epoch.
|
||||
cfg := params.BeaconConfig()
|
||||
if time.CurrentEpoch(beaconState) == cfg.GenesisEpoch {
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
// if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
|
||||
// state.current_sync_committee = state.next_sync_committee
|
||||
// state.next_sync_committee = get_next_sync_committee(state)
|
||||
func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconStateAltair) (state.BeaconStateAltair, error) {
|
||||
func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconState) (state.BeaconState, error) {
|
||||
nextEpoch := time.NextEpoch(beaconState)
|
||||
if nextEpoch%params.BeaconConfig().EpochsPerSyncCommitteePeriod == 0 {
|
||||
nextSyncCommittee, err := beaconState.NextSyncCommittee()
|
||||
@@ -48,7 +48,7 @@ func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconSt
|
||||
// def process_participation_flag_updates(state: BeaconState) -> None:
|
||||
// state.previous_epoch_participation = state.current_epoch_participation
|
||||
// state.current_epoch_participation = [ParticipationFlags(0b0000_0000) for _ in range(len(state.validators))]
|
||||
func ProcessParticipationFlagUpdates(beaconState state.BeaconStateAltair) (state.BeaconStateAltair, error) {
|
||||
func ProcessParticipationFlagUpdates(beaconState state.BeaconState) (state.BeaconState, error) {
|
||||
c, err := beaconState.CurrentEpochParticipation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -54,7 +54,7 @@ func ValidateNilSyncContribution(s *ethpb.SignedContributionAndProof) error {
|
||||
// pubkeys = [state.validators[index].pubkey for index in indices]
|
||||
// aggregate_pubkey = bls.AggregatePKs(pubkeys)
|
||||
// return SyncCommittee(pubkeys=pubkeys, aggregate_pubkey=aggregate_pubkey)
|
||||
func NextSyncCommittee(ctx context.Context, s state.BeaconStateAltair) (*ethpb.SyncCommittee, error) {
|
||||
func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCommittee, error) {
|
||||
indices, err := NextSyncCommitteeIndices(ctx, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -98,7 +98,7 @@ func NextSyncCommittee(ctx context.Context, s state.BeaconStateAltair) (*ethpb.S
|
||||
// sync_committee_indices.append(candidate_index)
|
||||
// i += 1
|
||||
// return sync_committee_indices
|
||||
func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconStateAltair) ([]types.ValidatorIndex, error) {
|
||||
func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]types.ValidatorIndex, error) {
|
||||
epoch := coreTime.NextEpoch(s)
|
||||
indices, err := helpers.ActiveValidatorIndices(ctx, s, epoch)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
func TestSyncCommitteeIndices_CanGet(t *testing.T) {
|
||||
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
|
||||
getState := func(t *testing.T, count uint64) state.BeaconState {
|
||||
validators := make([]*ethpb.Validator, count)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
@@ -37,7 +37,7 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) {
|
||||
}
|
||||
|
||||
type args struct {
|
||||
state state.BeaconStateAltair
|
||||
state state.BeaconState
|
||||
epoch types.Epoch
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -95,7 +95,7 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) {
|
||||
|
||||
func TestSyncCommitteeIndices_DifferentPeriods(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
|
||||
getState := func(t *testing.T, count uint64) state.BeaconState {
|
||||
validators := make([]*ethpb.Validator, count)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
@@ -129,7 +129,7 @@ func TestSyncCommitteeIndices_DifferentPeriods(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncCommittee_CanGet(t *testing.T) {
|
||||
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
|
||||
getState := func(t *testing.T, count uint64) state.BeaconState {
|
||||
validators := make([]*ethpb.Validator, count)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
blsKey, err := bls.RandKey()
|
||||
@@ -149,7 +149,7 @@ func TestSyncCommittee_CanGet(t *testing.T) {
|
||||
}
|
||||
|
||||
type args struct {
|
||||
state state.BeaconStateAltair
|
||||
state state.BeaconState
|
||||
epoch types.Epoch
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -384,7 +384,7 @@ func Test_ValidateSyncMessageTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getState(t *testing.T, count uint64) state.BeaconStateAltair {
|
||||
func getState(t *testing.T, count uint64) state.BeaconState {
|
||||
validators := make([]*ethpb.Validator, count)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
blsKey, err := bls.RandKey()
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
// process_historical_roots_update(state)
|
||||
// process_participation_flag_updates(state) # [New in Altair]
|
||||
// process_sync_committee_updates(state) # [New in Altair]
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconStateAltair, error) {
|
||||
func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "altair.ProcessEpoch")
|
||||
defer span.End()
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ import (
|
||||
// post.current_sync_committee = get_next_sync_committee(post)
|
||||
// post.next_sync_committee = get_next_sync_committee(post)
|
||||
// return post
|
||||
func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.BeaconStateAltair, error) {
|
||||
func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
|
||||
epoch := time.CurrentEpoch(state)
|
||||
|
||||
numValidators := state.NumValidators()
|
||||
@@ -137,7 +137,7 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
|
||||
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
||||
// for flag_index in participation_flag_indices:
|
||||
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
|
||||
func TranslateParticipation(ctx context.Context, state state.BeaconStateAltair, atts []*ethpb.PendingAttestation) (state.BeaconStateAltair, error) {
|
||||
func TranslateParticipation(ctx context.Context, state state.BeaconState, atts []*ethpb.PendingAttestation) (state.BeaconState, error) {
|
||||
epochParticipation, err := state.PreviousEpochParticipation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
@@ -25,7 +26,7 @@ func ProcessAttestationsNoVerifySignature(
|
||||
beaconState state.BeaconState,
|
||||
b interfaces.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -43,7 +44,7 @@ func ProcessBlockHeader(
|
||||
beaconState state.BeaconState,
|
||||
block interfaces.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.BeaconBlockIsNil(block); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyRoot, err := block.Block().Body().HashTreeRoot()
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ func ProcessRandao(
|
||||
beaconState state.BeaconState,
|
||||
b interfaces.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
|
||||
@@ -22,7 +22,6 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/slice:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
|
||||
@@ -6,31 +6,10 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
var ErrNilSignedBeaconBlock = errors.New("signed beacon block can't be nil")
|
||||
var ErrNilBeaconBlock = errors.New("beacon block can't be nil")
|
||||
var ErrNilBeaconBlockBody = errors.New("beacon block body can't be nil")
|
||||
|
||||
// BeaconBlockIsNil checks if any composite field of input signed beacon block is nil.
|
||||
// Access to these nil fields will result in run time panic,
|
||||
// it is recommended to run these checks as first line of defense.
|
||||
func BeaconBlockIsNil(b interfaces.SignedBeaconBlock) error {
|
||||
if b == nil || b.IsNil() {
|
||||
return ErrNilSignedBeaconBlock
|
||||
}
|
||||
if b.Block().IsNil() {
|
||||
return ErrNilBeaconBlock
|
||||
}
|
||||
if b.Block().Body().IsNil() {
|
||||
return ErrNilBeaconBlockBody
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockRootAtSlot returns the block root stored in the BeaconState for a recent slot.
|
||||
// It returns an error if the requested block root is not within the slot range.
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@ var (
|
||||
// 1. Checks if the public key exists in the sync committee cache
|
||||
// 2. If 1 fails, checks if the public key exists in the input current sync committee object
|
||||
func IsCurrentPeriodSyncCommittee(
|
||||
st state.BeaconStateAltair, valIdx types.ValidatorIndex,
|
||||
st state.BeaconState, valIdx types.ValidatorIndex,
|
||||
) (bool, error) {
|
||||
root, err := syncPeriodBoundaryRoot(st)
|
||||
if err != nil {
|
||||
@@ -63,7 +63,7 @@ func IsCurrentPeriodSyncCommittee(
|
||||
// 1. Checks if the public key exists in the sync committee cache
|
||||
// 2. If 1 fails, checks if the public key exists in the input next sync committee object
|
||||
func IsNextPeriodSyncCommittee(
|
||||
st state.BeaconStateAltair, valIdx types.ValidatorIndex,
|
||||
st state.BeaconState, valIdx types.ValidatorIndex,
|
||||
) (bool, error) {
|
||||
root, err := syncPeriodBoundaryRoot(st)
|
||||
if err != nil {
|
||||
@@ -90,7 +90,7 @@ func IsNextPeriodSyncCommittee(
|
||||
// CurrentPeriodSyncSubcommitteeIndices returns the subcommittee indices of the
|
||||
// current period sync committee for input validator.
|
||||
func CurrentPeriodSyncSubcommitteeIndices(
|
||||
st state.BeaconStateAltair, valIdx types.ValidatorIndex,
|
||||
st state.BeaconState, valIdx types.ValidatorIndex,
|
||||
) ([]types.CommitteeIndex, error) {
|
||||
root, err := syncPeriodBoundaryRoot(st)
|
||||
if err != nil {
|
||||
@@ -124,7 +124,7 @@ func CurrentPeriodSyncSubcommitteeIndices(
|
||||
|
||||
// NextPeriodSyncSubcommitteeIndices returns the subcommittee indices of the next period sync committee for input validator.
|
||||
func NextPeriodSyncSubcommitteeIndices(
|
||||
st state.BeaconStateAltair, valIdx types.ValidatorIndex,
|
||||
st state.BeaconState, valIdx types.ValidatorIndex,
|
||||
) ([]types.CommitteeIndex, error) {
|
||||
root, err := syncPeriodBoundaryRoot(st)
|
||||
if err != nil {
|
||||
@@ -151,7 +151,7 @@ func NextPeriodSyncSubcommitteeIndices(
|
||||
// UpdateSyncCommitteeCache updates sync committee cache.
|
||||
// It uses `state`'s latest block header root as key. To avoid misuse, it disallows
|
||||
// block header with state root zeroed out.
|
||||
func UpdateSyncCommitteeCache(st state.BeaconStateAltair) error {
|
||||
func UpdateSyncCommitteeCache(st state.BeaconState) error {
|
||||
nextSlot := st.Slot() + 1
|
||||
if nextSlot%params.BeaconConfig().SlotsPerEpoch != 0 {
|
||||
return errors.New("not at the end of the epoch to update cache")
|
||||
|
||||
@@ -38,6 +38,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
|
||||
@@ -229,7 +229,7 @@ func TestProcessEpoch_BadBalanceAltair(t *testing.T) {
|
||||
assert.ErrorContains(t, "addition overflows", err)
|
||||
}
|
||||
|
||||
func createFullAltairBlockWithOperations(t *testing.T) (state.BeaconStateAltair,
|
||||
func createFullAltairBlockWithOperations(t *testing.T) (state.BeaconState,
|
||||
*ethpb.SignedBeaconBlockAltair) {
|
||||
beaconState, privKeys := util.DeterministicGenesisStateAltair(t, 32)
|
||||
sCom, err := altair.NextSyncCommittee(context.Background(), beaconState)
|
||||
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
e "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/execution"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -52,7 +52,7 @@ func ExecuteStateTransition(
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
|
||||
// VerifyOperationLengths verifies that block operation lengths are valid.
|
||||
func VerifyOperationLengths(_ context.Context, state state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -160,7 +160,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
) (*bls.SignatureBatch, state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockNoVerifyAnySig")
|
||||
defer span.End()
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
signedBeaconBlock interfaces.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessOperationsNoVerifyAttsSigs")
|
||||
defer span.End()
|
||||
if err := helpers.BeaconBlockIsNil(signedBeaconBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signedBeaconBlock); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ func ProcessBlockForStateRoot(
|
||||
) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockForStateRoot")
|
||||
defer span.End()
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ func altairOperations(
|
||||
// This calls phase 0 block operations.
|
||||
func phase0Operations(
|
||||
ctx context.Context,
|
||||
state state.BeaconStateAltair,
|
||||
state state.BeaconState,
|
||||
signedBeaconBlock interfaces.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
state, err := b.ProcessProposerSlashings(ctx, state, signedBeaconBlock.Block().Body().ProposerSlashings(), v.SlashValidator)
|
||||
if err != nil {
|
||||
|
||||
@@ -35,7 +35,6 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
"//beacon-chain/db/iface:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -34,7 +34,7 @@ func (s *Store) Backup(ctx context.Context, outputDir string, permissionOverride
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(head); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(head); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure the backups directory exists.
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -84,7 +84,7 @@ func (s *Store) updateFinalizedBlockRoots(ctx context.Context, tx *bolt.Tx, chec
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(signedBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signedBlock); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -210,12 +210,12 @@ func Test_migrateStateValidators(t *testing.T) {
|
||||
func Test_migrateAltairStateValidators(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator)
|
||||
eval func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator)
|
||||
setup func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator)
|
||||
eval func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator)
|
||||
}{
|
||||
{
|
||||
name: "migrates validators and adds them to new buckets",
|
||||
setup: func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator) {
|
||||
setup: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
|
||||
// create some new buckets that should be present for this migration
|
||||
err := dbStore.db.Update(func(tx *bbolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists(stateValidatorsBucket)
|
||||
@@ -226,7 +226,7 @@ func Test_migrateAltairStateValidators(t *testing.T) {
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
eval: func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator) {
|
||||
eval: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
|
||||
// check whether the new buckets are present
|
||||
err := dbStore.db.View(func(tx *bbolt.Tx) error {
|
||||
valBkt := tx.Bucket(stateValidatorsBucket)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/genesis"
|
||||
state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
@@ -664,7 +663,7 @@ func (s *Store) slotByBlockRoot(ctx context.Context, tx *bolt.Tx, blockRoot []by
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(wsb); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(wsb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b.Block.Slot, nil
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
"proposer_boost.go",
|
||||
"store.go",
|
||||
"types.go",
|
||||
"unrealized_justification.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree",
|
||||
visibility = [
|
||||
@@ -43,6 +44,7 @@ go_test(
|
||||
"optimistic_sync_test.go",
|
||||
"proposer_boost_test.go",
|
||||
"store_test.go",
|
||||
"unrealized_justification_test.go",
|
||||
"vote_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
@@ -52,6 +54,7 @@ go_test(
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
|
||||
@@ -9,3 +9,6 @@ var errUnknownFinalizedRoot = errors.New("unknown finalized root")
|
||||
var errUnknownJustifiedRoot = errors.New("unknown justified root")
|
||||
var errInvalidOptimisticStatus = errors.New("invalid optimistic status")
|
||||
var errUnknownPayloadHash = errors.New("unknown payload hash")
|
||||
var errInvalidNilCheckpoint = errors.New("invalid nil checkpoint")
|
||||
var errInvalidUnrealizedJustifiedEpoch = errors.New("invalid unrealized justified epoch")
|
||||
var errInvalidUnrealizedFinalizedEpoch = errors.New("invalid unrealized finalized epoch")
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||
|
||||
@@ -51,7 +51,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- head
|
||||
// |
|
||||
// 3
|
||||
r, err = f.Head(context.Background(), 1, indexToHash(2), balances, 0)
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||
|
||||
@@ -63,7 +64,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- start
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(3), balances, 1)
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||
}
|
||||
@@ -72,7 +74,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
balances := []uint64{1, 1}
|
||||
f := setup(0, 0)
|
||||
|
||||
r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -113,7 +115,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -143,7 +145,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// head -> 9 10
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -173,11 +175,12 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
r, err = f.Head(context.Background(), 1, indexToHash(1), balances, 0)
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
||||
}
|
||||
|
||||
@@ -42,10 +42,8 @@ func (f *ForkChoice) NodeCount() int {
|
||||
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
||||
func (f *ForkChoice) Head(
|
||||
ctx context.Context,
|
||||
justifiedEpoch types.Epoch,
|
||||
justifiedRoot [32]byte,
|
||||
justifiedStateBalances []uint64,
|
||||
finalizedEpoch types.Epoch,
|
||||
) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.Head")
|
||||
defer span.End()
|
||||
@@ -58,8 +56,6 @@ func (f *ForkChoice) Head(
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
|
||||
f.store.updateCheckpoints(justifiedEpoch, finalizedEpoch)
|
||||
|
||||
if err := f.updateBalances(justifiedStateBalances); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not update balances")
|
||||
}
|
||||
@@ -72,10 +68,9 @@ func (f *ForkChoice) Head(
|
||||
return [32]byte{}, errors.Wrap(err, "could not apply weight changes")
|
||||
}
|
||||
|
||||
if err := f.store.treeRootNode.updateBestDescendant(ctx, justifiedEpoch, finalizedEpoch); err != nil {
|
||||
if err := f.store.treeRootNode.updateBestDescendant(ctx, f.store.justifiedEpoch, f.store.finalizedEpoch); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not update best descendant")
|
||||
}
|
||||
|
||||
return f.store.head(ctx, justifiedRoot)
|
||||
}
|
||||
|
||||
@@ -362,3 +357,25 @@ func (f *ForkChoice) InsertSlashedIndex(_ context.Context, index types.Validator
|
||||
node.balance -= f.balances[index]
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
||||
if jc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.justifiedEpoch = jc.Epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
||||
if fc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.finalizedEpoch = fc.Epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
@@ -191,28 +192,28 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
// Insert a block it will be head
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
head, err := f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{}, 1)
|
||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'a'}, head)
|
||||
|
||||
// Insert two extra blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1))
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, head)
|
||||
|
||||
// Insert two attestations for block b, one for c it becomes head
|
||||
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
||||
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'b'}, head)
|
||||
|
||||
// Process b's slashing, c is now head
|
||||
f.InsertSlashedIndex(ctx, 1)
|
||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
||||
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
||||
require.NoError(t, err)
|
||||
@@ -221,7 +222,7 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
||||
// Process b's slashing again, should be a noop
|
||||
f.InsertSlashedIndex(ctx, 1)
|
||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
||||
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
||||
require.NoError(t, err)
|
||||
@@ -238,3 +239,15 @@ func indexToHash(i uint64) [32]byte {
|
||||
binary.LittleEndian.PutUint64(b[:], i)
|
||||
return hash.Hash(b[:])
|
||||
}
|
||||
|
||||
func TestStore_UpdateCheckpoints(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
jr := [32]byte{'j'}
|
||||
fr := [32]byte{'f'}
|
||||
jc := ðpb.Checkpoint{Root: jr[:], Epoch: 3}
|
||||
fc := ðpb.Checkpoint{Root: fr[:], Epoch: 2}
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
||||
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
||||
require.Equal(t, f.store.justifiedEpoch, jc.Epoch)
|
||||
require.Equal(t, f.store.finalizedEpoch, fc.Epoch)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
if r != params.BeaconConfig().ZeroHash {
|
||||
t.Errorf("Incorrect head with genesis")
|
||||
@@ -25,7 +25,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// /
|
||||
// 2 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// head -> 2 1
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// | |
|
||||
// head -> 4 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 5 <- justified epoch = 2
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// head -> 4 3
|
||||
// |
|
||||
// 5 <- starting from 5 with justified epoch 0 should error
|
||||
_, err = f.Head(context.Background(), 1, indexToHash(5), balances, 1)
|
||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||
require.ErrorContains(t, wanted, err)
|
||||
|
||||
@@ -93,7 +93,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// 4 3
|
||||
// |
|
||||
// 5 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 1)
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -108,7 +109,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 6 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1))
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 1)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
headRoot, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -107,7 +107,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -143,7 +143,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
}
|
||||
|
||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -185,7 +185,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
// Regression: process attestations for C, check that it
|
||||
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
||||
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
||||
|
||||
@@ -194,7 +194,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -219,7 +219,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
fEpoch,
|
||||
),
|
||||
)
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -238,7 +238,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure the head is C, the honest block.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -256,7 +256,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||
|
||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
})
|
||||
@@ -264,7 +264,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -291,7 +291,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -310,7 +310,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -329,7 +329,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||
|
||||
// Expect the head to have switched to B.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||
})
|
||||
@@ -351,7 +351,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
a := zeroHash
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -370,7 +370,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -398,7 +398,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is still the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -422,7 +422,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// D cannot win without a boost.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||
|
||||
@@ -436,7 +436,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||
|
||||
// Ensure D becomes the head thanks to boosting.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, d, r, "Expected D to become the head")
|
||||
})
|
||||
|
||||
@@ -112,13 +112,15 @@ func (s *Store) insert(ctx context.Context,
|
||||
parent := s.nodeByRoot[parentRoot]
|
||||
|
||||
n := &Node{
|
||||
slot: slot,
|
||||
root: root,
|
||||
parent: parent,
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
optimistic: true,
|
||||
payloadHash: payloadHash,
|
||||
slot: slot,
|
||||
root: root,
|
||||
parent: parent,
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
unrealizedJustifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
unrealizedFinalizedEpoch: finalizedEpoch,
|
||||
optimistic: true,
|
||||
payloadHash: payloadHash,
|
||||
}
|
||||
|
||||
s.nodeByPayload[payloadHash] = n
|
||||
@@ -143,12 +145,6 @@ func (s *Store) insert(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateCheckpoints Update the justified / finalized epochs in store if necessary.
|
||||
func (s *Store) updateCheckpoints(justifiedEpoch, finalizedEpoch types.Epoch) {
|
||||
s.justifiedEpoch = justifiedEpoch
|
||||
s.finalizedEpoch = finalizedEpoch
|
||||
}
|
||||
|
||||
// pruneFinalizedNodeByRootMap prunes the `nodeByRoot` map
|
||||
// starting from `node` down to the finalized Node or to a leaf of the Fork
|
||||
// choice store. This method assumes a lock on nodesLock.
|
||||
|
||||
@@ -121,15 +121,6 @@ func TestStore_Insert(t *testing.T) {
|
||||
assert.Equal(t, indexToHash(100), child.root, "Incorrect root")
|
||||
}
|
||||
|
||||
func TestStore_updateCheckpoints(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
s := f.store
|
||||
|
||||
s.updateCheckpoints(1, 1)
|
||||
assert.Equal(t, types.Epoch(1), s.justifiedEpoch, "Did not update justified epoch")
|
||||
assert.Equal(t, types.Epoch(1), s.finalizedEpoch, "Did not update finalized epoch")
|
||||
}
|
||||
|
||||
func TestStore_Prune_LessThanThreshold(t *testing.T) {
|
||||
// Define 100 nodes in store.
|
||||
numOfNodes := uint64(100)
|
||||
|
||||
@@ -35,17 +35,19 @@ type Store struct {
|
||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||
// This is used as an array based stateful DAG for efficient fork choice look up.
|
||||
type Node struct {
|
||||
slot types.Slot // slot of the block converted to the node.
|
||||
root [fieldparams.RootLength]byte // root of the block converted to the node.
|
||||
payloadHash [fieldparams.RootLength]byte // payloadHash of the block converted to the node.
|
||||
parent *Node // parent index of this node.
|
||||
children []*Node // the list of direct children of this Node
|
||||
justifiedEpoch types.Epoch // justifiedEpoch of this node.
|
||||
finalizedEpoch types.Epoch // finalizedEpoch of this node.
|
||||
balance uint64 // the balance that voted for this node directly
|
||||
weight uint64 // weight of this node: the total balance including children
|
||||
bestDescendant *Node // bestDescendant node of this node.
|
||||
optimistic bool // whether the block has been fully validated or not
|
||||
slot types.Slot // slot of the block converted to the node.
|
||||
root [fieldparams.RootLength]byte // root of the block converted to the node.
|
||||
payloadHash [fieldparams.RootLength]byte // payloadHash of the block converted to the node.
|
||||
parent *Node // parent index of this node.
|
||||
children []*Node // the list of direct children of this Node
|
||||
justifiedEpoch types.Epoch // justifiedEpoch of this node.
|
||||
unrealizedJustifiedEpoch types.Epoch // the epoch that would be justified if the block would be advanced to the next epoch.
|
||||
finalizedEpoch types.Epoch // finalizedEpoch of this node.
|
||||
unrealizedFinalizedEpoch types.Epoch // the epoch that would be finalized if the block would be advanced to the next epoch.
|
||||
balance uint64 // the balance that voted for this node directly
|
||||
weight uint64 // weight of this node: the total balance including children
|
||||
bestDescendant *Node // bestDescendant node of this node.
|
||||
optimistic bool // whether the block has been fully validated or not
|
||||
}
|
||||
|
||||
// Vote defines an individual validator's vote.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package doublylinkedtree
|
||||
|
||||
import types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
|
||||
func (s *Store) setUnrealizedJustifiedEpoch(root [32]byte, epoch types.Epoch) error {
|
||||
s.nodesLock.Lock()
|
||||
defer s.nodesLock.Unlock()
|
||||
|
||||
node, ok := s.nodeByRoot[root]
|
||||
if !ok || node == nil {
|
||||
return ErrNilNode
|
||||
}
|
||||
if epoch < node.unrealizedJustifiedEpoch {
|
||||
return errInvalidUnrealizedJustifiedEpoch
|
||||
}
|
||||
node.unrealizedJustifiedEpoch = epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) setUnrealizedFinalizedEpoch(root [32]byte, epoch types.Epoch) error {
|
||||
s.nodesLock.Lock()
|
||||
defer s.nodesLock.Unlock()
|
||||
|
||||
node, ok := s.nodeByRoot[root]
|
||||
if !ok || node == nil {
|
||||
return ErrNilNode
|
||||
}
|
||||
if epoch < node.unrealizedFinalizedEpoch {
|
||||
return errInvalidUnrealizedFinalizedEpoch
|
||||
}
|
||||
node.unrealizedFinalizedEpoch = epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUnrealizedCheckpoints "realizes" the unrealized justified and finalized
|
||||
// epochs stored within nodes. It should be called at the beginning of each
|
||||
// epoch
|
||||
func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
for _, node := range f.store.nodeByRoot {
|
||||
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
||||
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
||||
if node.justifiedEpoch > f.store.justifiedEpoch {
|
||||
f.store.justifiedEpoch = node.justifiedEpoch
|
||||
}
|
||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
||||
f.store.finalizedEpoch = node.finalizedEpoch
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package doublylinkedtree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestStore_SetUnrealizedEpochs(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
f.store.nodesLock.RLock()
|
||||
require.Equal(t, types.Epoch(1), f.store.nodeByRoot[[32]byte{'b'}].unrealizedJustifiedEpoch)
|
||||
require.Equal(t, types.Epoch(1), f.store.nodeByRoot[[32]byte{'b'}].unrealizedFinalizedEpoch)
|
||||
f.store.nodesLock.RUnlock()
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'b'}, 2))
|
||||
f.store.nodesLock.RLock()
|
||||
require.Equal(t, types.Epoch(2), f.store.nodeByRoot[[32]byte{'b'}].unrealizedJustifiedEpoch)
|
||||
require.Equal(t, types.Epoch(2), f.store.nodeByRoot[[32]byte{'b'}].unrealizedFinalizedEpoch)
|
||||
f.store.nodesLock.RUnlock()
|
||||
|
||||
require.ErrorIs(t, errInvalidUnrealizedJustifiedEpoch, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 0))
|
||||
require.ErrorIs(t, errInvalidUnrealizedFinalizedEpoch, f.store.setUnrealizedFinalizedEpoch([32]byte{'b'}, 0))
|
||||
}
|
||||
|
||||
func TestStore_UpdateUnrealizedCheckpoints(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Epoch 2 | Epoch 3
|
||||
// |
|
||||
// C |
|
||||
// / |
|
||||
// A <-- B |
|
||||
// \ |
|
||||
// ---- D
|
||||
//
|
||||
// B is the first block that justifies A.
|
||||
//
|
||||
func TestStore_LongFork(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 2))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'c'}, 2))
|
||||
|
||||
// Add an attestation to c, it is head
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
|
||||
// D is head even though its weight is lower.
|
||||
hr := [32]byte{'d'}
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
||||
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
||||
|
||||
// Update unrealized justification, c becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Epoch 1 Epoch 2 Epoch 3
|
||||
// | |
|
||||
// | |
|
||||
// A <-- B <-- C <-- D <-- E <-- F <-- G <-- H |
|
||||
// | \ |
|
||||
// | --------------- I
|
||||
// | |
|
||||
//
|
||||
// E justifies A. G justifies E.
|
||||
//
|
||||
func TestStore_NoDeadLock(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
// Epoch 1 blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0))
|
||||
|
||||
// Epoch 2 Blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'d'}, [32]byte{'E'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'e'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'f'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'g'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'g'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 107, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'h'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'h'}, 1))
|
||||
// Add an attestation for h
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||
|
||||
// Epoch 3
|
||||
// Current Head is H
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
|
||||
// Insert Block I, it becomes Head
|
||||
hr := [32]byte{'i'}
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'i'}, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.FinalizedEpoch())
|
||||
|
||||
// Realized Justified checkpoints, H becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(2), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(1), f.FinalizedEpoch())
|
||||
}
|
||||
|
||||
// Epoch 1 | Epoch 2
|
||||
// |
|
||||
// -- D (late)
|
||||
// / |
|
||||
// A <- B <- C |
|
||||
// \ |
|
||||
// -- -- -- E <- F <- G <- H
|
||||
// |
|
||||
//
|
||||
// D justifies and comes late.
|
||||
//
|
||||
func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
// Epoch 1 blocks (D does not arrive)
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 0, 0))
|
||||
|
||||
// Epoch 2 blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'c'}, [32]byte{'E'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 107, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 0, 0))
|
||||
|
||||
// Insert an attestation to H, H is head
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
|
||||
// D arrives late, D is head
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
||||
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'h'}].weight)
|
||||
}
|
||||
@@ -14,7 +14,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 2 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// head -> 2 1
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// 2 1 <- +vote, new head
|
||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// vote, new head -> 2 1
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -75,7 +75,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- new vote
|
||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- head
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 4 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 5 <- justified epoch = 2
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -167,11 +167,11 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(8), indexToHash(7), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(9), indexToHash(8), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
// Update fork choice justified epoch to 1 and start block to 5.
|
||||
// Update fork choice justified epoch to 2 and start block to 5.
|
||||
// Verify 9 is the head:
|
||||
// 0
|
||||
// / \
|
||||
@@ -188,7 +188,9 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 8
|
||||
// |
|
||||
// 9 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
f.store.justifiedEpoch = 2
|
||||
f.store.finalizedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -212,7 +214,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
f.ProcessAttestation(context.Background(), []uint64{0, 1}, indexToHash(9), 5)
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(10), indexToHash(8), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -221,28 +223,28 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// The new validators voted for 10.
|
||||
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
||||
// The new head should be 10.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
// Set the balances of the last 2 validators to 0.
|
||||
balances = []uint64{1, 1, 1, 0, 0}
|
||||
// The head should be back to 9.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
// Set the balances back to normal.
|
||||
balances = []uint64{1, 1, 1, 1, 1}
|
||||
// The head should be back to 10.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
// Remove the last 2 validators.
|
||||
balances = []uint64{1, 1, 1}
|
||||
// The head should be back to 9.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -251,7 +253,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||
assert.Equal(t, 11, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -275,7 +277,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||
assert.Equal(t, 5, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -291,7 +293,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// head-> 11
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(11), indexToHash(9), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// ForkChoicer represents the full fork choice interface composed of all the sub-interfaces.
|
||||
@@ -22,7 +22,7 @@ type ForkChoicer interface {
|
||||
|
||||
// HeadRetriever retrieves head root and optimistic info of the current chain.
|
||||
type HeadRetriever interface {
|
||||
Head(context.Context, types.Epoch, [32]byte, []uint64, types.Epoch) ([32]byte, error)
|
||||
Head(context.Context, [32]byte, []uint64) ([32]byte, error)
|
||||
Tips() ([][32]byte, []types.Slot)
|
||||
IsOptimistic(root [32]byte) (bool, error)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ type Getter interface {
|
||||
IsCanonical(root [32]byte) bool
|
||||
FinalizedEpoch() types.Epoch
|
||||
JustifiedEpoch() types.Epoch
|
||||
ForkChoiceNodes() []*pbrpc.ForkChoiceNode
|
||||
ForkChoiceNodes() []*ethpb.ForkChoiceNode
|
||||
NodeCount() int
|
||||
}
|
||||
|
||||
@@ -73,4 +73,6 @@ type Getter interface {
|
||||
type Setter interface {
|
||||
SetOptimisticToValid(context.Context, [fieldparams.RootLength]byte) error
|
||||
SetOptimisticToInvalid(context.Context, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte) ([][32]byte, error)
|
||||
UpdateJustifiedCheckpoint(*ethpb.Checkpoint) error
|
||||
UpdateFinalizedCheckpoint(*ethpb.Checkpoint) error
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
"proposer_boost.go",
|
||||
"store.go",
|
||||
"types.go",
|
||||
"unrealized_justification.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray",
|
||||
visibility = [
|
||||
@@ -44,6 +45,7 @@ go_test(
|
||||
"optimistic_sync_test.go",
|
||||
"proposer_boost_test.go",
|
||||
"store_test.go",
|
||||
"unrealized_justification_test.go",
|
||||
"vote_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
@@ -53,6 +55,7 @@ go_test(
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
|
||||
@@ -13,3 +13,6 @@ var errInvalidParentDelta = errors.New("parent delta is invalid")
|
||||
var errInvalidNodeDelta = errors.New("node delta is invalid")
|
||||
var errInvalidDeltaLength = errors.New("delta length is invalid")
|
||||
var errInvalidOptimisticStatus = errors.New("invalid optimistic status")
|
||||
var errInvalidNilCheckpoint = errors.New("invalid nil checkpoint")
|
||||
var errInvalidUnrealizedJustifiedEpoch = errors.New("invalid unrealized justified epoch")
|
||||
var errInvalidUnrealizedFinalizedEpoch = errors.New("invalid unrealized finalized epoch")
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||
|
||||
@@ -51,7 +51,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- head
|
||||
// |
|
||||
// 3
|
||||
r, err = f.Head(context.Background(), 1, indexToHash(2), balances, 0)
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||
|
||||
@@ -63,7 +64,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- start
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(3), balances, 1)
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||
}
|
||||
@@ -72,7 +74,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
balances := []uint64{1, 1}
|
||||
f := setup(0, 0)
|
||||
|
||||
r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -113,7 +115,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -143,7 +145,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// head -> 9 10
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -173,17 +175,18 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
r, err = f.Head(context.Background(), 1, indexToHash(1), balances, 0)
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
||||
}
|
||||
|
||||
func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
f := New(justifiedEpoch, finalizedEpoch, params.BeaconConfig().ZeroHash)
|
||||
f := New(justifiedEpoch, finalizedEpoch)
|
||||
f.store.nodesIndices[params.BeaconConfig().ZeroHash] = 0
|
||||
f.store.nodes = append(f.store.nodes, &Node{
|
||||
slot: 0,
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
if r != params.BeaconConfig().ZeroHash {
|
||||
t.Errorf("Incorrect head with genesis")
|
||||
@@ -25,7 +25,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// /
|
||||
// 2 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// head -> 2 1
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// | |
|
||||
// head -> 4 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 5 <- justified epoch = 2
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1))
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// head -> 4 3
|
||||
// |
|
||||
// 5 <- starting from 5 with justified epoch 0 should error
|
||||
_, err = f.Head(context.Background(), 1, indexToHash(5), balances, 1)
|
||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||
require.ErrorContains(t, wanted, err)
|
||||
|
||||
@@ -93,7 +93,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// 4 3
|
||||
// |
|
||||
// 5 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 1)
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -108,7 +109,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 6 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1))
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 1)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
headRoot, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -107,7 +107,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
),
|
||||
)
|
||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -142,7 +142,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
SecondsIntoSlot: 0,
|
||||
}
|
||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -180,7 +180,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
// Regression: process attestations for C, check that it
|
||||
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
||||
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
||||
headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
||||
})
|
||||
@@ -188,7 +188,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -213,7 +213,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
fEpoch,
|
||||
),
|
||||
)
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -232,7 +232,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure the head is C, the honest block.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -250,7 +250,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||
|
||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
})
|
||||
@@ -258,7 +258,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f := setup(jEpoch, fEpoch)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -285,7 +285,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -304,7 +304,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -323,7 +323,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||
|
||||
// Expect the head to have switched to B.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||
})
|
||||
@@ -345,7 +345,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
a := zeroHash
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -364,7 +364,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -392,7 +392,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// Ensure C is still the head.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -416,7 +416,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
|
||||
// D cannot win without a boost.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||
|
||||
@@ -430,7 +430,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||
|
||||
// Ensure D becomes the head thanks to boosting.
|
||||
r, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch)
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, d, r, "Expected D to become the head")
|
||||
})
|
||||
|
||||
@@ -24,11 +24,10 @@ const defaultPruneThreshold = 256
|
||||
var lastHeadRoot [32]byte
|
||||
|
||||
// New initializes a new fork choice store.
|
||||
func New(justifiedEpoch, finalizedEpoch types.Epoch, finalizedRoot [32]byte) *ForkChoice {
|
||||
func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
s := &Store{
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
finalizedRoot: finalizedRoot,
|
||||
proposerBoostRoot: [32]byte{},
|
||||
nodes: make([]*Node, 0),
|
||||
nodesIndices: make(map[[32]byte]uint64),
|
||||
@@ -47,10 +46,8 @@ func New(justifiedEpoch, finalizedEpoch types.Epoch, finalizedRoot [32]byte) *Fo
|
||||
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
||||
func (f *ForkChoice) Head(
|
||||
ctx context.Context,
|
||||
justifiedEpoch types.Epoch,
|
||||
justifiedRoot [32]byte,
|
||||
justifiedStateBalances []uint64,
|
||||
finalizedEpoch types.Epoch,
|
||||
) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.Head")
|
||||
defer span.End()
|
||||
@@ -58,7 +55,6 @@ func (f *ForkChoice) Head(
|
||||
defer f.votesLock.Unlock()
|
||||
|
||||
calledHeadCount.Inc()
|
||||
|
||||
newBalances := justifiedStateBalances
|
||||
|
||||
// Using the write lock here because `updateCanonicalNodes` that gets called subsequently requires a write operation.
|
||||
@@ -70,7 +66,7 @@ func (f *ForkChoice) Head(
|
||||
}
|
||||
f.votes = newVotes
|
||||
|
||||
if err := f.store.applyWeightChanges(ctx, justifiedEpoch, finalizedEpoch, newBalances, deltas); err != nil {
|
||||
if err := f.store.applyWeightChanges(ctx, newBalances, deltas); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "Could not apply score changes")
|
||||
}
|
||||
f.balances = newBalances
|
||||
@@ -337,15 +333,17 @@ func (s *Store) insert(ctx context.Context,
|
||||
}
|
||||
|
||||
n := &Node{
|
||||
slot: slot,
|
||||
root: root,
|
||||
parent: parentIndex,
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
bestChild: NonExistentNode,
|
||||
bestDescendant: NonExistentNode,
|
||||
weight: 0,
|
||||
payloadHash: payloadHash,
|
||||
slot: slot,
|
||||
root: root,
|
||||
parent: parentIndex,
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
unrealizedJustifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
unrealizedFinalizedEpoch: finalizedEpoch,
|
||||
bestChild: NonExistentNode,
|
||||
bestDescendant: NonExistentNode,
|
||||
weight: 0,
|
||||
payloadHash: payloadHash,
|
||||
}
|
||||
|
||||
s.nodesIndices[root] = index
|
||||
@@ -371,7 +369,7 @@ func (s *Store) insert(ctx context.Context,
|
||||
// back propagate the nodes' delta to its parents' delta. After scoring changes,
|
||||
// the best child is then updated along with the best descendant.
|
||||
func (s *Store) applyWeightChanges(
|
||||
ctx context.Context, justifiedEpoch, finalizedEpoch types.Epoch, newBalances []uint64, delta []int,
|
||||
ctx context.Context, newBalances []uint64, delta []int,
|
||||
) error {
|
||||
_, span := trace.StartSpan(ctx, "protoArrayForkChoice.applyWeightChanges")
|
||||
defer span.End()
|
||||
@@ -381,12 +379,6 @@ func (s *Store) applyWeightChanges(
|
||||
return errInvalidDeltaLength
|
||||
}
|
||||
|
||||
// Update the justified / finalized epochs in store if necessary.
|
||||
if s.justifiedEpoch != justifiedEpoch || s.finalizedEpoch != finalizedEpoch {
|
||||
s.justifiedEpoch = justifiedEpoch
|
||||
s.finalizedEpoch = finalizedEpoch
|
||||
}
|
||||
|
||||
// Proposer score defaults to 0.
|
||||
proposerScore := uint64(0)
|
||||
|
||||
@@ -791,3 +783,25 @@ func (f *ForkChoice) InsertSlashedIndex(ctx context.Context, index types.Validat
|
||||
nodeIndex = node.parent
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
||||
if jc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.justifiedEpoch = jc.Epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
||||
if fc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.finalizedEpoch = fc.Epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
@@ -132,19 +133,10 @@ func TestStore_ApplyScoreChanges_InvalidDeltaLength(t *testing.T) {
|
||||
s := &Store{}
|
||||
|
||||
// This will fail because node indices has length of 0, and delta list has a length of 1.
|
||||
err := s.applyWeightChanges(context.Background(), 0, 0, []uint64{}, []int{1})
|
||||
err := s.applyWeightChanges(context.Background(), []uint64{}, []int{1})
|
||||
assert.ErrorContains(t, errInvalidDeltaLength.Error(), err)
|
||||
}
|
||||
|
||||
func TestStore_ApplyScoreChanges_UpdateEpochs(t *testing.T) {
|
||||
s := &Store{}
|
||||
|
||||
// The justified and finalized epochs in Store should be updated to 1 and 1 given the following input.
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), 1, 1, []uint64{}, []int{}))
|
||||
assert.Equal(t, types.Epoch(1), s.justifiedEpoch, "Did not update justified epoch")
|
||||
assert.Equal(t, types.Epoch(1), s.finalizedEpoch, "Did not update finalized epoch")
|
||||
}
|
||||
|
||||
func TestStore_ApplyScoreChanges_UpdateWeightsPositiveDelta(t *testing.T) {
|
||||
// Construct 3 nodes with weight 100 on each node. The 3 nodes linked to each other.
|
||||
s := &Store{nodes: []*Node{
|
||||
@@ -154,7 +146,7 @@ func TestStore_ApplyScoreChanges_UpdateWeightsPositiveDelta(t *testing.T) {
|
||||
|
||||
// Each node gets one unique vote. The weight should look like 103 <- 102 <- 101 because
|
||||
// they get propagated back.
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), 0, 0, []uint64{}, []int{1, 1, 1}))
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{1, 1, 1}))
|
||||
assert.Equal(t, uint64(103), s.nodes[0].weight)
|
||||
assert.Equal(t, uint64(102), s.nodes[1].weight)
|
||||
assert.Equal(t, uint64(101), s.nodes[2].weight)
|
||||
@@ -169,7 +161,7 @@ func TestStore_ApplyScoreChanges_UpdateWeightsNegativeDelta(t *testing.T) {
|
||||
|
||||
// Each node gets one unique vote which contributes to negative delta.
|
||||
// The weight should look like 97 <- 98 <- 99 because they get propagated back.
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), 0, 0, []uint64{}, []int{-1, -1, -1}))
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-1, -1, -1}))
|
||||
assert.Equal(t, uint64(97), s.nodes[0].weight)
|
||||
assert.Equal(t, uint64(98), s.nodes[1].weight)
|
||||
assert.Equal(t, uint64(99), s.nodes[2].weight)
|
||||
@@ -183,7 +175,7 @@ func TestStore_ApplyScoreChanges_UpdateWeightsMixedDelta(t *testing.T) {
|
||||
{parent: 1, root: [32]byte{'A'}, weight: 100}}}
|
||||
|
||||
// Each node gets one mixed vote. The weight should look like 100 <- 200 <- 250.
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), 0, 0, []uint64{}, []int{-100, -50, 150}))
|
||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-100, -50, 150}))
|
||||
assert.Equal(t, uint64(100), s.nodes[0].weight)
|
||||
assert.Equal(t, uint64(200), s.nodes[1].weight)
|
||||
assert.Equal(t, uint64(250), s.nodes[2].weight)
|
||||
@@ -779,27 +771,27 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
// Insert a block it will be head
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
head, err := f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{}, 1)
|
||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'a'}, head)
|
||||
|
||||
// Insert two extra blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1))
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, head)
|
||||
|
||||
// Insert two attestations for block b, it becomes head
|
||||
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
||||
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'b'}, head)
|
||||
|
||||
// Process b's slashing, c is now head
|
||||
f.InsertSlashedIndex(ctx, 1)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, head)
|
||||
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
||||
@@ -807,7 +799,7 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
||||
|
||||
// Process the same slashing again, should be a noop
|
||||
f.InsertSlashedIndex(ctx, 1)
|
||||
head, err = f.Head(ctx, 1, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300}, 1)
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, head)
|
||||
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
||||
@@ -818,3 +810,15 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
||||
f.InsertSlashedIndex(ctx, types.ValidatorIndex(len(f.votes)))
|
||||
require.Equal(t, true, len(f.store.slashedIndices) > 0)
|
||||
}
|
||||
|
||||
func TestStore_UpdateCheckpoints(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
jr := [32]byte{'j'}
|
||||
fr := [32]byte{'f'}
|
||||
jc := ðpb.Checkpoint{Root: jr[:], Epoch: 3}
|
||||
fc := ðpb.Checkpoint{Root: fr[:], Epoch: 2}
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
||||
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
||||
require.Equal(t, f.store.justifiedEpoch, jc.Epoch)
|
||||
require.Equal(t, f.store.finalizedEpoch, fc.Epoch)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ type Store struct {
|
||||
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
||||
justifiedEpoch types.Epoch // latest justified epoch in store.
|
||||
finalizedEpoch types.Epoch // latest finalized epoch in store.
|
||||
finalizedRoot [fieldparams.RootLength]byte // latest finalized root in store.
|
||||
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
|
||||
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
|
||||
previousProposerBoostScore uint64 // previous proposer boosted root score.
|
||||
@@ -36,16 +35,18 @@ type Store struct {
|
||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||
// This is used as an array based stateful DAG for efficient fork choice look up.
|
||||
type Node struct {
|
||||
slot types.Slot // slot of the block converted to the node.
|
||||
root [fieldparams.RootLength]byte // root of the block converted to the node.
|
||||
payloadHash [fieldparams.RootLength]byte // payloadHash of the block converted to the node.
|
||||
parent uint64 // parent index of this node.
|
||||
justifiedEpoch types.Epoch // justifiedEpoch of this node.
|
||||
finalizedEpoch types.Epoch // finalizedEpoch of this node.
|
||||
weight uint64 // weight of this node.
|
||||
bestChild uint64 // bestChild index of this node.
|
||||
bestDescendant uint64 // bestDescendant of this node.
|
||||
status status // optimistic status of this node
|
||||
slot types.Slot // slot of the block converted to the node.
|
||||
root [fieldparams.RootLength]byte // root of the block converted to the node.
|
||||
payloadHash [fieldparams.RootLength]byte // payloadHash of the block converted to the node.
|
||||
parent uint64 // parent index of this node.
|
||||
justifiedEpoch types.Epoch // justifiedEpoch of this node.
|
||||
unrealizedJustifiedEpoch types.Epoch // the epoch that would be justified if the block would be advanced to the next epoch.
|
||||
finalizedEpoch types.Epoch // finalizedEpoch of this node.
|
||||
unrealizedFinalizedEpoch types.Epoch // the epoch that would be finalized if the block would be advanced to the next epoch.
|
||||
weight uint64 // weight of this node.
|
||||
bestChild uint64 // bestChild index of this node.
|
||||
bestDescendant uint64 // bestDescendant of this node.
|
||||
status status // optimistic status of this node
|
||||
}
|
||||
|
||||
// enum used as optimistic status of a node
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package protoarray
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
)
|
||||
|
||||
func (s *Store) setUnrealizedJustifiedEpoch(root [32]byte, epoch types.Epoch) error {
|
||||
s.nodesLock.Lock()
|
||||
defer s.nodesLock.Unlock()
|
||||
index, ok := s.nodesIndices[root]
|
||||
if !ok {
|
||||
return ErrUnknownNodeRoot
|
||||
}
|
||||
if index >= uint64(len(s.nodes)) {
|
||||
return errInvalidNodeIndex
|
||||
}
|
||||
node := s.nodes[index]
|
||||
if node == nil {
|
||||
return errInvalidNodeIndex
|
||||
}
|
||||
if epoch < node.unrealizedJustifiedEpoch {
|
||||
return errInvalidUnrealizedJustifiedEpoch
|
||||
}
|
||||
node.unrealizedJustifiedEpoch = epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) setUnrealizedFinalizedEpoch(root [32]byte, epoch types.Epoch) error {
|
||||
s.nodesLock.Lock()
|
||||
defer s.nodesLock.Unlock()
|
||||
index, ok := s.nodesIndices[root]
|
||||
if !ok {
|
||||
return ErrUnknownNodeRoot
|
||||
}
|
||||
if index >= uint64(len(s.nodes)) {
|
||||
return errInvalidNodeIndex
|
||||
}
|
||||
node := s.nodes[index]
|
||||
if node == nil {
|
||||
return errInvalidNodeIndex
|
||||
}
|
||||
if epoch < node.unrealizedFinalizedEpoch {
|
||||
return errInvalidUnrealizedFinalizedEpoch
|
||||
}
|
||||
node.unrealizedFinalizedEpoch = epoch
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUnrealizedCheckpoints "realizes" the unrealized justified and finalized
|
||||
// epochs stored within nodes. It should be called at the beginning of each
|
||||
// epoch
|
||||
func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
for _, node := range f.store.nodes {
|
||||
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
||||
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
||||
if node.justifiedEpoch > f.store.justifiedEpoch {
|
||||
f.store.justifiedEpoch = node.justifiedEpoch
|
||||
}
|
||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
||||
f.store.finalizedEpoch = node.finalizedEpoch
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package protoarray
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestStore_SetUnrealizedEpochs(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
f.store.nodesLock.RLock()
|
||||
require.Equal(t, types.Epoch(1), f.store.nodes[2].unrealizedJustifiedEpoch)
|
||||
require.Equal(t, types.Epoch(1), f.store.nodes[2].unrealizedFinalizedEpoch)
|
||||
f.store.nodesLock.RUnlock()
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'b'}, 2))
|
||||
f.store.nodesLock.RLock()
|
||||
require.Equal(t, types.Epoch(2), f.store.nodes[2].unrealizedJustifiedEpoch)
|
||||
require.Equal(t, types.Epoch(2), f.store.nodes[2].unrealizedFinalizedEpoch)
|
||||
f.store.nodesLock.RUnlock()
|
||||
|
||||
require.ErrorIs(t, errInvalidUnrealizedJustifiedEpoch, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 0))
|
||||
require.ErrorIs(t, errInvalidUnrealizedFinalizedEpoch, f.store.setUnrealizedFinalizedEpoch([32]byte{'b'}, 0))
|
||||
}
|
||||
|
||||
func TestStore_UpdateUnrealizedCheckpoints(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Epoch 2 | Epoch 3
|
||||
// |
|
||||
// C |
|
||||
// / |
|
||||
// A <-- B |
|
||||
// \ |
|
||||
// ---- D
|
||||
//
|
||||
// B is the first block that justifies A.
|
||||
//
|
||||
func TestStore_LongFork(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'b'}, 2))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'c'}, 2))
|
||||
|
||||
// Add an attestation to c, it is head
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
|
||||
// D is head even though its weight is lower.
|
||||
hr := [32]byte{'d'}
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hr, headRoot)
|
||||
require.Equal(t, uint64(0), f.store.nodes[4].weight)
|
||||
require.Equal(t, uint64(100), f.store.nodes[3].weight)
|
||||
|
||||
// Update unrealized justification, c becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Epoch 1 Epoch 2 Epoch 3
|
||||
// | |
|
||||
// | |
|
||||
// A <-- B <-- C <-- D <-- E <-- F <-- G <-- H |
|
||||
// | \ |
|
||||
// | --------------- I
|
||||
// | |
|
||||
//
|
||||
// E justifies A. G justifies E.
|
||||
//
|
||||
func TestStore_NoDeadLock(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
// Epoch 1 blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0))
|
||||
|
||||
// Epoch 2 Blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'d'}, [32]byte{'E'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'e'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'f'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'g'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'g'}, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 107, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'h'}, 2))
|
||||
require.NoError(t, f.store.setUnrealizedFinalizedEpoch([32]byte{'h'}, 1))
|
||||
// Add an attestation for h
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||
|
||||
// Epoch 3
|
||||
// Current Head is H
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
|
||||
// Insert Block I, it becomes Head
|
||||
hr := [32]byte{'i'}
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hr, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.FinalizedEpoch())
|
||||
|
||||
// Realized Justified checkpoints, H becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(2), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(1), f.FinalizedEpoch())
|
||||
}
|
||||
|
||||
// Epoch 1 | Epoch 2
|
||||
// |
|
||||
// -- D (late) --
|
||||
// / |
|
||||
// A <- B <- C |
|
||||
// \ |
|
||||
// -- -- -- E <- F <- G <- H
|
||||
// |
|
||||
//
|
||||
// D justifies and comes late.
|
||||
//
|
||||
func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
// Epoch 1 blocks (D does not arrive)
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 0, 0))
|
||||
|
||||
// Epoch 2 blocks
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'c'}, [32]byte{'E'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'g'}, [32]byte{'f'}, [32]byte{'G'}, 0, 0))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 107, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 0, 0))
|
||||
|
||||
// Insert an attestation to H, H is head
|
||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
|
||||
// D arrives late, D is head
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
// nodes[8] = D since it's late!
|
||||
require.Equal(t, uint64(0), f.store.nodes[8].weight)
|
||||
require.Equal(t, uint64(100), f.store.nodes[7].weight)
|
||||
}
|
||||
@@ -14,7 +14,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
f := setup(1, 1)
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 2 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// head -> 2 1
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// 2 1 <- +vote, new head
|
||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// / \
|
||||
// vote, new head -> 2 1
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 3
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -75,7 +75,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- new vote
|
||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- head
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 4 <- head
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 5 <- justified epoch = 2
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -167,7 +167,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(8), indexToHash(7), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(9), indexToHash(8), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 1, params.BeaconConfig().ZeroHash, balances, 1)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -188,7 +188,9 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 8
|
||||
// |
|
||||
// 9 <- head
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
f.store.justifiedEpoch = 2
|
||||
f.store.finalizedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -212,7 +214,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
f.ProcessAttestation(context.Background(), []uint64{0, 1}, indexToHash(9), 5)
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(10), indexToHash(8), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -221,28 +223,28 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// The new validators voted for 10.
|
||||
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
||||
// The new head should be 10.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
// Set the balances of the last 2 validators to 0.
|
||||
balances = []uint64{1, 1, 1, 0, 0}
|
||||
// The head should be back to 9.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
// Set the balances back to normal.
|
||||
balances = []uint64{1, 1, 1, 1, 1}
|
||||
// The head should be back to 10.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
// Remove the last 2 validators.
|
||||
balances = []uint64{1, 1, 1}
|
||||
// The head should be back to 9.
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -251,7 +253,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||
assert.Equal(t, 11, len(f.store.nodes), "Incorrect nodes length after prune")
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -275,7 +277,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||
assert.Equal(t, 5, len(f.store.nodes), "Incorrect nodes length after prune")
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -291,7 +293,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// head-> 11
|
||||
require.NoError(t, f.InsertOptimisticBlock(context.Background(), 0, indexToHash(11), indexToHash(9), params.BeaconConfig().ZeroHash, 2, 2))
|
||||
|
||||
r, err = f.Head(context.Background(), 2, indexToHash(5), balances, 2)
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ func (b *BeaconNode) startForkChoice() {
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
b.forkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
} else {
|
||||
b.forkChoiceStore = protoarray.New(0, 0, params.BeaconConfig().ZeroHash)
|
||||
b.forkChoiceStore = protoarray.New(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -320,8 +320,12 @@ func handleRPCError(err error) error {
|
||||
return ErrInvalidParams
|
||||
case -32603:
|
||||
return ErrInternal
|
||||
case -32001:
|
||||
case -38001:
|
||||
return ErrUnknownPayload
|
||||
case -38002:
|
||||
return ErrInvalidForkchoiceState
|
||||
case -38003:
|
||||
return ErrInvalidPayloadAttributes
|
||||
case -32000:
|
||||
// Only -32000 status codes are data errors in the RPC specification.
|
||||
errWithData, ok := err.(rpc.DataError)
|
||||
|
||||
@@ -688,7 +688,17 @@ func Test_handleRPCError(t *testing.T) {
|
||||
{
|
||||
name: "ErrUnknownPayload",
|
||||
expectedContains: ErrUnknownPayload.Error(),
|
||||
given: &customError{code: -32001},
|
||||
given: &customError{code: -38001},
|
||||
},
|
||||
{
|
||||
name: "ErrInvalidForkchoiceState",
|
||||
expectedContains: ErrInvalidForkchoiceState.Error(),
|
||||
given: &customError{code: -38002},
|
||||
},
|
||||
{
|
||||
name: "ErrInvalidPayloadAttributes",
|
||||
expectedContains: ErrInvalidPayloadAttributes.Error(),
|
||||
given: &customError{code: -38003},
|
||||
},
|
||||
{
|
||||
name: "ErrServer unexpected no data",
|
||||
|
||||
@@ -15,8 +15,12 @@ var (
|
||||
ErrInternal = errors.New("internal JSON-RPC error")
|
||||
// ErrServer corresponds to JSON-RPC code -32000.
|
||||
ErrServer = errors.New("client error while processing request")
|
||||
// ErrUnknownPayload corresponds to JSON-RPC code -32001.
|
||||
// ErrUnknownPayload corresponds to JSON-RPC code -38001.
|
||||
ErrUnknownPayload = errors.New("payload does not exist or is not available")
|
||||
// ErrInvalidForkchoiceState corresponds to JSON-RPC code -38002.
|
||||
ErrInvalidForkchoiceState = errors.New("invalid forkchoice state")
|
||||
// ErrInvalidPayloadAttributes corresponds to JSON-RPC code -38003.
|
||||
ErrInvalidPayloadAttributes = errors.New("payload attributes are invalid / inconsistent")
|
||||
// ErrUnknownPayloadStatus when the payload status is unknown.
|
||||
ErrUnknownPayloadStatus = errors.New("unknown payload status")
|
||||
// ErrConfigMismatch when the execution node's terminal total difficulty or
|
||||
|
||||
@@ -584,7 +584,7 @@ func (bs *Server) GetBlockRoot(ctx context.Context, req *ethpbv1.BlockRequest) (
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve blocks for genesis slot: %v", err)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blk); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
return nil, status.Errorf(codes.NotFound, "Could not find genesis block: %v", err)
|
||||
}
|
||||
blkRoot, err := blk.Block().HashTreeRoot()
|
||||
@@ -598,7 +598,7 @@ func (bs *Server) GetBlockRoot(ctx context.Context, req *ethpbv1.BlockRequest) (
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve block for block root %#x: %v", req.BlockId, err)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blk); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
return nil, status.Errorf(codes.NotFound, "Could not find block: %v", err)
|
||||
}
|
||||
root = req.BlockId
|
||||
@@ -793,7 +793,7 @@ func handleGetBlockError(blk interfaces.SignedBeaconBlock, err error) error {
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get block from block ID: %v", err)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blk); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
return status.Errorf(codes.NotFound, "Could not find requested block: %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -13,7 +13,6 @@ go_library(
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/rpc/statefetcher:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/eth/v2:go_default_library",
|
||||
"//proto/migration:go_default_library",
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/proto/migration"
|
||||
@@ -84,11 +83,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case version.Altair:
|
||||
altairState, ok := beaconSt.(state.BeaconStateAltair)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.Internal, "Altair state type assertion failed")
|
||||
}
|
||||
protoState, err := migration.BeaconStateAltairToProto(altairState)
|
||||
protoState, err := migration.BeaconStateAltairToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
}
|
||||
@@ -100,11 +95,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case version.Bellatrix:
|
||||
bellatrixState, ok := beaconSt.(state.BeaconStateBellatrix)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.Internal, "Bellatrix state type assertion failed")
|
||||
}
|
||||
protoState, err := migration.BeaconStateBellatrixToProto(bellatrixState)
|
||||
protoState, err := migration.BeaconStateBellatrixToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//container/slice:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/cmd"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -250,7 +250,7 @@ func (bs *Server) listBlocksForGenesis(ctx context.Context, _ *ethpb.ListBlocksR
|
||||
if err != nil {
|
||||
return nil, 0, strconv.Itoa(0), status.Errorf(codes.Internal, "Could not retrieve blocks for genesis slot: %v", err)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(genBlk); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(genBlk); err != nil {
|
||||
return []blockContainer{}, 0, strconv.Itoa(0), status.Errorf(codes.NotFound, "Could not find genesis block: %v", err)
|
||||
}
|
||||
root, err := genBlk.Block().HashTreeRoot()
|
||||
@@ -393,7 +393,7 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not get head block")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(headBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(headBlock); err != nil {
|
||||
return nil, status.Errorf(codes.NotFound, "Head block of chain was nil: %v", err)
|
||||
}
|
||||
headBlockRoot, err := headBlock.Block().HashTreeRoot()
|
||||
@@ -409,7 +409,7 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
|
||||
}
|
||||
// Retrieve genesis block in the event we have genesis checkpoints.
|
||||
genBlock, err := bs.BeaconDB.GenesisBlock(ctx)
|
||||
if err != nil || helpers.BeaconBlockIsNil(genBlock) != nil {
|
||||
if err != nil || wrapper.BeaconBlockIsNil(genBlock) != nil {
|
||||
return status.Error(codes.Internal, "Could not get genesis block")
|
||||
}
|
||||
validGenesis = true
|
||||
@@ -419,7 +419,7 @@ func (bs *Server) chainHeadRetrieval(ctx context.Context) (*ethpb.ChainHead, err
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get %s block: %v", name, err)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get %s block: %v", name, err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_GetForkChoice_ProtoArray(t *testing.T) {
|
||||
store := protoarray.New(0, 0, [32]byte{'a'})
|
||||
store := protoarray.New(0, 0)
|
||||
bs := &Server{ForkFetcher: &mock.ChainService{ForkChoiceStore: store}}
|
||||
res, err := bs.GetForkChoice(context.Background(), &empty.Empty{})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -98,7 +99,7 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(finalizedBlock); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(finalizedBlock); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch finalizedBlock.Version() {
|
||||
|
||||
@@ -7,12 +7,12 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -223,7 +223,7 @@ func (p *StateProvider) headStateRoot(ctx context.Context) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get head block")
|
||||
}
|
||||
if err = helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err = wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.Block().StateRoot(), nil
|
||||
@@ -234,7 +234,7 @@ func (p *StateProvider) genesisStateRoot(ctx context.Context) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get genesis block")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.Block().StateRoot(), nil
|
||||
@@ -249,7 +249,7 @@ func (p *StateProvider) finalizedStateRoot(ctx context.Context) ([]byte, error)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized block")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.Block().StateRoot(), nil
|
||||
@@ -264,7 +264,7 @@ func (p *StateProvider) justifiedStateRoot(ctx context.Context) ([]byte, error)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get justified block")
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.Block().StateRoot(), nil
|
||||
|
||||
@@ -3,10 +3,8 @@ load("@prysm//tools/go:def.bzl", "go_library")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"altair.go",
|
||||
"bellatrix.go",
|
||||
"error.go",
|
||||
"phase0.go",
|
||||
"interfaces.go",
|
||||
"prometheus.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state",
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package state
|
||||
|
||||
import ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
|
||||
// BeaconStateAltair has read and write access to beacon state methods.
|
||||
type BeaconStateAltair interface {
|
||||
BeaconState
|
||||
CurrentSyncCommittee() (*ethpb.SyncCommittee, error)
|
||||
NextSyncCommittee() (*ethpb.SyncCommittee, error)
|
||||
SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error
|
||||
SetNextSyncCommittee(val *ethpb.SyncCommittee) error
|
||||
CurrentEpochParticipation() ([]byte, error)
|
||||
PreviousEpochParticipation() ([]byte, error)
|
||||
InactivityScores() ([]uint64, error)
|
||||
AppendCurrentParticipationBits(val byte) error
|
||||
AppendPreviousParticipationBits(val byte) error
|
||||
AppendInactivityScore(s uint64) error
|
||||
SetInactivityScores(val []uint64) error
|
||||
SetPreviousParticipationBits(val []byte) error
|
||||
SetCurrentParticipationBits(val []byte) error
|
||||
ModifyCurrentParticipationBits(func(val []byte) ([]byte, error)) error
|
||||
ModifyPreviousParticipationBits(func(val []byte) ([]byte, error)) error
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package state
|
||||
|
||||
// BeaconStateBellatrix has read and write access to beacon state methods.
|
||||
type BeaconStateBellatrix interface {
|
||||
BeaconStateAltair
|
||||
}
|
||||
@@ -204,7 +204,7 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
|
||||
|
||||
// InitializeFromProtoUnsafeAltair directly uses the beacon state protobuf fields
|
||||
// and sets them as fields of the BeaconState type.
|
||||
func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) {
|
||||
func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconState, error) {
|
||||
if st == nil {
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
@@ -292,7 +292,7 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
|
||||
|
||||
// InitializeFromProtoUnsafeBellatrix directly uses the beacon state protobuf fields
|
||||
// and sets them as fields of the BeaconState type.
|
||||
func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) {
|
||||
func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.BeaconState, error) {
|
||||
if st == nil {
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
"//beacon-chain/core/execution:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
@@ -33,6 +32,7 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -227,7 +227,7 @@ func (s *State) LastAncestorState(ctx context.Context, blockRoot [32]byte) (stat
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -94,7 +94,7 @@ func (c *CanonicalHistory) BlockForSlot(ctx context.Context, target types.Slot)
|
||||
// performing null/validity checks, and using CanonicalChecker to only pick canonical blocks.
|
||||
func (c *CanonicalHistory) bestForSlot(ctx context.Context, hbs []interfaces.SignedBeaconBlock) ([32]byte, interfaces.SignedBeaconBlock, error) {
|
||||
for _, b := range hbs {
|
||||
if helpers.BeaconBlockIsNil(b) != nil {
|
||||
if wrapper.BeaconBlockIsNil(b) != nil {
|
||||
continue
|
||||
}
|
||||
root, err := b.Block().HashTreeRoot()
|
||||
@@ -188,7 +188,7 @@ func (c *CanonicalHistory) ancestorChain(ctx context.Context, tail interfaces.Si
|
||||
msg := fmt.Sprintf("db error when retrieving parent of block at slot=%d by root=%#x", b.Slot(), b.ParentRoot())
|
||||
return nil, nil, errors.Wrap(err, msg)
|
||||
}
|
||||
if helpers.BeaconBlockIsNil(parent) != nil {
|
||||
if wrapper.BeaconBlockIsNil(parent) != nil {
|
||||
msg := fmt.Sprintf("unable to retrieve parent of block at slot=%d by root=%#x", b.Slot(), b.ParentRoot())
|
||||
return nil, nil, errors.Wrap(db.ErrNotFound, msg)
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/execution"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
prysmtime "github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
@@ -146,7 +146,7 @@ func executeStateTransitionStateGen(
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
if err := wrapper.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx, span := trace.StartSpan(ctx, "stategen.executeStateTransitionStateGen")
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
// InitializeFromProto the beacon state from a protobuf representation.
|
||||
func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) {
|
||||
func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconState, error) {
|
||||
if features.Get().EnableNativeState {
|
||||
return statenative.InitializeFromProtoAltair(proto.Clone(st).(*ethpb.BeaconStateAltair))
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair,
|
||||
|
||||
// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer
|
||||
// and sets it as the inner state of the BeaconState type.
|
||||
func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) {
|
||||
func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (state.BeaconState, error) {
|
||||
if features.Get().EnableNativeState {
|
||||
return statenative.InitializeFromProtoUnsafeAltair(st)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user