mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
10 Commits
versionRef
...
benchmark_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b82ec00778 | ||
|
|
8562af7754 | ||
|
|
42e4d5ea2c | ||
|
|
7414e9abcf | ||
|
|
4db40cafcc | ||
|
|
0587d9077a | ||
|
|
70647aa321 | ||
|
|
d8a36384f8 | ||
|
|
1a5c3cb49d | ||
|
|
572cc82ebc |
@@ -12,6 +12,7 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz/detect"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/mod/semver"
|
||||
@@ -55,7 +56,7 @@ func (o *OriginData) BlockBytes() []byte {
|
||||
}
|
||||
|
||||
func fname(prefix string, vu *detect.VersionedUnmarshaler, slot types.Slot, root [32]byte) string {
|
||||
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, vu.Fork.String(), slot, root)
|
||||
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, version.String(vu.Fork), slot, root)
|
||||
}
|
||||
|
||||
// DownloadFinalizedData downloads the most recently finalized state, and the block most recently applied to that state.
|
||||
@@ -69,7 +70,7 @@ func DownloadFinalizedData(ctx context.Context, client *Client) (*OriginData, er
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for finalized state")
|
||||
}
|
||||
log.Printf("detected supported config in remote finalized state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
log.Printf("detected supported config in remote finalized state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error unmarshaling finalized state to correct version")
|
||||
@@ -193,7 +194,7 @@ func computeBackwardsCompatible(ctx context.Context, client *Client) (*WeakSubje
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
@@ -244,7 +245,7 @@ func getWeakSubjectivityEpochFromHead(ctx context.Context, client *Client) (type
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, vu.Fork.String())
|
||||
log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
headState, err := vu.UnmarshalBeaconState(headBytes)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error unmarshaling state to correct version")
|
||||
|
||||
@@ -80,9 +80,9 @@ func TestHeadRoot_Nil(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_ForkChoiceStore(t *testing.T) {
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}}
|
||||
p := c.ForkChoiceStore()
|
||||
require.Equal(t, 0, int(p.FinalizedEpoch()))
|
||||
require.Equal(t, types.Epoch(0), p.FinalizedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
|
||||
@@ -327,7 +327,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)}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -357,7 +357,7 @@ func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||
|
||||
func TestService_ChainHeads_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -452,7 +452,7 @@ func TestService_IsOptimistic_ProtoArray(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -472,7 +472,7 @@ func TestService_IsOptimistic_DoublyLinkedTree(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -495,7 +495,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)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -510,7 +510,7 @@ func TestService_IsOptimisticForRoot_ProtoArray(t *testing.T) {
|
||||
|
||||
func TestService_IsOptimisticForRoot_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
@@ -526,7 +526,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)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 10
|
||||
@@ -591,7 +591,7 @@ func TestService_IsOptimisticForRoot_DB_ProtoArray(t *testing.T) {
|
||||
func TestService_IsOptimisticForRoot_DB_DoublyLinkedTree(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 10
|
||||
@@ -655,7 +655,7 @@ func TestService_IsOptimisticForRoot_DB_DoublyLinkedTree(t *testing.T) {
|
||||
func TestService_IsOptimisticForRoot_DB_non_canonical(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 10
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -142,7 +141,7 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if blk.Block().Version().IsPreBellatrix() {
|
||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
||||
return params.BeaconConfig().ZeroHash, nil
|
||||
}
|
||||
payload, err := blk.Block().Body().ExecutionPayload()
|
||||
@@ -154,14 +153,14 @@ func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, er
|
||||
|
||||
// notifyForkchoiceUpdate signals execution engine on a new payload.
|
||||
// It returns true if the EL has returned VALID for the block
|
||||
func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion version.ForkVersion,
|
||||
func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
|
||||
postStateHeader *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.notifyNewPayload")
|
||||
defer span.End()
|
||||
|
||||
// Execution payload is only supported in Bellatrix and beyond. Pre
|
||||
// merge blocks are never optimistic
|
||||
if postStateVersion.IsPreBellatrix() {
|
||||
if blocks.IsPreBellatrixVersion(postStateVersion) {
|
||||
return true, nil
|
||||
}
|
||||
if err := wrapper.BeaconBlockIsNil(blk); err != nil {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||
bstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -43,7 +44,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)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -184,7 +185,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
||||
fc := ðpb.Checkpoint{Epoch: 1, Root: tt.finalizedRoot[:]}
|
||||
fc := ðpb.Checkpoint{Epoch: 0, Root: tt.finalizedRoot[:]}
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'})
|
||||
arg := ¬ifyForkchoiceUpdateArg{
|
||||
@@ -289,7 +290,7 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbg))
|
||||
|
||||
// Insert blocks into forkchoice
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -326,7 +327,9 @@ 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, bra, []uint64{50, 100, 200})
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 0, Root: bra}
|
||||
require.NoError(t, fcs.UpdateJustifiedCheckpoint(jc))
|
||||
headRoot, err := fcs.Head(ctx, []uint64{50, 100, 200})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brg, headRoot)
|
||||
|
||||
@@ -347,7 +350,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, bra, service.justifiedBalances.balances)
|
||||
headRoot, err = fcs.Head(ctx, service.justifiedBalances.balances)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brd, headRoot)
|
||||
|
||||
@@ -364,7 +367,7 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -582,7 +585,7 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -625,7 +628,7 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -827,7 +830,7 @@ func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
stateGen := stategen.New(beaconDB)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stateGen),
|
||||
@@ -927,7 +930,7 @@ func TestService_removeInvalidBlockAndState(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
@@ -983,7 +986,7 @@ func TestService_getPayloadHash(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
@@ -95,16 +96,23 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) ([32]byte,
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
s.cfg.ForkChoiceStore = doublylinkedtree.New(j.Epoch, f.Epoch)
|
||||
s.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
} else {
|
||||
s.cfg.ForkChoiceStore = protoarray.New(j.Epoch, f.Epoch)
|
||||
s.cfg.ForkChoiceStore = protoarray.New()
|
||||
}
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, jb.Block(), headStartRoot, st, f, j); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return s.cfg.ForkChoiceStore.Head(ctx, headStartRoot, balances)
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: j.Epoch, Root: headStartRoot}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: f.Epoch, Root: s.ensureRootNotZeros(bytesutil.ToBytes32(f.Root))}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(jc); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fc); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
return s.cfg.ForkChoiceStore.Head(ctx, balances)
|
||||
}
|
||||
|
||||
// This saves head info to the local service cache, it also saves the
|
||||
|
||||
@@ -174,10 +174,8 @@ func TestUpdateHead_MissingJustifiedRoot(t *testing.T) {
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{'b'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{})
|
||||
headRoot, err := service.updateHead(context.Background(), []uint64{})
|
||||
_, err = service.updateHead(context.Background(), []uint64{})
|
||||
require.NoError(t, err)
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
require.NoError(t, service.saveHead(context.Background(), headRoot, wsb, st))
|
||||
}
|
||||
|
||||
func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
@@ -613,7 +611,7 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -630,7 +628,7 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
||||
fcp := ðpb.Checkpoint{
|
||||
Root: bellatrixBlkRoot[:],
|
||||
Epoch: 1,
|
||||
Epoch: 0,
|
||||
}
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(fcp, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(fcp, [32]byte{'b'})
|
||||
|
||||
@@ -67,7 +67,7 @@ func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justif
|
||||
log = log.WithField("justifiedEpoch", justified.Epoch)
|
||||
log = log.WithField("justifiedRoot", fmt.Sprintf("0x%s...", hex.EncodeToString(justified.Root)[:8]))
|
||||
log = log.WithField("parentRoot", fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]))
|
||||
log = log.WithField("version", block.Version().String())
|
||||
log = log.WithField("version", version.String(block.Version()))
|
||||
log = log.WithField("sinceSlotStartTime", prysmTime.Now().Sub(startTime))
|
||||
log = log.WithField("chainServiceProcessedTime", prysmTime.Now().Sub(receivedTime))
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
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/runtime/version"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -265,8 +266,8 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
|
||||
var b *precompute.Balance
|
||||
var v []*precompute.Validator
|
||||
var err error
|
||||
switch {
|
||||
case headState.Version().IsPhase0Compatible():
|
||||
switch headState.Version() {
|
||||
case version.Phase0:
|
||||
// Validator participation should be viewed on the canonical chain.
|
||||
v, b, err = precompute.New(ctx, headState)
|
||||
if err != nil {
|
||||
@@ -276,7 +277,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case headState.Version().IsParticipationBitsCompatible():
|
||||
case version.Altair, version.Bellatrix:
|
||||
v, b, err = altair.InitializePrecomputeValidators(ctx, headState)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
func testServiceOptsWithDB(t *testing.T) []Option {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
return []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -68,7 +70,8 @@ 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 {
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: bj.Epoch, Root: bytesutil.ToBytes32(bj.Root)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
func TestService_newSlot(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -109,7 +109,7 @@ func Test_validateMergeBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
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)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
@@ -28,7 +29,7 @@ func TestStore_OnAttestation_ErrorConditions_ProtoArray(t *testing.T) {
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
@@ -140,7 +141,7 @@ func TestStore_OnAttestation_ErrorConditions_DoublyLinkedTree(t *testing.T) {
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(doublylinkedtree.New(0, 0)),
|
||||
WithForkChoiceStore(doublylinkedtree.New()),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
@@ -250,7 +251,7 @@ func TestStore_OnAttestation_Ok_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -278,7 +279,7 @@ func TestStore_OnAttestation_Ok_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -487,7 +488,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -522,7 +523,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_DoublyLinkedTree(t *testing
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -610,7 +611,9 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, r32, []uint64{})
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 0, Root: r32}
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(jc))
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, []uint64{})
|
||||
require.NoError(t, err)
|
||||
err = service.VerifyFinalizedConsistency(context.Background(), r33[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -222,10 +222,12 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h)
|
||||
// Update Forkchoice checkpoints
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(psj); err != nil {
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: psj.Epoch, Root: bytesutil.ToBytes32(psj.Root)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(psf); err != nil {
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: psf.Epoch, Root: bytesutil.ToBytes32(psf.Root)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -317,15 +319,15 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
return s.handleEpochBoundary(ctx, postState)
|
||||
}
|
||||
|
||||
func getStateVersionAndPayload(st state.BeaconState) (version.ForkVersion, *ethpb.ExecutionPayloadHeader, error) {
|
||||
func getStateVersionAndPayload(st state.BeaconState) (int, *ethpb.ExecutionPayloadHeader, error) {
|
||||
if st == nil {
|
||||
return 0, nil, errors.New("nil state")
|
||||
}
|
||||
var preStateHeader *ethpb.ExecutionPayloadHeader
|
||||
var err error
|
||||
preStateVersion := st.Version()
|
||||
switch {
|
||||
case preStateVersion.IsPreBellatrix():
|
||||
switch preStateVersion {
|
||||
case version.Phase0, version.Altair:
|
||||
default:
|
||||
preStateHeader, err = st.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
@@ -378,7 +380,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
Messages: [][32]byte{},
|
||||
}
|
||||
type versionAndHeader struct {
|
||||
version version.ForkVersion
|
||||
version int
|
||||
header *ethpb.ExecutionPayloadHeader
|
||||
}
|
||||
preVersionAndHeaders := make([]*versionAndHeader, len(blks))
|
||||
@@ -441,8 +443,8 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
}
|
||||
}
|
||||
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
||||
JustifiedEpoch: jCheckpoints[i].Epoch,
|
||||
FinalizedEpoch: fCheckpoints[i].Epoch}
|
||||
JustifiedCheckpoint: jCheckpoints[i],
|
||||
FinalizedCheckpoint: fCheckpoints[i]}
|
||||
pendingNodes[len(blks)-i-1] = args
|
||||
s.saveInitSyncBlock(blockRoots[i], b)
|
||||
if err = s.handleBlockAfterBatchVerify(ctx, b, blockRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
||||
@@ -461,7 +463,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
}
|
||||
// Prune forkchoice store only if the new finalized checkpoint is higher
|
||||
// than the finalized checkpoint in forkchoice store.
|
||||
if fCheckpoints[len(blks)-1].Epoch > s.cfg.ForkChoiceStore.FinalizedEpoch() {
|
||||
if fCheckpoints[len(blks)-1].Epoch > s.cfg.ForkChoiceStore.FinalizedCheckpoint().Epoch {
|
||||
if err := s.cfg.ForkChoiceStore.Prune(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(fCheckpoints[len(blks)-1].Root))); err != nil {
|
||||
return errors.Wrap(err, "could not prune fork choice nodes")
|
||||
}
|
||||
@@ -543,7 +545,8 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
|
||||
return err
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(fCheckpoint, h)
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fCheckpoint); err != nil {
|
||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: fCheckpoint.Epoch, Root: bytesutil.ToBytes32(fCheckpoint.Root)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -684,9 +687,9 @@ func (s *Service) pruneCanonicalAttsFromPool(ctx context.Context, r [32]byte, b
|
||||
}
|
||||
|
||||
// validateMergeTransitionBlock validates the merge transition block.
|
||||
func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion version.ForkVersion, stateHeader *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) error {
|
||||
func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion int, stateHeader *ethpb.ExecutionPayloadHeader, blk interfaces.SignedBeaconBlock) error {
|
||||
// Skip validation if block is older than Bellatrix.
|
||||
if blk.Block().Version().IsPreBellatrix() {
|
||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -701,7 +704,7 @@ func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion
|
||||
|
||||
// Handle case where pre-state is Altair but block contains payload.
|
||||
// To reach here, the block must have contained a valid payload.
|
||||
if stateVersion.IsPreBellatrix() {
|
||||
if blocks.IsPreBellatrixVersion(stateVersion) {
|
||||
return s.validateMergeBlock(ctx, blk)
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,8 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(cpt, h)
|
||||
// Update forkchoice's justified checkpoint
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(cpt); err != nil {
|
||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: cpt.Epoch, Root: bytesutil.ToBytes32(cpt.Root)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -244,7 +245,8 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(cp, h)
|
||||
return s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(cp)
|
||||
return s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||
Epoch: cp.Epoch, Root: bytesutil.ToBytes32(cp.Root)})
|
||||
}
|
||||
|
||||
func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) error {
|
||||
@@ -360,7 +362,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
||||
return err
|
||||
}
|
||||
pendingNodes = append(pendingNodes, &forkchoicetypes.BlockAndCheckpoints{Block: blk,
|
||||
JustifiedEpoch: jCheckpoint.Epoch, FinalizedEpoch: fCheckpoint.Epoch})
|
||||
JustifiedCheckpoint: jCheckpoint, FinalizedCheckpoint: fCheckpoint})
|
||||
// As long as parent node is not in fork choice store, and parent node is in DB.
|
||||
root := bytesutil.ToBytes32(blk.ParentRoot())
|
||||
for !s.cfg.ForkChoiceStore.HasNode(root) && s.cfg.BeaconDB.HasBlock(ctx, root) {
|
||||
@@ -373,8 +375,8 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
||||
}
|
||||
root = bytesutil.ToBytes32(b.Block().ParentRoot())
|
||||
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
||||
JustifiedEpoch: jCheckpoint.Epoch,
|
||||
FinalizedEpoch: fCheckpoint.Epoch}
|
||||
JustifiedCheckpoint: jCheckpoint,
|
||||
FinalizedCheckpoint: fCheckpoint}
|
||||
pendingNodes = append(pendingNodes, args)
|
||||
}
|
||||
if len(pendingNodes) == 1 {
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestStore_OnBlock_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -150,7 +150,7 @@ func TestStore_OnBlock_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -253,7 +253,7 @@ func TestStore_OnBlock_ProposerBoostEarly(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
fcs := doublylinkedtree.New()
|
||||
opts := []Option{
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(fcs),
|
||||
@@ -268,7 +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, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, []uint64{})
|
||||
require.ErrorContains(t, "could not apply proposer boost score: invalid proposer boost root", err)
|
||||
}
|
||||
|
||||
@@ -293,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)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -340,7 +340,7 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
jroot := bytesutil.ToBytes32(jcp.Root)
|
||||
require.Equal(t, blkRoots[63], jroot)
|
||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
||||
@@ -362,7 +362,7 @@ func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -427,7 +427,7 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(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 = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -474,7 +474,7 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
jroot := bytesutil.ToBytes32(jcp.Root)
|
||||
require.Equal(t, blkRoots[63], jroot)
|
||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
|
||||
@@ -496,7 +496,7 @@ func TestStore_OnBlockBatch_NotifyNewPayload(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 = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
st, keys := util.DeterministicGenesisState(t, 64)
|
||||
bState := st.Copy()
|
||||
@@ -577,7 +577,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)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
lastJustifiedBlk := util.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||
@@ -610,7 +610,7 @@ func TestShouldUpdateJustified_ReturnFalse_DoublyLinkedTree(t *testing.T) {
|
||||
opts := testServiceOptsWithDB(t)
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
lastJustifiedBlk := util.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||
@@ -657,7 +657,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)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -694,7 +694,7 @@ func TestCachedPreState_CanGetFromStateSummary_DoublyLinkedTree(t *testing.T) {
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -728,7 +728,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)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
@@ -759,7 +759,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
@@ -805,7 +805,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -851,7 +851,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_DoublyLinkedTree(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -898,7 +898,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -947,7 +947,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_DoublyLinkedTree(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -996,7 +996,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_ProtoArray(t *testing.T) {
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -1063,7 +1063,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_DoublyLinkedTree(t *testing
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -1131,7 +1131,7 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling_DoublyLinkedTree(t *testin
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -1272,7 +1272,7 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1363,7 +1363,7 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1425,7 +1425,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -1570,7 +1570,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)
|
||||
fcs := protoarray.New()
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1626,7 +1626,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)
|
||||
fcs := protoarray.New()
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1645,7 +1645,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)
|
||||
fcs := protoarray.New()
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1686,7 +1686,7 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -1924,7 +1924,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -2052,7 +2052,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)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
@@ -2103,7 +2103,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)
|
||||
fcs := protoarray.New()
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts := []Option{
|
||||
@@ -2175,7 +2175,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)
|
||||
service.cfg.ForkChoiceStore = protoarray.New()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2183,7 +2183,7 @@ func Test_verifyBlkFinalizedSlot_invalidBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
fcs := protoarray.New(0, 0)
|
||||
fcs := protoarray.New()
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
|
||||
@@ -127,7 +127,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
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)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
WithAttestationPool(attestations.NewPool()),
|
||||
WithExitPool(voluntaryexits.NewPool()),
|
||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||
@@ -248,7 +248,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
@@ -208,11 +209,20 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
var forkChoicer f.ForkChoicer
|
||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
forkChoicer = doublylinkedtree.New(justified.Epoch, finalized.Epoch)
|
||||
forkChoicer = doublylinkedtree.New()
|
||||
} else {
|
||||
forkChoicer = protoarray.New(justified.Epoch, finalized.Epoch)
|
||||
forkChoicer = protoarray.New()
|
||||
}
|
||||
s.cfg.ForkChoiceStore = forkChoicer
|
||||
if err := forkChoicer.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: justified.Epoch,
|
||||
Root: bytesutil.ToBytes32(justified.Root)}); err != nil {
|
||||
return errors.Wrap(err, "could not update forkchoice's justified checkpoint")
|
||||
}
|
||||
if err := forkChoicer.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: finalized.Epoch,
|
||||
Root: bytesutil.ToBytes32(finalized.Root)}); err != nil {
|
||||
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
|
||||
}
|
||||
|
||||
st, err := s.cfg.StateGen.StateByRoot(s.ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized checkpoint state")
|
||||
|
||||
@@ -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)),
|
||||
WithForkChoiceStore(protoarray.New()),
|
||||
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), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
@@ -526,7 +526,7 @@ func TestHasBlock_ForkChoiceAndDB_DoublyLinkedTree(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(), 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), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
@@ -622,7 +622,7 @@ func BenchmarkHasBlockForkChoiceStore_DoublyLinkedTree(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
s := &Service{
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
|
||||
@@ -32,7 +32,7 @@ func (c *SyncCommitteeHeadStateCache) Put(slot types.Slot, st state.BeaconState)
|
||||
return ErrNilValueProvided
|
||||
}
|
||||
|
||||
if st.Version().IsPhase0Compatible() {
|
||||
if st.Version() == version.Phase0 {
|
||||
return ErrIncorrectType
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/slashings"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -78,11 +79,11 @@ func ProcessAttesterSlashing(
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version().IsPhase0Compatible():
|
||||
case beaconState.Version() == version.Phase0:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version().IsAltairCompatible():
|
||||
case beaconState.Version() == version.Altair:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
case beaconState.Version().IsBellatrixCompatible():
|
||||
case beaconState.Version() == version.Bellatrix:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -32,7 +33,7 @@ func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
|
||||
if st == nil {
|
||||
return false, errors.New("nil state")
|
||||
}
|
||||
if st.Version().IsPreBellatrix() {
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
return false, nil
|
||||
}
|
||||
h, err := st.LatestExecutionPayloadHeader()
|
||||
@@ -85,7 +86,7 @@ func IsExecutionEnabled(st state.BeaconState, body interfaces.BeaconBlockBody) (
|
||||
if st == nil || body == nil {
|
||||
return false, errors.New("nil state or block body")
|
||||
}
|
||||
if st.Version().IsPreBellatrix() {
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
return false, nil
|
||||
}
|
||||
header, err := st.LatestExecutionPayloadHeader()
|
||||
@@ -104,6 +105,11 @@ func IsExecutionEnabledUsingHeader(header *ethpb.ExecutionPayloadHeader, body in
|
||||
return IsExecutionBlock(body)
|
||||
}
|
||||
|
||||
// IsPreBellatrixVersion returns true if input version is before bellatrix fork.
|
||||
func IsPreBellatrixVersion(v int) bool {
|
||||
return v < version.Bellatrix
|
||||
}
|
||||
|
||||
// ValidatePayloadWhenMergeCompletes validates if payload is valid versus input beacon state.
|
||||
// These validation steps ONLY apply to post merge.
|
||||
//
|
||||
@@ -270,7 +276,7 @@ func ProcessPayloadHeader(st state.BeaconState, header *ethpb.ExecutionPayloadHe
|
||||
// GetBlockPayloadHash returns the hash of the execution payload of the block
|
||||
func GetBlockPayloadHash(blk interfaces.BeaconBlock) ([32]byte, error) {
|
||||
payloadHash := [32]byte{}
|
||||
if blk.Version().IsPreBellatrix() {
|
||||
if IsPreBellatrixVersion(blk.Version()) {
|
||||
return payloadHash, nil
|
||||
}
|
||||
payload, err := blk.Body().ExecutionPayload()
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"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/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
@@ -76,11 +77,11 @@ func ProcessProposerSlashing(
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version().IsPhase0Compatible():
|
||||
case beaconState.Version() == version.Phase0:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version().IsAltairCompatible():
|
||||
case beaconState.Version() == version.Altair:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
case beaconState.Version().IsBellatrixCompatible():
|
||||
case beaconState.Version() == version.Bellatrix:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
|
||||
@@ -171,7 +171,7 @@ func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *et
|
||||
}
|
||||
|
||||
// UpdateBalance updates pre computed balance store.
|
||||
func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion version.ForkVersion) *Balance {
|
||||
func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion int) *Balance {
|
||||
for _, v := range vp {
|
||||
if !v.IsSlashed {
|
||||
if v.IsCurrentEpochAttester {
|
||||
@@ -180,10 +180,10 @@ func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion version.ForkVers
|
||||
if v.IsCurrentEpochTargetAttester {
|
||||
bBal.CurrentEpochTargetAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if stateVersion.IsPhase0Compatible() && v.IsPrevEpochAttester {
|
||||
if stateVersion == version.Phase0 && v.IsPrevEpochAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if stateVersion.IsHigherOrEqualToAltair() && v.IsPrevEpochSourceAttester {
|
||||
if (stateVersion == version.Altair || stateVersion == version.Bellatrix) && v.IsPrevEpochSourceAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if v.IsPrevEpochTargetAttester {
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"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/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -47,7 +48,7 @@ func NextEpoch(state state.ReadOnlyBeaconState) types.Epoch {
|
||||
|
||||
// HigherEqualThanAltairVersionAndEpoch returns if the input state `s` has a higher version number than Altair state and input epoch `e` is higher equal than fork epoch.
|
||||
func HigherEqualThanAltairVersionAndEpoch(s state.BeaconState, e types.Epoch) bool {
|
||||
return s.Version().IsHigherOrEqualToAltair() && e >= params.BeaconConfig().AltairForkEpoch
|
||||
return s.Version() >= version.Altair && e >= params.BeaconConfig().AltairForkEpoch
|
||||
}
|
||||
|
||||
// CanUpgradeToAltair returns true if the input `slot` can upgrade to Altair.
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/math"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -247,14 +248,14 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
return nil, errors.Wrap(err, "could not process slot")
|
||||
}
|
||||
if time.CanProcessEpoch(state) {
|
||||
switch {
|
||||
case state.Version().IsPhase0Compatible():
|
||||
switch state.Version() {
|
||||
case version.Phase0:
|
||||
state, err = ProcessEpochPrecompute(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, "could not process epoch with optimizations")
|
||||
}
|
||||
case state.Version().IsHigherOrEqualToAltair():
|
||||
case version.Altair, version.Bellatrix:
|
||||
state, err = altair.ProcessEpoch(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"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"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -231,13 +232,13 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
}
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case signedBeaconBlock.Version().IsPhase0Compatible():
|
||||
switch signedBeaconBlock.Version() {
|
||||
case version.Phase0:
|
||||
state, err = phase0Operations(ctx, state, signedBeaconBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case signedBeaconBlock.Version().IsHigherOrEqualToAltair():
|
||||
case version.Altair, version.Bellatrix:
|
||||
state, err = altairOperations(ctx, state, signedBeaconBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -328,7 +329,7 @@ func ProcessBlockForStateRoot(
|
||||
return nil, errors.Wrap(err, "could not process block operation")
|
||||
}
|
||||
|
||||
if signed.Block().Version().IsPhase0Compatible() {
|
||||
if signed.Block().Version() == version.Phase0 {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/container/slice"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -793,14 +794,14 @@ func marshalBlock(_ context.Context, blk interfaces.SignedBeaconBlock) ([]byte,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case blk.Version().IsBlindedBlockCompatible():
|
||||
switch blk.Version() {
|
||||
case version.BellatrixBlind:
|
||||
return snappy.Encode(nil, append(bellatrixBlindKey, obj...)), nil
|
||||
case blk.Version().IsBellatrixCompatible():
|
||||
case version.Bellatrix:
|
||||
return snappy.Encode(nil, append(bellatrixKey, obj...)), nil
|
||||
case blk.Version().IsAltairCompatible():
|
||||
case version.Altair:
|
||||
return snappy.Encode(nil, append(altairKey, obj...)), nil
|
||||
case blk.Version().IsPhase0Compatible():
|
||||
case version.Phase0:
|
||||
return snappy.Encode(nil, obj), nil
|
||||
default:
|
||||
return nil, errors.New("Unknown block version")
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz/detect"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// SaveOrigin loads an ssz serialized Block & BeaconState from an io.Reader
|
||||
@@ -37,7 +38,7 @@ func (s *Store) SaveOrigin(ctx context.Context, serState, serBlock []byte) error
|
||||
return fmt.Errorf("config mismatch, beacon node configured to connect to %s, detected state is for %s", params.BeaconConfig().ConfigName, cf.Config.ConfigName)
|
||||
}
|
||||
|
||||
log.Infof("detected supported config for state & block version, config name=%s, fork name=%s", cf.Config.ConfigName, cf.Fork.String())
|
||||
log.Infof("detected supported config for state & block version, config name=%s, fork name=%s", cf.Config.ConfigName, version.String(cf.Fork))
|
||||
state, err := cf.UnmarshalBeaconState(serState)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize origin state w/ bytes + config+fork")
|
||||
|
||||
@@ -21,6 +21,8 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/forkchoice:go_default_library",
|
||||
"//beacon-chain/forkchoice/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
@@ -16,7 +17,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -46,7 +47,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||
|
||||
@@ -58,8 +59,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- head
|
||||
// |
|
||||
// 3
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(2), Epoch: 1}
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||
|
||||
@@ -71,8 +72,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- start
|
||||
// |
|
||||
// 3 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(3), Epoch: 2}
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||
}
|
||||
@@ -82,7 +83,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -143,7 +144,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -173,7 +174,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// head -> 9 10
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -203,19 +204,21 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(1)}
|
||||
r, err = f.Head(context.Background(), 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 {
|
||||
ctx := context.Background()
|
||||
f := New(justifiedEpoch, finalizedEpoch)
|
||||
f := New()
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: justifiedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: finalizedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 0, params.BeaconConfig().ZeroHash, [32]byte{}, params.BeaconConfig().ZeroHash, justifiedEpoch, finalizedEpoch)
|
||||
if err != nil {
|
||||
return nil
|
||||
|
||||
@@ -3,9 +3,12 @@ package doublylinkedtree
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -13,22 +16,22 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// New initializes a new fork choice store.
|
||||
func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
func New() *ForkChoice {
|
||||
s := &Store{
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
proposerBoostRoot: [32]byte{},
|
||||
nodeByRoot: make(map[[fieldparams.RootLength]byte]*Node),
|
||||
nodeByPayload: make(map[[fieldparams.RootLength]byte]*Node),
|
||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||
pruneThreshold: defaultPruneThreshold,
|
||||
justifiedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||
finalizedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||
proposerBoostRoot: [32]byte{},
|
||||
nodeByRoot: make(map[[fieldparams.RootLength]byte]*Node),
|
||||
nodeByPayload: make(map[[fieldparams.RootLength]byte]*Node),
|
||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||
pruneThreshold: defaultPruneThreshold,
|
||||
}
|
||||
|
||||
b := make([]uint64, 0)
|
||||
@@ -47,7 +50,6 @@ 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,
|
||||
justifiedRoot [32]byte,
|
||||
justifiedStateBalances []uint64,
|
||||
) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.Head")
|
||||
@@ -73,10 +75,12 @@ func (f *ForkChoice) Head(
|
||||
return [32]byte{}, errors.Wrap(err, "could not apply weight changes")
|
||||
}
|
||||
|
||||
if err := f.store.treeRootNode.updateBestDescendant(ctx, f.store.justifiedEpoch, f.store.finalizedEpoch); err != nil {
|
||||
jc := f.JustifiedCheckpoint()
|
||||
fc := f.FinalizedCheckpoint()
|
||||
if err := f.store.treeRootNode.updateBestDescendant(ctx, jc.Epoch, fc.Epoch); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not update best descendant")
|
||||
}
|
||||
return f.store.head(ctx, justifiedRoot)
|
||||
return f.store.head(ctx)
|
||||
}
|
||||
|
||||
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
||||
@@ -108,7 +112,7 @@ func (f *ForkChoice) ProcessAttestation(ctx context.Context, validatorIndices []
|
||||
}
|
||||
|
||||
// InsertNode processes a new block by inserting it to the fork choice store.
|
||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconState, root [32]byte) error {
|
||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, root [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.InsertNode")
|
||||
defer span.End()
|
||||
|
||||
@@ -138,6 +142,32 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconS
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
finalizedEpoch := fc.Epoch
|
||||
go func() {
|
||||
// compute unrealized checkpoints at N+2
|
||||
start := time.Now()
|
||||
|
||||
stCopy := state.Copy()
|
||||
copyTime := time.Since(start)
|
||||
nextStart := stCopy.Slot() + params.BeaconConfig().SlotsPerEpoch
|
||||
nextStart = nextStart - nextStart%params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
stCopy, err := transition.ProcessSlots(ctx, stCopy, nextStart)
|
||||
_ = err
|
||||
transitionTime := time.Since(start)
|
||||
ujc, ufc, err := precompute.UnrealizedCheckpoints(stCopy)
|
||||
_ = err
|
||||
elapsed := time.Since(start)
|
||||
log.WithFields(logrus.Fields{
|
||||
"copyTime": copyTime,
|
||||
"epochTransTime": transitionTime - copyTime,
|
||||
"unrealizedJustTime": elapsed - transitionTime,
|
||||
"totalElapsed": elapsed,
|
||||
"CurrentJustification": jc.Epoch,
|
||||
"UnrealizedJustification": ujc.Epoch,
|
||||
"UnrealizedFinalization": ufc.Epoch,
|
||||
}).Info("Pulled block to N+2")
|
||||
}()
|
||||
|
||||
return f.store.insert(ctx, slot, root, parentRoot, payloadHash, justifiedEpoch, finalizedEpoch)
|
||||
}
|
||||
|
||||
@@ -326,20 +356,24 @@ func (f *ForkChoice) SetOptimisticToValid(ctx context.Context, root [fieldparams
|
||||
return node.setNodeAndParentValidated(ctx)
|
||||
}
|
||||
|
||||
// JustifiedEpoch of fork choice store.
|
||||
func (f *ForkChoice) JustifiedEpoch() types.Epoch {
|
||||
return f.store.justifiedEpoch
|
||||
// JustifiedCheckpoint of fork choice store.
|
||||
func (f *ForkChoice) JustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||
f.store.checkpointsLock.RLock()
|
||||
defer f.store.checkpointsLock.RUnlock()
|
||||
return f.store.justifiedCheckpoint
|
||||
}
|
||||
|
||||
// FinalizedEpoch of fork choice store.
|
||||
func (f *ForkChoice) FinalizedEpoch() types.Epoch {
|
||||
return f.store.finalizedEpoch
|
||||
// FinalizedCheckpoint of fork choice store.
|
||||
func (f *ForkChoice) FinalizedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||
f.store.checkpointsLock.RLock()
|
||||
defer f.store.checkpointsLock.RUnlock()
|
||||
return f.store.finalizedCheckpoint
|
||||
}
|
||||
|
||||
func (f *ForkChoice) ForkChoiceNodes() []*pbrpc.ForkChoiceNode {
|
||||
func (f *ForkChoice) ForkChoiceNodes() []*ethpb.ForkChoiceNode {
|
||||
f.store.nodesLock.RLock()
|
||||
defer f.store.nodesLock.RUnlock()
|
||||
ret := make([]*pbrpc.ForkChoiceNode, len(f.store.nodeByRoot))
|
||||
ret := make([]*ethpb.ForkChoiceNode, len(f.store.nodeByRoot))
|
||||
return f.store.treeRootNode.rpcNodes(ret)
|
||||
}
|
||||
|
||||
@@ -384,25 +418,25 @@ func (f *ForkChoice) InsertSlashedIndex(_ context.Context, index types.Validator
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
||||
// UpdateJustifiedCheckpoint sets the justified checkpoint to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *forkchoicetypes.Checkpoint) error {
|
||||
if jc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.justifiedEpoch = jc.Epoch
|
||||
f.store.checkpointsLock.Lock()
|
||||
defer f.store.checkpointsLock.Unlock()
|
||||
f.store.justifiedCheckpoint = jc
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
||||
// UpdateFinalizedCheckpoint sets the finalized checkpoint to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *forkchoicetypes.Checkpoint) error {
|
||||
if fc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.finalizedEpoch = fc.Epoch
|
||||
f.store.checkpointsLock.Lock()
|
||||
defer f.store.checkpointsLock.Unlock()
|
||||
f.store.finalizedCheckpoint = fc
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -473,7 +507,7 @@ func (f *ForkChoice) InsertOptimisticChain(ctx context.Context, chain []*forkcho
|
||||
}
|
||||
if err := f.store.insert(ctx,
|
||||
b.Slot(), r, parentRoot, payloadHash,
|
||||
chain[i].JustifiedEpoch, chain[i].FinalizedEpoch); err != nil {
|
||||
chain[i].JustifiedCheckpoint.Epoch, chain[i].FinalizedCheckpoint.Epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,9 @@ func TestForkChoice_IsCanonicalReorg(t *testing.T) {
|
||||
require.DeepEqual(t, [32]byte{'3'}, f.store.treeRootNode.bestDescendant.root)
|
||||
f.store.nodesLock.Unlock()
|
||||
|
||||
h, err := f.store.head(ctx, [32]byte{'1'})
|
||||
r1 := [32]byte{'1'}
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 1, Root: r1}
|
||||
h, err := f.store.head(ctx)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, [32]byte{'3'}, h)
|
||||
require.DeepEqual(t, h, f.store.headNode.root)
|
||||
@@ -296,7 +298,7 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
head, err := f.Head(ctx, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'a'}, head)
|
||||
|
||||
@@ -307,21 +309,21 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
head, err = f.Head(ctx, []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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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)
|
||||
@@ -330,7 +332,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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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)
|
||||
@@ -352,12 +354,14 @@ 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}
|
||||
jc := &forkchoicetypes.Checkpoint{Root: jr, Epoch: 3}
|
||||
fc := &forkchoicetypes.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)
|
||||
require.Equal(t, f.store.justifiedCheckpoint.Epoch, jc.Epoch)
|
||||
require.Equal(t, f.store.justifiedCheckpoint.Root, jc.Root)
|
||||
require.Equal(t, f.store.finalizedCheckpoint.Epoch, fc.Epoch)
|
||||
require.Equal(t, f.store.finalizedCheckpoint.Root, fc.Root)
|
||||
}
|
||||
|
||||
func TestStore_CommonAncestor(t *testing.T) {
|
||||
@@ -562,8 +566,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
||||
FinalizedEpoch: 1})
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
})
|
||||
for i := uint64(2); i < 11; i++ {
|
||||
blk := util.NewBeaconBlock()
|
||||
blk.Block.Slot = types.Slot(i)
|
||||
@@ -571,8 +577,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||
blk.Block.ParentRoot = copiedRoot[:]
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
||||
FinalizedEpoch: 1})
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
})
|
||||
root, err = blk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
if r != params.BeaconConfig().ZeroHash {
|
||||
t.Errorf("Incorrect head with genesis")
|
||||
@@ -28,7 +28,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -65,7 +65,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -92,7 +92,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// head -> 4 3
|
||||
// |
|
||||
// 5 <- starting from 5 with justified epoch 0 should error
|
||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
f.store.justifiedCheckpoint.Root = indexToHash(5)
|
||||
_, err = f.Head(context.Background(), balances)
|
||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||
require.ErrorContains(t, wanted, err)
|
||||
|
||||
@@ -104,8 +105,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// 4 3
|
||||
// |
|
||||
// 5 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
f.store.justifiedCheckpoint.Epoch = 2
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -122,7 +123,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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, zeroHash, balances)
|
||||
headRoot, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -108,7 +108,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -144,7 +144,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
}
|
||||
|
||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||
|
||||
@@ -186,7 +186,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, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
||||
|
||||
@@ -195,7 +195,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, zeroHash, balances)
|
||||
r, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -220,7 +220,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure the head is C, the honest block.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -260,7 +260,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
||||
|
||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
})
|
||||
@@ -268,7 +268,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, zeroHash, balances)
|
||||
r, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -295,7 +295,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -314,7 +314,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -333,7 +333,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, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||
})
|
||||
@@ -355,7 +355,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
a := zeroHash
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
r, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -374,7 +374,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -402,7 +402,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is still the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -426,7 +426,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// D cannot win without a boost.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||
|
||||
@@ -442,7 +442,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, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, d, r, "Expected D to become the head")
|
||||
})
|
||||
|
||||
@@ -60,12 +60,12 @@ func (s *Store) PruneThreshold() uint64 {
|
||||
|
||||
// head starts from justified root and then follows the best descendant links
|
||||
// to find the best block for head. This function assumes a lock on s.nodesLock
|
||||
func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, error) {
|
||||
func (s *Store) head(ctx context.Context) ([32]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.head")
|
||||
defer span.End()
|
||||
|
||||
// JustifiedRoot has to be known
|
||||
justifiedNode, ok := s.nodeByRoot[justifiedRoot]
|
||||
justifiedNode, ok := s.nodeByRoot[s.justifiedCheckpoint.Root]
|
||||
if !ok || justifiedNode == nil {
|
||||
return [32]byte{}, errUnknownJustifiedRoot
|
||||
}
|
||||
@@ -77,9 +77,9 @@ func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, err
|
||||
bestDescendant = justifiedNode
|
||||
}
|
||||
|
||||
if !bestDescendant.viableForHead(s.justifiedEpoch, s.finalizedEpoch) {
|
||||
if !bestDescendant.viableForHead(s.justifiedCheckpoint.Epoch, s.finalizedCheckpoint.Epoch) {
|
||||
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
||||
bestDescendant.slot, bestDescendant.weight/10e9, bestDescendant.finalizedEpoch, s.finalizedEpoch, bestDescendant.justifiedEpoch, s.justifiedEpoch)
|
||||
bestDescendant.slot, bestDescendant.weight/10e9, bestDescendant.finalizedEpoch, s.finalizedCheckpoint.Epoch, bestDescendant.justifiedEpoch, s.justifiedCheckpoint.Epoch)
|
||||
}
|
||||
|
||||
// Update metrics.
|
||||
@@ -134,7 +134,8 @@ func (s *Store) insert(ctx context.Context,
|
||||
}
|
||||
} else {
|
||||
parent.children = append(parent.children, n)
|
||||
if err := s.treeRootNode.updateBestDescendant(ctx, s.justifiedEpoch, s.finalizedEpoch); err != nil {
|
||||
if err := s.treeRootNode.updateBestDescendant(ctx,
|
||||
s.justifiedCheckpoint.Epoch, s.finalizedCheckpoint.Epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
@@ -22,13 +23,13 @@ func TestStore_PruneThreshold(t *testing.T) {
|
||||
func TestStore_JustifiedEpoch(t *testing.T) {
|
||||
j := types.Epoch(100)
|
||||
f := setup(j, j)
|
||||
require.Equal(t, j, f.JustifiedEpoch())
|
||||
require.Equal(t, j, f.JustifiedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestStore_FinalizedEpoch(t *testing.T) {
|
||||
j := types.Epoch(50)
|
||||
f := setup(j, j)
|
||||
require.Equal(t, j, f.FinalizedEpoch())
|
||||
require.Equal(t, j, f.FinalizedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestStore_NodeCount(t *testing.T) {
|
||||
@@ -78,7 +79,8 @@ func TestForkChoice_HasNode(t *testing.T) {
|
||||
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
|
||||
_, err := f.store.head(context.Background(), [32]byte{'a'})
|
||||
f.store.justifiedCheckpoint.Root = [32]byte{'a'}
|
||||
_, err := f.store.head(context.Background())
|
||||
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
||||
}
|
||||
|
||||
@@ -90,7 +92,8 @@ func TestStore_Head_Itself(t *testing.T) {
|
||||
|
||||
// Since the justified node does not have a best descendant so the best node
|
||||
// is itself.
|
||||
h, err := f.store.head(context.Background(), indexToHash(1))
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: indexToHash(1)}
|
||||
h, err := f.store.head(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(1), h)
|
||||
}
|
||||
@@ -110,7 +113,8 @@ func TestStore_Head_BestDescendant(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
h, err := f.store.head(context.Background(), indexToHash(1))
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: indexToHash(1)}
|
||||
h, err := f.store.head(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, h, indexToHash(4))
|
||||
}
|
||||
@@ -133,7 +137,9 @@ func TestStore_Insert(t *testing.T) {
|
||||
treeRootNode := &Node{slot: 0, root: indexToHash(0)}
|
||||
nodeByRoot := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
||||
nodeByPayload := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
||||
s := &Store{nodeByRoot: nodeByRoot, treeRootNode: treeRootNode, nodeByPayload: nodeByPayload}
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 0}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 0}
|
||||
s := &Store{nodeByRoot: nodeByRoot, treeRootNode: treeRootNode, nodeByPayload: nodeByPayload, justifiedCheckpoint: jc, finalizedCheckpoint: fc}
|
||||
payloadHash := [32]byte{'a'}
|
||||
require.NoError(t, s.insert(context.Background(), 100, indexToHash(100), indexToHash(0), payloadHash, 1, 1))
|
||||
assert.Equal(t, 2, len(s.nodeByRoot), "Did not insert block")
|
||||
|
||||
@@ -3,6 +3,7 @@ package doublylinkedtree
|
||||
import (
|
||||
"sync"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
)
|
||||
@@ -17,8 +18,8 @@ type ForkChoice struct {
|
||||
|
||||
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
||||
type Store struct {
|
||||
justifiedEpoch types.Epoch // latest justified epoch in store.
|
||||
finalizedEpoch types.Epoch // latest finalized epoch in store.
|
||||
justifiedCheckpoint *forkchoicetypes.Checkpoint // latest justified epoch in store.
|
||||
finalizedCheckpoint *forkchoicetypes.Checkpoint // latest finalized epoch in store.
|
||||
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
||||
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.
|
||||
@@ -30,6 +31,7 @@ type Store struct {
|
||||
slashedIndices map[types.ValidatorIndex]bool // the list of equivocating validator indices
|
||||
nodesLock sync.RWMutex
|
||||
proposerBoostLock sync.RWMutex
|
||||
checkpointsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||
|
||||
@@ -44,11 +44,11 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
||||
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.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
|
||||
f.store.justifiedCheckpoint.Epoch = node.justifiedEpoch
|
||||
}
|
||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
||||
f.store.finalizedEpoch = node.finalizedEpoch
|
||||
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
|
||||
f.store.finalizedCheckpoint.Epoch = node.finalizedEpoch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -80,17 +80,17 @@ func TestStore_LongFork(t *testing.T) {
|
||||
|
||||
// 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})
|
||||
headRoot, err := f.Head(ctx, []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'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||
ha := [32]byte{'a'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 2, Root: ha}))
|
||||
headRoot, err = f.Head(ctx, []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)
|
||||
@@ -98,7 +98,7 @@ func TestStore_LongFork(t *testing.T) {
|
||||
|
||||
// Update unrealized justification, c becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err = f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
}
|
||||
@@ -157,30 +157,31 @@ func TestStore_NoDeadLock(t *testing.T) {
|
||||
|
||||
// Epoch 3
|
||||
// Current Head is H
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err := f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||
|
||||
// Insert Block I, it becomes Head
|
||||
hr := [32]byte{'i'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
ha := [32]byte{'a'}
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 1, Root: ha}))
|
||||
headRoot, err = f.Head(ctx, []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())
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||
require.Equal(t, types.Epoch(0), f.FinalizedCheckpoint().Epoch)
|
||||
|
||||
// Realized Justified checkpoints, H becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err = f.Head(ctx, []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())
|
||||
require.Equal(t, types.Epoch(2), f.JustifiedCheckpoint().Epoch)
|
||||
require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
// Epoch 1 | Epoch 2
|
||||
@@ -225,10 +226,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
|
||||
// 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})
|
||||
headRoot, err := f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||
|
||||
// D arrives late, D is head
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
||||
@@ -236,10 +237,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err = f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
||||
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'h'}].weight)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -15,7 +16,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -27,7 +28,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -39,7 +40,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -48,7 +49,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -57,7 +58,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -71,7 +72,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -82,7 +83,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -93,7 +94,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- head
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -109,7 +110,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -127,7 +128,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -188,7 +189,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -209,9 +210,9 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 8
|
||||
// |
|
||||
// 9 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
f.store.finalizedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(5), Epoch: 2}
|
||||
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(5), Epoch: 2}
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -237,7 +238,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -246,28 +247,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -276,7 +277,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -300,7 +301,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -318,7 +319,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ type ForkChoicer interface {
|
||||
|
||||
// HeadRetriever retrieves head root and optimistic info of the current chain.
|
||||
type HeadRetriever interface {
|
||||
Head(context.Context, [32]byte, []uint64) ([32]byte, error)
|
||||
Head(context.Context, []uint64) ([32]byte, error)
|
||||
Tips() ([][32]byte, []types.Slot)
|
||||
IsOptimistic(root [32]byte) (bool, error)
|
||||
}
|
||||
|
||||
// BlockProcessor processes the block that's used for accounting fork choice.
|
||||
type BlockProcessor interface {
|
||||
InsertNode(context.Context, state.ReadOnlyBeaconState, [32]byte) error
|
||||
InsertNode(context.Context, state.BeaconState, [32]byte) error
|
||||
InsertOptimisticChain(context.Context, []*forkchoicetypes.BlockAndCheckpoints) error
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ type Getter interface {
|
||||
AncestorRoot(ctx context.Context, root [32]byte, slot types.Slot) ([]byte, error)
|
||||
CommonAncestorRoot(ctx context.Context, root1 [32]byte, root2 [32]byte) ([32]byte, error)
|
||||
IsCanonical(root [32]byte) bool
|
||||
FinalizedEpoch() types.Epoch
|
||||
JustifiedEpoch() types.Epoch
|
||||
FinalizedCheckpoint() *forkchoicetypes.Checkpoint
|
||||
JustifiedCheckpoint() *forkchoicetypes.Checkpoint
|
||||
ForkChoiceNodes() []*ethpb.ForkChoiceNode
|
||||
NodeCount() int
|
||||
}
|
||||
@@ -69,6 +69,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
|
||||
UpdateJustifiedCheckpoint(*forkchoicetypes.Checkpoint) error
|
||||
UpdateFinalizedCheckpoint(*forkchoicetypes.Checkpoint) error
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
@@ -61,7 +62,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -91,7 +92,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2
|
||||
// |
|
||||
// 3 <- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||
|
||||
@@ -103,8 +104,9 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- head
|
||||
// |
|
||||
// 3
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(2)}
|
||||
f.store.justifiedCheckpoint = jc
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||
|
||||
@@ -116,8 +118,9 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
||||
// 2 <- start
|
||||
// |
|
||||
// 3 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
||||
jc = &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(3)}
|
||||
f.store.justifiedCheckpoint = jc
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||
}
|
||||
@@ -127,7 +130,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
f := setup(0, 0)
|
||||
ctx := context.Background()
|
||||
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -188,7 +191,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -218,7 +221,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// head -> 9 10
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
@@ -248,19 +251,22 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
||||
// 7 8
|
||||
// | |
|
||||
// 9 10 <-- head
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||
|
||||
f.store.justifiedEpoch = 1
|
||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(1)}
|
||||
f.store.justifiedCheckpoint = jc
|
||||
r, err = f.Head(context.Background(), 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)
|
||||
f := New()
|
||||
f.store.nodesIndices[params.BeaconConfig().ZeroHash] = 0
|
||||
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: justifiedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: finalizedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||
f.store.nodes = append(f.store.nodes, &Node{
|
||||
slot: 0,
|
||||
root: params.BeaconConfig().ZeroHash,
|
||||
@@ -271,6 +277,5 @@ func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
bestDescendant: NonExistentNode,
|
||||
weight: 0,
|
||||
})
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
if r != params.BeaconConfig().ZeroHash {
|
||||
t.Errorf("Incorrect head with genesis")
|
||||
@@ -28,7 +28,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -65,7 +65,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -92,7 +92,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// head -> 4 3
|
||||
// |
|
||||
// 5 <- starting from 5 with justified epoch 0 should error
|
||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
f.store.justifiedCheckpoint.Root = indexToHash(5)
|
||||
_, err = f.Head(context.Background(), balances)
|
||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||
require.ErrorContains(t, wanted, err)
|
||||
|
||||
@@ -104,8 +105,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
// 4 3
|
||||
// |
|
||||
// 5 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
f.store.justifiedCheckpoint.Epoch = 2
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -122,7 +123,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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, zeroHash, balances)
|
||||
headRoot, err := f.Head(ctx, 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) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, 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) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, 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) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, 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, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, 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, zeroHash, balances)
|
||||
headRoot, err = f.Head(ctx, 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, zeroHash, balances)
|
||||
r, err := f.Head(ctx, 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) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, 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) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure the head is C, the honest block.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -253,7 +253,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
||||
|
||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
})
|
||||
@@ -261,7 +261,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, zeroHash, balances)
|
||||
r, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -288,7 +288,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -307,7 +307,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -326,7 +326,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, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||
})
|
||||
@@ -348,7 +348,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
a := zeroHash
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(ctx, zeroHash, balances)
|
||||
r, err := f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -367,7 +367,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -395,7 +395,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// Ensure C is still the head.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||
|
||||
@@ -419,7 +419,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
// D cannot win without a boost.
|
||||
r, err = f.Head(ctx, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||
|
||||
@@ -435,7 +435,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, zeroHash, balances)
|
||||
r, err = f.Head(ctx, balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, d, r, "Expected D to become the head")
|
||||
})
|
||||
|
||||
@@ -29,17 +29,17 @@ const defaultPruneThreshold = 256
|
||||
var lastHeadRoot [32]byte
|
||||
|
||||
// New initializes a new fork choice store.
|
||||
func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
func New() *ForkChoice {
|
||||
s := &Store{
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
proposerBoostRoot: [32]byte{},
|
||||
nodes: make([]*Node, 0),
|
||||
nodesIndices: make(map[[32]byte]uint64),
|
||||
payloadIndices: make(map[[32]byte]uint64),
|
||||
canonicalNodes: make(map[[32]byte]bool),
|
||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||
pruneThreshold: defaultPruneThreshold,
|
||||
justifiedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||
finalizedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||
proposerBoostRoot: [32]byte{},
|
||||
nodes: make([]*Node, 0),
|
||||
nodesIndices: make(map[[32]byte]uint64),
|
||||
payloadIndices: make(map[[32]byte]uint64),
|
||||
canonicalNodes: make(map[[32]byte]bool),
|
||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||
pruneThreshold: defaultPruneThreshold,
|
||||
}
|
||||
|
||||
b := make([]uint64, 0)
|
||||
@@ -49,11 +49,7 @@ func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||
|
||||
// Head returns the head root from fork choice store.
|
||||
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
||||
func (f *ForkChoice) Head(
|
||||
ctx context.Context,
|
||||
justifiedRoot [32]byte,
|
||||
justifiedStateBalances []uint64,
|
||||
) ([32]byte, error) {
|
||||
func (f *ForkChoice) Head(ctx context.Context, justifiedStateBalances []uint64) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.Head")
|
||||
defer span.End()
|
||||
f.votesLock.Lock()
|
||||
@@ -76,7 +72,7 @@ func (f *ForkChoice) Head(
|
||||
}
|
||||
f.balances = newBalances
|
||||
|
||||
return f.store.head(ctx, justifiedRoot)
|
||||
return f.store.head(ctx)
|
||||
}
|
||||
|
||||
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
||||
@@ -120,7 +116,7 @@ func (f *ForkChoice) ProposerBoost() [fieldparams.RootLength]byte {
|
||||
}
|
||||
|
||||
// InsertNode processes a new block by inserting it to the fork choice store.
|
||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconState, root [32]byte) error {
|
||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, root [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.InsertNode")
|
||||
defer span.End()
|
||||
|
||||
@@ -273,14 +269,18 @@ func (s *Store) PruneThreshold() uint64 {
|
||||
return s.pruneThreshold
|
||||
}
|
||||
|
||||
// JustifiedEpoch of fork choice store.
|
||||
func (f *ForkChoice) JustifiedEpoch() types.Epoch {
|
||||
return f.store.justifiedEpoch
|
||||
// JustifiedCheckpoint of fork choice store.
|
||||
func (f *ForkChoice) JustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||
f.store.checkpointsLock.RLock()
|
||||
defer f.store.checkpointsLock.RUnlock()
|
||||
return f.store.justifiedCheckpoint
|
||||
}
|
||||
|
||||
// FinalizedEpoch of fork choice store.
|
||||
func (f *ForkChoice) FinalizedEpoch() types.Epoch {
|
||||
return f.store.finalizedEpoch
|
||||
// FinalizedCheckpoint of fork choice store.
|
||||
func (f *ForkChoice) FinalizedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||
f.store.checkpointsLock.RLock()
|
||||
defer f.store.checkpointsLock.RUnlock()
|
||||
return f.store.finalizedCheckpoint
|
||||
}
|
||||
|
||||
// proposerBoost of fork choice store.
|
||||
@@ -291,20 +291,23 @@ func (s *Store) proposerBoost() [fieldparams.RootLength]byte {
|
||||
}
|
||||
|
||||
// head starts from justified root and then follows the best descendant links
|
||||
// to find the best block for head.
|
||||
func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, error) {
|
||||
// to find the best block for head. It assumes the caller has a lock on nodes.
|
||||
func (s *Store) head(ctx context.Context) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.head")
|
||||
defer span.End()
|
||||
|
||||
// Justified index has to be valid in node indices map, and can not be out of bound.
|
||||
justifiedIndex, ok := s.nodesIndices[justifiedRoot]
|
||||
if s.justifiedCheckpoint == nil {
|
||||
return [32]byte{}, errInvalidNilCheckpoint
|
||||
}
|
||||
|
||||
justifiedIndex, ok := s.nodesIndices[s.justifiedCheckpoint.Root]
|
||||
if !ok {
|
||||
return [32]byte{}, errUnknownJustifiedRoot
|
||||
}
|
||||
if justifiedIndex >= uint64(len(s.nodes)) {
|
||||
return [32]byte{}, errInvalidJustifiedIndex
|
||||
}
|
||||
|
||||
justifiedNode := s.nodes[justifiedIndex]
|
||||
bestDescendantIndex := justifiedNode.bestDescendant
|
||||
// If the justified node doesn't have a best descendant,
|
||||
@@ -315,12 +318,11 @@ func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, err
|
||||
if bestDescendantIndex >= uint64(len(s.nodes)) {
|
||||
return [32]byte{}, errInvalidBestDescendantIndex
|
||||
}
|
||||
|
||||
bestNode := s.nodes[bestDescendantIndex]
|
||||
|
||||
if !s.viableForHead(bestNode) {
|
||||
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
||||
bestNode.slot, bestNode.weight/10e9, bestNode.finalizedEpoch, s.finalizedEpoch, bestNode.justifiedEpoch, s.justifiedEpoch)
|
||||
bestNode.slot, bestNode.weight/10e9, bestNode.finalizedEpoch, s.finalizedCheckpoint.Epoch, bestNode.justifiedEpoch, s.justifiedCheckpoint.Epoch)
|
||||
}
|
||||
|
||||
// Update metrics.
|
||||
@@ -743,10 +745,12 @@ func (s *Store) leadsToViableHead(node *Node) (bool, error) {
|
||||
// Any node with diff finalized or justified epoch than the ones in fork choice store
|
||||
// should not be viable to head.
|
||||
func (s *Store) viableForHead(node *Node) bool {
|
||||
s.checkpointsLock.RLock()
|
||||
defer s.checkpointsLock.RUnlock()
|
||||
// `node` is viable if its justified epoch and finalized epoch are the same as the one in `Store`.
|
||||
// It's also viable if we are in genesis epoch.
|
||||
justified := s.justifiedEpoch == node.justifiedEpoch || s.justifiedEpoch == 0
|
||||
finalized := s.finalizedEpoch == node.finalizedEpoch || s.finalizedEpoch == 0
|
||||
justified := s.justifiedCheckpoint.Epoch == node.justifiedEpoch || s.justifiedCheckpoint.Epoch == 0
|
||||
finalized := s.finalizedCheckpoint.Epoch == node.finalizedEpoch || s.finalizedCheckpoint.Epoch == 0
|
||||
|
||||
return justified && finalized
|
||||
}
|
||||
@@ -857,25 +861,25 @@ func (f *ForkChoice) InsertSlashedIndex(ctx context.Context, index types.Validat
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
||||
// UpdateJustifiedCheckpoint sets the justified checkpoint to the given one
|
||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *forkchoicetypes.Checkpoint) error {
|
||||
if jc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.justifiedEpoch = jc.Epoch
|
||||
f.store.checkpointsLock.Lock()
|
||||
defer f.store.checkpointsLock.Unlock()
|
||||
f.store.justifiedCheckpoint = jc
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
||||
// UpdateFinalizedCheckpoint sets the finalized checkpoint to the given one
|
||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *forkchoicetypes.Checkpoint) error {
|
||||
if fc == nil {
|
||||
return errInvalidNilCheckpoint
|
||||
}
|
||||
f.store.nodesLock.Lock()
|
||||
defer f.store.nodesLock.Unlock()
|
||||
f.store.finalizedEpoch = fc.Epoch
|
||||
f.store.checkpointsLock.Lock()
|
||||
defer f.store.checkpointsLock.Unlock()
|
||||
f.store.finalizedCheckpoint = fc
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -895,7 +899,7 @@ func (f *ForkChoice) InsertOptimisticChain(ctx context.Context, chain []*forkcho
|
||||
}
|
||||
if err := f.store.insert(ctx,
|
||||
b.Slot(), r, parentRoot, payloadHash,
|
||||
chain[i].JustifiedEpoch, chain[i].FinalizedEpoch); err != nil {
|
||||
chain[i].JustifiedCheckpoint.Epoch, chain[i].FinalizedCheckpoint.Epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@ func TestStore_PruneThreshold(t *testing.T) {
|
||||
func TestStore_JustifiedEpoch(t *testing.T) {
|
||||
j := types.Epoch(100)
|
||||
f := setup(j, j)
|
||||
require.Equal(t, j, f.JustifiedEpoch())
|
||||
require.Equal(t, j, f.JustifiedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestStore_FinalizedEpoch(t *testing.T) {
|
||||
j := types.Epoch(50)
|
||||
f := setup(j, j)
|
||||
require.Equal(t, j, f.FinalizedEpoch())
|
||||
require.Equal(t, j, f.FinalizedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
func TestForkChoice_HasNode(t *testing.T) {
|
||||
@@ -51,8 +51,9 @@ func TestForkChoice_HasNode(t *testing.T) {
|
||||
|
||||
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
||||
s := &Store{nodesIndices: make(map[[32]byte]uint64)}
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: [32]byte{'a'}}
|
||||
|
||||
_, err := s.head(context.Background(), [32]byte{})
|
||||
_, err := s.head(context.Background())
|
||||
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
||||
}
|
||||
|
||||
@@ -61,8 +62,9 @@ func TestStore_Head_UnknownJustifiedIndex(t *testing.T) {
|
||||
indices := make(map[[32]byte]uint64)
|
||||
indices[r] = 1
|
||||
s := &Store{nodesIndices: indices}
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
|
||||
_, err := s.head(context.Background(), r)
|
||||
_, err := s.head(context.Background())
|
||||
assert.ErrorContains(t, errInvalidJustifiedIndex.Error(), err)
|
||||
}
|
||||
|
||||
@@ -73,7 +75,9 @@ func TestStore_Head_Itself(t *testing.T) {
|
||||
// Since the justified node does not have a best descendant so the best node
|
||||
// is itself.
|
||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: NonExistentNode}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||
h, err := s.head(context.Background(), r)
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
h, err := s.head(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, r, h)
|
||||
}
|
||||
@@ -86,7 +90,9 @@ func TestStore_Head_BestDescendant(t *testing.T) {
|
||||
// Since the justified node's best descendant is at index 1, and its root is `best`,
|
||||
// the head should be `best`.
|
||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, bestDescendant: 1, parent: NonExistentNode}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||
h, err := s.head(context.Background(), r)
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
h, err := s.head(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, best, h)
|
||||
}
|
||||
@@ -99,7 +105,9 @@ func TestStore_Head_ContextCancelled(t *testing.T) {
|
||||
|
||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: 1}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||
cancel()
|
||||
_, err := s.head(ctx, r)
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||
_, err := s.head(ctx)
|
||||
require.ErrorContains(t, "context canceled", err)
|
||||
}
|
||||
|
||||
@@ -123,6 +131,8 @@ func TestStore_Insert_KnownParent(t *testing.T) {
|
||||
p := [32]byte{'B'}
|
||||
s.nodesIndices[p] = 0
|
||||
payloadHash := [32]byte{'c'}
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
require.NoError(t, s.insert(context.Background(), 100, [32]byte{'A'}, p, payloadHash, 1, 1))
|
||||
assert.Equal(t, 2, len(s.nodes), "Did not insert block")
|
||||
assert.Equal(t, 2, len(s.nodesIndices), "Did not insert block")
|
||||
@@ -150,6 +160,8 @@ 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.
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
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)
|
||||
@@ -165,6 +177,8 @@ 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.
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
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)
|
||||
@@ -179,6 +193,8 @@ 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.
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
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)
|
||||
@@ -187,7 +203,9 @@ func TestStore_ApplyScoreChanges_UpdateWeightsMixedDelta(t *testing.T) {
|
||||
|
||||
func TestStore_UpdateBestChildAndDescendant_RemoveChild(t *testing.T) {
|
||||
// Make parent's best child equal's to input child index and child is not viable.
|
||||
s := &Store{nodes: []*Node{{bestChild: 1}, {}}, justifiedEpoch: 1, finalizedEpoch: 1}
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{nodes: []*Node{{bestChild: 1}, {}}, justifiedCheckpoint: jc, finalizedCheckpoint: fc}
|
||||
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
||||
|
||||
// Verify parent's best child and best descendant are `none`.
|
||||
@@ -198,6 +216,8 @@ func TestStore_UpdateBestChildAndDescendant_RemoveChild(t *testing.T) {
|
||||
func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
|
||||
// Make parent's best child equal to child index and child is viable.
|
||||
s := &Store{nodes: []*Node{{bestChild: 1}, {bestDescendant: NonExistentNode}}}
|
||||
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
||||
|
||||
// Verify parent's best child is the same and best descendant is not set to child index.
|
||||
@@ -208,9 +228,11 @@ func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
|
||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T) {
|
||||
// Make parent's best child not equal to child index, child leads to viable index and
|
||||
// parent's best child doesn't lead to viable index.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||
@@ -224,9 +246,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T)
|
||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildByWeight(t *testing.T) {
|
||||
// Make parent's best child not equal to child index, child leads to viable index and
|
||||
// parents best child leads to viable index but child has more weight than parent's best child.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1}}}
|
||||
@@ -239,9 +263,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildByWeight(t *testing.T) {
|
||||
|
||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildAtLeaf(t *testing.T) {
|
||||
// Make parent's best child to none and input child leads to viable index.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||
@@ -255,9 +281,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildAtLeaf(t *testing.T) {
|
||||
func TestStore_UpdateBestChildAndDescendant_NoChangeByViability(t *testing.T) {
|
||||
// Make parent's best child not equal to child index, child leads to not viable index and
|
||||
// parents best child leads to viable index.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode}}}
|
||||
@@ -271,9 +299,11 @@ func TestStore_UpdateBestChildAndDescendant_NoChangeByViability(t *testing.T) {
|
||||
func TestStore_UpdateBestChildAndDescendant_NoChangeByWeight(t *testing.T) {
|
||||
// Make parent's best child not equal to child index, child leads to viable index and
|
||||
// parents best child leads to viable index but parent's best child has more weight.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||
@@ -286,9 +316,11 @@ func TestStore_UpdateBestChildAndDescendant_NoChangeByWeight(t *testing.T) {
|
||||
|
||||
func TestStore_UpdateBestChildAndDescendant_NoChangeAtLeaf(t *testing.T) {
|
||||
// Make parent's best child to none and input child does not lead to viable index.
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||
s := &Store{
|
||||
justifiedEpoch: 1,
|
||||
finalizedEpoch: 1,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||
{bestDescendant: NonExistentNode}}}
|
||||
@@ -786,10 +818,12 @@ func TestStore_LeadsToViableHead(t *testing.T) {
|
||||
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: tc.justifiedEpoch}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: tc.finalizedEpoch}
|
||||
s := &Store{
|
||||
justifiedEpoch: tc.justifiedEpoch,
|
||||
finalizedEpoch: tc.finalizedEpoch,
|
||||
nodes: []*Node{tc.n},
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
nodes: []*Node{tc.n},
|
||||
}
|
||||
got, err := s.leadsToViableHead(tc.n)
|
||||
require.NoError(t, err)
|
||||
@@ -812,9 +846,11 @@ func TestStore_ViableForHead(t *testing.T) {
|
||||
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: tc.justifiedEpoch}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: tc.finalizedEpoch}
|
||||
s := &Store{
|
||||
justifiedEpoch: tc.justifiedEpoch,
|
||||
finalizedEpoch: tc.finalizedEpoch,
|
||||
justifiedCheckpoint: jc,
|
||||
finalizedCheckpoint: fc,
|
||||
}
|
||||
assert.Equal(t, tc.want, s.viableForHead(tc.n))
|
||||
}
|
||||
@@ -984,7 +1020,7 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
||||
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
head, err := f.Head(ctx, []uint64{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'a'}, head)
|
||||
|
||||
@@ -995,20 +1031,20 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
||||
head, err = f.Head(ctx, []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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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)
|
||||
@@ -1016,7 +1052,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, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
||||
head, err = f.Head(ctx, []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)
|
||||
@@ -1032,12 +1068,12 @@ 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}
|
||||
jc := &forkchoicetypes.Checkpoint{Root: jr, Epoch: 3}
|
||||
fc := &forkchoicetypes.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)
|
||||
require.Equal(t, f.store.justifiedCheckpoint, jc)
|
||||
require.Equal(t, f.store.finalizedCheckpoint, fc)
|
||||
}
|
||||
|
||||
func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||
@@ -1051,8 +1087,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
||||
FinalizedEpoch: 1})
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
})
|
||||
for i := uint64(2); i < 11; i++ {
|
||||
blk := util.NewBeaconBlock()
|
||||
blk.Block.Slot = types.Slot(i)
|
||||
@@ -1060,8 +1098,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||
blk.Block.ParentRoot = copiedRoot[:]
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
||||
FinalizedEpoch: 1})
|
||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
})
|
||||
root, err = blk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package protoarray
|
||||
import (
|
||||
"sync"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
)
|
||||
@@ -18,8 +19,8 @@ type ForkChoice struct {
|
||||
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
||||
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.
|
||||
justifiedCheckpoint *forkchoicetypes.Checkpoint // latest justified checkpoint in store.
|
||||
finalizedCheckpoint *forkchoicetypes.Checkpoint // latest finalized checkpoint 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.
|
||||
@@ -30,6 +31,7 @@ type Store struct {
|
||||
slashedIndices map[types.ValidatorIndex]bool // The list of equivocating validators
|
||||
nodesLock sync.RWMutex
|
||||
proposerBoostLock sync.RWMutex
|
||||
checkpointsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||
|
||||
@@ -55,11 +55,11 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
||||
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.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
|
||||
f.store.justifiedCheckpoint.Epoch = node.justifiedEpoch
|
||||
}
|
||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
||||
f.store.finalizedEpoch = node.finalizedEpoch
|
||||
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
|
||||
f.store.finalizedCheckpoint.Epoch = node.finalizedEpoch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"context"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -81,25 +81,25 @@ func TestStore_LongFork(t *testing.T) {
|
||||
|
||||
// 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})
|
||||
headRoot, err := f.Head(ctx, []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'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||
ha := [32]byte{'a'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 2, Root: ha}))
|
||||
headRoot, err = f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hr, headRoot)
|
||||
require.Equal(t, [32]byte{'d'}, 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})
|
||||
headRoot, err = f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||
}
|
||||
@@ -158,30 +158,31 @@ func TestStore_NoDeadLock(t *testing.T) {
|
||||
|
||||
// Epoch 3
|
||||
// Current Head is H
|
||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err := f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||
|
||||
// Insert Block I, it becomes Head
|
||||
hr := [32]byte{'i'}
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
ha := [32]byte{'a'}
|
||||
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 1, Root: ha}))
|
||||
headRoot, err = f.Head(ctx, []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())
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||
require.Equal(t, types.Epoch(0), f.FinalizedCheckpoint().Epoch)
|
||||
|
||||
// Realized Justified checkpoints, H becomes head
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err = f.Head(ctx, []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())
|
||||
require.Equal(t, types.Epoch(2), f.JustifiedCheckpoint().Epoch)
|
||||
require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch)
|
||||
}
|
||||
|
||||
// Epoch 1 | Epoch 2
|
||||
@@ -226,10 +227,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
|
||||
// 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})
|
||||
headRoot, err := f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||
|
||||
// D arrives late, D is head
|
||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
||||
@@ -237,10 +238,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||
f.UpdateUnrealizedCheckpoints()
|
||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
||||
headRoot, err = f.Head(ctx, []uint64{100})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
||||
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||
// 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)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -15,7 +16,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The head should always start at the finalized block.
|
||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err := f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||
|
||||
@@ -27,7 +28,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -39,7 +40,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -48,7 +49,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -57,7 +58,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -71,7 +72,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -82,7 +83,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(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -93,7 +94,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// |
|
||||
// 3 <- head
|
||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -109,7 +110,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -127,7 +128,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -188,7 +189,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -209,9 +210,11 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
// 8
|
||||
// |
|
||||
// 9 <- head
|
||||
f.store.justifiedEpoch = 2
|
||||
f.store.finalizedEpoch = 2
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
jc := &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(5)}
|
||||
fc := &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(5)}
|
||||
f.store.justifiedCheckpoint = jc
|
||||
f.store.finalizedCheckpoint = fc
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -237,7 +240,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -246,28 +249,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), 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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||
|
||||
@@ -276,7 +279,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -300,7 +303,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(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||
|
||||
@@ -318,7 +321,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||
|
||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
||||
r, err = f.Head(context.Background(), balances)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// ProposerBoostRootArgs to call the BoostProposerRoot function.
|
||||
@@ -13,9 +15,17 @@ type ProposerBoostRootArgs struct {
|
||||
SecondsIntoSlot uint64
|
||||
}
|
||||
|
||||
// Checkpoint is an array version of ethpb.Checkpoint. It is used internally in
|
||||
// forkchoice, while the slice version is used in the interface to legagy code
|
||||
// in other packages
|
||||
type Checkpoint struct {
|
||||
Epoch types.Epoch
|
||||
Root [fieldparams.RootLength]byte
|
||||
}
|
||||
|
||||
// BlockAndCheckpoints to call the InsertOptimisticChain function
|
||||
type BlockAndCheckpoints struct {
|
||||
Block interfaces.BeaconBlock
|
||||
JustifiedEpoch types.Epoch
|
||||
FinalizedEpoch types.Epoch
|
||||
Block interfaces.BeaconBlock
|
||||
JustifiedCheckpoint *ethpb.Checkpoint
|
||||
FinalizedCheckpoint *ethpb.Checkpoint
|
||||
}
|
||||
|
||||
@@ -348,9 +348,9 @@ func (b *BeaconNode) Close() {
|
||||
|
||||
func (b *BeaconNode) startForkChoice() {
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
b.forkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
b.forkChoiceStore = doublylinkedtree.New()
|
||||
} else {
|
||||
b.forkChoiceStore = protoarray.New(0, 0)
|
||||
b.forkChoiceStore = protoarray.New()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,21 +10,21 @@ var (
|
||||
prometheus.HistogramOpts{
|
||||
Name: "new_payload_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for newPayloadV1 in milliseconds",
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
getPayloadLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "get_payload_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for getPayloadV1 in milliseconds",
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
forkchoiceUpdatedLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "forkchoice_updated_v1_latency_milliseconds",
|
||||
Help: "Captures RPC latency for forkchoiceUpdatedV1 in milliseconds",
|
||||
Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000},
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/proto/migration"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -23,7 +24,7 @@ func (ds *Server) GetBeaconState(ctx context.Context, req *ethpbv1.StateRequest)
|
||||
return nil, helpers.PrepareStateFetchGRPCError(err)
|
||||
}
|
||||
|
||||
if beaconSt.Version().IsHigherOrEqualToAltair() {
|
||||
if beaconSt.Version() != version.Phase0 {
|
||||
return nil, status.Error(codes.Internal, "State has incorrect type")
|
||||
}
|
||||
protoSt, err := migration.BeaconStateToProto(beaconSt)
|
||||
@@ -68,8 +69,8 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case beaconSt.Version().IsAltairCompatible():
|
||||
switch beaconSt.Version() {
|
||||
case version.Phase0:
|
||||
protoSt, err := migration.BeaconStateToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -81,7 +82,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case beaconSt.Version().IsAltairCompatible():
|
||||
case version.Altair:
|
||||
protoState, err := migration.BeaconStateAltairToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -93,7 +94,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
|
||||
},
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
}, nil
|
||||
case beaconSt.Version().IsBellatrixCompatible():
|
||||
case version.Bellatrix:
|
||||
protoState, err := migration.BeaconStateBellatrixToProto(beaconSt)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
|
||||
@@ -125,12 +126,12 @@ func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.StateReq
|
||||
return nil, status.Errorf(codes.Internal, "Could not marshal state into SSZ: %v", err)
|
||||
}
|
||||
var ver ethpbv2.Version
|
||||
switch {
|
||||
case st.Version().IsPhase0Compatible():
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
ver = ethpbv2.Version_PHASE0
|
||||
case st.Version().IsAltairCompatible():
|
||||
case version.Altair:
|
||||
ver = ethpbv2.Version_ALTAIR
|
||||
case st.Version().IsBellatrixCompatible():
|
||||
case version.Bellatrix:
|
||||
ver = ethpbv2.Version_BELLATRIX
|
||||
default:
|
||||
return nil, status.Error(codes.Internal, "Unsupported state version")
|
||||
|
||||
@@ -12,8 +12,8 @@ func (ds *Server) GetForkChoice(_ context.Context, _ *empty.Empty) (*pbrpc.ForkC
|
||||
store := ds.ForkFetcher.ForkChoicer()
|
||||
|
||||
return &pbrpc.ForkChoiceResponse{
|
||||
JustifiedEpoch: store.JustifiedEpoch(),
|
||||
FinalizedEpoch: store.FinalizedEpoch(),
|
||||
JustifiedEpoch: store.JustifiedCheckpoint().Epoch,
|
||||
FinalizedEpoch: store.FinalizedCheckpoint().Epoch,
|
||||
ForkchoiceNodes: store.ForkChoiceNodes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_GetForkChoice_ProtoArray(t *testing.T) {
|
||||
store := protoarray.New(0, 0)
|
||||
store := protoarray.New()
|
||||
bs := &Server{ForkFetcher: &mock.ChainService{ForkChoiceStore: store}}
|
||||
res, err := bs.GetForkChoice(context.Background(), &empty.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, store.JustifiedEpoch(), res.JustifiedEpoch, "Did not get wanted justified epoch")
|
||||
assert.Equal(t, store.FinalizedEpoch(), res.FinalizedEpoch, "Did not get wanted finalized epoch")
|
||||
assert.Equal(t, store.JustifiedCheckpoint().Epoch, res.JustifiedEpoch, "Did not get wanted justified epoch")
|
||||
assert.Equal(t, store.FinalizedCheckpoint().Epoch, res.FinalizedEpoch, "Did not get wanted finalized epoch")
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ go_library(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// BeaconState has read and write access to beacon state methods.
|
||||
@@ -60,7 +59,7 @@ type ReadOnlyBeaconState interface {
|
||||
FieldReferencesCount() map[string]uint64
|
||||
MarshalSSZ() ([]byte, error)
|
||||
IsNil() bool
|
||||
Version() version.ForkVersion
|
||||
Version() int
|
||||
LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,12 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
|
||||
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
|
||||
type BeaconState struct {
|
||||
version version.ForkVersion
|
||||
version int
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
|
||||
@@ -13,13 +13,12 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
|
||||
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
|
||||
type BeaconState struct {
|
||||
version version.ForkVersion
|
||||
version int
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
|
||||
@@ -2,11 +2,12 @@ package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// PreviousEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if !b.version.IsPhase0Compatible() {
|
||||
if b.version != version.Phase0 {
|
||||
return nil, errNotSupported("PreviousEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
@@ -28,7 +29,7 @@ func (b *BeaconState) previousEpochAttestationsVal() []*ethpb.PendingAttestation
|
||||
|
||||
// CurrentEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if !b.version.IsPhase0Compatible() {
|
||||
if b.version != version.Phase0 {
|
||||
return nil, errNotSupported("CurrentEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package state_native
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// GenesisTime of the beacon state as a uint64.
|
||||
@@ -25,7 +24,7 @@ func (b *BeaconState) GenesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (b *BeaconState) Version() version.ForkVersion {
|
||||
func (b *BeaconState) Version() int {
|
||||
return b.version
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@ package state_native
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// CurrentEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("CurrentEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
@@ -23,7 +24,7 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
|
||||
// PreviousEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("PreviousEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) {
|
||||
// current epoch and target attested in previous epoch. This function is used to
|
||||
// compute the "unrealized justification" that a synced Beacon Block will have.
|
||||
func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) {
|
||||
if !b.version.IsParticipationBitsCompatible() {
|
||||
if b.version == version.Phase0 {
|
||||
return 0, 0, 0, errNotSupported("UnrealizedCheckpointBalances", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@ package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// LatestExecutionPayloadHeader of the beacon state.
|
||||
func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) {
|
||||
if !b.version.IsExecutionPayloadCompatible() {
|
||||
if b.version == version.Phase0 || b.version == version.Altair {
|
||||
return nil, errNotSupported("LatestExecutionPayloadHeader", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
|
||||
gvrCopy := b.genesisValidatorsRoot
|
||||
|
||||
switch {
|
||||
case b.version.IsPhase0Compatible():
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
return ðpb.BeaconState{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
@@ -42,7 +42,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
}
|
||||
case b.version.IsAltairCompatible():
|
||||
case version.Altair:
|
||||
return ðpb.BeaconStateAltair{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
@@ -69,7 +69,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
}
|
||||
case b.version.IsBellatrixCompatible():
|
||||
case version.Bellatrix:
|
||||
return ðpb.BeaconStateBellatrix{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
|
||||
@@ -31,6 +31,6 @@ func init() {
|
||||
// to its corresponding data type.
|
||||
var fieldMap map[nativetypes.FieldIndex]types.DataType
|
||||
|
||||
func errNotSupported(funcName string, ver version.ForkVersion) error {
|
||||
return fmt.Errorf("%s is not supported for %s", funcName, ver.String())
|
||||
func errNotSupported(funcName string, ver int) error {
|
||||
return fmt.Errorf("%s is not supported for %s", funcName, version.String(ver))
|
||||
}
|
||||
|
||||
@@ -5,8 +5,5 @@ go_library(
|
||||
srcs = ["types.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
deps = ["@com_github_pkg_errors//:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -2,7 +2,6 @@ package types
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// FieldIndex represents the relevant field position in the
|
||||
@@ -10,7 +9,7 @@ import (
|
||||
type FieldIndex int
|
||||
|
||||
// String returns the name of the field index.
|
||||
func (f FieldIndex) String(_ version.ForkVersion) string {
|
||||
func (f FieldIndex) String(_ int) string {
|
||||
switch f {
|
||||
case GenesisTime:
|
||||
return "genesisTime"
|
||||
|
||||
@@ -211,7 +211,7 @@ func ReplayProcessSlots(ctx context.Context, state state.BeaconState, slot types
|
||||
return nil, errors.Wrap(err, "could not process epoch")
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported beacon state version: %s", state.Version().String())
|
||||
return nil, fmt.Errorf("unsupported beacon state version: %s", version.String(state.Version()))
|
||||
}
|
||||
}
|
||||
if err := state.SetSlot(state.Slot() + 1); err != nil {
|
||||
|
||||
@@ -27,14 +27,14 @@ const (
|
||||
|
||||
// BeaconStateField represents a field of the beacon state.
|
||||
type BeaconStateField interface {
|
||||
String(stateVersion version.ForkVersion) string
|
||||
String(stateVersion int) string
|
||||
RealPosition() int
|
||||
ElemsInChunk() (uint64, error)
|
||||
Native() bool
|
||||
}
|
||||
|
||||
// String returns the name of the field index.
|
||||
func (f FieldIndex) String(stateVersion version.ForkVersion) string {
|
||||
func (f FieldIndex) String(stateVersion int) string {
|
||||
switch f {
|
||||
case GenesisTime:
|
||||
return "genesisTime"
|
||||
@@ -67,12 +67,12 @@ func (f FieldIndex) String(stateVersion version.ForkVersion) string {
|
||||
case Slashings:
|
||||
return "slashings"
|
||||
case PreviousEpochAttestations:
|
||||
if stateVersion.IsParticipationBitsCompatible() {
|
||||
if version.Altair == stateVersion || version.Bellatrix == stateVersion {
|
||||
return "previousEpochParticipationBits"
|
||||
}
|
||||
return "previousEpochAttestations"
|
||||
case CurrentEpochAttestations:
|
||||
if stateVersion.IsParticipationBitsCompatible() {
|
||||
if version.Altair == stateVersion || version.Bellatrix == stateVersion {
|
||||
return "currentEpochParticipationBits"
|
||||
}
|
||||
return "currentEpochAttestations"
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
func (_ *BeaconState) Version() int {
|
||||
return version.Phase0
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
func (_ *BeaconState) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BeaconState) genesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() version.ForkVersion {
|
||||
func (_ *BeaconState) Version() int {
|
||||
return version.Bellatrix
|
||||
}
|
||||
|
||||
|
||||
@@ -122,12 +122,6 @@ func configureTestnet(ctx *cli.Context) error {
|
||||
if err := params.SetActive(params.RopstenConfig().Copy()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.Set(enableVecHTR.Names()[0], "true"); err != nil {
|
||||
log.WithError(err).Debug("error enabling vectorized HTR flag")
|
||||
}
|
||||
if err := ctx.Set(enableForkChoiceDoublyLinkedTree.Names()[0], "true"); err != nil {
|
||||
log.WithError(err).Debug("error enabling doubly linked tree forkchoice flag")
|
||||
}
|
||||
params.UseRopstenNetworkConfig()
|
||||
} else {
|
||||
log.Warn("Running on Ethereum Consensus Mainnet")
|
||||
|
||||
@@ -3,11 +3,11 @@ package bellatrix
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
field_params "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// PayloadToHeader converts `payload` into execution payload header format.
|
||||
|
||||
@@ -13,7 +13,6 @@ go_library(
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -25,7 +24,7 @@ type SignedBeaconBlock interface {
|
||||
PbBlindedBellatrixBlock() (*ethpb.SignedBlindedBeaconBlockBellatrix, error)
|
||||
ssz.Marshaler
|
||||
ssz.Unmarshaler
|
||||
Version() version.ForkVersion
|
||||
Version() int
|
||||
Header() (*ethpb.SignedBeaconBlockHeader, error)
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ type BeaconBlock interface {
|
||||
ssz.Marshaler
|
||||
ssz.Unmarshaler
|
||||
ssz.HashRoot
|
||||
Version() version.ForkVersion
|
||||
Version() int
|
||||
AsSignRequestObject() validatorpb.SignRequestObject
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ func (altairSignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeac
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (altairSignedBeaconBlock) Version() version.ForkVersion {
|
||||
func (altairSignedBeaconBlock) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ func (w altairBeaconBlock) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (altairBeaconBlock) Version() version.ForkVersion {
|
||||
func (altairBeaconBlock) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func (bellatrixSignedBeaconBlock) PbAltairBlock() (*eth.SignedBeaconBlockAltair,
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (bellatrixSignedBeaconBlock) Version() version.ForkVersion {
|
||||
func (bellatrixSignedBeaconBlock) Version() int {
|
||||
return version.Bellatrix
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ func (w bellatrixBeaconBlock) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (bellatrixBeaconBlock) Version() version.ForkVersion {
|
||||
func (bellatrixBeaconBlock) Version() int {
|
||||
return version.Bellatrix
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ func (Phase0SignedBeaconBlock) PbBlindedBellatrixBlock() (*eth.SignedBlindedBeac
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (Phase0SignedBeaconBlock) Version() version.ForkVersion {
|
||||
func (Phase0SignedBeaconBlock) Version() int {
|
||||
return version.Phase0
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ func (w Phase0BeaconBlock) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (Phase0BeaconBlock) Version() version.ForkVersion {
|
||||
func (Phase0BeaconBlock) Version() int {
|
||||
return version.Phase0
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func (signedBlindedBeaconBlockBellatrix) PbAltairBlock() (*eth.SignedBeaconBlock
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (signedBlindedBeaconBlockBellatrix) Version() version.ForkVersion {
|
||||
func (signedBlindedBeaconBlockBellatrix) Version() int {
|
||||
return version.BellatrixBlind
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ func (w blindedBeaconBlockBellatrix) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
func (blindedBeaconBlockBellatrix) Version() version.ForkVersion {
|
||||
func (blindedBeaconBlockBellatrix) Version() int {
|
||||
return version.BellatrixBlind
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ func (_ MetadataV0) MetadataObjV1() *pb.MetaDataV1 {
|
||||
}
|
||||
|
||||
// Version returns the fork version of the underlying object.
|
||||
func (_ MetadataV0) Version() version.ForkVersion {
|
||||
func (_ MetadataV0) Version() int {
|
||||
return version.Phase0
|
||||
}
|
||||
|
||||
@@ -154,6 +154,6 @@ func (m MetadataV1) MetadataObjV1() *pb.MetaDataV1 {
|
||||
}
|
||||
|
||||
// Version returns the fork version of the underlying object.
|
||||
func (_ MetadataV1) Version() version.ForkVersion {
|
||||
func (_ MetadataV1) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (m BlockMutator) Apply(b interfaces.SignedBeaconBlock) error {
|
||||
m.Bellatrix(bb)
|
||||
return nil
|
||||
}
|
||||
msg := fmt.Sprintf("version %d = %s", b.Version(), b.Version().String())
|
||||
msg := fmt.Sprintf("version %d = %s", b.Version(), version.String(b.Version()))
|
||||
return errors.Wrap(ErrUnsupportedSignedBeaconBlock, msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
type VersionedUnmarshaler struct {
|
||||
Config *params.BeaconChainConfig
|
||||
// Fork aligns with the fork names in config/params/values.go
|
||||
Fork version.ForkVersion
|
||||
Fork int
|
||||
// Version corresponds to the Version type defined in the beacon-chain spec, aka a "fork version number":
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types
|
||||
Version [fieldparams.VersionLength]byte
|
||||
@@ -60,7 +60,7 @@ func FromForkVersion(cv [fieldparams.VersionLength]byte) (*VersionedUnmarshaler,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var fork version.ForkVersion
|
||||
var fork int
|
||||
switch cv {
|
||||
case bytesutil.ToBytes4(cfg.GenesisForkVersion):
|
||||
fork = version.Phase0
|
||||
@@ -81,10 +81,9 @@ func FromForkVersion(cv [fieldparams.VersionLength]byte) (*VersionedUnmarshaler,
|
||||
// UnmarshalBeaconState uses internal knowledge in the VersionedUnmarshaler to pick the right concrete BeaconState type,
|
||||
// then Unmarshal()s the type and returns an instance of state.BeaconState if successful.
|
||||
func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.BeaconState, err error) {
|
||||
forkName := cf.Fork.String()
|
||||
fork := cf.Fork
|
||||
switch {
|
||||
case fork.IsPhase0Compatible():
|
||||
forkName := version.String(cf.Fork)
|
||||
switch fork := cf.Fork; fork {
|
||||
case version.Phase0:
|
||||
st := ðpb.BeaconState{}
|
||||
err = st.UnmarshalSSZ(marshaled)
|
||||
if err != nil {
|
||||
@@ -94,7 +93,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
|
||||
}
|
||||
case fork.IsAltairCompatible():
|
||||
case version.Altair:
|
||||
st := ðpb.BeaconStateAltair{}
|
||||
err = st.UnmarshalSSZ(marshaled)
|
||||
if err != nil {
|
||||
@@ -104,7 +103,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
|
||||
}
|
||||
case fork.IsBellatrixCompatible():
|
||||
case version.Bellatrix:
|
||||
st := ðpb.BeaconStateBellatrix{}
|
||||
err = st.UnmarshalSSZ(marshaled)
|
||||
if err != nil {
|
||||
@@ -159,7 +158,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac
|
||||
case version.Bellatrix:
|
||||
blk = ðpb.SignedBeaconBlockBellatrix{}
|
||||
default:
|
||||
forkName := cf.Fork.String()
|
||||
forkName := version.String(cf.Fork)
|
||||
return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", forkName, slot)
|
||||
}
|
||||
err = blk.UnmarshalSSZ(marshaled)
|
||||
@@ -190,7 +189,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (i
|
||||
case version.Bellatrix:
|
||||
blk = ðpb.SignedBlindedBeaconBlockBellatrix{}
|
||||
default:
|
||||
forkName := cf.Fork.String()
|
||||
forkName := version.String(cf.Fork)
|
||||
return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", forkName, slot)
|
||||
}
|
||||
err = blk.UnmarshalSSZ(marshaled)
|
||||
|
||||
@@ -7,7 +7,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
ssz "github.com/ferranbt/fastssz"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// Metadata returns the interface of a p2p metadata type.
|
||||
@@ -18,5 +17,5 @@ type Metadata interface {
|
||||
ssz.Unmarshaler
|
||||
MetadataObjV0() *pb.MetaDataV0
|
||||
MetadataObjV1() *pb.MetaDataV1
|
||||
Version() version.ForkVersion
|
||||
Version() int
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package version
|
||||
|
||||
type ForkVersion int
|
||||
|
||||
const (
|
||||
Phase0 ForkVersion = iota
|
||||
Phase0 = iota
|
||||
Altair
|
||||
Bellatrix
|
||||
BellatrixBlind
|
||||
)
|
||||
|
||||
func (v ForkVersion) String() string {
|
||||
switch v {
|
||||
func String(version int) string {
|
||||
switch version {
|
||||
case Phase0:
|
||||
return "phase0"
|
||||
case Altair:
|
||||
@@ -23,39 +21,3 @@ func (v ForkVersion) String() string {
|
||||
return "unknown version"
|
||||
}
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsPhase0Compatible() bool {
|
||||
return v == Phase0
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsAltairCompatible() bool {
|
||||
return v == Altair
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsHigherOrEqualToAltair() bool {
|
||||
return v >= Altair
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsPreBellatrix() bool {
|
||||
return v < Bellatrix
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsBellatrixCompatible() bool {
|
||||
return v == Bellatrix || v == BellatrixBlind
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsSyncCommitteeCompatible() bool {
|
||||
return v == Altair || v == Bellatrix || v == BellatrixBlind
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsParticipationBitsCompatible() bool {
|
||||
return v == Altair || v == Bellatrix || v == BellatrixBlind
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsExecutionPayloadCompatible() bool {
|
||||
return v.IsBellatrixCompatible()
|
||||
}
|
||||
|
||||
func (v ForkVersion) IsBlindedBlockCompatible() bool {
|
||||
return v == BellatrixBlind
|
||||
}
|
||||
|
||||
@@ -219,9 +219,13 @@ func (r *testRunner) testTxGeneration(ctx context.Context, g *errgroup.Group, ke
|
||||
})
|
||||
}
|
||||
|
||||
func (r *testRunner) waitForMatchingHead(ctx context.Context, timeout time.Duration, check, ref *grpc.ClientConn) error {
|
||||
start := time.Now()
|
||||
dctx, cancel := context.WithDeadline(ctx, start.Add(timeout))
|
||||
func (r *testRunner) waitForMatchingHead(ctx context.Context, check, ref *grpc.ClientConn) error {
|
||||
// sleep hack copied from testBeaconChainSync
|
||||
// Sleep a second for every 4 blocks that need to be synced for the newly started node.
|
||||
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
extraSecondsToSync := (r.config.EpochsToRun) * secondsPerEpoch
|
||||
deadline := time.Now().Add(time.Second * time.Duration(extraSecondsToSync))
|
||||
dctx, cancel := context.WithDeadline(ctx, deadline)
|
||||
defer cancel()
|
||||
checkClient := service.NewBeaconChainClient(check)
|
||||
refClient := service.NewBeaconChainClient(ref)
|
||||
@@ -229,8 +233,7 @@ func (r *testRunner) waitForMatchingHead(ctx context.Context, timeout time.Durat
|
||||
select {
|
||||
case <-dctx.Done():
|
||||
// deadline ensures that the test eventually exits when beacon node fails to sync in a resonable timeframe
|
||||
elapsed := time.Since(start)
|
||||
return fmt.Errorf("deadline exceeded after %s waiting for known good block to appear in checkpoint-synced node", elapsed)
|
||||
return fmt.Errorf("deadline exceeded waiting for known good block to appear in checkpoint-synced node")
|
||||
default:
|
||||
cResp, err := checkClient.GetBlockRoot(ctx, &v1.BlockRequest{BlockId: []byte("head")})
|
||||
if err != nil {
|
||||
@@ -253,7 +256,6 @@ func (r *testRunner) waitForMatchingHead(ctx context.Context, timeout time.Durat
|
||||
}
|
||||
|
||||
func (r *testRunner) testCheckpointSync(ctx context.Context, g *errgroup.Group, i int, conns []*grpc.ClientConn, bnAPI, enr, minerEnr string) error {
|
||||
matchTimeout := 3 * time.Minute
|
||||
ethNode := eth1.NewNode(i, minerEnr)
|
||||
g.Go(func() error {
|
||||
return ethNode.Start(ctx)
|
||||
@@ -302,7 +304,7 @@ func (r *testRunner) testCheckpointSync(ctx context.Context, g *errgroup.Group,
|
||||
|
||||
// this is so that the syncEvaluators checks can run on the checkpoint sync'd node
|
||||
conns = append(conns, c)
|
||||
err = r.waitForMatchingHead(ctx, matchTimeout, c, conns[0])
|
||||
err = r.waitForMatchingHead(ctx, c, conns[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func startChainService(t testing.TB, st state.BeaconState, block interfaces.Sign
|
||||
blockchain.WithFinalizedStateAtStartUp(st),
|
||||
blockchain.WithDatabase(db),
|
||||
blockchain.WithAttestationService(attPool),
|
||||
blockchain.WithForkChoiceStore(protoarray.New(0, 0)),
|
||||
blockchain.WithForkChoiceStore(protoarray.New()),
|
||||
blockchain.WithStateGen(stategen.New(db)),
|
||||
blockchain.WithStateNotifier(&mock.MockStateNotifier{}),
|
||||
blockchain.WithAttestationPool(attestations.NewPool()),
|
||||
|
||||
@@ -163,7 +163,7 @@ func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [f
|
||||
"numAttestations": len(blk.Block().Body().Attestations()),
|
||||
"numDeposits": len(blk.Block().Body().Deposits()),
|
||||
"graffiti": string(blk.Block().Body().Graffiti()),
|
||||
"fork": blk.Block().Version().String(),
|
||||
"fork": version.String(blk.Block().Version()),
|
||||
}).Info("Submitted new block")
|
||||
|
||||
if v.emitAccountMetrics {
|
||||
|
||||
Reference in New Issue
Block a user