Try   HackMD

Issue: Add operation for withdrawal credentials change operation

What?

New operation and signed message is proposed for Eth2, BLSSetWithdrawal, which could permanently change withdrawal_credentials:

BLSSetWithdrawal

class BLSSetWithdrawal(Container):
    bls_withdrawal_pubkey: Bytes32   # Reveal of withdrawal public key
    withdrawal_credentials: Bytes32  # New withdrawal credentials, shouldn't start with BLS_WITHDRAWAL_PREFIX (0x00)
    validator_index: ValidatorIndex

And SignedBLSSetWithdrawal message:

SignedBLSSetWithdrawal

class SignedBLSSetWithdrawal(Container):
    message: BLSSetWithdrawal
    signature: BLSSignature  # Signed by withdrawal BLS key

Why?

It's already confirmed that at least one extra withdrawal target option will be supported with merge of PR #2149 "Eth1 withdrawal credentials (0x01)" by @djrtwo. While new validators could submit deposits using this option, there were already tons of deposits before this PR was merged and some of their owners could be interested in Eth1 withdrawal. Moreover, for some parties it could be a best flow of withdrawal control during validator lifecycle to start with BLS key 0x00 withdrawal credentials and change it's target to Eth1 address later with 0x01 or another options introduced in future.

How?

  • we verify that current validator’s withdrawal_credentials is started with BLS_WITHDRAWAL_PREFIX (0x00)
  • we verify that new credentials are not started with BLS_WITHDRAWAL_PREFIX (0x00)

There are several assessments when choosing such behavior of this operation:

  • Why don’t allow change to another BLS public key? There are 2 most obvious usages for 0x00 to another 0x00 swaps:
    • Validator's withdrawal key was compromised. For some validators it would mean the validator signing key could be under attack too and the safest way is to withdraw now. Changing credentials to explicit target works in the safest way in this case
    • Validators could be traded on some market by withdrawal pubkey change. Currently there is no mechanism to change validator's signing key and it's not known whether it will be introduced in future. Also it provides additional load on beacon chain network and block size making this type of message to fight for its place under the sun with Deposit, Attestation and other more important network message types.
  • Whether to check that withdrawal_credentials is in the currently supported range. The answer should be “no”, as the deposit contract already doesn’t check it. It’s a kind of risk for the minutest number of user errors, but by changing this we could open a way to a number of bugs that could affect all users.

Draft implementation:

def process_bls_set_withdrawal(state: BeaconState, signed_bls_set_withdrawal: SignedBLSSetWithdrawal) -> None:
    set_withdrawal = signed_bls_set_withdrawal.message
    validator = state.validators[set_withdrawal.validator_index]
    # Verify the validator has BLS pubkey commitment
    assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
    # Verify the validator is active
    assert is_active_validator(validator, get_current_epoch(state))
    # Verify exit has not been initiated
    assert validator.exit_epoch == FAR_FUTURE_EPOCH
    # Verify new withdrawal credentials doesn't start with BLS_WITHDRAWAL_PREFIX
    assert set_withdrawal.withdrawal_credentials[:1] != BLS_WITHDRAWAL_PREFIX
    # Verify BLS pubkey reveal is correct
    assert hash(set_withdrawal.withdrawal_pubkey)[1:] == validator.withdrawal_credentials[1:]
    # Verify signature
    domain = get_domain(state, DOMAIN_BLS_SET_WITHDRAWAL, get_current_epoch(state))
    signing_root = compute_signing_root(set_withdrawal, domain)
    assert bls.Verify(set_withdrawal.withdrawal_pubkey, signing_root, signed_bls_set_withdrawal.signature)
    # Update withdrawal credentials
    validator.withdrawal_credentials = set_withdrawal.withdrawal_credentials

Some concerns

We have two options here, and I'm not sure, which way should we go:

  • allow change of credentials only for validators that doesn't initiate the exit
  • allow change of credentials for exited validators

Second option requires extra processing of withdrawals after withdrawal_credentials are changed for already exited validators. It’s not straightforward and requires thoughtful implementation to avoid bugs. For example, when we have 2 active withdrawal options, we should verify that one was not processed before withdrawal_credentials change, though Eth1 withdrawal is planned to be automatically on validator exit without extra messages on Beacon Chain, while BLS key withdrawal will require new message with processing.

Some important notes

  • this approach means once withdrawal_credentials are changed from BLS_WITHDRAWAL_PREFIX (0x00) to any other, withdrawal target could not be changed anymore. But this is already concreted by PR #2149
  • BLSSetWithdrawal could be added already, as nothing prevents to submit withdrawal_credentials to Deposit Contract today with a prefix other than BLS_WITHDRAWAL_PREFIX (0x00)

Simple eth1 withdrawals (beacon-chain centric) with BLSSetWithdrawalAddress proposal by @djrtwo inspiring this issue

Eth1 withdrawal credentials (0x01) #2149 by @djrtwo - PR merged in specs

Withdrawal credential rotation from BLS to Eth1 - some alternative approaches of withdrawal credentials change

Allow withdrawal_credentials to point to an eth1 address #2040 by @dapplion - Issue to add eth1 withdrawal prefix