Use advanced epoch cache when preparing proposals (#13377)

This commit is contained in:
Potuz 2023-12-27 09:42:51 -03:00 committed by GitHub
parent d0bf03e863
commit e80db9554d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 3 deletions

View File

@ -5,15 +5,27 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/time/slots"
)
// trackedProposer returns whether the beacon node was informed, via the
// validators/prepare_proposer endpoint, of the proposer at the given slot.
// It only returns true if the tracked proposer is present and active.
func (s *Service) trackedProposer(st state.ReadOnlyBeaconState, slot primitives.Slot) (cache.TrackedValidator, bool) {
id, err := helpers.BeaconProposerIndexAtSlot(s.ctx, st, slot)
if err != nil {
return cache.TrackedValidator{}, false
// if the head state and slot are in different epochs, try first the
// precomputed cache one epoch in advance
var id primitives.ValidatorIndex
var err error
stateEpoch := slots.ToEpoch(st.Slot())
e := slots.ToEpoch(slot)
if stateEpoch != e {
id, err = helpers.UnsafeBeaconProposerIndexAtSlot(st, slot)
}
if err != nil || stateEpoch == e {
id, err = helpers.BeaconProposerIndexAtSlot(s.ctx, st, slot)
if err != nil {
return cache.TrackedValidator{}, false
}
}
val, ok := s.cfg.TrackedValidatorsCache.Validator(id)
if !ok {

View File

@ -281,6 +281,39 @@ func cachedProposerIndexAtSlot(slot primitives.Slot, root [32]byte) (primitives.
return proposerIndices[slot%params.BeaconConfig().SlotsPerEpoch], nil
}
// cachedUnsafeProposerIndexAtSlot returns the proposer index at the given slot
// from the unsafe cache computed in the previous epoch
func cachedUnsafeProposerIndexAtSlot(slot primitives.Slot, root [32]byte) (primitives.ValidatorIndex, error) {
proposerIndices, has := proposerIndicesCache.UnsafeProposerIndices(slots.ToEpoch(slot), root)
if !has {
cache.ProposerIndicesCacheMiss.Inc()
return 0, errProposerIndexMiss
}
if len(proposerIndices) != int(params.BeaconConfig().SlotsPerEpoch) {
cache.ProposerIndicesCacheMiss.Inc()
return 0, errProposerIndexMiss
}
return proposerIndices[slot%params.BeaconConfig().SlotsPerEpoch], nil
}
// UnsafeBeaconProposerIndexAtSlot returns the proposer index at the given slot
// if it has been cached one epoch in advance
func UnsafeBeaconProposerIndexAtSlot(state state.ReadOnlyBeaconState, slot primitives.Slot) (primitives.ValidatorIndex, error) {
e := slots.ToEpoch(slot)
if e < 2 {
return 0, errProposerIndexMiss
}
s, err := slots.EpochEnd(e - 2)
if err != nil {
return 0, err
}
r, err := StateRootAtSlot(state, s)
if err != nil {
return 0, err
}
return cachedUnsafeProposerIndexAtSlot(slot, [32]byte(r))
}
// BeaconProposerIndexAtSlot returns proposer index at the given slot from the
// point of view of the given state as head state
func BeaconProposerIndexAtSlot(ctx context.Context, state state.ReadOnlyBeaconState, slot primitives.Slot) (primitives.ValidatorIndex, error) {

View File

@ -16,6 +16,7 @@ import (
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/time/slots"
)
func TestIsActiveValidator_OK(t *testing.T) {
@ -802,3 +803,26 @@ func TestLastActivatedValidatorIndex_OK(t *testing.T) {
require.NoError(t, err)
require.Equal(t, index, primitives.ValidatorIndex(3))
}
func TestUnsafeProposerIndexAtSlot(t *testing.T) {
bRoot := [32]byte{'A'}
e := 4
slot := primitives.Slot(e) * params.BeaconConfig().SlotsPerEpoch
indices, ok := proposerIndicesCache.UnsafeProposerIndices(primitives.Epoch(e), bRoot)
require.Equal(t, false, ok)
beaconState, err := state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{})
require.NoError(t, err)
roots := make([][]byte, fieldparams.StateRootsLength)
roots[(e-1)*int(params.BeaconConfig().SlotsPerEpoch)-1] = bRoot[:]
id := primitives.ValidatorIndex(17)
indices[0] = id
require.NoError(t, beaconState.SetStateRoots(roots))
require.NoError(t, beaconState.SetSlot(slot))
epoch := slots.ToEpoch(slot)
require.Equal(t, primitives.Epoch(e), epoch)
proposerIndicesCache.SetUnsafe(epoch, bRoot, indices)
pid, err := UnsafeBeaconProposerIndexAtSlot(beaconState, slot)
require.NoError(t, err)
require.Equal(t, id, pid)
}