Skip to content

Commit

Permalink
Add scheduled/proposed/missed blocks to proposalduties
Browse files Browse the repository at this point in the history
  • Loading branch information
alrevuelta committed Dec 29, 2021
1 parent 5bf7bc1 commit 85bcb71
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 28 deletions.
69 changes: 50 additions & 19 deletions metrics/proposalduties.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ import (
"time"
)

type ProposalDutiesMetrics struct {
Scheduled []Duty
Proposed []Duty
Missed []Duty
}

type Duty struct {
valIndex uint64
slot ethTypes.Slot
graffiti string
}

// Continuously reports scheduled and fulfilled duties for the validators for
Expand Down Expand Up @@ -42,15 +49,15 @@ func (a *Metrics) StreamDuties() {
log.Error("could not get duties: ", err)
continue
}
nOfScheduledBlocks, nOfProposedBlocks := getProposalDuties(duties, blocks)
metrics := getProposalDuties(duties, blocks)

prometheus.NOfScheduledBlocks.Set(float64(nOfScheduledBlocks))
prometheus.NOfProposedBlocks.Set(float64(nOfProposedBlocks))
prometheus.NOfScheduledBlocks.Set(float64(len(metrics.Scheduled)))
prometheus.NOfProposedBlocks.Set(float64(len(metrics.Proposed)))

log.WithFields(log.Fields{
"Epoch": head.FinalizedEpoch,
"RequestedDuties": nOfScheduledBlocks,
"PerformedDuties": nOfProposedBlocks,
"ScheduledDuties": len(metrics.Scheduled),
"PerformedDuties": len(metrics.Proposed),
}).Info("Block proposals duties:")
lastEpoch = uint64(head.FinalizedEpoch)

