diff --git a/beacon-chain/archiver/BUILD.bazel b/beacon-chain/archiver/BUILD.bazel index 47304321161d..6bdf783dc2c2 100644 --- a/beacon-chain/archiver/BUILD.bazel +++ b/beacon-chain/archiver/BUILD.bazel @@ -7,7 +7,6 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//beacon-chain/blockchain:go_default_library", - "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", @@ -16,6 +15,7 @@ go_library( "//proto/beacon/p2p/v1:go_default_library", "//shared/params:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], ) @@ -26,6 +26,7 @@ go_test( embed = [":go_default_library"], deps = [ "//beacon-chain/blockchain/testing:go_default_library", + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", diff --git a/beacon-chain/archiver/service.go b/beacon-chain/archiver/service.go index 0118743e061e..0328100e8b05 100644 --- a/beacon-chain/archiver/service.go +++ b/beacon-chain/archiver/service.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" - epochProcessing "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" @@ -22,30 +22,33 @@ var log = logrus.WithField("prefix", "archiver") // Service defining archiver functionality for persisting checkpointed // beacon chain information to a database backend for historical purposes. type Service struct { - ctx context.Context - cancel context.CancelFunc - beaconDB db.Database - headFetcher blockchain.HeadFetcher - stateNotifier statefeed.Notifier - lastArchivedEpoch uint64 + ctx context.Context + cancel context.CancelFunc + beaconDB db.Database + headFetcher blockchain.HeadFetcher + participationFetcher blockchain.ParticipationFetcher + stateNotifier statefeed.Notifier + lastArchivedEpoch uint64 } // Config options for the archiver service. type Config struct { - BeaconDB db.Database - HeadFetcher blockchain.HeadFetcher - StateNotifier statefeed.Notifier + BeaconDB db.Database + HeadFetcher blockchain.HeadFetcher + ParticipationFetcher blockchain.ParticipationFetcher + StateNotifier statefeed.Notifier } // NewArchiverService initializes the service from configuration options. func NewArchiverService(ctx context.Context, cfg *Config) *Service { ctx, cancel := context.WithCancel(ctx) return &Service{ - ctx: ctx, - cancel: cancel, - beaconDB: cfg.BeaconDB, - headFetcher: cfg.HeadFetcher, - stateNotifier: cfg.StateNotifier, + ctx: ctx, + cancel: cancel, + beaconDB: cfg.BeaconDB, + headFetcher: cfg.HeadFetcher, + participationFetcher: cfg.ParticipationFetcher, + stateNotifier: cfg.StateNotifier, } } @@ -113,10 +116,15 @@ func (s *Service) archiveActiveSetChanges(ctx context.Context, headState *pb.Bea // We compute participation metrics by first retrieving the head state and // matching validator attestations during the epoch. -func (s *Service) archiveParticipation(ctx context.Context, headState *pb.BeaconState, epoch uint64) error { - participation, err := epochProcessing.ComputeValidatorParticipation(headState, epoch) - if err != nil { - return errors.Wrap(err, "could not compute participation") +func (s *Service) archiveParticipation(ctx context.Context, epoch uint64) error { + p := s.participationFetcher.Participation(epoch) + participation := ðpb.ValidatorParticipation{} + if p != nil { + participation = ðpb.ValidatorParticipation{ + EligibleEther: p.PrevEpoch, + VotedEther: p.PrevEpochTargetAttesters, + GlobalParticipationRate: float32(p.PrevEpochTargetAttesters) / float32(p.PrevEpoch), + } } return s.beaconDB.SaveArchivedValidatorParticipation(ctx, epoch, participation) } @@ -161,7 +169,7 @@ func (s *Service) run(ctx context.Context) { log.WithError(err).Error("Could not archive active validator set changes") continue } - if err := s.archiveParticipation(ctx, headState, epochToArchive); err != nil { + if err := s.archiveParticipation(ctx, epochToArchive); err != nil { log.WithError(err).Error("Could not archive validator participation") continue } diff --git a/beacon-chain/archiver/service_test.go b/beacon-chain/archiver/service_test.go index b1bff3d822fc..e061b3bbf7f8 100644 --- a/beacon-chain/archiver/service_test.go +++ b/beacon-chain/archiver/service_test.go @@ -11,6 +11,7 @@ import ( ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-bitfield" mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" @@ -36,6 +37,7 @@ func TestArchiverService_ReceivesBlockProcessedEvent(t *testing.T) { svc.headFetcher = &mock.ChainService{ State: &pb.BeaconState{Slot: 1}, } + event := &feed.Event{ Type: statefeed.BlockProcessed, Data: &statefeed.BlockProcessedData{ @@ -144,6 +146,7 @@ func TestArchiverService_ComputesAndSavesParticipation(t *testing.T) { triggerStateEvent(t, svc, event) attestedBalance := uint64(1) + currentEpoch := helpers.CurrentEpoch(headState) wanted := ðpb.ValidatorParticipation{ VotedEther: attestedBalance, @@ -377,12 +380,16 @@ func setupState(t *testing.T, validatorCount uint64) *pb.BeaconState { func setupService(t *testing.T) (*Service, db.Database) { beaconDB := dbutil.SetupDB(t) ctx, cancel := context.WithCancel(context.Background()) + validatorCount := uint64(100) + totalBalance := validatorCount * params.BeaconConfig().MaxEffectiveBalance mockChainService := &mock.ChainService{} return &Service{ beaconDB: beaconDB, ctx: ctx, cancel: cancel, stateNotifier: mockChainService.StateNotifier(), + participationFetcher: &mock.ChainService{ + Balance: &precompute.Balance{PrevEpoch: totalBalance, PrevEpochTargetAttesters: 1}}, }, beaconDB } diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index 91a56fbae52f..febbe5f5cf61 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "//beacon-chain/blockchain/forkchoice:go_default_library", "//beacon-chain/cache/depositcache:go_default_library", "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index 798d34e7040e..5f26c4d897ee 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -7,6 +7,7 @@ import ( "github.com/gogo/protobuf/proto" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/params" @@ -55,6 +56,12 @@ type FinalizationFetcher interface { PreviousJustifiedCheckpt() *ethpb.Checkpoint } +// ParticipationFetcher defines a common interface for methods in blockchain service which +// directly retrieves validator participation related data. +type ParticipationFetcher interface { + Participation(epoch uint64) *precompute.Balance +} + // FinalizedCheckpt returns the latest finalized checkpoint from head state. func (s *Service) FinalizedCheckpt() *ethpb.Checkpoint { if s.headState == nil || s.headState.FinalizedCheckpoint == nil { @@ -183,3 +190,11 @@ func (s *Service) CurrentFork() *pb.Fork { } return proto.Clone(s.headState.Fork).(*pb.Fork) } + +// Participation returns the participation stats of a given epoch. +func (s *Service) Participation(epoch uint64) *precompute.Balance { + s.epochParticipationLock.RLock() + defer s.epochParticipationLock.RUnlock() + + return s.epochParticipation[epoch] +} diff --git a/beacon-chain/blockchain/receive_block.go b/beacon-chain/blockchain/receive_block.go index 35f3f4563ae7..4ad990450b9a 100644 --- a/beacon-chain/blockchain/receive_block.go +++ b/beacon-chain/blockchain/receive_block.go @@ -9,8 +9,10 @@ import ( "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" + "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" "github.com/prysmaticlabs/prysm/shared/traceutil" @@ -122,6 +124,10 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedB // Log state transition data. logStateTransitionData(blockCopy.Block, root[:]) + s.epochParticipationLock.Lock() + defer s.epochParticipationLock.Unlock() + s.epochParticipation[helpers.SlotToEpoch(blockCopy.Block.Slot)] = precompute.Balances + processedBlkNoPubsub.Inc() return nil @@ -168,6 +174,10 @@ func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *eth // Log state transition data. logStateTransitionData(blockCopy.Block, root[:]) + s.epochParticipationLock.Lock() + defer s.epochParticipationLock.Unlock() + s.epochParticipation[helpers.SlotToEpoch(blockCopy.Block.Slot)] = precompute.Balances + processedBlkNoPubsubForkchoice.Inc() return nil } @@ -226,6 +236,10 @@ func (s *Service) ReceiveBlockNoVerify(ctx context.Context, block *ethpb.SignedB "deposits": len(blockCopy.Block.Body.Deposits), }).Debug("Finished applying state transition") + s.epochParticipationLock.Lock() + defer s.epochParticipationLock.Unlock() + s.epochParticipation[helpers.SlotToEpoch(blockCopy.Block.Slot)] = precompute.Balances + return nil } diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 6db9bc7dd6bc..4b5f9cbac4f7 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -16,6 +16,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/forkchoice" "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" @@ -34,23 +35,25 @@ import ( // Service represents a service that handles the internal // logic of managing the full PoS beacon chain. type Service struct { - ctx context.Context - cancel context.CancelFunc - beaconDB db.Database - depositCache *depositcache.DepositCache - chainStartFetcher powchain.ChainStartFetcher - attPool attestations.Pool - forkChoiceStore forkchoice.ForkChoicer - genesisTime time.Time - p2p p2p.Broadcaster - maxRoutines int64 - headSlot uint64 - headBlock *ethpb.SignedBeaconBlock - headState *pb.BeaconState - canonicalRoots map[uint64][]byte - headLock sync.RWMutex - stateNotifier statefeed.Notifier - genesisRoot [32]byte + ctx context.Context + cancel context.CancelFunc + beaconDB db.Database + depositCache *depositcache.DepositCache + chainStartFetcher powchain.ChainStartFetcher + attPool attestations.Pool + forkChoiceStore forkchoice.ForkChoicer + genesisTime time.Time + p2p p2p.Broadcaster + maxRoutines int64 + headSlot uint64 + headBlock *ethpb.SignedBeaconBlock + headState *pb.BeaconState + canonicalRoots map[uint64][]byte + headLock sync.RWMutex + stateNotifier statefeed.Notifier + genesisRoot [32]byte + epochParticipation map[uint64]*precompute.Balance + epochParticipationLock sync.RWMutex } // Config options for the service. @@ -71,17 +74,18 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) { ctx, cancel := context.WithCancel(ctx) store := forkchoice.NewForkChoiceService(ctx, cfg.BeaconDB) return &Service{ - ctx: ctx, - cancel: cancel, - beaconDB: cfg.BeaconDB, - depositCache: cfg.DepositCache, - chainStartFetcher: cfg.ChainStartFetcher, - attPool: cfg.AttPool, - forkChoiceStore: store, - p2p: cfg.P2p, - canonicalRoots: make(map[uint64][]byte), - maxRoutines: cfg.MaxRoutines, - stateNotifier: cfg.StateNotifier, + ctx: ctx, + cancel: cancel, + beaconDB: cfg.BeaconDB, + depositCache: cfg.DepositCache, + chainStartFetcher: cfg.ChainStartFetcher, + attPool: cfg.AttPool, + forkChoiceStore: store, + p2p: cfg.P2p, + canonicalRoots: make(map[uint64][]byte), + maxRoutines: cfg.MaxRoutines, + stateNotifier: cfg.StateNotifier, + epochParticipation: make(map[uint64]*precompute.Balance), }, nil } diff --git a/beacon-chain/blockchain/testing/BUILD.bazel b/beacon-chain/blockchain/testing/BUILD.bazel index 2045190b7615..fbe6b0d0c57d 100644 --- a/beacon-chain/blockchain/testing/BUILD.bazel +++ b/beacon-chain/blockchain/testing/BUILD.bazel @@ -7,6 +7,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing", visibility = ["//beacon-chain:__subpackages__"], deps = [ + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/feed/operation:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index f82fc5da81b1..b8e02c917243 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" @@ -27,6 +28,7 @@ type ChainService struct { CurrentJustifiedCheckPoint *ethpb.Checkpoint PreviousJustifiedCheckPoint *ethpb.Checkpoint BlocksReceived []*ethpb.SignedBeaconBlock + Balance *precompute.Balance Genesis time.Time Fork *pb.Fork DB db.Database @@ -188,3 +190,8 @@ func (ms *ChainService) HeadSeed(epoch uint64) ([32]byte, error) { func (ms *ChainService) GenesisTime() time.Time { return ms.Genesis } + +// Participation mocks the same method in the chain service. +func (ms *ChainService) Participation(epoch uint64) *precompute.Balance { + return ms.Balance +} diff --git a/beacon-chain/cache/depositcache/pending_deposits.go b/beacon-chain/cache/depositcache/pending_deposits.go index ac9363f84fca..2f608c1bde40 100644 --- a/beacon-chain/cache/depositcache/pending_deposits.go +++ b/beacon-chain/cache/depositcache/pending_deposits.go @@ -5,10 +5,10 @@ import ( "math/big" "sort" - dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" + dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" "github.com/prysmaticlabs/prysm/shared/hashutil" log "github.com/sirupsen/logrus" "go.opencensus.io/trace" diff --git a/beacon-chain/cache/depositcache/pending_deposits_test.go b/beacon-chain/cache/depositcache/pending_deposits_test.go index 97a275d62477..61af642304b4 100644 --- a/beacon-chain/cache/depositcache/pending_deposits_test.go +++ b/beacon-chain/cache/depositcache/pending_deposits_test.go @@ -6,9 +6,9 @@ import ( "reflect" "testing" - dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" "github.com/gogo/protobuf/proto" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" + dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" ) var _ = PendingDepositsFetcher(&DepositCache{}) diff --git a/beacon-chain/core/epoch/BUILD.bazel b/beacon-chain/core/epoch/BUILD.bazel index 14f9a012cc6a..0e988b3f637b 100644 --- a/beacon-chain/core/epoch/BUILD.bazel +++ b/beacon-chain/core/epoch/BUILD.bazel @@ -2,10 +2,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = [ - "epoch_processing.go", - "participation.go", - ], + srcs = ["epoch_processing.go"], importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch", visibility = ["//beacon-chain:__subpackages__"], deps = [ @@ -26,13 +23,11 @@ go_test( srcs = [ "epoch_processing_fuzz_test.go", "epoch_processing_test.go", - "participation_test.go", ], embed = [":go_default_library"], deps = [ "//beacon-chain/core/helpers:go_default_library", "//proto/beacon/p2p/v1:go_default_library", - "//shared/bytesutil:go_default_library", "//shared/params:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library", "@com_github_google_gofuzz//:go_default_library", diff --git a/beacon-chain/core/epoch/epoch_processing.go b/beacon-chain/core/epoch/epoch_processing.go index 3deb2cf8c04a..11e96b0d2c6f 100644 --- a/beacon-chain/core/epoch/epoch_processing.go +++ b/beacon-chain/core/epoch/epoch_processing.go @@ -5,7 +5,6 @@ package epoch import ( - "bytes" "fmt" "sort" @@ -34,81 +33,6 @@ func (s sortableIndices) Less(i, j int) bool { return epochState.Validators[s[i]].ActivationEligibilityEpoch < epochState.Validators[s[j]].ActivationEligibilityEpoch } -// MatchedAttestations is an object that contains the correctly -// voted attestations based on source, target and head criteria. -type MatchedAttestations struct { - source []*pb.PendingAttestation - Target []*pb.PendingAttestation - head []*pb.PendingAttestation -} - -// MatchAttestations matches the attestations gathered in a span of an epoch -// and categorize them whether they correctly voted for source, target and head. -// We combined the individual helpers from spec for efficiency and to achieve O(N) run time. -// -// Spec pseudocode definition: -// def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: -// assert epoch in (get_current_epoch(state), get_previous_epoch(state)) -// return state.current_epoch_attestations if epoch == get_current_epoch(state) else state.previous_epoch_attestations -// -// def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: -// return [ -// a for a in get_matching_source_attestations(state, epoch) -// if a.data.target_root == get_block_root(state, epoch) -// ] -// -// def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: -// return [ -// a for a in get_matching_source_attestations(state, epoch) -// if a.data.beacon_block_root == get_block_root_at_slot(state, get_attestation_data_slot(state, a.data)) -// ] -func MatchAttestations(state *pb.BeaconState, epoch uint64) (*MatchedAttestations, error) { - currentEpoch := helpers.CurrentEpoch(state) - previousEpoch := helpers.PrevEpoch(state) - - // Input epoch for matching the source attestations has to be within range - // of current epoch & previous epoch. - if epoch != currentEpoch && epoch != previousEpoch { - return nil, fmt.Errorf("input epoch: %d != current epoch: %d or previous epoch: %d", - epoch, currentEpoch, previousEpoch) - } - - // Decide if the source attestations are coming from current or previous epoch. - var srcAtts []*pb.PendingAttestation - if epoch == currentEpoch { - srcAtts = state.CurrentEpochAttestations - } else { - srcAtts = state.PreviousEpochAttestations - } - targetRoot, err := helpers.BlockRoot(state, epoch) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for epoch %d", epoch) - } - - tgtAtts := make([]*pb.PendingAttestation, 0, len(srcAtts)) - headAtts := make([]*pb.PendingAttestation, 0, len(srcAtts)) - for _, srcAtt := range srcAtts { - // If the target root matches attestation's target root, - // then we know this attestation has correctly voted for target. - if bytes.Equal(srcAtt.Data.Target.Root, targetRoot) { - tgtAtts = append(tgtAtts, srcAtt) - } - headRoot, err := helpers.BlockRootAtSlot(state, srcAtt.Data.Slot) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for slot %d", srcAtt.Data.Slot) - } - if bytes.Equal(srcAtt.Data.BeaconBlockRoot, headRoot) { - headAtts = append(headAtts, srcAtt) - } - } - - return &MatchedAttestations{ - source: srcAtts, - Target: tgtAtts, - head: headAtts, - }, nil -} - // AttestingBalance returns the total balance from all the attesting indices. // // WARNING: This method allocates a new copy of the attesting validator indices set and is diff --git a/beacon-chain/core/epoch/epoch_processing_test.go b/beacon-chain/core/epoch/epoch_processing_test.go index 33616fe6f9d7..8ac82a568d3b 100644 --- a/beacon-chain/core/epoch/epoch_processing_test.go +++ b/beacon-chain/core/epoch/epoch_processing_test.go @@ -2,8 +2,6 @@ package epoch import ( "bytes" - "reflect" - "strings" "testing" "github.com/gogo/protobuf/proto" @@ -149,154 +147,6 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) { } } -func TestMatchAttestations_PrevEpoch(t *testing.T) { - e := params.BeaconConfig().SlotsPerEpoch - s := uint64(0) // slot - - // The correct epoch for source is the first epoch - // The correct vote for target is '1' - // The correct vote for head is '2' - prevAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // source - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{3}}}}, // source - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}}, // source, head - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}}, // source - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target, head - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // source, head - } - - currentAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // none - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none - } - - blockRoots := make([][]byte, 128) - for i := 0; i < len(blockRoots); i++ { - blockRoots[i] = []byte{byte(i + 1)} - } - state := &pb.BeaconState{ - Slot: s + e + 2, - CurrentEpochAttestations: currentAtts, - PreviousEpochAttestations: prevAtts, - BlockRoots: blockRoots, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - } - - mAtts, err := MatchAttestations(state, 0) - if err != nil { - t.Fatal(err) - } - - wantedSrcAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{3}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, - } - if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) { - t.Error("source attestations don't match") - } - - wantedTgtAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - } - if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) { - t.Error("target attestations don't match") - } - - wantedHeadAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, - } - - if !reflect.DeepEqual(mAtts.head, wantedHeadAtts) { - t.Error("head attestations don't match") - } -} - -func TestMatchAttestations_CurrentEpoch(t *testing.T) { - e := params.BeaconConfig().SlotsPerEpoch - s := uint64(0) // slot - - // The correct epoch for source is the first epoch - // The correct vote for target is '33' - // The correct vote for head is '34' - prevAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // none - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // none - } - - currentAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // source - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, // source, target, head - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, // source, target - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{68}}}}, // source, head - } - - blockRoots := make([][]byte, 128) - for i := 0; i < len(blockRoots); i++ { - blockRoots[i] = []byte{byte(i + 1)} - } - state := &pb.BeaconState{ - Slot: s + e + 2, - CurrentEpochAttestations: currentAtts, - PreviousEpochAttestations: prevAtts, - BlockRoots: blockRoots, - } - - mAtts, err := MatchAttestations(state, 1) - if err != nil { - t.Fatal(err) - } - - wantedSrcAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{68}}}}, - } - if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) { - t.Error("source attestations don't match") - } - - wantedTgtAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, - {Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, - } - if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) { - t.Error("target attestations don't match") - } - - wantedHeadAtts := []*pb.PendingAttestation{ - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, - {Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{68}}}}, - } - if !reflect.DeepEqual(mAtts.head, wantedHeadAtts) { - t.Error("head attestations don't match") - } -} - -func TestMatchAttestations_EpochOutOfBound(t *testing.T) { - _, err := MatchAttestations(&pb.BeaconState{Slot: 1}, 2 /* epoch */) - if !strings.Contains(err.Error(), "input epoch: 2 != current epoch: 0") { - t.Fatal("Did not receive wanted error") - } -} - func TestBaseReward_AccurateRewards(t *testing.T) { tests := []struct { a uint64 diff --git a/beacon-chain/core/epoch/participation.go b/beacon-chain/core/epoch/participation.go deleted file mode 100644 index 57f4e2211d56..000000000000 --- a/beacon-chain/core/epoch/participation.go +++ /dev/null @@ -1,44 +0,0 @@ -package epoch - -import ( - "fmt" - - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" - "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" -) - -// ComputeValidatorParticipation by matching validator attestations from the previous epoch, -// computing the attesting balance, and how much attested compared to the total balance. -// The previous epoch is used because it is deterministic, as the current epoch may not -// have completed yet and will not give accurate results. -func ComputeValidatorParticipation(state *pb.BeaconState, epoch uint64) (*ethpb.ValidatorParticipation, error) { - currentEpoch := helpers.CurrentEpoch(state) - previousEpoch := helpers.PrevEpoch(state) - if epoch != currentEpoch && epoch != previousEpoch { - return nil, fmt.Errorf( - "requested epoch is not previous epoch %d or current epoch %d, requested %d", - previousEpoch, - currentEpoch, - epoch, - ) - } - atts, err := MatchAttestations(state, epoch) - if err != nil { - return nil, errors.Wrap(err, "could not retrieve head attestations") - } - attestedBalances, err := AttestingBalance(state, atts.Target) - if err != nil { - return nil, errors.Wrap(err, "could not retrieve attested balances") - } - totalBalances, err := helpers.TotalActiveBalance(state) - if err != nil { - return nil, errors.Wrap(err, "could not retrieve total balances") - } - return ðpb.ValidatorParticipation{ - GlobalParticipationRate: float32(attestedBalances) / float32(totalBalances), - VotedEther: attestedBalances, - EligibleEther: totalBalances, - }, nil -} diff --git a/beacon-chain/core/epoch/participation_test.go b/beacon-chain/core/epoch/participation_test.go deleted file mode 100644 index 9d207d9ff335..000000000000 --- a/beacon-chain/core/epoch/participation_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package epoch_test - -import ( - "reflect" - "testing" - - ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" - pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" - "github.com/prysmaticlabs/prysm/shared/bytesutil" - "github.com/prysmaticlabs/prysm/shared/params" -) - -func TestComputeValidatorParticipation_PreviousEpoch(t *testing.T) { - params.OverrideBeaconConfig(params.MinimalSpecConfig()) - e := uint64(1) - attestedBalance := uint64(20) * params.BeaconConfig().MaxEffectiveBalance - validatorCount := uint64(100) - - validators := make([]*ethpb.Validator, validatorCount) - balances := make([]uint64, validatorCount) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - } - balances[i] = params.BeaconConfig().MaxEffectiveBalance - } - - blockRoots := make([][]byte, 256) - for i := 0; i < len(blockRoots); i++ { - slot := bytesutil.Bytes32(uint64(i)) - blockRoots[i] = slot - } - target := ðpb.Checkpoint{ - Epoch: e, - Root: blockRoots[0], - } - - atts := []*pb.PendingAttestation{ - { - Data: ðpb.AttestationData{Target: target, Slot: 0}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: 1}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: 2}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: 3}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: 4}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - } - - s := &pb.BeaconState{ - Slot: e*params.BeaconConfig().SlotsPerEpoch + 1, - Validators: validators, - Balances: balances, - BlockRoots: blockRoots, - Slashings: []uint64{0, 1e9, 1e9}, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - PreviousEpochAttestations: atts, - FinalizedCheckpoint: ðpb.Checkpoint{}, - JustificationBits: bitfield.Bitvector4{0x00}, - PreviousJustifiedCheckpoint: target, - } - - res, err := epoch.ComputeValidatorParticipation(s, e-1) - if err != nil { - t.Fatal(err) - } - - wanted := ðpb.ValidatorParticipation{ - VotedEther: attestedBalance, - EligibleEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance, - GlobalParticipationRate: float32(attestedBalance) / float32(validatorCount*params.BeaconConfig().MaxEffectiveBalance), - } - - if !reflect.DeepEqual(res, wanted) { - t.Errorf("Incorrect validator participation, wanted %v received %v", wanted, res) - } -} - -func TestComputeValidatorParticipation_CurrentEpoch(t *testing.T) { - params.OverrideBeaconConfig(params.MinimalSpecConfig()) - e := uint64(1) - attestedBalance := uint64(16) * params.BeaconConfig().MaxEffectiveBalance - validatorCount := uint64(100) - - validators := make([]*ethpb.Validator, validatorCount) - balances := make([]uint64, validatorCount) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - } - balances[i] = params.BeaconConfig().MaxEffectiveBalance - } - - slot := e*params.BeaconConfig().SlotsPerEpoch + 4 - blockRoots := make([][]byte, 256) - for i := 0; i < len(blockRoots); i++ { - slot := bytesutil.Bytes32(uint64(i)) - blockRoots[i] = slot - } - target := ðpb.Checkpoint{ - Epoch: e, - Root: blockRoots[params.BeaconConfig().SlotsPerEpoch], - } - - atts := []*pb.PendingAttestation{ - { - Data: ðpb.AttestationData{Target: target, Slot: slot - 4}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: slot - 3}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: slot - 2}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - { - Data: ðpb.AttestationData{Target: target, Slot: slot - 1}, - AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF}, - }, - } - - s := &pb.BeaconState{ - Slot: slot, - Validators: validators, - Balances: balances, - BlockRoots: blockRoots, - Slashings: []uint64{0, 1e9, 1e9}, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - CurrentEpochAttestations: atts, - FinalizedCheckpoint: ðpb.Checkpoint{}, - JustificationBits: bitfield.Bitvector4{0x00}, - CurrentJustifiedCheckpoint: target, - } - - res, err := epoch.ComputeValidatorParticipation(s, e) - if err != nil { - t.Fatal(err) - } - - wanted := ðpb.ValidatorParticipation{ - VotedEther: attestedBalance, - EligibleEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance, - GlobalParticipationRate: float32(attestedBalance) / float32(validatorCount*params.BeaconConfig().MaxEffectiveBalance), - } - - if !reflect.DeepEqual(res, wanted) { - t.Errorf("Incorrect validator participation, wanted %v received %v", wanted, res) - } -} diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index 94863985029b..204b81a4eb83 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -460,6 +460,7 @@ func (b *BeaconNode) registerRPCService(ctx *cli.Context) error { HeadFetcher: chainService, ForkFetcher: chainService, FinalizationFetcher: chainService, + ParticipationFetcher: chainService, BlockReceiver: chainService, AttestationReceiver: chainService, GenesisTimeFetcher: chainService, @@ -543,9 +544,10 @@ func (b *BeaconNode) registerArchiverService(ctx *cli.Context) error { return err } svc := archiver.NewArchiverService(context.Background(), &archiver.Config{ - BeaconDB: b.db, - HeadFetcher: chainService, - StateNotifier: b, + BeaconDB: b.db, + HeadFetcher: chainService, + ParticipationFetcher: chainService, + StateNotifier: b, }) return b.services.RegisterService(svc) } diff --git a/beacon-chain/powchain/log_processing.go b/beacon-chain/powchain/log_processing.go index 2062b4a7f11b..6882cd641022 100644 --- a/beacon-chain/powchain/log_processing.go +++ b/beacon-chain/powchain/log_processing.go @@ -394,6 +394,7 @@ func (s *Service) checkBlockNumberForChainStart(ctx context.Context, blkNum *big if hash == [32]byte{} { return errors.Wrap(err, "got empty block hash") } + timeStamp, err := s.BlockTimeByHeight(ctx, blkNum) if err != nil { return errors.Wrap(err, "could not get block timestamp") diff --git a/beacon-chain/powchain/log_processing_test.go b/beacon-chain/powchain/log_processing_test.go index 781abecfe9b1..476942d2d89c 100644 --- a/beacon-chain/powchain/log_processing_test.go +++ b/beacon-chain/powchain/log_processing_test.go @@ -713,6 +713,7 @@ func newPowchainService(t *testing.T, eth1Backend *contracts.TestAccount, beacon if err != nil { t.Fatal(err) } + web3Service.rpcClient = &mockPOW.RPCClient{Backend: eth1Backend.Backend} web3Service.reader = &goodReader{backend: eth1Backend.Backend} web3Service.blockFetcher = &goodFetcher{backend: eth1Backend.Backend} diff --git a/beacon-chain/powchain/testing/mock.go b/beacon-chain/powchain/testing/mock.go index fb596f4a70ad..7ede3d580204 100644 --- a/beacon-chain/powchain/testing/mock.go +++ b/beacon-chain/powchain/testing/mock.go @@ -7,10 +7,10 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/common" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/bytesutil" diff --git a/beacon-chain/rpc/beacon/BUILD.bazel b/beacon-chain/rpc/beacon/BUILD.bazel index 917911cba4f2..98a5085a6e81 100644 --- a/beacon-chain/rpc/beacon/BUILD.bazel +++ b/beacon-chain/rpc/beacon/BUILD.bazel @@ -14,7 +14,6 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//beacon-chain/blockchain:go_default_library", - "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", @@ -52,6 +51,7 @@ go_test( shard_count = 4, deps = [ "//beacon-chain/blockchain/testing:go_default_library", + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", diff --git a/beacon-chain/rpc/beacon/server.go b/beacon-chain/rpc/beacon/server.go index 3d5a6ab52194..fbbcafef9221 100644 --- a/beacon-chain/rpc/beacon/server.go +++ b/beacon-chain/rpc/beacon/server.go @@ -18,15 +18,16 @@ import ( // providing RPC endpoints to access data relevant to the Ethereum 2.0 phase 0 // beacon chain. type Server struct { - BeaconDB db.Database - Ctx context.Context - ChainStartFetcher powchain.ChainStartFetcher - HeadFetcher blockchain.HeadFetcher - FinalizationFetcher blockchain.FinalizationFetcher - StateNotifier statefeed.Notifier - Pool attestations.Pool - IncomingAttestation chan *ethpb.Attestation - CanonicalStateChan chan *pbp2p.BeaconState - ChainStartChan chan time.Time - SlotTicker slotutil.Ticker + BeaconDB db.Database + Ctx context.Context + ChainStartFetcher powchain.ChainStartFetcher + HeadFetcher blockchain.HeadFetcher + FinalizationFetcher blockchain.FinalizationFetcher + ParticipationFetcher blockchain.ParticipationFetcher + StateNotifier statefeed.Notifier + Pool attestations.Pool + IncomingAttestation chan *ethpb.Attestation + CanonicalStateChan chan *pbp2p.BeaconState + ChainStartChan chan time.Time + SlotTicker slotutil.Ticker } diff --git a/beacon-chain/rpc/beacon/validators.go b/beacon-chain/rpc/beacon/validators.go index a933b3fa70ef..884c709d10b3 100644 --- a/beacon-chain/rpc/beacon/validators.go +++ b/beacon-chain/rpc/beacon/validators.go @@ -8,7 +8,6 @@ import ( ptypes "github.com/gogo/protobuf/types" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" - "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/validators" @@ -442,12 +441,13 @@ func (bs *Server) GetValidatorParticipation( ) } - // Else if the request is for the current epoch, we compute validator participation - // right away and return the result based on the head state. - participation, err := epoch.ComputeValidatorParticipation(headState, requestedEpoch) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not compute participation: %v", err) + p := bs.ParticipationFetcher.Participation(requestedEpoch) + participation := ðpb.ValidatorParticipation{ + EligibleEther: p.PrevEpoch, + VotedEther: p.PrevEpochTargetAttesters, + GlobalParticipationRate: float32(p.PrevEpochTargetAttesters) / float32(p.PrevEpoch), } + return ðpb.ValidatorParticipationResponse{ Epoch: requestedEpoch, Finalized: requestedEpoch <= headState.FinalizedCheckpoint.Epoch, diff --git a/beacon-chain/rpc/beacon/validators_test.go b/beacon-chain/rpc/beacon/validators_test.go index 297e9a7661d7..1c0d7f157b34 100644 --- a/beacon-chain/rpc/beacon/validators_test.go +++ b/beacon-chain/rpc/beacon/validators_test.go @@ -14,6 +14,7 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/go-ssz" mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/db" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" @@ -1456,9 +1457,17 @@ func TestServer_GetValidatorParticipation_PrevEpoch(t *testing.T) { CurrentJustifiedCheckpoint: ðpb.Checkpoint{}, } + m := &mock.ChainService{ + State: s, + Balance: &precompute.Balance{ + PrevEpoch: validatorCount * params.BeaconConfig().MaxEffectiveBalance, + PrevEpochTargetAttesters: attestedBalance, + }, + } bs := &Server{ - BeaconDB: db, - HeadFetcher: &mock.ChainService{State: s}, + BeaconDB: db, + HeadFetcher: m, + ParticipationFetcher: m, } res, err := bs.GetValidatorParticipation(ctx, ðpb.GetValidatorParticipationRequest{}) diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index 0c6f2dc408f2..bb06a361318b 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -54,6 +54,7 @@ type Service struct { headFetcher blockchain.HeadFetcher forkFetcher blockchain.ForkFetcher finalizationFetcher blockchain.FinalizationFetcher + participationFetcher blockchain.ParticipationFetcher genesisTimeFetcher blockchain.GenesisTimeFetcher attestationReceiver blockchain.AttestationReceiver blockReceiver blockchain.BlockReceiver @@ -87,6 +88,7 @@ type Config struct { HeadFetcher blockchain.HeadFetcher ForkFetcher blockchain.ForkFetcher FinalizationFetcher blockchain.FinalizationFetcher + ParticipationFetcher blockchain.ParticipationFetcher AttestationReceiver blockchain.AttestationReceiver BlockReceiver blockchain.BlockReceiver POWChainService powchain.Chain @@ -114,6 +116,7 @@ func NewService(ctx context.Context, cfg *Config) *Service { headFetcher: cfg.HeadFetcher, forkFetcher: cfg.ForkFetcher, finalizationFetcher: cfg.FinalizationFetcher, + participationFetcher: cfg.ParticipationFetcher, genesisTimeFetcher: cfg.GenesisTimeFetcher, attestationReceiver: cfg.AttestationReceiver, blockReceiver: cfg.BlockReceiver, @@ -209,15 +212,16 @@ func (s *Service) Start() { PeersFetcher: s.peersFetcher, } beaconChainServer := &beacon.Server{ - Ctx: s.ctx, - BeaconDB: s.beaconDB, - Pool: s.attestationsPool, - HeadFetcher: s.headFetcher, - FinalizationFetcher: s.finalizationFetcher, - ChainStartFetcher: s.chainStartFetcher, - CanonicalStateChan: s.canonicalStateChan, - StateNotifier: s.stateNotifier, - SlotTicker: ticker, + Ctx: s.ctx, + BeaconDB: s.beaconDB, + Pool: s.attestationsPool, + HeadFetcher: s.headFetcher, + FinalizationFetcher: s.finalizationFetcher, + ParticipationFetcher: s.participationFetcher, + ChainStartFetcher: s.chainStartFetcher, + CanonicalStateChan: s.canonicalStateChan, + StateNotifier: s.stateNotifier, + SlotTicker: ticker, } aggregatorServer := &aggregator.Server{ BeaconDB: s.beaconDB, diff --git a/beacon-chain/rpc/validator/proposer.go b/beacon-chain/rpc/validator/proposer.go index ba4fcf10015a..ba31b9161894 100644 --- a/beacon-chain/rpc/validator/proposer.go +++ b/beacon-chain/rpc/validator/proposer.go @@ -6,7 +6,6 @@ import ( "math/big" "math/rand" - dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -14,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop" + dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/hashutil" diff --git a/endtoend/endtoend_test.go b/endtoend/endtoend_test.go index 6e70d85e4a48..f6f2daf9e07a 100644 --- a/endtoend/endtoend_test.go +++ b/endtoend/endtoend_test.go @@ -81,7 +81,7 @@ func runEndToEndTest(t *testing.T, config *end2EndConfig) { currentEpoch := uint64(0) ticker := GetEpochTicker(genesisTime, epochSeconds) for c := range ticker.C() { - if c >= config.epochsToRun || t.Failed() { + if c >= config.epochsToRun || t.Failed() { ticker.Done() break } @@ -150,7 +150,6 @@ func killProcesses(t *testing.T, pIDs []int) { } } - func logOutput(t *testing.T, tmpPath string, config *end2EndConfig) { if t.Failed() { // Log out errors from beacon chain nodes. diff --git a/endtoend/evaluators/validator.go b/endtoend/evaluators/validator.go index e8e8e2d3ad7e..cf5d6c0d85d0 100644 --- a/endtoend/evaluators/validator.go +++ b/endtoend/evaluators/validator.go @@ -27,7 +27,7 @@ var ValidatorsAreActive = Evaluator{ // ValidatorsParticipating ensures the expected amount of validators are active. var ValidatorsParticipating = Evaluator{ Name: "validators_participating_epoch_%d", - Policy: afterNthEpoch(1), + Policy: afterNthEpoch(3), Evaluation: validatorsParticipating, } diff --git a/shared/featureconfig/flags.go b/shared/featureconfig/flags.go index 789097929ed0..ada267d99b40 100644 --- a/shared/featureconfig/flags.go +++ b/shared/featureconfig/flags.go @@ -68,8 +68,8 @@ var ( Usage: "Enable of the saving of deposit related data", } noGenesisDelayFlag = cli.BoolFlag{ - Name: "no-genesis-delay", - Usage: "Start the genesis event right away using the eth1 block timestamp which " + + Name: "no-genesis-delay", + Usage: "Start the genesis event right away using the eth1 block timestamp which " + "triggered the genesis as the genesis time. This flag should be used for local " + "development and testing only.", } diff --git a/tools/cluster-pk-manager/client/main.go b/tools/cluster-pk-manager/client/main.go index 1ef5db52971f..34d875a6db12 100644 --- a/tools/cluster-pk-manager/client/main.go +++ b/tools/cluster-pk-manager/client/main.go @@ -13,10 +13,10 @@ import ( ) var ( - serverAddr = flag.String("server", "", "The address of the gRPC server") - podName = flag.String("pod-name", "", "The name of the pod running this tool") - numKeys = flag.Uint64("keys", 1, "The number of keys to request") - outputJSON = flag.String("output-json", "", "JSON file to write output to") + serverAddr = flag.String("server", "", "The address of the gRPC server") + podName = flag.String("pod-name", "", "The name of the pod running this tool") + numKeys = flag.Uint64("keys", 1, "The number of keys to request") + outputJSON = flag.String("output-json", "", "JSON file to write output to") ) // UnencryptedKeysContainer defines the structure of the unecrypted key JSON file.