rm outdated/semi-duplicate execution layer withdrawal request processing (#6301)

This commit is contained in:
tersec 2024-05-21 23:59:11 +00:00 committed by GitHub
parent 34853ca155
commit dd452f71d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 102 deletions

View File

@ -507,43 +507,86 @@ proc process_bls_to_execution_change*(
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/94a0b6c581f2809aa8aca4ef7ee6fbb63f9d74e9/specs/electra/beacon-chain.md#new-process_execution_layer_exit # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.2/specs/electra/beacon-chain.md#new-process_execution_layer_withdrawal_request
func process_execution_layer_withdrawal_request( func process_execution_layer_withdrawal_request*(
cfg: RuntimeConfig, state: var electra.BeaconState, cfg: RuntimeConfig, state: var electra.BeaconState,
execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest, execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest,
exit_queue_info: ExitQueueInfo, cache: var StateCache): cache: var StateCache) =
Result[ExitQueueInfo, cstring] =
# Verify pubkey exists
let let
pubkey_to_exit = execution_layer_withdrawal_request.validator_pubkey amount = execution_layer_withdrawal_request.amount
validator_index = findValidatorIndex(state, pubkey_to_exit).valueOr: is_full_exit_request = amount == static(FULL_EXIT_REQUEST_AMOUNT.Gwei)
return err("process_execution_layer_withdrawal_request: unknown index for validator pubkey")
validator = state.validators.item(validator_index) # If partial withdrawal queue is full, only full exits are processed
if lenu64(state.pending_partial_withdrawals) ==
PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
return
let
request_pubkey = execution_layer_withdrawal_request.validator_pubkey
index = findValidatorIndex(state, request_pubkey).valueOr:
return
validator = state.validators.item(index)
# Verify withdrawal credentials # Verify withdrawal credentials
let let
is_execution_address = validator.has_eth1_withdrawal_credential has_correct_credential = has_execution_withdrawal_credential(validator)
is_correct_source_address = is_correct_source_address =
validator.withdrawal_credentials.data.toOpenArray(12, 31) == validator.withdrawal_credentials.data.toOpenArray(12, 31) ==
execution_layer_withdrawal_request.source_address.data execution_layer_withdrawal_request.source_address.data
if not (is_execution_address and is_correct_source_address):
return err("process_execution_layer_withdrawal_request: not both execution address and correct source address") if not (has_correct_credential and is_correct_source_address):
return
# Verify the validator is active # Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)): if not is_active_validator(validator, get_current_epoch(state)):
return err("process_execution_layer_withdrawal_request: not active validator") return
# Verify exit has not been initiated # Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH: if validator.exit_epoch != FAR_FUTURE_EPOCH:
return err("process_execution_layer_withdrawal_request: validator exit already initiated") return
# Verify the validator has been active long enough # Verify the validator has been active long enough
if get_current_epoch(state) < validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD: if get_current_epoch(state) <
return err("process_execution_layer_withdrawal_request: validator not active long enough") validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD:
return
# Initiate exit let pending_balance_to_withdraw =
ok(? initiate_validator_exit( get_pending_balance_to_withdraw(state, index)
cfg, state, validator_index, exit_queue_info, cache))
if is_full_exit_request:
# Only exit validator if it has no pending withdrawals in the queue
if pending_balance_to_withdraw == 0.Gwei:
if initiate_validator_exit(cfg, state, index, default(ExitQueueInfo),
cache).isErr():
return
return
let
has_sufficient_effective_balance =
validator.effective_balance >= static(MIN_ACTIVATION_BALANCE.Gwei)
has_excess_balance = state.balances.item(index) >
static(MIN_ACTIVATION_BALANCE.Gwei) + pending_balance_to_withdraw
# Only allow partial withdrawals with compounding withdrawal credentials
if has_compounding_withdrawal_credential(validator) and
has_sufficient_effective_balance and has_excess_balance:
let
to_withdraw = min(
state.balances.item(index) - static(MIN_ACTIVATION_BALANCE.Gwei) -
pending_balance_to_withdraw,
amount
)
exit_queue_epoch =
compute_exit_epoch_and_update_churn(cfg, state, to_withdraw, cache)
withdrawable_epoch =
Epoch(exit_queue_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
# In theory can fail, but failing/early returning here is indistinguishable
discard state.pending_partial_withdrawals.add(PendingPartialWithdrawal(
index: index.uint64,
amount: to_withdraw,
withdrawable_epoch: withdrawable_epoch,
))
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#consolidations # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#consolidations
proc process_consolidation*( proc process_consolidation*(
@ -703,8 +746,8 @@ proc process_operations(
# [New in Electra:EIP7002:EIP7251] # [New in Electra:EIP7002:EIP7251]
when typeof(body).kind >= ConsensusFork.Electra: when typeof(body).kind >= ConsensusFork.Electra:
for op in body.execution_payload.withdrawal_requests: for op in body.execution_payload.withdrawal_requests:
discard ? process_execution_layer_withdrawal_request( process_execution_layer_withdrawal_request(
cfg, state, op, default(ExitQueueInfo), cache) cfg, state, op, cache)
for op in body.execution_payload.deposit_receipts: for op in body.execution_payload.deposit_receipts:
debugComment "combine with previous bloom filter construction" debugComment "combine with previous bloom filter construction"
let bloom_filter = constructBloomFilter(state.validators.asSeq) let bloom_filter = constructBloomFilter(state.validators.asSeq)
@ -1035,87 +1078,6 @@ func process_withdrawals*(
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-process_execution_layer_withdrawal_request
func process_execution_layer_withdrawal_request*(
cfg: RuntimeConfig, state: var electra.BeaconState,
execution_layer_withdrawal_request: ExecutionLayerWithdrawalRequest,
cache: var StateCache) =
let
amount = execution_layer_withdrawal_request.amount
is_full_exit_request = amount == static(FULL_EXIT_REQUEST_AMOUNT.Gwei)
# If partial withdrawal queue is full, only full exits are processed
if lenu64(state.pending_partial_withdrawals) ==
PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
return
let
request_pubkey = execution_layer_withdrawal_request.validator_pubkey
index = findValidatorIndex(state, request_pubkey).valueOr:
return
validator = state.validators.item(index)
# Verify withdrawal credentials
let
has_correct_credential = has_execution_withdrawal_credential(validator)
is_correct_source_address =
validator.withdrawal_credentials.data.toOpenArray(12, 31) ==
execution_layer_withdrawal_request.source_address.data
if not (has_correct_credential and is_correct_source_address):
return
# Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)):
return
# Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH:
return
# Verify the validator has been active long enough
if get_current_epoch(state) <
validator.activation_epoch + cfg.SHARD_COMMITTEE_PERIOD:
return
let pending_balance_to_withdraw =
get_pending_balance_to_withdraw(state, index)
if is_full_exit_request:
# Only exit validator if it has no pending withdrawals in the queue
if pending_balance_to_withdraw == 0.Gwei:
if initiate_validator_exit(cfg, state, index, default(ExitQueueInfo),
cache).isErr():
return
return
let
has_sufficient_effective_balance =
validator.effective_balance >= static(MIN_ACTIVATION_BALANCE.Gwei)
has_excess_balance = state.balances.item(index) >
static(MIN_ACTIVATION_BALANCE.Gwei) + pending_balance_to_withdraw
# Only allow partial withdrawals with compounding withdrawal credentials
if has_compounding_withdrawal_credential(validator) and
has_sufficient_effective_balance and has_excess_balance:
let
to_withdraw = min(
state.balances.item(index) - static(MIN_ACTIVATION_BALANCE.Gwei) -
pending_balance_to_withdraw,
amount
)
exit_queue_epoch =
compute_exit_epoch_and_update_churn(cfg, state, to_withdraw, cache)
withdrawable_epoch =
Epoch(exit_queue_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
# In theory can fail, but failing/early returning here is indistinguishable
discard state.pending_partial_withdrawals.add(PendingPartialWithdrawal(
index: index.uint64,
amount: to_withdraw,
withdrawable_epoch: withdrawable_epoch,
))
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash # https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash
func kzg_commitment_to_versioned_hash*( func kzg_commitment_to_versioned_hash*(
kzg_commitment: KzgCommitment): VersionedHash = kzg_commitment: KzgCommitment): VersionedHash =

View File

@ -239,16 +239,19 @@ proc doSSZ(conf: NcliConf) =
of "bellatrix_signed_block": printit(bellatrix.SignedBeaconBlock) of "bellatrix_signed_block": printit(bellatrix.SignedBeaconBlock)
of "capella_signed_block": printit(capella.SignedBeaconBlock) of "capella_signed_block": printit(capella.SignedBeaconBlock)
of "deneb_signed_block": printit(deneb.SignedBeaconBlock) of "deneb_signed_block": printit(deneb.SignedBeaconBlock)
of "electra_signed_block": printit(electra.SignedBeaconBlock)
of "phase0_block": printit(phase0.BeaconBlock) of "phase0_block": printit(phase0.BeaconBlock)
of "altair_block": printit(altair.BeaconBlock) of "altair_block": printit(altair.BeaconBlock)
of "bellatrix_block": printit(bellatrix.BeaconBlock) of "bellatrix_block": printit(bellatrix.BeaconBlock)
of "capella_block": printit(capella.BeaconBlock) of "capella_block": printit(capella.BeaconBlock)
of "deneb_block": printit(deneb.BeaconBlock) of "deneb_block": printit(deneb.BeaconBlock)
of "electra_block": printit(electra.BeaconBlock)
of "phase0_block_body": printit(phase0.BeaconBlockBody) of "phase0_block_body": printit(phase0.BeaconBlockBody)
of "altair_block_body": printit(altair.BeaconBlockBody) of "altair_block_body": printit(altair.BeaconBlockBody)
of "bellatrix_block_body": printit(bellatrix.BeaconBlockBody) of "bellatrix_block_body": printit(bellatrix.BeaconBlockBody)
of "capella_block_body": printit(capella.BeaconBlockBody) of "capella_block_body": printit(capella.BeaconBlockBody)
of "deneb_block_body": printit(deneb.BeaconBlockBody) of "deneb_block_body": printit(deneb.BeaconBlockBody)
of "electra_block_body": printit(electra.BeaconBlockBody)
of "block_header": printit(BeaconBlockHeader) of "block_header": printit(BeaconBlockHeader)
of "deposit": printit(Deposit) of "deposit": printit(Deposit)
of "deposit_data": printit(DepositData) of "deposit_data": printit(DepositData)
@ -258,6 +261,7 @@ proc doSSZ(conf: NcliConf) =
of "bellatrix_state": printit(bellatrix.BeaconState) of "bellatrix_state": printit(bellatrix.BeaconState)
of "capella_state": printit(capella.BeaconState) of "capella_state": printit(capella.BeaconState)
of "deneb_state": printit(deneb.BeaconState) of "deneb_state": printit(deneb.BeaconState)
of "electra_state": printit(electra.BeaconState)
of "proposer_slashing": printit(ProposerSlashing) of "proposer_slashing": printit(ProposerSlashing)
of "voluntary_exit": printit(VoluntaryExit) of "voluntary_exit": printit(VoluntaryExit)

View File

@ -6,6 +6,7 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].} {.push raises: [].}
{.used.}
import unittest2, results, chronos, stint import unittest2, results, chronos, stint
import ../beacon_chain/validators/beacon_validators, import ../beacon_chain/validators/beacon_validators,