Skip to content

Commit

Permalink
Merge pull request #2262 from ethereum/dev
Browse files Browse the repository at this point in the history
Altair alpha.2 release
  • Loading branch information
djrtwo authored Mar 22, 2021
2 parents 409cf0f + d49cddc commit 3d0c549
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 108 deletions.
2 changes: 1 addition & 1 deletion configs/mainnet/altair.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
# 2**10 (= 1,024)
SYNC_COMMITTEE_SIZE: 1024
# 2**6 (= 64)
SYNC_SUBCOMMITTEE_SIZE: 64
SYNC_PUBKEYS_PER_AGGREGATE: 64
# 2**2 (= 4)
INACTIVITY_SCORE_BIAS: 4

Expand Down
5 changes: 3 additions & 2 deletions configs/minimal/altair.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
# [customized]
SYNC_COMMITTEE_SIZE: 32
# [customized]
SYNC_SUBCOMMITTEE_SIZE: 16
SYNC_PUBKEYS_PER_AGGREGATE: 16
# 2**2 (= 4)
INACTIVITY_SCORE_BIAS: 4

Expand All @@ -35,7 +35,8 @@ DOMAIN_SYNC_COMMITTEE: 0x07000000

# Fork
# ---------------------------------------------------------------
ALTAIR_FORK_VERSION: 0x01000000
# Highest byte set to 0x01 to avoid collisions with mainnet versioning
ALTAIR_FORK_VERSION: 0x01000001
# [customized]
ALTAIR_FORK_SLOT: 0

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ def finalize_options(self):
specs/phase0/weak-subjectivity.md
specs/altair/beacon-chain.md
specs/altair/fork.md
specs/altair/validator.md
specs/altair/sync-protocol.md
"""
else:
Expand Down
50 changes: 11 additions & 39 deletions specs/altair/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ This patch updates a few configuration values to move penalty parameters toward
| Name | Value |
| - | - |
| `SYNC_COMMITTEE_SIZE` | `uint64(2**10)` (= 1,024) |
| `SYNC_SUBCOMMITTEE_SIZE` | `uint64(2**6)` (= 64) |
| `SYNC_PUBKEYS_PER_AGGREGATE` | `uint64(2**6)` (= 64) |
| `INACTIVITY_SCORE_BIAS` | `uint64(4)` |

### Time parameters
Expand Down Expand Up @@ -210,7 +210,7 @@ class SyncAggregate(Container):
```python
class SyncCommittee(Container):
pubkeys: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE]
pubkey_aggregates: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE // SYNC_SUBCOMMITTEE_SIZE]
pubkey_aggregates: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE // SYNC_PUBKEYS_PER_AGGREGATE]
```

## Helper functions
Expand Down Expand Up @@ -294,8 +294,8 @@ def get_sync_committee(state: BeaconState, epoch: Epoch) -> SyncCommittee:
"""
indices = get_sync_committee_indices(state, epoch)
pubkeys = [state.validators[index].pubkey for index in indices]
subcommitees = [pubkeys[i:i + SYNC_SUBCOMMITTEE_SIZE] for i in range(0, len(pubkeys), SYNC_SUBCOMMITTEE_SIZE)]
pubkey_aggregates = [bls.AggregatePKs(subcommitee) for subcommitee in subcommitees]
partition = [pubkeys[i:i + SYNC_PUBKEYS_PER_AGGREGATE] for i in range(0, len(pubkeys), SYNC_PUBKEYS_PER_AGGREGATE)]
pubkey_aggregates = [bls.AggregatePKs(preaggregate) for preaggregate in partition]
return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=pubkey_aggregates)
```

Expand Down Expand Up @@ -575,48 +575,20 @@ def process_epoch(state: BeaconState) -> None:

#### Justification and finalization

*Note*: The function `process_justification_and_finalization` is modified with `matching_target_attestations` replaced by `matching_target_indices`.
*Note*: The function `process_justification_and_finalization` is modified to adapt to the new participation records.

```python
def process_justification_and_finalization(state: BeaconState) -> None:
# Initial FFG checkpoint values have a `0x00` stub for `root`.
# Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return
previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state)
old_previous_justified_checkpoint = state.previous_justified_checkpoint
old_current_justified_checkpoint = state.current_justified_checkpoint

# Process justifications
state.previous_justified_checkpoint = state.current_justified_checkpoint
state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
state.justification_bits[0] = 0b0
matching_target_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, previous_epoch)
if get_total_balance(state, matching_target_indices) * 3 >= get_total_active_balance(state) * 2:
state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
root=get_block_root(state, previous_epoch))
state.justification_bits[1] = 0b1
matching_target_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, current_epoch)
if get_total_balance(state, matching_target_indices) * 3 >= get_total_active_balance(state) * 2:
state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
root=get_block_root(state, current_epoch))
state.justification_bits[0] = 0b1

