From c661ddf12c15bab9bbb59fe034687aebc07db5b8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 17 Mar 2021 09:35:39 -0600 Subject: [PATCH 1/9] hoist container definitions to preamble --- specs/phase0/validator.md | 65 ++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index 281078d209..1767d3d446 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -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) @@ -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) @@ -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) @@ -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 @@ -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: @@ -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: From 208a6583051bdcc05ae57b3d1d3afc50f8371c35 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 18 Mar 2021 15:41:12 -0600 Subject: [PATCH 2/9] Use different name for constant for sync committee aggregates --- configs/mainnet/altair.yaml | 2 +- configs/minimal/altair.yaml | 2 +- specs/altair/beacon-chain.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/mainnet/altair.yaml b/configs/mainnet/altair.yaml index f30e9fcdc5..32bcd1b84c 100644 --- a/configs/mainnet/altair.yaml +++ b/configs/mainnet/altair.yaml @@ -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_PUBKEY_AGGREGATE_SIZE: 64 # 2**2 (= 4) INACTIVITY_SCORE_BIAS: 4 diff --git a/configs/minimal/altair.yaml b/configs/minimal/altair.yaml index afdaf9eb5b..50033344f6 100644 --- a/configs/minimal/altair.yaml +++ b/configs/minimal/altair.yaml @@ -17,7 +17,7 @@ PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2 # [customized] SYNC_COMMITTEE_SIZE: 32 # [customized] -SYNC_SUBCOMMITTEE_SIZE: 16 +SYNC_PUBKEY_AGGREGATE_SIZE: 16 # 2**2 (= 4) INACTIVITY_SCORE_BIAS: 4 diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 58e82364ce..f62f7c1d2f 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -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_PUBKEY_AGGREGATE_SIZE` | `uint64(2**6)` (= 64) | | `INACTIVITY_SCORE_BIAS` | `uint64(4)` | ### Time parameters @@ -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_PUBKEY_AGGREGATE_SIZE] ``` ## Helper functions @@ -294,7 +294,7 @@ 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)] + subcommitees = [pubkeys[i:i + SYNC_PUBKEY_AGGREGATE_SIZE] for i in range(0, len(pubkeys), SYNC_PUBKEY_AGGREGATE_SIZE)] pubkey_aggregates = [bls.AggregatePKs(subcommitee) for subcommitee in subcommitees] return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=pubkey_aggregates) ``` From 053661ad2070ba1a7b02db805e9deaaa2a3e3d33 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 19 Mar 2021 10:04:46 +0000 Subject: [PATCH 3/9] Update beacon-chain.md --- specs/altair/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index f62f7c1d2f..f4fc8f067b 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -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_PUBKEY_AGGREGATE_SIZE] for i in range(0, len(pubkeys), SYNC_PUBKEY_AGGREGATE_SIZE)] - pubkey_aggregates = [bls.AggregatePKs(subcommitee) for subcommitee in subcommitees] + partition = [pubkeys[i:i + SYNC_PUBKEY_AGGREGATE_SIZE] for i in range(0, len(pubkeys), SYNC_PUBKEY_AGGREGATE_SIZE)] + pubkey_aggregates = [bls.AggregatePKs(preaggregate) for preaggregate in partition] return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=pubkey_aggregates) ``` From 484fae3c2b285f5f2043a13d2dfa2e238c223ea9 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 19 Mar 2021 07:59:49 -0600 Subject: [PATCH 4/9] update constant name --- configs/mainnet/altair.yaml | 2 +- configs/minimal/altair.yaml | 2 +- specs/altair/beacon-chain.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/mainnet/altair.yaml b/configs/mainnet/altair.yaml index 32bcd1b84c..1bebafe907 100644 --- a/configs/mainnet/altair.yaml +++ b/configs/mainnet/altair.yaml @@ -17,7 +17,7 @@ PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2 # 2**10 (= 1,024) SYNC_COMMITTEE_SIZE: 1024 # 2**6 (= 64) -SYNC_PUBKEY_AGGREGATE_SIZE: 64 +SYNC_PUBKEYS_PER_AGGREGATE: 64 # 2**2 (= 4) INACTIVITY_SCORE_BIAS: 4 diff --git a/configs/minimal/altair.yaml b/configs/minimal/altair.yaml index 50033344f6..003db9b4e3 100644 --- a/configs/minimal/altair.yaml +++ b/configs/minimal/altair.yaml @@ -17,7 +17,7 @@ PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2 # [customized] SYNC_COMMITTEE_SIZE: 32 # [customized] -SYNC_PUBKEY_AGGREGATE_SIZE: 16 +SYNC_PUBKEYS_PER_AGGREGATE: 16 # 2**2 (= 4) INACTIVITY_SCORE_BIAS: 4 diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index f4fc8f067b..1d56470115 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -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_PUBKEY_AGGREGATE_SIZE` | `uint64(2**6)` (= 64) | +| `SYNC_PUBKEYS_PER_AGGREGATE` | `uint64(2**6)` (= 64) | | `INACTIVITY_SCORE_BIAS` | `uint64(4)` | ### Time parameters @@ -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_PUBKEY_AGGREGATE_SIZE] + pubkey_aggregates: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE // SYNC_PUBKEYS_PER_AGGREGATE] ``` ## Helper functions @@ -294,7 +294,7 @@ 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] - partition = [pubkeys[i:i + SYNC_PUBKEY_AGGREGATE_SIZE] for i in range(0, len(pubkeys), SYNC_PUBKEY_AGGREGATE_SIZE)] + 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) ``` From 2ce389216dc7fd2dd17a5da620e3a01dd1780470 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 19 Mar 2021 23:38:59 +0800 Subject: [PATCH 5/9] Executable Altair validator guide --- setup.py | 1 + specs/altair/validator.md | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index ef6c65289d..9de8ef9111 100644 --- a/setup.py +++ b/setup.py @@ -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: diff --git a/specs/altair/validator.md b/specs/altair/validator.md index 59c1ab81f2..25897b97e0 100644 --- a/specs/altair/validator.md +++ b/specs/altair/validator.md @@ -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) @@ -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. @@ -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: @@ -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 ] ``` @@ -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, From 493dd17cc407765110f9e6fe4fef66b4c07965b3 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 21 Mar 2021 04:22:37 +0100 Subject: [PATCH 6/9] reduce justification and finalization Altair diff --- specs/altair/beacon-chain.md | 42 ++++++------------------------------ specs/phase0/beacon-chain.md | 17 +++++++++++---- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 58e82364ce..3f702dca4b 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -575,7 +575,7 @@ 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: @@ -583,40 +583,12 @@ 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_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 = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)) + current = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_current_epoch(state)) + weigh_justification_and_finalization( + state, get_total_active_balance(state), + get_total_balance(state, previous), + get_total_balance(state, current)) ``` #### Inactivity scores diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index 9fcd118523..d978c4a754 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -1320,7 +1320,18 @@ 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 = get_matching_target_attestations(state, get_previous_epoch(state)) + current = get_matching_target_attestations(state, get_current_epoch(state)) + weigh_justification_and_finalization( + state, get_total_active_balance(state), + get_attesting_balance(state, previous), + get_attesting_balance(state, current)) +``` +```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 @@ -1330,13 +1341,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 From 4a82a375ae8ab9d0f43113a1973c72eeacb04636 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 21 Mar 2021 22:07:28 +0100 Subject: [PATCH 7/9] avoid altair fork version collision, update test prep, fix genesis state creator bug --- configs/minimal/altair.yaml | 3 ++- tests/core/pyspec/eth2spec/test/context.py | 3 +-- tests/core/pyspec/eth2spec/test/helpers/genesis.py | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/configs/minimal/altair.yaml b/configs/minimal/altair.yaml index afdaf9eb5b..48766b12dc 100644 --- a/configs/minimal/altair.yaml +++ b/configs/minimal/altair.yaml @@ -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 diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index ddb01adcb6..caf44e983d 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -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) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 46bc62fe53..14fd9aa474 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -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, ) From 4dd855667ae32cbd1370e0062fd3dabef0b3172f Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 22 Mar 2021 02:50:05 +0100 Subject: [PATCH 8/9] fix mixed up formats. Output slots as ints, output genesis eth1 init data as yaml dict --- .../phase0/genesis/test_initialization.py | 22 ++++++++++--------- .../eth2spec/test/phase0/sanity/test_slots.py | 10 ++++----- tests/formats/genesis/initialization.md | 10 ++++----- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py index 1ec40c56fc..41fbd77262 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py @@ -16,6 +16,13 @@ def get_post_altair_description(spec): return f"Although it's not phase 0, we may use {spec.fork} spec to start testnets." +def eth1_init_data(eth1_block_hash, eth1_timestamp): + yield 'eth1', { + 'eth1_block_hash': '0x' + eth1_block_hash.hex(), + 'eth1_timestamp': int(eth1_timestamp), + } + + @with_all_phases @spec_test @single_phase @@ -35,8 +42,7 @@ def test_initialize_beacon_state_from_eth1(spec): eth1_block_hash = b'\x12' * 32 eth1_timestamp = spec.MIN_GENESIS_TIME - yield 'eth1_block_hash', eth1_block_hash - yield 'eth1_timestamp', eth1_timestamp + yield from eth1_init_data(eth1_block_hash, eth1_timestamp) yield 'deposits', deposits # initialize beacon_state @@ -79,8 +85,7 @@ def test_initialize_beacon_state_some_small_balances(spec): eth1_block_hash = b'\x12' * 32 eth1_timestamp = spec.MIN_GENESIS_TIME - yield 'eth1_block_hash', eth1_block_hash - yield 'eth1_timestamp', eth1_timestamp + yield from eth1_init_data(eth1_block_hash, eth1_timestamp) yield 'deposits', deposits # initialize beacon_state @@ -136,8 +141,7 @@ def test_initialize_beacon_state_one_topup_activation(spec): eth1_block_hash = b'\x13' * 32 eth1_timestamp = spec.MIN_GENESIS_TIME - yield 'eth1_block_hash', eth1_block_hash - yield 'eth1_timestamp', eth1_timestamp + yield from eth1_init_data(eth1_block_hash, eth1_timestamp) yield 'deposits', deposits # initialize beacon_state @@ -165,8 +169,7 @@ def test_initialize_beacon_state_random_invalid_genesis(spec): eth1_block_hash = b'\x14' * 32 eth1_timestamp = spec.MIN_GENESIS_TIME + 1 - yield 'eth1_block_hash', eth1_block_hash - yield 'eth1_timestamp', eth1_timestamp + yield from eth1_init_data(eth1_block_hash, eth1_timestamp) yield 'deposits', deposits # initialize beacon_state @@ -205,8 +208,7 @@ def test_initialize_beacon_state_random_valid_genesis(spec): eth1_block_hash = b'\x15' * 32 eth1_timestamp = spec.MIN_GENESIS_TIME + 2 - yield 'eth1_block_hash', eth1_block_hash - yield 'eth1_timestamp', eth1_timestamp + yield from eth1_init_data(eth1_block_hash, eth1_timestamp) yield 'deposits', deposits # initialize beacon_state diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py index dd4f302ae1..198ada6b90 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py @@ -10,7 +10,7 @@ def test_slots_1(spec, state): yield 'pre', state slots = 1 - yield 'slots', slots + yield 'slots', int(slots) spec.process_slots(state, state.slot + slots) yield 'post', state @@ -23,7 +23,7 @@ def test_slots_1(spec, state): def test_slots_2(spec, state): yield 'pre', state slots = 2 - yield 'slots', slots + yield 'slots', int(slots) spec.process_slots(state, state.slot + slots) yield 'post', state @@ -33,7 +33,7 @@ def test_slots_2(spec, state): def test_empty_epoch(spec, state): yield 'pre', state slots = spec.SLOTS_PER_EPOCH - yield 'slots', slots + yield 'slots', int(slots) spec.process_slots(state, state.slot + slots) yield 'post', state @@ -43,7 +43,7 @@ def test_empty_epoch(spec, state): def test_double_empty_epoch(spec, state): yield 'pre', state slots = spec.SLOTS_PER_EPOCH * 2 - yield 'slots', slots + yield 'slots', int(slots) spec.process_slots(state, state.slot + slots) yield 'post', state @@ -55,6 +55,6 @@ def test_over_epoch_boundary(spec, state): spec.process_slots(state, state.slot + (spec.SLOTS_PER_EPOCH // 2)) yield 'pre', state slots = spec.SLOTS_PER_EPOCH - yield 'slots', slots + yield 'slots', int(slots) spec.process_slots(state, state.slot + slots) yield 'post', state diff --git a/tests/formats/genesis/initialization.md b/tests/formats/genesis/initialization.md index 7a791dcfa3..73630de51c 100644 --- a/tests/formats/genesis/initialization.md +++ b/tests/formats/genesis/initialization.md @@ -4,13 +4,13 @@ Tests the initialization of a genesis state based on Eth1 data. ## Test case format -### `eth1_block_hash.ssz_snappy` +### `eth1.yaml` -An SSZ-snappy encoded root of the Eth1 block. - -### `eth1_timestamp.yaml` +```yaml +eth1_block_hash: Bytes32 -- A `Bytes32` hex encoded, with prefix 0x. The root of the Eth1 block. E.g. "0x4242424242424242424242424242424242424242424242424242424242424242" +eth1_timestamp: int -- An integer. The timestamp of the block, in seconds. +``` -An integer. The timestamp of the block, in seconds. ### `meta.yaml` From bb85ef5a579c2c2d1cb015e8de6900979e8a35af Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 22 Mar 2021 10:50:18 -0600 Subject: [PATCH 9/9] pr cleanup --- specs/altair/beacon-chain.md | 12 ++++++------ specs/phase0/beacon-chain.md | 15 ++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 3f702dca4b..8be2f04ec0 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -583,12 +583,12 @@ 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 = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)) - current = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_current_epoch(state)) - weigh_justification_and_finalization( - state, get_total_active_balance(state), - get_total_balance(state, previous), - get_total_balance(state, current)) + 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 diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index d978c4a754..e56a8ea223 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -1320,16 +1320,17 @@ 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 = get_matching_target_attestations(state, get_previous_epoch(state)) - current = get_matching_target_attestations(state, get_current_epoch(state)) - weigh_justification_and_finalization( - state, get_total_active_balance(state), - get_attesting_balance(state, previous), - get_attesting_balance(state, current)) + 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, +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)