Add calculations for slot scaling

This commit is contained in:
Jim McDonald 2020-10-28 15:31:28 +00:00
parent 13f5d5eeaf
commit a14870fa3f
No known key found for this signature in database
GPG Key ID: 89CEB61B2AD2A5E7
4 changed files with 228 additions and 19 deletions

View File

@ -55,8 +55,13 @@ func (s *Service) BeaconBlockProposal(ctx context.Context, slot uint64, randaoRe
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained beacon block proposal")
cancel()
// Obtain the slot of the block to which the proposal refers.
// We use this to allow the scorer to score blocks with earlier parents lower.
// TODO need a go-eth2-client provider to obtain this information.
parentSlot := uint64(slot - 1)
mu.Lock()
score := scoreBeaconBlockProposal(ctx, name, proposal)
score := scoreBeaconBlockProposal(ctx, name, parentSlot, proposal)
if score > bestScore || bestProposal == nil {
bestScore = score
bestProposal = proposal

View File

@ -32,6 +32,7 @@ type parameters struct {
clientMonitor metrics.ClientMonitor
processConcurrency int64
beaconBlockProposalProviders map[string]eth2client.BeaconBlockProposalProvider
signedBeaconBlockProvider eth2client.SignedBeaconBlockProvider
timeout time.Duration
}

View File

@ -22,7 +22,7 @@ import (
// scoreBeaconBlockPropsal generates a score for a beacon block.
// The score is relative to the reward expected by proposing the block.
func scoreBeaconBlockProposal(ctx context.Context, name string, blockProposal *spec.BeaconBlock) float64 {
func scoreBeaconBlockProposal(ctx context.Context, name string, parentSlot uint64, blockProposal *spec.BeaconBlock) float64 {
if blockProposal == nil {
return 0
}
@ -83,17 +83,28 @@ func scoreBeaconBlockProposal(ctx context.Context, name string, blockProposal *s
}
attesterSlashingScore := slashingWeight * float64(indicesSlashed)
// Scale scores by the distance between the proposal and parent slots.
scale := uint64(1)
if blockProposal.Slot <= parentSlot {
log.Warn().Uint64("slot", blockProposal.Slot).Uint64("parent_slot", parentSlot).Msg("Invalid parent slot for proposal")
scale = 32
} else {
scale = blockProposal.Slot - parentSlot
}
log.Trace().
Uint64("slot", blockProposal.Slot).
Uint64("parent_slot", parentSlot).
Str("provider", name).
Float64("immediate_attestations", immediateAttestationScore).
Float64("attestations", attestationScore).
Float64("proposer_slashings", proposerSlashingScore).
Float64("attester_slashings", attesterSlashingScore).
Float64("total", attestationScore+proposerSlashingScore+attesterSlashingScore).
Uint64("scale", scale).
Float64("total", (attestationScore+proposerSlashingScore+attesterSlashingScore)/float64(scale)).
Msg("Scored block")
return attestationScore + proposerSlashingScore + attesterSlashingScore
return (attestationScore + proposerSlashingScore + attesterSlashingScore) / float64(scale)
}
// intersection returns a list of items common between the two sets.

View File

@ -15,6 +15,8 @@ package best
import (
"context"
"encoding/hex"
"strings"
"testing"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
@ -22,6 +24,14 @@ import (
"github.com/stretchr/testify/assert"
)
func _bytes(input string) []byte {
res, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
panic(err)
}
return res
}
func aggregationBits(set uint64, total uint64) bitfield.Bitlist {
bits := bitfield.NewBitlist(total)
for i := uint64(0); i < set; i++ {
@ -40,19 +50,22 @@ func specificAggregationBits(set []uint64, total uint64) bitfield.Bitlist {
func TestScore(t *testing.T) {
tests := []struct {
name string
block *spec.BeaconBlock
score float64
err string
name string
block *spec.BeaconBlock
parentSlot uint64
score float64
err string
}{
{
name: "Nil",
score: 0,
name: "Nil",
parentSlot: 1,
score: 0,
},
{
name: "Empty",
block: &spec.BeaconBlock{},
score: 0,
name: "Empty",
block: &spec.BeaconBlock{},
parentSlot: 1,
score: 0,
},
{
name: "SingleAttestation",
@ -69,7 +82,26 @@ func TestScore(t *testing.T) {
},
},
},
score: 1,
parentSlot: 12344,
score: 1,
},
{
name: "SingleAttestationParentRootDistance2",
block: &spec.BeaconBlock{
Slot: 12345,
Body: &spec.BeaconBlockBody{
Attestations: []*spec.Attestation{
{
AggregationBits: aggregationBits(1, 128),
Data: &spec.AttestationData{
Slot: 12344,
},
},
},
},
},
parentSlot: 12343,
score: 0.5,
},
{
name: "SingleAttestationDistance2",
@ -86,7 +118,8 @@ func TestScore(t *testing.T) {
},
},
},
score: 0.875,
parentSlot: 12344,
score: 0.875,
},
{
name: "TwoAttestations",
@ -109,7 +142,8 @@ func TestScore(t *testing.T) {
},
},
},
score: 2.8125,
parentSlot: 12344,
score: 2.8125,
},
{
name: "AttesterSlashing",
@ -136,7 +170,8 @@ func TestScore(t *testing.T) {
},
},
},
score: 1450,
parentSlot: 12344,
score: 1450,
},
{
name: "DuplicateAttestations",
@ -159,13 +194,170 @@ func TestScore(t *testing.T) {
},
},
},
score: 4,
parentSlot: 12344,
score: 4,
},
{
name: "Full",
block: &spec.BeaconBlock{
Slot: 12345,
Body: &spec.BeaconBlockBody{
Attestations: []*spec.Attestation{
{
AggregationBits: aggregationBits(50, 128),
Data: &spec.AttestationData{
Slot: 12344,
},
},
},
AttesterSlashings: []*spec.AttesterSlashing{
{
Attestation1: &spec.IndexedAttestation{
AttestingIndices: []uint64{1, 2, 3},
},
Attestation2: &spec.IndexedAttestation{
AttestingIndices: []uint64{2, 3, 4},
},
},
},
ProposerSlashings: []*spec.ProposerSlashing{
{
Header1: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0101010101010101010101010101010101010101010101010101010101010101"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
Header2: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0404040404040404040404040404040404040404040404040404040404040404"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
},
},
},
},
parentSlot: 12344,
score: 2150,
},
{
name: "FullParentRootDistance2",
block: &spec.BeaconBlock{
Slot: 12345,
Body: &spec.BeaconBlockBody{
Attestations: []*spec.Attestation{
{
AggregationBits: aggregationBits(50, 128),
Data: &spec.AttestationData{
Slot: 12344,
},
},
},
AttesterSlashings: []*spec.AttesterSlashing{
{
Attestation1: &spec.IndexedAttestation{
AttestingIndices: []uint64{1, 2, 3},
},
Attestation2: &spec.IndexedAttestation{
AttestingIndices: []uint64{2, 3, 4},
},
},
},
ProposerSlashings: []*spec.ProposerSlashing{
{
Header1: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0101010101010101010101010101010101010101010101010101010101010101"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
Header2: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0404040404040404040404040404040404040404040404040404040404040404"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
},
},
},
},
parentSlot: 12343,
score: 1075,
},
{
name: "FullParentRootDistance4",
block: &spec.BeaconBlock{
Slot: 12345,
Body: &spec.BeaconBlockBody{
Attestations: []*spec.Attestation{
{
AggregationBits: aggregationBits(50, 128),
Data: &spec.AttestationData{
Slot: 12344,
},
},
},
AttesterSlashings: []*spec.AttesterSlashing{
{
Attestation1: &spec.IndexedAttestation{
AttestingIndices: []uint64{1, 2, 3},
},
Attestation2: &spec.IndexedAttestation{
AttestingIndices: []uint64{2, 3, 4},
},
},
},
ProposerSlashings: []*spec.ProposerSlashing{
{
Header1: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0101010101010101010101010101010101010101010101010101010101010101"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
Header2: &spec.SignedBeaconBlockHeader{
Message: &spec.BeaconBlockHeader{
Slot: 10,
ProposerIndex: 1,
ParentRoot: _bytes("0x0404040404040404040404040404040404040404040404040404040404040404"),
StateRoot: _bytes("0x0202020202020202020202020202020202020202020202020202020202020202"),
BodyRoot: _bytes("0x0303030303030303030303030303030303030303030303030303030303030303"),
},
Signature: _bytes("0x040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404"),
},
},
},
},
},
parentSlot: 12341,
score: 537.5,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
score := scoreBeaconBlockProposal(context.Background(), test.name, test.block)
score := scoreBeaconBlockProposal(context.Background(), test.name, test.parentSlot, test.block)
assert.Equal(t, test.score, score)
})
}