mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-07 22:54:17 -05:00
Update to v0.12 (#5614)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://app.fuzzit.dev/orgs/prysmaticlabs-gh/dashboard)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v0.11.3)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v0.12.1)
|
||||
[](https://discord.gg/KSA7rPr)
|
||||
[](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
|
||||
12
WORKSPACE
12
WORKSPACE
@@ -215,8 +215,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "489f85d7c17a901b9069c95f656154fdf1385db00f3aeb3e0319aed8745f9453",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/general.tar.gz",
|
||||
sha256 = "678c50336ce39bef19b2a0dc69e20a7bda37a673ae07dc0577386e9876e0a525",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/general.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -231,8 +231,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "b83000fbcb60b7a5b8c0e805f3fee6953b17bfe0fe6658416e7d99e6d261f284",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/minimal.tar.gz",
|
||||
sha256 = "d0ce95a3ca0d30df24f96a1b5cfad1f7e6fcc07ad84ca221d92480add051af3e",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/minimal.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -247,8 +247,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "ae0c09ab49afa69085c91f9e2f2f4de6526d43b927609839b1597c674b4dccde",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/mainnet.tar.gz",
|
||||
sha256 = "1dfa1ae6822912508dbf6d1fe7608169372daa3ad1e53a3ed0867cb2d6e0ccb0",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/mainnet.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
@@ -45,6 +45,7 @@ type HeadFetcher interface {
|
||||
HeadValidatorsIndices(epoch uint64) ([]uint64, error)
|
||||
HeadSeed(epoch uint64) ([32]byte, error)
|
||||
HeadGenesisValidatorRoot() [32]byte
|
||||
HeadETH1Data() *ethpb.Eth1Data
|
||||
ProtoArrayStore() *protoarray.Store
|
||||
}
|
||||
|
||||
@@ -179,6 +180,14 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte {
|
||||
return s.headGenesisValidatorRoot()
|
||||
}
|
||||
|
||||
// HeadETH1Data returns the eth1data of the current head state.
|
||||
func (s *Service) HeadETH1Data() *ethpb.Eth1Data {
|
||||
if !s.hasHeadState() {
|
||||
return ðpb.Eth1Data{}
|
||||
}
|
||||
return s.head.state.Eth1Data()
|
||||
}
|
||||
|
||||
// ProtoArrayStore returns the proto array store object.
|
||||
func (s *Service) ProtoArrayStore() *protoarray.Store {
|
||||
return s.forkChoiceStore.Store()
|
||||
|
||||
@@ -210,3 +210,24 @@ func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
|
||||
t.Error("Did not get correct genesis validator root")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeadETH1Data_Nil(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
c := setupBeaconChain(t, db)
|
||||
if !reflect.DeepEqual(c.HeadETH1Data(), ðpb.Eth1Data{}) {
|
||||
t.Error("Incorrect pre chain start value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeadETH1Data_CanRetrieve(t *testing.T) {
|
||||
d := ðpb.Eth1Data{DepositCount: 999}
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Eth1Data: d})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := &Service{}
|
||||
c.head = &head{state: s}
|
||||
if !proto.Equal(c.HeadETH1Data(), d) {
|
||||
t.Error("Received incorrect eth1 data")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
@@ -242,7 +241,7 @@ func TestGenerateState_CorrectlyGenerated(t *testing.T) {
|
||||
}
|
||||
|
||||
beaconState, privs := testutil.DeterministicGenesisState(t, 32)
|
||||
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
||||
genesisBlock := testutil.NewBeaconBlock()
|
||||
bodyRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -36,14 +36,12 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
|
||||
// current_epoch = compute_epoch_at_slot(get_current_slot(store))
|
||||
// # Use GENESIS_EPOCH for previous when genesis to avoid underflow
|
||||
// previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else GENESIS_EPOCH
|
||||
// # If attestation target is from a future epoch, delay consideration until the epoch arrives
|
||||
// assert target.epoch in [current_epoch, previous_epoch]
|
||||
// assert target.epoch == compute_epoch_at_slot(attestation.data.slot)
|
||||
//
|
||||
// # Attestations target be for a known block. If target block is unknown, delay consideration until the block is found
|
||||
// assert target.root in store.blocks
|
||||
// # Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrives
|
||||
// base_state = store.block_states[target.root].copy()
|
||||
// assert store.time >= base_state.genesis_time + compute_start_slot_at_epoch(target.epoch) * SECONDS_PER_SLOT
|
||||
//
|
||||
// # Attestations must be for a known block. If block is unknown, delay consideration until the block is found
|
||||
// assert attestation.data.beacon_block_root in store.blocks
|
||||
@@ -68,6 +66,7 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
|
||||
// for i in indexed_attestation.attesting_indices:
|
||||
// if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch:
|
||||
// store.latest_messages[i] = LatestMessage(epoch=target.epoch, root=attestation.data.beacon_block_root)
|
||||
// TODO(#6072): This code path is highly untested. Requires comprehensive tests and simpler refactoring.
|
||||
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockchain.onAttestation")
|
||||
defer span.End()
|
||||
@@ -83,7 +82,6 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
}
|
||||
|
||||
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
||||
tgtSlot := helpers.StartSlot(tgt.Epoch)
|
||||
|
||||
if helpers.SlotToEpoch(a.Data.Slot) != a.Data.Target.Epoch {
|
||||
return nil, fmt.Errorf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(a.Data.Slot), a.Data.Target.Epoch)
|
||||
@@ -108,16 +106,16 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify Attestations cannot be from future epochs.
|
||||
if err := helpers.VerifySlotTime(genesisTime, tgtSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation target slot")
|
||||
}
|
||||
|
||||
// Verify attestation beacon block is known and not from the future.
|
||||
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation beacon block")
|
||||
}
|
||||
|
||||
// Verify LMG GHOST and FFG votes are consistent with each other.
|
||||
if err := s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation beacon block")
|
||||
}
|
||||
|
||||
// Verify attestations can only affect the fork choice of subsequent slots.
|
||||
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -143,6 +143,20 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyLMDFFGConsistent verifies LMD GHOST and FFG votes are consistent with each other.
|
||||
func (s *Service) verifyLMDFFGConsistent(ctx context.Context, ffgEpoch uint64, ffgRoot []byte, lmdRoot []byte) error {
|
||||
ffgSlot := helpers.StartSlot(ffgEpoch)
|
||||
r, err := s.ancestor(ctx, lmdRoot, ffgSlot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(ffgRoot, r) {
|
||||
return errors.New("FFG and LMD votes are not consistent")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyAttestation validates input attestation is valid.
|
||||
func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.BeaconState, a *ethpb.Attestation) (*ethpb.IndexedAttestation, error) {
|
||||
committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex)
|
||||
|
||||
@@ -468,3 +468,68 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
|
||||
t.Error("Did not receive the wanted error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b32 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 32}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r32, err := stateutil.BlockRoot(b32.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b33 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 33, ParentRoot: r32[:]}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b33); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r33, err := stateutil.BlockRoot(b33.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wanted := "FFG and LMD votes are not consistent"
|
||||
if err := service.verifyLMDFFGConsistent(context.Background(), 1, []byte{'a'}, r33[:]); err.Error() != wanted {
|
||||
t.Error("Did not get wanted error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b32 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 32}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b32); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r32, err := stateutil.BlockRoot(b32.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b33 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 33, ParentRoot: r32[:]}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b33); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r33, err := stateutil.BlockRoot(b33.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := service.verifyLMDFFGConsistent(context.Background(), 1, r32[:], r33[:]); err != nil {
|
||||
t.Errorf("Could not verify LMD and FFG votes to be consistent: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +387,8 @@ func (s *Service) filterBlockRoots(ctx context.Context, roots [][32]byte) ([][32
|
||||
// elif block.slot == slot:
|
||||
// return root
|
||||
// else:
|
||||
// return Bytes32() # root is older than queried slot: no results.
|
||||
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot.
|
||||
// return root
|
||||
func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "forkchoice.ancestor")
|
||||
defer span.End()
|
||||
|
||||
@@ -230,13 +230,15 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
if !update {
|
||||
t.Error("Should be able to update justified, received false")
|
||||
}
|
||||
|
||||
lastJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: []byte{'G'}}}
|
||||
lastJustifiedBlk := testutil.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1, ParentRoot: lastJustifiedRoot[:]}}
|
||||
newJustifiedBlk := testutil.NewBeaconBlock()
|
||||
newJustifiedBlk.Block.Slot = 1
|
||||
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
|
||||
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -271,12 +273,14 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: []byte{'G'}}}
|
||||
lastJustifiedBlk := testutil.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: lastJustifiedRoot[:]}}
|
||||
newJustifiedBlk := testutil.NewBeaconBlock()
|
||||
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
|
||||
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -743,11 +747,14 @@ func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
|
||||
b.Body = ðpb.BeaconBlockBody{}
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
|
||||
beaconBlock.Block.Body = ðpb.BeaconBlockBody{}
|
||||
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(b.ParentRoot)); err != nil {
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -64,6 +65,11 @@ func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mb *mockBroadcaster) BroadcastAttestation(_ context.Context, _ uint64, _ *ethpb.Attestation) error {
|
||||
mb.broadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ = p2p.Broadcaster(&mockBroadcaster{})
|
||||
|
||||
func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
@@ -186,7 +192,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
|
||||
chainService := setupBeaconChain(t, db)
|
||||
|
||||
genesisBlk := b.NewGenesisBlock([]byte{})
|
||||
genesisBlk := testutil.NewBeaconBlock()
|
||||
blkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -283,7 +289,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := b.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -296,7 +302,9 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
|
||||
headBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: finalizedSlot, ParentRoot: genesisRoot[:]}}
|
||||
headBlock := testutil.NewBeaconBlock()
|
||||
headBlock.Block.Slot = finalizedSlot
|
||||
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
|
||||
headState := testutil.NewBeaconState()
|
||||
if err := headState.SetSlot(finalizedSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -323,9 +331,6 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveBlock(ctx, headBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := &Service{beaconDB: db, stateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
||||
if err := c.initializeChainInfo(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -37,6 +37,7 @@ type ChainService struct {
|
||||
Genesis time.Time
|
||||
ValidatorsRoot [32]byte
|
||||
Fork *pb.Fork
|
||||
ETH1Data *ethpb.Eth1Data
|
||||
DB db.Database
|
||||
stateNotifier statefeed.Notifier
|
||||
blockNotifier blockfeed.Notifier
|
||||
@@ -222,6 +223,11 @@ func (ms *ChainService) HeadSeed(epoch uint64) ([32]byte, error) {
|
||||
return helpers.Seed(ms.State, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
}
|
||||
|
||||
// HeadETH1Data provides the current ETH1Data of the head state.
|
||||
func (ms *ChainService) HeadETH1Data() *ethpb.Eth1Data {
|
||||
return ms.ETH1Data
|
||||
}
|
||||
|
||||
// ProtoArrayStore mocks the same method in the chain service.
|
||||
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
|
||||
return ms.ForkChoiceStore
|
||||
@@ -252,6 +258,12 @@ func (ms *ChainService) IsValidAttestation(ctx context.Context, att *ethpb.Attes
|
||||
return ms.ValidAttestation
|
||||
}
|
||||
|
||||
// IsCanonical returns and determines whether a block with the provided root is part of
|
||||
// the canonical chain.
|
||||
func (ms *ChainService) IsCanonical(ctx context.Context, blockRoot [32]byte) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// ClearCachedStates does nothing.
|
||||
func (ms *ChainService) ClearCachedStates() {}
|
||||
|
||||
|
||||
4
beacon-chain/cache/BUILD.bazel
vendored
4
beacon-chain/cache/BUILD.bazel
vendored
@@ -7,12 +7,12 @@ go_library(
|
||||
"attestation_data.go",
|
||||
"checkpoint_state.go",
|
||||
"committee.go",
|
||||
"committee_ids.go",
|
||||
"common.go",
|
||||
"doc.go",
|
||||
"hot_state_cache.go",
|
||||
"skip_slot_cache.go",
|
||||
"state_summary.go",
|
||||
"subnet_ids.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
|
||||
visibility = [
|
||||
@@ -44,11 +44,11 @@ go_test(
|
||||
"attestation_data_test.go",
|
||||
"checkpoint_state_test.go",
|
||||
"committee_fuzz_test.go",
|
||||
"committee_ids_test.go",
|
||||
"committee_test.go",
|
||||
"feature_flag_test.go",
|
||||
"hot_state_cache_test.go",
|
||||
"skip_slot_cache_test.go",
|
||||
"subnet_ids_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
)
|
||||
|
||||
type committeeIDs struct {
|
||||
type subnetIDs struct {
|
||||
attester *lru.Cache
|
||||
attesterLock sync.RWMutex
|
||||
aggregator *lru.Cache
|
||||
@@ -19,10 +19,10 @@ type committeeIDs struct {
|
||||
subnetsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// CommitteeIDs for attester and aggregator.
|
||||
var CommitteeIDs = newCommitteeIDs()
|
||||
// SubnetIDs for attester and aggregator.
|
||||
var SubnetIDs = newSubnetIDs()
|
||||
|
||||
func newCommitteeIDs() *committeeIDs {
|
||||
func newSubnetIDs() *subnetIDs {
|
||||
// Given a node can calculate committee assignments of current epoch and next epoch.
|
||||
// Max size is set to 2 epoch length.
|
||||
cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2)
|
||||
@@ -37,15 +37,15 @@ func newCommitteeIDs() *committeeIDs {
|
||||
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot)
|
||||
subLength := epochDuration * time.Duration(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
||||
persistentCache := cache.New(subLength*time.Second, epochDuration*time.Second)
|
||||
return &committeeIDs{attester: attesterCache, aggregator: aggregatorCache, persistentSubnets: persistentCache}
|
||||
return &subnetIDs{attester: attesterCache, aggregator: aggregatorCache, persistentSubnets: persistentCache}
|
||||
}
|
||||
|
||||
// AddAttesterCommiteeID adds committee ID for subscribing subnet for the attester of a given slot.
|
||||
func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
|
||||
// AddAttesterSubnetID adds the subnet index for subscribing subnet for the attester of a given slot.
|
||||
func (c *subnetIDs) AddAttesterSubnetID(slot uint64, subnetID uint64) {
|
||||
c.attesterLock.Lock()
|
||||
defer c.attesterLock.Unlock()
|
||||
|
||||
ids := []uint64{committeeID}
|
||||
ids := []uint64{subnetID}
|
||||
val, exists := c.attester.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
@@ -53,8 +53,8 @@ func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
|
||||
c.attester.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot.
|
||||
func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
|
||||
// GetAttesterSubnetIDs gets the subnet IDs for subscribed subnets for attesters of the slot.
|
||||
func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
|
||||
c.attesterLock.RLock()
|
||||
defer c.attesterLock.RUnlock()
|
||||
|
||||
@@ -68,12 +68,12 @@ func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddAggregatorCommiteeID adds committee ID for subscribing subnet for the aggregator of a given slot.
|
||||
func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) {
|
||||
// AddAggregatorSubnetID adds the subnet ID for subscribing subnet for the aggregator of a given slot.
|
||||
func (c *subnetIDs) AddAggregatorSubnetID(slot uint64, subnetID uint64) {
|
||||
c.aggregatorLock.Lock()
|
||||
defer c.aggregatorLock.Unlock()
|
||||
|
||||
ids := []uint64{committeeID}
|
||||
ids := []uint64{subnetID}
|
||||
val, exists := c.aggregator.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
@@ -81,8 +81,8 @@ func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64)
|
||||
c.aggregator.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot.
|
||||
func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
|
||||
// GetAggregatorSubnetIDs gets the subnet IDs for subscribing subnet for aggregator of the slot.
|
||||
func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
|
||||
c.aggregatorLock.RLock()
|
||||
defer c.aggregatorLock.RUnlock()
|
||||
|
||||
@@ -93,9 +93,9 @@ func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
|
||||
return val.([]uint64)
|
||||
}
|
||||
|
||||
// GetPersistentCommittees retrieves the persistent committee and expiration time of that validator's
|
||||
// GetPersistentSubnets retrieves the persistent subnet and expiration time of that validator's
|
||||
// subscription.
|
||||
func (c *committeeIDs) GetPersistentCommittees(pubkey []byte) ([]uint64, bool, time.Time) {
|
||||
func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
|
||||
c.subnetsLock.RLock()
|
||||
defer c.subnetsLock.RUnlock()
|
||||
|
||||
@@ -106,9 +106,9 @@ func (c *committeeIDs) GetPersistentCommittees(pubkey []byte) ([]uint64, bool, t
|
||||
return id.([]uint64), ok, duration
|
||||
}
|
||||
|
||||
// GetAllCommittees retrieves all the non-expired subscribed committees of all the validators
|
||||
// GetAllSubnets retrieves all the non-expired subscribed subnets of all the validators
|
||||
// in the cache.
|
||||
func (c *committeeIDs) GetAllCommittees() []uint64 {
|
||||
func (c *subnetIDs) GetAllSubnets() []uint64 {
|
||||
c.subnetsLock.RLock()
|
||||
defer c.subnetsLock.RUnlock()
|
||||
|
||||
@@ -126,7 +126,7 @@ func (c *committeeIDs) GetAllCommittees() []uint64 {
|
||||
|
||||
// AddPersistentCommittee adds the relevant committee for that particular validator along with its
|
||||
// expiration period.
|
||||
func (c *committeeIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
|
||||
func (c *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
|
||||
c.subnetsLock.Lock()
|
||||
defer c.subnetsLock.Unlock()
|
||||
|
||||
@@ -5,59 +5,59 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommitteeIDCache_RoundTrip(t *testing.T) {
|
||||
c := newCommitteeIDs()
|
||||
func TestSubnetIDsCache_RoundTrip(t *testing.T) {
|
||||
c := newSubnetIDs()
|
||||
slot := uint64(100)
|
||||
committeeIDs := c.GetAggregatorCommitteeIDs(slot)
|
||||
committeeIDs := c.GetAggregatorSubnetIDs(slot)
|
||||
if len(committeeIDs) != 0 {
|
||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 1)
|
||||
res := c.GetAggregatorCommitteeIDs(slot)
|
||||
c.AddAggregatorSubnetID(slot, 1)
|
||||
res := c.GetAggregatorSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 2)
|
||||
res = c.GetAggregatorCommitteeIDs(slot)
|
||||
c.AddAggregatorSubnetID(slot, 2)
|
||||
res = c.GetAggregatorSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1, 2}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 3)
|
||||
res = c.GetAggregatorCommitteeIDs(slot)
|
||||
c.AddAggregatorSubnetID(slot, 3)
|
||||
res = c.GetAggregatorSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1, 2, 3}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
committeeIDs = c.GetAttesterCommitteeIDs(slot)
|
||||
committeeIDs = c.GetAttesterSubnetIDs(slot)
|
||||
if len(committeeIDs) != 0 {
|
||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 11)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
c.AddAttesterSubnetID(slot, 11)
|
||||
res = c.GetAttesterSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 22)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
c.AddAttesterSubnetID(slot, 22)
|
||||
res = c.GetAttesterSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11, 22}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 33)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
c.AddAttesterSubnetID(slot, 33)
|
||||
res = c.GetAttesterSubnetIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11, 22, 33}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
||||
func TestSubnetIDsCache_PersistentCommitteeRoundtrip(t *testing.T) {
|
||||
pubkeySet := [][48]byte{}
|
||||
c := newCommitteeIDs()
|
||||
c := newSubnetIDs()
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
pubkey := [48]byte{byte(i)}
|
||||
@@ -68,7 +68,7 @@ func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
pubkey := [48]byte{byte(i)}
|
||||
|
||||
idxs, ok, _ := c.GetPersistentCommittees(pubkey[:])
|
||||
idxs, ok, _ := c.GetPersistentSubnets(pubkey[:])
|
||||
if !ok {
|
||||
t.Errorf("Couldn't find entry in cache for pubkey %#x", pubkey)
|
||||
continue
|
||||
@@ -77,7 +77,7 @@ func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
||||
t.Fatalf("Wanted index of %d but got %d", i, idxs[0])
|
||||
}
|
||||
}
|
||||
coms := c.GetAllCommittees()
|
||||
coms := c.GetAllSubnets()
|
||||
if len(coms) != 20 {
|
||||
t.Errorf("Number of committees is not %d but is %d", 20, len(coms))
|
||||
}
|
||||
@@ -44,11 +44,11 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root")
|
||||
}
|
||||
sigRoot := &pb.SigningRoot{
|
||||
signingData := &pb.SigningData{
|
||||
ObjectRoot: root[:],
|
||||
Domain: domain,
|
||||
}
|
||||
ctrRoot, err := ssz.HashTreeRoot(sigRoot)
|
||||
ctrRoot, err := ssz.HashTreeRoot(signingData)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get container root")
|
||||
}
|
||||
@@ -67,11 +67,11 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain []b
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
ctr := &pb.SigningRoot{
|
||||
signingData := &pb.SigningData{
|
||||
ObjectRoot: signedData,
|
||||
Domain: domain,
|
||||
}
|
||||
root, err := ssz.HashTreeRoot(ctr)
|
||||
root, err := ssz.HashTreeRoot(signingData)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash container")
|
||||
}
|
||||
@@ -1104,11 +1104,11 @@ func VerifyExit(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, fork
|
||||
return fmt.Errorf("expected current epoch >= exit epoch, received %d < %d", currentEpoch, exit.Epoch)
|
||||
}
|
||||
// Verify the validator has been active long enough.
|
||||
if currentEpoch < validator.ActivationEpoch()+params.BeaconConfig().PersistentCommitteePeriod {
|
||||
if currentEpoch < validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod {
|
||||
return fmt.Errorf(
|
||||
"validator has not been active long enough to exit, wanted epoch %d >= %d",
|
||||
currentEpoch,
|
||||
validator.ActivationEpoch()+params.BeaconConfig().PersistentCommitteePeriod,
|
||||
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
|
||||
)
|
||||
}
|
||||
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
|
||||
|
||||
@@ -433,7 +433,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root, err := ssz.HashTreeRoot(&pb.SigningRoot{ObjectRoot: buf, Domain: domain})
|
||||
root, err := ssz.HashTreeRoot(&pb.SigningData{ObjectRoot: buf, Domain: domain})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -2018,7 +2018,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = state.SetSlot(state.Slot() + (params.BeaconConfig().PersistentCommitteePeriod * params.BeaconConfig().SlotsPerEpoch))
|
||||
err = state.SetSlot(state.Slot() + (params.BeaconConfig().ShardCommitteePeriod * params.BeaconConfig().SlotsPerEpoch))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ go_test(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -90,12 +91,14 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
|
||||
votedTarget = true
|
||||
}
|
||||
|
||||
same, err = SameHead(s, a)
|
||||
if err != nil {
|
||||
return false, false, false, errors.Wrap(err, "could not check same head")
|
||||
}
|
||||
if same {
|
||||
votedHead = true
|
||||
if votedTarget {
|
||||
same, err = SameHead(s, a)
|
||||
if err != nil {
|
||||
return false, false, false, errors.Wrap(err, "could not check same head")
|
||||
}
|
||||
if same {
|
||||
votedHead = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return votedPrevEpoch, votedTarget, votedHead, nil
|
||||
@@ -176,5 +179,34 @@ func UpdateBalance(vp []*Validator, bBal *Balance) *Balance {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EnsureBalancesLowerBound(bBal)
|
||||
}
|
||||
|
||||
// EnsureBalancesLowerBound ensures all the balances such as active current epoch, active previous epoch and more
|
||||
// have EffectiveBalanceIncrement(1 eth) as a lower bound.
|
||||
func EnsureBalancesLowerBound(bBal *Balance) *Balance {
|
||||
ebi := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
if ebi > bBal.ActiveCurrentEpoch {
|
||||
bBal.ActiveCurrentEpoch = ebi
|
||||
}
|
||||
if ebi > bBal.ActivePrevEpoch {
|
||||
bBal.ActivePrevEpoch = ebi
|
||||
}
|
||||
if ebi > bBal.CurrentEpochAttested {
|
||||
bBal.CurrentEpochAttested = ebi
|
||||
}
|
||||
if ebi > bBal.CurrentEpochTargetAttested {
|
||||
bBal.CurrentEpochTargetAttested = ebi
|
||||
}
|
||||
if ebi > bBal.PrevEpochAttested {
|
||||
bBal.PrevEpochAttested = ebi
|
||||
}
|
||||
if ebi > bBal.PrevEpochTargetAttested {
|
||||
bBal.PrevEpochTargetAttested = ebi
|
||||
}
|
||||
if ebi > bBal.PrevEpochHeadAttested {
|
||||
bBal.PrevEpochHeadAttested = ebi
|
||||
}
|
||||
return bBal
|
||||
}
|
||||
|
||||
@@ -50,21 +50,23 @@ func TestUpdateValidator_InclusionOnlyCountsPrevEpoch(t *testing.T) {
|
||||
|
||||
func TestUpdateBalance(t *testing.T) {
|
||||
vp := []*precompute.Validator{
|
||||
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
||||
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||
}
|
||||
wantedPBal := &precompute.Balance{
|
||||
CurrentEpochAttested: 200,
|
||||
CurrentEpochTargetAttested: 200,
|
||||
PrevEpochAttested: 300,
|
||||
PrevEpochTargetAttested: 100,
|
||||
PrevEpochHeadAttested: 200,
|
||||
ActiveCurrentEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
ActivePrevEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
CurrentEpochAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
CurrentEpochTargetAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochAttested: 300 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochTargetAttested: 100 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochHeadAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
}
|
||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{})
|
||||
if !reflect.DeepEqual(pBal, wantedPBal) {
|
||||
@@ -220,7 +222,7 @@ func TestProcessAttestations(t *testing.T) {
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att2.Data.Target.Root = rt[:]
|
||||
att2.Data.Target.Root = newRt[:]
|
||||
att2.Data.BeaconBlockRoot = newRt[:]
|
||||
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
|
||||
if err != nil {
|
||||
@@ -260,8 +262,37 @@ func TestProcessAttestations(t *testing.T) {
|
||||
if !pVals[i].IsPrevEpochAttester {
|
||||
t.Error("Not a prev epoch attester")
|
||||
}
|
||||
if !pVals[i].IsPrevEpochTargetAttester {
|
||||
t.Error("Not a prev epoch target attester")
|
||||
}
|
||||
if !pVals[i].IsPrevEpochHeadAttester {
|
||||
t.Error("Not a prev epoch head attester")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureBalancesLowerBound(t *testing.T) {
|
||||
b := &precompute.Balance{}
|
||||
b = precompute.EnsureBalancesLowerBound(b)
|
||||
if b.ActiveCurrentEpoch != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted active current balance")
|
||||
}
|
||||
if b.ActivePrevEpoch != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted active previous balance")
|
||||
}
|
||||
if b.CurrentEpochAttested != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted current attested balance")
|
||||
}
|
||||
if b.CurrentEpochTargetAttested != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted target attested balance")
|
||||
}
|
||||
if b.PrevEpochAttested != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted prev attested balance")
|
||||
}
|
||||
if b.PrevEpochTargetAttested != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted prev target attested balance")
|
||||
}
|
||||
if b.PrevEpochHeadAttested != params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
t.Error("Did not get wanted prev head attested balance")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
|
||||
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
// Was validator withdrawable or slashed
|
||||
withdrawable := currentEpoch >= val.WithdrawableEpoch()
|
||||
withdrawable := prevEpoch+1 >= val.WithdrawableEpoch()
|
||||
pVal := &Validator{
|
||||
IsSlashed: val.Slashed(),
|
||||
IsWithdrawableCurrentEpoch: withdrawable,
|
||||
|
||||
@@ -2,7 +2,6 @@ package precompute
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
@@ -27,116 +26,144 @@ func ProcessRewardsAndPenaltiesPrecompute(
|
||||
return state, errors.New("precomputed registries not the same length as state registries")
|
||||
}
|
||||
|
||||
attsRewards, attsPenalties, err := attestationDeltas(state, pBal, vp)
|
||||
attsRewards, attsPenalties, err := AttestationsDelta(state, pBal, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
||||
}
|
||||
proposerRewards, err := proposerDeltaPrecompute(state, pBal, vp)
|
||||
proposerRewards, err := ProposersDelta(state, pBal, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
||||
}
|
||||
validatorBals := state.Balances()
|
||||
for i := 0; i < numOfVals; i++ {
|
||||
vp[i].BeforeEpochTransitionBalance, err = state.BalanceAtIndex(uint64(i))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get validator balance before epoch")
|
||||
}
|
||||
vp[i].BeforeEpochTransitionBalance = validatorBals[i]
|
||||
|
||||
if err := helpers.IncreaseBalance(state, uint64(i), attsRewards[i]+proposerRewards[i]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.DecreaseBalance(state, uint64(i), attsPenalties[i]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Compute the post balance of the validator after accounting for the
|
||||
// attester and proposer rewards and penalties.
|
||||
validatorBals[i] = helpers.IncreaseBalanceWithVal(validatorBals[i], attsRewards[i]+proposerRewards[i])
|
||||
validatorBals[i] = helpers.DecreaseBalanceWithVal(validatorBals[i], attsPenalties[i])
|
||||
|
||||
vp[i].AfterEpochTransitionBalance, err = state.BalanceAtIndex(uint64(i))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get validator balance after epoch")
|
||||
}
|
||||
vp[i].AfterEpochTransitionBalance = validatorBals[i]
|
||||
}
|
||||
|
||||
if err := state.SetBalances(validatorBals); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set validator balances")
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// This computes the rewards and penalties differences for individual validators based on the
|
||||
// AttestationsDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// voting records.
|
||||
func attestationDeltas(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, []uint64, error) {
|
||||
func AttestationsDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, []uint64, error) {
|
||||
numOfVals := state.NumValidators()
|
||||
rewards := make([]uint64, numOfVals)
|
||||
penalties := make([]uint64, numOfVals)
|
||||
prevEpoch := helpers.PrevEpoch(state)
|
||||
finalizedEpoch := state.FinalizedCheckpointEpoch()
|
||||
|
||||
for i, v := range vp {
|
||||
rewards[i], penalties[i] = attestationDelta(state, pBal, v)
|
||||
rewards[i], penalties[i] = attestationDelta(pBal, v, prevEpoch, finalizedEpoch)
|
||||
}
|
||||
return rewards, penalties, nil
|
||||
}
|
||||
|
||||
func attestationDelta(state *stateTrie.BeaconState, pBal *Balance, v *Validator) (uint64, uint64) {
|
||||
func attestationDelta(pBal *Balance, v *Validator, prevEpoch uint64, finalizedEpoch uint64) (uint64, uint64) {
|
||||
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
if !eligible || pBal.ActiveCurrentEpoch == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
e := helpers.PrevEpoch(state)
|
||||
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
||||
effectiveBalanceIncrement := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
vb := v.CurrentEpochEffectiveBalance
|
||||
br := vb * params.BeaconConfig().BaseRewardFactor / mathutil.IntegerSquareRoot(pBal.ActiveCurrentEpoch) / params.BeaconConfig().BaseRewardsPerEpoch
|
||||
br := vb * params.BeaconConfig().BaseRewardFactor / mathutil.IntegerSquareRoot(pBal.ActiveCurrentEpoch) / baseRewardsPerEpoch
|
||||
r, p := uint64(0), uint64(0)
|
||||
currentEpochBalance := pBal.ActiveCurrentEpoch / effectiveBalanceIncrement
|
||||
|
||||
// Process source reward / penalty
|
||||
if v.IsPrevEpochAttester && !v.IsSlashed {
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||
maxAtteserReward := br - proposerReward
|
||||
r += maxAtteserReward / v.InclusionDistance
|
||||
maxAttesterReward := br - proposerReward
|
||||
r += maxAttesterReward / v.InclusionDistance
|
||||
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
} else {
|
||||
rewardNumerator := br * (pBal.PrevEpochAttested / effectiveBalanceIncrement)
|
||||
r += rewardNumerator / currentEpochBalance
|
||||
|
||||
}
|
||||
} else {
|
||||
p += br
|
||||
}
|
||||
|
||||
// Process target reward / penalty
|
||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
} else {
|
||||
rewardNumerator := br * (pBal.PrevEpochTargetAttested / effectiveBalanceIncrement)
|
||||
r += rewardNumerator / currentEpochBalance
|
||||
}
|
||||
} else {
|
||||
p += br
|
||||
}
|
||||
|
||||
// Process head reward / penalty
|
||||
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
} else {
|
||||
rewardNumerator := br * (pBal.PrevEpochHeadAttested / effectiveBalanceIncrement)
|
||||
r += rewardNumerator / currentEpochBalance
|
||||
}
|
||||
} else {
|
||||
p += br
|
||||
}
|
||||
|
||||
// Process finality delay penalty
|
||||
finalizedEpoch := state.FinalizedCheckpointEpoch()
|
||||
finalityDelay := e - finalizedEpoch
|
||||
if finalityDelay > params.BeaconConfig().MinEpochsToInactivityPenalty {
|
||||
p += params.BeaconConfig().BaseRewardsPerEpoch * br
|
||||
if !v.IsPrevEpochTargetAttester {
|
||||
finalityDelay := finalityDelay(prevEpoch, finalizedEpoch)
|
||||
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// If validator is performing optimally, this cancels all rewards for a neutral balance.
|
||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||
p += baseRewardsPerEpoch*br - proposerReward
|
||||
// Apply an additional penalty to validators that did not vote on the correct target or has been slashed.
|
||||
// Equivalent to the following condition from the spec:
|
||||
// `index not in get_unslashed_attesting_indices(state, matching_target_attestations)`
|
||||
if !v.IsPrevEpochTargetAttester || v.IsSlashed {
|
||||
p += vb * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
}
|
||||
}
|
||||
return r, p
|
||||
}
|
||||
|
||||
// This computes the rewards and penalties differences for individual validators based on the
|
||||
// ProposersDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// proposer inclusion records.
|
||||
func proposerDeltaPrecompute(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, error) {
|
||||
func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, error) {
|
||||
numofVals := state.NumValidators()
|
||||
rewards := make([]uint64, numofVals)
|
||||
|
||||
totalBalance := pBal.ActiveCurrentEpoch
|
||||
balanceSqrt := mathutil.IntegerSquareRoot(totalBalance)
|
||||
// Balance square root cannot be 0, this prevents division by 0.
|
||||
if balanceSqrt == 0 {
|
||||
balanceSqrt = 1
|
||||
}
|
||||
|
||||
baseRewardFactor := params.BeaconConfig().BaseRewardFactor
|
||||
balanceSqrt := mathutil.IntegerSquareRoot(totalBalance)
|
||||
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
||||
proposerRewardQuotient := params.BeaconConfig().ProposerRewardQuotient
|
||||
for _, v := range vp {
|
||||
if v.IsPrevEpochAttester {
|
||||
// Only apply inclusion rewards to proposer only if the attested hasn't been slashed.
|
||||
if v.IsPrevEpochAttester && !v.IsSlashed {
|
||||
vBalance := v.CurrentEpochEffectiveBalance
|
||||
baseReward := vBalance * baseRewardFactor / balanceSqrt / baseRewardsPerEpoch
|
||||
proposerReward := baseReward / proposerRewardQuotient
|
||||
@@ -145,3 +172,21 @@ func proposerDeltaPrecompute(state *stateTrie.BeaconState, pBal *Balance, vp []*
|
||||
}
|
||||
return rewards, nil
|
||||
}
|
||||
|
||||
// isInInactivityLeak returns true if the state is experiencing inactivity leak.
|
||||
//
|
||||
// Spec code:
|
||||
// def is_in_inactivity_leak(state: BeaconState) -> bool:
|
||||
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
||||
func isInInactivityLeak(prevEpoch uint64, finalizedEpoch uint64) bool {
|
||||
return finalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty
|
||||
}
|
||||
|
||||
// finalityDelay returns the finality delay using the beacon state.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_finality_delay(state: BeaconState) -> uint64:
|
||||
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch
|
||||
func finalityDelay(prevEpoch uint64, finalizedEpoch uint64) uint64 {
|
||||
return prevEpoch - finalizedEpoch
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -90,6 +91,14 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
slashedAttestedIndices := []uint64{1413}
|
||||
for _, i := range slashedAttestedIndices {
|
||||
vs := state.Validators()
|
||||
vs[i].Slashed = true
|
||||
if state.SetValidators(vs) != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
vp, bp, err := New(context.Background(), state)
|
||||
if err != nil {
|
||||
@@ -100,7 +109,11 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rewards, penalties, err := attestationDeltas(state, bp, vp)
|
||||
// Add some variances to target and head balances.
|
||||
// See: https://github.com/prysmaticlabs/prysm/issues/5593
|
||||
bp.PrevEpochTargetAttested = bp.PrevEpochTargetAttested / 2
|
||||
bp.PrevEpochHeadAttested = bp.PrevEpochHeadAttested * 2 / 3
|
||||
rewards, penalties, err := AttestationsDelta(state, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -113,18 +126,21 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attestedIndices := []uint64{55, 1339, 1746, 1811, 1569, 1413}
|
||||
attestedIndices := []uint64{55, 1339, 1746, 1811, 1569}
|
||||
for _, i := range attestedIndices {
|
||||
base, err := epoch.BaseReward(state, i)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get base reward: %v", err)
|
||||
}
|
||||
|
||||
// Base rewards for getting source right
|
||||
wanted := 3 * (base * attestedBalance / totalBalance)
|
||||
wanted := attestedBalance*base/totalBalance +
|
||||
bp.PrevEpochTargetAttested*base/totalBalance +
|
||||
bp.PrevEpochHeadAttested*base/totalBalance
|
||||
// Base rewards for proposer and attesters working together getting attestation
|
||||
// on chain in the fatest manner
|
||||
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
||||
wanted += (base - proposerReward) * params.BeaconConfig().MinAttestationInclusionDelay
|
||||
wanted += (base-proposerReward)*params.BeaconConfig().MinAttestationInclusionDelay - 1
|
||||
if rewards[i] != wanted {
|
||||
t.Errorf("Wanted reward balance %d, got %d for validator with index %d", wanted, rewards[i], i)
|
||||
}
|
||||
@@ -134,6 +150,19 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
for _, i := range slashedAttestedIndices {
|
||||
base, err := epoch.BaseReward(state, i)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get base reward: %v", err)
|
||||
}
|
||||
if rewards[i] != 0 {
|
||||
t.Errorf("Wanted slashed indices reward balance 0, got %d", penalties[i])
|
||||
}
|
||||
if penalties[i] != 3*base {
|
||||
t.Errorf("Wanted slashed indices penalty balance %d, got %d", 3*base, penalties[i])
|
||||
}
|
||||
}
|
||||
|
||||
nonAttestedIndices := []uint64{434, 677, 872, 791}
|
||||
for _, i := range nonAttestedIndices {
|
||||
base, err := epoch.BaseReward(state, i)
|
||||
@@ -190,12 +219,79 @@ func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
|
||||
|
||||
pBal.ActiveCurrentEpoch = 0 // Could cause a divide by zero panic.
|
||||
|
||||
_, _, err = attestationDeltas(state, pBal, pVals)
|
||||
_, _, err = AttestationsDelta(state, pBal, pVals)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(2048)
|
||||
base := buildState(e+3, validatorCount)
|
||||
atts := make([]*pb.PendingAttestation, 3)
|
||||
for i := 0; i < len(atts); i++ {
|
||||
atts[i] = &pb.PendingAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := state.SetSlot(params.BeaconConfig().SlotsPerEpoch * 10); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slashedAttestedIndices := []uint64{14, 37, 68, 77, 139}
|
||||
for _, i := range slashedAttestedIndices {
|
||||
vs := state.Validators()
|
||||
vs[i].Slashed = true
|
||||
if state.SetValidators(vs) != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
vp, bp, err := New(context.Background(), state)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rewards, penalties, err := AttestationsDelta(state, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
finalityDelay := helpers.PrevEpoch(state) - state.FinalizedCheckpointEpoch()
|
||||
for _, i := range slashedAttestedIndices {
|
||||
base, err := epoch.BaseReward(state, i)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get base reward: %v", err)
|
||||
}
|
||||
penalty := 3 * base
|
||||
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
||||
penalty += params.BeaconConfig().BaseRewardsPerEpoch*base - proposerReward
|
||||
penalty += vp[i].CurrentEpochEffectiveBalance * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
if penalties[i] != penalty {
|
||||
t.Errorf("Wanted slashed indices penalty balance %d, got %d", penalty, penalties[i])
|
||||
}
|
||||
|
||||
if rewards[i] != 0 {
|
||||
t.Errorf("Wanted slashed indices reward balance 0, got %d", penalties[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
@@ -234,3 +330,133 @@ func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{},
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposerDeltaPrecompute_HappyCase(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(10)
|
||||
base := buildState(e, validatorCount)
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
proposerIndex := uint64(1)
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex},
|
||||
}
|
||||
r, err := ProposersDelta(state, b, v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
baseReward := v[0].CurrentEpochEffectiveBalance * params.BeaconConfig().BaseRewardFactor /
|
||||
mathutil.IntegerSquareRoot(b.ActiveCurrentEpoch) / params.BeaconConfig().BaseRewardsPerEpoch
|
||||
proposerReward := baseReward / params.BeaconConfig().ProposerRewardQuotient
|
||||
|
||||
if r[proposerIndex] != proposerReward {
|
||||
t.Errorf("Wanted proposer reward %d, got %d", proposerReward, r[proposerIndex])
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposerDeltaPrecompute_SlashedCase(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(10)
|
||||
base := buildState(e, validatorCount)
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
proposerIndex := uint64(1)
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex, IsSlashed: true},
|
||||
}
|
||||
r, err := ProposersDelta(state, b, v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if r[proposerIndex] != 0 {
|
||||
t.Errorf("Wanted proposer reward for slashed %d, got %d", 0, r[proposerIndex])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFinalityDelay(t *testing.T) {
|
||||
base := buildState(params.BeaconConfig().SlotsPerEpoch*10, 1)
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prevEpoch := uint64(0)
|
||||
finalizedEpoch := uint64(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(state)
|
||||
finalizedEpoch = state.FinalizedCheckpointEpoch()
|
||||
}
|
||||
setVal()
|
||||
d := finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w := helpers.PrevEpoch(state) - state.FinalizedCheckpointEpoch()
|
||||
if d != w {
|
||||
t.Error("Did not get wanted finality delay")
|
||||
}
|
||||
|
||||
if err := state.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 4}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setVal()
|
||||
d = finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w = helpers.PrevEpoch(state) - state.FinalizedCheckpointEpoch()
|
||||
if d != w {
|
||||
t.Error("Did not get wanted finality delay")
|
||||
}
|
||||
|
||||
if err := state.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 5}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setVal()
|
||||
d = finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w = helpers.PrevEpoch(state) - state.FinalizedCheckpointEpoch()
|
||||
if d != w {
|
||||
t.Error("Did not get wanted finality delay")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInInactivityLeak(t *testing.T) {
|
||||
base := buildState(params.BeaconConfig().SlotsPerEpoch*10, 1)
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prevEpoch := uint64(0)
|
||||
finalizedEpoch := uint64(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(state)
|
||||
finalizedEpoch = state.FinalizedCheckpointEpoch()
|
||||
}
|
||||
setVal()
|
||||
if !isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
t.Error("Wanted inactivity leak true")
|
||||
}
|
||||
|
||||
if err := state.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 4}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setVal()
|
||||
if !isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
t.Error("Wanted inactivity leak true")
|
||||
}
|
||||
|
||||
if err := state.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 5}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setVal()
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
t.Error("Wanted inactivity leak false")
|
||||
}
|
||||
}
|
||||
|
||||
76
beacon-chain/core/epoch/precompute/spectest/BUILD.bazel
Normal file
76
beacon-chain/core/epoch/precompute/spectest/BUILD.bazel
Normal file
@@ -0,0 +1,76 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
test_suite(
|
||||
name = "go_default_test",
|
||||
tags = ["spectest"],
|
||||
tests = [
|
||||
":go_mainnet_test",
|
||||
# Minimal tests must be run with --define ssz=minimal
|
||||
#":go_minimal_test",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_mainnet_test",
|
||||
size = "small",
|
||||
srcs = glob(
|
||||
["*_test.go"],
|
||||
exclude = ["*_minimal_test.go"],
|
||||
),
|
||||
data = [
|
||||
"@eth2_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
shard_count = 4,
|
||||
tags = [
|
||||
"spectest",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
# Requires --define ssz=minimal
|
||||
go_test(
|
||||
name = "go_minimal_test",
|
||||
size = "small",
|
||||
srcs = glob(
|
||||
["*_test.go"],
|
||||
exclude = ["*_mainnet_test.go"],
|
||||
),
|
||||
data = [
|
||||
"@eth2_spec_tests_minimal//:test_data",
|
||||
],
|
||||
tags = [
|
||||
"manual",
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRewardsPenaltiesMainnet(t *testing.T) {
|
||||
runPrecomputeRewardsAndPenaltiesTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRewardsPenaltiesMinimal(t *testing.T) {
|
||||
runPrecomputeRewardsAndPenaltiesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
type Delta struct {
|
||||
Rewards []uint64 `json:"rewards"`
|
||||
Penalties []uint64 `json:"penalties"`
|
||||
}
|
||||
|
||||
var deltaFiles = []string{"source_deltas.yaml", "target_deltas.yaml", "head_deltas.yaml", "inactivity_penalty_deltas.yaml", "inclusion_delay_deltas.yaml"}
|
||||
|
||||
func runPrecomputeRewardsAndPenaltiesTests(t *testing.T, config string) {
|
||||
if err := spectest.SetConfig(t, config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testPath := "rewards/core/pyspec_tests"
|
||||
testFolders, testsFolderPath := testutil.TestFolders(t, config, testPath)
|
||||
for _, folder := range testFolders {
|
||||
helpers.ClearCache()
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
folderPath := path.Join(testsFolderPath, folder.Name())
|
||||
runPrecomputeRewardsAndPenaltiesTest(t, folderPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func runPrecomputeRewardsAndPenaltiesTest(t *testing.T, testFolderPath string) {
|
||||
ctx := context.Background()
|
||||
preBeaconStateFile, err := testutil.BazelFileBytes(path.Join(testFolderPath, "pre.ssz"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
preBeaconStateBase := &pb.BeaconState{}
|
||||
if err := ssz.Unmarshal(preBeaconStateFile, preBeaconStateBase); err != nil {
|
||||
t.Fatalf("Failed to unmarshal: %v", err)
|
||||
}
|
||||
preBeaconState, err := beaconstate.InitializeFromProto(preBeaconStateBase)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vp, bp, err := precompute.New(ctx, preBeaconState)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vp, bp, err = precompute.ProcessAttestations(ctx, preBeaconState, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rewards, penalties, err := precompute.AttestationsDelta(preBeaconState, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pRewards, err := precompute.ProposersDelta(preBeaconState, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rewards) != len(penalties) && len(pRewards) != len(pRewards) {
|
||||
t.Fatal("Incorrect lengths")
|
||||
}
|
||||
for i, reward := range rewards {
|
||||
rewards[i] = reward + pRewards[i]
|
||||
}
|
||||
|
||||
totalSpecTestRewards := make([]uint64, len(rewards))
|
||||
totalSpecTestPenalties := make([]uint64, len(penalties))
|
||||
|
||||
for _, dFile := range deltaFiles {
|
||||
sourceFile, err := testutil.BazelFileBytes(path.Join(testFolderPath, dFile))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d := &Delta{}
|
||||
err = yaml.Unmarshal(sourceFile, &d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i, reward := range d.Rewards {
|
||||
totalSpecTestRewards[i] += reward
|
||||
}
|
||||
for i, penalty := range d.Penalties {
|
||||
totalSpecTestPenalties[i] += penalty
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(rewards, totalSpecTestRewards) {
|
||||
t.Error("Rewards don't match")
|
||||
t.Log(rewards)
|
||||
t.Log(totalSpecTestRewards)
|
||||
}
|
||||
if !reflect.DeepEqual(penalties, totalSpecTestPenalties) {
|
||||
t.Error("Penalties don't match")
|
||||
t.Log(penalties)
|
||||
t.Log(totalSpecTestPenalties)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRewardsAndPenaltiesMinimal(t *testing.T) {
|
||||
runRewardsAndPenaltiesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func runRewardsAndPenaltiesTests(t *testing.T, config string) {
|
||||
if err := spectest.SetConfig(t, config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testPath := "epoch_processing/rewards_and_penalties/pyspec_tests"
|
||||
testFolders, testsFolderPath := testutil.TestFolders(t, config, testPath)
|
||||
for _, folder := range testFolders {
|
||||
helpers.ClearCache()
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
folderPath := path.Join(testsFolderPath, folder.Name())
|
||||
testutil.RunEpochOperationTest(t, folderPath, processRewardsAndPenaltiesPrecomputeWrapper)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func processRewardsAndPenaltiesPrecomputeWrapper(t *testing.T, state *state.BeaconState) (*state.BeaconState, error) {
|
||||
ctx := context.Background()
|
||||
vp, bp, err := precompute.New(ctx, state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vp, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
state, err = precompute.ProcessRewardsAndPenaltiesPrecompute(state, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatalf("could not process reward: %v", err)
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
@@ -176,3 +176,40 @@ func AggregateSignature(attestations []*ethpb.Attestation) (*bls.Signature, erro
|
||||
func IsAggregated(attestation *ethpb.Attestation) bool {
|
||||
return attestation.AggregationBits.Count() > 1
|
||||
}
|
||||
|
||||
// ComputeSubnetForAttestation returns the subnet for which the provided attestation will be broadcasted to.
|
||||
// This differs from the spec definition by instead passing in the active validators indices in the attestation's
|
||||
// given epoch.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_subnet_for_attestation(state: BeaconState, attestation: Attestation) -> uint64:
|
||||
// """
|
||||
// Compute the correct subnet for an attestation for Phase 0.
|
||||
// Note, this mimics expected Phase 1 behavior where attestations will be mapped to their shard subnet.
|
||||
// """
|
||||
// slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH
|
||||
// committees_since_epoch_start = get_committee_count_at_slot(state, attestation.data.slot) * slots_since_epoch_start
|
||||
// return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT
|
||||
func ComputeSubnetForAttestation(activeValCount uint64, att *ethpb.Attestation) uint64 {
|
||||
return ComputeSubnetFromCommitteeAndSlot(activeValCount, att.Data.CommitteeIndex, att.Data.Slot)
|
||||
}
|
||||
|
||||
// ComputeSubnetFromCommitteeAndSlot is a flattened version of ComputeSubnetForAttestation where we only pass in
|
||||
// the relevant fields from the attestation as function arguments.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_subnet_for_attestation(state: BeaconState, attestation: Attestation) -> uint64:
|
||||
// """
|
||||
// Compute the correct subnet for an attestation for Phase 0.
|
||||
// Note, this mimics expected Phase 1 behavior where attestations will be mapped to their shard subnet.
|
||||
// """
|
||||
// slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH
|
||||
// committees_since_epoch_start = get_committee_count_at_slot(state, attestation.data.slot) * slots_since_epoch_start
|
||||
// return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT
|
||||
func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) uint64 {
|
||||
slotSinceStart := SlotsSinceEpochStarts(attSlot)
|
||||
comCount := SlotCommitteeCount(activeValCount)
|
||||
commsSinceStart := comCount * slotSinceStart
|
||||
computedSubnet := (commsSinceStart + comIdx) % params.BeaconNetworkConfig().AttestationSubnetCount
|
||||
return computedSubnet
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package helpers_test
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -348,3 +349,53 @@ func TestAggregateSignature_False(t *testing.T) {
|
||||
t.Error("Signature not suppose to verify")
|
||||
}
|
||||
}
|
||||
|
||||
func TestComputeSubnetForAttestation_ComputeForAttestation(t *testing.T) {
|
||||
// Create 10 committees
|
||||
committeeCount := uint64(10)
|
||||
validatorCount := committeeCount * params.BeaconConfig().TargetCommitteeSize
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
|
||||
for i := 0; i < len(validators); i++ {
|
||||
k := make([]byte, 48)
|
||||
copy(k, strconv.Itoa(i))
|
||||
validators[i] = ðpb.Validator{
|
||||
PublicKey: k,
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: 200,
|
||||
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
StateRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{
|
||||
AggregationBits: []byte{'A'},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 34,
|
||||
CommitteeIndex: 4,
|
||||
BeaconBlockRoot: []byte{'C'},
|
||||
Source: nil,
|
||||
Target: nil,
|
||||
},
|
||||
Signature: []byte{'B'},
|
||||
XXX_NoUnkeyedLiteral: struct{}{},
|
||||
XXX_unrecognized: nil,
|
||||
XXX_sizecache: 0,
|
||||
}
|
||||
valCount, err := helpers.ActiveValidatorCount(state, helpers.SlotToEpoch(att.Data.Slot))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sub := helpers.ComputeSubnetForAttestation(valCount, att)
|
||||
if sub != 6 {
|
||||
t.Errorf("Did not get correct subnet for attestation, wanted %d but got %d", 6, sub)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,21 @@ func IncreaseBalance(state *stateTrie.BeaconState, idx uint64, delta uint64) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return state.UpdateBalancesAtIndex(idx, balAtIdx+delta)
|
||||
return state.UpdateBalancesAtIndex(idx, IncreaseBalanceWithVal(balAtIdx, delta))
|
||||
}
|
||||
|
||||
// IncreaseBalanceWithVal increases validator with the given 'index' balance by 'delta' in Gwei.
|
||||
// This method is flattened version of the spec method, taking in the raw balance and returning
|
||||
// the post balance.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
|
||||
// """
|
||||
// Increase the validator balance at index ``index`` by ``delta``.
|
||||
// """
|
||||
// state.balances[index] += delta
|
||||
func IncreaseBalanceWithVal(currBalance uint64, delta uint64) uint64 {
|
||||
return currBalance + delta
|
||||
}
|
||||
|
||||
// DecreaseBalance decreases validator with the given 'index' balance by 'delta' in Gwei.
|
||||
@@ -85,8 +99,22 @@ func DecreaseBalance(state *stateTrie.BeaconState, idx uint64, delta uint64) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if delta > balAtIdx {
|
||||
return state.UpdateBalancesAtIndex(idx, 0)
|
||||
}
|
||||
return state.UpdateBalancesAtIndex(idx, balAtIdx-delta)
|
||||
return state.UpdateBalancesAtIndex(idx, DecreaseBalanceWithVal(balAtIdx, delta))
|
||||
}
|
||||
|
||||
// DecreaseBalanceWithVal decreases validator with the given 'index' balance by 'delta' in Gwei.
|
||||
// This method is flattened version of the spec method, taking in the raw balance and returning
|
||||
// the post balance.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
|
||||
// """
|
||||
// Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
|
||||
// """
|
||||
// state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
|
||||
func DecreaseBalanceWithVal(currBalance uint64, delta uint64) uint64 {
|
||||
if delta > currBalance {
|
||||
return 0
|
||||
}
|
||||
return currBalance - delta
|
||||
}
|
||||
|
||||
@@ -22,20 +22,19 @@ const DomainByteLength = 4
|
||||
// failed to verify.
|
||||
var ErrSigFailedToVerify = errors.New("signature did not verify")
|
||||
|
||||
// ComputeSigningRoot computes the root of the object by calculating the root of the object domain tree.
|
||||
// ComputeSigningRoot computes the root of the object by calculating the hash tree root of the signing data with the given domain.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
|
||||
// """
|
||||
// Return the signing root of an object by calculating the root of the object-domain tree.
|
||||
// Return the signing root for the corresponding signing data.
|
||||
// """
|
||||
// domain_wrapped_object = SigningRoot(
|
||||
// return hash_tree_root(SigningData(
|
||||
// object_root=hash_tree_root(ssz_object),
|
||||
// domain=domain,
|
||||
// )
|
||||
// return hash_tree_root(domain_wrapped_object)
|
||||
// ))
|
||||
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
||||
return signingRoot(func() ([32]byte, error) {
|
||||
return signingData(func() ([32]byte, error) {
|
||||
switch object.(type) {
|
||||
case *ethpb.BeaconBlock:
|
||||
return stateutil.BlockRoot(object.(*ethpb.BeaconBlock))
|
||||
@@ -48,14 +47,14 @@ func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
||||
}, domain)
|
||||
}
|
||||
|
||||
// Computes the signing root by utilising the provided root function and then
|
||||
// returning the signing root of the container object.
|
||||
func signingRoot(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, error) {
|
||||
// Computes the signing data by utilising the provided root function and then
|
||||
// returning the signing data of the container object.
|
||||
func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, error) {
|
||||
objRoot, err := rootFunc()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
container := &p2ppb.SigningRoot{
|
||||
container := &p2ppb.SigningData{
|
||||
ObjectRoot: objRoot[:],
|
||||
Domain: domain,
|
||||
}
|
||||
@@ -92,7 +91,7 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub []byte, signature []byte
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
root, err := signingRoot(func() ([32]byte, error) {
|
||||
root, err := signingData(func() ([32]byte, error) {
|
||||
// utilize custom block hashing function
|
||||
return stateutil.BlockRoot(blk)
|
||||
}, domain)
|
||||
@@ -115,7 +114,7 @@ func VerifyBlockHeaderSigningRoot(blkHdr *ethpb.BeaconBlockHeader, pub []byte, s
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
root, err := signingRoot(func() ([32]byte, error) {
|
||||
root, err := signingData(func() ([32]byte, error) {
|
||||
return stateutil.BlockHeaderRoot(blkHdr)
|
||||
}, domain)
|
||||
if err != nil {
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestSigningRoot_Compatibility(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newRoot, err := signingRoot(func() ([32]byte, error) {
|
||||
newRoot, err := signingData(func() ([32]byte, error) {
|
||||
return stateutil.BlockRoot(blk)
|
||||
}, params.BeaconConfig().DomainBeaconProposer[:])
|
||||
if err != nil {
|
||||
|
||||
@@ -54,7 +54,10 @@ go_test(
|
||||
"transition_fuzz_test.go",
|
||||
"transition_test.go",
|
||||
],
|
||||
data = ["//shared/benchutil/benchmark_files:benchmark_data"],
|
||||
data = [
|
||||
"//beacon-chain/core/state/regression_files:regression_data",
|
||||
"//shared/benchutil/benchmark_files:benchmark_data",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
shard_count = 3,
|
||||
deps = [
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
var runAmount = 25
|
||||
|
||||
func TestBenchmarkExecuteStateTransition(t *testing.T) {
|
||||
func TestExecuteStateTransition_FullBlock(t *testing.T) {
|
||||
benchutil.SetBenchmarkConfig()
|
||||
beaconState, err := benchutil.PreGenState1Epoch()
|
||||
if err != nil {
|
||||
|
||||
9
beacon-chain/core/state/regression_files/BUILD.bazel
Normal file
9
beacon-chain/core/state/regression_files/BUILD.bazel
Normal file
@@ -0,0 +1,9 @@
|
||||
filegroup(
|
||||
name = "regression_data",
|
||||
srcs = glob([
|
||||
"*.ssz",
|
||||
]),
|
||||
visibility = [
|
||||
"//beacon-chain/core/state:__pkg__",
|
||||
],
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -190,9 +190,9 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState *stateTrie.BeaconS
|
||||
Eth1DepositIndex: preState.Eth1DepositIndex(),
|
||||
}
|
||||
|
||||
bodyRoot, err := ssz.HashTreeRoot(ðpb.BeaconBlockBody{})
|
||||
bodyRoot, err := stateutil.BlockBodyRoot(ðpb.BeaconBlockBody{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not hash tree root %v", bodyRoot)
|
||||
return nil, errors.Wrap(err, "could not hash tree root empty block body")
|
||||
}
|
||||
|
||||
state.LatestBlockHeader = ðpb.BeaconBlockHeader{
|
||||
|
||||
@@ -92,9 +92,18 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nextSlotState := beaconState.Copy()
|
||||
if err := nextSlotState.SetSlot(beaconState.Slot() + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(nextSlotState)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ProposerIndex: 74,
|
||||
ProposerIndex: proposerIdx,
|
||||
Slot: beaconState.Slot() + 1,
|
||||
ParentRoot: parentRoot[:],
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
@@ -371,7 +380,7 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
|
||||
proposerSlashIdx := uint64(3)
|
||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
||||
err = beaconState.SetSlot((params.BeaconConfig().PersistentCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
err = beaconState.SetSlot((params.BeaconConfig().ShardCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -754,7 +763,7 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
ctr := &pb.SigningRoot{
|
||||
ctr := &pb.SigningData{
|
||||
ObjectRoot: buf,
|
||||
Domain: domain,
|
||||
}
|
||||
@@ -902,9 +911,17 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nextSlotState := s.Copy()
|
||||
if err := nextSlotState.SetSlot(s.Slot() + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(nextSlotState)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
blk := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ProposerIndex: 156,
|
||||
ProposerIndex: proposerIdx,
|
||||
Slot: s.Slot() + 1,
|
||||
ParentRoot: parentRoot[:],
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
|
||||
@@ -2,7 +2,6 @@ package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
@@ -10,7 +9,9 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
||||
@@ -22,7 +23,7 @@ func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
||||
prevBlock := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: slot - 1,
|
||||
ParentRoot: []byte{1, 2, 3},
|
||||
ParentRoot: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||
},
|
||||
}
|
||||
if err := db.SaveBlock(ctx, prevBlock); err != nil {
|
||||
@@ -31,7 +32,7 @@ func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: slot,
|
||||
ParentRoot: []byte{1, 2, 3},
|
||||
ParentRoot: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||
},
|
||||
}
|
||||
// Even with a full cache, saving new blocks should not cause
|
||||
@@ -59,7 +60,7 @@ func TestStore_BlocksCRUD(t *testing.T) {
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 20,
|
||||
ParentRoot: []byte{1, 2, 3},
|
||||
ParentRoot: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||
},
|
||||
}
|
||||
blockRoot, err := stateutil.BlockRoot(block.Block)
|
||||
@@ -97,18 +98,15 @@ func TestStore_BlocksCRUD(t *testing.T) {
|
||||
func TestStore_BlocksBatchDelete(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
numBlocks := 1000
|
||||
numBlocks := 10
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
||||
blockRoots := make([][32]byte, 0)
|
||||
oddBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
||||
for i := 0; i < len(totalBlocks); i++ {
|
||||
totalBlocks[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: uint64(i),
|
||||
ParentRoot: []byte("parent"),
|
||||
},
|
||||
}
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
if i%2 == 0 {
|
||||
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
||||
if err != nil {
|
||||
@@ -122,7 +120,7 @@ func TestStore_BlocksBatchDelete(t *testing.T) {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot([]byte("parent")))
|
||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -134,27 +132,25 @@ func TestStore_BlocksBatchDelete(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// When we retrieve the data, only the odd indexed blocks should remain.
|
||||
retrieved, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot([]byte("parent")))
|
||||
retrieved, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sort.Slice(retrieved, func(i, j int) bool {
|
||||
return retrieved[i].Block.Slot < retrieved[j].Block.Slot
|
||||
})
|
||||
if !reflect.DeepEqual(retrieved, oddBlocks) {
|
||||
t.Errorf("Wanted %v, received %v", oddBlocks, retrieved)
|
||||
for i, block := range retrieved {
|
||||
if !proto.Equal(block, oddBlocks[i]) {
|
||||
t.Errorf("Wanted %v, received %v", oddBlocks[i], block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_GenesisBlock(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
genesisBlock := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 0,
|
||||
ParentRoot: []byte{1, 2, 3},
|
||||
},
|
||||
}
|
||||
genesisBlock := testutil.NewBeaconBlock()
|
||||
genesisBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
|
||||
blockRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -177,12 +173,9 @@ func TestStore_GenesisBlock(t *testing.T) {
|
||||
func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 20,
|
||||
ParentRoot: []byte{1, 2, 3},
|
||||
},
|
||||
}
|
||||
block := testutil.NewBeaconBlock()
|
||||
block.Block.Slot = 20
|
||||
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
|
||||
blockRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -218,38 +211,22 @@ func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
||||
|
||||
func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
blocks := []*ethpb.SignedBeaconBlock{
|
||||
{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 4,
|
||||
ParentRoot: []byte("parent"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 5,
|
||||
ParentRoot: []byte("parent2"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 6,
|
||||
ParentRoot: []byte("parent2"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 7,
|
||||
ParentRoot: []byte("parent3"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 8,
|
||||
ParentRoot: []byte("parent4"),
|
||||
},
|
||||
},
|
||||
}
|
||||
b4 := testutil.NewBeaconBlock()
|
||||
b4.Block.Slot = 4
|
||||
b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
b5 := testutil.NewBeaconBlock()
|
||||
b5.Block.Slot = 5
|
||||
b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
|
||||
b6 := testutil.NewBeaconBlock()
|
||||
b6.Block.Slot = 6
|
||||
b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
|
||||
b7 := testutil.NewBeaconBlock()
|
||||
b7.Block.Slot = 7
|
||||
b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32)
|
||||
b8 := testutil.NewBeaconBlock()
|
||||
b8.Block.Slot = 8
|
||||
b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32)
|
||||
blocks := []*ethpb.SignedBeaconBlock{b4, b5, b6, b7, b8}
|
||||
ctx := context.Background()
|
||||
if err := db.SaveBlocks(ctx, blocks); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -260,12 +237,12 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
||||
expectedNumBlocks int
|
||||
}{
|
||||
{
|
||||
filter: filters.NewFilter().SetParentRoot([]byte("parent2")),
|
||||
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)),
|
||||
expectedNumBlocks: 2,
|
||||
},
|
||||
{
|
||||
// No block meets the criteria below.
|
||||
filter: filters.NewFilter().SetParentRoot([]byte{3, 4, 5}),
|
||||
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)),
|
||||
expectedNumBlocks: 0,
|
||||
},
|
||||
{
|
||||
@@ -304,7 +281,7 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
||||
{
|
||||
// Composite filter criteria.
|
||||
filter: filters.NewFilter().
|
||||
SetParentRoot([]byte("parent2")).
|
||||
SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)).
|
||||
SetStartSlot(6).
|
||||
SetEndSlot(8),
|
||||
expectedNumBlocks: 1,
|
||||
@@ -323,17 +300,15 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
||||
|
||||
func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
for i := 0; i < 500; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
}
|
||||
ctx := context.Background()
|
||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
|
||||
@@ -349,17 +324,15 @@ func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) {
|
||||
func TestStore_Blocks_Retrieve_Epoch(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
slots := params.BeaconConfig().SlotsPerEpoch * 7
|
||||
b := make([]*ethpb.SignedBeaconBlock, slots)
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, slots)
|
||||
for i := uint64(0); i < slots; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
Slot: i,
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
}
|
||||
ctx := context.Background()
|
||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
|
||||
@@ -382,18 +355,16 @@ func TestStore_Blocks_Retrieve_Epoch(t *testing.T) {
|
||||
|
||||
func TestStore_Blocks_Retrieve_SlotRangeWithStep(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
for i := 0; i < 500; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
}
|
||||
const step = 2
|
||||
ctx := context.Background()
|
||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step))
|
||||
@@ -415,7 +386,8 @@ func TestStore_SaveBlock_CanGetHighest(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
block := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
block := testutil.NewBeaconBlock()
|
||||
block.Block.Slot = 1
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -427,7 +399,7 @@ func TestStore_SaveBlock_CanGetHighest(t *testing.T) {
|
||||
t.Errorf("Wanted %v, received %v", block, highestSavedBlock)
|
||||
}
|
||||
|
||||
block = ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 999}}
|
||||
block.Block.Slot = 999
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -439,7 +411,7 @@ func TestStore_SaveBlock_CanGetHighest(t *testing.T) {
|
||||
t.Errorf("Wanted %v, received %v", block, highestSavedBlock)
|
||||
}
|
||||
|
||||
block = ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 300000000}} // 100 years.
|
||||
block.Block.Slot = 300000000
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -456,15 +428,18 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
block1 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
block1 := testutil.NewBeaconBlock()
|
||||
block1.Block.Slot = 1
|
||||
if err := db.SaveBlock(ctx, block1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block2 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 10}}
|
||||
block2 := testutil.NewBeaconBlock()
|
||||
block2.Block.Slot = 10
|
||||
if err := db.SaveBlock(ctx, block2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block3 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 100}}
|
||||
block3 := testutil.NewBeaconBlock()
|
||||
block3.Block.Slot = 100
|
||||
if err := db.SaveBlock(ctx, block3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -512,7 +487,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesisBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{}}
|
||||
genesisBlock := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -523,7 +498,8 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
if err := db.SaveBlock(ctx, genesisBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block1 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
block1 := testutil.NewBeaconBlock()
|
||||
block1.Block.Slot = 1
|
||||
if err := db.SaveBlock(ctx, block1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -555,25 +531,23 @@ func TestStore_SaveBlocks_CanGetHighest(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||
for i := 0; i < 500; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
}
|
||||
|
||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
highestSavedBlock, err := db.HighestSlotBlocks(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !proto.Equal(b[len(b)-1], highestSavedBlock[0]) {
|
||||
t.Errorf("Wanted %v, received %v", b[len(b)-1], highestSavedBlock)
|
||||
if !proto.Equal(totalBlocks[len(totalBlocks)-1], highestSavedBlock[0]) {
|
||||
t.Errorf("Wanted %v, received %v", totalBlocks[len(totalBlocks)-1], highestSavedBlock)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,7 +559,7 @@ func TestStore_SaveBlocks_HasCachedBlocks(t *testing.T) {
|
||||
for i := 0; i < 500; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
ParentRoot: bytesutil.PadTo([]byte("parent"), 32),
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
@@ -613,7 +587,8 @@ func TestStore_DeleteBlock_CanGetHighest(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
b50 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 50}}
|
||||
b50 := testutil.NewBeaconBlock()
|
||||
b50.Block.Slot = 50
|
||||
if err := db.SaveBlock(ctx, b50); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -625,7 +600,8 @@ func TestStore_DeleteBlock_CanGetHighest(t *testing.T) {
|
||||
t.Errorf("Wanted %v, received %v", b50, highestSavedBlock)
|
||||
}
|
||||
|
||||
b51 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 51}}
|
||||
b51 := testutil.NewBeaconBlock()
|
||||
b51.Block.Slot = 51
|
||||
r51, err := stateutil.BlockRoot(b51.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -659,22 +635,20 @@ func TestStore_DeleteBlocks_CanGetHighest(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
var err error
|
||||
b := make([]*ethpb.SignedBeaconBlock, 100)
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, 100)
|
||||
r := make([][32]byte, 100)
|
||||
for i := 0; i < 100; i++ {
|
||||
b[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: []byte("parent"),
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
r[i], err = stateutil.BlockRoot(b[i].Block)
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
r[i], err = stateutil.BlockRoot(totalBlocks[i].Block)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.DeleteBlocks(ctx, [][32]byte{r[99], r[98], r[97]}); err != nil {
|
||||
@@ -684,7 +658,7 @@ func TestStore_DeleteBlocks_CanGetHighest(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !proto.Equal(b[96], highestSavedBlock[0]) {
|
||||
t.Errorf("Wanted %v, received %v", b[len(b)-1], highestSavedBlock)
|
||||
if !proto.Equal(totalBlocks[96], highestSavedBlock[0]) {
|
||||
t.Errorf("Wanted %v, received %v", totalBlocks[len(totalBlocks)-1], highestSavedBlock)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ func isSSZStorageFormat(obj interface{}) bool {
|
||||
switch obj.(type) {
|
||||
case *pb.BeaconState:
|
||||
return true
|
||||
case *ethpb.SignedBeaconBlock:
|
||||
return true
|
||||
case *ethpb.SignedAggregateAttestationAndProof:
|
||||
return true
|
||||
case *ethpb.BeaconBlock:
|
||||
return true
|
||||
case *ethpb.Attestation:
|
||||
|
||||
@@ -132,12 +132,9 @@ func TestStore_StatesBatchDelete(t *testing.T) {
|
||||
blockRoots := make([][32]byte, 0)
|
||||
evenBlockRoots := make([][32]byte, 0)
|
||||
for i := 0; i < len(totalBlocks); i++ {
|
||||
totalBlocks[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: uint64(i),
|
||||
ParentRoot: []byte("parent"),
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
totalBlocks[i] = b
|
||||
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -17,13 +17,13 @@ var (
|
||||
DepositContractFlag = &cli.StringFlag{
|
||||
Name: "deposit-contract",
|
||||
Usage: "Deposit contract address. Beacon chain node will listen logs coming from the deposit contract to determine when validator is eligible to participate.",
|
||||
Value: "0x5cA1e00004366Ac85f492887AAab12d0e6418876",
|
||||
Value: "0x0F0F0fc0530007361933EaB5DB97d09aCDD6C1c8",
|
||||
}
|
||||
// RPCHost defines the host on which the RPC server should listen.
|
||||
RPCHost = &cli.StringFlag{
|
||||
Name: "rpc-host",
|
||||
Usage: "Host on which the RPC server should listen",
|
||||
Value: "0.0.0.0",
|
||||
Value: "127.0.0.1",
|
||||
}
|
||||
// RPCPort defines a beacon node RPC port to open.
|
||||
RPCPort = &cli.IntFlag{
|
||||
@@ -82,7 +82,7 @@ var (
|
||||
ContractDeploymentBlock = &cli.IntFlag{
|
||||
Name: "contract-deployment-block",
|
||||
Usage: "The eth1 block in which the deposit contract was deployed.",
|
||||
Value: 2523557,
|
||||
Value: 2844925,
|
||||
}
|
||||
// SetGCPercent is the percentage of current live allocations at which the garbage collector is to run.
|
||||
SetGCPercent = &cli.IntFlag{
|
||||
|
||||
@@ -40,7 +40,7 @@ func main() {
|
||||
gw := gateway.New(
|
||||
context.Background(),
|
||||
*beaconRPC,
|
||||
fmt.Sprintf("0.0.0.0:%d", *port),
|
||||
fmt.Sprintf("127.0.0.1:%d", *port),
|
||||
mux,
|
||||
strings.Split(*allowedOrigins, ","),
|
||||
*enableDebugRPCEndpoints,
|
||||
|
||||
@@ -599,7 +599,7 @@ func (b *BeaconNode) registerGRPCGateway() error {
|
||||
}
|
||||
gatewayPort := b.cliCtx.Int(flags.GRPCGatewayPort.Name)
|
||||
selfAddress := fmt.Sprintf("127.0.0.1:%d", b.cliCtx.Int(flags.RPCPort.Name))
|
||||
gatewayAddress := fmt.Sprintf("0.0.0.0:%d", gatewayPort)
|
||||
gatewayAddress := fmt.Sprintf("127.0.0.1:%d", gatewayPort)
|
||||
allowedOrigins := strings.Split(b.cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",")
|
||||
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
||||
return b.services.RegisterService(
|
||||
|
||||
@@ -528,9 +528,6 @@ func TestPool_PendingAttesterSlashings(t *testing.T) {
|
||||
pending []*PendingAttesterSlashing
|
||||
}
|
||||
params.SetupTestConfigCleanup(t)
|
||||
conf := params.BeaconConfig()
|
||||
conf.MaxAttesterSlashings = 1
|
||||
params.OverrideBeaconConfig(conf)
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 64)
|
||||
pendingSlashings := make([]*PendingAttesterSlashing, 20)
|
||||
slashings := make([]*ethpb.AttesterSlashing, 20)
|
||||
@@ -562,14 +559,14 @@ func TestPool_PendingAttesterSlashings(t *testing.T) {
|
||||
fields: fields{
|
||||
pending: pendingSlashings,
|
||||
},
|
||||
want: slashings[0:1],
|
||||
want: slashings[0:2],
|
||||
},
|
||||
{
|
||||
name: "Multiple indices",
|
||||
fields: fields{
|
||||
pending: pendingSlashings[3:6],
|
||||
},
|
||||
want: slashings[3:4],
|
||||
want: slashings[3:5],
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -18,33 +18,49 @@ import (
|
||||
// GossipTypeMapping.
|
||||
var ErrMessageNotMapped = errors.New("message type is not mapped to a PubSub topic")
|
||||
|
||||
const attestationSubnetTopicFormat = "/eth2/%x/beacon_attestation_%d"
|
||||
|
||||
// Broadcast a message to the p2p network.
|
||||
func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
|
||||
ctx, span := trace.StartSpan(ctx, "p2p.Broadcast")
|
||||
defer span.End()
|
||||
forkDigest, err := s.forkDigest()
|
||||
if err != nil {
|
||||
err := errors.Wrap(err, "could not retrieve fork digest")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
|
||||
var topic string
|
||||
switch msg.(type) {
|
||||
case *eth.Attestation:
|
||||
topic = attestationToTopic(msg.(*eth.Attestation), forkDigest)
|
||||
default:
|
||||
var ok bool
|
||||
topic, ok = GossipTypeMapping[reflect.TypeOf(msg)]
|
||||
if !ok {
|
||||
traceutil.AnnotateError(span, ErrMessageNotMapped)
|
||||
return ErrMessageNotMapped
|
||||
}
|
||||
topic = fmt.Sprintf(topic, forkDigest)
|
||||
topic, ok := GossipTypeMapping[reflect.TypeOf(msg)]
|
||||
if !ok {
|
||||
traceutil.AnnotateError(span, ErrMessageNotMapped)
|
||||
return ErrMessageNotMapped
|
||||
}
|
||||
return s.broadcastObject(ctx, msg, fmt.Sprintf(topic, forkDigest))
|
||||
}
|
||||
|
||||
// BroadcastAttestation broadcasts an attestation to the p2p network.
|
||||
func (s *Service) BroadcastAttestation(ctx context.Context, subnet uint64, att *eth.Attestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "p2p.BroadcastAttestation")
|
||||
defer span.End()
|
||||
forkDigest, err := s.forkDigest()
|
||||
if err != nil {
|
||||
err := errors.Wrap(err, "could not retrieve fork digest")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
return s.broadcastObject(ctx, att, attestationToTopic(subnet, forkDigest))
|
||||
}
|
||||
|
||||
// method to broadcast messages to other peers in our gossip mesh.
|
||||
func (s *Service) broadcastObject(ctx context.Context, obj interface{}, topic string) error {
|
||||
_, span := trace.StartSpan(ctx, "p2p.broadcastObject")
|
||||
defer span.End()
|
||||
|
||||
span.AddAttributes(trace.StringAttribute("topic", topic))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := s.Encoding().EncodeGossip(buf, msg); err != nil {
|
||||
if _, err := s.Encoding().EncodeGossip(buf, obj); err != nil {
|
||||
err := errors.Wrap(err, "could not encode message")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
@@ -64,11 +80,6 @@ func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const attestationSubnetTopicFormat = "/eth2/%x/committee_index%d_beacon_attestation"
|
||||
|
||||
func attestationToTopic(att *eth.Attestation, forkDigest [4]byte) string {
|
||||
if att == nil || att.Data == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(attestationSubnetTopicFormat, forkDigest, att.Data.CommitteeIndex)
|
||||
func attestationToTopic(subnet uint64, forkDigest [4]byte) string {
|
||||
return fmt.Sprintf(attestationSubnetTopicFormat, forkDigest, subnet)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
testpb "github.com/prysmaticlabs/prysm/proto/testing"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -109,36 +110,33 @@ func TestService_Attestation_Subnet(t *testing.T) {
|
||||
att: ð.Attestation{
|
||||
Data: ð.AttestationData{
|
||||
CommitteeIndex: 0,
|
||||
Slot: 2,
|
||||
},
|
||||
},
|
||||
topic: "/eth2/00000000/committee_index0_beacon_attestation",
|
||||
topic: "/eth2/00000000/beacon_attestation_2",
|
||||
},
|
||||
{
|
||||
att: ð.Attestation{
|
||||
Data: ð.AttestationData{
|
||||
CommitteeIndex: 11,
|
||||
Slot: 10,
|
||||
},
|
||||
},
|
||||
topic: "/eth2/00000000/committee_index11_beacon_attestation",
|
||||
topic: "/eth2/00000000/beacon_attestation_21",
|
||||
},
|
||||
{
|
||||
att: ð.Attestation{
|
||||
Data: ð.AttestationData{
|
||||
CommitteeIndex: 55,
|
||||
Slot: 529,
|
||||
},
|
||||
},
|
||||
topic: "/eth2/00000000/committee_index55_beacon_attestation",
|
||||
},
|
||||
{
|
||||
att: ð.Attestation{},
|
||||
topic: "",
|
||||
},
|
||||
{
|
||||
topic: "",
|
||||
topic: "/eth2/00000000/beacon_attestation_8",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if res := attestationToTopic(tt.att, [4]byte{} /* fork digest */); res != tt.topic {
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(100, tt.att.Data.CommitteeIndex, tt.att.Data.Slot)
|
||||
if res := attestationToTopic(subnet, [4]byte{} /* fork digest */); res != tt.topic {
|
||||
t.Errorf("Wrong topic, got %s wanted %s", res, tt.topic)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
// GossipTopicMappings represent the protocol ID to protobuf message type map for easy
|
||||
// lookup.
|
||||
var GossipTopicMappings = map[string]proto.Message{
|
||||
"/eth2/%x/beacon_block": &pb.SignedBeaconBlock{},
|
||||
"/eth2/%x/committee_index%d_beacon_attestation": &pb.Attestation{},
|
||||
"/eth2/%x/voluntary_exit": &pb.SignedVoluntaryExit{},
|
||||
"/eth2/%x/proposer_slashing": &pb.ProposerSlashing{},
|
||||
"/eth2/%x/attester_slashing": &pb.AttesterSlashing{},
|
||||
"/eth2/%x/beacon_aggregate_and_proof": &pb.SignedAggregateAttestationAndProof{},
|
||||
"/eth2/%x/beacon_block": &pb.SignedBeaconBlock{},
|
||||
"/eth2/%x/beacon_attestation_%d": &pb.Attestation{},
|
||||
"/eth2/%x/voluntary_exit": &pb.SignedVoluntaryExit{},
|
||||
"/eth2/%x/proposer_slashing": &pb.ProposerSlashing{},
|
||||
"/eth2/%x/attester_slashing": &pb.AttesterSlashing{},
|
||||
"/eth2/%x/beacon_aggregate_and_proof": &pb.SignedAggregateAttestationAndProof{},
|
||||
}
|
||||
|
||||
// GossipTypeMapping is the inverse of GossipTopicMappings so that an arbitrary protobuf message
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -28,6 +29,7 @@ type P2P interface {
|
||||
// Broadcaster broadcasts messages to peers over the p2p pubsub protocol.
|
||||
type Broadcaster interface {
|
||||
Broadcast(context.Context, proto.Message) error
|
||||
BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error
|
||||
}
|
||||
|
||||
// SetStreamHandler configures p2p to handle streams of a certain topic ID.
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/runutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||||
)
|
||||
@@ -136,7 +137,7 @@ func NewService(cfg *Config) (*Service, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(cfg.KademliaBootStrapAddr) != 0 && !cfg.NoDiscovery {
|
||||
if len(cfg.KademliaBootStrapAddr) != 0 && !cfg.NoDiscovery && featureconfig.Get().EnableKadDHT {
|
||||
dopts := []dhtopts.Option{
|
||||
dhtopts.Datastore(dsync.MutexWrap(ds.NewMapDatastore())),
|
||||
dhtopts.Protocols(
|
||||
@@ -235,7 +236,7 @@ func (s *Service) Start() {
|
||||
go s.listenForNewNodes()
|
||||
}
|
||||
|
||||
if len(s.cfg.KademliaBootStrapAddr) != 0 && !s.cfg.NoDiscovery {
|
||||
if len(s.cfg.KademliaBootStrapAddr) != 0 && !s.cfg.NoDiscovery && featureconfig.Get().EnableKadDHT {
|
||||
for _, addr := range s.cfg.KademliaBootStrapAddr {
|
||||
peersToWatch = append(peersToWatch, addr)
|
||||
err := startDHTDiscovery(s.host, addr)
|
||||
@@ -390,7 +391,7 @@ func (s *Service) RefreshENR() {
|
||||
return
|
||||
}
|
||||
bitV := bitfield.NewBitvector64()
|
||||
committees := cache.CommitteeIDs.GetAllCommittees()
|
||||
committees := cache.SubnetIDs.GetAllSubnets()
|
||||
for _, idx := range committees {
|
||||
bitV.SetBitAt(idx, true)
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func TestStartDiscV5_DiscoverPeersWithSubnets(t *testing.T) {
|
||||
dv5Listener: listeners[0],
|
||||
metaData: &pb.MetaData{},
|
||||
}
|
||||
cache.CommitteeIDs.AddAttesterCommiteeID(0, 10)
|
||||
cache.SubnetIDs.AddAttesterSubnetID(0, 10)
|
||||
testService.RefreshENR()
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ go_library(
|
||||
"@com_github_libp2p_go_libp2p_pubsub//:go_default_library",
|
||||
"@com_github_libp2p_go_libp2p_swarm//testing:go_default_library",
|
||||
"@com_github_multiformats_go_multiaddr//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
)
|
||||
|
||||
// MockBroadcaster implements p2p.Broadcaster for testing.
|
||||
@@ -16,3 +17,9 @@ func (m *MockBroadcaster) Broadcast(context.Context, proto.Message) error {
|
||||
m.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastAttestation records a broadcast occurred.
|
||||
func (m *MockBroadcaster) BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error {
|
||||
m.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -133,6 +134,12 @@ func (p *TestP2P) Broadcast(ctx context.Context, msg proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastAttestation broadcasts an attestation.
|
||||
func (p *TestP2P) BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error {
|
||||
p.BroadcastCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetStreamHandler for RPC.
|
||||
func (p *TestP2P) SetStreamHandler(topic string, handler network.StreamHandler) {
|
||||
p.Host.SetStreamHandler(protocol.ID(topic), handler)
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -246,12 +245,9 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
||||
}
|
||||
|
||||
func (s *Service) createGenesisTime(timeStamp uint64) uint64 {
|
||||
if featureconfig.Get().CustomGenesisDelay == 0 {
|
||||
return timeStamp
|
||||
}
|
||||
timeStampRdDown := timeStamp - timeStamp%featureconfig.Get().CustomGenesisDelay
|
||||
// genesisTime will be set to the first second of the day, two days after it was triggered.
|
||||
return timeStampRdDown + 2*featureconfig.Get().CustomGenesisDelay
|
||||
// adds in the genesis delay to the eth1 block time
|
||||
// on which it was triggered.
|
||||
return timeStamp + featureconfig.Get().CustomGenesisDelay
|
||||
}
|
||||
|
||||
// processPastLogs processes all the past logs from the deposit contract and
|
||||
@@ -284,15 +280,19 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for currentBlockNum < s.LatestBlockHeight().Uint64() {
|
||||
latestFollowHeight, err := s.followBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for currentBlockNum < latestFollowHeight {
|
||||
// stop requesting, if we have all the logs
|
||||
if logCount == uint64(s.lastReceivedMerkleIndex+1) {
|
||||
break
|
||||
}
|
||||
start := currentBlockNum
|
||||
end := currentBlockNum + eth1HeaderReqLimit
|
||||
if end > s.LatestBlockHeight().Uint64() {
|
||||
end = s.LatestBlockHeight().Uint64()
|
||||
if end > latestFollowHeight {
|
||||
end = latestFollowHeight
|
||||
}
|
||||
query := ethereum.FilterQuery{
|
||||
Addresses: []common.Address{
|
||||
@@ -303,9 +303,9 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
}
|
||||
remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1)
|
||||
// only change the end block if the remaining logs are below the required log limit.
|
||||
if remainingLogs < depositlogRequestLimit && end >= s.LatestBlockHeight().Uint64() {
|
||||
query.ToBlock = s.LatestBlockHeight()
|
||||
end = s.LatestBlockHeight().Uint64()
|
||||
if remainingLogs < depositlogRequestLimit && end >= latestFollowHeight {
|
||||
query.ToBlock = big.NewInt(int64(latestFollowHeight))
|
||||
end = latestFollowHeight
|
||||
}
|
||||
logs, err := s.httpLogger.FilterLogs(ctx, query)
|
||||
if err != nil {
|
||||
@@ -355,7 +355,10 @@ func (s *Service) requestBatchedLogs(ctx context.Context) error {
|
||||
// We request for the nth block behind the current head, in order to have
|
||||
// stabilized logs when we retrieve it from the 1.0 chain.
|
||||
|
||||
requestedBlock := s.latestEth1Data.BlockHeight - uint64(params.BeaconConfig().LogBlockDelay)
|
||||
requestedBlock, err := s.followBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := s.latestEth1Data.LastRequestedBlock + 1; i <= requestedBlock; i++ {
|
||||
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
|
||||
if err != nil {
|
||||
|
||||
@@ -488,18 +488,18 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
||||
}
|
||||
web3Service.rpcClient = &mockPOW.RPCClient{Backend: testAcc.Backend}
|
||||
web3Service.httpLogger = testAcc.Backend
|
||||
web3Service.blockFetcher = &goodFetcher{backend: testAcc.Backend}
|
||||
web3Service.latestEth1Data.LastRequestedBlock = 0
|
||||
web3Service.latestEth1Data.BlockHeight = 0
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
bConfig := params.MinimalSpecConfig()
|
||||
bConfig.MinGenesisTime = 0
|
||||
bConfig.SecondsPerETH1Block = 10
|
||||
params.OverrideBeaconConfig(bConfig)
|
||||
flags.Get().DeploymentBlock = 0
|
||||
|
||||
testAcc.Backend.Commit()
|
||||
if err := testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond()))); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
totalNumOfDeposits := depositsReqForChainStart + 30
|
||||
|
||||
@@ -529,7 +529,12 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
}
|
||||
// Forward the chain to account for the follow distance
|
||||
for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
|
||||
// Set up our subscriber now to listen for the chain started event.
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
@@ -726,7 +731,7 @@ func TestConsistentGenesisState(t *testing.T) {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
|
||||
for i := 0; i < int(params.BeaconConfig().LogBlockDelay); i++ {
|
||||
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
|
||||
|
||||
@@ -317,6 +317,32 @@ func (s *Service) AreAllDepositsProcessed() (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// refers to the latest eth1 block which follows the condition: eth1_timestamp +
|
||||
// SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= current_unix_time
|
||||
func (s *Service) followBlockHeight(ctx context.Context) (uint64, error) {
|
||||
latestValidBlock := uint64(0)
|
||||
if s.latestEth1Data.BlockHeight > params.BeaconConfig().Eth1FollowDistance {
|
||||
latestValidBlock = s.latestEth1Data.BlockHeight - params.BeaconConfig().Eth1FollowDistance
|
||||
}
|
||||
blockTime, err := s.BlockTimeByHeight(ctx, big.NewInt(int64(latestValidBlock)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
followTime := func(t uint64) uint64 {
|
||||
return t + params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().SecondsPerETH1Block
|
||||
}
|
||||
for followTime(blockTime) > s.latestEth1Data.BlockTime && latestValidBlock > 0 {
|
||||
// reduce block height to get eth1 block which
|
||||
// fulfills stated condition
|
||||
latestValidBlock--
|
||||
blockTime, err = s.BlockTimeByHeight(ctx, big.NewInt(int64(latestValidBlock)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return latestValidBlock, nil
|
||||
}
|
||||
|
||||
func (s *Service) connectToPowChain() error {
|
||||
httpClient, rpcClient, err := s.dialETH1Nodes()
|
||||
if err != nil {
|
||||
@@ -502,7 +528,7 @@ func safelyHandlePanic() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) handleDelayTicker() {
|
||||
func (s *Service) handleETH1FollowDistance() {
|
||||
defer safelyHandlePanic()
|
||||
|
||||
// use a 5 minutes timeout for block time, because the max mining time is 278 sec (block 7208027)
|
||||
@@ -568,6 +594,7 @@ func (s *Service) initPOWService() {
|
||||
|
||||
s.latestEth1Data.BlockHeight = header.Number.Uint64()
|
||||
s.latestEth1Data.BlockHash = header.Hash().Bytes()
|
||||
s.latestEth1Data.BlockTime = header.Time
|
||||
|
||||
if err := s.processPastLogs(context.Background()); err != nil {
|
||||
log.Errorf("Unable to process past logs %v", err)
|
||||
@@ -605,7 +632,7 @@ func (s *Service) run(done <-chan struct{}) {
|
||||
}
|
||||
s.processBlockHeader(head)
|
||||
case <-ticker.C:
|
||||
s.handleDelayTicker()
|
||||
s.handleETH1FollowDistance()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
@@ -187,6 +188,67 @@ func TestStop_OK(t *testing.T) {
|
||||
hook.Reset()
|
||||
}
|
||||
|
||||
func TestFollowBlock_OK(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
}
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndPoint: endpoint,
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unable to setup web3 ETH1.0 chain service: %v", err)
|
||||
}
|
||||
|
||||
// simulated backend sets eth1 block
|
||||
// time as 10 seconds
|
||||
conf := params.BeaconConfig()
|
||||
conf.SecondsPerETH1Block = 10
|
||||
params.OverrideBeaconConfig(conf)
|
||||
defer func() {
|
||||
params.UseMainnetConfig()
|
||||
}()
|
||||
|
||||
web3Service = setDefaultMocks(web3Service)
|
||||
web3Service.blockFetcher = &goodFetcher{backend: testAcc.Backend}
|
||||
baseHeight := testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
// process follow_distance blocks
|
||||
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
// set current height
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
|
||||
h, err := web3Service.followBlockHeight(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if h != baseHeight {
|
||||
t.Errorf("Unexpected block height of %d received instead of %d", h, baseHeight)
|
||||
}
|
||||
numToForward := uint64(2)
|
||||
expectedHeight := numToForward + baseHeight
|
||||
// forward 2 blocks
|
||||
for i := uint64(0); i < numToForward; i++ {
|
||||
testAcc.Backend.Commit()
|
||||
}
|
||||
// set current height
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
|
||||
h, err = web3Service.followBlockHeight(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if h != expectedHeight {
|
||||
t.Errorf("Unexpected block height of %d received instead of %d", h, expectedHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitDataFromContract_OK(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
if err != nil {
|
||||
|
||||
@@ -93,7 +93,16 @@ func TestServer_ListAttestations_Genesis(t *testing.T) {
|
||||
}); err != nil && !strings.Contains(err.Error(), "Could not find genesis") {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 1}}
|
||||
att := ðpb.Attestation{
|
||||
Signature: make([]byte, 96),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 2,
|
||||
CommitteeIndex: 1,
|
||||
Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
},
|
||||
}
|
||||
|
||||
parentRoot := [32]byte{1, 2, 3}
|
||||
blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{
|
||||
@@ -159,8 +168,11 @@ func TestServer_ListAttestations_NoPagination(t *testing.T) {
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Signature: make([]byte, 96),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
Slot: i,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
@@ -197,27 +209,31 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
||||
db := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
someRoot := []byte{1, 2, 3}
|
||||
sourceRoot := []byte{4, 5, 6}
|
||||
someRoot := [32]byte{1, 2, 3}
|
||||
sourceRoot := [32]byte{4, 5, 6}
|
||||
sourceEpoch := uint64(5)
|
||||
targetRoot := []byte{7, 8, 9}
|
||||
targetRoot := [32]byte{7, 8, 9}
|
||||
targetEpoch := uint64(7)
|
||||
|
||||
blocks := []*ethpb.SignedBeaconBlock{
|
||||
{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 4,
|
||||
Slot: 4,
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: someRoot,
|
||||
BeaconBlockRoot: someRoot[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: sourceRoot,
|
||||
Root: sourceRoot[:],
|
||||
Epoch: sourceEpoch,
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: targetRoot,
|
||||
Root: targetRoot[:],
|
||||
Epoch: targetEpoch,
|
||||
},
|
||||
Slot: 3,
|
||||
@@ -229,19 +245,23 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 5 + params.BeaconConfig().SlotsPerEpoch,
|
||||
Slot: 5 + params.BeaconConfig().SlotsPerEpoch,
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: someRoot,
|
||||
BeaconBlockRoot: someRoot[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: sourceRoot,
|
||||
Root: sourceRoot[:],
|
||||
Epoch: sourceEpoch,
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: targetRoot,
|
||||
Root: targetRoot[:],
|
||||
Epoch: targetEpoch,
|
||||
},
|
||||
Slot: 4 + params.BeaconConfig().SlotsPerEpoch,
|
||||
@@ -253,19 +273,23 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 5,
|
||||
Slot: 5,
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: someRoot,
|
||||
BeaconBlockRoot: someRoot[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: sourceRoot,
|
||||
Root: sourceRoot[:],
|
||||
Epoch: sourceEpoch,
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: targetRoot,
|
||||
Root: targetRoot[:],
|
||||
Epoch: targetEpoch,
|
||||
},
|
||||
Slot: 4,
|
||||
@@ -321,10 +345,14 @@ func TestServer_ListAttestations_Pagination_CustomPageParameters(t *testing.T) {
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
CommitteeIndex: s,
|
||||
Slot: i,
|
||||
CommitteeIndex: s,
|
||||
Slot: i,
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -423,17 +451,22 @@ func TestServer_ListAttestations_Pagination_CustomPageParameters(t *testing.T) {
|
||||
func TestServer_ListAttestations_Pagination_OutOfRange(t *testing.T) {
|
||||
db := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
testutil.NewBeaconBlock()
|
||||
count := uint64(1)
|
||||
atts := make([]*ethpb.Attestation, 0, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
blockExample := ðpb.SignedBeaconBlock{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Graffiti: make([]byte, 32),
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
Slot: i,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
@@ -485,14 +518,21 @@ func TestServer_ListAttestations_Pagination_DefaultPageSize(t *testing.T) {
|
||||
atts := make([]*ethpb.Attestation, 0, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
blockExample := ðpb.SignedBeaconBlock{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("root"), 32)},
|
||||
Slot: i,
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("root"), 96),
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
},
|
||||
},
|
||||
@@ -624,10 +664,15 @@ func TestServer_ListIndexedAttestations_GenesisEpoch(t *testing.T) {
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
Signature: make([]byte, 96),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: targetRoot[:],
|
||||
},
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
Slot: i,
|
||||
CommitteeIndex: 0,
|
||||
},
|
||||
|
||||
@@ -22,8 +22,10 @@ import (
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/mock"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func TestServer_ListBlocks_NoResults(t *testing.T) {
|
||||
@@ -91,13 +93,9 @@ func TestServer_ListBlocks_Genesis(t *testing.T) {
|
||||
}
|
||||
|
||||
// Should return the proper genesis block if it exists.
|
||||
parentRoot := [32]byte{1, 2, 3}
|
||||
blk := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 0,
|
||||
ParentRoot: parentRoot[:],
|
||||
},
|
||||
}
|
||||
parentRoot := [32]byte{'a'}
|
||||
blk := testutil.NewBeaconBlock()
|
||||
blk.Block.ParentRoot = parentRoot[:]
|
||||
root, err := stateutil.BlockRoot(blk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -195,11 +193,8 @@ func TestServer_ListBlocks_Pagination(t *testing.T) {
|
||||
blks := make([]*ethpb.SignedBeaconBlock, count)
|
||||
blkContainers := make([]*ethpb.BeaconBlockContainer, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
b := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: i,
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = i
|
||||
root, err := stateutil.BlockRoot(b.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -229,20 +224,62 @@ func TestServer_ListBlocks_Pagination(t *testing.T) {
|
||||
QueryFilter: ðpb.ListBlocksRequest_Slot{Slot: 5},
|
||||
PageSize: 3},
|
||||
res: ðpb.ListBlocksResponse{
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 5}}, BlockRoot: blkContainers[5].BlockRoot}},
|
||||
NextPageToken: "",
|
||||
TotalSize: 1}},
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Graffiti: make([]byte, 32),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
BlockHash: make([]byte, 32),
|
||||
DepositRoot: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Slot: 5}},
|
||||
BlockRoot: blkContainers[5].BlockRoot}},
|
||||
NextPageToken: "",
|
||||
TotalSize: 1}},
|
||||
{req: ðpb.ListBlocksRequest{
|
||||
PageToken: strconv.Itoa(0),
|
||||
QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]},
|
||||
PageSize: 3},
|
||||
res: ðpb.ListBlocksResponse{
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 6}}, BlockRoot: blkContainers[6].BlockRoot}},
|
||||
TotalSize: 1}},
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Graffiti: make([]byte, 32),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
BlockHash: make([]byte, 32),
|
||||
DepositRoot: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Slot: 6}},
|
||||
BlockRoot: blkContainers[6].BlockRoot}},
|
||||
TotalSize: 1}},
|
||||
{req: ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]}},
|
||||
res: ðpb.ListBlocksResponse{
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 6}}, BlockRoot: blkContainers[6].BlockRoot}},
|
||||
TotalSize: 1}},
|
||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{
|
||||
Signature: make([]byte, 96),
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Graffiti: make([]byte, 32),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
BlockHash: make([]byte, 32),
|
||||
DepositRoot: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Slot: 6}},
|
||||
BlockRoot: blkContainers[6].BlockRoot}},
|
||||
TotalSize: 1}},
|
||||
{req: ðpb.ListBlocksRequest{
|
||||
PageToken: strconv.Itoa(0),
|
||||
QueryFilter: ðpb.ListBlocksRequest_Epoch{Epoch: 0},
|
||||
@@ -374,7 +411,8 @@ func TestServer_GetChainHead_NoFinalizedBlock(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
genBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 0, ParentRoot: []byte{'G'}}}
|
||||
genBlock := testutil.NewBeaconBlock()
|
||||
genBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -417,7 +455,8 @@ func TestServer_GetChainHead_NoHeadBlock(t *testing.T) {
|
||||
func TestServer_GetChainHead(t *testing.T) {
|
||||
db := dbTest.SetupDB(t)
|
||||
|
||||
genBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 0, ParentRoot: []byte{'G'}}}
|
||||
genBlock := testutil.NewBeaconBlock()
|
||||
genBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -429,7 +468,9 @@ func TestServer_GetChainHead(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
finalizedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1, ParentRoot: []byte{'A'}}}
|
||||
finalizedBlock := testutil.NewBeaconBlock()
|
||||
finalizedBlock.Block.Slot = 1
|
||||
finalizedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), finalizedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -437,7 +478,10 @@ func TestServer_GetChainHead(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
justifiedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 2, ParentRoot: []byte{'B'}}}
|
||||
|
||||
justifiedBlock := testutil.NewBeaconBlock()
|
||||
justifiedBlock.Block.Slot = 2
|
||||
justifiedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'B'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), justifiedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -445,7 +489,10 @@ func TestServer_GetChainHead(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prevJustifiedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 3, ParentRoot: []byte{'C'}}}
|
||||
|
||||
prevJustifiedBlock := testutil.NewBeaconBlock()
|
||||
prevJustifiedBlock.Block.Slot = 3
|
||||
prevJustifiedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'C'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), prevJustifiedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -546,7 +593,8 @@ func TestServer_StreamChainHead_ContextCanceled(t *testing.T) {
|
||||
func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
||||
db := dbTest.SetupDB(t)
|
||||
|
||||
genBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 0, ParentRoot: []byte{'G'}}}
|
||||
genBlock := testutil.NewBeaconBlock()
|
||||
genBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -558,7 +606,9 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
finalizedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1, ParentRoot: []byte{'A'}}}
|
||||
finalizedBlock := testutil.NewBeaconBlock()
|
||||
finalizedBlock.Block.Slot = 1
|
||||
finalizedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), finalizedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -566,7 +616,10 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
justifiedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 2, ParentRoot: []byte{'B'}}}
|
||||
|
||||
justifiedBlock := testutil.NewBeaconBlock()
|
||||
justifiedBlock.Block.Slot = 2
|
||||
justifiedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'B'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), justifiedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -574,7 +627,10 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prevJustifiedBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 3, ParentRoot: []byte{'C'}}}
|
||||
|
||||
prevJustifiedBlock := testutil.NewBeaconBlock()
|
||||
prevJustifiedBlock.Block.Slot = 3
|
||||
prevJustifiedBlock.Block.ParentRoot = bytesutil.PadTo([]byte{'C'}, 32)
|
||||
if err := db.SaveBlock(context.Background(), prevJustifiedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1892,7 +1892,9 @@ func TestServer_GetValidatorParticipation_PrevEpoch(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wanted := ðpb.ValidatorParticipation{EligibleEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance}
|
||||
wanted := ðpb.ValidatorParticipation{EligibleEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
|
||||
VotedEther: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
GlobalParticipationRate: float32(params.BeaconConfig().EffectiveBalanceIncrement) / float32(validatorCount*params.BeaconConfig().MaxEffectiveBalance)}
|
||||
if !reflect.DeepEqual(res.Participation, wanted) {
|
||||
t.Error("Incorrect validator participation respond")
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ func assignValidatorToSubnet(pubkey []byte, status ethpb.ValidatorStatus) {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok, expTime := cache.CommitteeIDs.GetPersistentCommittees(pubkey)
|
||||
_, ok, expTime := cache.SubnetIDs.GetPersistentSubnets(pubkey)
|
||||
if ok && expTime.After(roughtime.Now()) {
|
||||
return
|
||||
}
|
||||
@@ -208,5 +208,5 @@ func assignValidatorToSubnet(pubkey []byte, status ethpb.ValidatorStatus) {
|
||||
assignedDuration += int(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
||||
|
||||
totalDuration := epochDuration * time.Duration(assignedDuration)
|
||||
cache.CommitteeIDs.AddPersistentCommittee(pubkey, assignedIdxs, totalDuration*time.Second)
|
||||
cache.SubnetIDs.AddPersistentCommittee(pubkey, assignedIdxs, totalDuration*time.Second)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
blk "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -40,7 +39,7 @@ func TestGetDuties_NextEpoch_CantFindValidatorIdx(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 10)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
@@ -78,7 +77,7 @@ func TestGetDuties_NextEpoch_CantFindValidatorIdx(t *testing.T) {
|
||||
func TestGetDuties_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
if err != nil {
|
||||
@@ -165,7 +164,7 @@ func TestGetDuties_OK(t *testing.T) {
|
||||
func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
if err != nil {
|
||||
@@ -222,7 +221,7 @@ func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
||||
func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := uint64(64)
|
||||
testutil.ResetCache()
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
@@ -274,11 +273,11 @@ func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
||||
if len(res.CurrentEpochDuties) != 2 {
|
||||
t.Errorf("expected 2 assignments but got %d", len(res.CurrentEpochDuties))
|
||||
}
|
||||
if res.CurrentEpochDuties[0].AttesterSlot != 2 {
|
||||
t.Errorf("Expected res.CurrentEpochDuties[0].AttesterSlot == 7, got %d", res.CurrentEpochDuties[0].AttesterSlot)
|
||||
if res.CurrentEpochDuties[0].AttesterSlot != 4 {
|
||||
t.Errorf("Expected res.CurrentEpochDuties[0].AttesterSlot == 4, got %d", res.CurrentEpochDuties[0].AttesterSlot)
|
||||
}
|
||||
if res.CurrentEpochDuties[1].AttesterSlot != 1 {
|
||||
t.Errorf("Expected res.CurrentEpochDuties[1].AttesterSlot == 1, got %d", res.CurrentEpochDuties[1].AttesterSlot)
|
||||
if res.CurrentEpochDuties[1].AttesterSlot != 4 {
|
||||
t.Errorf("Expected res.CurrentEpochDuties[1].AttesterSlot == 4, got %d", res.CurrentEpochDuties[1].AttesterSlot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +308,7 @@ func TestStreamDuties_SyncNotReady(t *testing.T) {
|
||||
func TestStreamDuties_OK(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
if err != nil {
|
||||
@@ -380,7 +379,7 @@ func TestStreamDuties_OK(t *testing.T) {
|
||||
func TestStreamDuties_OK_ChainReorg(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
if err != nil {
|
||||
@@ -469,7 +468,7 @@ func TestAssignValidatorToSubnet(t *testing.T) {
|
||||
k := pubKey(3)
|
||||
|
||||
assignValidatorToSubnet(k, ethpb.ValidatorStatus_ACTIVE)
|
||||
coms, ok, exp := cache.CommitteeIDs.GetPersistentCommittees(k)
|
||||
coms, ok, exp := cache.SubnetIDs.GetPersistentSubnets(k)
|
||||
if !ok {
|
||||
t.Fatal("No cache entry found for validator")
|
||||
}
|
||||
@@ -487,7 +486,7 @@ func TestAssignValidatorToSubnet(t *testing.T) {
|
||||
func BenchmarkCommitteeAssignment(b *testing.B) {
|
||||
db := dbutil.SetupDB(b)
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
depChainStart := uint64(8192 * 2)
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
if err != nil {
|
||||
|
||||
@@ -148,6 +148,9 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
// ProposeAttestation is a function called by an attester to vote
|
||||
// on a block via an attestation object as defined in the Ethereum Serenity specification.
|
||||
func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation) (*ethpb.AttestResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation")
|
||||
defer span.End()
|
||||
|
||||
if _, err := bls.SignatureFromBytes(att.Signature); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature")
|
||||
}
|
||||
@@ -166,8 +169,16 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation
|
||||
},
|
||||
})
|
||||
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := helpers.SlotToEpoch(att.Data.Slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(wantedEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.Data.CommitteeIndex, att.Data.Slot)
|
||||
|
||||
// Broadcast the new attestation to the network.
|
||||
if err := vs.P2P.Broadcast(ctx, att); err != nil {
|
||||
if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err)
|
||||
}
|
||||
|
||||
@@ -187,14 +198,46 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation
|
||||
|
||||
// SubscribeCommitteeSubnets subscribes to the committee ID subnet given subscribe request.
|
||||
func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.CommitteeSubnetsSubscribeRequest) (*ptypes.Empty, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.SubscribeCommitteeSubnets")
|
||||
defer span.End()
|
||||
|
||||
if len(req.Slots) != len(req.CommitteeIds) && len(req.CommitteeIds) != len(req.IsAggregator) {
|
||||
return nil, status.Error(codes.InvalidArgument, "request fields are not the same length")
|
||||
}
|
||||
if len(req.Slots) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "no attester slots provided")
|
||||
}
|
||||
|
||||
fetchValsLen := func(slot uint64) (uint64, error) {
|
||||
wantedEpoch := helpers.SlotToEpoch(slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(wantedEpoch)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(len(vals)), nil
|
||||
}
|
||||
|
||||
// Request the head validator indices of epoch represented by the first requested
|
||||
// slot.
|
||||
currValsLen, err := fetchValsLen(req.Slots[0])
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve head validator length: %v", err)
|
||||
}
|
||||
currEpoch := helpers.SlotToEpoch(req.Slots[0])
|
||||
|
||||
for i := 0; i < len(req.Slots); i++ {
|
||||
cache.CommitteeIDs.AddAttesterCommiteeID(req.Slots[i], req.CommitteeIds[i])
|
||||
// If epoch has changed, re-request active validators length
|
||||
if currEpoch != helpers.SlotToEpoch(req.Slots[i]) {
|
||||
currValsLen, err = fetchValsLen(req.Slots[i])
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve head validator length: %v", err)
|
||||
}
|
||||
currEpoch = helpers.SlotToEpoch(req.Slots[i])
|
||||
}
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(currValsLen, req.CommitteeIds[i], req.Slots[i])
|
||||
cache.SubnetIDs.AddAttesterSubnetID(req.Slots[i], subnet)
|
||||
if req.IsAggregator[i] {
|
||||
cache.CommitteeIDs.AddAggregatorCommiteeID(req.Slots[i], req.CommitteeIds[i])
|
||||
cache.SubnetIDs.AddAggregatorSubnetID(req.Slots[i], subnet)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -40,12 +42,9 @@ func TestProposeAttestation_OK(t *testing.T) {
|
||||
AttPool: attestations.NewPool(),
|
||||
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
|
||||
}
|
||||
head := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 999,
|
||||
ParentRoot: []byte{'a'},
|
||||
},
|
||||
}
|
||||
head := testutil.NewBeaconBlock()
|
||||
head.Block.Slot = 999
|
||||
head.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
|
||||
if err := db.SaveBlock(ctx, head); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -637,3 +636,86 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) {
|
||||
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_SubscribeCommitteeSubnets_NoSlots(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
attesterServer := &Server{
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BeaconDB: db,
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
AttPool: attestations.NewPool(),
|
||||
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
|
||||
}
|
||||
|
||||
_, err := attesterServer.SubscribeCommitteeSubnets(context.Background(), ðpb.CommitteeSubnetsSubscribeRequest{
|
||||
Slots: nil,
|
||||
CommitteeIds: nil,
|
||||
IsAggregator: nil,
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "no attester slots provided") {
|
||||
t.Fatalf("Expected no attester slots provided error, received: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_SubscribeCommitteeSubnets_MultipleSlots(t *testing.T) {
|
||||
db := dbutil.SetupDB(t)
|
||||
// fixed seed
|
||||
s := rand.NewSource(10)
|
||||
randGen := rand.New(s)
|
||||
|
||||
validators := make([]*ethpb.Validator, 64)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
if err := state.SetValidators(validators); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attesterServer := &Server{
|
||||
HeadFetcher: &mock.ChainService{State: state},
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
BeaconDB: db,
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
AttPool: attestations.NewPool(),
|
||||
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
|
||||
}
|
||||
|
||||
var slots []uint64
|
||||
var comIdxs []uint64
|
||||
var isAggregator []bool
|
||||
|
||||
for i := uint64(100); i < 200; i++ {
|
||||
slots = append(slots, i)
|
||||
comIdxs = append(comIdxs, uint64(randGen.Int63n(64)))
|
||||
boolVal := randGen.Uint64()%2 == 0
|
||||
isAggregator = append(isAggregator, boolVal)
|
||||
}
|
||||
|
||||
_, err := attesterServer.SubscribeCommitteeSubnets(context.Background(), ðpb.CommitteeSubnetsSubscribeRequest{
|
||||
Slots: slots,
|
||||
CommitteeIds: comIdxs,
|
||||
IsAggregator: isAggregator,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := uint64(100); i < 200; i++ {
|
||||
subnets := cache.SubnetIDs.GetAttesterSubnetIDs(i)
|
||||
if len(subnets) != 1 {
|
||||
t.Errorf("Wanted subnets of length 1 but got %d", len(subnets))
|
||||
}
|
||||
if isAggregator[i-100] {
|
||||
subnets = cache.SubnetIDs.GetAggregatorSubnetIDs(i)
|
||||
if len(subnets) != 1 {
|
||||
t.Errorf("Wanted subnets of length 1 but got %d", len(subnets))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
blk "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -34,7 +33,7 @@ func TestSub(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -123,7 +122,7 @@ func TestProposeExit_NoPanic(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
|
||||
@@ -382,6 +382,11 @@ func (vs *Server) defaultEth1DataResponse(ctx context.Context, currentHeight *bi
|
||||
if depositsTillHeight == 0 {
|
||||
return vs.ChainStartFetcher.ChainStartEth1Data(), nil
|
||||
}
|
||||
// Check for the validity of deposit count.
|
||||
currentETH1Data := vs.HeadFetcher.HeadETH1Data()
|
||||
if depositsTillHeight < currentETH1Data.DepositCount {
|
||||
return currentETH1Data, nil
|
||||
}
|
||||
return ðpb.Eth1Data{
|
||||
DepositRoot: depositRoot[:],
|
||||
BlockHash: blockHash[:],
|
||||
|
||||
@@ -94,24 +94,36 @@ func TestGetBlock_OK(t *testing.T) {
|
||||
Graffiti: graffiti[:],
|
||||
}
|
||||
|
||||
// We include max proposer slashings which is currently 1 in the pool.
|
||||
proposerSlashing, err := testutil.GenerateProposerSlashingForValidator(
|
||||
beaconState,
|
||||
privKeys[0],
|
||||
0, /* validator index */
|
||||
)
|
||||
if err := proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing); err != nil {
|
||||
t.Fatal(err)
|
||||
proposerSlashings := make([]*ethpb.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings)
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxProposerSlashings; i++ {
|
||||
proposerSlashing, err := testutil.GenerateProposerSlashingForValidator(
|
||||
beaconState,
|
||||
privKeys[i],
|
||||
i, /* validator index */
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
proposerSlashings[i] = proposerSlashing
|
||||
if err := proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// We include max attester slashings which is currently 1 in the pool.
|
||||
attesterSlashing, err := testutil.GenerateAttesterSlashingForValidator(
|
||||
beaconState,
|
||||
privKeys[1],
|
||||
1, /* validator index */
|
||||
)
|
||||
if err := proposerServer.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing); err != nil {
|
||||
t.Fatal(err)
|
||||
attSlashings := make([]*ethpb.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings)
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ {
|
||||
attesterSlashing, err := testutil.GenerateAttesterSlashingForValidator(
|
||||
beaconState,
|
||||
privKeys[i+params.BeaconConfig().MaxProposerSlashings],
|
||||
i+params.BeaconConfig().MaxProposerSlashings, /* validator index */
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
attSlashings[i] = attesterSlashing
|
||||
if err := proposerServer.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
block, err := proposerServer.GetBlock(ctx, req)
|
||||
@@ -131,17 +143,17 @@ func TestGetBlock_OK(t *testing.T) {
|
||||
if !bytes.Equal(block.Body.Graffiti, req.Graffiti) {
|
||||
t.Fatal("Expected block to have correct graffiti")
|
||||
}
|
||||
if len(block.Body.ProposerSlashings) != 1 {
|
||||
t.Fatalf("Wanted %d proposer slashings, got %d", 1, len(block.Body.ProposerSlashings))
|
||||
if len(block.Body.ProposerSlashings) != int(params.BeaconConfig().MaxProposerSlashings) {
|
||||
t.Fatalf("Wanted %d proposer slashings, got %d", params.BeaconConfig().MaxProposerSlashings, len(block.Body.ProposerSlashings))
|
||||
}
|
||||
if !reflect.DeepEqual(block.Body.ProposerSlashings[0], proposerSlashing) {
|
||||
t.Errorf("Wanted proposer slashing %v, got %v", proposerSlashing, block.Body.ProposerSlashings[0])
|
||||
if !reflect.DeepEqual(block.Body.ProposerSlashings, proposerSlashings) {
|
||||
t.Errorf("Wanted proposer slashing %v, got %v", proposerSlashings, block.Body.ProposerSlashings)
|
||||
}
|
||||
if len(block.Body.AttesterSlashings) != 1 {
|
||||
t.Fatalf("Wanted %d attester slashings, got %d", 1, len(block.Body.AttesterSlashings))
|
||||
if len(block.Body.AttesterSlashings) != int(params.BeaconConfig().MaxAttesterSlashings) {
|
||||
t.Fatalf("Wanted %d attester slashings, got %d", params.BeaconConfig().MaxAttesterSlashings, len(block.Body.AttesterSlashings))
|
||||
}
|
||||
if !reflect.DeepEqual(block.Body.AttesterSlashings[0], attesterSlashing) {
|
||||
t.Errorf("Wanted attester slashing %v, got %v", attesterSlashing, block.Body.AttesterSlashings)
|
||||
if !reflect.DeepEqual(block.Body.AttesterSlashings, attSlashings) {
|
||||
t.Errorf("Wanted attester slashing %v, got %v", attSlashings, block.Body.AttesterSlashings)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +287,7 @@ func TestProposeBlock_OK(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
|
||||
genesis := b.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -301,13 +313,9 @@ func TestProposeBlock_OK(t *testing.T) {
|
||||
HeadFetcher: c,
|
||||
BlockNotifier: c.BlockNotifier(),
|
||||
}
|
||||
req := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 5,
|
||||
ParentRoot: []byte("parent-hash"),
|
||||
Body: ðpb.BeaconBlockBody{},
|
||||
},
|
||||
}
|
||||
req := testutil.NewBeaconBlock()
|
||||
req.Block.Slot = 5
|
||||
req.Block.ParentRoot = bytesutil.PadTo([]byte("parent-hash"), 32)
|
||||
if err := db.SaveBlock(ctx, req); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -355,7 +363,7 @@ func TestComputeStateRoot_OK(t *testing.T) {
|
||||
|
||||
req := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ProposerIndex: 41,
|
||||
ProposerIndex: 21,
|
||||
ParentRoot: parentRoot[:],
|
||||
Slot: 1,
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
@@ -1197,7 +1205,75 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
|
||||
|
||||
// TODO(2312): Add more tests for edge cases and better coverage.
|
||||
func TestEth1Data(t *testing.T) {
|
||||
slot := uint64(10000)
|
||||
slot := uint64(20000)
|
||||
|
||||
p := &mockPOW.POWChain{
|
||||
BlockNumberByHeight: map[uint64]*big.Int{
|
||||
slot * params.BeaconConfig().SecondsPerSlot: big.NewInt(8196),
|
||||
},
|
||||
HashesByHeight: map[int][]byte{
|
||||
8180: []byte("8180"),
|
||||
},
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositCount: 55,
|
||||
},
|
||||
}
|
||||
|
||||
headState := testutil.NewBeaconState()
|
||||
if err := headState.SetEth1Data(ðpb.Eth1Data{DepositCount: 55}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ps := &Server{
|
||||
ChainStartFetcher: p,
|
||||
Eth1InfoFetcher: p,
|
||||
Eth1BlockFetcher: p,
|
||||
DepositFetcher: depositcache.NewDepositCache(),
|
||||
HeadFetcher: &mock.ChainService{State: headState},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
eth1Data, err := ps.eth1Data(ctx, slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if eth1Data.DepositCount != 55 {
|
||||
t.Error("Expected deposit count to be 55")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEth1Data_SmallerDepositCount(t *testing.T) {
|
||||
slot := uint64(20000)
|
||||
deps := []*dbpb.DepositContainer{
|
||||
{
|
||||
Index: 0,
|
||||
Eth1BlockHeight: 8,
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: []byte("a"),
|
||||
Signature: make([]byte, 96),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
}},
|
||||
},
|
||||
{
|
||||
Index: 1,
|
||||
Eth1BlockHeight: 14,
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: []byte("b"),
|
||||
Signature: make([]byte, 96),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
}},
|
||||
},
|
||||
}
|
||||
depositTrie, err := trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth))
|
||||
if err != nil {
|
||||
t.Fatalf("could not setup deposit trie: %v", err)
|
||||
}
|
||||
depositCache := depositcache.NewDepositCache()
|
||||
for _, dp := range deps {
|
||||
depositCache.InsertDeposit(context.Background(), dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.Root())
|
||||
}
|
||||
|
||||
p := &mockPOW.POWChain{
|
||||
BlockNumberByHeight: map[uint64]*big.Int{
|
||||
@@ -1214,7 +1290,8 @@ func TestEth1Data(t *testing.T) {
|
||||
ChainStartFetcher: p,
|
||||
Eth1InfoFetcher: p,
|
||||
Eth1BlockFetcher: p,
|
||||
DepositFetcher: depositcache.NewDepositCache(),
|
||||
HeadFetcher: &mock.ChainService{ETH1Data: ðpb.Eth1Data{DepositCount: 10}},
|
||||
DepositFetcher: depositCache,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -1223,8 +1300,10 @@ func TestEth1Data(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if eth1Data.DepositCount != 55 {
|
||||
t.Error("Expected deposit count to be 55")
|
||||
// Will default to 10 as the current deposit count in the
|
||||
// cache is only 2.
|
||||
if eth1Data.DepositCount != 10 {
|
||||
t.Errorf("Expected deposit count to be 10 but got %d", eth1Data.DepositCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1284,7 +1363,7 @@ func TestFilterAttestation_OK(t *testing.T) {
|
||||
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
genesis := b.NewGenesisBlock([]byte{})
|
||||
genesis := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
blk "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -70,7 +69,7 @@ func TestWaitForActivation_ContextClosed(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -135,7 +134,7 @@ func TestWaitForActivation_ValidatorOriginallyExists(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
@@ -244,7 +243,7 @@ func TestWaitForActivation_MultipleStatuses(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
blk "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||
@@ -136,7 +135,7 @@ func TestValidatorStatus_Pending(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
pubKey := pubKey(1)
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -236,7 +235,7 @@ func TestValidatorStatus_Active(t *testing.T) {
|
||||
// Active because activation epoch <= current epoch < exit epoch.
|
||||
activeEpoch := helpers.ActivationExitEpoch(0)
|
||||
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -301,7 +300,7 @@ func TestValidatorStatus_Exiting(t *testing.T) {
|
||||
epoch := helpers.SlotToEpoch(slot)
|
||||
exitEpoch := helpers.ActivationExitEpoch(epoch)
|
||||
withdrawableEpoch := exitEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -372,7 +371,7 @@ func TestValidatorStatus_Slashing(t *testing.T) {
|
||||
// Exit slashed because slashed is true, exit epoch is =< current epoch and withdrawable epoch > epoch .
|
||||
slot := uint64(10000)
|
||||
epoch := helpers.SlotToEpoch(slot)
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -442,7 +441,7 @@ func TestValidatorStatus_Exited(t *testing.T) {
|
||||
// Exit because only exit epoch is =< current epoch.
|
||||
slot := uint64(10000)
|
||||
epoch := helpers.SlotToEpoch(slot)
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -566,7 +565,7 @@ func TestActivationStatus_OK(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
@@ -655,7 +654,7 @@ func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
pbKey := pubKey(5)
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -795,7 +794,7 @@ func TestDepositBlockSlotAfterGenesisTime(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -834,7 +833,7 @@ func TestDepositBlockSlotAfterGenesisTime(t *testing.T) {
|
||||
t.Fatalf("Could not get the deposit block slot %v", err)
|
||||
}
|
||||
|
||||
expected := uint64(53)
|
||||
expected := uint64(69)
|
||||
|
||||
if resp != expected {
|
||||
t.Errorf("Wanted %v, got %v", expected, resp)
|
||||
@@ -870,7 +869,7 @@ func TestDepositBlockSlotBeforeGenesisTime(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
if err := db.SaveBlock(ctx, block); err != nil {
|
||||
t.Fatalf("Could not save genesis block: %v", err)
|
||||
}
|
||||
@@ -940,7 +939,7 @@ func TestMultipleValidatorStatus_Pubkeys(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
@@ -995,7 +994,7 @@ func TestMultipleValidatorStatus_Pubkeys(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Status: ethpb.ValidatorStatus_DEPOSITED,
|
||||
DepositInclusionSlot: 53,
|
||||
DepositInclusionSlot: 69,
|
||||
ActivationEpoch: 18446744073709551615,
|
||||
},
|
||||
{
|
||||
@@ -1059,7 +1058,7 @@ func TestMultipleValidatorStatus_Indices(t *testing.T) {
|
||||
},
|
||||
}
|
||||
stateObj, err := stateTrie.InitializeFromProtoUnsafe(beaconState)
|
||||
block := blk.NewGenesisBlock([]byte{})
|
||||
block := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get signing root %v", err)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
|
||||
//pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -245,23 +246,30 @@ func TestLastAncestorState_CanGet(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
service := New(db, cache.NewStateSummaryCache())
|
||||
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: []byte{'a'}}
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
b0 := testutil.NewBeaconBlock()
|
||||
b0.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
|
||||
r0, err := ssz.HashTreeRoot(b0.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b1 := ðpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
|
||||
r1, err := ssz.HashTreeRoot(b1)
|
||||
b1 := testutil.NewBeaconBlock()
|
||||
b1.Block.Slot = 1
|
||||
b1.Block.ParentRoot = bytesutil.PadTo(r0[:], 32)
|
||||
r1, err := ssz.HashTreeRoot(b1.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b2 := ðpb.BeaconBlock{Slot: 2, ParentRoot: r1[:]}
|
||||
r2, err := ssz.HashTreeRoot(b2)
|
||||
b2 := testutil.NewBeaconBlock()
|
||||
b2.Block.Slot = 2
|
||||
b2.Block.ParentRoot = bytesutil.PadTo(r1[:], 32)
|
||||
r2, err := ssz.HashTreeRoot(b2.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b3 := ðpb.BeaconBlock{Slot: 3, ParentRoot: r2[:]}
|
||||
r3, err := ssz.HashTreeRoot(b3)
|
||||
b3 := testutil.NewBeaconBlock()
|
||||
b3.Block.Slot = 3
|
||||
b3.Block.ParentRoot = bytesutil.PadTo(r2[:], 32)
|
||||
r3, err := ssz.HashTreeRoot(b3.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -271,16 +279,16 @@ func TestLastAncestorState_CanGet(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: b0}); err != nil {
|
||||
if err := service.beaconDB.SaveBlock(ctx, b0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: b1}); err != nil {
|
||||
if err := service.beaconDB.SaveBlock(ctx, b1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: b2}); err != nil {
|
||||
if err := service.beaconDB.SaveBlock(ctx, b2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: b3}); err != nil {
|
||||
if err := service.beaconDB.SaveBlock(ctx, b3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, b1State, r1); err != nil {
|
||||
|
||||
@@ -179,7 +179,7 @@ func TestLoadBlocks_FirstBranch(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
roots, savedBlocks, err := tree1(db, []byte{'A'})
|
||||
roots, savedBlocks, err := tree1(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -190,15 +190,18 @@ func TestLoadBlocks_FirstBranch(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[8]},
|
||||
{Block: savedBlocks[6]},
|
||||
{Block: savedBlocks[4]},
|
||||
{Block: savedBlocks[2]},
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[8],
|
||||
savedBlocks[6],
|
||||
savedBlocks[4],
|
||||
savedBlocks[2],
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,13 +223,16 @@ func TestLoadBlocks_SecondBranch(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[5]},
|
||||
{Block: savedBlocks[3]},
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[5],
|
||||
savedBlocks[3],
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,15 +254,18 @@ func TestLoadBlocks_ThirdBranch(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[7]},
|
||||
{Block: savedBlocks[6]},
|
||||
{Block: savedBlocks[4]},
|
||||
{Block: savedBlocks[2]},
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[7],
|
||||
savedBlocks[6],
|
||||
savedBlocks[4],
|
||||
savedBlocks[2],
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,13 +287,16 @@ func TestLoadBlocks_SameSlots(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[6]},
|
||||
{Block: savedBlocks[5]},
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[6],
|
||||
savedBlocks[5],
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +307,7 @@ func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
roots, savedBlocks, err := tree3(db, []byte{'A'})
|
||||
roots, savedBlocks, err := tree3(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -306,12 +318,15 @@ func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[2]},
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[2],
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +337,7 @@ func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
roots, savedBlocks, err := tree4(db, []byte{'A'})
|
||||
roots, savedBlocks, err := tree4(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -333,11 +348,14 @@ func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
||||
}
|
||||
|
||||
wanted := []*ethpb.SignedBeaconBlock{
|
||||
{Block: savedBlocks[1]},
|
||||
{Block: savedBlocks[0]},
|
||||
savedBlocks[1],
|
||||
savedBlocks[0],
|
||||
}
|
||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
|
||||
for i, block := range wanted {
|
||||
if !proto.Equal(block, filteredBlocks[i]) {
|
||||
t.Error("Did not get wanted blocks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +366,7 @@ func TestLoadBlocks_BadStart(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
roots, _, err := tree1(db, []byte{'A'})
|
||||
roots, _, err := tree1(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -661,7 +679,7 @@ func TestProcessStateUpToSlot_CanProcess(t *testing.T) {
|
||||
// B0 - B1 - - B3 -- B5
|
||||
// \- B2 -- B4 -- B6 ----- B8
|
||||
// \- B7
|
||||
func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock, error) {
|
||||
func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
if err != nil {
|
||||
@@ -709,15 +727,20 @@ func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8} {
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
|
||||
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(b.ParentRoot)); err != nil {
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
returnedBlocks = append(returnedBlocks, beaconBlock)
|
||||
}
|
||||
return [][32]byte{r0, r1, r2, r3, r4, r5, r6, r7, r8}, []*ethpb.BeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8}, nil
|
||||
return [][32]byte{r0, r1, r2, r3, r4, r5, r6, r7, r8}, returnedBlocks, nil
|
||||
}
|
||||
|
||||
// tree2 constructs the following tree:
|
||||
@@ -726,7 +749,7 @@ func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
// \- B2
|
||||
// \- B2
|
||||
// \- B2 -- B3
|
||||
func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock, error) {
|
||||
func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
if err != nil {
|
||||
@@ -764,15 +787,21 @@ func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24, b3} {
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
|
||||
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.StateRoot, 32)
|
||||
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(b.ParentRoot)); err != nil {
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
returnedBlocks = append(returnedBlocks, beaconBlock)
|
||||
}
|
||||
return [][32]byte{r0, r1, r21, r22, r23, r24, r3}, []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24, b3}, nil
|
||||
return [][32]byte{r0, r1, r21, r22, r23, r24, r3}, returnedBlocks, nil
|
||||
}
|
||||
|
||||
// tree3 constructs the following tree:
|
||||
@@ -781,7 +810,7 @@ func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
// \- B2
|
||||
// \- B2
|
||||
// \- B2
|
||||
func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock, error) {
|
||||
func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
if err != nil {
|
||||
@@ -814,16 +843,22 @@ func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24} {
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
|
||||
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.StateRoot, 32)
|
||||
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(b.ParentRoot)); err != nil {
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
returnedBlocks = append(returnedBlocks, beaconBlock)
|
||||
}
|
||||
|
||||
return [][32]byte{r0, r1, r21, r22, r23, r24}, []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24}, nil
|
||||
return [][32]byte{r0, r1, r21, r22, r23, r24}, returnedBlocks, nil
|
||||
}
|
||||
|
||||
// tree4 constructs the following tree:
|
||||
@@ -832,7 +867,7 @@ func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
// \- B2
|
||||
// \- B2
|
||||
// \- B2
|
||||
func tree4(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock, error) {
|
||||
func tree4(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
if err != nil {
|
||||
@@ -860,14 +895,20 @@ func tree4(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b21, b22, b23, b24} {
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
|
||||
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.StateRoot, 32)
|
||||
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(b.ParentRoot)); err != nil {
|
||||
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
returnedBlocks = append(returnedBlocks, beaconBlock)
|
||||
}
|
||||
|
||||
return [][32]byte{r0, r21, r22, r23, r24}, []*ethpb.BeaconBlock{b0, b21, b22, b23, b24}, nil
|
||||
return [][32]byte{r0, r21, r22, r23, r24}, returnedBlocks, nil
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ go_library(
|
||||
"service.go",
|
||||
"subscriber.go",
|
||||
"subscriber_beacon_aggregate_proof.go",
|
||||
"subscriber_beacon_attestation.go",
|
||||
"subscriber_beacon_blocks.go",
|
||||
"subscriber_committee_index_beacon_attestation.go",
|
||||
"subscriber_handlers.go",
|
||||
"utils.go",
|
||||
"validate_aggregate_proof.go",
|
||||
"validate_attester_slashing.go",
|
||||
"validate_beacon_attestation.go",
|
||||
"validate_beacon_blocks.go",
|
||||
"validate_committee_index_beacon_attestation.go",
|
||||
"validate_proposer_slashing.go",
|
||||
"validate_voluntary_exit.go",
|
||||
],
|
||||
@@ -63,7 +63,6 @@ go_library(
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
@@ -109,15 +108,15 @@ go_test(
|
||||
"rpc_test.go",
|
||||
"service_test.go",
|
||||
"subscriber_beacon_aggregate_proof_test.go",
|
||||
"subscriber_beacon_attestation_test.go",
|
||||
"subscriber_beacon_blocks_test.go",
|
||||
"subscriber_committee_index_beacon_attestation_test.go",
|
||||
"subscriber_test.go",
|
||||
"sync_test.go",
|
||||
"utils_test.go",
|
||||
"validate_aggregate_proof_test.go",
|
||||
"validate_attester_slashing_test.go",
|
||||
"validate_beacon_attestation_test.go",
|
||||
"validate_beacon_blocks_test.go",
|
||||
"validate_committee_index_beacon_attestation_test.go",
|
||||
"validate_proposer_slashing_test.go",
|
||||
"validate_voluntary_exit_test.go",
|
||||
],
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
)
|
||||
|
||||
const genericError = "internal service error"
|
||||
@@ -23,7 +24,10 @@ var responseCodeServerError = byte(0x02)
|
||||
|
||||
func (r *Service) generateErrorResponse(code byte, reason string) ([]byte, error) {
|
||||
buf := bytes.NewBuffer([]byte{code})
|
||||
if _, err := r.p2p.Encoding().EncodeWithLength(buf, []byte(reason)); err != nil {
|
||||
resp := &pb.ErrorResponse{
|
||||
Message: []byte(reason),
|
||||
}
|
||||
if _, err := r.p2p.Encoding().EncodeWithLength(buf, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -42,10 +46,12 @@ func ReadStatusCode(stream io.Reader, encoding encoder.NetworkEncoding) (uint8,
|
||||
return 0, "", nil
|
||||
}
|
||||
|
||||
msg := make([]byte, 0)
|
||||
if err := encoding.DecodeWithLength(stream, &msg); err != nil {
|
||||
msg := &pb.ErrorResponse{
|
||||
Message: []byte{},
|
||||
}
|
||||
if err := encoding.DecodeWithLength(stream, msg); err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
|
||||
return b[0], string(msg), nil
|
||||
return b[0], string(msg.Message), nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
)
|
||||
|
||||
func TestRegularSync_generateErrorResponse(t *testing.T) {
|
||||
@@ -24,11 +25,11 @@ func TestRegularSync_generateErrorResponse(t *testing.T) {
|
||||
if b[0] != responseCodeServerError {
|
||||
t.Errorf("The first byte was not the status code. Got %#x wanted %#x", b, responseCodeServerError)
|
||||
}
|
||||
msg := make([]byte, 0)
|
||||
if err := r.p2p.Encoding().DecodeWithLength(buf, &msg); err != nil {
|
||||
msg := &pb.ErrorResponse{}
|
||||
if err := r.p2p.Encoding().DecodeWithLength(buf, msg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(msg) != "something bad happened" {
|
||||
if string(msg.Message) != "something bad happened" {
|
||||
t.Errorf("Received the wrong message: %v", msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,11 +464,15 @@ func (f *blocksFetcher) requestBlocks(
|
||||
}()
|
||||
|
||||
resp := make([]*eth.SignedBeaconBlock, 0, req.Count)
|
||||
for {
|
||||
for i := uint64(0); ; i++ {
|
||||
blk, err := prysmsync.ReadChunkedBlock(stream, f.p2p)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
// exit if more than max request blocks are returned
|
||||
if i >= params.BeaconNetworkConfig().MaxRequestBlocks {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ func (r *Service) updateMetrics() {
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not compute fork digest")
|
||||
}
|
||||
indices := r.aggregatorCommitteeIndices(r.chain.CurrentSlot())
|
||||
indices := r.aggregatorSubnetIndices(r.chain.CurrentSlot())
|
||||
attTopic := p2p.GossipTypeMapping[reflect.TypeOf(&pb.Attestation{})]
|
||||
attTopic += r.p2p.Encoding().ProtocolSuffix()
|
||||
for _, committeeIdx := range indices {
|
||||
@@ -99,7 +99,7 @@ func (r *Service) updateMetrics() {
|
||||
// We update all other gossip topics.
|
||||
for topic := range p2p.GossipTopicMappings {
|
||||
// We already updated attestation subnet topics.
|
||||
if strings.Contains(topic, "committee_index") {
|
||||
if strings.Contains(topic, "beacon_attestation") {
|
||||
continue
|
||||
}
|
||||
topic += r.p2p.Encoding().ProtocolSuffix()
|
||||
|
||||
@@ -139,7 +139,7 @@ func (s *Service) processPendingAtts(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
req := [][32]byte{bRoot}
|
||||
req := [][]byte{bRoot[:]}
|
||||
if err := s.sendRecentBeaconBlocksRequest(ctx, req, pid); err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
log.Errorf("Could not send recent block request: %v", err)
|
||||
|
||||
@@ -173,11 +173,13 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[33].Sign(slotRoot[:])
|
||||
// Arbitrary aggregator index for testing purposes.
|
||||
aggregatorIndex := committee[0]
|
||||
sig := privKeys[aggregatorIndex].Sign(slotRoot[:])
|
||||
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||
SelectionProof: sig.Marshal(),
|
||||
Aggregate: att,
|
||||
AggregatorIndex: 33,
|
||||
AggregatorIndex: aggregatorIndex,
|
||||
}
|
||||
attesterDomain, err = helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainAggregateAndProof, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
@@ -187,7 +189,7 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
aggreSig := privKeys[33].Sign(signingRoot[:]).Marshal()
|
||||
aggreSig := privKeys[aggregatorIndex].Sign(signingRoot[:]).Marshal()
|
||||
|
||||
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -75,7 +75,7 @@ func (r *Service) processPendingBlocks(ctx context.Context) error {
|
||||
"currentSlot": b.Block.Slot,
|
||||
"parentRoot": hex.EncodeToString(bytesutil.Trunc(b.Block.ParentRoot)),
|
||||
}).Info("Requesting parent block")
|
||||
req := [][32]byte{bytesutil.ToBytes32(b.Block.ParentRoot)}
|
||||
req := [][]byte{b.Block.ParentRoot}
|
||||
|
||||
// Start with a random peer to query, but choose the first peer in our unsorted list that claims to
|
||||
// have a head slot newer than the block slot we are requesting.
|
||||
|
||||
@@ -49,7 +49,7 @@ func (r *Service) registerRPCHandlers() {
|
||||
)
|
||||
r.registerRPC(
|
||||
p2p.RPCBlocksByRootTopic,
|
||||
[][32]byte{},
|
||||
&pb.BeaconBlocksByRootRequest{},
|
||||
r.beaconBlocksRootRPCHandler,
|
||||
)
|
||||
r.registerRPC(
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
libp2pcore "github.com/libp2p/go-libp2p-core"
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -61,6 +61,7 @@ func (r *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa
|
||||
trace.StringAttribute("peer", stream.Conn().RemotePeer().Pretty()),
|
||||
trace.Int64Attribute("remaining_capacity", remainingBucketCapacity),
|
||||
)
|
||||
maxRequestBlocks := params.BeaconNetworkConfig().MaxRequestBlocks
|
||||
for startSlot <= endReqSlot {
|
||||
remainingBucketCapacity = r.blocksRateLimiter.Remaining(stream.Conn().RemotePeer().String())
|
||||
if int64(allowedBlocksPerSecond) > remainingBucketCapacity {
|
||||
@@ -78,7 +79,7 @@ func (r *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa
|
||||
}
|
||||
|
||||
// TODO(3147): Update this with reasonable constraints.
|
||||
if endSlot-startSlot > rangeLimit || m.Step == 0 {
|
||||
if endSlot-startSlot > rangeLimit || m.Step == 0 || m.Count > maxRequestBlocks {
|
||||
r.writeErrorResponseToStream(responseCodeInvalidRequest, stepError, stream)
|
||||
err := errors.New(stepError)
|
||||
traceutil.AnnotateError(span, err)
|
||||
@@ -145,24 +146,29 @@ func (r *Service) writeBlockRangeToStream(ctx context.Context, startSlot, endSlo
|
||||
roots = append([][32]byte{genRoot}, roots...)
|
||||
}
|
||||
blks, roots = r.sortBlocksAndRoots(blks, roots)
|
||||
checkpoint, err := r.db.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to retrieve finalized checkpoint")
|
||||
r.writeErrorResponseToStream(responseCodeServerError, genericError, stream)
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
for i, b := range blks {
|
||||
if b == nil || b.Block == nil {
|
||||
continue
|
||||
}
|
||||
blk := b.Block
|
||||
|
||||
// Check that the block is valid according to the request and part of the canonical chain.
|
||||
isRequestedSlotStep := (blk.Slot-startSlot)%step == 0
|
||||
isRecentUnfinalizedSlot := blk.Slot >= helpers.StartSlot(checkpoint.Epoch+1) || checkpoint.Epoch == 0
|
||||
if isRequestedSlotStep && (isRecentUnfinalizedSlot || r.db.IsFinalizedBlock(ctx, roots[i])) {
|
||||
if isRequestedSlotStep {
|
||||
canonical, err := r.chain.IsCanonical(ctx, roots[i])
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to determine canonical block")
|
||||
r.writeErrorResponseToStream(responseCodeServerError, genericError, stream)
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
if !canonical {
|
||||
continue
|
||||
}
|
||||
if err := r.chunkWriter(stream, b); err != nil {
|
||||
log.WithError(err).Error("Failed to send a chunked response")
|
||||
r.writeErrorResponseToStream(responseCodeServerError, genericError, stream)
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
@@ -42,7 +43,8 @@ func TestRPCBeaconBlocksByRange_RPCHandlerReturnsBlocks(t *testing.T) {
|
||||
}
|
||||
|
||||
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, int64(req.Count*10), false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, int64(req.Count*10), false),
|
||||
chain: &chainMock.ChainService{}}
|
||||
pcl := protocol.ID("/testing")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -107,7 +109,8 @@ func TestRPCBeaconBlocksByRange_RPCHandlerReturnsSortedBlocks(t *testing.T) {
|
||||
}
|
||||
|
||||
// Start service with 160 as allowed blocks capacity (and almost zero capacity recovery).
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, int64(req.Count*10), false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, int64(req.Count*10), false),
|
||||
chain: &chainMock.ChainService{}}
|
||||
pcl := protocol.ID("/testing")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -175,7 +178,7 @@ func TestRPCBeaconBlocksByRange_ReturnsGenesisBlock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(10000, 10000, false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(10000, 10000, false), chain: &chainMock.ChainService{}}
|
||||
pcl := protocol.ID("/testing")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -270,7 +273,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
||||
}
|
||||
|
||||
capacity := int64(flags.Get().BlockBatchLimit * 3)
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false), chain: &chainMock.ChainService{}}
|
||||
|
||||
req := &pb.BeaconBlocksByRangeRequest{
|
||||
StartSlot: 100,
|
||||
@@ -301,7 +304,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
||||
}
|
||||
|
||||
capacity := int64(flags.Get().BlockBatchLimit * 3)
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false), chain: &chainMock.ChainService{}}
|
||||
|
||||
req := &pb.BeaconBlocksByRangeRequest{
|
||||
StartSlot: 100,
|
||||
@@ -336,7 +339,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
||||
}
|
||||
|
||||
capacity := int64(flags.Get().BlockBatchLimit * flags.Get().BlockBatchLimitBurstFactor)
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false)}
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(0.000001, capacity, false), chain: &chainMock.ChainService{}}
|
||||
|
||||
req := &pb.BeaconBlocksByRangeRequest{
|
||||
StartSlot: 100,
|
||||
|
||||
@@ -10,15 +10,19 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
||||
// those corresponding blocks from that peer.
|
||||
func (r *Service) sendRecentBeaconBlocksRequest(ctx context.Context, blockRoots [][32]byte, id peer.ID) error {
|
||||
func (r *Service) sendRecentBeaconBlocksRequest(ctx context.Context, blockRoots [][]byte, id peer.ID) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
stream, err := r.p2p.Send(ctx, blockRoots, p2p.RPCBlocksByRootTopic, id)
|
||||
req := &pbp2p.BeaconBlocksByRootRequest{BlockRoots: blockRoots}
|
||||
stream, err := r.p2p.Send(ctx, req, p2p.RPCBlocksByRootTopic, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -32,6 +36,10 @@ func (r *Service) sendRecentBeaconBlocksRequest(ctx context.Context, blockRoots
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
// Exit if peer sends more than max request blocks.
|
||||
if uint64(i) >= params.BeaconNetworkConfig().MaxRequestBlocks {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Unable to retrieve block from stream")
|
||||
return err
|
||||
@@ -62,11 +70,11 @@ func (r *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
||||
setRPCStreamDeadlines(stream)
|
||||
log := log.WithField("handler", "beacon_blocks_by_root")
|
||||
|
||||
blockRoots, ok := msg.([][32]byte)
|
||||
req, ok := msg.(*pbp2p.BeaconBlocksByRootRequest)
|
||||
if !ok {
|
||||
return errors.New("message is not type [][32]byte")
|
||||
return errors.New("message is not type BeaconBlocksByRootRequest")
|
||||
}
|
||||
if len(blockRoots) == 0 {
|
||||
if len(req.BlockRoots) == 0 {
|
||||
resp, err := r.generateErrorResponse(responseCodeInvalidRequest, "no block roots provided in request")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to generate a response error")
|
||||
@@ -78,7 +86,7 @@ func (r *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
||||
return errors.New("no block roots provided")
|
||||
}
|
||||
|
||||
if int64(len(blockRoots)) > r.blocksRateLimiter.Remaining(stream.Conn().RemotePeer().String()) {
|
||||
if int64(len(req.BlockRoots)) > r.blocksRateLimiter.Remaining(stream.Conn().RemotePeer().String()) {
|
||||
r.p2p.Peers().IncrementBadResponses(stream.Conn().RemotePeer())
|
||||
if r.p2p.Peers().IsBad(stream.Conn().RemotePeer()) {
|
||||
log.Debug("Disconnecting bad peer")
|
||||
@@ -99,10 +107,22 @@ func (r *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
||||
return errors.New(rateLimitedError)
|
||||
}
|
||||
|
||||
r.blocksRateLimiter.Add(stream.Conn().RemotePeer().String(), int64(len(blockRoots)))
|
||||
if uint64(len(req.BlockRoots)) > params.BeaconNetworkConfig().MaxRequestBlocks {
|
||||
resp, err := r.generateErrorResponse(responseCodeInvalidRequest, "requested more than the max block limit")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to generate a response error")
|
||||
} else {
|
||||
if _, err := stream.Write(resp); err != nil {
|
||||
log.WithError(err).Errorf("Failed to write to stream")
|
||||
}
|
||||
}
|
||||
return errors.New("requested more than the max block limit")
|
||||
}
|
||||
|
||||
for _, root := range blockRoots {
|
||||
blk, err := r.db.Block(ctx, root)
|
||||
r.blocksRateLimiter.Add(stream.Conn().RemotePeer().String(), int64(len(req.BlockRoots)))
|
||||
|
||||
for _, root := range req.BlockRoots {
|
||||
blk, err := r.db.Block(ctx, bytesutil.ToBytes32(root))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to fetch block")
|
||||
resp, err := r.generateErrorResponse(responseCodeServerError, genericError)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
@@ -30,7 +31,7 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
||||
}
|
||||
d := db.SetupDB(t)
|
||||
|
||||
var blkRoots [][32]byte
|
||||
var blkRoots [][]byte
|
||||
// Populate the database with blocks that would match the request.
|
||||
for i := 1; i < 11; i++ {
|
||||
blk := ðpb.BeaconBlock{
|
||||
@@ -43,7 +44,7 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
||||
if err := d.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: blk}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
blkRoots = append(blkRoots, root)
|
||||
blkRoots = append(blkRoots, root[:])
|
||||
}
|
||||
|
||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(10000, 10000, false)}
|
||||
@@ -69,8 +70,8 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = r.beaconBlocksRootRPCHandler(context.Background(), blkRoots, stream1)
|
||||
req := &pb.BeaconBlocksByRootRequest{BlockRoots: blkRoots}
|
||||
err = r.beaconBlocksRootRPCHandler(context.Background(), req, stream1)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
@@ -111,7 +112,7 @@ func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
||||
Root: blockBRoot[:],
|
||||
}
|
||||
|
||||
expectedRoots := [][32]byte{blockBRoot, blockARoot}
|
||||
expectedRoots := [][]byte{blockBRoot[:], blockARoot[:]}
|
||||
|
||||
r := &Service{
|
||||
p2p: p1,
|
||||
@@ -132,12 +133,12 @@ func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
||||
wg.Add(1)
|
||||
p2.Host.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||
defer wg.Done()
|
||||
out := [][32]byte{}
|
||||
if err := p2.Encoding().DecodeWithLength(stream, &out); err != nil {
|
||||
out := &pb.BeaconBlocksByRootRequest{BlockRoots: [][]byte{}}
|
||||
if err := p2.Encoding().DecodeWithLength(stream, out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(out, expectedRoots) {
|
||||
t.Fatalf("Did not receive expected message. Got %+v wanted %+v", out, expectedRoots)
|
||||
if !reflect.DeepEqual(out.BlockRoots, expectedRoots) {
|
||||
t.Fatalf("Did not receive expected message. Got %+v wanted %+v", out.BlockRoots, expectedRoots)
|
||||
}
|
||||
response := []*ethpb.SignedBeaconBlock{blockB, blockA}
|
||||
for _, blk := range response {
|
||||
|
||||
@@ -66,6 +66,7 @@ type blockchainService interface {
|
||||
blockchain.AttestationReceiver
|
||||
blockchain.TimeFetcher
|
||||
blockchain.GenesisFetcher
|
||||
blockchain.CanonicalFetcher
|
||||
}
|
||||
|
||||
// Service is responsible for handling all run time p2p related operations as the
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
pb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/messagehandler"
|
||||
@@ -68,15 +67,16 @@ func (r *Service) registerSubscribers() {
|
||||
r.attesterSlashingSubscriber,
|
||||
)
|
||||
if featureconfig.Get().DisableDynamicCommitteeSubnets {
|
||||
r.subscribeDynamic(
|
||||
"/eth2/%x/committee_index%d_beacon_attestation",
|
||||
r.committeesCount, /* determineSubsLen */
|
||||
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
||||
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
||||
)
|
||||
for i := uint64(0); i < params.BeaconNetworkConfig().AttestationSubnetCount; i++ {
|
||||
r.subscribe(
|
||||
fmt.Sprintf("/eth2/%%x/beacon_attestation_%d", i),
|
||||
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
||||
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
||||
)
|
||||
}
|
||||
} else {
|
||||
r.subscribeDynamicWithSubnets(
|
||||
"/eth2/%x/committee_index%d_beacon_attestation",
|
||||
"/eth2/%x/beacon_attestation_%d",
|
||||
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
||||
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
||||
)
|
||||
@@ -211,9 +211,9 @@ func (r *Service) subscribeDynamicWithSubnets(
|
||||
}
|
||||
|
||||
// Persistent subscriptions from validators
|
||||
persistentSubs := r.persistentCommitteeIndices()
|
||||
persistentSubs := r.persistentSubnetIndices()
|
||||
// Update desired topic indices for aggregator
|
||||
wantedSubs := r.aggregatorCommitteeIndices(currentSlot)
|
||||
wantedSubs := r.aggregatorSubnetIndices(currentSlot)
|
||||
|
||||
// Combine subscriptions to get all requested subscriptions
|
||||
wantedSubs = sliceutil.SetUint64(append(persistentSubs, wantedSubs...))
|
||||
@@ -225,7 +225,7 @@ func (r *Service) subscribeDynamicWithSubnets(
|
||||
r.subscribeAggregatorSubnet(subscriptions, idx, base, digest, validate, handle)
|
||||
}
|
||||
// find desired subs for attesters
|
||||
attesterSubs := r.attesterCommitteeIndices(currentSlot)
|
||||
attesterSubs := r.attesterSubnetIndices(currentSlot)
|
||||
for _, idx := range attesterSubs {
|
||||
r.lookupAttesterSubnets(digest, idx)
|
||||
}
|
||||
@@ -234,57 +234,6 @@ func (r *Service) subscribeDynamicWithSubnets(
|
||||
}()
|
||||
}
|
||||
|
||||
// subscribe to a dynamically increasing index of topics. This method expects a fmt compatible
|
||||
// string for the topic name and a maxID to represent the number of subscribed topics that should be
|
||||
// maintained. As the state feed emits a newly updated state, the maxID function will be called to
|
||||
// determine the appropriate number of topics. This method supports only sequential number ranges
|
||||
// for topics.
|
||||
func (r *Service) subscribeDynamic(topicFormat string, determineSubsLen func() int, validate pubsub.ValidatorEx, handle subHandler) {
|
||||
base := p2p.GossipTopicMappings[topicFormat]
|
||||
if base == nil {
|
||||
log.Fatalf("%s is not mapped to any message in GossipTopicMappings", topicFormat)
|
||||
}
|
||||
digest, err := r.forkDigest()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Could not compute fork digest")
|
||||
}
|
||||
var subscriptions []*pubsub.Subscription
|
||||
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := r.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-r.ctx.Done():
|
||||
stateSub.Unsubscribe()
|
||||
return
|
||||
case <-stateChannel:
|
||||
if r.chainStarted && r.initialSync.Syncing() {
|
||||
continue
|
||||
}
|
||||
// Update topic count.
|
||||
wantedSubs := determineSubsLen()
|
||||
// Resize as appropriate.
|
||||
if len(subscriptions) > wantedSubs { // Reduce topics
|
||||
var cancelSubs []*pubsub.Subscription
|
||||
subscriptions, cancelSubs = subscriptions[:wantedSubs-1], subscriptions[wantedSubs:]
|
||||
for i, sub := range cancelSubs {
|
||||
sub.Cancel()
|
||||
if err := r.p2p.PubSub().UnregisterTopicValidator(fmt.Sprintf(topicFormat, i+wantedSubs)); err != nil {
|
||||
log.WithError(err).Error("Failed to unregister topic validator")
|
||||
}
|
||||
}
|
||||
} else if len(subscriptions) < wantedSubs { // Increase topics
|
||||
for i := len(subscriptions); i < wantedSubs; i++ {
|
||||
sub := r.subscribeWithBase(base, fmt.Sprintf(topicFormat, digest, i), validate, handle)
|
||||
subscriptions = append(subscriptions, sub)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// revalidate that our currently connected subnets are valid.
|
||||
func (r *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subscription,
|
||||
wantedSubs []uint64, topicFormat string, digest [4]byte) {
|
||||
|
||||
@@ -23,7 +23,6 @@ func (r *Service) beaconAggregateProofSubscriber(ctx context.Context, msg proto.
|
||||
if a.Message.Aggregate == nil || a.Message.Aggregate.Data == nil {
|
||||
return errors.New("nil aggregate")
|
||||
}
|
||||
r.setAggregatorIndexEpochSeen(a.Message.Aggregate.Data.Target.Epoch, a.Message.AggregatorIndex)
|
||||
|
||||
// Broadcast the aggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received aggregated attestation.
|
||||
|
||||
@@ -46,34 +46,30 @@ func (r *Service) committeeIndexBeaconAttestationSubscriber(ctx context.Context,
|
||||
return r.attPool.SaveUnaggregatedAttestation(a)
|
||||
}
|
||||
|
||||
func (r *Service) committeesCount() int {
|
||||
activeValidatorIndices, err := r.chain.HeadValidatorsIndices(helpers.SlotToEpoch(r.chain.HeadSlot()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return int(helpers.SlotCommitteeCount(uint64(len(activeValidatorIndices))))
|
||||
func (r *Service) subnetCount() int {
|
||||
return int(params.BeaconNetworkConfig().AttestationSubnetCount)
|
||||
}
|
||||
|
||||
func (r *Service) persistentCommitteeIndices() []uint64 {
|
||||
return cache.CommitteeIDs.GetAllCommittees()
|
||||
func (r *Service) persistentSubnetIndices() []uint64 {
|
||||
return cache.SubnetIDs.GetAllSubnets()
|
||||
}
|
||||
|
||||
func (r *Service) aggregatorCommitteeIndices(currentSlot uint64) []uint64 {
|
||||
func (r *Service) aggregatorSubnetIndices(currentSlot uint64) []uint64 {
|
||||
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
||||
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||
commIds := []uint64{}
|
||||
for i := currentSlot; i <= endSlot; i++ {
|
||||
commIds = append(commIds, cache.CommitteeIDs.GetAggregatorCommitteeIDs(i)...)
|
||||
commIds = append(commIds, cache.SubnetIDs.GetAggregatorSubnetIDs(i)...)
|
||||
}
|
||||
return sliceutil.SetUint64(commIds)
|
||||
}
|
||||
|
||||
func (r *Service) attesterCommitteeIndices(currentSlot uint64) []uint64 {
|
||||
func (r *Service) attesterSubnetIndices(currentSlot uint64) []uint64 {
|
||||
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
||||
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||
commIds := []uint64{}
|
||||
for i := currentSlot; i <= endSlot; i++ {
|
||||
commIds = append(commIds, cache.CommitteeIDs.GetAttesterCommitteeIDs(i)...)
|
||||
commIds = append(commIds, cache.SubnetIDs.GetAttesterSubnetIDs(i)...)
|
||||
}
|
||||
return sliceutil.SetUint64(commIds)
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func TestService_committeeIndexBeaconAttestationSubscriber_ValidMessage(t *testi
|
||||
}
|
||||
att.Signature = sKeys[16].Sign(attRoot[:]).Marshal()
|
||||
|
||||
p.ReceivePubSub("/eth2/%x/committee_index0_beacon_attestation", att)
|
||||
p.ReceivePubSub("/eth2/%x/beacon_attestation_0", att)
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
@@ -108,7 +107,7 @@ func (r *Service) validateAggregatedAtt(ctx context.Context, signed *ethpb.Signe
|
||||
}
|
||||
}
|
||||
|
||||
// Verify validator index is within the aggregate's committee.
|
||||
// Verify validator index is within the beacon committee.
|
||||
if err := validateIndexInCommittee(ctx, s, signed.Message.Aggregate, signed.Message.AggregatorIndex); err != nil {
|
||||
traceutil.AnnotateError(span, errors.Wrapf(err, "Could not validate index in committee"))
|
||||
return pubsub.ValidationReject
|
||||
@@ -169,7 +168,7 @@ func (r *Service) setAggregatorIndexEpochSeen(epoch uint64, aggregatorIndex uint
|
||||
r.seenAttestationCache.Add(string(b), true)
|
||||
}
|
||||
|
||||
// This validates the aggregator's index in state is within the attesting indices of the attestation.
|
||||
// This validates the aggregator's index in state is within the beacon committee.
|
||||
func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *ethpb.Attestation, validatorIndex uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "sync.validateIndexInCommittee")
|
||||
defer span.End()
|
||||
@@ -178,9 +177,8 @@ func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attestingIndices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
var withinCommittee bool
|
||||
for _, i := range attestingIndices {
|
||||
for _, i := range committee {
|
||||
if validatorIndex == i {
|
||||
withinCommittee = true
|
||||
break
|
||||
@@ -188,7 +186,7 @@ func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *
|
||||
}
|
||||
if !withinCommittee {
|
||||
return fmt.Errorf("validator index %d is not within the committee: %v",
|
||||
validatorIndex, attestingIndices)
|
||||
validatorIndex, committee)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -65,6 +65,37 @@ func TestVerifyIndexInCommittee_CanVerify(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyIndexInCommittee_ExistsInBeaconCommittee(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
params.UseMinimalConfig()
|
||||
defer params.UseMainnetConfig()
|
||||
|
||||
validators := uint64(64)
|
||||
s, _ := testutil.DeterministicGenesisState(t, validators)
|
||||
if err := s.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bf := []byte{0xff}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AggregationBits: bf}
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(s, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err := validateIndexInCommittee(ctx, s, att, committee[0]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wanted := "validator index 1000 is not within the committee"
|
||||
if err := validateIndexInCommittee(ctx, s, att, 1000); err == nil || !strings.Contains(err.Error(), wanted) {
|
||||
t.Error("Did not receive wanted error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySelection_NotAnAggregator(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
params.UseMinimalConfig()
|
||||
@@ -400,11 +431,11 @@ func TestValidateAggregateAndProofWithNewStateMgmt_CanValidate(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig := privKeys[33].Sign(slotRoot[:])
|
||||
sig := privKeys[22].Sign(slotRoot[:])
|
||||
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||
SelectionProof: sig.Marshal(),
|
||||
Aggregate: att,
|
||||
AggregatorIndex: 33,
|
||||
AggregatorIndex: 22,
|
||||
}
|
||||
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
||||
|
||||
@@ -416,7 +447,7 @@ func TestValidateAggregateAndProofWithNewStateMgmt_CanValidate(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
aggreSig := privKeys[33].Sign(signingRoot[:]).Marshal()
|
||||
aggreSig := privKeys[22].Sign(signingRoot[:]).Marshal()
|
||||
signedAggregateAndProof.Signature = aggreSig[:]
|
||||
|
||||
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||
@@ -524,11 +555,11 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig := privKeys[33].Sign(slotRoot[:])
|
||||
sig := privKeys[22].Sign(slotRoot[:])
|
||||
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||
SelectionProof: sig.Marshal(),
|
||||
Aggregate: att,
|
||||
AggregatorIndex: 33,
|
||||
AggregatorIndex: 22,
|
||||
}
|
||||
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
||||
|
||||
@@ -540,7 +571,7 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
aggreSig := privKeys[33].Sign(signingRoot[:]).Marshal()
|
||||
aggreSig := privKeys[22].Sign(signingRoot[:]).Marshal()
|
||||
signedAggregateAndProof.Signature = aggreSig[:]
|
||||
|
||||
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
|
||||
// Validation
|
||||
// - The attestation's committee index (attestation.data.index) is for the correct subnet.
|
||||
// - The attestation is unaggregated -- that is, it has exactly one participating validator (len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1).
|
||||
// - The attestation is unaggregated -- that is, it has exactly one participating validator (len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1).
|
||||
// - The block being voted for (attestation.data.beacon_block_root) passes validation.
|
||||
// - attestation.data.slot is within the last ATTESTATION_PROPAGATION_SLOT_RANGE slots (attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot).
|
||||
// - The signature of attestation is valid.
|
||||
@@ -57,6 +58,11 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
||||
if att.Data == nil {
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
// Attestation aggregation bits must exist.
|
||||
if att.AggregationBits == nil {
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
// Verify this the first attestation received for the participating validator for the slot.
|
||||
if s.hasSeenCommitteeIndicesSlot(att.Data.Slot, att.Data.CommitteeIndex, att.AggregationBits) {
|
||||
return pubsub.ValidationIgnore
|
||||
@@ -69,12 +75,34 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
||||
traceutil.AnnotateError(span, err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
if !strings.HasPrefix(originalTopic, fmt.Sprintf(format, digest, att.Data.CommitteeIndex)) {
|
||||
preState, err := s.chain.AttestationPreState(ctx, att)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to retrieve pre state")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
valCount, err := helpers.ActiveValidatorCount(preState, helpers.SlotToEpoch(att.Data.Slot))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not retrieve active validator count")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
subnet := helpers.ComputeSubnetForAttestation(valCount, att)
|
||||
|
||||
if !strings.HasPrefix(originalTopic, fmt.Sprintf(format, digest, subnet)) {
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(preState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
// Attestation must be unaggregated.
|
||||
if att.AggregationBits == nil || att.AggregationBits.Count() != 1 {
|
||||
// Attestation must be unaggregated and the bit index must exist in the range of committee indices.
|
||||
// Note: eth2 spec suggests (len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1)
|
||||
// however this validation can be achieved without use of get_attesting_indices which is an O(n) lookup.
|
||||
if att.AggregationBits.Count() != 1 || att.AggregationBits.BitIndices()[0] >= len(committee) {
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
@@ -95,12 +123,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
preState, err := s.chain.AttestationPreState(ctx, att)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to retrieve pre state")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
// Attestation's signature is a valid BLS signature and belongs to correct public key..
|
||||
if !featureconfig.Get().DisableStrictAttestationPubsubVerification {
|
||||
if err := blocks.VerifyAttestation(ctx, preState, att); err != nil {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user