Skip to content

Commit

Permalink
Better attesting summary reporting (prysmaticlabs#4845)
Browse files Browse the repository at this point in the history
  • Loading branch information
terencechain authored and cryptomental committed Feb 28, 2020
1 parent 84daeb7 commit 6988af3
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 58 deletions.
2 changes: 1 addition & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ go_repository(
go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "6720aaf759152b73b1162d7c2156ecc4e788a8d3",
commit = "9e66dfce9956682649fedac730eb5aa2d5973456",
importpath = "github.com/prysmaticlabs/ethereumapis",
patch_args = ["-p1"],
patches = [
Expand Down
6 changes: 6 additions & 0 deletions beacon-chain/core/state/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import (
"go.opencensus.io/trace"
)

// ValidatorSummary tracks validator's attesting summary on per epoch basis. This
// gets updated during epoch transition.
var ValidatorSummary []*precompute.Validator

// ExecuteStateTransition defines the procedure for a state transition function.
//
// Spec pseudocode definition:
Expand Down Expand Up @@ -595,6 +599,8 @@ func ProcessEpochPrecompute(ctx context.Context, state *stateTrie.BeaconState) (
return nil, err
}

ValidatorSummary = vp

state, err = precompute.ProcessJustificationAndFinalizationPreCompute(state, bp)
if err != nil {
return nil, errors.Wrap(err, "could not process justification")
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/beacon/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (bs *Server) StreamBlocks(_ *ptypes.Empty, stream ethpb.BeaconChain_StreamB
// One nil block shouldn't stop the stream.
continue
}
if err := stream.Send(data.SignedBlock.Block); err != nil {
if err := stream.Send(data.SignedBlock); err != nil {
return status.Errorf(codes.Unavailable, "Could not send over stream: %v", err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/beacon/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ func TestServer_StreamBlocks_OnHeadUpdated(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockStream := mockRPC.NewMockBeaconChain_StreamBlocksServer(ctrl)
mockStream.EXPECT().Send(b.Block).Do(func(arg0 interface{}) {
mockStream.EXPECT().Send(b).Do(func(arg0 interface{}) {
exitRoutine <- true
})
mockStream.EXPECT().Context().Return(ctx).AnyTimes()
Expand Down
64 changes: 29 additions & 35 deletions beacon-chain/rpc/beacon/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,51 +581,45 @@ func (bs *Server) GetValidatorQueue(
func (bs *Server) GetValidatorPerformance(
ctx context.Context, req *ethpb.ValidatorPerformanceRequest,
) (*ethpb.ValidatorPerformanceResponse, error) {
headState, err := bs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get head state")
}

// Advance state with empty transitions up to the requested epoch start slot.
if req.Slot > headState.Slot() {
headState, err = state.ProcessSlots(ctx, headState, req.Slot)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not process slots up to %d: %v", req.Slot, err)
}
}
validatorSummary := state.ValidatorSummary

balances := make([]uint64, len(req.PublicKeys))
effectiveBalances := make([]uint64, 0)
inclusionSlots := make([]uint64, 0)
inclusionDistances := make([]uint64, 0)
correctlyVotedSource := make([]bool, 0)
correctlyVotedTarget := make([]bool, 0)
correctlyVotedHead := make([]bool, 0)
missingValidators := make([][]byte, 0)
for i, key := range req.PublicKeys {
index, ok, err := bs.BeaconDB.ValidatorIndex(ctx, key)
if err != nil || !ok {

// Convert the list of validator public keys to list of validator indices.
// Also track missing validators using public keys.
for _, key := range req.PublicKeys {
idx, ok, err := bs.BeaconDB.ValidatorIndex(ctx, key)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not fetch validator idx for public key %#x: %v", key, err)
}
if !ok {
missingValidators = append(missingValidators, key)
balances[i] = 0
continue
}
balances[i], err = headState.BalanceAtIndex(index)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get balance at index %d", i)
}
}

activeCount, err := helpers.ActiveValidatorCount(headState, helpers.SlotToEpoch(req.Slot))
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not retrieve active validator count: %v", err)
}

totalActiveBalance, err := helpers.TotalActiveBalance(headState)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not retrieve total active balance: %v", err)
effectiveBalances = append(effectiveBalances, validatorSummary[idx].CurrentEpochEffectiveBalance)
inclusionSlots = append(inclusionSlots, validatorSummary[idx].InclusionSlot)
inclusionDistances = append(inclusionDistances, validatorSummary[idx].InclusionDistance)
correctlyVotedSource = append(correctlyVotedSource, validatorSummary[idx].IsPrevEpochAttester)
correctlyVotedTarget = append(correctlyVotedTarget, validatorSummary[idx].IsPrevEpochTargetAttester)
correctlyVotedHead = append(correctlyVotedHead, validatorSummary[idx].IsPrevEpochHeadAttester)
}

avgBalance := float32(totalActiveBalance / activeCount)
return &ethpb.ValidatorPerformanceResponse{
Balances: balances,
AverageActiveValidatorBalance: avgBalance,
MissingValidators: missingValidators,
TotalValidators: uint64(headState.NumValidators()),
TotalActiveValidators: activeCount,
InclusionSlots: inclusionSlots,
InclusionDistances: inclusionDistances,
CorrectlyVotedSource: correctlyVotedSource,
CorrectlyVotedTarget: correctlyVotedTarget,
CorrectlyVotedHead: correctlyVotedHead,
Balances: effectiveBalances,
MissingValidators: missingValidators,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/testing/beacon_chain_service_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shared/featureconfig/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ var (
Hidden: true,
}
deprecatedForkchoiceAggregateAttestations = cli.BoolFlag{
Name: "forkchoice-aggregate-attestations",
Name: "forkchoice-aggregate-attestations",
Usage: deprecatedUsage,
Hidden: true,
}
Expand Down
4 changes: 2 additions & 2 deletions shared/mock/beacon_chain_service_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions slasher/beaconclient/receivers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ func TestService_ReceiveBlocks(t *testing.T) {
}
stream := mock.NewMockBeaconChain_StreamBlocksClient(ctrl)
ctx, cancel := context.WithCancel(context.Background())
block := &ethpb.BeaconBlock{
Slot: 5,
}
client.EXPECT().StreamBlocks(
gomock.Any(),
&ptypes.Empty{},
).Return(stream, nil)
stream.EXPECT().Context().Return(ctx).AnyTimes()
stream.EXPECT().Recv().Return(
block,
&ethpb.SignedBeaconBlock{},
nil,
).Do(func() {
cancel()
Expand Down
8 changes: 4 additions & 4 deletions third_party/com_github_prysmaticlabs_ethereumapis-tags.patch
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ index 2ce5c34..4cbb276 100644
+ bytes signature = 3 [(gogoproto.moretags) = "ssz-size:\"96\""];
}
diff --git a/eth/v1alpha1/beacon_chain.proto b/eth/v1alpha1/beacon_chain.proto
index 8de1adb..ffcc8f4 100644
index 731fa45..3a9092c 100644
--- a/eth/v1alpha1/beacon_chain.proto
+++ b/eth/v1alpha1/beacon_chain.proto
@@ -15,6 +15,7 @@ syntax = "proto3";
Expand Down Expand Up @@ -369,7 +369,7 @@ index 8de1adb..ffcc8f4 100644

// Indices of validators ejected in the given epoch.
repeated uint64 ejected_indices = 9;
@@ -583,11 +583,11 @@ message ValidatorQueue {
@@ -591,11 +591,11 @@ message ValidatorQueue {

// Ordered list of 48 byte public keys awaiting activation. 0th index is the
// next key to be processed.
Expand All @@ -383,7 +383,7 @@ index 8de1adb..ffcc8f4 100644
}

message ListValidatorAssignmentsRequest {
@@ -599,7 +599,7 @@ message ListValidatorAssignmentsRequest {
@@ -607,7 +607,7 @@ message ListValidatorAssignmentsRequest {
bool genesis = 2;
}
// 48 byte validator public keys to filter assignments for the given epoch.
Expand All @@ -392,7 +392,7 @@ index 8de1adb..ffcc8f4 100644

// Validator indicies to filter assignments for the given epoch.
repeated uint64 indices = 4;
@@ -634,7 +634,7 @@ message ValidatorAssignments {
@@ -642,7 +642,7 @@ message ValidatorAssignments {
uint64 proposer_slot = 4;

// 48 byte BLS public key.
Expand Down
42 changes: 34 additions & 8 deletions validator/client/validator_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func (v *validator) LogValidatorGainsAndLosses(ctx context.Context, slot uint64)
pubKeys := bytesutil.FromBytes48Array(pks)

req := &ethpb.ValidatorPerformanceRequest{
Slot: slot,
PublicKeys: pubKeys,
}
resp, err := v.beaconClient.GetValidatorPerformance(ctx, req)
Expand All @@ -57,6 +56,12 @@ func (v *validator) LogValidatorGainsAndLosses(ctx context.Context, slot uint64)
for _, val := range resp.MissingValidators {
missingValidators[bytesutil.ToBytes48(val)] = true
}

included := 0
votedSource := 0
votedTarget := 0
votedHead := 0

for i, pkey := range pubKeys {
pubKey := fmt.Sprintf("%#x", pkey[:8])
log := log.WithField("pubKey", pubKey)
Expand All @@ -73,20 +78,41 @@ func (v *validator) LogValidatorGainsAndLosses(ctx context.Context, slot uint64)
newBalance := float64(resp.Balances[i]) / float64(params.BeaconConfig().GweiPerEth)

if v.prevBalance[bytesutil.ToBytes48(pkey)] > 0 {
prevBalance := float64(v.prevBalance[bytesutil.ToBytes48(pkey)]) / float64(params.BeaconConfig().GweiPerEth)
percentNet := (newBalance - prevBalance) / prevBalance
log.WithFields(logrus.Fields{
"epoch": (slot / params.BeaconConfig().SlotsPerEpoch) - 1,
"prevBalance": prevBalance,
"newBalance": newBalance,
"percentChange": fmt.Sprintf("%.5f%%", percentNet*100),
}).Info("New Balance")
"epoch": (slot / params.BeaconConfig().SlotsPerEpoch) - 1,
"correctlyVotedSource": resp.CorrectlyVotedSource[i],
"correctlyVotedTarget": resp.CorrectlyVotedTarget[i],
"correctlyVotedHead": resp.CorrectlyVotedHead[i],
"inclusionSlot": resp.InclusionSlots[i],
"inclusionDistance": resp.InclusionDistances[i],
}).Info("Previous epoch voting summary")
if v.emitAccountMetrics {
validatorBalancesGaugeVec.WithLabelValues(pubKey).Set(newBalance)
}
}

if resp.InclusionSlots[i] != ^uint64(0) {
included++
}
if resp.CorrectlyVotedSource[i] {
votedSource++
}
if resp.CorrectlyVotedTarget[i] {
votedTarget++
}
if resp.CorrectlyVotedHead[i] {
votedHead++
}
v.prevBalance[bytesutil.ToBytes48(pkey)] = resp.Balances[i]
}

log.WithFields(logrus.Fields{
"epoch": (slot / params.BeaconConfig().SlotsPerEpoch) - 1,
"attestationInclusionPercentage": fmt.Sprintf("%.2f", float64(included)/float64(len(resp.InclusionSlots))),
"correctlyVotedSourcePercentage": fmt.Sprintf("%.2f", float64(votedSource)/float64(len(resp.CorrectlyVotedSource))),
"correctlyVotedTargetPercentage": fmt.Sprintf("%.2f", float64(votedTarget)/float64(len(resp.CorrectlyVotedTarget))),
"correctlyVotedHeadPercentage": fmt.Sprintf("%.2f", float64(votedHead)/float64(len(resp.CorrectlyVotedHead))),
}).Info("Previous epoch aggregated voting summary")

return nil
}

0 comments on commit 6988af3

Please sign in to comment.