Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eth1 withdrawal credentials (0x01) #2149

Merged
merged 11 commits into from
Feb 16, 2021
7 changes: 7 additions & 0 deletions specs/phase0/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [Misc](#misc)
- [Gwei values](#gwei-values)
- [Initial values](#initial-values)
- [Withdrawal prefixes](#withdrawal-prefixes)
- [Time parameters](#time-parameters)
- [State list lengths](#state-list-lengths)
- [Rewards and penalties](#rewards-and-penalties)
Expand Down Expand Up @@ -209,7 +210,13 @@ The following values are (non-configurable) constants used throughout the specif
| Name | Value |
| - | - |
| `GENESIS_FORK_VERSION` | `Version('0x00000000')` |

### Withdrawal prefixes

| Name | Value |
| - | - |
| `BLS_WITHDRAWAL_PREFIX` | `Bytes1('0x00')` |
| `ETH1_ADDRESS_WITHDRAWAL_PREFIX` | `Bytes1('0x01')` |

### Time parameters

Expand Down
11 changes: 6 additions & 5 deletions specs/phase0/deposit-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@ The amount of ETH (rounded down to the closest Gwei) sent to the deposit contrac

#### Withdrawal credentials

One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawing validator balance (e.g. to another validator, or to shards). The first byte of `withdrawal_credentials` is a version number. As of now, the only expected format is as follows:
One of the `DepositData` fields is `withdrawal_credentials` which constrains validator withdrawals.
The first byte of this 32-byte field is a withdrawal prefix which defines the semantics of the remaining 31 bytes.
The withdrawal prefixes currently supported are `BLS_WITHDRAWAL_PREFIX` and `ETH1_ADDRESS_WITHDRAWAL_PREFIX`.
Read more in the [validator guide](./validator.md#withdrawal-credentials).

* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX`
* `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey

The private key corresponding to `withdrawal_pubkey` will be required to initiate a withdrawal. It can be stored separately until a withdrawal is required, e.g. in cold storage.
*Note*: The deposit contract does not validate the `withdrawal_credentials` field.
Support for new withdrawal prefixes can be added without modifying the deposit contract.

#### `DepositEvent` log

Expand Down
41 changes: 35 additions & 6 deletions specs/phase0/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ This is an accompanying document to [Ethereum 2.0 Phase 0 -- The Beacon Chain](.
- [Becoming a validator](#becoming-a-validator)
- [Initialization](#initialization)
- [BLS public key](#bls-public-key)
- [BLS withdrawal key](#bls-withdrawal-key)
- [Withdrawal credentials](#withdrawal-credentials)
- [`BLS_WITHDRAWAL_PREFIX`](#bls_withdrawal_prefix)
- [`ETH1_ADDRESS_WITHDRAWAL_PREFIX`](#eth1_address_withdrawal_prefix)
- [Submit deposit](#submit-deposit)
- [Process deposit](#process-deposit)
- [Validator index](#validator-index)
Expand Down Expand Up @@ -100,14 +102,41 @@ A validator must initialize many parameters locally before submitting a deposit

Validator public keys are [G1 points](beacon-chain.md#bls-signatures) on the [BLS12-381 curve](https://z.cash/blog/new-snark-curve). A private key, `privkey`, must be securely generated along with the resultant `pubkey`. This `privkey` must be "hot", that is, constantly available to sign data throughout the lifetime of the validator.

#### BLS withdrawal key
#### Withdrawal credentials

A secondary withdrawal private key, `withdrawal_privkey`, must also be securely generated along with the resultant `withdrawal_pubkey`. This `withdrawal_privkey` does not have to be available for signing during the normal lifetime of a validator and can live in "cold storage".
The `withdrawal_credentials` field constrains validator withdrawals.
The first byte of this 32-byte field is a withdrawal prefix which defines the semantics of the remaining 31 bytes.

The validator constructs their `withdrawal_credentials` via the following:
The following withdrawal prefixes are currently supported.

* Set `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX`.
* Set `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]`.
##### `BLS_WITHDRAWAL_PREFIX`

Withdrawal credentials with the BLS withdrawal prefix allow a BLS key pair
`(bls_withdrawal_privkey, bls_withdrawal_pubkey)` to trigger withdrawals.
The `withdrawal_credentials` field must be such that:

* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX`
* `withdrawal_credentials[1:] == hash(bls_withdrawal_pubkey)[1:]`

*Note*: The `bls_withdrawal_privkey` is not required for validating and can be kept in cold storage.

##### `ETH1_ADDRESS_WITHDRAWAL_PREFIX`

Withdrawal credentials with the Eth1 address withdrawal prefix specify
a 20-byte Eth1 address `eth1_withdrawal_address` as the recipient for all withdrawals.
The `eth1_withdrawal_address` can be the address of either an externally owned account or of a contract.

The `withdrawal_credentials` field must be such that:

* `withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX`
* `withdrawal_credentials[1:12] == b'\x00' * 11`
* `withdrawal_credentials[12:] == eth1_withdrawal_address`

After the merge of eth1 into eth2,
withdrawals to `eth1_withdrawal_address` will be normal ETH transfers (with no payload other than the validator's ETH)
triggered by a user transaction that will set the gas price and gas limit as well pay fees.
As long as the account or contract with address `eth1_withdrawal_address` can receive ETH transfers
the future withdrawal protocol is agnostic to all other implementation details.

### Submit deposit

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,49 @@ def test_new_deposit_over_max(spec, state):
yield from run_deposit_processing(spec, state, deposit, validator_index)


@with_all_phases
@spec_state_test
def test_new_deposit_eth1_withdrawal_credentials(spec, state):
# fresh deposit = next validator index = validator appended to registry
validator_index = len(state.validators)
withdrawal_credentials = (
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
+ b'\x00' * 11 # specified 0s
+ b'\x59' * 20 # a 20-byte eth1 address
)
amount = spec.MAX_EFFECTIVE_BALANCE
deposit = prepare_state_and_deposit(
spec, state,
validator_index,
amount,
withdrawal_credentials=withdrawal_credentials,
signed=True,
)

yield from run_deposit_processing(spec, state, deposit, validator_index)


@with_all_phases
@spec_state_test
def test_new_deposit_non_versioned_withdrawal_credentials(spec, state):
djrtwo marked this conversation as resolved.
Show resolved Hide resolved
# fresh deposit = next validator index = validator appended to registry
validator_index = len(state.validators)
withdrawal_credentials = (
b'\xFF' # Non specified withdrawal credentials version
+ b'\x02' * 31 # Garabage bytes
)
amount = spec.MAX_EFFECTIVE_BALANCE
deposit = prepare_state_and_deposit(
spec, state,
validator_index,
amount,
withdrawal_credentials=withdrawal_credentials,
signed=True,
)

yield from run_deposit_processing(spec, state, deposit, validator_index)


@with_all_phases
@spec_state_test
@always_bls
Expand Down