diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 3d54befbf..28809f94a 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -50,17 +50,20 @@ CAPELLA_FORK_EPOCH: 194048 # April 12, 2023, 10:27:35pm UTC # Deneb DENEB_FORK_VERSION: 0x04000000 DENEB_FORK_EPOCH: 269568 # March 13, 2024, 01:55:35pm UTC +# Electra +ELECTRA_FORK_VERSION: 0x05000000 +ELECTRA_FORK_EPOCH: 18446744073709551615 # EIP6110 -EIP6110_FORK_VERSION: 0x05000000 # temporary stub +EIP6110_FORK_VERSION: 0x06000000 # temporary stub EIP6110_FORK_EPOCH: 18446744073709551615 # EIP7002 -EIP7002_FORK_VERSION: 0x05000000 # temporary stub +EIP7002_FORK_VERSION: 0x07000000 # temporary stub EIP7002_FORK_EPOCH: 18446744073709551615 # EIP7251 EIP7251_FORK_VERSION: 0x06000000 # temporary stub EIP7251_FORK_EPOCH: 18446744073709551615 # WHISK -WHISK_FORK_VERSION: 0x06000000 # temporary stub +WHISK_FORK_VERSION: 0x08000000 # temporary stub WHISK_FORK_EPOCH: 18446744073709551615 diff --git a/configs/minimal.yaml b/configs/minimal.yaml index f565dee9f..96a0f662d 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -46,20 +46,23 @@ BELLATRIX_FORK_EPOCH: 18446744073709551615 # Capella CAPELLA_FORK_VERSION: 0x03000001 CAPELLA_FORK_EPOCH: 18446744073709551615 -# DENEB +# Deneb DENEB_FORK_VERSION: 0x04000001 DENEB_FORK_EPOCH: 18446744073709551615 +# Electra +ELECTRA_FORK_VERSION: 0x05000001 +ELECTRA_FORK_EPOCH: 18446744073709551615 # EIP6110 -EIP6110_FORK_VERSION: 0x05000001 +EIP6110_FORK_VERSION: 0x06000001 EIP6110_FORK_EPOCH: 18446744073709551615 # EIP7002 -EIP7002_FORK_VERSION: 0x05000001 +EIP7002_FORK_VERSION: 0x07000001 EIP7002_FORK_EPOCH: 18446744073709551615 # EIP7251 EIP7251_FORK_VERSION: 0x06000000 # temporary stub EIP7251_FORK_EPOCH: 18446744073709551615 # WHISK -WHISK_FORK_VERSION: 0x06000001 +WHISK_FORK_VERSION: 0x08000001 WHISK_FORK_EPOCH: 18446744073709551615 diff --git a/specs/_features/eip6110/fork.md b/specs/_features/eip6110/fork.md index 6b5ab0431..8bb8e2a67 100644 --- a/specs/_features/eip6110/fork.md +++ b/specs/_features/eip6110/fork.md @@ -28,7 +28,7 @@ Warning: this configuration is not definitive. | Name | Value | | - | - | -| `EIP6110_FORK_VERSION` | `Version('0x05000000')` | +| `EIP6110_FORK_VERSION` | `Version('0x06000000')` | | `EIP6110_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | ## Helper functions diff --git a/specs/_features/eip7002/fork.md b/specs/_features/eip7002/fork.md index 87008de77..8f095389d 100644 --- a/specs/_features/eip7002/fork.md +++ b/specs/_features/eip7002/fork.md @@ -28,7 +28,7 @@ Warning: this configuration is not definitive. | Name | Value | | - | - | -| `EIP7002_FORK_VERSION` | `Version('0x05000000')` | +| `EIP7002_FORK_VERSION` | `Version('0x07000000')` | | `EIP7002_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | ## Helper functions diff --git a/specs/_features/eip7549/beacon-chain.md b/specs/_features/eip7549/beacon-chain.md index 2382551e2..cac3a5723 100644 --- a/specs/_features/eip7549/beacon-chain.md +++ b/specs/_features/eip7549/beacon-chain.md @@ -44,7 +44,7 @@ This is the beacon chain specification to move the attestation committee index o ```python class Attestation(Container): - aggregation_bits: List[Bitlist[MAX_VALIDATORS_PER_COMMITTEE], MAX_COMMITTEES_PER_SLOT] # [Modified in EIP7549] + aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [Modified in EIP7549] data: AttestationData committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] # [New in EIP7549] signature: BLSSignature @@ -83,12 +83,15 @@ def get_attesting_indices(state: BeaconState, attestation: Attestation) -> Set[V output = set() committee_indices = get_committee_indices(attestation.committee_bits) + committee_offset = 0 for index in committee_indices: - attesting_bits = attestation.aggregation_bits[index] committee = get_beacon_committee(state, attestation.data.slot, index) - committee_attesters = set(index for i, index in enumerate(committee) if attesting_bits[i]) + committee_attesters = set( + index for i, index in enumerate(committee) if attestation.aggregation_bits[committee_offset + i]) output = output.union(committee_attesters) + committee_offset += len(committee) + return output ``` @@ -106,11 +109,13 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # [Modified in EIP7549] assert data.index == 0 committee_indices = get_committee_indices(attestation.committee_bits) - assert len(committee_indices) == len(attestation.aggregation_bits) + participants_count = 0 for index in committee_indices: assert index < get_committee_count_per_slot(state, data.target.epoch) committee = get_beacon_committee(state, data.slot, index) - assert len(attestation.aggregation_bits[index]) == len(committee) + participants_count += len(committee) + + assert len(attestation.aggregation_bits) == participants_count # Participation flag indices participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot) diff --git a/specs/_features/eip7549/p2p-interface.md b/specs/_features/eip7549/p2p-interface.md index c7413ea4b..20aa291b3 100644 --- a/specs/_features/eip7549/p2p-interface.md +++ b/specs/_features/eip7549/p2p-interface.md @@ -36,19 +36,17 @@ The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are The following convenience variables are re-defined - `index = get_committee_indices(aggregate.committee_bits)[0]` -- `aggregation_bits = aggregate.aggregation_bits[0]` The following validations are added: -* [REJECT] `len(committee_indices) == len(aggregate.attestation_bits) == 1`, where `committee_indices = get_committee_indices(aggregate)`. +* [REJECT] `len(committee_indices) == 1`, where `committee_indices = get_committee_indices(aggregate)`. * [REJECT] `aggregate.data.index == 0` ###### `beacon_attestation_{subnet_id}` The following convenience variables are re-defined - `index = get_committee_indices(attestation.committee_bits)[0]` -- `aggregation_bits = attestation.aggregation_bits[0]` The following validations are added: -* [REJECT] `len(committee_indices) == len(attestation.attestation_bits) == 1`, where `committee_indices = get_committee_indices(attestation)`. +* [REJECT] `len(committee_indices) == 1`, where `committee_indices = get_committee_indices(attestation)`. * [REJECT] `attestation.data.index == 0` diff --git a/specs/_features/eip7549/validator.md b/specs/_features/eip7549/validator.md index 6ae84aca6..98310bc6f 100644 --- a/specs/_features/eip7549/validator.md +++ b/specs/_features/eip7549/validator.md @@ -26,17 +26,36 @@ ##### Attestations -Attestations received from aggregators with disjoint `committee_bits` sets and equal `AttestationData` SHOULD be consolidated into a single `Attestation` object. +The network attestation aggregates contain only the assigned committee attestations. +Attestation aggregates received by the block proposer from the committee aggregators with disjoint `committee_bits` sets and equal `AttestationData` SHOULD be consolidated into a single `Attestation` object. +The proposer should run the following function to construct an on chain final aggregate form a list of network aggregates with equal `AttestationData`: + +```python +def compute_on_chain_aggregate(network_aggregates: List[Attestation]) -> Attestation: + aggregates = sorted(network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0]) + + data = aggregates[0].data + aggregation_bits = Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]() + for a in aggregates: + for b in a.aggregation_bits: + aggregation_bits.append(b) + + signature = bls.Aggregate([a.signature for a in aggregates]) + + committee_indices = [get_committee_indices(a.committee_bits)[0] for a in aggregates] + committee_flags = [(index in committee_indices) for index in range(0, MAX_COMMITTEES_PER_SLOT)] + committee_bits = Bitvector[MAX_COMMITTEES_PER_SLOT](committee_flags) + + return Attestation(aggregation_bits, data, committee_bits, signature) +``` ### Attesting #### Construct attestation - Set `attestation_data.index = 0`. -- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` of length `len(committee)`, where the bit of the index of the validator in the `committee` is set to `0b1`. -- Set `attestation.aggregation_bits = [aggregation_bits]`, a list of length 1 -- Let `committee_bits` be a `Bitvector[MAX_COMMITTEES_PER_SLOT]`, where the bit at the index associated with the validator's committee is set to `0b1` -- Set `attestation.committee_bits = committee_bits` +- Let `attestation.aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]` of length `len(committee)`, where the bit of the index of the validator in the `committee` is set to `0b1`. +- Let `attestation.committee_bits` be a `Bitvector[MAX_COMMITTEES_PER_SLOT]`, where the bit at the index associated with the validator's committee is set to `0b1`. *Note*: Calling `get_attesting_indices(state, attestation)` should return a list of length equal to 1, containing `validator_index`. @@ -45,7 +64,6 @@ Attestations received from aggregators with disjoint `committee_bits` sets and e #### Construct aggregate - Set `attestation_data.index = 0`. -- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` of length `len(committee)`, where each bit set from each individual attestation is set to `0b1`. -- Set `attestation.aggregation_bits = [aggregation_bits]`, a list of length 1 -- Set `attestation.committee_bits = committee_bits`, where `committee_bits` has the same value as in each individual attestation +- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]` of length `len(committee)`, where each bit set from each individual attestation is set to `0b1`. +- Set `attestation.committee_bits = committee_bits`, where `committee_bits` has the same value as in each individual attestation. diff --git a/specs/_features/whisk/fork.md b/specs/_features/whisk/fork.md index ef3eb0846..300d19129 100644 --- a/specs/_features/whisk/fork.md +++ b/specs/_features/whisk/fork.md @@ -41,7 +41,7 @@ Warning: this configuration is not definitive. | Name | Value | | -------------------- | ----------------------- | -| `WHISK_FORK_VERSION` | `Version('0x05000000')` | +| `WHISK_FORK_VERSION` | `Version('0x08000000')` | | `WHISK_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | ## Fork to Whisk diff --git a/specs/phase0/p2p-interface.md b/specs/phase0/p2p-interface.md index a34b34233..ff1bd03a1 100644 --- a/specs/phase0/p2p-interface.md +++ b/specs/phase0/p2p-interface.md @@ -245,7 +245,7 @@ The following gossipsub [parameters](https://github.com/libp2p/specs/blob/master - `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 60 - `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 6 - `mcache_gossip` (number of windows to gossip about): 3 -- `seen_ttl` (number of heartbeat intervals to retain message IDs): 550 +- `seen_ttl` (expiry time for cache of seen message ids, seconds): SECONDS_PER_SLOT * SLOTS_PER_EPOCH * 2 *Note*: Gossipsub v1.1 introduces a number of [additional parameters](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#overview-of-new-parameters) @@ -367,7 +367,7 @@ The following validations MUST pass before forwarding the `signed_aggregate_and_ - _[REJECT]_ The aggregate attestation's epoch matches its target -- i.e. `aggregate.data.target.epoch == compute_epoch_at_slot(aggregate.data.slot)` - _[REJECT]_ The number of aggregation bits matches the committee size -- i.e. - `len(aggregation_bits) == len(get_beacon_committee(state, aggregate.data.slot, aggregate.data.index))`. + `len(aggregation_bits) == len(get_beacon_committee(state, aggregate.data.slot, index))`. - _[REJECT]_ The aggregate attestation has participants -- that is, `len(get_attesting_indices(state, aggregate)) >= 1`. - _[IGNORE]_ A valid aggregate attestation defined by `hash_tree_root(aggregate.data)` whose `aggregation_bits` is a non-strict superset has _not_ already been seen. diff --git a/tests/formats/light_client/single_merkle_proof.md b/tests/formats/light_client/single_merkle_proof.md index d2137605e..0cb4cd0d0 100644 --- a/tests/formats/light_client/single_merkle_proof.md +++ b/tests/formats/light_client/single_merkle_proof.md @@ -7,7 +7,7 @@ generation and verification of merkle proofs based on static data. Tests for each individual SSZ type are grouped into a `suite` indicating the SSZ type name. -### `object.yaml` +### `object.ssz_snappy` A SSZ-snappy encoded object from which other data is generated. The SSZ type can be determined from the test `suite` name.