Closed moles1 closed 12 months ago
One possible solution would be to record shares in a validator on the beacon chain itself. A naive implementation might look like the following:
Set MAX_VALIDATOR_SHARES
to an arbitrary constant, e.g. 32
Update validator container to:
class Validator(Container):
pubkey: BLSPubkey
withdrawal_credentials: Vector[Bytes32, MAX_VALIDATOR_SHARES] # Commitments to pubkeys for withdrawals
withdrawal_shares: Vector[Gwei, MAX_VALIDATOR_SHARES] # Relative shares for each set of withdrawal credentials, by index
effective_balance: Gwei # Balance at stake
slashed: boolean
# Status epochs
activation_eligibility_epoch: Epoch # When criteria for activation were met
activation_epoch: Epoch
exit_epoch: Epoch
withdrawable_epoch: Epoch # When validator can withdraw funds
In the process_deposit method, if deposit.data.pubkey
is found in validator_pubkeys
(and before increase_balance
is called):
validator
to state.validators[index]
validator_balance
to state.balances[index]
total_withdrawal_shares
to the sum of validator.withdrawal_shares
total_withdrawal_shares != validator_balance
, for each validator.withdrawal_shares
, update share
to share * validator_balance / total_withdrawal_shares
deposit.data.withdrawal_credentials
in validator.withdrawal_credentials
:
deposit.data.amount
to validator.withdrawal_shares
at matching index;len(validator.withdrawal_credentials) < MAX_VALIDATOR_SHARES
, then append deposit.data.withdrawal_credentials
to validator.withdrawal_credentials
and append deposit.data.amount
to validator.withdrawal_shares
During operations where validator balance is transferred (such as transfers and withdrawals):
validator.withdrawal_credentials
and find the matching share index
validator.withdrawal_shares[index] > 0
transfer_amount
to validator.withdrawal_shares[index] * validator_balance / total_withdrawal_shares
(as described above)transfer_amount
validator.withdrawal_shares[index]
to 0
decrease_balance
Another possible solution involves adding an alternate withdrawal mechanism to the spec, where the submitted withdrawal credentials represent an eth 1.0 address, instead of a BLS pubkey (/ eth 2.0 address).
During the construction of validator deposit data:
ETH1_WITHDRAWAL_PREFIX
to an arbitrary constant, e.g. Bytes1('0x01')
withdrawal_credentials[:1]
to ETH1_WITHDRAWAL_PREFIX
withdrawal_credentials[1:21]
to the eth 1.0 withdrawal addresswithdrawal_credentials[21:]
to null bytesThis solution requires no changes to the spec for phases 0 & 1, but obviously does require a strong commitment to an eth1 + eth2 merge e.g. as described in this ethresearch post. It also assumes that there will be a guaranteed mechanism whereby the beacon chain can process withdrawal messages from an eth1 address.
(Thanks to @dankrad for participating in initial discussions around this issue and helping to explore options!)
Execution withdrawal credentials type 0x01 are available now, merge and capella fork activated :)
After the phase 2 rollout, validator deposits can be made with withdrawal credentials representing the address of a smart contract on a shard.
However, during phases 0 & 1, the only option for withdrawal credentials is the pubkey of a BLS keypair (or an aggregate key) submitted by the depositor. This poses a significant problem for trustless validator pools wanting to operate during this time:
This makes it difficult for decentralized staking pools to operate during phases 0 & 1, potentially moving the ecosystem towards centralized / custodial platforms. There do not appear to be viable solutions to this problem outside of the protocol; some possible in-protocol solutions are outlined below: