Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat-deposit-helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobkaufmann committed Apr 12, 2024
2 parents 92b92dd + af5a8d3 commit c8fc562
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 5,396 deletions.
6 changes: 3 additions & 3 deletions ethereum-consensus/src/altair/block_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
increase_balance, is_valid_indexed_attestation, process_block_header, process_eth1_data,
process_operations, process_randao,
sync::SyncAggregate,
Attestation, Bytes32,
Attestation, Bytes32, Gwei,
},
crypto::eth_fast_aggregate_verify,
domains::DomainType,
Expand Down Expand Up @@ -174,7 +174,7 @@ pub fn add_validator_to_registry<
>,
public_key: BlsPublicKey,
withdrawal_credentials: Bytes32,
amount: u64,
amount: Gwei,
context: &Context,
) {
state.validators.push(get_validator_from_deposit(
Expand All @@ -186,7 +186,7 @@ pub fn add_validator_to_registry<
state.balances.push(amount);
state.previous_epoch_participation.push(ParticipationFlags::default());
state.current_epoch_participation.push(ParticipationFlags::default());
state.inactivity_scores.push(0)
state.inactivity_scores.push(0);
}

pub fn process_sync_aggregate<
Expand Down
221 changes: 12 additions & 209 deletions ethereum-consensus/src/altair/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ pub use crate::{
phase0::{
beacon_block::{BeaconBlockHeader, SignedBeaconBlockHeader},
beacon_state::{Fork, ForkData, HistoricalBatch, HistoricalSummary},
block_processing::DEPOSIT_MERKLE_DEPTH,
block_processing::{get_validator_from_deposit, xor},
constants::{
BASE_REWARDS_PER_EPOCH, DEPOSIT_CONTRACT_TREE_DEPTH, DEPOSIT_DATA_LIST_BOUND,
JUSTIFICATION_BITS_LENGTH,
},
helpers::{
compute_activation_exit_epoch, compute_committee, compute_domain,
compute_epoch_at_slot, compute_fork_data_root, compute_fork_digest,
compute_shuffled_index, compute_shuffled_indices, compute_start_slot_at_epoch,
is_active_validator, is_eligible_for_activation_queue, is_slashable_attestation_data,
is_slashable_validator,
},
operations::{
Attestation, AttestationData, AttesterSlashing, Checkpoint, Deposit, DepositData,
DepositMessage, Eth1Data, IndexedAttestation, PendingAttestation, ProposerSlashing,
Expand All @@ -62,7 +69,7 @@ use crate::{
crypto::{fast_aggregate_verify, hash},
ssz::prelude::*,
};
use std::{cmp, collections::HashSet};
use std::collections::HashSet;
pub fn process_proposer_slashing<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down Expand Up @@ -188,27 +195,6 @@ pub fn process_attester_slashing<
Ok(())
}
}
pub fn get_validator_from_deposit(
public_key: BlsPublicKey,
withdrawal_credentials: Bytes32,
amount: Gwei,
context: &Context,
) -> Validator {
let effective_balance = Gwei::min(
amount - amount % context.effective_balance_increment,
context.max_effective_balance,
);
Validator {
public_key,
withdrawal_credentials,
effective_balance,
activation_eligibility_epoch: FAR_FUTURE_EPOCH,
activation_epoch: FAR_FUTURE_EPOCH,
exit_epoch: FAR_FUTURE_EPOCH,
withdrawable_epoch: FAR_FUTURE_EPOCH,
..Default::default()
}
}
pub fn apply_deposit<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down Expand Up @@ -284,17 +270,12 @@ pub fn process_deposit<
) -> Result<()> {
let leaf = deposit.data.hash_tree_root()?;
let branch = &deposit.proof;
let depth = DEPOSIT_CONTRACT_TREE_DEPTH + 1;
let index = state.eth1_deposit_index as usize;
let root = state.eth1_data.deposit_root;
if is_valid_merkle_branch(leaf, branch, DEPOSIT_MERKLE_DEPTH, index, root).is_err() {
if is_valid_merkle_branch(leaf, branch, depth, index, root).is_err() {
return Err(invalid_operation_error(InvalidOperation::Deposit(
InvalidDeposit::InvalidProof {
leaf,
branch: branch.to_vec(),
depth: DEPOSIT_MERKLE_DEPTH,
index,
root,
},
InvalidDeposit::InvalidProof { leaf, branch: branch.to_vec(), depth, index, root },
)));
}
state.eth1_deposit_index += 1;
Expand Down Expand Up @@ -447,10 +428,6 @@ pub fn process_block_header<
}
Ok(())
}
pub fn xor(a: &Bytes32, b: &Bytes32) -> Bytes32 {
let inner = a.iter().zip(b.iter()).map(|(a, b)| a ^ b).collect::<Vec<_>>();
ByteVector::<32>::try_from(inner.as_ref()).unwrap()
}
pub fn process_randao<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down Expand Up @@ -1014,13 +991,6 @@ pub fn get_genesis_block<
> {
Ok(BeaconBlock { state_root: genesis_state.hash_tree_root()?, ..Default::default() })
}
pub fn is_active_validator(validator: &Validator, epoch: Epoch) -> bool {
validator.activation_epoch <= epoch && epoch < validator.exit_epoch
}
pub fn is_eligible_for_activation_queue(validator: &Validator, context: &Context) -> bool {
validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH &&
validator.effective_balance == context.max_effective_balance
}
pub fn is_eligible_for_activation<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand All @@ -1046,17 +1016,6 @@ pub fn is_eligible_for_activation<
validator.activation_eligibility_epoch <= state.finalized_checkpoint.epoch &&
validator.activation_epoch == FAR_FUTURE_EPOCH
}
pub fn is_slashable_validator(validator: &Validator, epoch: Epoch) -> bool {
!validator.slashed &&
validator.activation_epoch <= epoch &&
epoch < validator.withdrawable_epoch
}
pub fn is_slashable_attestation_data(data_1: &AttestationData, data_2: &AttestationData) -> bool {
let double_vote = data_1 != data_2 && data_1.target.epoch == data_2.target.epoch;
let surround_vote =
data_1.source.epoch < data_2.source.epoch && data_2.target.epoch < data_1.target.epoch;
double_vote || surround_vote
}
pub fn is_valid_indexed_attestation<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down Expand Up @@ -1225,98 +1184,6 @@ pub fn get_current_epoch<
) -> Epoch {
compute_epoch_at_slot(state.slot, context)
}
pub fn compute_shuffled_index(
mut index: usize,
index_count: usize,
seed: &Bytes32,
context: &Context,
) -> Result<usize> {
if index >= index_count {
return Err(Error::InvalidShufflingIndex { index, total: index_count });
}
let mut pivot_input = [0u8; 33];
pivot_input[..32].copy_from_slice(seed.as_ref());
let mut source_input = [0u8; 37];
source_input[..32].copy_from_slice(seed.as_ref());
for current_round in 0..context.shuffle_round_count {
pivot_input[32] = current_round as u8;
let pivot_bytes: [u8; 8] = hash(pivot_input).as_ref()[..8].try_into().unwrap();
let pivot = (u64::from_le_bytes(pivot_bytes) as usize) % index_count;
let flip = (pivot + index_count - index) % index_count;
let position = cmp::max(index, flip);
let position_bytes: [u8; 4] = ((position / 256) as u32).to_le_bytes();
source_input[32] = current_round as u8;
source_input[33..].copy_from_slice(&position_bytes);
let source = hash(source_input);
let byte = source.as_ref()[(position % 256) / 8];
let bit = (byte >> (position % 8)) % 2;
index = if bit != 0 { flip } else { index };
}
Ok(index)
}
pub fn compute_shuffled_indices(
indices: &[ValidatorIndex],
seed: &Bytes32,
context: &Context,
) -> ShuffledIndices {
let mut input = indices.to_vec();
if input.is_empty() {
return input;
}
let index_count = input.len();
let mut pivot_input = [0u8; 33];
pivot_input[..32].copy_from_slice(seed.as_ref());
let mut source_input = [0u8; 37];
source_input[..32].copy_from_slice(seed.as_ref());
for current_round in (0..=context.shuffle_round_count - 1).rev() {
pivot_input[32] = current_round as u8;
let pivot_bytes: [u8; 8] = hash(pivot_input).as_ref()[..8].try_into().unwrap();
let pivot = u64::from_le_bytes(pivot_bytes) as usize % index_count;
source_input[32] = current_round as u8;
let position = (pivot >> 8) as u32;
source_input[33..].copy_from_slice(&position.to_le_bytes());
let mut source = hash(source_input);
let mut byte_source = source[(pivot & 0xff) >> 3];
let mirror = (pivot + 1) >> 1;
for i in 0..mirror {
let j = pivot - i;
if j & 0xff == 0xff {
let position = (j >> 8) as u32;
source_input[33..].copy_from_slice(&position.to_le_bytes());
source = hash(source_input);
}
if j & 0x07 == 0x07 {
byte_source = source[(j & 0xff) >> 3];
}
let bit_source = (byte_source >> (j & 0x07)) & 0x01;
if bit_source == 1 {
input.swap(i, j);
}
}
let end = index_count - 1;
let position = (end >> 8) as u32;
source_input[33..].copy_from_slice(&position.to_le_bytes());
source = hash(source_input);
byte_source = source[(end & 0xff) >> 3];
let mirror = (pivot + index_count + 1) >> 1;
for (k, i) in ((pivot + 1)..mirror).enumerate() {
let j = end - k;
if j & 0xff == 0xff {
let position = (j >> 8) as u32;
source_input[33..].copy_from_slice(&position.to_le_bytes());
source = hash(source_input);
}
if j & 0x07 == 0x07 {
byte_source = source[(j & 0xff) >> 3];
}
let bit_source = (byte_source >> (j & 0x07)) & 0x01;
if bit_source == 1 {
input.swap(i, j);
}
}
}
input
}
pub fn sample_proposer_index<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down Expand Up @@ -1408,70 +1275,6 @@ pub fn compute_proposer_index<
}
}
}
pub fn compute_committee(
indices: &[ValidatorIndex],
seed: &Bytes32,
index: usize,
count: usize,
context: &Context,
) -> Result<Vec<ValidatorIndex>> {
if cfg!(feature = "shuffling") {
let shuffled_indices = compute_shuffled_indices(indices, seed, context);
let index_count = indices.len();
let start = index_count * index / count;
let end = index_count * (index + 1) / count;
let committee = shuffled_indices[start..end].to_vec();
Ok(committee)
} else {
let start = indices.len() * index / count;
let end = indices.len() * (index + 1) / count;
let mut committee = vec![0usize; end - start];
for i in start..end {
let index = compute_shuffled_index(i, indices.len(), seed, context)?;
committee[i - start] = indices[index];
}
Ok(committee)
}
}
pub fn compute_epoch_at_slot(slot: Slot, context: &Context) -> Epoch {
slot / context.slots_per_epoch
}
pub fn compute_start_slot_at_epoch(epoch: Epoch, context: &Context) -> Slot {
epoch * context.slots_per_epoch
}
pub fn compute_activation_exit_epoch(epoch: Epoch, context: &Context) -> Epoch {
epoch + 1 + context.max_seed_lookahead
}
pub fn compute_fork_digest(
current_version: Version,
genesis_validators_root: Root,
) -> Result<ForkDigest> {
let fork_data_root = compute_fork_data_root(current_version, genesis_validators_root)?;
let digest = &fork_data_root[..4];
Ok(digest.try_into().expect("should not fail"))
}
pub fn compute_domain(
domain_type: DomainType,
fork_version: Option<Version>,
genesis_validators_root: Option<Root>,
context: &Context,
) -> Result<Domain> {
let fork_version = fork_version.unwrap_or(context.genesis_fork_version);
let genesis_validators_root = genesis_validators_root.unwrap_or_default();
let fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)?;
let mut domain = Domain::default();
domain[..4].copy_from_slice(&domain_type.as_bytes());
domain[4..].copy_from_slice(&fork_data_root[..28]);
Ok(domain)
}
pub fn compute_fork_data_root(
current_version: Version,
genesis_validators_root: Root,
) -> Result<Root> {
ForkData { current_version, genesis_validators_root }
.hash_tree_root()
.map_err(Error::Merkleization)
}
pub fn get_previous_epoch<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
Expand Down
Loading

0 comments on commit c8fc562

Please sign in to comment.