# Process finalizations
bits = state.justification_bits
# The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
state.finalized_checkpoint = old_previous_justified_checkpoint
# The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_checkpoint = old_previous_justified_checkpoint
# The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_checkpoint = old_current_justified_checkpoint
# The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
state.finalized_checkpoint = old_current_justified_checkpoint
previous_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state))
current_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_current_epoch(state))
total_active_balance = get_total_active_balance(state)
previous_target_balance = get_total_balance(state, previous_indices)
current_target_balance = get_total_balance(state, current_indices)
weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
```

#### Inactivity scores
Expand Down
25 changes: 16 additions & 9 deletions specs/altair/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This is an accompanying document to [Ethereum 2.0 Altair -- The Beacon Chain](./
- [`SyncCommitteeContribution`](#synccommitteecontribution)
- [`ContributionAndProof`](#contributionandproof)
- [`SignedContributionAndProof`](#signedcontributionandproof)
- [`SyncCommitteeSigningData`](#synccommitteesigningdata)
- [Validator assignments](#validator-assignments)
- [Sync Committee](#sync-committee)
- [Lookahead](#lookahead)
Expand Down Expand Up @@ -125,6 +126,14 @@ class SignedContributionAndProof(Container):
signature: BLSSignature
```

### `SyncCommitteeSigningData`

```python
class SyncCommitteeSigningData(Container):
slot: Slot
subcommittee_index: uint64
```

## Validator assignments

A validator determines beacon committee assignments and beacon block proposal duties as defined in the Phase 0 document.
Expand All @@ -137,7 +146,9 @@ This function is a predicate indicating the presence or absence of the validator
```python
def compute_sync_committee_period(epoch: Epoch) -> uint64:
return epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD
```

