mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-14 06:55:07 -05:00
Compare commits
7 Commits
gloas-api-
...
copy-free-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1c6048b43 | ||
|
|
10f46a9ec8 | ||
|
|
22e77add54 | ||
|
|
a458e91fc0 | ||
|
|
c941e5511d | ||
|
|
31f35ed9ee | ||
|
|
acf0396cd5 |
@@ -112,6 +112,34 @@ func ProcessExecutionPayload(
|
||||
return errors.Wrap(err, "signature verification failed")
|
||||
}
|
||||
|
||||
envelope, err := signedEnvelope.Envelope()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get envelope from signed envelope")
|
||||
}
|
||||
|
||||
if err := ApplyExecutionPayload(ctx, st, envelope); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := st.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get hash tree root")
|
||||
}
|
||||
if r != envelope.StateRoot() {
|
||||
return fmt.Errorf("state root mismatch: expected %#x, got %#x", envelope.StateRoot(), r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyExecutionPayload applies the execution payload envelope to the state and performs the same
|
||||
// consistency checks as the full processing path. This keeps the post-payload state root computation
|
||||
// on a shared code path, even though some bid/payload checks are not strictly required for the root itself.
|
||||
func ApplyExecutionPayload(
|
||||
ctx context.Context,
|
||||
st state.BeaconState,
|
||||
envelope interfaces.ROExecutionPayloadEnvelope,
|
||||
) error {
|
||||
latestHeader := st.LatestBlockHeader()
|
||||
if len(latestHeader.StateRoot) == 0 || bytes.Equal(latestHeader.StateRoot, make([]byte, 32)) {
|
||||
previousStateRoot, err := st.HashTreeRoot(ctx)
|
||||
@@ -128,10 +156,6 @@ func ProcessExecutionPayload(
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not compute block header root")
|
||||
}
|
||||
envelope, err := signedEnvelope.Envelope()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get envelope from signed envelope")
|
||||
}
|
||||
|
||||
beaconBlockRoot := envelope.BeaconBlockRoot()
|
||||
if !bytes.Equal(beaconBlockRoot[:], blockHeaderRoot[:]) {
|
||||
@@ -217,14 +241,6 @@ func ProcessExecutionPayload(
|
||||
return errors.Wrap(err, "could not set latest block hash")
|
||||
}
|
||||
|
||||
r, err := st.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get hash tree root")
|
||||
}
|
||||
if r != envelope.StateRoot() {
|
||||
return fmt.Errorf("state root mismatch: expected %#x, got %#x", envelope.StateRoot(), r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -73,23 +73,22 @@ func PopulateFromSidecar(sidecar blocks.VerifiedRODataColumn) *SidecarReconstruc
|
||||
|
||||
// ValidatorsCustodyRequirement returns the number of custody groups regarding the validator indices attached to the beacon node.
|
||||
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/validator.md#validator-custody
|
||||
func ValidatorsCustodyRequirement(state beaconState.ReadOnlyBeaconState, validatorsIndex map[primitives.ValidatorIndex]bool) (uint64, error) {
|
||||
totalNodeBalance := uint64(0)
|
||||
func ValidatorsCustodyRequirement(st beaconState.ReadOnlyBalances, validatorsIndex map[primitives.ValidatorIndex]bool) (uint64, error) {
|
||||
cfg := params.BeaconConfig()
|
||||
idxs := make([]primitives.ValidatorIndex, 0, len(validatorsIndex))
|
||||
for index := range validatorsIndex {
|
||||
validator, err := state.ValidatorAtIndexReadOnly(index)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "validator at index %v", index)
|
||||
}
|
||||
|
||||
totalNodeBalance += validator.EffectiveBalance()
|
||||
idxs = append(idxs, index)
|
||||
}
|
||||
totalBalance, err := st.EffectiveBalanceSum(idxs)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "effective balances")
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
numberOfCustodyGroups := cfg.NumberOfCustodyGroups
|
||||
validatorCustodyRequirement := cfg.ValidatorCustodyRequirement
|
||||
balancePerAdditionalCustodyGroup := cfg.BalancePerAdditionalCustodyGroup
|
||||
|
||||
count := totalNodeBalance / balancePerAdditionalCustodyGroup
|
||||
count := totalBalance / balancePerAdditionalCustodyGroup
|
||||
return min(max(count, validatorCustodyRequirement), numberOfCustodyGroups), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ type ReadOnlyBalances interface {
|
||||
Balances() []uint64
|
||||
BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error)
|
||||
BalancesLength() int
|
||||
EffectiveBalanceSum([]primitives.ValidatorIndex) (uint64, error)
|
||||
}
|
||||
|
||||
// ReadOnlyCheckpoint defines a struct which only has read access to checkpoint methods.
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Validators participating in consensus on the beacon chain.
|
||||
@@ -80,6 +81,25 @@ func (b *BeaconState) ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Va
|
||||
return b.validatorAtIndex(idx)
|
||||
}
|
||||
|
||||
// EffectiveBalances returns the sum of the effective balances of the given list of validator indices, the eb of each given validator, or an
|
||||
// error if one of the indices is out of bounds, or the state wasn't correctly initialized.
|
||||
func (b *BeaconState) EffectiveBalanceSum(idxs []primitives.ValidatorIndex) (uint64, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
var sum uint64
|
||||
for i := range idxs {
|
||||
if b.validatorsMultiValue == nil {
|
||||
return 0, errors.Wrap(state.ErrNilValidatorsInState, "nil validators multi-value slice")
|
||||
}
|
||||
v, err := b.validatorsMultiValue.At(b, uint64(idxs[i]))
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "validators multi value at index")
|
||||
}
|
||||
sum += v.EffectiveBalance
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) validatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error) {
|
||||
if b.validatorsMultiValue == nil {
|
||||
return ðpb.Validator{}, nil
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/stategen"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
)
|
||||
|
||||
@@ -14,6 +15,8 @@ type StateManager struct {
|
||||
StatesBySlot map[primitives.Slot]state.BeaconState
|
||||
}
|
||||
|
||||
var _ stategen.StateManager = (*StateManager)(nil)
|
||||
|
||||
// NewService --
|
||||
func NewService() *StateManager {
|
||||
return &StateManager{
|
||||
@@ -101,3 +104,8 @@ func (m *StateManager) AddStateForSlot(state state.BeaconState, slot primitives.
|
||||
func (m *StateManager) DeleteStateFromCaches(context.Context, [32]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FinalizedReadOnlyBalances --
|
||||
func (m *StateManager) FinalizedReadOnlyBalances() stategen.NilCheckableReadOnlyBalances {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
@@ -27,6 +27,13 @@ var defaultHotStateDBInterval primitives.Slot = 128
|
||||
|
||||
var populatePubkeyCacheOnce sync.Once
|
||||
|
||||
// NilCheckableReadOnlyBalances adds the IsNil method to ReadOnlyBalances
|
||||
// to allow checking if the underlying state value is nil.
|
||||
type NilCheckableReadOnlyBalances interface {
|
||||
state.ReadOnlyBalances
|
||||
IsNil() bool
|
||||
}
|
||||
|
||||
// StateManager represents a management object that handles the internal
|
||||
// logic of maintaining both hot and cold states in DB.
|
||||
type StateManager interface {
|
||||
@@ -43,6 +50,7 @@ type StateManager interface {
|
||||
ActiveNonSlashedBalancesByRoot(context.Context, [32]byte) ([]uint64, error)
|
||||
StateByRootIfCachedNoCopy(blockRoot [32]byte) state.BeaconState
|
||||
StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
||||
FinalizedReadOnlyBalances() NilCheckableReadOnlyBalances
|
||||
}
|
||||
|
||||
// State is a concrete implementation of StateManager.
|
||||
@@ -201,3 +209,8 @@ func (s *State) FinalizedState() state.BeaconState {
|
||||
defer s.finalizedInfo.lock.RUnlock()
|
||||
return s.finalizedInfo.state.Copy()
|
||||
}
|
||||
|
||||
// Returns the finalized state as a ReadOnlyBalances so that it can be used read-only without copying.
|
||||
func (s *State) FinalizedReadOnlyBalances() NilCheckableReadOnlyBalances {
|
||||
return s.finalizedInfo.state
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ func (s *Service) validatorsCustodyRequirement() (uint64, error) {
|
||||
}
|
||||
|
||||
// Retrieve the finalized state.
|
||||
finalizedState := s.cfg.stateGen.FinalizedState()
|
||||
finalizedState := s.cfg.stateGen.FinalizedReadOnlyBalances()
|
||||
if finalizedState == nil || finalizedState.IsNil() {
|
||||
return 0, nilFinalizedStateError
|
||||
}
|
||||
|
||||
2
changelog/kasey_copy-free-balance-lookup.md
Normal file
2
changelog/kasey_copy-free-balance-lookup.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Fixed
|
||||
- Avoid copying the full finalized state every time we compute cgc.
|
||||
2
changelog/tt_apply_execution_payload.md
Normal file
2
changelog/tt_apply_execution_payload.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Ignored
|
||||
- Refactor ProcessExecutionPayload to ApplyExecutionPayload
|
||||
Reference in New Issue
Block a user