mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Update to v0.12 (#5614)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||||
[](https://app.fuzzit.dev/orgs/prysmaticlabs-gh/dashboard)
|
[](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://discord.gg/KSA7rPr)
|
||||||
[](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](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"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
sha256 = "489f85d7c17a901b9069c95f656154fdf1385db00f3aeb3e0319aed8745f9453",
|
sha256 = "678c50336ce39bef19b2a0dc69e20a7bda37a673ae07dc0577386e9876e0a525",
|
||||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/general.tar.gz",
|
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/general.tar.gz",
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@@ -231,8 +231,8 @@ filegroup(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
sha256 = "b83000fbcb60b7a5b8c0e805f3fee6953b17bfe0fe6658416e7d99e6d261f284",
|
sha256 = "d0ce95a3ca0d30df24f96a1b5cfad1f7e6fcc07ad84ca221d92480add051af3e",
|
||||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/minimal.tar.gz",
|
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/minimal.tar.gz",
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@@ -247,8 +247,8 @@ filegroup(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
sha256 = "ae0c09ab49afa69085c91f9e2f2f4de6526d43b927609839b1597c674b4dccde",
|
sha256 = "1dfa1ae6822912508dbf6d1fe7608169372daa3ad1e53a3ed0867cb2d6e0ccb0",
|
||||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.3/mainnet.tar.gz",
|
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.1/mainnet.tar.gz",
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type HeadFetcher interface {
|
|||||||
HeadValidatorsIndices(epoch uint64) ([]uint64, error)
|
HeadValidatorsIndices(epoch uint64) ([]uint64, error)
|
||||||
HeadSeed(epoch uint64) ([32]byte, error)
|
HeadSeed(epoch uint64) ([32]byte, error)
|
||||||
HeadGenesisValidatorRoot() [32]byte
|
HeadGenesisValidatorRoot() [32]byte
|
||||||
|
HeadETH1Data() *ethpb.Eth1Data
|
||||||
ProtoArrayStore() *protoarray.Store
|
ProtoArrayStore() *protoarray.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +180,14 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte {
|
|||||||
return s.headGenesisValidatorRoot()
|
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.
|
// ProtoArrayStore returns the proto array store object.
|
||||||
func (s *Service) ProtoArrayStore() *protoarray.Store {
|
func (s *Service) ProtoArrayStore() *protoarray.Store {
|
||||||
return s.forkChoiceStore.Store()
|
return s.forkChoiceStore.Store()
|
||||||
|
|||||||
@@ -210,3 +210,24 @@ func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
|
|||||||
t.Error("Did not get correct genesis validator root")
|
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"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
"github.com/prysmaticlabs/go-ssz"
|
"github.com/prysmaticlabs/go-ssz"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
"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/helpers"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
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)
|
beaconState, privs := testutil.DeterministicGenesisState(t, 32)
|
||||||
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
genesisBlock := testutil.NewBeaconBlock()
|
||||||
bodyRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
bodyRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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))
|
// current_epoch = compute_epoch_at_slot(get_current_slot(store))
|
||||||
// # Use GENESIS_EPOCH for previous when genesis to avoid underflow
|
// # Use GENESIS_EPOCH for previous when genesis to avoid underflow
|
||||||
// previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else GENESIS_EPOCH
|
// 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 in [current_epoch, previous_epoch]
|
||||||
// assert target.epoch == compute_epoch_at_slot(attestation.data.slot)
|
// 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
|
// # 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
|
// 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
|
// # 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
|
// 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:
|
// for i in indexed_attestation.attesting_indices:
|
||||||
// if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch:
|
// 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)
|
// 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) {
|
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]uint64, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "blockchain.onAttestation")
|
ctx, span := trace.StartSpan(ctx, "blockchain.onAttestation")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@@ -83,7 +82,6 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
||||||
tgtSlot := helpers.StartSlot(tgt.Epoch)
|
|
||||||
|
|
||||||
if helpers.SlotToEpoch(a.Data.Slot) != a.Data.Target.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)
|
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
|
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.
|
// Verify attestation beacon block is known and not from the future.
|
||||||
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
|
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not verify attestation beacon block")
|
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.
|
// 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 {
|
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -143,6 +143,20 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
|||||||
return nil
|
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.
|
// verifyAttestation validates input attestation is valid.
|
||||||
func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.BeaconState, a *ethpb.Attestation) (*ethpb.IndexedAttestation, error) {
|
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)
|
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")
|
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:
|
// elif block.slot == slot:
|
||||||
// return root
|
// return root
|
||||||
// else:
|
// 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) {
|
func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byte, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "forkchoice.ancestor")
|
ctx, span := trace.StartSpan(ctx, "forkchoice.ancestor")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -230,13 +230,15 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
|||||||
if !update {
|
if !update {
|
||||||
t.Error("Should be able to update justified, received false")
|
t.Error("Should be able to update justified, received false")
|
||||||
}
|
}
|
||||||
|
lastJustifiedBlk := testutil.NewBeaconBlock()
|
||||||
lastJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: []byte{'G'}}}
|
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||||
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
|
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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)
|
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -271,12 +273,14 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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)
|
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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)
|
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -743,11 +747,14 @@ func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
|
|||||||
st := testutil.NewBeaconState()
|
st := testutil.NewBeaconState()
|
||||||
|
|
||||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
|
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
|
||||||
b.Body = ðpb.BeaconBlockBody{}
|
beaconBlock := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
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
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
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/event"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
@@ -64,6 +65,11 @@ func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mb *mockBroadcaster) BroadcastAttestation(_ context.Context, _ uint64, _ *ethpb.Attestation) error {
|
||||||
|
mb.broadcastCalled = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ = p2p.Broadcaster(&mockBroadcaster{})
|
var _ = p2p.Broadcaster(&mockBroadcaster{})
|
||||||
|
|
||||||
func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||||
@@ -186,7 +192,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
|||||||
|
|
||||||
chainService := setupBeaconChain(t, db)
|
chainService := setupBeaconChain(t, db)
|
||||||
|
|
||||||
genesisBlk := b.NewGenesisBlock([]byte{})
|
genesisBlk := testutil.NewBeaconBlock()
|
||||||
blkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
|
blkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -283,7 +289,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
|||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
genesis := b.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -296,7 +302,9 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
|
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()
|
headState := testutil.NewBeaconState()
|
||||||
if err := headState.SetSlot(finalizedSlot); err != nil {
|
if err := headState.SetSlot(finalizedSlot); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -323,9 +331,6 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := db.SaveBlock(ctx, headBlock); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
c := &Service{beaconDB: db, stateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
c := &Service{beaconDB: db, stateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
||||||
if err := c.initializeChainInfo(ctx); err != nil {
|
if err := c.initializeChainInfo(ctx); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type ChainService struct {
|
|||||||
Genesis time.Time
|
Genesis time.Time
|
||||||
ValidatorsRoot [32]byte
|
ValidatorsRoot [32]byte
|
||||||
Fork *pb.Fork
|
Fork *pb.Fork
|
||||||
|
ETH1Data *ethpb.Eth1Data
|
||||||
DB db.Database
|
DB db.Database
|
||||||
stateNotifier statefeed.Notifier
|
stateNotifier statefeed.Notifier
|
||||||
blockNotifier blockfeed.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)
|
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.
|
// ProtoArrayStore mocks the same method in the chain service.
|
||||||
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
|
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
|
||||||
return ms.ForkChoiceStore
|
return ms.ForkChoiceStore
|
||||||
@@ -252,6 +258,12 @@ func (ms *ChainService) IsValidAttestation(ctx context.Context, att *ethpb.Attes
|
|||||||
return ms.ValidAttestation
|
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.
|
// ClearCachedStates does nothing.
|
||||||
func (ms *ChainService) ClearCachedStates() {}
|
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",
|
"attestation_data.go",
|
||||||
"checkpoint_state.go",
|
"checkpoint_state.go",
|
||||||
"committee.go",
|
"committee.go",
|
||||||
"committee_ids.go",
|
|
||||||
"common.go",
|
"common.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"hot_state_cache.go",
|
"hot_state_cache.go",
|
||||||
"skip_slot_cache.go",
|
"skip_slot_cache.go",
|
||||||
"state_summary.go",
|
"state_summary.go",
|
||||||
|
"subnet_ids.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
|
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
|
||||||
visibility = [
|
visibility = [
|
||||||
@@ -44,11 +44,11 @@ go_test(
|
|||||||
"attestation_data_test.go",
|
"attestation_data_test.go",
|
||||||
"checkpoint_state_test.go",
|
"checkpoint_state_test.go",
|
||||||
"committee_fuzz_test.go",
|
"committee_fuzz_test.go",
|
||||||
"committee_ids_test.go",
|
|
||||||
"committee_test.go",
|
"committee_test.go",
|
||||||
"feature_flag_test.go",
|
"feature_flag_test.go",
|
||||||
"hot_state_cache_test.go",
|
"hot_state_cache_test.go",
|
||||||
"skip_slot_cache_test.go",
|
"skip_slot_cache_test.go",
|
||||||
|
"subnet_ids_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type committeeIDs struct {
|
type subnetIDs struct {
|
||||||
attester *lru.Cache
|
attester *lru.Cache
|
||||||
attesterLock sync.RWMutex
|
attesterLock sync.RWMutex
|
||||||
aggregator *lru.Cache
|
aggregator *lru.Cache
|
||||||
@@ -19,10 +19,10 @@ type committeeIDs struct {
|
|||||||
subnetsLock sync.RWMutex
|
subnetsLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitteeIDs for attester and aggregator.
|
// SubnetIDs for attester and aggregator.
|
||||||
var CommitteeIDs = newCommitteeIDs()
|
var SubnetIDs = newSubnetIDs()
|
||||||
|
|
||||||
func newCommitteeIDs() *committeeIDs {
|
func newSubnetIDs() *subnetIDs {
|
||||||
// Given a node can calculate committee assignments of current epoch and next epoch.
|
// Given a node can calculate committee assignments of current epoch and next epoch.
|
||||||
// Max size is set to 2 epoch length.
|
// Max size is set to 2 epoch length.
|
||||||
cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2)
|
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)
|
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot)
|
||||||
subLength := epochDuration * time.Duration(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
subLength := epochDuration * time.Duration(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
||||||
persistentCache := cache.New(subLength*time.Second, epochDuration*time.Second)
|
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.
|
// AddAttesterSubnetID adds the subnet index for subscribing subnet for the attester of a given slot.
|
||||||
func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
|
func (c *subnetIDs) AddAttesterSubnetID(slot uint64, subnetID uint64) {
|
||||||
c.attesterLock.Lock()
|
c.attesterLock.Lock()
|
||||||
defer c.attesterLock.Unlock()
|
defer c.attesterLock.Unlock()
|
||||||
|
|
||||||
ids := []uint64{committeeID}
|
ids := []uint64{subnetID}
|
||||||
val, exists := c.attester.Get(slot)
|
val, exists := c.attester.Get(slot)
|
||||||
if exists {
|
if exists {
|
||||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||||
@@ -53,8 +53,8 @@ func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
|
|||||||
c.attester.Add(slot, ids)
|
c.attester.Add(slot, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot.
|
// GetAttesterSubnetIDs gets the subnet IDs for subscribed subnets for attesters of the slot.
|
||||||
func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
|
func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
|
||||||
c.attesterLock.RLock()
|
c.attesterLock.RLock()
|
||||||
defer c.attesterLock.RUnlock()
|
defer c.attesterLock.RUnlock()
|
||||||
|
|
||||||
@@ -68,12 +68,12 @@ func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAggregatorCommiteeID adds committee ID for subscribing subnet for the aggregator of a given slot.
|
// AddAggregatorSubnetID adds the subnet ID for subscribing subnet for the aggregator of a given slot.
|
||||||
func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) {
|
func (c *subnetIDs) AddAggregatorSubnetID(slot uint64, subnetID uint64) {
|
||||||
c.aggregatorLock.Lock()
|
c.aggregatorLock.Lock()
|
||||||
defer c.aggregatorLock.Unlock()
|
defer c.aggregatorLock.Unlock()
|
||||||
|
|
||||||
ids := []uint64{committeeID}
|
ids := []uint64{subnetID}
|
||||||
val, exists := c.aggregator.Get(slot)
|
val, exists := c.aggregator.Get(slot)
|
||||||
if exists {
|
if exists {
|
||||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||||
@@ -81,8 +81,8 @@ func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64)
|
|||||||
c.aggregator.Add(slot, ids)
|
c.aggregator.Add(slot, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot.
|
// GetAggregatorSubnetIDs gets the subnet IDs for subscribing subnet for aggregator of the slot.
|
||||||
func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
|
func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
|
||||||
c.aggregatorLock.RLock()
|
c.aggregatorLock.RLock()
|
||||||
defer c.aggregatorLock.RUnlock()
|
defer c.aggregatorLock.RUnlock()
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
|
|||||||
return val.([]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.
|
// subscription.
|
||||||
func (c *committeeIDs) GetPersistentCommittees(pubkey []byte) ([]uint64, bool, time.Time) {
|
func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
|
||||||
c.subnetsLock.RLock()
|
c.subnetsLock.RLock()
|
||||||
defer c.subnetsLock.RUnlock()
|
defer c.subnetsLock.RUnlock()
|
||||||
|
|
||||||
@@ -106,9 +106,9 @@ func (c *committeeIDs) GetPersistentCommittees(pubkey []byte) ([]uint64, bool, t
|
|||||||
return id.([]uint64), ok, duration
|
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.
|
// in the cache.
|
||||||
func (c *committeeIDs) GetAllCommittees() []uint64 {
|
func (c *subnetIDs) GetAllSubnets() []uint64 {
|
||||||
c.subnetsLock.RLock()
|
c.subnetsLock.RLock()
|
||||||
defer c.subnetsLock.RUnlock()
|
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
|
// AddPersistentCommittee adds the relevant committee for that particular validator along with its
|
||||||
// expiration period.
|
// 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()
|
c.subnetsLock.Lock()
|
||||||
defer c.subnetsLock.Unlock()
|
defer c.subnetsLock.Unlock()
|
||||||
|
|
||||||
@@ -5,59 +5,59 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommitteeIDCache_RoundTrip(t *testing.T) {
|
func TestSubnetIDsCache_RoundTrip(t *testing.T) {
|
||||||
c := newCommitteeIDs()
|
c := newSubnetIDs()
|
||||||
slot := uint64(100)
|
slot := uint64(100)
|
||||||
committeeIDs := c.GetAggregatorCommitteeIDs(slot)
|
committeeIDs := c.GetAggregatorSubnetIDs(slot)
|
||||||
if len(committeeIDs) != 0 {
|
if len(committeeIDs) != 0 {
|
||||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAggregatorCommiteeID(slot, 1)
|
c.AddAggregatorSubnetID(slot, 1)
|
||||||
res := c.GetAggregatorCommitteeIDs(slot)
|
res := c.GetAggregatorSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{1}) {
|
if !reflect.DeepEqual(res, []uint64{1}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAggregatorCommiteeID(slot, 2)
|
c.AddAggregatorSubnetID(slot, 2)
|
||||||
res = c.GetAggregatorCommitteeIDs(slot)
|
res = c.GetAggregatorSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{1, 2}) {
|
if !reflect.DeepEqual(res, []uint64{1, 2}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAggregatorCommiteeID(slot, 3)
|
c.AddAggregatorSubnetID(slot, 3)
|
||||||
res = c.GetAggregatorCommitteeIDs(slot)
|
res = c.GetAggregatorSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{1, 2, 3}) {
|
if !reflect.DeepEqual(res, []uint64{1, 2, 3}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
committeeIDs = c.GetAttesterCommitteeIDs(slot)
|
committeeIDs = c.GetAttesterSubnetIDs(slot)
|
||||||
if len(committeeIDs) != 0 {
|
if len(committeeIDs) != 0 {
|
||||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAttesterCommiteeID(slot, 11)
|
c.AddAttesterSubnetID(slot, 11)
|
||||||
res = c.GetAttesterCommitteeIDs(slot)
|
res = c.GetAttesterSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{11}) {
|
if !reflect.DeepEqual(res, []uint64{11}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAttesterCommiteeID(slot, 22)
|
c.AddAttesterSubnetID(slot, 22)
|
||||||
res = c.GetAttesterCommitteeIDs(slot)
|
res = c.GetAttesterSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{11, 22}) {
|
if !reflect.DeepEqual(res, []uint64{11, 22}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddAttesterCommiteeID(slot, 33)
|
c.AddAttesterSubnetID(slot, 33)
|
||||||
res = c.GetAttesterCommitteeIDs(slot)
|
res = c.GetAttesterSubnetIDs(slot)
|
||||||
if !reflect.DeepEqual(res, []uint64{11, 22, 33}) {
|
if !reflect.DeepEqual(res, []uint64{11, 22, 33}) {
|
||||||
t.Error("Expected equal value to return from cache")
|
t.Error("Expected equal value to return from cache")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
func TestSubnetIDsCache_PersistentCommitteeRoundtrip(t *testing.T) {
|
||||||
pubkeySet := [][48]byte{}
|
pubkeySet := [][48]byte{}
|
||||||
c := newCommitteeIDs()
|
c := newSubnetIDs()
|
||||||
|
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
pubkey := [48]byte{byte(i)}
|
pubkey := [48]byte{byte(i)}
|
||||||
@@ -68,7 +68,7 @@ func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
|||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
pubkey := [48]byte{byte(i)}
|
pubkey := [48]byte{byte(i)}
|
||||||
|
|
||||||
idxs, ok, _ := c.GetPersistentCommittees(pubkey[:])
|
idxs, ok, _ := c.GetPersistentSubnets(pubkey[:])
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Couldn't find entry in cache for pubkey %#x", pubkey)
|
t.Errorf("Couldn't find entry in cache for pubkey %#x", pubkey)
|
||||||
continue
|
continue
|
||||||
@@ -77,7 +77,7 @@ func TestCommitteeIDs_PersistentCommitteeRoundtrip(t *testing.T) {
|
|||||||
t.Fatalf("Wanted index of %d but got %d", i, idxs[0])
|
t.Fatalf("Wanted index of %d but got %d", i, idxs[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coms := c.GetAllCommittees()
|
coms := c.GetAllSubnets()
|
||||||
if len(coms) != 20 {
|
if len(coms) != 20 {
|
||||||
t.Errorf("Number of committees is not %d but is %d", 20, len(coms))
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not get signing root")
|
return errors.Wrap(err, "could not get signing root")
|
||||||
}
|
}
|
||||||
sigRoot := &pb.SigningRoot{
|
signingData := &pb.SigningData{
|
||||||
ObjectRoot: root[:],
|
ObjectRoot: root[:],
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
}
|
}
|
||||||
ctrRoot, err := ssz.HashTreeRoot(sigRoot)
|
ctrRoot, err := ssz.HashTreeRoot(signingData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not get container root")
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not convert bytes to signature")
|
return errors.Wrap(err, "could not convert bytes to signature")
|
||||||
}
|
}
|
||||||
ctr := &pb.SigningRoot{
|
signingData := &pb.SigningData{
|
||||||
ObjectRoot: signedData,
|
ObjectRoot: signedData,
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
}
|
}
|
||||||
root, err := ssz.HashTreeRoot(ctr)
|
root, err := ssz.HashTreeRoot(signingData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not hash container")
|
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)
|
return fmt.Errorf("expected current epoch >= exit epoch, received %d < %d", currentEpoch, exit.Epoch)
|
||||||
}
|
}
|
||||||
// Verify the validator has been active long enough.
|
// 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(
|
return fmt.Errorf(
|
||||||
"validator has not been active long enough to exit, wanted epoch %d >= %d",
|
"validator has not been active long enough to exit, wanted epoch %d >= %d",
|
||||||
currentEpoch,
|
currentEpoch,
|
||||||
validator.ActivationEpoch()+params.BeaconConfig().PersistentCommitteePeriod,
|
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
|
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
|
||||||
|
|||||||
@@ -433,7 +433,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -2018,7 +2018,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ go_test(
|
|||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
"//proto/beacon/p2p/v1:go_default_library",
|
"//proto/beacon/p2p/v1:go_default_library",
|
||||||
"//shared/attestationutil:go_default_library",
|
"//shared/attestationutil:go_default_library",
|
||||||
|
"//shared/mathutil:go_default_library",
|
||||||
"//shared/params:go_default_library",
|
"//shared/params:go_default_library",
|
||||||
"//shared/testutil:go_default_library",
|
"//shared/testutil:go_default_library",
|
||||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
@@ -90,6 +91,7 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
|
|||||||
votedTarget = true
|
votedTarget = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if votedTarget {
|
||||||
same, err = SameHead(s, a)
|
same, err = SameHead(s, a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, false, false, errors.Wrap(err, "could not check same head")
|
return false, false, false, errors.Wrap(err, "could not check same head")
|
||||||
@@ -98,6 +100,7 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
|
|||||||
votedHead = true
|
votedHead = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return votedPrevEpoch, votedTarget, votedHead, nil
|
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
|
return bBal
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,21 +50,23 @@ func TestUpdateValidator_InclusionOnlyCountsPrevEpoch(t *testing.T) {
|
|||||||
|
|
||||||
func TestUpdateBalance(t *testing.T) {
|
func TestUpdateBalance(t *testing.T) {
|
||||||
vp := []*precompute.Validator{
|
vp := []*precompute.Validator{
|
||||||
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsCurrentEpochTargetAttester: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsCurrentEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsPrevEpochAttester: true, IsPrevEpochHeadAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100},
|
{IsSlashed: true, IsCurrentEpochAttester: true, CurrentEpochEffectiveBalance: 100 * params.BeaconConfig().EffectiveBalanceIncrement},
|
||||||
}
|
}
|
||||||
wantedPBal := &precompute.Balance{
|
wantedPBal := &precompute.Balance{
|
||||||
CurrentEpochAttested: 200,
|
ActiveCurrentEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
CurrentEpochTargetAttested: 200,
|
ActivePrevEpoch: params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
PrevEpochAttested: 300,
|
CurrentEpochAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
PrevEpochTargetAttested: 100,
|
CurrentEpochTargetAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
PrevEpochHeadAttested: 200,
|
PrevEpochAttested: 300 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
|
PrevEpochTargetAttested: 100 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
|
PrevEpochHeadAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||||
}
|
}
|
||||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{})
|
pBal := precompute.UpdateBalance(vp, &precompute.Balance{})
|
||||||
if !reflect.DeepEqual(pBal, wantedPBal) {
|
if !reflect.DeepEqual(pBal, wantedPBal) {
|
||||||
@@ -220,7 +222,7 @@ func TestProcessAttestations(t *testing.T) {
|
|||||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
att2.Data.Target.Root = rt[:]
|
att2.Data.Target.Root = newRt[:]
|
||||||
att2.Data.BeaconBlockRoot = newRt[:]
|
att2.Data.BeaconBlockRoot = newRt[:]
|
||||||
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
|
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -260,8 +262,37 @@ func TestProcessAttestations(t *testing.T) {
|
|||||||
if !pVals[i].IsPrevEpochAttester {
|
if !pVals[i].IsPrevEpochAttester {
|
||||||
t.Error("Not a prev epoch attester")
|
t.Error("Not a prev epoch attester")
|
||||||
}
|
}
|
||||||
|
if !pVals[i].IsPrevEpochTargetAttester {
|
||||||
|
t.Error("Not a prev epoch target attester")
|
||||||
|
}
|
||||||
if !pVals[i].IsPrevEpochHeadAttester {
|
if !pVals[i].IsPrevEpochHeadAttester {
|
||||||
t.Error("Not a prev epoch head attester")
|
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 {
|
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||||
// Was validator withdrawable or slashed
|
// Was validator withdrawable or slashed
|
||||||
withdrawable := currentEpoch >= val.WithdrawableEpoch()
|
withdrawable := prevEpoch+1 >= val.WithdrawableEpoch()
|
||||||
pVal := &Validator{
|
pVal := &Validator{
|
||||||
IsSlashed: val.Slashed(),
|
IsSlashed: val.Slashed(),
|
||||||
IsWithdrawableCurrentEpoch: withdrawable,
|
IsWithdrawableCurrentEpoch: withdrawable,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package precompute
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
"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")
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
return nil, errors.Wrap(err, "could not get attestation delta")
|
||||||
}
|
}
|
||||||
|
validatorBals := state.Balances()
|
||||||
for i := 0; i < numOfVals; i++ {
|
for i := 0; i < numOfVals; i++ {
|
||||||
vp[i].BeforeEpochTransitionBalance, err = state.BalanceAtIndex(uint64(i))
|
vp[i].BeforeEpochTransitionBalance = validatorBals[i]
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not get validator balance before epoch")
|
// 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 = validatorBals[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := helpers.IncreaseBalance(state, uint64(i), attsRewards[i]+proposerRewards[i]); err != nil {
|
if err := state.SetBalances(validatorBals); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "could not set validator balances")
|
||||||
}
|
|
||||||
if err := helpers.DecreaseBalance(state, uint64(i), attsPenalties[i]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vp[i].AfterEpochTransitionBalance, err = state.BalanceAtIndex(uint64(i))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not get validator balance after epoch")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return state, nil
|
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.
|
// 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()
|
numOfVals := state.NumValidators()
|
||||||
rewards := make([]uint64, numOfVals)
|
rewards := make([]uint64, numOfVals)
|
||||||
penalties := make([]uint64, numOfVals)
|
penalties := make([]uint64, numOfVals)
|
||||||
|
prevEpoch := helpers.PrevEpoch(state)
|
||||||
|
finalizedEpoch := state.FinalizedCheckpointEpoch()
|
||||||
|
|
||||||
for i, v := range vp {
|
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
|
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)
|
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||||
if !eligible || pBal.ActiveCurrentEpoch == 0 {
|
if !eligible || pBal.ActiveCurrentEpoch == 0 {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
e := helpers.PrevEpoch(state)
|
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
||||||
|
effectiveBalanceIncrement := params.BeaconConfig().EffectiveBalanceIncrement
|
||||||
vb := v.CurrentEpochEffectiveBalance
|
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)
|
r, p := uint64(0), uint64(0)
|
||||||
|
currentEpochBalance := pBal.ActiveCurrentEpoch / effectiveBalanceIncrement
|
||||||
|
|
||||||
// Process source reward / penalty
|
// Process source reward / penalty
|
||||||
if v.IsPrevEpochAttester && !v.IsSlashed {
|
if v.IsPrevEpochAttester && !v.IsSlashed {
|
||||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
|
||||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
|
||||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
|
||||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||||
maxAtteserReward := br - proposerReward
|
maxAttesterReward := br - proposerReward
|
||||||
r += maxAtteserReward / v.InclusionDistance
|
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 {
|
} else {
|
||||||
p += br
|
p += br
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process target reward / penalty
|
// Process target reward / penalty
|
||||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
// optimal participation receives full base reward compensation here.
|
||||||
|
r += br
|
||||||
|
} else {
|
||||||
|
rewardNumerator := br * (pBal.PrevEpochTargetAttested / effectiveBalanceIncrement)
|
||||||
|
r += rewardNumerator / currentEpochBalance
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p += br
|
p += br
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process head reward / penalty
|
// Process head reward / penalty
|
||||||
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
|
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
|
||||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||||
rewardNumerator := br * pBal.PrevEpochAttested / inc
|
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||||
r += rewardNumerator / (pBal.ActiveCurrentEpoch / inc)
|
// optimal participation receives full base reward compensation here.
|
||||||
|
r += br
|
||||||
|
} else {
|
||||||
|
rewardNumerator := br * (pBal.PrevEpochHeadAttested / effectiveBalanceIncrement)
|
||||||
|
r += rewardNumerator / currentEpochBalance
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p += br
|
p += br
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process finality delay penalty
|
// Process finality delay penalty
|
||||||
finalizedEpoch := state.FinalizedCheckpointEpoch()
|
finalityDelay := finalityDelay(prevEpoch, finalizedEpoch)
|
||||||
finalityDelay := e - finalizedEpoch
|
|
||||||
if finalityDelay > params.BeaconConfig().MinEpochsToInactivityPenalty {
|
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||||
p += params.BeaconConfig().BaseRewardsPerEpoch * br
|
// If validator is performing optimally, this cancels all rewards for a neutral balance.
|
||||||
if !v.IsPrevEpochTargetAttester {
|
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
|
p += vb * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r, p
|
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.
|
// 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()
|
numofVals := state.NumValidators()
|
||||||
rewards := make([]uint64, numofVals)
|
rewards := make([]uint64, numofVals)
|
||||||
|
|
||||||
totalBalance := pBal.ActiveCurrentEpoch
|
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
|
baseRewardFactor := params.BeaconConfig().BaseRewardFactor
|
||||||
balanceSqrt := mathutil.IntegerSquareRoot(totalBalance)
|
|
||||||
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
||||||
proposerRewardQuotient := params.BeaconConfig().ProposerRewardQuotient
|
proposerRewardQuotient := params.BeaconConfig().ProposerRewardQuotient
|
||||||
for _, v := range vp {
|
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
|
vBalance := v.CurrentEpochEffectiveBalance
|
||||||
baseReward := vBalance * baseRewardFactor / balanceSqrt / baseRewardsPerEpoch
|
baseReward := vBalance * baseRewardFactor / balanceSqrt / baseRewardsPerEpoch
|
||||||
proposerReward := baseReward / proposerRewardQuotient
|
proposerReward := baseReward / proposerRewardQuotient
|
||||||
@@ -145,3 +172,21 @@ func proposerDeltaPrecompute(state *stateTrie.BeaconState, pBal *Balance, vp []*
|
|||||||
}
|
}
|
||||||
return rewards, nil
|
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/core/helpers"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,6 +91,14 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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)
|
vp, bp, err := New(context.Background(), state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,7 +109,11 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -113,18 +126,21 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
attestedIndices := []uint64{55, 1339, 1746, 1811, 1569, 1413}
|
attestedIndices := []uint64{55, 1339, 1746, 1811, 1569}
|
||||||
for _, i := range attestedIndices {
|
for _, i := range attestedIndices {
|
||||||
base, err := epoch.BaseReward(state, i)
|
base, err := epoch.BaseReward(state, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Could not get base reward: %v", err)
|
t.Errorf("Could not get base reward: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base rewards for getting source right
|
// 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
|
// Base rewards for proposer and attesters working together getting attestation
|
||||||
// on chain in the fatest manner
|
// on chain in the fatest manner
|
||||||
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
||||||
wanted += (base - proposerReward) * params.BeaconConfig().MinAttestationInclusionDelay
|
wanted += (base-proposerReward)*params.BeaconConfig().MinAttestationInclusionDelay - 1
|
||||||
if rewards[i] != wanted {
|
if rewards[i] != wanted {
|
||||||
t.Errorf("Wanted reward balance %d, got %d for validator with index %d", wanted, rewards[i], i)
|
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}
|
nonAttestedIndices := []uint64{434, 677, 872, 791}
|
||||||
for _, i := range nonAttestedIndices {
|
for _, i := range nonAttestedIndices {
|
||||||
base, err := epoch.BaseReward(state, i)
|
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.
|
pBal.ActiveCurrentEpoch = 0 // Could cause a divide by zero panic.
|
||||||
|
|
||||||
_, _, err = attestationDeltas(state, pBal, pVals)
|
_, _, err = AttestationsDelta(state, pBal, pVals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
|
||||||
validators := make([]*ethpb.Validator, validatorCount)
|
validators := make([]*ethpb.Validator, validatorCount)
|
||||||
for i := 0; i < len(validators); i++ {
|
for i := 0; i < len(validators); i++ {
|
||||||
@@ -234,3 +330,133 @@ func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
|
|||||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{},
|
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 {
|
func IsAggregated(attestation *ethpb.Attestation) bool {
|
||||||
return attestation.AggregationBits.Count() > 1
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
@@ -348,3 +349,53 @@ func TestAggregateSignature_False(t *testing.T) {
|
|||||||
t.Error("Signature not suppose to verify")
|
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 {
|
if err != nil {
|
||||||
return err
|
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.
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if delta > balAtIdx {
|
return state.UpdateBalancesAtIndex(idx, DecreaseBalanceWithVal(balAtIdx, delta))
|
||||||
return state.UpdateBalancesAtIndex(idx, 0)
|
|
||||||
}
|
}
|
||||||
return state.UpdateBalancesAtIndex(idx, 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.
|
// failed to verify.
|
||||||
var ErrSigFailedToVerify = errors.New("signature did not 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:
|
// Spec pseudocode definition:
|
||||||
// def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
|
// 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),
|
// object_root=hash_tree_root(ssz_object),
|
||||||
// domain=domain,
|
// domain=domain,
|
||||||
// )
|
// ))
|
||||||
// return hash_tree_root(domain_wrapped_object)
|
|
||||||
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
||||||
return signingRoot(func() ([32]byte, error) {
|
return signingData(func() ([32]byte, error) {
|
||||||
switch object.(type) {
|
switch object.(type) {
|
||||||
case *ethpb.BeaconBlock:
|
case *ethpb.BeaconBlock:
|
||||||
return stateutil.BlockRoot(object.(*ethpb.BeaconBlock))
|
return stateutil.BlockRoot(object.(*ethpb.BeaconBlock))
|
||||||
@@ -48,14 +47,14 @@ func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
|||||||
}, domain)
|
}, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the signing root by utilising the provided root function and then
|
// Computes the signing data by utilising the provided root function and then
|
||||||
// returning the signing root of the container object.
|
// returning the signing data of the container object.
|
||||||
func signingRoot(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, error) {
|
func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, error) {
|
||||||
objRoot, err := rootFunc()
|
objRoot, err := rootFunc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return [32]byte{}, err
|
return [32]byte{}, err
|
||||||
}
|
}
|
||||||
container := &p2ppb.SigningRoot{
|
container := &p2ppb.SigningData{
|
||||||
ObjectRoot: objRoot[:],
|
ObjectRoot: objRoot[:],
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
}
|
}
|
||||||
@@ -92,7 +91,7 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub []byte, signature []byte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not convert bytes to signature")
|
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
|
// utilize custom block hashing function
|
||||||
return stateutil.BlockRoot(blk)
|
return stateutil.BlockRoot(blk)
|
||||||
}, domain)
|
}, domain)
|
||||||
@@ -115,7 +114,7 @@ func VerifyBlockHeaderSigningRoot(blkHdr *ethpb.BeaconBlockHeader, pub []byte, s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not convert bytes to signature")
|
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)
|
return stateutil.BlockHeaderRoot(blkHdr)
|
||||||
}, domain)
|
}, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func TestSigningRoot_Compatibility(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
newRoot, err := signingRoot(func() ([32]byte, error) {
|
newRoot, err := signingData(func() ([32]byte, error) {
|
||||||
return stateutil.BlockRoot(blk)
|
return stateutil.BlockRoot(blk)
|
||||||
}, params.BeaconConfig().DomainBeaconProposer[:])
|
}, params.BeaconConfig().DomainBeaconProposer[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ go_test(
|
|||||||
"transition_fuzz_test.go",
|
"transition_fuzz_test.go",
|
||||||
"transition_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"],
|
embed = [":go_default_library"],
|
||||||
shard_count = 3,
|
shard_count = 3,
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
var runAmount = 25
|
var runAmount = 25
|
||||||
|
|
||||||
func TestBenchmarkExecuteStateTransition(t *testing.T) {
|
func TestExecuteStateTransition_FullBlock(t *testing.T) {
|
||||||
benchutil.SetBenchmarkConfig()
|
benchutil.SetBenchmarkConfig()
|
||||||
beaconState, err := benchutil.PreGenState1Epoch()
|
beaconState, err := benchutil.PreGenState1Epoch()
|
||||||
if err != nil {
|
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(),
|
Eth1DepositIndex: preState.Eth1DepositIndex(),
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyRoot, err := ssz.HashTreeRoot(ðpb.BeaconBlockBody{})
|
bodyRoot, err := stateutil.BlockBodyRoot(ðpb.BeaconBlockBody{})
|
||||||
if err != nil {
|
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{
|
state.LatestBlockHeader = ðpb.BeaconBlockHeader{
|
||||||
|
|||||||
@@ -92,9 +92,18 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
|||||||
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
||||||
t.Fatal(err)
|
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.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
ProposerIndex: 74,
|
ProposerIndex: proposerIdx,
|
||||||
Slot: beaconState.Slot() + 1,
|
Slot: beaconState.Slot() + 1,
|
||||||
ParentRoot: parentRoot[:],
|
ParentRoot: parentRoot[:],
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
@@ -371,7 +380,7 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
|||||||
|
|
||||||
proposerSlashIdx := uint64(3)
|
proposerSlashIdx := uint64(3)
|
||||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -754,7 +763,7 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
ctr := &pb.SigningRoot{
|
ctr := &pb.SigningData{
|
||||||
ObjectRoot: buf,
|
ObjectRoot: buf,
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
}
|
}
|
||||||
@@ -902,9 +911,17 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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{
|
blk := ðpb.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
ProposerIndex: 156,
|
ProposerIndex: proposerIdx,
|
||||||
Slot: s.Slot() + 1,
|
Slot: s.Slot() + 1,
|
||||||
ParentRoot: parentRoot[:],
|
ParentRoot: parentRoot[:],
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package kv
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -10,7 +9,9 @@ import (
|
|||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"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/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
||||||
@@ -22,7 +23,7 @@ func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
|||||||
prevBlock := ðpb.SignedBeaconBlock{
|
prevBlock := ðpb.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: slot - 1,
|
Slot: slot - 1,
|
||||||
ParentRoot: []byte{1, 2, 3},
|
ParentRoot: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := db.SaveBlock(ctx, prevBlock); err != nil {
|
if err := db.SaveBlock(ctx, prevBlock); err != nil {
|
||||||
@@ -31,7 +32,7 @@ func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
|||||||
block := ðpb.SignedBeaconBlock{
|
block := ðpb.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: slot,
|
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
|
// 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.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: 20,
|
Slot: 20,
|
||||||
ParentRoot: []byte{1, 2, 3},
|
ParentRoot: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockRoot, err := stateutil.BlockRoot(block.Block)
|
blockRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
@@ -97,18 +98,15 @@ func TestStore_BlocksCRUD(t *testing.T) {
|
|||||||
func TestStore_BlocksBatchDelete(t *testing.T) {
|
func TestStore_BlocksBatchDelete(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
numBlocks := 1000
|
numBlocks := 10
|
||||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
||||||
blockRoots := make([][32]byte, 0)
|
blockRoots := make([][32]byte, 0)
|
||||||
oddBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
oddBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
||||||
for i := 0; i < len(totalBlocks); i++ {
|
for i := 0; i < len(totalBlocks); i++ {
|
||||||
totalBlocks[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
Slot: uint64(i),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
ParentRoot: []byte("parent"),
|
totalBlocks[i] = b
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -122,7 +120,7 @@ func TestStore_BlocksBatchDelete(t *testing.T) {
|
|||||||
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -134,27 +132,25 @@ func TestStore_BlocksBatchDelete(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
// When we retrieve the data, only the odd indexed blocks should remain.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
sort.Slice(retrieved, func(i, j int) bool {
|
sort.Slice(retrieved, func(i, j int) bool {
|
||||||
return retrieved[i].Block.Slot < retrieved[j].Block.Slot
|
return retrieved[i].Block.Slot < retrieved[j].Block.Slot
|
||||||
})
|
})
|
||||||
if !reflect.DeepEqual(retrieved, oddBlocks) {
|
for i, block := range retrieved {
|
||||||
t.Errorf("Wanted %v, received %v", oddBlocks, retrieved)
|
if !proto.Equal(block, oddBlocks[i]) {
|
||||||
|
t.Errorf("Wanted %v, received %v", oddBlocks[i], block)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_GenesisBlock(t *testing.T) {
|
func TestStore_GenesisBlock(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
genesisBlock := ðpb.SignedBeaconBlock{
|
genesisBlock := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
genesisBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
|
||||||
Slot: 0,
|
|
||||||
ParentRoot: []byte{1, 2, 3},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
blockRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
blockRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -177,12 +173,9 @@ func TestStore_GenesisBlock(t *testing.T) {
|
|||||||
func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
block := ðpb.SignedBeaconBlock{
|
block := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
block.Block.Slot = 20
|
||||||
Slot: 20,
|
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
|
||||||
ParentRoot: []byte{1, 2, 3},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
blockRoot, err := stateutil.BlockRoot(block.Block)
|
blockRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -218,38 +211,22 @@ func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
blocks := []*ethpb.SignedBeaconBlock{
|
b4 := testutil.NewBeaconBlock()
|
||||||
{
|
b4.Block.Slot = 4
|
||||||
Block: ðpb.BeaconBlock{
|
b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: 4,
|
b5 := testutil.NewBeaconBlock()
|
||||||
ParentRoot: []byte("parent"),
|
b5.Block.Slot = 5
|
||||||
},
|
b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
|
||||||
},
|
b6 := testutil.NewBeaconBlock()
|
||||||
{
|
b6.Block.Slot = 6
|
||||||
Block: ðpb.BeaconBlock{
|
b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
|
||||||
Slot: 5,
|
b7 := testutil.NewBeaconBlock()
|
||||||
ParentRoot: []byte("parent2"),
|
b7.Block.Slot = 7
|
||||||
},
|
b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32)
|
||||||
},
|
b8 := testutil.NewBeaconBlock()
|
||||||
{
|
b8.Block.Slot = 8
|
||||||
Block: ðpb.BeaconBlock{
|
b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32)
|
||||||
Slot: 6,
|
blocks := []*ethpb.SignedBeaconBlock{b4, b5, b6, b7, b8}
|
||||||
ParentRoot: []byte("parent2"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Block: ðpb.BeaconBlock{
|
|
||||||
Slot: 7,
|
|
||||||
ParentRoot: []byte("parent3"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Block: ðpb.BeaconBlock{
|
|
||||||
Slot: 8,
|
|
||||||
ParentRoot: []byte("parent4"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := db.SaveBlocks(ctx, blocks); err != nil {
|
if err := db.SaveBlocks(ctx, blocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -260,12 +237,12 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
|||||||
expectedNumBlocks int
|
expectedNumBlocks int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
filter: filters.NewFilter().SetParentRoot([]byte("parent2")),
|
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)),
|
||||||
expectedNumBlocks: 2,
|
expectedNumBlocks: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// No block meets the criteria below.
|
// 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,
|
expectedNumBlocks: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -304,7 +281,7 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Composite filter criteria.
|
// Composite filter criteria.
|
||||||
filter: filters.NewFilter().
|
filter: filters.NewFilter().
|
||||||
SetParentRoot([]byte("parent2")).
|
SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)).
|
||||||
SetStartSlot(6).
|
SetStartSlot(6).
|
||||||
SetEndSlot(8),
|
SetEndSlot(8),
|
||||||
expectedNumBlocks: 1,
|
expectedNumBlocks: 1,
|
||||||
@@ -323,17 +300,15 @@ func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) {
|
func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||||
for i := 0; i < 500; i++ {
|
for i := 0; i < 500; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
ParentRoot: []byte("parent"),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: uint64(i),
|
totalBlocks[i] = b
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
|
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) {
|
func TestStore_Blocks_Retrieve_Epoch(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
slots := params.BeaconConfig().SlotsPerEpoch * 7
|
slots := params.BeaconConfig().SlotsPerEpoch * 7
|
||||||
b := make([]*ethpb.SignedBeaconBlock, slots)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, slots)
|
||||||
for i := uint64(0); i < slots; i++ {
|
for i := uint64(0); i < slots; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
ParentRoot: []byte("parent"),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: i,
|
totalBlocks[i] = b
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
|
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) {
|
func TestStore_Blocks_Retrieve_SlotRangeWithStep(t *testing.T) {
|
||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||||
for i := 0; i < 500; i++ {
|
for i := 0; i < 500; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
ParentRoot: []byte("parent"),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: uint64(i),
|
totalBlocks[i] = b
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const step = 2
|
const step = 2
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
retrieved, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step))
|
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)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
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 {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -427,7 +399,7 @@ func TestStore_SaveBlock_CanGetHighest(t *testing.T) {
|
|||||||
t.Errorf("Wanted %v, received %v", block, highestSavedBlock)
|
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 {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -439,7 +411,7 @@ func TestStore_SaveBlock_CanGetHighest(t *testing.T) {
|
|||||||
t.Errorf("Wanted %v, received %v", block, highestSavedBlock)
|
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 {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -456,15 +428,18 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
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 {
|
if err := db.SaveBlock(ctx, block1); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(ctx, block2); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(ctx, block3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -512,7 +487,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
genesisBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{}}
|
genesisBlock := testutil.NewBeaconBlock()
|
||||||
genesisRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
genesisRoot, err := stateutil.BlockRoot(genesisBlock.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -523,7 +498,8 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
|||||||
if err := db.SaveBlock(ctx, genesisBlock); err != nil {
|
if err := db.SaveBlock(ctx, genesisBlock); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(ctx, block1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -555,25 +531,23 @@ func TestStore_SaveBlocks_CanGetHighest(t *testing.T) {
|
|||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
b := make([]*ethpb.SignedBeaconBlock, 500)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, 500)
|
||||||
for i := 0; i < 500; i++ {
|
for i := 0; i < 500; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
ParentRoot: []byte("parent"),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: uint64(i),
|
totalBlocks[i] = b
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
highestSavedBlock, err := db.HighestSlotBlocks(ctx)
|
highestSavedBlock, err := db.HighestSlotBlocks(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !proto.Equal(b[len(b)-1], highestSavedBlock[0]) {
|
if !proto.Equal(totalBlocks[len(totalBlocks)-1], highestSavedBlock[0]) {
|
||||||
t.Errorf("Wanted %v, received %v", b[len(b)-1], highestSavedBlock)
|
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++ {
|
for i := 0; i < 500; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b[i] = ðpb.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
ParentRoot: []byte("parent"),
|
ParentRoot: bytesutil.PadTo([]byte("parent"), 32),
|
||||||
Slot: uint64(i),
|
Slot: uint64(i),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -613,7 +587,8 @@ func TestStore_DeleteBlock_CanGetHighest(t *testing.T) {
|
|||||||
db := setupDB(t)
|
db := setupDB(t)
|
||||||
ctx := context.Background()
|
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 {
|
if err := db.SaveBlock(ctx, b50); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -625,7 +600,8 @@ func TestStore_DeleteBlock_CanGetHighest(t *testing.T) {
|
|||||||
t.Errorf("Wanted %v, received %v", b50, highestSavedBlock)
|
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)
|
r51, err := stateutil.BlockRoot(b51.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -659,22 +635,20 @@ func TestStore_DeleteBlocks_CanGetHighest(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
b := make([]*ethpb.SignedBeaconBlock, 100)
|
totalBlocks := make([]*ethpb.SignedBeaconBlock, 100)
|
||||||
r := make([][32]byte, 100)
|
r := make([][32]byte, 100)
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
b[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
ParentRoot: []byte("parent"),
|
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||||
Slot: uint64(i),
|
totalBlocks[i] = b
|
||||||
},
|
r[i], err = stateutil.BlockRoot(totalBlocks[i].Block)
|
||||||
}
|
|
||||||
r[i], err = stateutil.BlockRoot(b[i].Block)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.SaveBlocks(ctx, b); err != nil {
|
if err := db.SaveBlocks(ctx, totalBlocks); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := db.DeleteBlocks(ctx, [][32]byte{r[99], r[98], r[97]}); err != nil {
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !proto.Equal(b[96], highestSavedBlock[0]) {
|
if !proto.Equal(totalBlocks[96], highestSavedBlock[0]) {
|
||||||
t.Errorf("Wanted %v, received %v", b[len(b)-1], highestSavedBlock)
|
t.Errorf("Wanted %v, received %v", totalBlocks[len(totalBlocks)-1], highestSavedBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ func isSSZStorageFormat(obj interface{}) bool {
|
|||||||
switch obj.(type) {
|
switch obj.(type) {
|
||||||
case *pb.BeaconState:
|
case *pb.BeaconState:
|
||||||
return true
|
return true
|
||||||
|
case *ethpb.SignedBeaconBlock:
|
||||||
|
return true
|
||||||
|
case *ethpb.SignedAggregateAttestationAndProof:
|
||||||
|
return true
|
||||||
case *ethpb.BeaconBlock:
|
case *ethpb.BeaconBlock:
|
||||||
return true
|
return true
|
||||||
case *ethpb.Attestation:
|
case *ethpb.Attestation:
|
||||||
|
|||||||
@@ -132,12 +132,9 @@ func TestStore_StatesBatchDelete(t *testing.T) {
|
|||||||
blockRoots := make([][32]byte, 0)
|
blockRoots := make([][32]byte, 0)
|
||||||
evenBlockRoots := make([][32]byte, 0)
|
evenBlockRoots := make([][32]byte, 0)
|
||||||
for i := 0; i < len(totalBlocks); i++ {
|
for i := 0; i < len(totalBlocks); i++ {
|
||||||
totalBlocks[i] = ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = uint64(i)
|
||||||
Slot: uint64(i),
|
totalBlocks[i] = b
|
||||||
ParentRoot: []byte("parent"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ var (
|
|||||||
DepositContractFlag = &cli.StringFlag{
|
DepositContractFlag = &cli.StringFlag{
|
||||||
Name: "deposit-contract",
|
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.",
|
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 defines the host on which the RPC server should listen.
|
||||||
RPCHost = &cli.StringFlag{
|
RPCHost = &cli.StringFlag{
|
||||||
Name: "rpc-host",
|
Name: "rpc-host",
|
||||||
Usage: "Host on which the RPC server should listen",
|
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 defines a beacon node RPC port to open.
|
||||||
RPCPort = &cli.IntFlag{
|
RPCPort = &cli.IntFlag{
|
||||||
@@ -82,7 +82,7 @@ var (
|
|||||||
ContractDeploymentBlock = &cli.IntFlag{
|
ContractDeploymentBlock = &cli.IntFlag{
|
||||||
Name: "contract-deployment-block",
|
Name: "contract-deployment-block",
|
||||||
Usage: "The eth1 block in which the deposit contract was deployed.",
|
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 is the percentage of current live allocations at which the garbage collector is to run.
|
||||||
SetGCPercent = &cli.IntFlag{
|
SetGCPercent = &cli.IntFlag{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func main() {
|
|||||||
gw := gateway.New(
|
gw := gateway.New(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
*beaconRPC,
|
*beaconRPC,
|
||||||
fmt.Sprintf("0.0.0.0:%d", *port),
|
fmt.Sprintf("127.0.0.1:%d", *port),
|
||||||
mux,
|
mux,
|
||||||
strings.Split(*allowedOrigins, ","),
|
strings.Split(*allowedOrigins, ","),
|
||||||
*enableDebugRPCEndpoints,
|
*enableDebugRPCEndpoints,
|
||||||
|
|||||||
@@ -599,7 +599,7 @@ func (b *BeaconNode) registerGRPCGateway() error {
|
|||||||
}
|
}
|
||||||
gatewayPort := b.cliCtx.Int(flags.GRPCGatewayPort.Name)
|
gatewayPort := b.cliCtx.Int(flags.GRPCGatewayPort.Name)
|
||||||
selfAddress := fmt.Sprintf("127.0.0.1:%d", b.cliCtx.Int(flags.RPCPort.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), ",")
|
allowedOrigins := strings.Split(b.cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",")
|
||||||
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
||||||
return b.services.RegisterService(
|
return b.services.RegisterService(
|
||||||
|
|||||||
@@ -528,9 +528,6 @@ func TestPool_PendingAttesterSlashings(t *testing.T) {
|
|||||||
pending []*PendingAttesterSlashing
|
pending []*PendingAttesterSlashing
|
||||||
}
|
}
|
||||||
params.SetupTestConfigCleanup(t)
|
params.SetupTestConfigCleanup(t)
|
||||||
conf := params.BeaconConfig()
|
|
||||||
conf.MaxAttesterSlashings = 1
|
|
||||||
params.OverrideBeaconConfig(conf)
|
|
||||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 64)
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 64)
|
||||||
pendingSlashings := make([]*PendingAttesterSlashing, 20)
|
pendingSlashings := make([]*PendingAttesterSlashing, 20)
|
||||||
slashings := make([]*ethpb.AttesterSlashing, 20)
|
slashings := make([]*ethpb.AttesterSlashing, 20)
|
||||||
@@ -562,14 +559,14 @@ func TestPool_PendingAttesterSlashings(t *testing.T) {
|
|||||||
fields: fields{
|
fields: fields{
|
||||||
pending: pendingSlashings,
|
pending: pendingSlashings,
|
||||||
},
|
},
|
||||||
want: slashings[0:1],
|
want: slashings[0:2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple indices",
|
name: "Multiple indices",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
pending: pendingSlashings[3:6],
|
pending: pendingSlashings[3:6],
|
||||||
},
|
},
|
||||||
want: slashings[3:4],
|
want: slashings[3:5],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -18,33 +18,49 @@ import (
|
|||||||
// GossipTypeMapping.
|
// GossipTypeMapping.
|
||||||
var ErrMessageNotMapped = errors.New("message type is not mapped to a PubSub topic")
|
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.
|
// Broadcast a message to the p2p network.
|
||||||
func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
|
func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "p2p.Broadcast")
|
ctx, span := trace.StartSpan(ctx, "p2p.Broadcast")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
forkDigest, err := s.forkDigest()
|
forkDigest, err := s.forkDigest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err := errors.Wrap(err, "could not retrieve fork digest")
|
||||||
|
traceutil.AnnotateError(span, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var topic string
|
topic, ok := GossipTypeMapping[reflect.TypeOf(msg)]
|
||||||
switch msg.(type) {
|
|
||||||
case *eth.Attestation:
|
|
||||||
topic = attestationToTopic(msg.(*eth.Attestation), forkDigest)
|
|
||||||
default:
|
|
||||||
var ok bool
|
|
||||||
topic, ok = GossipTypeMapping[reflect.TypeOf(msg)]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
traceutil.AnnotateError(span, ErrMessageNotMapped)
|
traceutil.AnnotateError(span, ErrMessageNotMapped)
|
||||||
return ErrMessageNotMapped
|
return ErrMessageNotMapped
|
||||||
}
|
}
|
||||||
topic = fmt.Sprintf(topic, forkDigest)
|
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))
|
span.AddAttributes(trace.StringAttribute("topic", topic))
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
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")
|
err := errors.Wrap(err, "could not encode message")
|
||||||
traceutil.AnnotateError(span, err)
|
traceutil.AnnotateError(span, err)
|
||||||
return err
|
return err
|
||||||
@@ -64,11 +80,6 @@ func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const attestationSubnetTopicFormat = "/eth2/%x/committee_index%d_beacon_attestation"
|
func attestationToTopic(subnet uint64, forkDigest [4]byte) string {
|
||||||
|
return fmt.Sprintf(attestationSubnetTopicFormat, forkDigest, subnet)
|
||||||
func attestationToTopic(att *eth.Attestation, forkDigest [4]byte) string {
|
|
||||||
if att == nil || att.Data == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(attestationSubnetTopicFormat, forkDigest, att.Data.CommitteeIndex)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
testpb "github.com/prysmaticlabs/prysm/proto/testing"
|
testpb "github.com/prysmaticlabs/prysm/proto/testing"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
@@ -109,36 +110,33 @@ func TestService_Attestation_Subnet(t *testing.T) {
|
|||||||
att: ð.Attestation{
|
att: ð.Attestation{
|
||||||
Data: ð.AttestationData{
|
Data: ð.AttestationData{
|
||||||
CommitteeIndex: 0,
|
CommitteeIndex: 0,
|
||||||
|
Slot: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
topic: "/eth2/00000000/committee_index0_beacon_attestation",
|
topic: "/eth2/00000000/beacon_attestation_2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
att: ð.Attestation{
|
att: ð.Attestation{
|
||||||
Data: ð.AttestationData{
|
Data: ð.AttestationData{
|
||||||
CommitteeIndex: 11,
|
CommitteeIndex: 11,
|
||||||
|
Slot: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
topic: "/eth2/00000000/committee_index11_beacon_attestation",
|
topic: "/eth2/00000000/beacon_attestation_21",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
att: ð.Attestation{
|
att: ð.Attestation{
|
||||||
Data: ð.AttestationData{
|
Data: ð.AttestationData{
|
||||||
CommitteeIndex: 55,
|
CommitteeIndex: 55,
|
||||||
|
Slot: 529,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
topic: "/eth2/00000000/committee_index55_beacon_attestation",
|
topic: "/eth2/00000000/beacon_attestation_8",
|
||||||
},
|
|
||||||
{
|
|
||||||
att: ð.Attestation{},
|
|
||||||
topic: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
topic: "",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
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)
|
t.Errorf("Wrong topic, got %s wanted %s", res, tt.topic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// lookup.
|
// lookup.
|
||||||
var GossipTopicMappings = map[string]proto.Message{
|
var GossipTopicMappings = map[string]proto.Message{
|
||||||
"/eth2/%x/beacon_block": &pb.SignedBeaconBlock{},
|
"/eth2/%x/beacon_block": &pb.SignedBeaconBlock{},
|
||||||
"/eth2/%x/committee_index%d_beacon_attestation": &pb.Attestation{},
|
"/eth2/%x/beacon_attestation_%d": &pb.Attestation{},
|
||||||
"/eth2/%x/voluntary_exit": &pb.SignedVoluntaryExit{},
|
"/eth2/%x/voluntary_exit": &pb.SignedVoluntaryExit{},
|
||||||
"/eth2/%x/proposer_slashing": &pb.ProposerSlashing{},
|
"/eth2/%x/proposer_slashing": &pb.ProposerSlashing{},
|
||||||
"/eth2/%x/attester_slashing": &pb.AttesterSlashing{},
|
"/eth2/%x/attester_slashing": &pb.AttesterSlashing{},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
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/encoder"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
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.
|
// Broadcaster broadcasts messages to peers over the p2p pubsub protocol.
|
||||||
type Broadcaster interface {
|
type Broadcaster interface {
|
||||||
Broadcast(context.Context, proto.Message) error
|
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.
|
// SetStreamHandler configures p2p to handle streams of a certain topic ID.
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
"github.com/prysmaticlabs/prysm/shared"
|
"github.com/prysmaticlabs/prysm/shared"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||||
"github.com/prysmaticlabs/prysm/shared/runutil"
|
"github.com/prysmaticlabs/prysm/shared/runutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||||||
)
|
)
|
||||||
@@ -136,7 +137,7 @@ func NewService(cfg *Config) (*Service, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cfg.KademliaBootStrapAddr) != 0 && !cfg.NoDiscovery {
|
if len(cfg.KademliaBootStrapAddr) != 0 && !cfg.NoDiscovery && featureconfig.Get().EnableKadDHT {
|
||||||
dopts := []dhtopts.Option{
|
dopts := []dhtopts.Option{
|
||||||
dhtopts.Datastore(dsync.MutexWrap(ds.NewMapDatastore())),
|
dhtopts.Datastore(dsync.MutexWrap(ds.NewMapDatastore())),
|
||||||
dhtopts.Protocols(
|
dhtopts.Protocols(
|
||||||
@@ -235,7 +236,7 @@ func (s *Service) Start() {
|
|||||||
go s.listenForNewNodes()
|
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 {
|
for _, addr := range s.cfg.KademliaBootStrapAddr {
|
||||||
peersToWatch = append(peersToWatch, addr)
|
peersToWatch = append(peersToWatch, addr)
|
||||||
err := startDHTDiscovery(s.host, addr)
|
err := startDHTDiscovery(s.host, addr)
|
||||||
@@ -390,7 +391,7 @@ func (s *Service) RefreshENR() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
bitV := bitfield.NewBitvector64()
|
bitV := bitfield.NewBitvector64()
|
||||||
committees := cache.CommitteeIDs.GetAllCommittees()
|
committees := cache.SubnetIDs.GetAllSubnets()
|
||||||
for _, idx := range committees {
|
for _, idx := range committees {
|
||||||
bitV.SetBitAt(idx, true)
|
bitV.SetBitAt(idx, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func TestStartDiscV5_DiscoverPeersWithSubnets(t *testing.T) {
|
|||||||
dv5Listener: listeners[0],
|
dv5Listener: listeners[0],
|
||||||
metaData: &pb.MetaData{},
|
metaData: &pb.MetaData{},
|
||||||
}
|
}
|
||||||
cache.CommitteeIDs.AddAttesterCommiteeID(0, 10)
|
cache.SubnetIDs.AddAttesterSubnetID(0, 10)
|
||||||
testService.RefreshENR()
|
testService.RefreshENR()
|
||||||
time.Sleep(2 * time.Second)
|
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_pubsub//:go_default_library",
|
||||||
"@com_github_libp2p_go_libp2p_swarm//testing:go_default_library",
|
"@com_github_libp2p_go_libp2p_swarm//testing:go_default_library",
|
||||||
"@com_github_multiformats_go_multiaddr//: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",
|
"@com_github_sirupsen_logrus//:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockBroadcaster implements p2p.Broadcaster for testing.
|
// MockBroadcaster implements p2p.Broadcaster for testing.
|
||||||
@@ -16,3 +17,9 @@ func (m *MockBroadcaster) Broadcast(context.Context, proto.Message) error {
|
|||||||
m.BroadcastCalled = true
|
m.BroadcastCalled = true
|
||||||
return nil
|
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"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
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/encoder"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
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
|
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.
|
// SetStreamHandler for RPC.
|
||||||
func (p *TestP2P) SetStreamHandler(topic string, handler network.StreamHandler) {
|
func (p *TestP2P) SetStreamHandler(topic string, handler network.StreamHandler) {
|
||||||
p.Host.SetStreamHandler(protocol.ID(topic), handler)
|
p.Host.SetStreamHandler(protocol.ID(topic), handler)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -246,12 +245,9 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) createGenesisTime(timeStamp uint64) uint64 {
|
func (s *Service) createGenesisTime(timeStamp uint64) uint64 {
|
||||||
if featureconfig.Get().CustomGenesisDelay == 0 {
|
// adds in the genesis delay to the eth1 block time
|
||||||
return timeStamp
|
// on which it was triggered.
|
||||||
}
|
return timeStamp + featureconfig.Get().CustomGenesisDelay
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// processPastLogs processes all the past logs from the deposit contract and
|
// 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
|
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
|
// stop requesting, if we have all the logs
|
||||||
if logCount == uint64(s.lastReceivedMerkleIndex+1) {
|
if logCount == uint64(s.lastReceivedMerkleIndex+1) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
start := currentBlockNum
|
start := currentBlockNum
|
||||||
end := currentBlockNum + eth1HeaderReqLimit
|
end := currentBlockNum + eth1HeaderReqLimit
|
||||||
if end > s.LatestBlockHeight().Uint64() {
|
if end > latestFollowHeight {
|
||||||
end = s.LatestBlockHeight().Uint64()
|
end = latestFollowHeight
|
||||||
}
|
}
|
||||||
query := ethereum.FilterQuery{
|
query := ethereum.FilterQuery{
|
||||||
Addresses: []common.Address{
|
Addresses: []common.Address{
|
||||||
@@ -303,9 +303,9 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1)
|
remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1)
|
||||||
// only change the end block if the remaining logs are below the required log limit.
|
// only change the end block if the remaining logs are below the required log limit.
|
||||||
if remainingLogs < depositlogRequestLimit && end >= s.LatestBlockHeight().Uint64() {
|
if remainingLogs < depositlogRequestLimit && end >= latestFollowHeight {
|
||||||
query.ToBlock = s.LatestBlockHeight()
|
query.ToBlock = big.NewInt(int64(latestFollowHeight))
|
||||||
end = s.LatestBlockHeight().Uint64()
|
end = latestFollowHeight
|
||||||
}
|
}
|
||||||
logs, err := s.httpLogger.FilterLogs(ctx, query)
|
logs, err := s.httpLogger.FilterLogs(ctx, query)
|
||||||
if err != nil {
|
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
|
// 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.
|
// 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++ {
|
for i := s.latestEth1Data.LastRequestedBlock + 1; i <= requestedBlock; i++ {
|
||||||
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
|
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -488,18 +488,18 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
web3Service.rpcClient = &mockPOW.RPCClient{Backend: testAcc.Backend}
|
web3Service.rpcClient = &mockPOW.RPCClient{Backend: testAcc.Backend}
|
||||||
web3Service.httpLogger = testAcc.Backend
|
web3Service.httpLogger = testAcc.Backend
|
||||||
|
web3Service.blockFetcher = &goodFetcher{backend: testAcc.Backend}
|
||||||
web3Service.latestEth1Data.LastRequestedBlock = 0
|
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)
|
params.SetupTestConfigCleanup(t)
|
||||||
bConfig := params.MinimalSpecConfig()
|
bConfig := params.MinimalSpecConfig()
|
||||||
bConfig.MinGenesisTime = 0
|
bConfig.MinGenesisTime = 0
|
||||||
|
bConfig.SecondsPerETH1Block = 10
|
||||||
params.OverrideBeaconConfig(bConfig)
|
params.OverrideBeaconConfig(bConfig)
|
||||||
flags.Get().DeploymentBlock = 0
|
flags.Get().DeploymentBlock = 0
|
||||||
|
|
||||||
testAcc.Backend.Commit()
|
testAcc.Backend.Commit()
|
||||||
if err := testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond()))); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
totalNumOfDeposits := depositsReqForChainStart + 30
|
totalNumOfDeposits := depositsReqForChainStart + 30
|
||||||
|
|
||||||
@@ -529,7 +529,12 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
|||||||
testAcc.Backend.Commit()
|
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.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.
|
// Set up our subscriber now to listen for the chain started event.
|
||||||
stateChannel := make(chan *feed.Event, 1)
|
stateChannel := make(chan *feed.Event, 1)
|
||||||
@@ -726,7 +731,7 @@ func TestConsistentGenesisState(t *testing.T) {
|
|||||||
testAcc.Backend.Commit()
|
testAcc.Backend.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < int(params.BeaconConfig().LogBlockDelay); i++ {
|
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
|
||||||
testAcc.Backend.Commit()
|
testAcc.Backend.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,6 +317,32 @@ func (s *Service) AreAllDepositsProcessed() (bool, error) {
|
|||||||
return true, nil
|
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 {
|
func (s *Service) connectToPowChain() error {
|
||||||
httpClient, rpcClient, err := s.dialETH1Nodes()
|
httpClient, rpcClient, err := s.dialETH1Nodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -502,7 +528,7 @@ func safelyHandlePanic() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) handleDelayTicker() {
|
func (s *Service) handleETH1FollowDistance() {
|
||||||
defer safelyHandlePanic()
|
defer safelyHandlePanic()
|
||||||
|
|
||||||
// use a 5 minutes timeout for block time, because the max mining time is 278 sec (block 7208027)
|
// 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.BlockHeight = header.Number.Uint64()
|
||||||
s.latestEth1Data.BlockHash = header.Hash().Bytes()
|
s.latestEth1Data.BlockHash = header.Hash().Bytes()
|
||||||
|
s.latestEth1Data.BlockTime = header.Time
|
||||||
|
|
||||||
if err := s.processPastLogs(context.Background()); err != nil {
|
if err := s.processPastLogs(context.Background()); err != nil {
|
||||||
log.Errorf("Unable to process past logs %v", err)
|
log.Errorf("Unable to process past logs %v", err)
|
||||||
@@ -605,7 +632,7 @@ func (s *Service) run(done <-chan struct{}) {
|
|||||||
}
|
}
|
||||||
s.processBlockHeader(head)
|
s.processBlockHeader(head)
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
s.handleDelayTicker()
|
s.handleETH1FollowDistance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
||||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||||
"github.com/prysmaticlabs/prysm/shared/event"
|
"github.com/prysmaticlabs/prysm/shared/event"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||||
)
|
)
|
||||||
@@ -187,6 +188,67 @@ func TestStop_OK(t *testing.T) {
|
|||||||
hook.Reset()
|
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) {
|
func TestInitDataFromContract_OK(t *testing.T) {
|
||||||
testAcc, err := contracts.Setup()
|
testAcc, err := contracts.Setup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -93,7 +93,16 @@ func TestServer_ListAttestations_Genesis(t *testing.T) {
|
|||||||
}); err != nil && !strings.Contains(err.Error(), "Could not find genesis") {
|
}); err != nil && !strings.Contains(err.Error(), "Could not find genesis") {
|
||||||
t.Fatal(err)
|
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}
|
parentRoot := [32]byte{1, 2, 3}
|
||||||
blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{
|
blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{
|
||||||
@@ -159,8 +168,11 @@ func TestServer_ListAttestations_NoPagination(t *testing.T) {
|
|||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Data: ðpb.AttestationData{
|
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,
|
Slot: i,
|
||||||
},
|
},
|
||||||
AggregationBits: bitfield.Bitlist{0b11},
|
AggregationBits: bitfield.Bitlist{0b11},
|
||||||
@@ -197,27 +209,31 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
|||||||
db := dbTest.SetupDB(t)
|
db := dbTest.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
someRoot := []byte{1, 2, 3}
|
someRoot := [32]byte{1, 2, 3}
|
||||||
sourceRoot := []byte{4, 5, 6}
|
sourceRoot := [32]byte{4, 5, 6}
|
||||||
sourceEpoch := uint64(5)
|
sourceEpoch := uint64(5)
|
||||||
targetRoot := []byte{7, 8, 9}
|
targetRoot := [32]byte{7, 8, 9}
|
||||||
targetEpoch := uint64(7)
|
targetEpoch := uint64(7)
|
||||||
|
|
||||||
blocks := []*ethpb.SignedBeaconBlock{
|
blocks := []*ethpb.SignedBeaconBlock{
|
||||||
{
|
{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: 4,
|
Slot: 4,
|
||||||
|
ParentRoot: make([]byte, 32),
|
||||||
|
StateRoot: make([]byte, 32),
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
RandaoReveal: make([]byte, 96),
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
BeaconBlockRoot: someRoot,
|
BeaconBlockRoot: someRoot[:],
|
||||||
Source: ðpb.Checkpoint{
|
Source: ðpb.Checkpoint{
|
||||||
Root: sourceRoot,
|
Root: sourceRoot[:],
|
||||||
Epoch: sourceEpoch,
|
Epoch: sourceEpoch,
|
||||||
},
|
},
|
||||||
Target: ðpb.Checkpoint{
|
Target: ðpb.Checkpoint{
|
||||||
Root: targetRoot,
|
Root: targetRoot[:],
|
||||||
Epoch: targetEpoch,
|
Epoch: targetEpoch,
|
||||||
},
|
},
|
||||||
Slot: 3,
|
Slot: 3,
|
||||||
@@ -229,19 +245,23 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: 5 + params.BeaconConfig().SlotsPerEpoch,
|
Slot: 5 + params.BeaconConfig().SlotsPerEpoch,
|
||||||
|
ParentRoot: make([]byte, 32),
|
||||||
|
StateRoot: make([]byte, 32),
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
RandaoReveal: make([]byte, 96),
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
BeaconBlockRoot: someRoot,
|
BeaconBlockRoot: someRoot[:],
|
||||||
Source: ðpb.Checkpoint{
|
Source: ðpb.Checkpoint{
|
||||||
Root: sourceRoot,
|
Root: sourceRoot[:],
|
||||||
Epoch: sourceEpoch,
|
Epoch: sourceEpoch,
|
||||||
},
|
},
|
||||||
Target: ðpb.Checkpoint{
|
Target: ðpb.Checkpoint{
|
||||||
Root: targetRoot,
|
Root: targetRoot[:],
|
||||||
Epoch: targetEpoch,
|
Epoch: targetEpoch,
|
||||||
},
|
},
|
||||||
Slot: 4 + params.BeaconConfig().SlotsPerEpoch,
|
Slot: 4 + params.BeaconConfig().SlotsPerEpoch,
|
||||||
@@ -253,19 +273,23 @@ func TestServer_ListAttestations_FiltersCorrectly(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
Slot: 5,
|
Slot: 5,
|
||||||
|
ParentRoot: make([]byte, 32),
|
||||||
|
StateRoot: make([]byte, 32),
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
RandaoReveal: make([]byte, 96),
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
BeaconBlockRoot: someRoot,
|
BeaconBlockRoot: someRoot[:],
|
||||||
Source: ðpb.Checkpoint{
|
Source: ðpb.Checkpoint{
|
||||||
Root: sourceRoot,
|
Root: sourceRoot[:],
|
||||||
Epoch: sourceEpoch,
|
Epoch: sourceEpoch,
|
||||||
},
|
},
|
||||||
Target: ðpb.Checkpoint{
|
Target: ðpb.Checkpoint{
|
||||||
Root: targetRoot,
|
Root: targetRoot[:],
|
||||||
Epoch: targetEpoch,
|
Epoch: targetEpoch,
|
||||||
},
|
},
|
||||||
Slot: 4,
|
Slot: 4,
|
||||||
@@ -323,8 +347,12 @@ func TestServer_ListAttestations_Pagination_CustomPageParameters(t *testing.T) {
|
|||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
CommitteeIndex: s,
|
CommitteeIndex: s,
|
||||||
Slot: i,
|
Slot: i,
|
||||||
|
BeaconBlockRoot: make([]byte, 32),
|
||||||
|
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||||
|
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||||
},
|
},
|
||||||
AggregationBits: bitfield.Bitlist{0b11},
|
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) {
|
func TestServer_ListAttestations_Pagination_OutOfRange(t *testing.T) {
|
||||||
db := dbTest.SetupDB(t)
|
db := dbTest.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
testutil.NewBeaconBlock()
|
||||||
count := uint64(1)
|
count := uint64(1)
|
||||||
atts := make([]*ethpb.Attestation, 0, count)
|
atts := make([]*ethpb.Attestation, 0, count)
|
||||||
for i := uint64(0); i < count; i++ {
|
for i := uint64(0); i < count; i++ {
|
||||||
blockExample := ðpb.SignedBeaconBlock{
|
blockExample := ðpb.SignedBeaconBlock{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
|
ParentRoot: make([]byte, 32),
|
||||||
|
StateRoot: make([]byte, 32),
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
Graffiti: make([]byte, 32),
|
||||||
|
RandaoReveal: make([]byte, 96),
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
BeaconBlockRoot: []byte("root"),
|
BeaconBlockRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||||
Slot: i,
|
Slot: i,
|
||||||
},
|
},
|
||||||
AggregationBits: bitfield.Bitlist{0b11},
|
AggregationBits: bitfield.Bitlist{0b11},
|
||||||
@@ -485,14 +518,21 @@ func TestServer_ListAttestations_Pagination_DefaultPageSize(t *testing.T) {
|
|||||||
atts := make([]*ethpb.Attestation, 0, count)
|
atts := make([]*ethpb.Attestation, 0, count)
|
||||||
for i := uint64(0); i < count; i++ {
|
for i := uint64(0); i < count; i++ {
|
||||||
blockExample := ðpb.SignedBeaconBlock{
|
blockExample := ðpb.SignedBeaconBlock{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
|
ParentRoot: make([]byte, 32),
|
||||||
|
StateRoot: make([]byte, 32),
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
|
RandaoReveal: make([]byte, 96),
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
Data: ðpb.AttestationData{
|
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,
|
Slot: i,
|
||||||
},
|
},
|
||||||
|
Signature: bytesutil.PadTo([]byte("root"), 96),
|
||||||
AggregationBits: bitfield.Bitlist{0b11},
|
AggregationBits: bitfield.Bitlist{0b11},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -624,10 +664,15 @@ func TestServer_ListIndexedAttestations_GenesisEpoch(t *testing.T) {
|
|||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
Attestations: []*ethpb.Attestation{
|
Attestations: []*ethpb.Attestation{
|
||||||
{
|
{
|
||||||
|
Signature: make([]byte, 96),
|
||||||
Data: ðpb.AttestationData{
|
Data: ðpb.AttestationData{
|
||||||
|
BeaconBlockRoot: make([]byte, 32),
|
||||||
Target: ðpb.Checkpoint{
|
Target: ðpb.Checkpoint{
|
||||||
Root: targetRoot[:],
|
Root: targetRoot[:],
|
||||||
},
|
},
|
||||||
|
Source: ðpb.Checkpoint{
|
||||||
|
Root: make([]byte, 32),
|
||||||
|
},
|
||||||
Slot: i,
|
Slot: i,
|
||||||
CommitteeIndex: 0,
|
CommitteeIndex: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ import (
|
|||||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
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/mock"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServer_ListBlocks_NoResults(t *testing.T) {
|
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.
|
// Should return the proper genesis block if it exists.
|
||||||
parentRoot := [32]byte{1, 2, 3}
|
parentRoot := [32]byte{'a'}
|
||||||
blk := ðpb.SignedBeaconBlock{
|
blk := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
blk.Block.ParentRoot = parentRoot[:]
|
||||||
Slot: 0,
|
|
||||||
ParentRoot: parentRoot[:],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
root, err := stateutil.BlockRoot(blk.Block)
|
root, err := stateutil.BlockRoot(blk.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -195,11 +193,8 @@ func TestServer_ListBlocks_Pagination(t *testing.T) {
|
|||||||
blks := make([]*ethpb.SignedBeaconBlock, count)
|
blks := make([]*ethpb.SignedBeaconBlock, count)
|
||||||
blkContainers := make([]*ethpb.BeaconBlockContainer, count)
|
blkContainers := make([]*ethpb.BeaconBlockContainer, count)
|
||||||
for i := uint64(0); i < count; i++ {
|
for i := uint64(0); i < count; i++ {
|
||||||
b := ðpb.SignedBeaconBlock{
|
b := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
b.Block.Slot = i
|
||||||
Slot: i,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
root, err := stateutil.BlockRoot(b.Block)
|
root, err := stateutil.BlockRoot(b.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -229,7 +224,21 @@ func TestServer_ListBlocks_Pagination(t *testing.T) {
|
|||||||
QueryFilter: ðpb.ListBlocksRequest_Slot{Slot: 5},
|
QueryFilter: ðpb.ListBlocksRequest_Slot{Slot: 5},
|
||||||
PageSize: 3},
|
PageSize: 3},
|
||||||
res: ðpb.ListBlocksResponse{
|
res: ðpb.ListBlocksResponse{
|
||||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 5}}, BlockRoot: blkContainers[5].BlockRoot}},
|
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: "",
|
NextPageToken: "",
|
||||||
TotalSize: 1}},
|
TotalSize: 1}},
|
||||||
{req: ðpb.ListBlocksRequest{
|
{req: ðpb.ListBlocksRequest{
|
||||||
@@ -237,11 +246,39 @@ func TestServer_ListBlocks_Pagination(t *testing.T) {
|
|||||||
QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]},
|
QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]},
|
||||||
PageSize: 3},
|
PageSize: 3},
|
||||||
res: ðpb.ListBlocksResponse{
|
res: ðpb.ListBlocksResponse{
|
||||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 6}}, BlockRoot: blkContainers[6].BlockRoot}},
|
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}},
|
TotalSize: 1}},
|
||||||
{req: ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]}},
|
{req: ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Root{Root: root6[:]}},
|
||||||
res: ðpb.ListBlocksResponse{
|
res: ðpb.ListBlocksResponse{
|
||||||
BlockContainers: []*ethpb.BeaconBlockContainer{{Block: ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 6}}, BlockRoot: blkContainers[6].BlockRoot}},
|
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}},
|
TotalSize: 1}},
|
||||||
{req: ðpb.ListBlocksRequest{
|
{req: ðpb.ListBlocksRequest{
|
||||||
PageToken: strconv.Itoa(0),
|
PageToken: strconv.Itoa(0),
|
||||||
@@ -374,7 +411,8 @@ func TestServer_GetChainHead_NoFinalizedBlock(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -417,7 +455,8 @@ func TestServer_GetChainHead_NoHeadBlock(t *testing.T) {
|
|||||||
func TestServer_GetChainHead(t *testing.T) {
|
func TestServer_GetChainHead(t *testing.T) {
|
||||||
db := dbTest.SetupDB(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 {
|
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -429,7 +468,9 @@ func TestServer_GetChainHead(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), finalizedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -437,7 +478,10 @@ func TestServer_GetChainHead(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), justifiedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -445,7 +489,10 @@ func TestServer_GetChainHead(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), prevJustifiedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -546,7 +593,8 @@ func TestServer_StreamChainHead_ContextCanceled(t *testing.T) {
|
|||||||
func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
||||||
db := dbTest.SetupDB(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 {
|
if err := db.SaveBlock(context.Background(), genBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -558,7 +606,9 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), finalizedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -566,7 +616,10 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), justifiedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -574,7 +627,10 @@ func TestServer_StreamChainHead_OnHeadUpdated(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if err := db.SaveBlock(context.Background(), prevJustifiedBlock); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1892,7 +1892,9 @@ func TestServer_GetValidatorParticipation_PrevEpoch(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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) {
|
if !reflect.DeepEqual(res.Participation, wanted) {
|
||||||
t.Error("Incorrect validator participation respond")
|
t.Error("Incorrect validator participation respond")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ func assignValidatorToSubnet(pubkey []byte, status ethpb.ValidatorStatus) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok, expTime := cache.CommitteeIDs.GetPersistentCommittees(pubkey)
|
_, ok, expTime := cache.SubnetIDs.GetPersistentSubnets(pubkey)
|
||||||
if ok && expTime.After(roughtime.Now()) {
|
if ok && expTime.After(roughtime.Now()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -208,5 +208,5 @@ func assignValidatorToSubnet(pubkey []byte, status ethpb.ValidatorStatus) {
|
|||||||
assignedDuration += int(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
assignedDuration += int(params.BeaconNetworkConfig().EpochsPerRandomSubnetSubscription)
|
||||||
|
|
||||||
totalDuration := epochDuration * time.Duration(assignedDuration)
|
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"
|
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
"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"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
@@ -40,7 +39,7 @@ func TestGetDuties_NextEpoch_CantFindValidatorIdx(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconState, _ := testutil.DeterministicGenesisState(t, 10)
|
beaconState, _ := testutil.DeterministicGenesisState(t, 10)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
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) {
|
func TestGetDuties_OK(t *testing.T) {
|
||||||
db := dbutil.SetupDB(t)
|
db := dbutil.SetupDB(t)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -165,7 +164,7 @@ func TestGetDuties_OK(t *testing.T) {
|
|||||||
func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
||||||
db := dbutil.SetupDB(t)
|
db := dbutil.SetupDB(t)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -222,7 +221,7 @@ func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
|||||||
func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
||||||
db := dbutil.SetupDB(t)
|
db := dbutil.SetupDB(t)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := uint64(64)
|
depChainStart := uint64(64)
|
||||||
testutil.ResetCache()
|
testutil.ResetCache()
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
@@ -274,11 +273,11 @@ func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
|||||||
if len(res.CurrentEpochDuties) != 2 {
|
if len(res.CurrentEpochDuties) != 2 {
|
||||||
t.Errorf("expected 2 assignments but got %d", len(res.CurrentEpochDuties))
|
t.Errorf("expected 2 assignments but got %d", len(res.CurrentEpochDuties))
|
||||||
}
|
}
|
||||||
if res.CurrentEpochDuties[0].AttesterSlot != 2 {
|
if res.CurrentEpochDuties[0].AttesterSlot != 4 {
|
||||||
t.Errorf("Expected res.CurrentEpochDuties[0].AttesterSlot == 7, got %d", res.CurrentEpochDuties[0].AttesterSlot)
|
t.Errorf("Expected res.CurrentEpochDuties[0].AttesterSlot == 4, got %d", res.CurrentEpochDuties[0].AttesterSlot)
|
||||||
}
|
}
|
||||||
if res.CurrentEpochDuties[1].AttesterSlot != 1 {
|
if res.CurrentEpochDuties[1].AttesterSlot != 4 {
|
||||||
t.Errorf("Expected res.CurrentEpochDuties[1].AttesterSlot == 1, got %d", res.CurrentEpochDuties[1].AttesterSlot)
|
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) {
|
func TestStreamDuties_OK(t *testing.T) {
|
||||||
db := dbutil.SetupDB(t)
|
db := dbutil.SetupDB(t)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -380,7 +379,7 @@ func TestStreamDuties_OK(t *testing.T) {
|
|||||||
func TestStreamDuties_OK_ChainReorg(t *testing.T) {
|
func TestStreamDuties_OK_ChainReorg(t *testing.T) {
|
||||||
db := dbutil.SetupDB(t)
|
db := dbutil.SetupDB(t)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -469,7 +468,7 @@ func TestAssignValidatorToSubnet(t *testing.T) {
|
|||||||
k := pubKey(3)
|
k := pubKey(3)
|
||||||
|
|
||||||
assignValidatorToSubnet(k, ethpb.ValidatorStatus_ACTIVE)
|
assignValidatorToSubnet(k, ethpb.ValidatorStatus_ACTIVE)
|
||||||
coms, ok, exp := cache.CommitteeIDs.GetPersistentCommittees(k)
|
coms, ok, exp := cache.SubnetIDs.GetPersistentSubnets(k)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("No cache entry found for validator")
|
t.Fatal("No cache entry found for validator")
|
||||||
}
|
}
|
||||||
@@ -487,7 +486,7 @@ func TestAssignValidatorToSubnet(t *testing.T) {
|
|||||||
func BenchmarkCommitteeAssignment(b *testing.B) {
|
func BenchmarkCommitteeAssignment(b *testing.B) {
|
||||||
db := dbutil.SetupDB(b)
|
db := dbutil.SetupDB(b)
|
||||||
|
|
||||||
genesis := blk.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
depChainStart := uint64(8192 * 2)
|
depChainStart := uint64(8192 * 2)
|
||||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
deposits, _, err := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||||
if err != nil {
|
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
|
// ProposeAttestation is a function called by an attester to vote
|
||||||
// on a block via an attestation object as defined in the Ethereum Serenity specification.
|
// 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) {
|
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 {
|
if _, err := bls.SignatureFromBytes(att.Signature); err != nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature")
|
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.
|
// 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)
|
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.
|
// SubscribeCommitteeSubnets subscribes to the committee ID subnet given subscribe request.
|
||||||
func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.CommitteeSubnetsSubscribeRequest) (*ptypes.Empty, error) {
|
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) {
|
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")
|
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++ {
|
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] {
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -22,6 +23,7 @@ import (
|
|||||||
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
|
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
|
||||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
@@ -40,12 +42,9 @@ func TestProposeAttestation_OK(t *testing.T) {
|
|||||||
AttPool: attestations.NewPool(),
|
AttPool: attestations.NewPool(),
|
||||||
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
|
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
|
||||||
}
|
}
|
||||||
head := ðpb.SignedBeaconBlock{
|
head := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
head.Block.Slot = 999
|
||||||
Slot: 999,
|
head.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
|
||||||
ParentRoot: []byte{'a'},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := db.SaveBlock(ctx, head); err != nil {
|
if err := db.SaveBlock(ctx, head); err != nil {
|
||||||
t.Fatal(err)
|
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)
|
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"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
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"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
@@ -34,7 +33,7 @@ func TestSub(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
t.Fatalf("Could not save genesis block: %v", err)
|
||||||
}
|
}
|
||||||
@@ -123,7 +122,7 @@ func TestProposeExit_NoPanic(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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 {
|
if depositsTillHeight == 0 {
|
||||||
return vs.ChainStartFetcher.ChainStartEth1Data(), nil
|
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{
|
return ðpb.Eth1Data{
|
||||||
DepositRoot: depositRoot[:],
|
DepositRoot: depositRoot[:],
|
||||||
BlockHash: blockHash[:],
|
BlockHash: blockHash[:],
|
||||||
|
|||||||
@@ -94,25 +94,37 @@ func TestGetBlock_OK(t *testing.T) {
|
|||||||
Graffiti: graffiti[:],
|
Graffiti: graffiti[:],
|
||||||
}
|
}
|
||||||
|
|
||||||
// We include max proposer slashings which is currently 1 in the pool.
|
proposerSlashings := make([]*ethpb.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings)
|
||||||
|
for i := uint64(0); i < params.BeaconConfig().MaxProposerSlashings; i++ {
|
||||||
proposerSlashing, err := testutil.GenerateProposerSlashingForValidator(
|
proposerSlashing, err := testutil.GenerateProposerSlashingForValidator(
|
||||||
beaconState,
|
beaconState,
|
||||||
privKeys[0],
|
privKeys[i],
|
||||||
0, /* validator index */
|
i, /* validator index */
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
proposerSlashings[i] = proposerSlashing
|
||||||
if err := proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing); err != nil {
|
if err := proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We include max attester slashings which is currently 1 in the pool.
|
attSlashings := make([]*ethpb.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings)
|
||||||
|
for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ {
|
||||||
attesterSlashing, err := testutil.GenerateAttesterSlashingForValidator(
|
attesterSlashing, err := testutil.GenerateAttesterSlashingForValidator(
|
||||||
beaconState,
|
beaconState,
|
||||||
privKeys[1],
|
privKeys[i+params.BeaconConfig().MaxProposerSlashings],
|
||||||
1, /* validator index */
|
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 {
|
if err := proposerServer.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
block, err := proposerServer.GetBlock(ctx, req)
|
block, err := proposerServer.GetBlock(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -131,17 +143,17 @@ func TestGetBlock_OK(t *testing.T) {
|
|||||||
if !bytes.Equal(block.Body.Graffiti, req.Graffiti) {
|
if !bytes.Equal(block.Body.Graffiti, req.Graffiti) {
|
||||||
t.Fatal("Expected block to have correct graffiti")
|
t.Fatal("Expected block to have correct graffiti")
|
||||||
}
|
}
|
||||||
if len(block.Body.ProposerSlashings) != 1 {
|
if len(block.Body.ProposerSlashings) != int(params.BeaconConfig().MaxProposerSlashings) {
|
||||||
t.Fatalf("Wanted %d proposer slashings, got %d", 1, len(block.Body.ProposerSlashings))
|
t.Fatalf("Wanted %d proposer slashings, got %d", params.BeaconConfig().MaxProposerSlashings, len(block.Body.ProposerSlashings))
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(block.Body.ProposerSlashings[0], proposerSlashing) {
|
if !reflect.DeepEqual(block.Body.ProposerSlashings, proposerSlashings) {
|
||||||
t.Errorf("Wanted proposer slashing %v, got %v", proposerSlashing, block.Body.ProposerSlashings[0])
|
t.Errorf("Wanted proposer slashing %v, got %v", proposerSlashings, block.Body.ProposerSlashings)
|
||||||
}
|
}
|
||||||
if len(block.Body.AttesterSlashings) != 1 {
|
if len(block.Body.AttesterSlashings) != int(params.BeaconConfig().MaxAttesterSlashings) {
|
||||||
t.Fatalf("Wanted %d attester slashings, got %d", 1, len(block.Body.AttesterSlashings))
|
t.Fatalf("Wanted %d attester slashings, got %d", params.BeaconConfig().MaxAttesterSlashings, len(block.Body.AttesterSlashings))
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(block.Body.AttesterSlashings[0], attesterSlashing) {
|
if !reflect.DeepEqual(block.Body.AttesterSlashings, attSlashings) {
|
||||||
t.Errorf("Wanted attester slashing %v, got %v", attesterSlashing, block.Body.AttesterSlashings)
|
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.SetupTestConfigCleanup(t)
|
||||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||||
|
|
||||||
genesis := b.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
t.Fatalf("Could not save genesis block: %v", err)
|
||||||
}
|
}
|
||||||
@@ -301,13 +313,9 @@ func TestProposeBlock_OK(t *testing.T) {
|
|||||||
HeadFetcher: c,
|
HeadFetcher: c,
|
||||||
BlockNotifier: c.BlockNotifier(),
|
BlockNotifier: c.BlockNotifier(),
|
||||||
}
|
}
|
||||||
req := ðpb.SignedBeaconBlock{
|
req := testutil.NewBeaconBlock()
|
||||||
Block: ðpb.BeaconBlock{
|
req.Block.Slot = 5
|
||||||
Slot: 5,
|
req.Block.ParentRoot = bytesutil.PadTo([]byte("parent-hash"), 32)
|
||||||
ParentRoot: []byte("parent-hash"),
|
|
||||||
Body: ðpb.BeaconBlockBody{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := db.SaveBlock(ctx, req); err != nil {
|
if err := db.SaveBlock(ctx, req); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -355,7 +363,7 @@ func TestComputeStateRoot_OK(t *testing.T) {
|
|||||||
|
|
||||||
req := ðpb.SignedBeaconBlock{
|
req := ðpb.SignedBeaconBlock{
|
||||||
Block: ðpb.BeaconBlock{
|
Block: ðpb.BeaconBlock{
|
||||||
ProposerIndex: 41,
|
ProposerIndex: 21,
|
||||||
ParentRoot: parentRoot[:],
|
ParentRoot: parentRoot[:],
|
||||||
Slot: 1,
|
Slot: 1,
|
||||||
Body: ðpb.BeaconBlockBody{
|
Body: ðpb.BeaconBlockBody{
|
||||||
@@ -1197,7 +1205,75 @@ func TestDefaultEth1Data_NoBlockExists(t *testing.T) {
|
|||||||
|
|
||||||
// TODO(2312): Add more tests for edge cases and better coverage.
|
// TODO(2312): Add more tests for edge cases and better coverage.
|
||||||
func TestEth1Data(t *testing.T) {
|
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{
|
p := &mockPOW.POWChain{
|
||||||
BlockNumberByHeight: map[uint64]*big.Int{
|
BlockNumberByHeight: map[uint64]*big.Int{
|
||||||
@@ -1214,7 +1290,8 @@ func TestEth1Data(t *testing.T) {
|
|||||||
ChainStartFetcher: p,
|
ChainStartFetcher: p,
|
||||||
Eth1InfoFetcher: p,
|
Eth1InfoFetcher: p,
|
||||||
Eth1BlockFetcher: p,
|
Eth1BlockFetcher: p,
|
||||||
DepositFetcher: depositcache.NewDepositCache(),
|
HeadFetcher: &mock.ChainService{ETH1Data: ðpb.Eth1Data{DepositCount: 10}},
|
||||||
|
DepositFetcher: depositCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -1223,8 +1300,10 @@ func TestEth1Data(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if eth1Data.DepositCount != 55 {
|
// Will default to 10 as the current deposit count in the
|
||||||
t.Error("Expected deposit count to be 55")
|
// 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.SetupTestConfigCleanup(t)
|
||||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||||
genesis := b.NewGenesisBlock([]byte{})
|
genesis := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
if err := db.SaveBlock(context.Background(), genesis); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
t.Fatalf("Could not save genesis block: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
"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"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
@@ -70,7 +69,7 @@ func TestWaitForActivation_ContextClosed(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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)
|
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
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)
|
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
t.Fatalf("Could not get signing root %v", err)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
"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"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||||
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
@@ -136,7 +135,7 @@ func TestValidatorStatus_Pending(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
pubKey := pubKey(1)
|
pubKey := pubKey(1)
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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.
|
// Active because activation epoch <= current epoch < exit epoch.
|
||||||
activeEpoch := helpers.ActivationExitEpoch(0)
|
activeEpoch := helpers.ActivationExitEpoch(0)
|
||||||
|
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
t.Fatalf("Could not save genesis block: %v", err)
|
||||||
}
|
}
|
||||||
@@ -301,7 +300,7 @@ func TestValidatorStatus_Exiting(t *testing.T) {
|
|||||||
epoch := helpers.SlotToEpoch(slot)
|
epoch := helpers.SlotToEpoch(slot)
|
||||||
exitEpoch := helpers.ActivationExitEpoch(epoch)
|
exitEpoch := helpers.ActivationExitEpoch(epoch)
|
||||||
withdrawableEpoch := exitEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
withdrawableEpoch := exitEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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 .
|
// Exit slashed because slashed is true, exit epoch is =< current epoch and withdrawable epoch > epoch .
|
||||||
slot := uint64(10000)
|
slot := uint64(10000)
|
||||||
epoch := helpers.SlotToEpoch(slot)
|
epoch := helpers.SlotToEpoch(slot)
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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.
|
// Exit because only exit epoch is =< current epoch.
|
||||||
slot := uint64(10000)
|
slot := uint64(10000)
|
||||||
epoch := helpers.SlotToEpoch(slot)
|
epoch := helpers.SlotToEpoch(slot)
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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)
|
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
t.Fatalf("Could not get signing root %v", err)
|
||||||
@@ -655,7 +654,7 @@ func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
pbKey := pubKey(5)
|
pbKey := pubKey(5)
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
if err := db.SaveBlock(ctx, block); err != nil {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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 {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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)
|
t.Fatalf("Could not get the deposit block slot %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := uint64(53)
|
expected := uint64(69)
|
||||||
|
|
||||||
if resp != expected {
|
if resp != expected {
|
||||||
t.Errorf("Wanted %v, got %v", expected, resp)
|
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 {
|
if err := db.SaveBlock(ctx, block); err != nil {
|
||||||
t.Fatalf("Could not save genesis block: %v", err)
|
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)
|
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
t.Fatalf("Could not get signing root %v", err)
|
||||||
@@ -995,7 +994,7 @@ func TestMultipleValidatorStatus_Pubkeys(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Status: ethpb.ValidatorStatus_DEPOSITED,
|
Status: ethpb.ValidatorStatus_DEPOSITED,
|
||||||
DepositInclusionSlot: 53,
|
DepositInclusionSlot: 69,
|
||||||
ActivationEpoch: 18446744073709551615,
|
ActivationEpoch: 18446744073709551615,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1059,7 +1058,7 @@ func TestMultipleValidatorStatus_Indices(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
stateObj, err := stateTrie.InitializeFromProtoUnsafe(beaconState)
|
stateObj, err := stateTrie.InitializeFromProtoUnsafe(beaconState)
|
||||||
block := blk.NewGenesisBlock([]byte{})
|
block := testutil.NewBeaconBlock()
|
||||||
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
genesisRoot, err := stateutil.BlockRoot(block.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get signing root %v", err)
|
t.Fatalf("Could not get signing root %v", err)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||||
|
|
||||||
//pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
//pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
@@ -245,23 +246,30 @@ func TestLastAncestorState_CanGet(t *testing.T) {
|
|||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
service := New(db, cache.NewStateSummaryCache())
|
service := New(db, cache.NewStateSummaryCache())
|
||||||
|
|
||||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: []byte{'a'}}
|
b0 := testutil.NewBeaconBlock()
|
||||||
r0, err := ssz.HashTreeRoot(b0)
|
b0.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
|
||||||
|
r0, err := ssz.HashTreeRoot(b0.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b1 := ðpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
|
b1 := testutil.NewBeaconBlock()
|
||||||
r1, err := ssz.HashTreeRoot(b1)
|
b1.Block.Slot = 1
|
||||||
|
b1.Block.ParentRoot = bytesutil.PadTo(r0[:], 32)
|
||||||
|
r1, err := ssz.HashTreeRoot(b1.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b2 := ðpb.BeaconBlock{Slot: 2, ParentRoot: r1[:]}
|
b2 := testutil.NewBeaconBlock()
|
||||||
r2, err := ssz.HashTreeRoot(b2)
|
b2.Block.Slot = 2
|
||||||
|
b2.Block.ParentRoot = bytesutil.PadTo(r1[:], 32)
|
||||||
|
r2, err := ssz.HashTreeRoot(b2.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b3 := ðpb.BeaconBlock{Slot: 3, ParentRoot: r2[:]}
|
b3 := testutil.NewBeaconBlock()
|
||||||
r3, err := ssz.HashTreeRoot(b3)
|
b3.Block.Slot = 3
|
||||||
|
b3.Block.ParentRoot = bytesutil.PadTo(r2[:], 32)
|
||||||
|
r3, err := ssz.HashTreeRoot(b3.Block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -271,16 +279,16 @@ func TestLastAncestorState_CanGet(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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)
|
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)
|
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)
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := service.beaconDB.SaveState(ctx, b1State, r1); err != nil {
|
if err := service.beaconDB.SaveState(ctx, b1State, r1); err != nil {
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ func TestLoadBlocks_FirstBranch(t *testing.T) {
|
|||||||
beaconDB: db,
|
beaconDB: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
roots, savedBlocks, err := tree1(db, []byte{'A'})
|
roots, savedBlocks, err := tree1(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -190,17 +190,20 @@ func TestLoadBlocks_FirstBranch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[8]},
|
savedBlocks[8],
|
||||||
{Block: savedBlocks[6]},
|
savedBlocks[6],
|
||||||
{Block: savedBlocks[4]},
|
savedBlocks[4],
|
||||||
{Block: savedBlocks[2]},
|
savedBlocks[2],
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_SecondBranch(t *testing.T) {
|
func TestLoadBlocks_SecondBranch(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -220,15 +223,18 @@ func TestLoadBlocks_SecondBranch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[5]},
|
savedBlocks[5],
|
||||||
{Block: savedBlocks[3]},
|
savedBlocks[3],
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_ThirdBranch(t *testing.T) {
|
func TestLoadBlocks_ThirdBranch(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -248,17 +254,20 @@ func TestLoadBlocks_ThirdBranch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[7]},
|
savedBlocks[7],
|
||||||
{Block: savedBlocks[6]},
|
savedBlocks[6],
|
||||||
{Block: savedBlocks[4]},
|
savedBlocks[4],
|
||||||
{Block: savedBlocks[2]},
|
savedBlocks[2],
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_SameSlots(t *testing.T) {
|
func TestLoadBlocks_SameSlots(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -278,15 +287,18 @@ func TestLoadBlocks_SameSlots(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[6]},
|
savedBlocks[6],
|
||||||
{Block: savedBlocks[5]},
|
savedBlocks[5],
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -295,7 +307,7 @@ func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
|||||||
beaconDB: db,
|
beaconDB: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
roots, savedBlocks, err := tree3(db, []byte{'A'})
|
roots, savedBlocks, err := tree3(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -306,14 +318,17 @@ func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[2]},
|
savedBlocks[2],
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -322,7 +337,7 @@ func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
|||||||
beaconDB: db,
|
beaconDB: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
roots, savedBlocks, err := tree4(db, []byte{'A'})
|
roots, savedBlocks, err := tree4(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -333,13 +348,16 @@ func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wanted := []*ethpb.SignedBeaconBlock{
|
wanted := []*ethpb.SignedBeaconBlock{
|
||||||
{Block: savedBlocks[1]},
|
savedBlocks[1],
|
||||||
{Block: savedBlocks[0]},
|
savedBlocks[0],
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(filteredBlocks, wanted) {
|
|
||||||
|
for i, block := range wanted {
|
||||||
|
if !proto.Equal(block, filteredBlocks[i]) {
|
||||||
t.Error("Did not get wanted blocks")
|
t.Error("Did not get wanted blocks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadBlocks_BadStart(t *testing.T) {
|
func TestLoadBlocks_BadStart(t *testing.T) {
|
||||||
db := testDB.SetupDB(t)
|
db := testDB.SetupDB(t)
|
||||||
@@ -348,7 +366,7 @@ func TestLoadBlocks_BadStart(t *testing.T) {
|
|||||||
beaconDB: db,
|
beaconDB: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
roots, _, err := tree1(db, []byte{'A'})
|
roots, _, err := tree1(db, bytesutil.PadTo([]byte{'A'}, 32))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -661,7 +679,7 @@ func TestProcessStateUpToSlot_CanProcess(t *testing.T) {
|
|||||||
// B0 - B1 - - B3 -- B5
|
// B0 - B1 - - B3 -- B5
|
||||||
// \- B2 -- B4 -- B6 ----- B8
|
// \- B2 -- B4 -- B6 ----- B8
|
||||||
// \- B7
|
// \- 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}
|
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||||
r0, err := ssz.HashTreeRoot(b0)
|
r0, err := ssz.HashTreeRoot(b0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -709,15 +727,20 @@ func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
}
|
}
|
||||||
st := testutil.NewBeaconState()
|
st := testutil.NewBeaconState()
|
||||||
|
|
||||||
|
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8} {
|
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
|
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
|
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:
|
// tree2 constructs the following tree:
|
||||||
@@ -726,7 +749,7 @@ func tree1(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
// \- B2
|
// \- B2
|
||||||
// \- B2
|
// \- B2
|
||||||
// \- B2 -- B3
|
// \- 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}
|
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||||
r0, err := ssz.HashTreeRoot(b0)
|
r0, err := ssz.HashTreeRoot(b0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -764,15 +787,21 @@ func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
}
|
}
|
||||||
st := testutil.NewBeaconState()
|
st := testutil.NewBeaconState()
|
||||||
|
|
||||||
|
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24, b3} {
|
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
|
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
|
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:
|
// tree3 constructs the following tree:
|
||||||
@@ -781,7 +810,7 @@ func tree2(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
// \- B2
|
// \- B2
|
||||||
// \- B2
|
// \- 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}
|
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||||
r0, err := ssz.HashTreeRoot(b0)
|
r0, err := ssz.HashTreeRoot(b0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -814,16 +843,22 @@ func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
}
|
}
|
||||||
st := testutil.NewBeaconState()
|
st := testutil.NewBeaconState()
|
||||||
|
|
||||||
|
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b21, b22, b23, b24} {
|
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
|
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
|
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:
|
// tree4 constructs the following tree:
|
||||||
@@ -832,7 +867,7 @@ func tree3(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
// \- B2
|
// \- B2
|
||||||
// \- B2
|
// \- 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}
|
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||||
r0, err := ssz.HashTreeRoot(b0)
|
r0, err := ssz.HashTreeRoot(b0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -860,14 +895,20 @@ func tree4(db db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.BeaconBlock
|
|||||||
}
|
}
|
||||||
st := testutil.NewBeaconState()
|
st := testutil.NewBeaconState()
|
||||||
|
|
||||||
|
returnedBlocks := []*ethpb.SignedBeaconBlock{}
|
||||||
for _, b := range []*ethpb.BeaconBlock{b0, b21, b22, b23, b24} {
|
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
|
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
|
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",
|
"service.go",
|
||||||
"subscriber.go",
|
"subscriber.go",
|
||||||
"subscriber_beacon_aggregate_proof.go",
|
"subscriber_beacon_aggregate_proof.go",
|
||||||
|
"subscriber_beacon_attestation.go",
|
||||||
"subscriber_beacon_blocks.go",
|
"subscriber_beacon_blocks.go",
|
||||||
"subscriber_committee_index_beacon_attestation.go",
|
|
||||||
"subscriber_handlers.go",
|
"subscriber_handlers.go",
|
||||||
"utils.go",
|
"utils.go",
|
||||||
"validate_aggregate_proof.go",
|
"validate_aggregate_proof.go",
|
||||||
"validate_attester_slashing.go",
|
"validate_attester_slashing.go",
|
||||||
|
"validate_beacon_attestation.go",
|
||||||
"validate_beacon_blocks.go",
|
"validate_beacon_blocks.go",
|
||||||
"validate_committee_index_beacon_attestation.go",
|
|
||||||
"validate_proposer_slashing.go",
|
"validate_proposer_slashing.go",
|
||||||
"validate_voluntary_exit.go",
|
"validate_voluntary_exit.go",
|
||||||
],
|
],
|
||||||
@@ -63,7 +63,6 @@ go_library(
|
|||||||
"//beacon-chain/state/stateutil:go_default_library",
|
"//beacon-chain/state/stateutil:go_default_library",
|
||||||
"//proto/beacon/p2p/v1:go_default_library",
|
"//proto/beacon/p2p/v1:go_default_library",
|
||||||
"//shared:go_default_library",
|
"//shared:go_default_library",
|
||||||
"//shared/attestationutil:go_default_library",
|
|
||||||
"//shared/bls:go_default_library",
|
"//shared/bls:go_default_library",
|
||||||
"//shared/bytesutil:go_default_library",
|
"//shared/bytesutil:go_default_library",
|
||||||
"//shared/featureconfig:go_default_library",
|
"//shared/featureconfig:go_default_library",
|
||||||
@@ -109,15 +108,15 @@ go_test(
|
|||||||
"rpc_test.go",
|
"rpc_test.go",
|
||||||
"service_test.go",
|
"service_test.go",
|
||||||
"subscriber_beacon_aggregate_proof_test.go",
|
"subscriber_beacon_aggregate_proof_test.go",
|
||||||
|
"subscriber_beacon_attestation_test.go",
|
||||||
"subscriber_beacon_blocks_test.go",
|
"subscriber_beacon_blocks_test.go",
|
||||||
"subscriber_committee_index_beacon_attestation_test.go",
|
|
||||||
"subscriber_test.go",
|
"subscriber_test.go",
|
||||||
"sync_test.go",
|
"sync_test.go",
|
||||||
"utils_test.go",
|
"utils_test.go",
|
||||||
"validate_aggregate_proof_test.go",
|
"validate_aggregate_proof_test.go",
|
||||||
"validate_attester_slashing_test.go",
|
"validate_attester_slashing_test.go",
|
||||||
|
"validate_beacon_attestation_test.go",
|
||||||
"validate_beacon_blocks_test.go",
|
"validate_beacon_blocks_test.go",
|
||||||
"validate_committee_index_beacon_attestation_test.go",
|
|
||||||
"validate_proposer_slashing_test.go",
|
"validate_proposer_slashing_test.go",
|
||||||
"validate_voluntary_exit_test.go",
|
"validate_voluntary_exit_test.go",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
|
||||||
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const genericError = "internal service error"
|
const genericError = "internal service error"
|
||||||
@@ -23,7 +24,10 @@ var responseCodeServerError = byte(0x02)
|
|||||||
|
|
||||||
func (r *Service) generateErrorResponse(code byte, reason string) ([]byte, error) {
|
func (r *Service) generateErrorResponse(code byte, reason string) ([]byte, error) {
|
||||||
buf := bytes.NewBuffer([]byte{code})
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,10 +46,12 @@ func ReadStatusCode(stream io.Reader, encoding encoder.NetworkEncoding) (uint8,
|
|||||||
return 0, "", nil
|
return 0, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := make([]byte, 0)
|
msg := &pb.ErrorResponse{
|
||||||
if err := encoding.DecodeWithLength(stream, &msg); err != nil {
|
Message: []byte{},
|
||||||
|
}
|
||||||
|
if err := encoding.DecodeWithLength(stream, msg); err != nil {
|
||||||
return 0, "", err
|
return 0, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return b[0], string(msg), nil
|
return b[0], string(msg.Message), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/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) {
|
func TestRegularSync_generateErrorResponse(t *testing.T) {
|
||||||
@@ -24,11 +25,11 @@ func TestRegularSync_generateErrorResponse(t *testing.T) {
|
|||||||
if b[0] != responseCodeServerError {
|
if b[0] != responseCodeServerError {
|
||||||
t.Errorf("The first byte was not the status code. Got %#x wanted %#x", b, responseCodeServerError)
|
t.Errorf("The first byte was not the status code. Got %#x wanted %#x", b, responseCodeServerError)
|
||||||
}
|
}
|
||||||
msg := make([]byte, 0)
|
msg := &pb.ErrorResponse{}
|
||||||
if err := r.p2p.Encoding().DecodeWithLength(buf, &msg); err != nil {
|
if err := r.p2p.Encoding().DecodeWithLength(buf, msg); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if string(msg) != "something bad happened" {
|
if string(msg.Message) != "something bad happened" {
|
||||||
t.Errorf("Received the wrong message: %v", msg)
|
t.Errorf("Received the wrong message: %v", msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,11 +464,15 @@ func (f *blocksFetcher) requestBlocks(
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
resp := make([]*eth.SignedBeaconBlock, 0, req.Count)
|
resp := make([]*eth.SignedBeaconBlock, 0, req.Count)
|
||||||
for {
|
for i := uint64(0); ; i++ {
|
||||||
blk, err := prysmsync.ReadChunkedBlock(stream, f.p2p)
|
blk, err := prysmsync.ReadChunkedBlock(stream, f.p2p)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// exit if more than max request blocks are returned
|
||||||
|
if i >= params.BeaconNetworkConfig().MaxRequestBlocks {
|
||||||
|
break
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func (r *Service) updateMetrics() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Errorf("Could not compute fork digest")
|
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 := p2p.GossipTypeMapping[reflect.TypeOf(&pb.Attestation{})]
|
||||||
attTopic += r.p2p.Encoding().ProtocolSuffix()
|
attTopic += r.p2p.Encoding().ProtocolSuffix()
|
||||||
for _, committeeIdx := range indices {
|
for _, committeeIdx := range indices {
|
||||||
@@ -99,7 +99,7 @@ func (r *Service) updateMetrics() {
|
|||||||
// We update all other gossip topics.
|
// We update all other gossip topics.
|
||||||
for topic := range p2p.GossipTopicMappings {
|
for topic := range p2p.GossipTopicMappings {
|
||||||
// We already updated attestation subnet topics.
|
// We already updated attestation subnet topics.
|
||||||
if strings.Contains(topic, "committee_index") {
|
if strings.Contains(topic, "beacon_attestation") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
topic += r.p2p.Encoding().ProtocolSuffix()
|
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 {
|
if err := s.sendRecentBeaconBlocksRequest(ctx, req, pid); err != nil {
|
||||||
traceutil.AnnotateError(span, err)
|
traceutil.AnnotateError(span, err)
|
||||||
log.Errorf("Could not send recent block request: %v", err)
|
log.Errorf("Could not send recent block request: %v", err)
|
||||||
|
|||||||
@@ -173,11 +173,13 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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{
|
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||||
SelectionProof: sig.Marshal(),
|
SelectionProof: sig.Marshal(),
|
||||||
Aggregate: att,
|
Aggregate: att,
|
||||||
AggregatorIndex: 33,
|
AggregatorIndex: aggregatorIndex,
|
||||||
}
|
}
|
||||||
attesterDomain, err = helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainAggregateAndProof, beaconState.GenesisValidatorRoot())
|
attesterDomain, err = helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainAggregateAndProof, beaconState.GenesisValidatorRoot())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -187,7 +189,7 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
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 {
|
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func (r *Service) processPendingBlocks(ctx context.Context) error {
|
|||||||
"currentSlot": b.Block.Slot,
|
"currentSlot": b.Block.Slot,
|
||||||
"parentRoot": hex.EncodeToString(bytesutil.Trunc(b.Block.ParentRoot)),
|
"parentRoot": hex.EncodeToString(bytesutil.Trunc(b.Block.ParentRoot)),
|
||||||
}).Info("Requesting parent block")
|
}).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
|
// 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.
|
// have a head slot newer than the block slot we are requesting.
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func (r *Service) registerRPCHandlers() {
|
|||||||
)
|
)
|
||||||
r.registerRPC(
|
r.registerRPC(
|
||||||
p2p.RPCBlocksByRootTopic,
|
p2p.RPCBlocksByRootTopic,
|
||||||
[][32]byte{},
|
&pb.BeaconBlocksByRootRequest{},
|
||||||
r.beaconBlocksRootRPCHandler,
|
r.beaconBlocksRootRPCHandler,
|
||||||
)
|
)
|
||||||
r.registerRPC(
|
r.registerRPC(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
libp2pcore "github.com/libp2p/go-libp2p-core"
|
libp2pcore "github.com/libp2p/go-libp2p-core"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
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/db/filters"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||||
"go.opencensus.io/trace"
|
"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.StringAttribute("peer", stream.Conn().RemotePeer().Pretty()),
|
||||||
trace.Int64Attribute("remaining_capacity", remainingBucketCapacity),
|
trace.Int64Attribute("remaining_capacity", remainingBucketCapacity),
|
||||||
)
|
)
|
||||||
|
maxRequestBlocks := params.BeaconNetworkConfig().MaxRequestBlocks
|
||||||
for startSlot <= endReqSlot {
|
for startSlot <= endReqSlot {
|
||||||
remainingBucketCapacity = r.blocksRateLimiter.Remaining(stream.Conn().RemotePeer().String())
|
remainingBucketCapacity = r.blocksRateLimiter.Remaining(stream.Conn().RemotePeer().String())
|
||||||
if int64(allowedBlocksPerSecond) > remainingBucketCapacity {
|
if int64(allowedBlocksPerSecond) > remainingBucketCapacity {
|
||||||
@@ -78,7 +79,7 @@ func (r *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(3147): Update this with reasonable constraints.
|
// 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)
|
r.writeErrorResponseToStream(responseCodeInvalidRequest, stepError, stream)
|
||||||
err := errors.New(stepError)
|
err := errors.New(stepError)
|
||||||
traceutil.AnnotateError(span, err)
|
traceutil.AnnotateError(span, err)
|
||||||
@@ -145,24 +146,29 @@ func (r *Service) writeBlockRangeToStream(ctx context.Context, startSlot, endSlo
|
|||||||
roots = append([][32]byte{genRoot}, roots...)
|
roots = append([][32]byte{genRoot}, roots...)
|
||||||
}
|
}
|
||||||
blks, roots = r.sortBlocksAndRoots(blks, 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 {
|
for i, b := range blks {
|
||||||
if b == nil || b.Block == nil {
|
if b == nil || b.Block == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
blk := b.Block
|
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
|
isRequestedSlotStep := (blk.Slot-startSlot)%step == 0
|
||||||
isRecentUnfinalizedSlot := blk.Slot >= helpers.StartSlot(checkpoint.Epoch+1) || checkpoint.Epoch == 0
|
if isRequestedSlotStep {
|
||||||
if isRequestedSlotStep && (isRecentUnfinalizedSlot || r.db.IsFinalizedBlock(ctx, roots[i])) {
|
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 {
|
if err := r.chunkWriter(stream, b); err != nil {
|
||||||
log.WithError(err).Error("Failed to send a chunked response")
|
log.WithError(err).Error("Failed to send a chunked response")
|
||||||
|
r.writeErrorResponseToStream(responseCodeServerError, genericError, stream)
|
||||||
|
traceutil.AnnotateError(span, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
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"
|
db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
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).
|
// 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")
|
pcl := protocol.ID("/testing")
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
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).
|
// 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")
|
pcl := protocol.ID("/testing")
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
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")
|
pcl := protocol.ID("/testing")
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -270,7 +273,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
capacity := int64(flags.Get().BlockBatchLimit * 3)
|
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{
|
req := &pb.BeaconBlocksByRangeRequest{
|
||||||
StartSlot: 100,
|
StartSlot: 100,
|
||||||
@@ -301,7 +304,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
capacity := int64(flags.Get().BlockBatchLimit * 3)
|
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{
|
req := &pb.BeaconBlocksByRangeRequest{
|
||||||
StartSlot: 100,
|
StartSlot: 100,
|
||||||
@@ -336,7 +339,7 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
capacity := int64(flags.Get().BlockBatchLimit * flags.Get().BlockBatchLimitBurstFactor)
|
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{
|
req := &pb.BeaconBlocksByRangeRequest{
|
||||||
StartSlot: 100,
|
StartSlot: 100,
|
||||||
|
|||||||
@@ -10,15 +10,19 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"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
|
// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get
|
||||||
// those corresponding blocks from that peer.
|
// 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)
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -32,6 +36,10 @@ func (r *Service) sendRecentBeaconBlocksRequest(ctx context.Context, blockRoots
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// Exit if peer sends more than max request blocks.
|
||||||
|
if uint64(i) >= params.BeaconNetworkConfig().MaxRequestBlocks {
|
||||||
|
break
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Unable to retrieve block from stream")
|
log.WithError(err).Error("Unable to retrieve block from stream")
|
||||||
return err
|
return err
|
||||||
@@ -62,11 +70,11 @@ func (r *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
|||||||
setRPCStreamDeadlines(stream)
|
setRPCStreamDeadlines(stream)
|
||||||
log := log.WithField("handler", "beacon_blocks_by_root")
|
log := log.WithField("handler", "beacon_blocks_by_root")
|
||||||
|
|
||||||
blockRoots, ok := msg.([][32]byte)
|
req, ok := msg.(*pbp2p.BeaconBlocksByRootRequest)
|
||||||
if !ok {
|
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")
|
resp, err := r.generateErrorResponse(responseCodeInvalidRequest, "no block roots provided in request")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Failed to generate a response error")
|
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")
|
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())
|
r.p2p.Peers().IncrementBadResponses(stream.Conn().RemotePeer())
|
||||||
if r.p2p.Peers().IsBad(stream.Conn().RemotePeer()) {
|
if r.p2p.Peers().IsBad(stream.Conn().RemotePeer()) {
|
||||||
log.Debug("Disconnecting bad peer")
|
log.Debug("Disconnecting bad peer")
|
||||||
@@ -99,10 +107,22 @@ func (r *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{
|
|||||||
return errors.New(rateLimitedError)
|
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 {
|
r.blocksRateLimiter.Add(stream.Conn().RemotePeer().String(), int64(len(req.BlockRoots)))
|
||||||
blk, err := r.db.Block(ctx, root)
|
|
||||||
|
for _, root := range req.BlockRoots {
|
||||||
|
blk, err := r.db.Block(ctx, bytesutil.ToBytes32(root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Failed to fetch block")
|
log.WithError(err).Error("Failed to fetch block")
|
||||||
resp, err := r.generateErrorResponse(responseCodeServerError, genericError)
|
resp, err := r.generateErrorResponse(responseCodeServerError, genericError)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
"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/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,7 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
d := db.SetupDB(t)
|
d := db.SetupDB(t)
|
||||||
|
|
||||||
var blkRoots [][32]byte
|
var blkRoots [][]byte
|
||||||
// Populate the database with blocks that would match the request.
|
// Populate the database with blocks that would match the request.
|
||||||
for i := 1; i < 11; i++ {
|
for i := 1; i < 11; i++ {
|
||||||
blk := ðpb.BeaconBlock{
|
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 {
|
if err := d.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: blk}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
blkRoots = append(blkRoots, root)
|
blkRoots = append(blkRoots, root[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
r := &Service{p2p: p1, db: d, blocksRateLimiter: leakybucket.NewCollector(10000, 10000, false)}
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
req := &pb.BeaconBlocksByRootRequest{BlockRoots: blkRoots}
|
||||||
err = r.beaconBlocksRootRPCHandler(context.Background(), blkRoots, stream1)
|
err = r.beaconBlocksRootRPCHandler(context.Background(), req, stream1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,7 @@ func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
|||||||
Root: blockBRoot[:],
|
Root: blockBRoot[:],
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedRoots := [][32]byte{blockBRoot, blockARoot}
|
expectedRoots := [][]byte{blockBRoot[:], blockARoot[:]}
|
||||||
|
|
||||||
r := &Service{
|
r := &Service{
|
||||||
p2p: p1,
|
p2p: p1,
|
||||||
@@ -132,12 +133,12 @@ func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
p2.Host.SetStreamHandler(pcl, func(stream network.Stream) {
|
p2.Host.SetStreamHandler(pcl, func(stream network.Stream) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
out := [][32]byte{}
|
out := &pb.BeaconBlocksByRootRequest{BlockRoots: [][]byte{}}
|
||||||
if err := p2.Encoding().DecodeWithLength(stream, &out); err != nil {
|
if err := p2.Encoding().DecodeWithLength(stream, out); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(out, expectedRoots) {
|
if !reflect.DeepEqual(out.BlockRoots, expectedRoots) {
|
||||||
t.Fatalf("Did not receive expected message. Got %+v wanted %+v", out, expectedRoots)
|
t.Fatalf("Did not receive expected message. Got %+v wanted %+v", out.BlockRoots, expectedRoots)
|
||||||
}
|
}
|
||||||
response := []*ethpb.SignedBeaconBlock{blockB, blockA}
|
response := []*ethpb.SignedBeaconBlock{blockB, blockA}
|
||||||
for _, blk := range response {
|
for _, blk := range response {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ type blockchainService interface {
|
|||||||
blockchain.AttestationReceiver
|
blockchain.AttestationReceiver
|
||||||
blockchain.TimeFetcher
|
blockchain.TimeFetcher
|
||||||
blockchain.GenesisFetcher
|
blockchain.GenesisFetcher
|
||||||
|
blockchain.CanonicalFetcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service is responsible for handling all run time p2p related operations as the
|
// 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"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
pb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
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/beacon-chain/p2p"
|
||||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||||
"github.com/prysmaticlabs/prysm/shared/messagehandler"
|
"github.com/prysmaticlabs/prysm/shared/messagehandler"
|
||||||
@@ -68,15 +67,16 @@ func (r *Service) registerSubscribers() {
|
|||||||
r.attesterSlashingSubscriber,
|
r.attesterSlashingSubscriber,
|
||||||
)
|
)
|
||||||
if featureconfig.Get().DisableDynamicCommitteeSubnets {
|
if featureconfig.Get().DisableDynamicCommitteeSubnets {
|
||||||
r.subscribeDynamic(
|
for i := uint64(0); i < params.BeaconNetworkConfig().AttestationSubnetCount; i++ {
|
||||||
"/eth2/%x/committee_index%d_beacon_attestation",
|
r.subscribe(
|
||||||
r.committeesCount, /* determineSubsLen */
|
fmt.Sprintf("/eth2/%%x/beacon_attestation_%d", i),
|
||||||
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
||||||
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
||||||
)
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
r.subscribeDynamicWithSubnets(
|
r.subscribeDynamicWithSubnets(
|
||||||
"/eth2/%x/committee_index%d_beacon_attestation",
|
"/eth2/%x/beacon_attestation_%d",
|
||||||
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
r.validateCommitteeIndexBeaconAttestation, /* validator */
|
||||||
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
r.committeeIndexBeaconAttestationSubscriber, /* message handler */
|
||||||
)
|
)
|
||||||
@@ -211,9 +211,9 @@ func (r *Service) subscribeDynamicWithSubnets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Persistent subscriptions from validators
|
// Persistent subscriptions from validators
|
||||||
persistentSubs := r.persistentCommitteeIndices()
|
persistentSubs := r.persistentSubnetIndices()
|
||||||
// Update desired topic indices for aggregator
|
// Update desired topic indices for aggregator
|
||||||
wantedSubs := r.aggregatorCommitteeIndices(currentSlot)
|
wantedSubs := r.aggregatorSubnetIndices(currentSlot)
|
||||||
|
|
||||||
// Combine subscriptions to get all requested subscriptions
|
// Combine subscriptions to get all requested subscriptions
|
||||||
wantedSubs = sliceutil.SetUint64(append(persistentSubs, wantedSubs...))
|
wantedSubs = sliceutil.SetUint64(append(persistentSubs, wantedSubs...))
|
||||||
@@ -225,7 +225,7 @@ func (r *Service) subscribeDynamicWithSubnets(
|
|||||||
r.subscribeAggregatorSubnet(subscriptions, idx, base, digest, validate, handle)
|
r.subscribeAggregatorSubnet(subscriptions, idx, base, digest, validate, handle)
|
||||||
}
|
}
|
||||||
// find desired subs for attesters
|
// find desired subs for attesters
|
||||||
attesterSubs := r.attesterCommitteeIndices(currentSlot)
|
attesterSubs := r.attesterSubnetIndices(currentSlot)
|
||||||
for _, idx := range attesterSubs {
|
for _, idx := range attesterSubs {
|
||||||
r.lookupAttesterSubnets(digest, idx)
|
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.
|
// revalidate that our currently connected subnets are valid.
|
||||||
func (r *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subscription,
|
func (r *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subscription,
|
||||||
wantedSubs []uint64, topicFormat string, digest [4]byte) {
|
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 {
|
if a.Message.Aggregate == nil || a.Message.Aggregate.Data == nil {
|
||||||
return errors.New("nil aggregate")
|
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
|
// Broadcast the aggregated attestation on a feed to notify other services in the beacon node
|
||||||
// of a received aggregated attestation.
|
// of a received aggregated attestation.
|
||||||
|
|||||||
@@ -46,34 +46,30 @@ func (r *Service) committeeIndexBeaconAttestationSubscriber(ctx context.Context,
|
|||||||
return r.attPool.SaveUnaggregatedAttestation(a)
|
return r.attPool.SaveUnaggregatedAttestation(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Service) committeesCount() int {
|
func (r *Service) subnetCount() int {
|
||||||
activeValidatorIndices, err := r.chain.HeadValidatorsIndices(helpers.SlotToEpoch(r.chain.HeadSlot()))
|
return int(params.BeaconNetworkConfig().AttestationSubnetCount)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return int(helpers.SlotCommitteeCount(uint64(len(activeValidatorIndices))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Service) persistentCommitteeIndices() []uint64 {
|
func (r *Service) persistentSubnetIndices() []uint64 {
|
||||||
return cache.CommitteeIDs.GetAllCommittees()
|
return cache.SubnetIDs.GetAllSubnets()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Service) aggregatorCommitteeIndices(currentSlot uint64) []uint64 {
|
func (r *Service) aggregatorSubnetIndices(currentSlot uint64) []uint64 {
|
||||||
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
||||||
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||||
commIds := []uint64{}
|
commIds := []uint64{}
|
||||||
for i := currentSlot; i <= endSlot; i++ {
|
for i := currentSlot; i <= endSlot; i++ {
|
||||||
commIds = append(commIds, cache.CommitteeIDs.GetAggregatorCommitteeIDs(i)...)
|
commIds = append(commIds, cache.SubnetIDs.GetAggregatorSubnetIDs(i)...)
|
||||||
}
|
}
|
||||||
return sliceutil.SetUint64(commIds)
|
return sliceutil.SetUint64(commIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Service) attesterCommitteeIndices(currentSlot uint64) []uint64 {
|
func (r *Service) attesterSubnetIndices(currentSlot uint64) []uint64 {
|
||||||
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
endEpoch := helpers.SlotToEpoch(currentSlot) + 1
|
||||||
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
endSlot := endEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||||
commIds := []uint64{}
|
commIds := []uint64{}
|
||||||
for i := currentSlot; i <= endSlot; i++ {
|
for i := currentSlot; i <= endSlot; i++ {
|
||||||
commIds = append(commIds, cache.CommitteeIDs.GetAttesterCommitteeIDs(i)...)
|
commIds = append(commIds, cache.SubnetIDs.GetAttesterSubnetIDs(i)...)
|
||||||
}
|
}
|
||||||
return sliceutil.SetUint64(commIds)
|
return sliceutil.SetUint64(commIds)
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func TestService_committeeIndexBeaconAttestationSubscriber_ValidMessage(t *testi
|
|||||||
}
|
}
|
||||||
att.Signature = sKeys[16].Sign(attRoot[:]).Marshal()
|
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)
|
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/helpers"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/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/bls"
|
||||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
"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 {
|
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"))
|
traceutil.AnnotateError(span, errors.Wrapf(err, "Could not validate index in committee"))
|
||||||
return pubsub.ValidationReject
|
return pubsub.ValidationReject
|
||||||
@@ -169,7 +168,7 @@ func (r *Service) setAggregatorIndexEpochSeen(epoch uint64, aggregatorIndex uint
|
|||||||
r.seenAttestationCache.Add(string(b), true)
|
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 {
|
func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *ethpb.Attestation, validatorIndex uint64) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "sync.validateIndexInCommittee")
|
ctx, span := trace.StartSpan(ctx, "sync.validateIndexInCommittee")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@@ -178,9 +177,8 @@ func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
attestingIndices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
|
||||||
var withinCommittee bool
|
var withinCommittee bool
|
||||||
for _, i := range attestingIndices {
|
for _, i := range committee {
|
||||||
if validatorIndex == i {
|
if validatorIndex == i {
|
||||||
withinCommittee = true
|
withinCommittee = true
|
||||||
break
|
break
|
||||||
@@ -188,7 +186,7 @@ func validateIndexInCommittee(ctx context.Context, s *stateTrie.BeaconState, a *
|
|||||||
}
|
}
|
||||||
if !withinCommittee {
|
if !withinCommittee {
|
||||||
return fmt.Errorf("validator index %d is not within the committee: %v",
|
return fmt.Errorf("validator index %d is not within the committee: %v",
|
||||||
validatorIndex, attestingIndices)
|
validatorIndex, committee)
|
||||||
}
|
}
|
||||||
return nil
|
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) {
|
func TestVerifySelection_NotAnAggregator(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
params.UseMinimalConfig()
|
params.UseMinimalConfig()
|
||||||
@@ -400,11 +431,11 @@ func TestValidateAggregateAndProofWithNewStateMgmt_CanValidate(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := privKeys[33].Sign(slotRoot[:])
|
sig := privKeys[22].Sign(slotRoot[:])
|
||||||
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||||
SelectionProof: sig.Marshal(),
|
SelectionProof: sig.Marshal(),
|
||||||
Aggregate: att,
|
Aggregate: att,
|
||||||
AggregatorIndex: 33,
|
AggregatorIndex: 22,
|
||||||
}
|
}
|
||||||
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
||||||
|
|
||||||
@@ -416,7 +447,7 @@ func TestValidateAggregateAndProofWithNewStateMgmt_CanValidate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
aggreSig := privKeys[33].Sign(signingRoot[:]).Marshal()
|
aggreSig := privKeys[22].Sign(signingRoot[:]).Marshal()
|
||||||
signedAggregateAndProof.Signature = aggreSig[:]
|
signedAggregateAndProof.Signature = aggreSig[:]
|
||||||
|
|
||||||
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||||
@@ -524,11 +555,11 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := privKeys[33].Sign(slotRoot[:])
|
sig := privKeys[22].Sign(slotRoot[:])
|
||||||
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
aggregateAndProof := ðpb.AggregateAttestationAndProof{
|
||||||
SelectionProof: sig.Marshal(),
|
SelectionProof: sig.Marshal(),
|
||||||
Aggregate: att,
|
Aggregate: att,
|
||||||
AggregatorIndex: 33,
|
AggregatorIndex: 22,
|
||||||
}
|
}
|
||||||
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
signedAggregateAndProof := ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
|
||||||
|
|
||||||
@@ -540,7 +571,7 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
aggreSig := privKeys[33].Sign(signingRoot[:]).Marshal()
|
aggreSig := privKeys[22].Sign(signingRoot[:]).Marshal()
|
||||||
signedAggregateAndProof.Signature = aggreSig[:]
|
signedAggregateAndProof.Signature = aggreSig[:]
|
||||||
|
|
||||||
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
if err := beaconState.SetGenesisTime(uint64(time.Now().Unix())); err != nil {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
"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/beacon-chain/p2p"
|
||||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||||
@@ -19,7 +20,7 @@ import (
|
|||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
// - The attestation's committee index (attestation.data.index) is for the correct subnet.
|
// - 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.
|
// - 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).
|
// - 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.
|
// - The signature of attestation is valid.
|
||||||
@@ -57,6 +58,11 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
|||||||
if att.Data == nil {
|
if att.Data == nil {
|
||||||
return pubsub.ValidationReject
|
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.
|
// Verify this the first attestation received for the participating validator for the slot.
|
||||||
if s.hasSeenCommitteeIndicesSlot(att.Data.Slot, att.Data.CommitteeIndex, att.AggregationBits) {
|
if s.hasSeenCommitteeIndicesSlot(att.Data.Slot, att.Data.CommitteeIndex, att.AggregationBits) {
|
||||||
return pubsub.ValidationIgnore
|
return pubsub.ValidationIgnore
|
||||||
@@ -69,12 +75,34 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
|||||||
traceutil.AnnotateError(span, err)
|
traceutil.AnnotateError(span, err)
|
||||||
return pubsub.ValidationIgnore
|
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
|
return pubsub.ValidationIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attestation must be unaggregated.
|
// Attestation must be unaggregated and the bit index must exist in the range of committee indices.
|
||||||
if att.AggregationBits == nil || att.AggregationBits.Count() != 1 {
|
// 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
|
return pubsub.ValidationReject
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,12 +123,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
|||||||
return pubsub.ValidationIgnore
|
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..
|
// Attestation's signature is a valid BLS signature and belongs to correct public key..
|
||||||
if !featureconfig.Get().DisableStrictAttestationPubsubVerification {
|
if !featureconfig.Get().DisableStrictAttestationPubsubVerification {
|
||||||
if err := blocks.VerifyAttestation(ctx, preState, att); err != nil {
|
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