```python
def is_assigned_to_sync_committee(state: BeaconState,
epoch: Epoch,
validator_index: ValidatorIndex) -> bool:
Expand Down Expand Up @@ -280,9 +291,10 @@ This function returns multiple subnets if a given validator index is included mu
```python
def compute_subnets_for_sync_committee(state: BeaconState, validator_index: ValidatorIndex) -> Sequence[uint64]:
target_pubkey = state.validators[validator_index].pubkey
sync_committee_indices = [index for index, pubkey in enumerate(state.current_sync_committee.pubkeys) if pubkey == target_pubkey]
sync_committee_indices = [index for index, pubkey in enumerate(state.current_sync_committee.pubkeys)
if pubkey == target_pubkey]
return [
uint64(index // (SYNC_COMMITEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT))
uint64(index // (SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT))
for index in sync_committee_indices
]
```
Expand All @@ -301,13 +313,8 @@ A validator is selected to aggregate based on the computation in `is_sync_commit
The signature function takes a `BeaconState` with the relevant sync committees for the queried `slot` (i.e. `state.slot` is within the span covered by the current or next sync committee period), the `subcommittee_index` equal to the `subnet_id`, and the `privkey` is the BLS private key associated with the validator.

```python
class SyncCommitteeSigningData(Container):
slot: Slot
subcommittee_index: uint64
```

```python
def get_sync_committee_slot_signature(state: BeaconState, slot: Slot, subcommittee_index: uint64, privkey: int) -> BLSSignature:
def get_sync_committee_slot_signature(state: BeaconState, slot: Slot,
subcommittee_index: uint64, privkey: int) -> BLSSignature:
domain = get_domain(state, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, compute_epoch_at_slot(slot))
signing_data = SyncCommitteeSigningData(
slot=slot,
Expand Down
18 changes: 14 additions & 4 deletions specs/phase0/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -1320,7 +1320,19 @@ def process_justification_and_finalization(state: BeaconState) -> None:
# Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return
previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
current_attestations = get_matching_target_attestations(state, get_current_epoch(state))
total_active_balance = get_total_active_balance(state)
previous_target_balance = get_attesting_balance(state, previous_attestations)
current_target_balance = get_attesting_balance(state, current_attestations)
weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
```

```python
def weigh_justification_and_finalization(state: BeaconState,
total_active_balance: Gwei,
previous_epoch_target_balance: Gwei,
current_epoch_target_balance: Gwei) -> None:
previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state)
old_previous_justified_checkpoint = state.previous_justified_checkpoint
Expand All @@ -1330,13 +1342,11 @@ def process_justification_and_finalization(state: BeaconState) -> None:
state.previous_justified_checkpoint = state.current_justified_checkpoint
state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
state.justification_bits[0] = 0b0
matching_target_attestations = get_matching_target_attestations(state, previous_epoch) # Previous epoch
if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2:
if previous_epoch_target_balance * 3 >= total_active_balance * 2:
state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
root=get_block_root(state, previous_epoch))
state.justification_bits[1] = 0b1
matching_target_attestations = get_matching_target_attestations(state, current_epoch) # Current epoch
if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2:
if current_epoch_target_balance * 3 >= total_active_balance * 2:
state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
root=get_block_root(state, current_epoch))
state.justification_bits[0] = 0b1
Expand Down
65 changes: 34 additions & 31 deletions specs/phase0/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ This is an accompanying document to [Ethereum 2.0 Phase 0 -- The Beacon Chain](.
- [Prerequisites](#prerequisites)
- [Constants](#constants)
- [Misc](#misc)
- [Containers](#containers)
- [`Eth1Block`](#eth1block)
- [`AggregateAndProof`](#aggregateandproof)
- [`SignedAggregateAndProof`](#signedaggregateandproof)
- [Becoming a validator](#becoming-a-validator)
- [Initialization](#initialization)
- [BLS public key](#bls-public-key)
Expand All @@ -33,7 +37,6 @@ This is an accompanying document to [Ethereum 2.0 Phase 0 -- The Beacon Chain](.
- [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody)
- [Randao reveal](#randao-reveal)
- [Eth1 Data](#eth1-data)
- [`Eth1Block`](#eth1block)
- [`get_eth1_data`](#get_eth1_data)
- [Proposer slashings](#proposer-slashings)
- [Attester slashings](#attester-slashings)
Expand All @@ -60,8 +63,6 @@ This is an accompanying document to [Ethereum 2.0 Phase 0 -- The Beacon Chain](.
- [Aggregation bits](#aggregation-bits-1)
- [Aggregate signature](#aggregate-signature-1)
- [Broadcast aggregate](#broadcast-aggregate)
- [`AggregateAndProof`](#aggregateandproof)
- [`SignedAggregateAndProof`](#signedaggregateandproof)
- [Phase 0 attestation subnet stability](#phase-0-attestation-subnet-stability)
- [How to avoid slashing](#how-to-avoid-slashing)
- [Proposer slashing](#proposer-slashing)
Expand Down Expand Up @@ -92,6 +93,35 @@ All terminology, constants, functions, and protocol mechanics defined in the [Ph
| `EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION` | `2**8` (= 256) | epochs | ~27 hours |
| `ATTESTATION_SUBNET_COUNT` | `64` | The number of attestation subnets used in the gossipsub protocol. |

## Containers

### `Eth1Block`

```python
class Eth1Block(Container):
timestamp: uint64
deposit_root: Root
deposit_count: uint64
# All other eth1 block fields
```

### `AggregateAndProof`

```python
class AggregateAndProof(Container):
aggregator_index: ValidatorIndex
aggregate: Attestation
selection_proof: BLSSignature
```

### `SignedAggregateAndProof`

```python
class SignedAggregateAndProof(Container):
message: AggregateAndProof
signature: BLSSignature
```

## Becoming a validator

### Initialization
Expand Down Expand Up @@ -302,20 +332,10 @@ If over half of the block proposers in the current Eth1 voting period vote for t
`eth1_data` then `state.eth1_data` updates immediately allowing new deposits to be processed.
Each deposit in `block.body.deposits` must verify against `state.eth1_data.eth1_deposit_root`.

###### `Eth1Block`
###### `get_eth1_data`

Let `Eth1Block` be an abstract object representing Eth1 blocks with the `timestamp` and depost contract data available.

```python
class Eth1Block(Container):
timestamp: uint64
deposit_root: Root
deposit_count: uint64
# All other eth1 block fields
```

###### `get_eth1_data`

Let `get_eth1_data(block: Eth1Block) -> Eth1Data` be the function that returns the Eth1 data for a given Eth1 block.

An honest block proposer sets `block.body.eth1_data = get_eth1_vote(state, eth1_chain)` where:
Expand Down Expand Up @@ -581,23 +601,6 @@ def get_aggregate_and_proof_signature(state: BeaconState,
return bls.Sign(privkey, signing_root)
```

##### `AggregateAndProof`

```python
class AggregateAndProof(Container):
aggregator_index: ValidatorIndex
aggregate: Attestation
selection_proof: BLSSignature
```

##### `SignedAggregateAndProof`

```python
class SignedAggregateAndProof(Container):
message: AggregateAndProof
signature: BLSSignature
```

## Phase 0 attestation subnet stability

Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each validator must:
Expand Down
3 changes: 1 addition & 2 deletions tests/core/pyspec/eth2spec/test/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ def deco(fn):

def entry(*args, spec: Spec, phases: SpecForks, **kw):
# make a key for the state
# genesis fork version separates configs during test-generation runtime.
key = (spec.fork, spec.GENESIS_FORK_VERSION, spec.__file__, balances_fn, threshold_fn)
key = (spec.fork, spec.CONFIG_NAME, spec.__file__, balances_fn, threshold_fn)
global _custom_state_cache_dict
if key not in _custom_state_cache_dict:
state = _prepare_state(balances_fn, threshold_fn, spec, phases)
Expand Down
5 changes: 5 additions & 0 deletions tests/core/pyspec/eth2spec/test/helpers/genesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
deposit_count=len(validator_balances),
block_hash=eth1_block_hash,
),
fork=spec.Fork(
previous_version=spec.GENESIS_FORK_VERSION,
current_version=spec.GENESIS_FORK_VERSION,
epoch=spec.GENESIS_EPOCH,
),
latest_block_header=spec.BeaconBlockHeader(body_root=spec.hash_tree_root(spec.BeaconBlockBody())),
randao_mixes=[eth1_block_hash] * spec.EPOCHS_PER_HISTORICAL_VECTOR,
)
Expand Down
Loading

0 comments on commit 3d0c549

Please sign in to comment.