rm outdated/semi-duplicate execution layer withdrawal request processing (#6301)
This commit is contained in:
parent
34853ca155
commit
dd452f71d3
|
@ -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 =
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue