Added domain separation
This commit is contained in:
parent
71451e0a0b
commit
54217772fe
|
@ -90,6 +90,15 @@ The primary source of load on the beacon chain are "attestations". Attestations
|
||||||
| `ENTRY` | `0` |
|
| `ENTRY` | `0` |
|
||||||
| `EXIT` | `1` |
|
| `EXIT` | `1` |
|
||||||
|
|
||||||
|
**Domains for BLS signatures**
|
||||||
|
|
||||||
|
| Name | Value |
|
||||||
|
| - | :-: |
|
||||||
|
| `DOMAIN_DEPOSIT` | `0` |
|
||||||
|
| `DOMAIN_ATTESTATION` | `1` |
|
||||||
|
| `DOMAIN_PROPOSAL` | `2` |
|
||||||
|
| `DOMAIN_LOGOUT` | `3` |
|
||||||
|
|
||||||
### PoW chain registration contract
|
### PoW chain registration contract
|
||||||
|
|
||||||
The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to the PoW chain. A registration contract is added to the PoW chain to deposit ETH. This contract has a `registration` function which takes as arguments `pubkey`, `withdrawal_shard`, `withdrawal_address`, `randao_commitment` as defined in a `ValidatorRecord` below. A BLS `proof_of_possession` of types `bytes` is given as a final argument.
|
The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to the PoW chain. A registration contract is added to the PoW chain to deposit ETH. This contract has a `registration` function which takes as arguments `pubkey`, `withdrawal_shard`, `withdrawal_address`, `randao_commitment` as defined in a `ValidatorRecord` below. A BLS `proof_of_possession` of types `bytes` is given as a final argument.
|
||||||
|
@ -152,8 +161,6 @@ An `AttestationSignedData` has the following fields:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
# Fork version
|
|
||||||
'fork_version': 'uint64',
|
|
||||||
# Slot number
|
# Slot number
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
# Shard number
|
# Shard number
|
||||||
|
@ -652,7 +659,7 @@ The `add_validator` routine is defined below.
|
||||||
|
|
||||||
This routine should be run for every validator that is inducted as part of a log created on the PoW chain [TODO: explain where to check for these logs]. The status of the validators added after genesis is `PENDING_ACTIVATION`. These logs should be processed in the order in which they are emitted by the PoW chain.
|
This routine should be run for every validator that is inducted as part of a log created on the PoW chain [TODO: explain where to check for these logs]. The status of the validators added after genesis is `PENDING_ACTIVATION`. These logs should be processed in the order in which they are emitted by the PoW chain.
|
||||||
|
|
||||||
First, a helper function:
|
First, some helper functions:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def min_empty_validator(validators: List[ValidatorRecord], current_slot: int):
|
def min_empty_validator(validators: List[ValidatorRecord], current_slot: int):
|
||||||
|
@ -662,10 +669,15 @@ def min_empty_validator(validators: List[ValidatorRecord], current_slot: int):
|
||||||
return None
|
return None
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_fork_version(state: State, slot: uint64):
|
||||||
|
return state.pre_fork_version if slot < state.fork_slot_number else state.post_fork_version
|
||||||
|
```
|
||||||
|
|
||||||
Now, to add a validator:
|
Now, to add a validator:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def add_validator(validators: List[ValidatorRecord],
|
def add_validator(state: State,
|
||||||
pubkey: int,
|
pubkey: int,
|
||||||
proof_of_possession: bytes,
|
proof_of_possession: bytes,
|
||||||
withdrawal_shard: int,
|
withdrawal_shard: int,
|
||||||
|
@ -678,7 +690,8 @@ def add_validator(validators: List[ValidatorRecord],
|
||||||
signed_message = as_bytes32(pubkey) + as_bytes2(withdrawal_shard) + withdrawal_address + randao_commitment
|
signed_message = as_bytes32(pubkey) + as_bytes2(withdrawal_shard) + withdrawal_address + randao_commitment
|
||||||
assert BLSVerify(pub=pubkey,
|
assert BLSVerify(pub=pubkey,
|
||||||
msg=hash(signed_message),
|
msg=hash(signed_message),
|
||||||
sig=proof_of_possession)
|
sig=proof_of_possession,
|
||||||
|
domain=get_fork_version(state, current_slot) * 2**32 + DOMAIN_DEPOSIT)
|
||||||
# Pubkey uniqueness
|
# Pubkey uniqueness
|
||||||
assert pubkey not in [v.pubkey for v in validators]
|
assert pubkey not in [v.pubkey for v in validators]
|
||||||
rec = ValidatorRecord(
|
rec = ValidatorRecord(
|
||||||
|
@ -815,9 +828,9 @@ For each one of these attestations:
|
||||||
* Compute `parent_hashes` = `[get_block_hash(state, block, slot - CYCLE_LENGTH + i) for i in range(1, CYCLE_LENGTH - len(oblique_parent_hashes) + 1)] + oblique_parent_hashes` (eg, if `CYCLE_LENGTH = 4`, `slot = 5`, the actual block hashes starting from slot 0 are `Z A B C D E F G H I J`, and `oblique_parent_hashes = [D', E']` then `parent_hashes = [B, C, D' E']`). Note that when *creating* an attestation for a block, the hash of that block itself won't yet be in the `state`, so you would need to add it explicitly.
|
* Compute `parent_hashes` = `[get_block_hash(state, block, slot - CYCLE_LENGTH + i) for i in range(1, CYCLE_LENGTH - len(oblique_parent_hashes) + 1)] + oblique_parent_hashes` (eg, if `CYCLE_LENGTH = 4`, `slot = 5`, the actual block hashes starting from slot 0 are `Z A B C D E F G H I J`, and `oblique_parent_hashes = [D', E']` then `parent_hashes = [B, C, D' E']`). Note that when *creating* an attestation for a block, the hash of that block itself won't yet be in the `state`, so you would need to add it explicitly.
|
||||||
* Let `attestation_indices` be `get_shards_and_committees_for_slot(state, slot)[x]`, choosing `x` so that `attestation_indices.shard` equals the `shard` value provided to find the set of validators that is creating this attestation record.
|
* Let `attestation_indices` be `get_shards_and_committees_for_slot(state, slot)[x]`, choosing `x` so that `attestation_indices.shard` equals the `shard` value provided to find the set of validators that is creating this attestation record.
|
||||||
* Verify that `len(attester_bitfield) == ceil_div8(len(attestation_indices))`, where `ceil_div8 = (x + 7) // 8`. Verify that bits `len(attestation_indices)....` and higher, if present (i.e. `len(attestation_indices)` is not a multiple of 8), are all zero.
|
* Verify that `len(attester_bitfield) == ceil_div8(len(attestation_indices))`, where `ceil_div8 = (x + 7) // 8`. Verify that bits `len(attestation_indices)....` and higher, if present (i.e. `len(attestation_indices)` is not a multiple of 8), are all zero.
|
||||||
* Derive a group public key by adding the public keys of all of the attesters in `attestation_indices` for whom the corresponding bit in `attester_bitfield` (the ith bit is `(attester_bitfield[i // 8] >> (7 - (i %8))) % 2`) equals 1.
|
* Derive a `group_public_key` by adding the public keys of all of the attesters in `attestation_indices` for whom the corresponding bit in `attester_bitfield` (the ith bit is `(attester_bitfield[i // 8] >> (7 - (i %8))) % 2`) equals 1.
|
||||||
* Let `fork_version = pre_fork_version if slot < fork_slot_number else post_fork_version`.
|
* Let `data = AttestationSignedData(slot, shard, parent_hashes, shard_block_hash, last_crosslinked_hash, shard_block_combined_data_root, justified_slot)`
|
||||||
* Verify that `aggregate_sig` verifies using the group pubkey generated and the serialized form of `AttestationSignedData(fork_version, slot, shard, parent_hashes, shard_block_hash, last_crosslinked_hash, shard_block_combined_data_root, justified_slot)` as the message.
|
* Check `BLSVerify(pubkey=group_public_key, msg=data, sig=aggregate_sig, domain=get_fork_version(state, slot) * 2**32 + DOMAIN_ATTESTATION)`
|
||||||
|
|
||||||
Extend the list of `AttestationRecord` objects in the `state` with those included in the block, ordering the new additions in the same order as they came in the block.
|
Extend the list of `AttestationRecord` objects in the `state` with those included in the block, ordering the new additions in the same order as they came in the block.
|
||||||
|
|
||||||
|
@ -843,12 +856,12 @@ For each `SpecialRecord` `obj` in `block.specials`, verify that its `kind` is on
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
'validator_index': 'uint64',
|
'validator_index': 'uint64',
|
||||||
'signature': '[uint256]'
|
'signature': '[uint384]'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Perform the following checks:
|
Perform the following checks:
|
||||||
|
|
||||||
* Let `fork_version = pre_fork_version if block.slot < fork_slot_number else post_fork_version`. Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg=hash(LOGOUT_MESSAGE + bytes8(fork_version)), sig=data.signature)`
|
* Verify that `BLSVerify(pubkey=validators[data.validator_index].pubkey, msg=hash(LOGOUT_MESSAGE + bytes8(fork_version)), sig=data.signature, domain=get_fork_version(state, current_slot) * 2**32 + DOMAIN_LOGOUT)`
|
||||||
* Verify that `validators[validator_index].status == ACTIVE`.
|
* Verify that `validators[validator_index].status == ACTIVE`.
|
||||||
|
|
||||||
Run `exit_validator(data.validator_index, state, penalize=False, current_slot=block.slot)`.
|
Run `exit_validator(data.validator_index, state, penalize=False, current_slot=block.slot)`.
|
||||||
|
@ -859,16 +872,16 @@ Run `exit_validator(data.validator_index, state, penalize=False, current_slot=bl
|
||||||
{
|
{
|
||||||
'vote1_aggregate_sig_indices': '[uint24]',
|
'vote1_aggregate_sig_indices': '[uint24]',
|
||||||
'vote1_data': AttestationSignedData,
|
'vote1_data': AttestationSignedData,
|
||||||
'vote1_aggregate_sig': '[uint256]',
|
'vote1_aggregate_sig': '[uint384]',
|
||||||
'vote2_aggregate_sig_indices': '[uint24]',
|
'vote2_aggregate_sig_indices': '[uint24]',
|
||||||
'vote2_data': AttestationSignedData,
|
'vote2_data': AttestationSignedData,
|
||||||
'vote2_aggregate_sig': '[uint256]',
|
'vote2_aggregate_sig': '[uint384]',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Perform the following checks:
|
Perform the following checks:
|
||||||
|
|
||||||
* For each `aggregate_sig`, verify that `BLSVerify(pubkey=aggregate_pubkey([validators[i].pubkey for i in aggregate_sig_indices]), msg=vote_data, sig=aggsig)` passes.
|
* For each `aggregate_sig`, verify that `BLSVerify(pubkey=aggregate_pubkey([validators[i].pubkey for i in aggregate_sig_indices]), msg=vote_data, sig=aggsig, domain=get_fork_version(state, vote_data.slot) * 2**32 + DOMAIN_ATTESTATION)` passes.
|
||||||
* Verify that `vote1_data != vote2_data`.
|
* Verify that `vote1_data != vote2_data`.
|
||||||
* Let `intersection = [x for x in vote1_aggregate_sig_indices if x in vote2_aggregate_sig_indices]`. Verify that `len(intersection) >= 1`.
|
* Let `intersection = [x for x in vote1_aggregate_sig_indices if x in vote2_aggregate_sig_indices]`. Verify that `len(intersection) >= 1`.
|
||||||
* Verify that `vote1_data.justified_slot < vote2_data.justified_slot < vote2_data.slot <= vote1_data.slot`.
|
* Verify that `vote1_data.justified_slot < vote2_data.justified_slot < vote2_data.slot <= vote1_data.slot`.
|
||||||
|
|
Loading…
Reference in New Issue