mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Implement fork choice spec tests (#10159)
* starting * Reimplement store * begin on proposer boost * implement fork choice proposer boost algorithm * boosting * gaz * add mutexes and previous root * comment on compute proposer boost * safe * rem todo * reset and add tests * unit test for proposer boost score * boost works * Can process block * Basic test case passing * ex ante * test * propoer test * More progresses * More fixes * rm unused pieces * Refactor, add phase 0 * locks * vanilla ex-ante attack * test similar to spec test * works works works * boost test working for num votes > proposer boost weight * commentary fixes * rem unused * comments * Proposer boost use store time * Reset proposer root * debugging * passing * Rm unused visibility imports * Move update head to better place * Fix deepsrc complains * Fix more complains * Raul's feedback * Use correct byte lengths Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
@@ -28,6 +28,7 @@ go_library(
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//async:go_default_library",
|
||||
|
||||
@@ -107,6 +107,17 @@ func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return ethpb.CopyCheckpoint(cp)
|
||||
}
|
||||
|
||||
// BestJustifiedCheckpt returns the best justified checkpoint from store.
|
||||
func (s *Service) BestJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
cp := s.store.BestJustifiedCheckpt()
|
||||
// If there is no best justified checkpoint, return the checkpoint with root as zeros to be used for genesis cases.
|
||||
if cp == nil {
|
||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
||||
}
|
||||
|
||||
return ethpb.CopyCheckpoint(cp)
|
||||
}
|
||||
|
||||
// HeadSlot returns the slot of the head of the chain.
|
||||
func (s *Service) HeadSlot() types.Slot {
|
||||
s.headLock.RLock()
|
||||
@@ -316,3 +327,8 @@ func (s *Service) HeadValidatorIndexToPublicKey(_ context.Context, index types.V
|
||||
}
|
||||
return v.PublicKey(), nil
|
||||
}
|
||||
|
||||
// SetGenesisTime sets the genesis time of beacon chain.
|
||||
func (s *Service) SetGenesisTime(t time.Time) {
|
||||
s.genesisTime = t
|
||||
}
|
||||
|
||||
@@ -23,6 +23,21 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// UpdateHeadWithBalances updates the beacon state head after getting justified balanced from cache.
|
||||
func (s *Service) UpdateHeadWithBalances(ctx context.Context) error {
|
||||
cp := s.store.JustifiedCheckpt()
|
||||
if cp == nil {
|
||||
return errors.New("no justified checkpoint")
|
||||
}
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("could not read balances for state w/ justified checkpoint %#x", cp.Root)
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
||||
return s.updateHead(ctx, balances)
|
||||
}
|
||||
|
||||
// This defines the current chain service's view of head.
|
||||
type head struct {
|
||||
slot types.Slot // current head slot.
|
||||
@@ -37,21 +52,6 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.updateHead")
|
||||
defer span.End()
|
||||
|
||||
// To get the proper head update, a node first checks its best justified
|
||||
// can become justified. This is designed to prevent bounce attack and
|
||||
// ensure head gets its best justified info.
|
||||
bestJustified := s.store.BestJustifiedCheckpt()
|
||||
if bestJustified == nil {
|
||||
return errNilBestJustifiedInStore
|
||||
}
|
||||
justified := s.store.JustifiedCheckpt()
|
||||
if justified == nil {
|
||||
return errNilJustifiedInStore
|
||||
}
|
||||
if bestJustified.Epoch > justified.Epoch {
|
||||
s.store.SetJustifiedCheckpt(bestJustified)
|
||||
}
|
||||
|
||||
// Get head from the fork choice service.
|
||||
f := s.store.FinalizedCheckpt()
|
||||
if f == nil {
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
// ancestor_at_finalized_slot = get_ancestor(store, store.best_justified_checkpoint.root, finalized_slot)
|
||||
// if ancestor_at_finalized_slot == store.finalized_checkpoint.root:
|
||||
// store.justified_checkpoint = store.best_justified_checkpoint
|
||||
func (s *Service) newSlot(ctx context.Context, slot types.Slot) error {
|
||||
func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
||||
|
||||
// Reset proposer boost root in fork choice.
|
||||
if err := s.cfg.ForkChoiceStore.ResetBoostedProposerRoot(ctx); err != nil {
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestService_newSlot(t *testing.T) {
|
||||
store.SetBestJustifiedCheckpt(test.args.bestJustified)
|
||||
service.store = store
|
||||
|
||||
require.NoError(t, service.newSlot(ctx, test.args.slot))
|
||||
require.NoError(t, service.NewSlot(ctx, test.args.slot))
|
||||
if test.args.shouldEqual {
|
||||
require.DeepSSZEqual(t, service.store.BestJustifiedCheckpt(), service.store.JustifiedCheckpt())
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,7 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -9,12 +10,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// onAttestation is called whenever an attestation is received, verifies the attestation is valid and saves
|
||||
// OnAttestation is called whenever an attestation is received, verifies the attestation is valid and saves
|
||||
// it to the DB. As a stateless function, this does not hold nor delay attestation based on the spec descriptions.
|
||||
// The delay is handled by the caller in `processAttestations`.
|
||||
//
|
||||
@@ -36,7 +36,7 @@ import (
|
||||
//
|
||||
// # Update latest messages for attesting indices
|
||||
// update_latest_messages(store, indexed_attestation.attesting_indices, attestation)
|
||||
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error {
|
||||
func (s *Service) OnAttestation(ctx context.Context, a *ethpb.Attestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation")
|
||||
defer span.End()
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error
|
||||
return err
|
||||
}
|
||||
|
||||
genesisTime := baseState.GenesisTime()
|
||||
genesisTime := uint64(s.genesisTime.Unix())
|
||||
|
||||
// Verify attestation target is from current epoch or previous epoch.
|
||||
if err := verifyAttTargetEpoch(ctx, genesisTime, uint64(time.Now().Unix()), tgt); err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -117,7 +117,7 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := service.onAttestation(ctx, tt.a)
|
||||
err := service.OnAttestation(ctx, tt.a)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
} else {
|
||||
@@ -140,7 +140,7 @@ func TestStore_OnAttestation_Ok(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
genesisState, pks := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(time.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
service.SetGenesisTime(time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
att, err := util.GenerateAttestations(genesisState, pks, 1, 0, false)
|
||||
require.NoError(t, err)
|
||||
@@ -150,7 +150,7 @@ func TestStore_OnAttestation_Ok(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.onAttestation(ctx, att[0]))
|
||||
require.NoError(t, service.OnAttestation(ctx, att[0]))
|
||||
}
|
||||
|
||||
func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
|
||||
@@ -160,11 +160,10 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
}
|
||||
newFinalized := postState.FinalizedCheckpointEpoch() > finalized.Epoch
|
||||
if newFinalized {
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
s.store.SetPrevFinalizedCheckpt(finalized)
|
||||
s.store.SetFinalizedCheckpt(postState.FinalizedCheckpoint())
|
||||
s.store.SetPrevJustifiedCheckpt(justified)
|
||||
s.store.SetJustifiedCheckpt(postState.CurrentJustifiedCheckpoint())
|
||||
}
|
||||
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -45,7 +44,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b block.BeaconBlock) (st
|
||||
}
|
||||
|
||||
// Verify block slot time is not from the future.
|
||||
if err := slots.VerifyTime(preState.GenesisTime(), b.Slot(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
if err := slots.VerifyTime(uint64(s.genesisTime.Unix()), b.Slot(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -328,56 +327,6 @@ func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot)
|
||||
return s.ancestorByDB(ctx, bytesutil.ToBytes32(b.ParentRoot()), slot)
|
||||
}
|
||||
|
||||
// This updates justified check point in store, if the new justified is later than stored justified or
|
||||
// the store's justified is not in chain with finalized check point.
|
||||
//
|
||||
// Spec definition:
|
||||
// # Potentially update justified if different from store
|
||||
// if store.justified_checkpoint != state.current_justified_checkpoint:
|
||||
// # Update justified if new justified is later than store justified
|
||||
// if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
|
||||
// store.justified_checkpoint = state.current_justified_checkpoint
|
||||
// return
|
||||
// # Update justified if store justified is not in chain with finalized checkpoint
|
||||
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)
|
||||
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot)
|
||||
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root:
|
||||
// store.justified_checkpoint = state.current_justified_checkpoint
|
||||
func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state state.BeaconState) error {
|
||||
// Update justified if it's different than the one cached in the store.
|
||||
justified := s.store.JustifiedCheckpt()
|
||||
if justified == nil {
|
||||
return errNilJustifiedInStore
|
||||
}
|
||||
if !attestation.CheckPointIsEqual(justified, state.CurrentJustifiedCheckpoint()) {
|
||||
if state.CurrentJustifiedCheckpoint().Epoch > justified.Epoch {
|
||||
s.store.SetJustifiedCheckpt(state.CurrentJustifiedCheckpoint())
|
||||
// we don't need to check if the previous justified checkpoint was an ancestor since the new
|
||||
// finalized checkpoint is overriding it.
|
||||
return nil
|
||||
}
|
||||
|
||||
finalized := s.store.FinalizedCheckpt()
|
||||
if finalized == nil {
|
||||
return errNilFinalizedInStore
|
||||
}
|
||||
// Update justified if store justified is not in chain with finalized check point.
|
||||
finalizedSlot, err := slots.EpochStart(finalized.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(justified.Root))
|
||||
anc, err := s.ancestor(ctx, justifiedRoot[:], finalizedSlot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(anc, finalized.Root) {
|
||||
s.store.SetJustifiedCheckpt(state.CurrentJustifiedCheckpoint())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This retrieves missing blocks from DB (ie. the blocks that couldn't be received over sync) and inserts them to fork choice store.
|
||||
// This is useful for block tree visualizer and additional vote accounting.
|
||||
func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk block.BeaconBlock,
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
@@ -737,89 +736,6 @@ func TestEnsureRootNotZeroHashes(t *testing.T) {
|
||||
assert.Equal(t, root, r, "Did not get wanted justified root")
|
||||
}
|
||||
|
||||
func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
fcs := protoarray.New(0, 0, [32]byte{'a'})
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(fcs),
|
||||
}
|
||||
ctx := context.Background()
|
||||
type args struct {
|
||||
cachedCheckPoint *ethpb.Checkpoint
|
||||
stateCheckPoint *ethpb.Checkpoint
|
||||
diffFinalizedCheckPoint bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *ethpb.Checkpoint
|
||||
}{
|
||||
{
|
||||
name: "Same justified, do nothing",
|
||||
args: args{
|
||||
cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
|
||||
stateCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
|
||||
},
|
||||
want: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
|
||||
},
|
||||
{
|
||||
name: "Different justified, higher epoch, cache new justified",
|
||||
args: args{
|
||||
cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
|
||||
stateCheckPoint: ðpb.Checkpoint{Epoch: 2, Root: []byte{'b'}},
|
||||
},
|
||||
want: ðpb.Checkpoint{Epoch: 2, Root: []byte{'b'}},
|
||||
},
|
||||
{
|
||||
name: "finalized has different justified, cache new justified",
|
||||
args: args{
|
||||
cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
|
||||
stateCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'b'}},
|
||||
diffFinalizedCheckPoint: true,
|
||||
},
|
||||
want: ðpb.Checkpoint{Epoch: 1, Root: []byte{'b'}},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
beaconState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint))
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.store.SetJustifiedCheckpt(test.args.cachedCheckPoint)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
|
||||
genesisState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
|
||||
|
||||
if test.args.diffFinalizedCheckPoint {
|
||||
b1 := util.NewBeaconBlock()
|
||||
b1.Block.Slot = 1
|
||||
b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
|
||||
r1, err := b1.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b100 := util.NewBeaconBlock()
|
||||
b100.Block.Slot = 100
|
||||
b100.Block.ParentRoot = r1[:]
|
||||
r100, err := b100.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
for _, b := range []*ethpb.SignedBeaconBlock{b1, b100} {
|
||||
beaconBlock := util.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Block.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)))
|
||||
}
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: []byte{'c'}, Epoch: 1})
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r100[:], Epoch: service.store.JustifiedCheckpt().Epoch})
|
||||
}
|
||||
|
||||
require.NoError(t, service.finalizedImpliesNewJustified(ctx, beaconState))
|
||||
assert.Equal(t, true, attestation.CheckPointIsEqual(test.want, service.store.JustifiedCheckpt()), "Did not get wanted check point")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyBlkDescendant(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -42,7 +42,7 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveAttestationNoPubsub")
|
||||
defer span.End()
|
||||
|
||||
if err := s.onAttestation(ctx, att); err != nil {
|
||||
if err := s.OnAttestation(ctx, att); err != nil {
|
||||
return errors.Wrap(err, "could not process attestation")
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ func (s *Service) spawnProcessAttestationsRoutine(stateFeed *event.Feed) {
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
case <-st.C():
|
||||
if err := s.newSlot(s.ctx, s.CurrentSlot()); err != nil {
|
||||
if err := s.NewSlot(s.ctx, s.CurrentSlot()); err != nil {
|
||||
log.WithError(err).Error("Could not process new slot")
|
||||
return
|
||||
}
|
||||
|
||||
5
beacon-chain/cache/depositcache/BUILD.bazel
vendored
5
beacon-chain/cache/depositcache/BUILD.bazel
vendored
@@ -8,7 +8,10 @@ go_library(
|
||||
"pending_deposits.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
|
||||
@@ -7,7 +7,10 @@ go_library(
|
||||
"interfaces.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -229,6 +230,13 @@ func (s *Store) FinalizedEpoch() types.Epoch {
|
||||
return s.finalizedEpoch
|
||||
}
|
||||
|
||||
// ProposerBoost of fork choice store.
|
||||
func (s *Store) ProposerBoost() [fieldparams.RootLength]byte {
|
||||
s.proposerBoostLock.RLock()
|
||||
defer s.proposerBoostLock.RUnlock()
|
||||
return s.proposerBoostRoot
|
||||
}
|
||||
|
||||
// Nodes of fork choice store.
|
||||
func (s *Store) Nodes() []*Node {
|
||||
s.nodesLock.RLock()
|
||||
|
||||
@@ -43,7 +43,7 @@ type Node struct {
|
||||
weight uint64 // weight of this node.
|
||||
bestChild uint64 // bestChild index of this node.
|
||||
bestDescendant uint64 // bestDescendant of this node.
|
||||
graffiti [32]byte // graffiti of the block node.
|
||||
graffiti [fieldparams.RootLength]byte // graffiti of the block node.
|
||||
}
|
||||
|
||||
// optimisticStore defines a structure that tracks the tips of the fully
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/operations/attestations/kv:go_default_library",
|
||||
|
||||
@@ -19,6 +19,7 @@ go_library(
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/endtoend:__subpackages__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
|
||||
14
testing/spectest/mainnet/altair/forkchoice/BUILD.bazel
Normal file
14
testing/spectest/mainnet/altair/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMainnet_Altair_Forkchoice(t *testing.T) {
|
||||
forkchoice.Run(t, "mainnet", version.Altair)
|
||||
}
|
||||
14
testing/spectest/mainnet/phase0/forkchoice/BUILD.bazel
Normal file
14
testing/spectest/mainnet/phase0/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMainnet_Altair_Forkchoice(t *testing.T) {
|
||||
forkchoice.Run(t, "mainnet", version.Phase0)
|
||||
}
|
||||
18
testing/spectest/minimal/altair/forkchoice/BUILD.bazel
Normal file
18
testing/spectest/minimal/altair/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,18 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMinimal_Altair_Forkchoice(t *testing.T) {
|
||||
forkchoice.Run(t, "minimal", version.Altair)
|
||||
}
|
||||
18
testing/spectest/minimal/phase0/forkchoice/BUILD.bazel
Normal file
18
testing/spectest/minimal/phase0/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,18 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = [
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMinimal_Altair_Forkchoice(t *testing.T) {
|
||||
forkchoice.Run(t, "minimal", version.Phase0)
|
||||
}
|
||||
40
testing/spectest/shared/common/forkchoice/BUILD.bazel
Normal file
40
testing/spectest/shared/common/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,40 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"runner.go",
|
||||
"service.go",
|
||||
"type.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/testing/spectest/shared/common/forkchoice",
|
||||
visibility = ["//testing/spectest:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/state/v1:go_default_library",
|
||||
"//beacon-chain/state/v2:go_default_library",
|
||||
"//beacon-chain/state/v3:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/block:go_default_library",
|
||||
"//proto/prysm/v1alpha1/wrapper:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/spectest/utils:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
],
|
||||
)
|
||||
228
testing/spectest/shared/common/forkchoice/runner.go
Normal file
228
testing/spectest/shared/common/forkchoice/runner.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/golang/snappy"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/spectest/utils"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
)
|
||||
|
||||
// Run executes "forkchoice" test.
|
||||
func Run(t *testing.T, config string, fork int) {
|
||||
require.NoError(t, utils.SetConfig(t, config))
|
||||
testFolders, _ := utils.TestFolders(t, config, version.String(fork), "fork_choice")
|
||||
|
||||
for _, folder := range testFolders {
|
||||
folderPath := path.Join("fork_choice", folder.Name(), "pyspec_tests")
|
||||
testFolders, testsFolderPath := utils.TestFolders(t, config, version.String(fork), folderPath)
|
||||
|
||||
for _, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
preStepsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "steps.yaml")
|
||||
require.NoError(t, err)
|
||||
var steps []Step
|
||||
require.NoError(t, utils.UnmarshalYaml(preStepsFile, &steps))
|
||||
|
||||
preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "anchor_state.ssz_snappy")
|
||||
require.NoError(t, err)
|
||||
preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile)
|
||||
require.NoError(t, err)
|
||||
|
||||
blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "anchor_block.ssz_snappy")
|
||||
require.NoError(t, err)
|
||||
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
|
||||
require.NoError(t, err)
|
||||
|
||||
var beaconState state.BeaconState
|
||||
var beaconBlock block.SignedBeaconBlock
|
||||
switch fork {
|
||||
case version.Phase0:
|
||||
beaconState = unmarshalPhase0State(t, preBeaconStateSSZ)
|
||||
beaconBlock = unmarshalPhase0Block(t, blockSSZ)
|
||||
case version.Altair:
|
||||
beaconState = unmarshalAltairState(t, preBeaconStateSSZ)
|
||||
beaconBlock = unmarshalAltairBlock(t, blockSSZ)
|
||||
case version.Bellatrix:
|
||||
beaconState = unmarshalBellatrixState(t, preBeaconStateSSZ)
|
||||
beaconBlock = unmarshalBellatrixBlock(t, blockSSZ)
|
||||
default:
|
||||
t.Fatalf("unknown fork version: %v", fork)
|
||||
}
|
||||
|
||||
service := startChainService(t, beaconState, beaconBlock)
|
||||
var lastTick int64
|
||||
for _, step := range steps {
|
||||
if step.Tick != nil {
|
||||
newTick := int64(*step.Tick)
|
||||
service.SetGenesisTime(time.Unix(time.Now().Unix()-newTick, 0))
|
||||
if newTick > lastTick {
|
||||
slot := uint64(newTick) / params.BeaconConfig().SecondsPerSlot
|
||||
require.NoError(t, service.NewSlot(ctx, types.Slot(slot)))
|
||||
lastTick = newTick
|
||||
}
|
||||
}
|
||||
if step.Block != nil {
|
||||
blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.Block, ".ssz_snappy"))
|
||||
require.NoError(t, err)
|
||||
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
|
||||
require.NoError(t, err)
|
||||
var beaconBlock block.SignedBeaconBlock
|
||||
switch fork {
|
||||
case version.Phase0:
|
||||
beaconBlock = unmarshalSignedPhase0Block(t, blockSSZ)
|
||||
case version.Altair:
|
||||
beaconBlock = unmarshalSignedAltairBlock(t, blockSSZ)
|
||||
case version.Bellatrix:
|
||||
beaconBlock = unmarshalSignedBellatrixBlock(t, blockSSZ)
|
||||
default:
|
||||
t.Fatalf("unknown fork version: %v", fork)
|
||||
}
|
||||
r, err := beaconBlock.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
if step.Valid != nil && !*step.Valid {
|
||||
require.Equal(t, true, service.ReceiveBlock(ctx, beaconBlock, r) != nil)
|
||||
} else {
|
||||
require.NoError(t, service.ReceiveBlock(ctx, beaconBlock, r))
|
||||
}
|
||||
}
|
||||
if step.Attestation != nil {
|
||||
attFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.Attestation, ".ssz_snappy"))
|
||||
require.NoError(t, err)
|
||||
attSSZ, err := snappy.Decode(nil /* dst */, attFile)
|
||||
require.NoError(t, err)
|
||||
att := ðpb.Attestation{}
|
||||
require.NoError(t, att.UnmarshalSSZ(attSSZ), "Failed to unmarshal")
|
||||
require.NoError(t, service.OnAttestation(ctx, att))
|
||||
}
|
||||
if step.Check != nil {
|
||||
require.NoError(t, service.UpdateHeadWithBalances(ctx))
|
||||
c := step.Check
|
||||
if c.Head != nil {
|
||||
r, err := service.HeadRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, common.FromHex(c.Head.Root), r)
|
||||
require.Equal(t, types.Slot(c.Head.Slot), service.HeadSlot())
|
||||
}
|
||||
if c.JustifiedCheckPoint != nil {
|
||||
cp := ðpb.Checkpoint{
|
||||
Epoch: types.Epoch(c.JustifiedCheckPoint.Epoch),
|
||||
Root: common.FromHex(c.JustifiedCheckPoint.Root),
|
||||
}
|
||||
require.DeepEqual(t, cp, service.CurrentJustifiedCheckpt())
|
||||
}
|
||||
if c.BestJustifiedCheckPoint != nil {
|
||||
cp := ðpb.Checkpoint{
|
||||
Epoch: types.Epoch(c.BestJustifiedCheckPoint.Epoch),
|
||||
Root: common.FromHex(c.BestJustifiedCheckPoint.Root),
|
||||
}
|
||||
require.DeepEqual(t, cp, service.BestJustifiedCheckpt())
|
||||
}
|
||||
if c.FinalizedCheckPoint != nil {
|
||||
cp := ðpb.Checkpoint{
|
||||
Epoch: types.Epoch(c.FinalizedCheckPoint.Epoch),
|
||||
Root: common.FromHex(c.FinalizedCheckPoint.Root),
|
||||
}
|
||||
require.DeepSSZEqual(t, cp, service.FinalizedCheckpt())
|
||||
}
|
||||
if c.ProposerBoostRoot != nil {
|
||||
want := common.FromHex(*c.ProposerBoostRoot)
|
||||
require.DeepEqual(t, bytesutil.ToBytes32(want), service.ProtoArrayStore().ProposerBoost())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalPhase0State(t *testing.T, raw []byte) state.BeaconState {
|
||||
base := ðpb.BeaconState{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
st, err := v1.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
return st
|
||||
}
|
||||
|
||||
func unmarshalPhase0Block(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.BeaconBlock{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func unmarshalSignedPhase0Block(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.SignedBeaconBlock{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(base)
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func unmarshalAltairState(t *testing.T, raw []byte) state.BeaconState {
|
||||
base := ðpb.BeaconStateAltair{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
st, err := v2.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
return st
|
||||
}
|
||||
|
||||
func unmarshalAltairBlock(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.BeaconBlockAltair{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(ðpb.SignedBeaconBlockAltair{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func unmarshalSignedAltairBlock(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.SignedBeaconBlockAltair{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(base)
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func unmarshalBellatrixState(t *testing.T, raw []byte) state.BeaconState {
|
||||
base := ðpb.BeaconStateBellatrix{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
st, err := v3.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
return st
|
||||
}
|
||||
|
||||
func unmarshalBellatrixBlock(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.BeaconBlockBellatrix{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func unmarshalSignedBellatrixBlock(t *testing.T, raw []byte) block.SignedBeaconBlock {
|
||||
base := ðpb.SignedBeaconBlockBellatrix{}
|
||||
require.NoError(t, base.UnmarshalSSZ(raw))
|
||||
blk, err := wrapper.WrappedSignedBeaconBlock(base)
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
58
testing/spectest/shared/common/forkchoice/service.go
Normal file
58
testing/spectest/shared/common/forkchoice/service.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
coreTime "github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func startChainService(t *testing.T, st state.BeaconState, block block.SignedBeaconBlock) *blockchain.Service {
|
||||
db := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
require.NoError(t, db.SaveBlock(ctx, block))
|
||||
r, err := block.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, r))
|
||||
require.NoError(t, db.SaveState(ctx, st, r))
|
||||
cp := ðpb.Checkpoint{
|
||||
Epoch: coreTime.CurrentEpoch(st),
|
||||
Root: r[:],
|
||||
}
|
||||
require.NoError(t, db.SaveJustifiedCheckpoint(ctx, cp))
|
||||
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
|
||||
attPool, err := attestations.NewService(ctx, &attestations.Config{
|
||||
Pool: attestations.NewPool(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := append([]blockchain.Option{},
|
||||
blockchain.WithFinalizedStateAtStartUp(st),
|
||||
blockchain.WithDatabase(db),
|
||||
blockchain.WithAttestationService(attPool),
|
||||
blockchain.WithForkChoiceStore(protoarray.New(0, 0, params.BeaconConfig().ZeroHash)),
|
||||
blockchain.WithStateGen(stategen.New(db)),
|
||||
blockchain.WithStateNotifier(&mock.MockStateNotifier{}),
|
||||
blockchain.WithAttestationPool(attestations.NewPool()),
|
||||
blockchain.WithDepositCache(depositCache),
|
||||
)
|
||||
service, err := blockchain.NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
service.Start()
|
||||
return service
|
||||
}
|
||||
29
testing/spectest/shared/common/forkchoice/type.go
Normal file
29
testing/spectest/shared/common/forkchoice/type.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package forkchoice
|
||||
|
||||
type Step struct {
|
||||
Tick *int `json:"tick"`
|
||||
Block *string `json:"block"`
|
||||
Valid *bool `json:"valid"`
|
||||
Attestation *string `json:"attestation"`
|
||||
Check *Check `json:"checks"`
|
||||
}
|
||||
|
||||
type Check struct {
|
||||
Time *int `json:"time"`
|
||||
GenesisTime int `json:"genesis_time"`
|
||||
ProposerBoostRoot *string `json:"proposer_boost_root"`
|
||||
Head *SlotRoot `json:"head"`
|
||||
JustifiedCheckPoint *EpochRoot `json:"justified_checkpoint"`
|
||||
BestJustifiedCheckPoint *EpochRoot `json:"best_justified_checkpoint"`
|
||||
FinalizedCheckPoint *EpochRoot `json:"finalized_checkpoint"`
|
||||
}
|
||||
|
||||
type SlotRoot struct {
|
||||
Slot int `json:"slot"`
|
||||
Root string `json:"root"`
|
||||
}
|
||||
|
||||
type EpochRoot struct {
|
||||
Epoch int `json:"epoch"`
|
||||
Root string `json:"root"`
|
||||
}
|
||||
Reference in New Issue
Block a user