Expand Down Expand Up @@ -98,16 +105,20 @@ func (a *Metrics) FetchDuties(
// of performed proposals
func getProposalDuties(
duties *ethpb.DutiesResponse,
blocks *ethpb.ListBeaconBlocksResponse) (uint64, uint64) {
blocks *ethpb.ListBeaconBlocksResponse) *ProposalDutiesMetrics {

metrics := &ProposalDutiesMetrics{
Scheduled: make([]Duty, 0),
Proposed: make([]Duty, 0),
Missed: make([]Duty, 0),
}
log.Info("metrics:", metrics)

if duties == nil {
log.Warn("No data is available to calculate the duties")
return 0, 0
return metrics
}

// Store the proposing duties that belongs to our validators
proposalDuties := make([]Duty, 0)

// Scan all duties in the given epoch
for i := range duties.CurrentEpochDuties {
// If there are any proposal duties append them
Expand All @@ -116,7 +127,7 @@ func getProposalDuties(
valIndex := uint64(duties.CurrentEpochDuties[i].ValidatorIndex)
// Most likely there will be only a single proposal per epoch
for _, propSlot := range duties.CurrentEpochDuties[i].ProposerSlots {
proposalDuties = append(proposalDuties, Duty{valIndex, propSlot})
metrics.Scheduled = append(metrics.Scheduled, Duty{valIndex: valIndex, slot: propSlot})

// TODO: Move this somewhere else
log.WithFields(log.Fields{
Expand All @@ -130,35 +141,55 @@ func getProposalDuties(
}

// Just return if no proposal duties were found for us
if len(proposalDuties) == 0 {
return 0, 0
if len(metrics.Scheduled) == 0 {
return metrics
}

proposalsPerformed := uint64(0)

// Iterate our validator proposal duties
for _, duty := range proposalDuties {
for _, duty := range metrics.Scheduled {
// Iterate all blocks and check if we proposed the ones we should
for _, block := range blocks.BlockContainers {
propIndex, slot, graffiti := getBlockParams(block)
// If the block at the slot was proposed by us (valIndex)
if duty.valIndex == propIndex && duty.slot == slot {
metrics.Proposed = append(metrics.Proposed, Duty{
valIndex: propIndex,
slot: slot,
graffiti: graffiti})
// TODO: Move this somewhere else
log.WithFields(log.Fields{
"ValIndex": propIndex,
"Slot": slot,
//"Epoch": uint64(slot) % a.slotsInEpoch,
"Graffiti": graffiti,
}).Info("Proposal Duty Completion Verified:")
proposalsPerformed++
break
}
}
}

totalProposalDuties := uint64(len(proposalDuties))
metrics.Missed = getMissedDuties(metrics.Scheduled, metrics.Proposed)

return metrics
}

func getMissedDuties(scheduled []Duty, proposed []Duty) []Duty {
missed := make([]Duty, 0)

for _, s := range scheduled {
found := false
for _, p := range proposed {
if s.slot == p.slot && s.valIndex == p.valIndex {
found = true
break
}
}
if found == false {
missed = append(missed, s)
}
}

return totalProposalDuties, proposalsPerformed
return missed
}

func getBlockParams(block *ethpb.BeaconBlockContainer) (uint64, ethTypes.Slot, string) {
Expand Down
57 changes: 48 additions & 9 deletions metrics/proposalduties_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package metrics
import (
ethTypes "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/prysm/v2/proto/prysm/v1alpha1"
log "github.com/sirupsen/logrus"
//log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"testing"
)
Expand Down Expand Up @@ -60,9 +60,9 @@ var duties = &ethpb.DutiesResponse{
}}

// Blocks can be:
//BeaconBlockContainer_Phase0Block
//BeaconBlockContainer_AltairBlock
//And soon: BeaconBlockMerge
// BeaconBlockContainer_Phase0Block
// BeaconBlockContainer_AltairBlock
// And soon: BeaconBlockMerge

// Only p1-p5 duties are fulfilled
var blocks = &ethpb.ListBeaconBlocksResponse{
Expand Down Expand Up @@ -106,11 +106,50 @@ var blocks = &ethpb.ListBeaconBlocksResponse{
}

func Test_getProposalDuties(t *testing.T) {
proposalDuties, performedDuties := getProposalDuties(duties, blocks)
metrics := getProposalDuties(duties, blocks)

log.Info("proposalDuties:", proposalDuties)
log.Info("performedDuties:", performedDuties)
require.Equal(t, len(metrics.Scheduled), 7)
require.Equal(t, len(metrics.Proposed), 5)
require.Equal(t, len(metrics.Missed), 2)

require.Equal(t, proposalDuties, uint64(7))
require.Equal(t, performedDuties, uint64(5))
// Scheduled blocks
for i := 0; i < 7; i++ {
require.Equal(t, metrics.Scheduled[i].valIndex, uint64(i+1))
require.Equal(t, metrics.Scheduled[i].slot, ethTypes.Slot(32000+i))
}

// Proposed blocks
for i := 0; i < 5; i++ {
require.Equal(t, metrics.Proposed[i].valIndex, uint64(i+1))
require.Equal(t, metrics.Proposed[i].slot, ethTypes.Slot(32000+i))
}

// Missed blocks
for i := 0; i < 2; i++ {
require.Equal(t, metrics.Missed[i].valIndex, uint64(i+6))
require.Equal(t, metrics.Missed[i].slot, ethTypes.Slot(32005+i))
}
}

func Test_getMissedDuties(t *testing.T) {
missedDuties := getMissedDuties(
// Schedulled
[]Duty{
{valIndex: 1, slot: ethTypes.Slot(1000)},
{valIndex: 2, slot: ethTypes.Slot(2000)},
{valIndex: 3, slot: ethTypes.Slot(3000)},
{valIndex: 4, slot: ethTypes.Slot(4000)},
},
// Proposed
[]Duty{
{valIndex: 1, slot: ethTypes.Slot(1000)},
{valIndex: 4, slot: ethTypes.Slot(4000)},
},
)

require.Equal(t, missedDuties[0].valIndex, uint64(2))
require.Equal(t, missedDuties[0].slot, ethTypes.Slot(2000))

require.Equal(t, missedDuties[1].valIndex, uint64(3))
require.Equal(t, missedDuties[1].slot, ethTypes.Slot(3000))
}

0 comments on commit 85bcb71

Please sign in to comment.