mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-26 13:48:44 -05:00
Compare commits
1 Commits
testing-ch
...
gloas/proc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdc07e1f1b |
@@ -4,6 +4,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bid.go",
|
||||
"builder.go",
|
||||
"pending_payment.go",
|
||||
"proposer_slashing.go",
|
||||
],
|
||||
|
||||
46
beacon-chain/core/gloas/builder.go
Normal file
46
beacon-chain/core/gloas/builder.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package gloas
|
||||
|
||||
import (
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
)
|
||||
|
||||
// IsBuilderIndex returns true when the BuilderIndex flag is set on a validator index.
|
||||
// Spec v1.6.1 (pseudocode):
|
||||
// def is_builder_index(validator_index: ValidatorIndex) -> bool:
|
||||
//
|
||||
// return (validator_index & BUILDER_INDEX_FLAG) != 0
|
||||
func IsBuilderIndex(validatorIndex primitives.ValidatorIndex) bool {
|
||||
return uint64(validatorIndex)¶ms.BeaconConfig().BuilderIndexFlag != 0
|
||||
}
|
||||
|
||||
// ConvertValidatorIndexToBuilderIndex strips the builder flag from a validator index.
|
||||
// Spec v1.6.1 (pseudocode):
|
||||
// def convert_validator_index_to_builder_index(validator_index: ValidatorIndex) -> BuilderIndex:
|
||||
//
|
||||
// return BuilderIndex(validator_index & ~BUILDER_INDEX_FLAG)
|
||||
func ConvertValidatorIndexToBuilderIndex(validatorIndex primitives.ValidatorIndex) primitives.BuilderIndex {
|
||||
return primitives.BuilderIndex(uint64(validatorIndex) & ^params.BeaconConfig().BuilderIndexFlag)
|
||||
}
|
||||
|
||||
// ConvertBuilderIndexToValidatorIndex sets the builder flag on a builder index.
|
||||
// Spec v1.6.1 (pseudocode):
|
||||
// def convert_builder_index_to_validator_index(builder_index: BuilderIndex) -> ValidatorIndex:
|
||||
//
|
||||
// return ValidatorIndex(builder_index | BUILDER_INDEX_FLAG)
|
||||
func ConvertBuilderIndexToValidatorIndex(builderIndex primitives.BuilderIndex) primitives.ValidatorIndex {
|
||||
return primitives.ValidatorIndex(uint64(builderIndex) | params.BeaconConfig().BuilderIndexFlag)
|
||||
}
|
||||
|
||||
// IsBuilderWithdrawalCredential returns true when the builder withdrawal prefix is set.
|
||||
// Spec v1.6.1 (pseudocode):
|
||||
// def is_builder_withdrawal_credential(withdrawal_credentials: Bytes32) -> bool:
|
||||
//
|
||||
// return withdrawal_credentials[:1] == BUILDER_WITHDRAWAL_PREFIX
|
||||
func IsBuilderWithdrawalCredential(withdrawalCredentials []byte) bool {
|
||||
if len(withdrawalCredentials) == 0 {
|
||||
return false
|
||||
}
|
||||
return withdrawalCredentials[0] == params.BeaconConfig().BuilderWithdrawalPrefixByte
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package state
|
||||
import (
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -13,6 +14,10 @@ type writeOnlyGloasFields interface {
|
||||
RotateBuilderPendingPayments() error
|
||||
AppendBuilderPendingWithdrawals([]*ethpb.BuilderPendingWithdrawal) error
|
||||
UpdateExecutionPayloadAvailabilityAtIndex(idx uint64, val byte) error
|
||||
|
||||
SetPayloadExpectedWithdrawals(withdrawals []*enginev1.Withdrawal) error
|
||||
DequeueBuilderPendingWithdrawals(num uint64) error
|
||||
SetNextWithdrawalBuilderIndex(idx primitives.BuilderIndex) error
|
||||
}
|
||||
|
||||
type readOnlyGloasFields interface {
|
||||
@@ -21,4 +26,13 @@ type readOnlyGloasFields interface {
|
||||
CanBuilderCoverBid(primitives.BuilderIndex, primitives.Gwei) (bool, error)
|
||||
LatestBlockHash() ([32]byte, error)
|
||||
BuilderPendingPayments() ([]*ethpb.BuilderPendingPayment, error)
|
||||
|
||||
IsParentBlockFull() bool
|
||||
BuildersCount() int
|
||||
Builders() ([]*ethpb.Builder, error)
|
||||
BuildersSweepWithdrawals(withdrawalIndex uint64, priorWithdrawalCount uint64) ([]*enginev1.Withdrawal, uint64, uint64, error)
|
||||
NextWithdrawalBuilderIndex() (primitives.BuilderIndex, error)
|
||||
BuilderPendingWithdrawals() ([]*ethpb.BuilderPendingWithdrawal, error)
|
||||
|
||||
ExpectedWithdrawalsGloas() ([]*enginev1.Withdrawal, uint64, uint64, uint64, uint64, error)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
"getters_eth1.go",
|
||||
"getters_exit.go",
|
||||
"getters_gloas.go",
|
||||
"getters_gloas_withdrawals.go",
|
||||
"getters_misc.go",
|
||||
"getters_participation.go",
|
||||
"getters_payload_header.go",
|
||||
|
||||
@@ -1,15 +1,35 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v7/time/slots"
|
||||
)
|
||||
|
||||
// IsParentBlockFull returns true when the latest bid was fulfilled with a payload.
|
||||
func (b *BeaconState) IsParentBlockFull() bool {
|
||||
if b.version < version.Gloas {
|
||||
return false
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if b.latestExecutionPayloadBid == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(b.latestExecutionPayloadBid.BlockHash, b.latestBlockHash)
|
||||
}
|
||||
|
||||
// LatestBlockHash returns the hash of the latest execution block.
|
||||
func (b *BeaconState) LatestBlockHash() ([32]byte, error) {
|
||||
if b.version < version.Gloas {
|
||||
@@ -147,3 +167,110 @@ func (b *BeaconState) BuilderPendingPayments() ([]*ethpb.BuilderPendingPayment,
|
||||
|
||||
return b.builderPendingPaymentsVal(), nil
|
||||
}
|
||||
|
||||
// BuilderPendingWithdrawals returns the builder pending withdrawals queue.
|
||||
func (b *BeaconState) BuilderPendingWithdrawals() ([]*ethpb.BuilderPendingWithdrawal, error) {
|
||||
if b.version < version.Gloas {
|
||||
return nil, errNotSupported("BuilderPendingWithdrawals", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.builderPendingWithdrawalsVal(), nil
|
||||
}
|
||||
|
||||
// BuildersCount returns the number of builders in the registry.
|
||||
func (b *BeaconState) BuildersCount() int {
|
||||
if b.version < version.Gloas {
|
||||
return 0
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return len(b.builders)
|
||||
}
|
||||
|
||||
// Builders returns the builders registry.
|
||||
func (b *BeaconState) Builders() ([]*ethpb.Builder, error) {
|
||||
if b.version < version.Gloas {
|
||||
return nil, errNotSupported("Builders", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
builders := make([]*ethpb.Builder, len(b.builders))
|
||||
for i := range b.builders {
|
||||
builders[i] = ethpb.CopyBuilder(b.builders[i])
|
||||
}
|
||||
|
||||
return builders, nil
|
||||
}
|
||||
|
||||
// BuildersSweepWithdrawals returns builder withdrawals selected by a sweep over the builders registry.
|
||||
// This mirrors `get_builders_sweep_withdrawals` in the spec, but performs the sweep under a single read lock.
|
||||
func (b *BeaconState) BuildersSweepWithdrawals(withdrawalIndex uint64, priorWithdrawalCount uint64) ([]*enginev1.Withdrawal, uint64, uint64, error) {
|
||||
if b.version < version.Gloas {
|
||||
return nil, withdrawalIndex, 0, errNotSupported("BuildersSweepWithdrawals", b.version)
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
withdrawalsLimit := cfg.MaxWithdrawalsPerPayload - 1
|
||||
if priorWithdrawalCount > withdrawalsLimit {
|
||||
return nil, withdrawalIndex, 0, fmt.Errorf("prior withdrawals length %d exceeds limit %d", priorWithdrawalCount, withdrawalsLimit)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if len(b.builders) == 0 {
|
||||
return nil, withdrawalIndex, 0, nil
|
||||
}
|
||||
|
||||
buildersLimit := len(b.builders)
|
||||
if maxBuilders := int(cfg.MaxBuildersPerWithdrawalsSweep); buildersLimit > maxBuilders {
|
||||
buildersLimit = maxBuilders
|
||||
}
|
||||
|
||||
builderIndex := b.nextWithdrawalBuilderIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
flag := cfg.BuilderIndexFlag
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, buildersLimit)
|
||||
var processedCount uint64
|
||||
for i := 0; i < buildersLimit; i++ {
|
||||
if priorWithdrawalCount+uint64(len(withdrawals)) >= withdrawalsLimit {
|
||||
break
|
||||
}
|
||||
|
||||
builder := b.builders[builderIndex]
|
||||
if builder != nil && builder.WithdrawableEpoch <= epoch && builder.Balance > 0 {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: primitives.ValidatorIndex(uint64(builderIndex) | flag),
|
||||
Address: bytesutil.SafeCopyBytes(builder.ExecutionAddress),
|
||||
Amount: uint64(builder.Balance),
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
|
||||
builderIndex = primitives.BuilderIndex((uint64(builderIndex) + 1) % uint64(len(b.builders)))
|
||||
processedCount++
|
||||
}
|
||||
|
||||
return withdrawals, withdrawalIndex, processedCount, nil
|
||||
}
|
||||
|
||||
// NextWithdrawalBuilderIndex returns the next builder index for the withdrawals sweep.
|
||||
func (b *BeaconState) NextWithdrawalBuilderIndex() (primitives.BuilderIndex, error) {
|
||||
if b.version < version.Gloas {
|
||||
return 0, errNotSupported("NextWithdrawalBuilderIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.nextWithdrawalBuilderIndex, nil
|
||||
}
|
||||
|
||||
176
beacon-chain/state/state-native/getters_gloas_withdrawals.go
Normal file
176
beacon-chain/state/state-native/getters_gloas_withdrawals.go
Normal file
@@ -0,0 +1,176 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v7/time/slots"
|
||||
)
|
||||
|
||||
// ExpectedWithdrawalsGloas returns the withdrawals that a proposer will need to pack in the next block
|
||||
// applied to the current state. It is also used by validators to check that the execution payload carried
|
||||
// the right number of withdrawals.
|
||||
//
|
||||
// Spec v1.7.0-alpha.1:
|
||||
//
|
||||
// def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals:
|
||||
// withdrawal_index = state.next_withdrawal_index
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
//
|
||||
// # [New in Gloas:EIP7732]
|
||||
// # Get builder withdrawals
|
||||
// builder_withdrawals, withdrawal_index, processed_builder_withdrawals_count = (
|
||||
// get_builder_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(builder_withdrawals)
|
||||
//
|
||||
// # Get partial withdrawals
|
||||
// partial_withdrawals, withdrawal_index, processed_partial_withdrawals_count = (
|
||||
// get_pending_partial_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(partial_withdrawals)
|
||||
//
|
||||
// # [New in Gloas:EIP7732]
|
||||
// # Get builders sweep withdrawals
|
||||
// builders_sweep_withdrawals, withdrawal_index, processed_builders_sweep_count = (
|
||||
// get_builders_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(builders_sweep_withdrawals)
|
||||
//
|
||||
// # Get validators sweep withdrawals
|
||||
// validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
||||
// get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(validators_sweep_withdrawals)
|
||||
//
|
||||
// return ExpectedWithdrawals(
|
||||
// withdrawals,
|
||||
// # [New in Gloas:EIP7732]
|
||||
// processed_builder_withdrawals_count,
|
||||
// processed_partial_withdrawals_count,
|
||||
// # [New in Gloas:EIP7732]
|
||||
// processed_builders_sweep_count,
|
||||
// processed_validators_sweep_count,
|
||||
// )
|
||||
func (b *BeaconState) ExpectedWithdrawalsGloas() ([]*enginev1.Withdrawal, uint64, uint64, uint64, uint64, error) {
|
||||
if b.version < version.Gloas {
|
||||
return nil, 0, 0, 0, 0, errNotSupported("ExpectedWithdrawalsGloas", b.version)
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
withdrawalsLimit := cfg.MaxWithdrawalsPerPayload - 1
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, cfg.MaxWithdrawalsPerPayload)
|
||||
withdrawnByValidator := make(map[primitives.ValidatorIndex]uint64)
|
||||
withdrawalsCount := uint64(0)
|
||||
withdrawalIndex := b.nextWithdrawalIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
|
||||
// get_builder_withdrawals
|
||||
builderWithdrawals, withdrawalIndex, processedBuilderWithdrawalsCount, err := b.getBuilderWithdrawalsGloas(withdrawalIndex, withdrawals, withdrawalsLimit)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, builderWithdrawals...)
|
||||
withdrawalsCount += uint64(len(builderWithdrawals))
|
||||
|
||||
// get_pending_partial_withdrawals
|
||||
partialWithdrawals, withdrawalIndex, processedPartialWithdrawalsCount, err := b.getPendingPartialWithdrawals(withdrawalIndex, withdrawalsCount, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, partialWithdrawals...)
|
||||
withdrawalsCount += uint64(len(partialWithdrawals))
|
||||
|
||||
// get_builders_sweep_withdrawals
|
||||
buildersSweepWithdrawals, withdrawalIndex, processedBuildersSweepCount, err := b.getBuildersSweepWithdrawalsGloas(epoch, withdrawalIndex, withdrawalsCount, withdrawalsLimit)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, buildersSweepWithdrawals...)
|
||||
withdrawalsCount += uint64(len(buildersSweepWithdrawals))
|
||||
|
||||
// get_validators_sweep_withdrawals
|
||||
validatorsSweepWithdrawals, _, processedValidatorsSweepCount, err := b.getValidatorsSweepWithdrawals(withdrawalIndex, withdrawalsCount, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, validatorsSweepWithdrawals...)
|
||||
|
||||
return withdrawals, processedBuilderWithdrawalsCount, processedPartialWithdrawalsCount, processedBuildersSweepCount, processedValidatorsSweepCount, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) getBuilderWithdrawalsGloas(withdrawalIndex uint64, priorWithdrawals []*enginev1.Withdrawal, withdrawalsLimit uint64) ([]*enginev1.Withdrawal, uint64, uint64, error) {
|
||||
cfg := params.BeaconConfig()
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, len(b.builderPendingWithdrawals))
|
||||
var processedCount uint64
|
||||
for _, w := range b.builderPendingWithdrawals {
|
||||
if uint64(len(priorWithdrawals)+len(withdrawals)) >= withdrawalsLimit {
|
||||
break
|
||||
}
|
||||
if w == nil {
|
||||
continue
|
||||
}
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: primitives.ValidatorIndex(
|
||||
uint64(primitives.BuilderIndex(w.BuilderIndex)) | cfg.BuilderIndexFlag,
|
||||
),
|
||||
Address: bytesutil.SafeCopyBytes(w.FeeRecipient),
|
||||
Amount: uint64(w.Amount),
|
||||
})
|
||||
withdrawalIndex++
|
||||
processedCount++
|
||||
}
|
||||
return withdrawals, withdrawalIndex, processedCount, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) getBuildersSweepWithdrawalsGloas(epoch primitives.Epoch, withdrawalIndex uint64, priorWithdrawalCount uint64, withdrawalsLimit uint64) ([]*enginev1.Withdrawal, uint64, uint64, error) {
|
||||
cfg := params.BeaconConfig()
|
||||
|
||||
if priorWithdrawalCount >= withdrawalsLimit || len(b.builders) == 0 {
|
||||
return nil, withdrawalIndex, 0, nil
|
||||
}
|
||||
|
||||
buildersLimit := len(b.builders)
|
||||
if maxBuilders := int(cfg.MaxBuildersPerWithdrawalsSweep); buildersLimit > maxBuilders {
|
||||
buildersLimit = maxBuilders
|
||||
}
|
||||
|
||||
builderIndex := b.nextWithdrawalBuilderIndex
|
||||
if uint64(builderIndex) >= uint64(len(b.builders)) {
|
||||
return nil, withdrawalIndex, 0, fmt.Errorf("next withdrawal builder index %d out of range", builderIndex)
|
||||
}
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, buildersLimit)
|
||||
var processedCount uint64
|
||||
for i := 0; i < buildersLimit; i++ {
|
||||
if priorWithdrawalCount+uint64(len(withdrawals)) >= withdrawalsLimit {
|
||||
break
|
||||
}
|
||||
|
||||
builder := b.builders[builderIndex]
|
||||
if builder != nil && builder.WithdrawableEpoch <= epoch && builder.Balance > 0 {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: primitives.ValidatorIndex(uint64(builderIndex) | cfg.BuilderIndexFlag),
|
||||
Address: bytesutil.SafeCopyBytes(builder.ExecutionAddress),
|
||||
Amount: uint64(builder.Balance),
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
|
||||
builderIndex = primitives.BuilderIndex((uint64(builderIndex) + 1) % uint64(len(b.builders)))
|
||||
processedCount++
|
||||
}
|
||||
|
||||
return withdrawals, withdrawalIndex, processedCount, nil
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
@@ -48,140 +49,265 @@ func (b *BeaconState) NextWithdrawalValidatorIndex() (primitives.ValidatorIndex,
|
||||
//
|
||||
// Spec definition:
|
||||
//
|
||||
// def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
||||
// epoch = get_current_epoch(state)
|
||||
// withdrawal_index = state.next_withdrawal_index
|
||||
// validator_index = state.next_withdrawal_validator_index
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
// processed_partial_withdrawals_count = 0
|
||||
// def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals:
|
||||
// withdrawal_index = state.next_withdrawal_index
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
//
|
||||
// # [New in Electra:EIP7251] Consume pending partial withdrawals
|
||||
// for withdrawal in state.pending_partial_withdrawals:
|
||||
// if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP:
|
||||
// break
|
||||
// # [New in Electra:EIP7251]
|
||||
// # Get partial withdrawals
|
||||
// partial_withdrawals, withdrawal_index, processed_partial_withdrawals_count = (
|
||||
// get_pending_partial_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(partial_withdrawals)
|
||||
//
|
||||
// validator = state.validators[withdrawal.index]
|
||||
// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
||||
// total_withdrawn = sum(w.amount for w in withdrawals if w.validator_index == withdrawal.validator_index)
|
||||
// balance = state.balances[withdrawal.validator_index] - total_withdrawn
|
||||
// has_excess_balance = balance > MIN_ACTIVATION_BALANCE
|
||||
// if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance:
|
||||
// withdrawable_balance = min(balance - MIN_ACTIVATION_BALANCE, withdrawal.amount)
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=withdrawal.index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=withdrawable_balance,
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// # Get validators sweep withdrawals
|
||||
// validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
||||
// get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
||||
// )
|
||||
// withdrawals.extend(validators_sweep_withdrawals)
|
||||
//
|
||||
// processed_partial_withdrawals_count += 1
|
||||
//
|
||||
// # Sweep for remaining.
|
||||
// bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
// for _ in range(bound):
|
||||
// validator = state.validators[validator_index]
|
||||
// # [Modified in Electra:EIP7251]
|
||||
// partially_withdrawn_balance = sum(withdrawal.amount for withdrawal in withdrawals if withdrawal.validator_index == validator_index)
|
||||
// balance = state.balances[validator_index] - partially_withdrawn_balance
|
||||
// if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=balance,
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// elif is_partially_withdrawable_validator(validator, balance):
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=balance - get_max_effective_balance(validator), # [Modified in Electra:EIP7251]
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
// break
|
||||
// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
// return withdrawals, processed_partial_withdrawals_count
|
||||
// return ExpectedWithdrawals(
|
||||
// withdrawals,
|
||||
// # [New in Electra:EIP7251]
|
||||
// processed_partial_withdrawals_count,
|
||||
// processed_validators_sweep_count,
|
||||
// )
|
||||
func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, error) {
|
||||
if b.version < version.Capella {
|
||||
if b.version < version.Capella || b.version >= version.Gloas {
|
||||
return nil, 0, errNotSupported("ExpectedWithdrawals", b.version)
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, params.BeaconConfig().MaxWithdrawalsPerPayload)
|
||||
validatorIndex := b.nextWithdrawalValidatorIndex
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, cfg.MaxWithdrawalsPerPayload)
|
||||
withdrawnByValidator := make(map[primitives.ValidatorIndex]uint64)
|
||||
withdrawalsCount := uint64(0)
|
||||
withdrawalIndex := b.nextWithdrawalIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
|
||||
// Electra partial withdrawals functionality.
|
||||
var processedPartialWithdrawalsCount uint64
|
||||
if b.version >= version.Electra {
|
||||
for _, w := range b.pendingPartialWithdrawals {
|
||||
if w.WithdrawableEpoch > epoch || len(withdrawals) >= int(params.BeaconConfig().MaxPendingPartialsPerWithdrawalsSweep) {
|
||||
break
|
||||
}
|
||||
|
||||
v, err := b.validatorAtIndexReadOnly(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to determine withdrawals at index %d: %w", w.Index, err)
|
||||
}
|
||||
vBal, err := b.balanceAtIndex(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("could not retrieve balance at index %d: %w", w.Index, err)
|
||||
}
|
||||
hasSufficientEffectiveBalance := v.EffectiveBalance() >= params.BeaconConfig().MinActivationBalance
|
||||
var totalWithdrawn uint64
|
||||
for _, wi := range withdrawals {
|
||||
if wi.ValidatorIndex == w.Index {
|
||||
totalWithdrawn += wi.Amount
|
||||
}
|
||||
}
|
||||
balance, err := mathutil.Sub64(vBal, totalWithdrawn)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "failed to subtract balance %d with total withdrawn %d", vBal, totalWithdrawn)
|
||||
}
|
||||
hasExcessBalance := balance > params.BeaconConfig().MinActivationBalance
|
||||
if v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance {
|
||||
amount := min(balance-params.BeaconConfig().MinActivationBalance, w.Amount)
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: w.Index,
|
||||
Address: v.GetWithdrawalCredentials()[12:],
|
||||
Amount: amount,
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
processedPartialWithdrawalsCount++
|
||||
partialWithdrawals, nextWithdrawalIndex, processedCount, err := b.getPendingPartialWithdrawals(withdrawalIndex, withdrawalsCount, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, partialWithdrawals...)
|
||||
withdrawalsCount += uint64(len(partialWithdrawals))
|
||||
withdrawalIndex = nextWithdrawalIndex
|
||||
processedPartialWithdrawalsCount = processedCount
|
||||
|
||||
sweepWithdrawals, _, _, err := b.getValidatorsSweepWithdrawals(withdrawalIndex, withdrawalsCount, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
withdrawals = append(withdrawals, sweepWithdrawals...)
|
||||
|
||||
return withdrawals, processedPartialWithdrawalsCount, nil
|
||||
}
|
||||
|
||||
// getPendingPartialWithdrawals is shared between Electra and Gloas expected withdrawals.
|
||||
// It assumes the caller already holds b.lock.RLock().
|
||||
//
|
||||
// Spec (Electra):
|
||||
//
|
||||
// def get_pending_partial_withdrawals(
|
||||
// state: BeaconState,
|
||||
// withdrawal_index: WithdrawalIndex,
|
||||
// prior_withdrawals: Sequence[Withdrawal],
|
||||
// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]:
|
||||
// epoch = get_current_epoch(state)
|
||||
// withdrawals_limit = min(
|
||||
// len(prior_withdrawals) + MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP,
|
||||
// MAX_WITHDRAWALS_PER_PAYLOAD - 1,
|
||||
// )
|
||||
// assert len(prior_withdrawals) <= withdrawals_limit
|
||||
//
|
||||
// processed_count: uint64 = 0
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
// for withdrawal in state.pending_partial_withdrawals:
|
||||
// all_withdrawals = prior_withdrawals + withdrawals
|
||||
// is_withdrawable = withdrawal.withdrawable_epoch <= epoch
|
||||
// has_reached_limit = len(all_withdrawals) >= withdrawals_limit
|
||||
// if not is_withdrawable or has_reached_limit:
|
||||
// break
|
||||
//
|
||||
// validator_index = withdrawal.validator_index
|
||||
// validator = state.validators[validator_index]
|
||||
// balance = get_balance_after_withdrawals(state, validator_index, all_withdrawals)
|
||||
// if is_eligible_for_partial_withdrawals(validator, balance):
|
||||
// withdrawal_amount = min(balance - MIN_ACTIVATION_BALANCE, withdrawal.amount)
|
||||
// withdrawals.append(
|
||||
// Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=withdrawal_amount,
|
||||
// )
|
||||
// )
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
//
|
||||
// processed_count += 1
|
||||
//
|
||||
// return withdrawals, withdrawal_index, processed_count
|
||||
func (b *BeaconState) getPendingPartialWithdrawals(withdrawalIndex uint64, priorWithdrawalCount uint64, withdrawnByValidator map[primitives.ValidatorIndex]uint64) ([]*enginev1.Withdrawal, uint64, uint64, error) {
|
||||
if b.version < version.Capella {
|
||||
return nil, withdrawalIndex, 0, errNotSupported("getPendingPartialWithdrawals", b.version)
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
withdrawalsLimit := min(priorWithdrawalCount+cfg.MaxPendingPartialsPerWithdrawalsSweep, cfg.MaxWithdrawalsPerPayload-1)
|
||||
if priorWithdrawalCount > withdrawalsLimit {
|
||||
return nil, withdrawalIndex, 0, fmt.Errorf("prior withdrawals length %d exceeds limit %d", priorWithdrawalCount, withdrawalsLimit)
|
||||
}
|
||||
|
||||
remaining := withdrawalsLimit - priorWithdrawalCount
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, remaining)
|
||||
var processedCount uint64
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
for _, w := range b.pendingPartialWithdrawals {
|
||||
isWithdrawable := w.WithdrawableEpoch <= epoch
|
||||
hasReachedLimit := priorWithdrawalCount+uint64(len(withdrawals)) >= withdrawalsLimit
|
||||
if !isWithdrawable || hasReachedLimit {
|
||||
break
|
||||
}
|
||||
|
||||
v, err := b.validatorAtIndexReadOnly(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, 0, fmt.Errorf("failed to determine withdrawals at index %d: %w", w.Index, err)
|
||||
}
|
||||
vBal, err := b.balanceAtIndex(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, 0, fmt.Errorf("could not retrieve balance at index %d: %w", w.Index, err)
|
||||
}
|
||||
|
||||
balance, err := b.balanceAfterWithdrawals(w.Index, vBal, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
if isEligibleForPartialWithdrawals(v, balance, cfg) {
|
||||
withdrawalAmount := min(balance-cfg.MinActivationBalance, w.Amount)
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: w.Index,
|
||||
Address: v.GetWithdrawalCredentials()[ETH1AddressOffset:],
|
||||
Amount: withdrawalAmount,
|
||||
})
|
||||
withdrawnByValidator[w.Index] += withdrawalAmount
|
||||
withdrawalIndex++
|
||||
}
|
||||
processedCount++
|
||||
}
|
||||
|
||||
return withdrawals, withdrawalIndex, processedCount, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) balanceAfterWithdrawals(validatorIndex primitives.ValidatorIndex, balance uint64, withdrawnByValidator map[primitives.ValidatorIndex]uint64) (uint64, error) {
|
||||
totalWithdrawn := withdrawnByValidator[validatorIndex]
|
||||
out, err := mathutil.Sub64(balance, totalWithdrawn)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "failed to subtract balance %d with total withdrawn %d for validator %d", balance, totalWithdrawn, validatorIndex)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func isEligibleForPartialWithdrawals(v state.ReadOnlyValidator, balance uint64, cfg *params.BeaconChainConfig) bool {
|
||||
hasSufficientEffectiveBalance := v.EffectiveBalance() >= cfg.MinActivationBalance
|
||||
hasExcessBalance := balance > cfg.MinActivationBalance
|
||||
return v.ExitEpoch() == cfg.FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance
|
||||
}
|
||||
|
||||
// getValidatorsSweepWithdrawals is shared between Electra and Gloas expected withdrawals.
|
||||
// It assumes the caller already holds b.lock.RLock().
|
||||
//
|
||||
// Spec (Electra):
|
||||
//
|
||||
// def get_validators_sweep_withdrawals(
|
||||
// state: BeaconState,
|
||||
// withdrawal_index: WithdrawalIndex,
|
||||
// prior_withdrawals: Sequence[Withdrawal],
|
||||
// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]:
|
||||
// epoch = get_current_epoch(state)
|
||||
// validators_limit = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
// withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD
|
||||
// # There must be at least one space reserved for validator sweep withdrawals
|
||||
// assert len(prior_withdrawals) < withdrawals_limit
|
||||
//
|
||||
// processed_count: uint64 = 0
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
// validator_index = state.next_withdrawal_validator_index
|
||||
// for _ in range(validators_limit):
|
||||
// all_withdrawals = prior_withdrawals + withdrawals
|
||||
// has_reached_limit = len(all_withdrawals) >= withdrawals_limit
|
||||
// if has_reached_limit:
|
||||
// break
|
||||
//
|
||||
// validator = state.validators[validator_index]
|
||||
// balance = get_balance_after_withdrawals(state, validator_index, all_withdrawals)
|
||||
// if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
// withdrawals.append(
|
||||
// Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=balance,
|
||||
// )
|
||||
// )
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// elif is_partially_withdrawable_validator(validator, balance):
|
||||
// withdrawals.append(
|
||||
// Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// # [Modified in Electra:EIP7251]
|
||||
// amount=balance - get_max_effective_balance(validator),
|
||||
// )
|
||||
// )
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
//
|
||||
// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
// processed_count += 1
|
||||
//
|
||||
// return withdrawals, withdrawal_index, processed_count
|
||||
func (b *BeaconState) getValidatorsSweepWithdrawals(withdrawalIndex uint64, priorWithdrawalCount uint64, withdrawnByValidator map[primitives.ValidatorIndex]uint64) ([]*enginev1.Withdrawal, uint64, uint64, error) {
|
||||
if b.version < version.Capella {
|
||||
return nil, withdrawalIndex, 0, errNotSupported("getValidatorsSweepWithdrawals", b.version)
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
withdrawalsLimit := cfg.MaxWithdrawalsPerPayload
|
||||
if priorWithdrawalCount >= withdrawalsLimit {
|
||||
return nil, withdrawalIndex, 0, nil
|
||||
}
|
||||
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
validatorsLen := b.validatorsLen()
|
||||
bound := min(uint64(validatorsLen), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
||||
for range bound {
|
||||
validatorsLimit := min(uint64(validatorsLen), cfg.MaxValidatorsPerWithdrawalsSweep)
|
||||
|
||||
validatorIndex := b.nextWithdrawalValidatorIndex
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, validatorsLimit)
|
||||
var processedCount uint64
|
||||
for range validatorsLimit {
|
||||
if priorWithdrawalCount+uint64(len(withdrawals)) >= withdrawalsLimit {
|
||||
break
|
||||
}
|
||||
|
||||
val, err := b.validatorAtIndexReadOnly(validatorIndex)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex)
|
||||
return nil, 0, 0, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex)
|
||||
}
|
||||
balance, err := b.balanceAtIndex(validatorIndex)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
|
||||
return nil, 0, 0, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
|
||||
}
|
||||
if b.version >= version.Electra {
|
||||
var partiallyWithdrawnBalance uint64
|
||||
for _, w := range withdrawals {
|
||||
if w.ValidatorIndex == validatorIndex {
|
||||
partiallyWithdrawnBalance += w.Amount
|
||||
}
|
||||
}
|
||||
balance, err = mathutil.Sub64(balance, partiallyWithdrawnBalance)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "could not subtract balance %d with partial withdrawn balance %d", balance, partiallyWithdrawnBalance)
|
||||
}
|
||||
|
||||
balance, err = b.balanceAfterWithdrawals(validatorIndex, balance, withdrawnByValidator)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
if helpers.IsFullyWithdrawableValidator(val, balance, epoch, b.version) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
@@ -189,26 +315,28 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err
|
||||
Address: bytesutil.SafeCopyBytes(val.GetWithdrawalCredentials()[ETH1AddressOffset:]),
|
||||
Amount: balance,
|
||||
})
|
||||
withdrawnByValidator[validatorIndex] += balance
|
||||
withdrawalIndex++
|
||||
} else if helpers.IsPartiallyWithdrawableValidator(val, balance, epoch, b.version) {
|
||||
amount := balance - helpers.ValidatorMaxEffectiveBalance(val)
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.GetWithdrawalCredentials()[ETH1AddressOffset:]),
|
||||
Amount: balance - helpers.ValidatorMaxEffectiveBalance(val),
|
||||
Amount: amount,
|
||||
})
|
||||
withdrawnByValidator[validatorIndex] += amount
|
||||
withdrawalIndex++
|
||||
}
|
||||
if uint64(len(withdrawals)) == params.BeaconConfig().MaxWithdrawalsPerPayload {
|
||||
break
|
||||
}
|
||||
validatorIndex += 1
|
||||
|
||||
validatorIndex++
|
||||
if uint64(validatorIndex) == uint64(validatorsLen) {
|
||||
validatorIndex = 0
|
||||
}
|
||||
processedCount++
|
||||
}
|
||||
|
||||
return withdrawals, processedPartialWithdrawalsCount, nil
|
||||
return withdrawals, withdrawalIndex, processedCount, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) PendingPartialWithdrawals() ([]*ethpb.PendingPartialWithdrawal, error) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/types"
|
||||
@@ -8,10 +9,32 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
)
|
||||
|
||||
// SetPayloadExpectedWithdrawals stores the expected withdrawals for the next payload.
|
||||
func (b *BeaconState) SetPayloadExpectedWithdrawals(withdrawals []*enginev1.Withdrawal) error {
|
||||
if b.version < version.Gloas {
|
||||
return errNotSupported("SetPayloadExpectedWithdrawals", b.version)
|
||||
}
|
||||
|
||||
if withdrawals == nil {
|
||||
return errors.New("cannot set nil payload expected withdrawals")
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PayloadExpectedWithdrawals].MinusRef()
|
||||
b.sharedFieldReferences[types.PayloadExpectedWithdrawals] = stateutil.NewRef(1)
|
||||
b.payloadExpectedWithdrawals = withdrawals
|
||||
b.markFieldAsDirty(types.PayloadExpectedWithdrawals)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RotateBuilderPendingPayments rotates the queue by dropping slots per epoch payments from the
|
||||
// front and appending slots per epoch empty payments to the end.
|
||||
// This implements: state.builder_pending_payments = state.builder_pending_payments[SLOTS_PER_EPOCH:] + [BuilderPendingPayment() for _ in range(SLOTS_PER_EPOCH)]
|
||||
@@ -69,6 +92,38 @@ func (b *BeaconState) AppendBuilderPendingWithdrawals(withdrawals []*ethpb.Build
|
||||
return nil
|
||||
}
|
||||
|
||||
// DequeueBuilderPendingWithdrawals removes processed builder withdrawals from the front of the queue.
|
||||
func (b *BeaconState) DequeueBuilderPendingWithdrawals(n uint64) error {
|
||||
if b.version < version.Gloas {
|
||||
return errNotSupported("DequeueBuilderPendingWithdrawals", b.version)
|
||||
}
|
||||
|
||||
if n > uint64(len(b.builderPendingWithdrawals)) {
|
||||
return errors.New("cannot dequeue more builder withdrawals than are in the queue")
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.sharedFieldReferences[types.BuilderPendingWithdrawals].Refs() > 1 {
|
||||
withdrawals := make([]*ethpb.BuilderPendingWithdrawal, len(b.builderPendingWithdrawals))
|
||||
copy(withdrawals, b.builderPendingWithdrawals)
|
||||
b.builderPendingWithdrawals = withdrawals
|
||||
b.sharedFieldReferences[types.BuilderPendingWithdrawals].MinusRef()
|
||||
b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.builderPendingWithdrawals = b.builderPendingWithdrawals[n:]
|
||||
b.markFieldAsDirty(types.BuilderPendingWithdrawals)
|
||||
b.rebuildTrie[types.BuilderPendingWithdrawals] = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetExecutionPayloadBid sets the latest execution payload bid in the state.
|
||||
func (b *BeaconState) SetExecutionPayloadBid(h interfaces.ROExecutionPayloadBid) error {
|
||||
if b.version < version.Gloas {
|
||||
@@ -161,3 +216,17 @@ func (b *BeaconState) UpdateExecutionPayloadAvailabilityAtIndex(idx uint64, val
|
||||
b.markFieldAsDirty(types.ExecutionPayloadAvailability)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetNextWithdrawalBuilderIndex sets the next builder index for the withdrawals sweep.
|
||||
func (b *BeaconState) SetNextWithdrawalBuilderIndex(index primitives.BuilderIndex) error {
|
||||
if b.version < version.Gloas {
|
||||
return errNotSupported("SetNextWithdrawalBuilderIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.nextWithdrawalBuilderIndex = index
|
||||
b.markFieldAsDirty(types.NextWithdrawalBuilderIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ type BeaconChainConfig struct {
|
||||
HysteresisQuotient uint64 `yaml:"HYSTERESIS_QUOTIENT" spec:"true"` // HysteresisQuotient defines the hysteresis quotient for effective balance calculations.
|
||||
HysteresisDownwardMultiplier uint64 `yaml:"HYSTERESIS_DOWNWARD_MULTIPLIER" spec:"true"` // HysteresisDownwardMultiplier defines the hysteresis downward multiplier for effective balance calculations.
|
||||
HysteresisUpwardMultiplier uint64 `yaml:"HYSTERESIS_UPWARD_MULTIPLIER" spec:"true"` // HysteresisUpwardMultiplier defines the hysteresis upward multiplier for effective balance calculations.
|
||||
BuilderIndexFlag uint64 `yaml:"BUILDER_INDEX_FLAG" spec:"true"` // BuilderIndexFlag marks a ValidatorIndex as a BuilderIndex when the bit is set.
|
||||
|
||||
// Gwei value constants.
|
||||
MinDepositAmount uint64 `yaml:"MIN_DEPOSIT_AMOUNT" spec:"true"` // MinDepositAmount is the minimum amount of Gwei a validator can send to the deposit contract at once (lower amounts will be reverted).
|
||||
@@ -126,6 +127,7 @@ type BeaconChainConfig struct {
|
||||
MaxWithdrawalsPerPayload uint64 `yaml:"MAX_WITHDRAWALS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalsPerPayload defines the maximum number of withdrawals in a block.
|
||||
MaxBlsToExecutionChanges uint64 `yaml:"MAX_BLS_TO_EXECUTION_CHANGES" spec:"true"` // MaxBlsToExecutionChanges defines the maximum number of BLS-to-execution-change objects in a block.
|
||||
MaxValidatorsPerWithdrawalsSweep uint64 `yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxValidatorsPerWithdrawalsSweep bounds the size of the sweep searching for withdrawals per slot.
|
||||
MaxBuildersPerWithdrawalsSweep uint64 `yaml:"MAX_BUILDERS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxBuildersPerWithdrawalsSweep bounds the size of the builder withdrawals sweep per slot.
|
||||
|
||||
// BLS domain values.
|
||||
DomainBeaconProposer [4]byte `yaml:"DOMAIN_BEACON_PROPOSER" spec:"true"` // DomainBeaconProposer defines the BLS signature domain for beacon proposal verification.
|
||||
|
||||
@@ -194,6 +194,8 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte {
|
||||
fmt.Sprintf("SHARD_COMMITTEE_PERIOD: %d", cfg.ShardCommitteePeriod),
|
||||
fmt.Sprintf("MIN_VALIDATOR_WITHDRAWABILITY_DELAY: %d", cfg.MinValidatorWithdrawabilityDelay),
|
||||
fmt.Sprintf("MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: %d", cfg.MaxValidatorsPerWithdrawalsSweep),
|
||||
fmt.Sprintf("MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: %d", cfg.MaxBuildersPerWithdrawalsSweep),
|
||||
fmt.Sprintf("BUILDER_INDEX_FLAG: %d", cfg.BuilderIndexFlag),
|
||||
fmt.Sprintf("MAX_SEED_LOOKAHEAD: %d", cfg.MaxSeedLookahead),
|
||||
fmt.Sprintf("EJECTION_BALANCE: %d", cfg.EjectionBalance),
|
||||
fmt.Sprintf("MIN_PER_EPOCH_CHURN_LIMIT: %d", cfg.MinPerEpochChurnLimit),
|
||||
|
||||
@@ -83,6 +83,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
HysteresisQuotient: 4,
|
||||
HysteresisDownwardMultiplier: 1,
|
||||
HysteresisUpwardMultiplier: 5,
|
||||
BuilderIndexFlag: 1099511627776,
|
||||
|
||||
// Gwei value constants.
|
||||
MinDepositAmount: 1 * 1e9,
|
||||
@@ -169,6 +170,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
MaxWithdrawalsPerPayload: 16,
|
||||
MaxBlsToExecutionChanges: 16,
|
||||
MaxValidatorsPerWithdrawalsSweep: 16384,
|
||||
MaxBuildersPerWithdrawalsSweep: 16384,
|
||||
|
||||
// BLS domain values.
|
||||
DomainBeaconProposer: bytesutil.Uint32ToBytes4(0x00000000),
|
||||
|
||||
@@ -49,6 +49,7 @@ func compareConfigs(t *testing.T, expected, actual *params.BeaconChainConfig) {
|
||||
require.DeepEqual(t, expected.HysteresisQuotient, actual.HysteresisQuotient)
|
||||
require.DeepEqual(t, expected.HysteresisDownwardMultiplier, actual.HysteresisDownwardMultiplier)
|
||||
require.DeepEqual(t, expected.HysteresisUpwardMultiplier, actual.HysteresisUpwardMultiplier)
|
||||
require.DeepEqual(t, expected.BuilderIndexFlag, actual.BuilderIndexFlag)
|
||||
require.DeepEqual(t, expected.MinDepositAmount, actual.MinDepositAmount)
|
||||
require.DeepEqual(t, expected.MaxEffectiveBalance, actual.MaxEffectiveBalance)
|
||||
require.DeepEqual(t, expected.EjectionBalance, actual.EjectionBalance)
|
||||
@@ -94,6 +95,7 @@ func compareConfigs(t *testing.T, expected, actual *params.BeaconChainConfig) {
|
||||
require.DeepEqual(t, expected.MaxDeposits, actual.MaxDeposits)
|
||||
require.DeepEqual(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits)
|
||||
require.DeepEqual(t, expected.MaxWithdrawalsPerPayload, actual.MaxWithdrawalsPerPayload)
|
||||
require.DeepEqual(t, expected.MaxBuildersPerWithdrawalsSweep, actual.MaxBuildersPerWithdrawalsSweep)
|
||||
require.DeepEqual(t, expected.DomainBeaconProposer, actual.DomainBeaconProposer)
|
||||
require.DeepEqual(t, expected.DomainRandao, actual.DomainRandao)
|
||||
require.DeepEqual(t, expected.DomainBeaconAttester, actual.DomainBeaconAttester)
|
||||
|
||||
Reference in New Issue
Block a user