Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
24edf45
Add Electra fork boilerplate
macladson Jan 24, 2024
bc36e97
Remove electra from spec tests
macladson Jan 25, 2024
150e37c
Fix tests
macladson Jan 29, 2024
ae60752
Remove sneaky log file
macladson Jan 29, 2024
f7848a5
Fix more tests
macladson Jan 29, 2024
2dfb580
Fix even more tests and add suggestions
macladson Jan 30, 2024
6948b94
Remove unrelated lcli addition
macladson Jan 31, 2024
ad8ad52
Update more tests
macladson Jan 31, 2024
811f50c
Merge branch 'unstable' into electra
macladson Mar 4, 2024
02dd670
Add comment for test-suite lcli override
macladson Mar 4, 2024
8e54a9b
Merge branch 'unstable' into electra
macladson Mar 4, 2024
7b9765a
Cleanup
macladson Mar 4, 2024
1089cb5
Merge branch 'unstable' into electra
macladson Mar 18, 2024
ef724dc
Apply suggestions
macladson Mar 18, 2024
ec88934
Merge branch 'unstable' into electra
macladson Mar 21, 2024
e2a1b27
add todos
eserilev Mar 27, 2024
937e230
initial poc
eserilev Mar 28, 2024
49e8fd1
merge unstable
eserilev Apr 2, 2024
b0f2df7
attestation superstruct changes
eserilev Apr 7, 2024
13de1aa
add indexed attestation logic
eserilev Apr 7, 2024
fcfdf24
continued superstruct refactoring
eserilev Apr 8, 2024
4625b3d
superstruct refactoring
eserilev Apr 9, 2024
531de20
update indexed_attestation
eserilev Apr 9, 2024
485f5fb
initial test fixes
eserilev Apr 11, 2024
1750dc2
fmt
eserilev Apr 11, 2024
00abfb3
TODO
eserilev Apr 13, 2024
3585321
merge conflicts
eserilev Apr 13, 2024
55ff98c
getting tests to pass
eserilev Apr 13, 2024
1110958
get tests to pass
eserilev Apr 14, 2024
cf9ecda
fix beacon chain tests, impl test random
eserilev Apr 14, 2024
84c0d99
update test random impl for attestation
eserilev Apr 15, 2024
5987da3
skip tests, update committe index calc
eserilev Apr 17, 2024
4258e66
super struct fun
eserilev Apr 17, 2024
b115fe0
compute on chain aggregate, superstruct changes
eserilev Apr 18, 2024
083216e
use existing aggreagte fn
eserilev Apr 18, 2024
4ca7b6a
test fixes
eserilev Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/src/attestation_simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pub fn produce_unaggregated_attestation<T: BeaconChainTypes>(
// Store the unaggregated attestation in the validator monitor for later processing
match chain.produce_unaggregated_attestation(current_slot, beacon_committee_index) {
Ok(unaggregated_attestation) => {
let data = &unaggregated_attestation.data;
let data = &unaggregated_attestation.data();

debug!(
chain.log,
Expand Down
201 changes: 133 additions & 68 deletions beacon_node/beacon_chain/src/attestation_verification.rs

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions beacon_node/beacon_chain/src/beacon_block_reward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use operation_pool::RewardCache;
use safe_arith::SafeArith;
use slog::error;
use state_processing::{
common::{get_attestation_participation_flag_indices, get_attesting_indices_from_state},
common::{
get_attestation_participation_flag_indices, indexed_attestation_base,
indexed_attestation_electra,
},
epoch_cache::initialize_epoch_cache,
per_block_processing::{
altair::sync_committee::compute_sync_aggregate_rewards, get_slashable_indices,
Expand Down Expand Up @@ -202,7 +205,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
let mut previous_epoch_participation = state.previous_epoch_participation()?.clone();

for attestation in block.body().attestations() {
let data = &attestation.data;
let data = &attestation.data();
let inclusion_delay = state.slot().safe_sub(data.slot)?.as_u64();
// [Modified in Deneb:EIP7045]
let participation_flag_indices = get_attestation_participation_flag_indices(
Expand All @@ -212,7 +215,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
&self.spec,
)?;

let attesting_indices = get_attesting_indices_from_state(state, attestation)?;
let attesting_indices = match attestation {
types::Attestation::Base(att) => {
indexed_attestation_base::get_attesting_indices_from_state(state, att)?
}
types::Attestation::Electra(att) => {
indexed_attestation_electra::get_attesting_indices_from_state(state, att)?
}
};

let mut proposer_reward_numerator = 0;
for index in attesting_indices {
let index = index as usize;
Expand Down
155 changes: 130 additions & 25 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ use slasher::Slasher;
use slog::{crit, debug, error, info, trace, warn, Logger};
use slot_clock::SlotClock;
use ssz::Encode;
use state_processing::common::{indexed_attestation_base, indexed_attestation_electra};
use state_processing::{
common::get_attesting_indices_from_state,
epoch_cache::initialize_epoch_cache,
per_block_processing,
per_block_processing::{
Expand All @@ -121,6 +121,7 @@ use store::{
use task_executor::{ShutdownReason, TaskExecutor};
use tokio_stream::Stream;
use tree_hash::TreeHash;
use types::attestation::{AttestationBase, AttestationElectra};
use types::blob_sidecar::FixedBlobSidecarList;
use types::payload::BlockProductionVersion;
use types::*;
Expand Down Expand Up @@ -1674,7 +1675,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
&self,
attestation: Attestation<T::EthSpec>,
) -> Result<Attestation<T::EthSpec>, Error> {
let beacon_block_root = attestation.data.beacon_block_root;
let beacon_block_root = attestation.data().beacon_block_root;
match self
.canonical_head
.fork_choice_read_lock()
Expand Down Expand Up @@ -1940,17 +1941,38 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
};
drop(cache_timer);

Ok(Attestation {
aggregation_bits: BitList::with_capacity(committee_len)?,
data: AttestationData {
slot: request_slot,
index: request_index,
beacon_block_root,
source: justified_checkpoint,
target,
},
signature: AggregateSignature::empty(),
})
if self.spec.fork_name_at_slot::<T::EthSpec>(request_slot) >= ForkName::Electra {
// TODO(eip7549) if # of committees is zero, dont try to set a bit
let mut committee_bits = BitVector::default();
if committee_len > 0 {
committee_bits.set(request_index as usize, true)?;
}
Ok(Attestation::Electra(AttestationElectra {
// TODO(eip7549) need to make sure bitlists are of the correct length
aggregation_bits: BitList::with_capacity(committee_len)?,
data: AttestationData {
slot: request_slot,
index: 0u64,
beacon_block_root,
source: justified_checkpoint,
target,
},
committee_bits,
signature: AggregateSignature::empty(),
}))
} else {
Ok(Attestation::Base(AttestationBase {
aggregation_bits: BitList::with_capacity(committee_len)?,
data: AttestationData {
slot: request_slot,
index: request_index,
beacon_block_root,
source: justified_checkpoint,
target,
},
signature: AggregateSignature::empty(),
}))
}
}

/// Performs the same validation as `Self::verify_unaggregated_attestation_for_gossip`, but for
Expand Down Expand Up @@ -2162,8 +2184,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Stored unaggregated attestation";
"outcome" => ?outcome,
"index" => attestation.data.index,
"slot" => attestation.data.slot.as_u64(),
"index" => attestation.committee_index(),
"slot" => attestation.data().slot.as_u64(),
),
Err(NaiveAggregationError::SlotTooLow {
slot,
Expand All @@ -2181,8 +2203,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Failed to store unaggregated attestation";
"error" => ?e,
"index" => attestation.data.index,
"slot" => attestation.data.slot.as_u64(),
"index" => attestation.committee_index(),
"slot" => attestation.data().slot.as_u64(),
);
return Err(Error::from(e).into());
}
Expand Down Expand Up @@ -3730,7 +3752,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Failed to get indexed attestation";
"purpose" => "validator monitor",
"attestation_slot" => attestation.data.slot,
"attestation_slot" => attestation.data().slot,
"error" => ?e,
);
continue;
Expand Down Expand Up @@ -3786,7 +3808,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Failed to register observed attestation";
"error" => ?e,
"epoch" => a.data.target.epoch
"epoch" => a.data().target.epoch
);
}
}
Expand All @@ -3798,7 +3820,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Failed to get indexed attestation";
"purpose" => "observation",
"attestation_slot" => a.data.slot,
"attestation_slot" => a.data().slot,
"error" => ?e,
);
continue;
Expand All @@ -3809,13 +3831,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {

for &validator_index in &indexed_attestation.attesting_indices {
if let Err(e) = observed_block_attesters
.observe_validator(a.data.target.epoch, validator_index as usize)
.observe_validator(a.data().target.epoch, validator_index as usize)
{
debug!(
self.log,
"Failed to register observed block attester";
"error" => ?e,
"epoch" => a.data.target.epoch,
"epoch" => a.data().target.epoch,
"validator_index" => validator_index,
)
}
Expand All @@ -3839,7 +3861,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Failed to get indexed attestation";
"purpose" => "slasher",
"attestation_slot" => attestation.data.slot,
"attestation_slot" => attestation.data().slot,
"error" => ?e,
);
continue;
Expand Down Expand Up @@ -4978,7 +5000,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
metrics::start_timer(&metrics::BLOCK_PRODUCTION_UNAGGREGATED_TIMES);
for attestation in self.naive_aggregation_pool.read().iter() {
let import = |attestation: &Attestation<T::EthSpec>| {
let attesting_indices = get_attesting_indices_from_state(&state, attestation)?;
let attesting_indices = match attestation {
Attestation::Base(att) => {
indexed_attestation_base::get_attesting_indices_from_state(&state, att)?
}
Attestation::Electra(att) => {
indexed_attestation_electra::get_attesting_indices_from_state(&state, att)?
}
};
self.op_pool
.insert_attestation(attestation.clone(), attesting_indices)
};
Expand Down Expand Up @@ -5138,6 +5167,79 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
}

// TODO(eip7549) clean up this impl
fn compute_on_chain_aggregate(
attestations: &Vec<Attestation<T::EthSpec>>,
) -> Result<Vec<Attestation<T::EthSpec>>, Error> {
let mut aggregated_attestations: Vec<Attestation<T::EthSpec>> = vec![];
let mut attestations_by_data: HashMap<
AttestationData,
Vec<AttestationElectra<T::EthSpec>>,
> = HashMap::new();

let mut duplicate_check: HashSet<
Vec<u8>,
> = HashSet::new();

//TODO(eip7549) i just wanted to get something working
// this needs to be cleaned up before merging to unstable
for attestation in attestations {
let electra_attestation = attestation
.as_electra()
//TODO(eip7549) this should be a different error type
.map_err(|_| BeaconChainError::AttestationCacheLockTimeout)?;

if duplicate_check.get(&electra_attestation.clone().aggregation_bits.into_bytes().to_vec()).is_some() {
continue;
} else {
duplicate_check.insert(electra_attestation.clone().aggregation_bits.into_bytes().to_vec());
}

attestations_by_data
.entry(electra_attestation.clone().data)
.or_insert_with(Vec::new)
.push(electra_attestation.clone());
}

for (_, attestations) in attestations_by_data.iter_mut() {
attestations.sort_by_key(|a| *a.get_committee_indices().first().unwrap_or(&0u64));
let committee_indices: Vec<u64> = attestations
.iter()
.map(|a| *a.get_committee_indices().first().unwrap_or(&0u64))
.collect();

let committee_flags: Vec<bool> = (0..T::EthSpec::max_committees_per_slot())
.map(|index| committee_indices.contains(&(index as u64)))
.collect();

let mut committee_bits = BitVector::default();

for (i, &flag) in committee_flags.iter().enumerate() {
committee_bits
.set(i, flag)
//TODO(eip7549) this should be a different error type
.map_err(|_| BeaconChainError::AttestationCacheLockTimeout)?;
}

if let Some(first_attestation) = attestations.first() {
let mut aggregate_attestation = AttestationElectra::<T::EthSpec> {
aggregation_bits: first_attestation.aggregation_bits.clone(),
signature: first_attestation.signature.clone(),
committee_bits,
data: first_attestation.data.clone(),
};
for attestation in attestations.iter().skip(1) {
aggregate_attestation.aggregate(&attestation);
}

aggregated_attestations.push(Attestation::Electra(aggregate_attestation))
}
}


return Ok(aggregated_attestations);
}

fn complete_partial_beacon_block<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
partial_beacon_block: PartialBeaconBlock<T::EthSpec>,
Expand Down Expand Up @@ -5317,6 +5419,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
block_contents
.ok_or(BlockProductionError::MissingExecutionPayload)?
.deconstruct();
let aggregate_attestation = Self::compute_on_chain_aggregate(&attestations)
// .map_err(|_| BlockProductionError::MissingExecutionPayload)?;
.unwrap_or(attestations);

(
BeaconBlock::Electra(BeaconBlockElectra {
Expand All @@ -5330,7 +5435,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
graffiti,
proposer_slashings: proposer_slashings.into(),
attester_slashings: attester_slashings.into(),
attestations: attestations.into(),
attestations: aggregate_attestation.into(),
deposits: deposits.into(),
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
Expand Down
17 changes: 12 additions & 5 deletions beacon_node/beacon_chain/src/block_reward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::{AttestationRewards, BlockReward, BlockRewardMeta};
use operation_pool::{AttMaxCover, MaxCover, RewardCache, SplitAttestation};
use state_processing::{
common::get_attesting_indices_from_state,
common::{indexed_attestation_base, indexed_attestation_electra},
per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards,
};
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, EthSpec, Hash256};
Expand All @@ -28,9 +28,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.body()
.attestations()
.iter()
.map(|att| {
let attesting_indices = get_attesting_indices_from_state(state, att)?;
Ok(SplitAttestation::new(att.clone(), attesting_indices))
.map(|attestaton| {
let attesting_indices = match attestaton {
types::Attestation::Base(att) => {
indexed_attestation_base::get_attesting_indices_from_state(state, att)?
}
types::Attestation::Electra(att) => {
indexed_attestation_electra::get_attesting_indices_from_state(state, att)?
}
};
Ok(SplitAttestation::new(attestaton.clone(), attesting_indices))
})
.collect::<Result<Vec<_>, BeaconChainError>>()?;

Expand Down Expand Up @@ -87,7 +94,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.body()
.attestations()
.iter()
.map(|a| a.data.clone())
.map(|a| a.data().clone())
.collect()
} else {
vec![]
Expand Down
Loading