diff --git a/beacon_chain/genesis/src/beacon_block.rs b/beacon_chain/genesis/src/beacon_block.rs index 78968b7a6..3fefff6a0 100644 --- a/beacon_chain/genesis/src/beacon_block.rs +++ b/beacon_chain/genesis/src/beacon_block.rs @@ -1,17 +1,15 @@ -use bls::{Signature, BLS_AGG_SIG_BYTE_SIZE}; use spec::ChainSpec; -use ssz::{encode::encode_length, Decodable, LENGTH_BYTES}; use types::{BeaconBlock, BeaconBlockBody, Hash256}; /// Generate a genesis BeaconBlock. pub fn genesis_beacon_block(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock { BeaconBlock { - slot: spec.initial_slot_number, + slot: spec.genesis_slot_number, parent_root: spec.zero_hash, state_root, randao_reveal: spec.zero_hash, candidate_pow_receipt_root: spec.zero_hash, - signature: genesis_signature(), + signature: spec.empty_signature.clone(), body: BeaconBlockBody { proposer_slashings: vec![], casper_slashings: vec![], @@ -25,19 +23,10 @@ pub fn genesis_beacon_block(state_root: Hash256, spec: &ChainSpec) -> BeaconBloc } } -fn genesis_signature() -> Signature { - let mut bytes = encode_length(BLS_AGG_SIG_BYTE_SIZE, LENGTH_BYTES); - bytes.append(&mut vec![0; BLS_AGG_SIG_BYTE_SIZE]); - let (signature, _) = match Signature::ssz_decode(&bytes, 0) { - Ok(sig) => sig, - Err(_) => unreachable!(), - }; - signature -} - #[cfg(test)] mod tests { use super::*; + use bls::Signature; #[test] fn test_genesis() { @@ -95,5 +84,6 @@ mod tests { for item in raw_sig_bytes.iter() { assert!(*item == 0); } + assert_eq!(genesis_block.signature, Signature::empty_signature()); } } diff --git a/beacon_chain/genesis/src/beacon_state.rs b/beacon_chain/genesis/src/beacon_state.rs index 58feca840..54cf1388d 100644 --- a/beacon_chain/genesis/src/beacon_state.rs +++ b/beacon_chain/genesis/src/beacon_state.rs @@ -21,7 +21,7 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result { }; let initial_crosslink = CrosslinkRecord { - slot: spec.initial_slot_number, + slot: spec.genesis_slot_number, shard_block_root: spec.zero_hash, }; @@ -29,19 +29,19 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result { /* * Misc */ - slot: spec.initial_slot_number, + slot: spec.genesis_slot_number, genesis_time: spec.genesis_time, fork_data: ForkData { - pre_fork_version: spec.initial_fork_version, - post_fork_version: spec.initial_fork_version, - fork_slot: spec.initial_slot_number, + pre_fork_version: spec.genesis_fork_version, + post_fork_version: spec.genesis_fork_version, + fork_slot: spec.genesis_slot_number, }, /* * Validator registry */ validator_registry: spec.initial_validators.clone(), validator_balances: spec.initial_balances.clone(), - validator_registry_latest_change_slot: spec.initial_slot_number, + validator_registry_latest_change_slot: spec.genesis_slot_number, validator_registry_exit_count: 0, validator_registry_delta_chain_tip: spec.zero_hash, /* @@ -52,7 +52,12 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result { spec.zero_hash; (spec.latest_randao_mixes_length / spec.epoch_length) as usize ], - shard_committees_at_slots: vec![], + previous_epoch_start_shard: spec.genesis_start_shard, + current_epoch_start_shard: spec.genesis_start_shard, + previous_epoch_calculation_slot: spec.genesis_slot_number, + current_epoch_calculation_slot: spec.genesis_slot_number, + previous_epoch_randao_mix: spec.zero_hash, + current_epoch_randao_mix: spec.zero_hash, /* * Custody challenges */ @@ -60,10 +65,10 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result { /* * Finality */ - previous_justified_slot: spec.initial_slot_number, - justified_slot: spec.initial_slot_number, + previous_justified_slot: spec.genesis_slot_number, + justified_slot: spec.genesis_slot_number, justification_bitfield: 0, - finalized_slot: spec.initial_slot_number, + finalized_slot: spec.genesis_slot_number, /* * Recent state */ diff --git a/beacon_chain/spec/src/foundation.rs b/beacon_chain/spec/src/foundation.rs index c2794e44b..81bee7c4a 100644 --- a/beacon_chain/spec/src/foundation.rs +++ b/beacon_chain/spec/src/foundation.rs @@ -1,5 +1,5 @@ use super::ChainSpec; -use bls::{Keypair, PublicKey, SecretKey}; +use bls::{Keypair, PublicKey, SecretKey, Signature}; use types::{Address, Hash256, ValidatorRecord}; @@ -17,12 +17,11 @@ impl ChainSpec { * Misc */ shard_count: 1_024, - target_committee_size: 256, + target_committee_size: 128, ejection_balance: 16, max_balance_churn_quotient: 32, gwei_per_eth: u64::pow(10, 9), beacon_chain_shard_number: u64::max_value(), - bls_withdrawal_prefix_byte: 0x00, max_casper_votes: 1_024, latest_block_roots_length: 8_192, latest_randao_mixes_length: 8_192, @@ -38,32 +37,35 @@ impl ChainSpec { /* * Initial Values */ - initial_fork_version: 0, - initial_slot_number: 0, + genesis_fork_version: 0, + genesis_slot_number: 0, + genesis_start_shard: 0, + far_future_slot: u64::max_value(), zero_hash: Hash256::zero(), + empty_signature: Signature::empty_signature(), + bls_withdrawal_prefix_byte: 0x00, /* * Time parameters */ slot_duration: 6, min_attestation_inclusion_delay: 4, epoch_length: 64, - min_validator_registry_change_interval: 256, + seed_lookahead: 64, + entry_exit_delay: 256, pow_receipt_root_voting_period: 1_024, - shard_persistent_committee_change_period: u64::pow(2, 17), - collective_penalty_calculation_period: u64::pow(2, 20), - zero_balance_validator_ttl: u64::pow(2, 22), + min_validator_withdrawal_time: u64::pow(2, 14), /* * Reward and penalty quotients */ - base_reward_quotient: 2_048, + base_reward_quotient: 1_024, whistleblower_reward_quotient: 512, includer_reward_quotient: 8, - inactivity_penalty_quotient: u64::pow(2, 34), + inactivity_penalty_quotient: u64::pow(2, 24), /* * Max operations per block */ max_proposer_slashings: 16, - max_casper_slashings: 15, + max_casper_slashings: 16, max_attestations: 128, max_deposits: 16, max_exits: 16, @@ -104,7 +106,18 @@ fn initial_validators_for_testing() -> Vec { }; let validator_record = ValidatorRecord { pubkey: keypair.pk.clone(), - ..Default::default() + withdrawal_credentials: Hash256::zero(), + randao_commitment: Hash256::zero(), + randao_layers: 0, + activation_slot: u64::max_value(), + exit_slot: u64::max_value(), + withdrawal_slot: u64::max_value(), + penalized_slot: u64::max_value(), + exit_count: 0, + status_flags: None, + custody_commitment: Hash256::zero(), + latest_custody_reseed_slot: 0, + penultimate_custody_reseed_slot: 0, }; initial_validators.push(validator_record); } diff --git a/beacon_chain/spec/src/lib.rs b/beacon_chain/spec/src/lib.rs index 5b7bdfae3..fbe82794d 100644 --- a/beacon_chain/spec/src/lib.rs +++ b/beacon_chain/spec/src/lib.rs @@ -3,6 +3,7 @@ extern crate types; mod foundation; +use bls::Signature; use types::{Address, Hash256, ValidatorRecord}; #[derive(PartialEq, Debug)] @@ -16,7 +17,6 @@ pub struct ChainSpec { pub max_balance_churn_quotient: u64, pub gwei_per_eth: u64, pub beacon_chain_shard_number: u64, - pub bls_withdrawal_prefix_byte: u8, pub max_casper_votes: u64, pub latest_block_roots_length: u64, pub latest_randao_mixes_length: u64, @@ -32,20 +32,23 @@ pub struct ChainSpec { /* * Initial Values */ - pub initial_fork_version: u64, - pub initial_slot_number: u64, + pub genesis_fork_version: u64, + pub genesis_slot_number: u64, + pub genesis_start_shard: u64, + pub far_future_slot: u64, pub zero_hash: Hash256, + pub empty_signature: Signature, + pub bls_withdrawal_prefix_byte: u8, /* * Time parameters */ pub slot_duration: u64, pub min_attestation_inclusion_delay: u64, pub epoch_length: u64, - pub min_validator_registry_change_interval: u64, - pub pow_receipt_root_voting_period: u64, - pub shard_persistent_committee_change_period: u64, - pub collective_penalty_calculation_period: u64, - pub zero_balance_validator_ttl: u64, + pub seed_lookahead: u64, + pub entry_exit_delay: u64, + pub pow_receipt_root_voting_period: u64, // a.k.a. deposit_root_voting_period + pub min_validator_withdrawal_time: u64, /* * Reward and penalty quotients */ diff --git a/beacon_chain/types/src/attestation_data_and_custody_bit.rs b/beacon_chain/types/src/attestation_data_and_custody_bit.rs new file mode 100644 index 000000000..66584b0d9 --- /dev/null +++ b/beacon_chain/types/src/attestation_data_and_custody_bit.rs @@ -0,0 +1,60 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use rand::RngCore; +use crate::test_utils::TestRandom; +use super::AttestationData; + +#[derive(Debug, Clone, PartialEq, Default)] +pub struct AttestationDataAndCustodyBit { + pub data: AttestationData, + pub custody_bit: bool, +} + +impl Encodable for AttestationDataAndCustodyBit { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.data); + s.append(&self.custody_bit); + } +} + +impl Decodable for AttestationDataAndCustodyBit { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (data, i) = <_>::ssz_decode(bytes, i)?; + let (custody_bit, i) = <_>::ssz_decode(bytes, i)?; + + let attestation_data_and_custody_bit = AttestationDataAndCustodyBit { + data, + custody_bit, + }; + + Ok((attestation_data_and_custody_bit, i)) + } +} + +impl TestRandom for AttestationDataAndCustodyBit { + fn random_for_test(rng: &mut T) -> Self { + Self { + data: <_>::random_for_test(rng), + custody_bit: <_>::random_for_test(rng), + } + } +} + +#[cfg(test)] +mod test { + use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use super::*; + use super::super::ssz::ssz_encode; + + #[test] + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + + let original = AttestationDataAndCustodyBit::random_for_test(&mut rng); + + let bytes = ssz_encode(&original); + + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/beacon_state.rs b/beacon_chain/types/src/beacon_state.rs index cbcb00d19..c55ce8ec9 100644 --- a/beacon_chain/types/src/beacon_state.rs +++ b/beacon_chain/types/src/beacon_state.rs @@ -2,7 +2,6 @@ use super::candidate_pow_receipt_root_record::CandidatePoWReceiptRootRecord; use super::crosslink_record::CrosslinkRecord; use super::fork_data::ForkData; use super::pending_attestation_record::PendingAttestationRecord; -use super::shard_committee::ShardCommittee; use super::validator_record::ValidatorRecord; use super::Hash256; use crate::test_utils::TestRandom; @@ -30,7 +29,12 @@ pub struct BeaconState { // Randomness and committees pub latest_randao_mixes: Vec, pub latest_vdf_outputs: Vec, - pub shard_committees_at_slots: Vec>, + pub previous_epoch_start_shard: u64, + pub current_epoch_start_shard: u64, + pub previous_epoch_calculation_slot: u64, + pub current_epoch_calculation_slot: u64, + pub previous_epoch_randao_mix: Hash256, + pub current_epoch_randao_mix: Hash256, // Custody challenges pub custody_challenges: Vec, @@ -73,7 +77,12 @@ impl Encodable for BeaconState { s.append(&self.validator_registry_delta_chain_tip); s.append(&self.latest_randao_mixes); s.append(&self.latest_vdf_outputs); - s.append(&self.shard_committees_at_slots); + s.append(&self.previous_epoch_start_shard); + s.append(&self.current_epoch_start_shard); + s.append(&self.previous_epoch_calculation_slot); + s.append(&self.current_epoch_calculation_slot); + s.append(&self.previous_epoch_randao_mix); + s.append(&self.current_epoch_randao_mix); s.append(&self.custody_challenges); s.append(&self.previous_justified_slot); s.append(&self.justified_slot); @@ -101,7 +110,12 @@ impl Decodable for BeaconState { let (validator_registry_delta_chain_tip, i) = <_>::ssz_decode(bytes, i)?; let (latest_randao_mixes, i) = <_>::ssz_decode(bytes, i)?; let (latest_vdf_outputs, i) = <_>::ssz_decode(bytes, i)?; - let (shard_committees_at_slots, i) = <_>::ssz_decode(bytes, i)?; + let (previous_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?; + let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?; + let (previous_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?; + let (current_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?; + let (previous_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?; + let (current_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?; let (custody_challenges, i) = <_>::ssz_decode(bytes, i)?; let (previous_justified_slot, i) = <_>::ssz_decode(bytes, i)?; let (justified_slot, i) = <_>::ssz_decode(bytes, i)?; @@ -127,7 +141,12 @@ impl Decodable for BeaconState { validator_registry_delta_chain_tip, latest_randao_mixes, latest_vdf_outputs, - shard_committees_at_slots, + previous_epoch_start_shard, + current_epoch_start_shard, + previous_epoch_calculation_slot, + current_epoch_calculation_slot, + previous_epoch_randao_mix, + current_epoch_randao_mix, custody_challenges, previous_justified_slot, justified_slot, @@ -159,7 +178,12 @@ impl TestRandom for BeaconState { validator_registry_delta_chain_tip: <_>::random_for_test(rng), latest_randao_mixes: <_>::random_for_test(rng), latest_vdf_outputs: <_>::random_for_test(rng), - shard_committees_at_slots: <_>::random_for_test(rng), + previous_epoch_start_shard: <_>::random_for_test(rng), + current_epoch_start_shard: <_>::random_for_test(rng), + previous_epoch_calculation_slot: <_>::random_for_test(rng), + current_epoch_calculation_slot: <_>::random_for_test(rng), + previous_epoch_randao_mix: <_>::random_for_test(rng), + current_epoch_randao_mix: <_>::random_for_test(rng), custody_challenges: <_>::random_for_test(rng), previous_justified_slot: <_>::random_for_test(rng), justified_slot: <_>::random_for_test(rng), diff --git a/beacon_chain/types/src/candidate_pow_receipt_root_record.rs b/beacon_chain/types/src/candidate_pow_receipt_root_record.rs index 5f260c423..9648763f3 100644 --- a/beacon_chain/types/src/candidate_pow_receipt_root_record.rs +++ b/beacon_chain/types/src/candidate_pow_receipt_root_record.rs @@ -3,6 +3,7 @@ use super::Hash256; use crate::test_utils::TestRandom; use rand::RngCore; +// Note: this is refer to as DepositRootVote in specs #[derive(Debug, PartialEq, Clone)] pub struct CandidatePoWReceiptRootRecord { pub candidate_pow_receipt_root: Hash256, diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index df0ce4d4c..5a8cde8ab 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -159,12 +159,15 @@ impl TestRandom for ValidatorRecord { withdrawal_credentials: <_>::random_for_test(rng), randao_commitment: <_>::random_for_test(rng), randao_layers: <_>::random_for_test(rng), + activation_slot: <_>::random_for_test(rng), + exit_slot: <_>::random_for_test(rng), + withdrawal_slot: <_>::random_for_test(rng), + penalized_slot: <_>::random_for_test(rng), exit_count: <_>::random_for_test(rng), status_flags: Some(<_>::random_for_test(rng)), custody_commitment: <_>::random_for_test(rng), latest_custody_reseed_slot: <_>::random_for_test(rng), penultimate_custody_reseed_slot: <_>::random_for_test(rng), - ..Self::default() } } } diff --git a/beacon_chain/utils/bls/src/signature.rs b/beacon_chain/utils/bls/src/signature.rs index 242908e21..07fc2baff 100644 --- a/beacon_chain/utils/bls/src/signature.rs +++ b/beacon_chain/utils/bls/src/signature.rs @@ -35,6 +35,12 @@ impl Signature { pub fn as_raw(&self) -> &RawSignature { &self.0 } + + /// Returns a new empty signature. + pub fn empty_signature() -> Self { + let empty: Vec = vec![0; 97]; + Signature(RawSignature::from_bytes(&empty).unwrap()) + } } impl Encodable for Signature { @@ -68,4 +74,16 @@ mod tests { assert_eq!(original, decoded); } + + #[test] + pub fn test_empty_signature() { + let sig = Signature::empty_signature(); + + let sig_as_bytes: Vec = sig.as_raw().as_bytes(); + + assert_eq!(sig_as_bytes.len(), 97); + for one_byte in sig_as_bytes.iter() { + assert_eq!(*one_byte, 0); + } + } } diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index 4ac9d7924..9dd5089ba 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -13,7 +13,7 @@ pub fn process_deposit( state: &mut BeaconState, deposit: &Deposit, spec: &ChainSpec, -) -> Result { +) -> Result<(), ValidatorInductionError> { let deposit_input = &deposit.deposit_data.deposit_input; let deposit_data = &deposit.deposit_data; @@ -33,7 +33,7 @@ pub fn process_deposit( == deposit_input.withdrawal_credentials { state.validator_balances[i] += deposit_data.value; - return Ok(i); + return Ok(()); } Err(ValidatorInductionError::InvalidWithdrawalCredentials) @@ -43,39 +43,26 @@ pub fn process_deposit( pubkey: deposit_input.pubkey.clone(), withdrawal_credentials: deposit_input.withdrawal_credentials, randao_commitment: deposit_input.randao_commitment, + randao_layers: 0, + activation_slot: spec.far_future_slot, + exit_slot: spec.far_future_slot, + withdrawal_slot: spec.far_future_slot, + penalized_slot: spec.far_future_slot, + exit_count: 0, + status_flags: None, custody_commitment: deposit_input.custody_commitment, latest_custody_reseed_slot: 0, penultimate_custody_reseed_slot: 0, - ..std::default::Default::default() }; - match min_empty_validator_index(state, spec) { - Some(i) => { - state.validator_registry[i] = validator; - state.validator_balances[i] = deposit_data.value; - Ok(i) - } - None => { - state.validator_registry.push(validator); - state.validator_balances.push(deposit_data.value); - Ok(state.validator_registry.len() - 1) - } - } + let _index = state.validator_registry.len(); + state.validator_registry.push(validator); + state.validator_balances.push(deposit_data.value); + Ok(()) } } } -// NOTE: this has been modified from the spec to get tests working -// this function is no longer used in the latest spec so this is simply a transition step -fn min_empty_validator_index(state: &BeaconState, _spec: &ChainSpec) -> Option { - for i in 0..state.validator_registry.len() { - if state.validator_balances[i] == 0 { - return Some(i); - } - } - None -} - #[cfg(test)] mod tests { use super::*; @@ -120,7 +107,7 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); - assert_eq!(result.unwrap(), 0); + assert_eq!(result.unwrap(), ()); assert!(deposit_equals_record( &deposit, &state.validator_registry[0] @@ -138,7 +125,7 @@ mod tests { let mut deposit = get_deposit(); let result = process_deposit(&mut state, &deposit, &spec); deposit.deposit_data.value = DEPOSIT_GWEI; - assert_eq!(result.unwrap(), i); + assert_eq!(result.unwrap(), ()); assert!(deposit_equals_record( &deposit, &state.validator_registry[i] @@ -167,7 +154,7 @@ mod tests { let result = process_deposit(&mut state, &deposit, &spec); - assert_eq!(result.unwrap(), 0); + assert_eq!(result.unwrap(), ()); assert!(deposit_equals_record( &deposit, &state.validator_registry[0] @@ -177,31 +164,6 @@ mod tests { assert_eq!(state.validator_balances.len(), 1); } - #[test] - fn test_process_deposit_replace_validator() { - let mut state = BeaconState::default(); - let spec = ChainSpec::foundation(); - - let validator = get_validator(); - state.validator_registry.push(validator); - state.validator_balances.push(0); - - let mut deposit = get_deposit(); - deposit.deposit_data.value = DEPOSIT_GWEI; - state.slot = spec.zero_balance_validator_ttl; - - let result = process_deposit(&mut state, &deposit, &spec); - - assert_eq!(result.unwrap(), 0); - assert!(deposit_equals_record( - &deposit, - &state.validator_registry[0] - )); - assert_eq!(state.validator_balances[0], DEPOSIT_GWEI); - assert_eq!(state.validator_registry.len(), 1); - assert_eq!(state.validator_balances.len(), 1); - } - #[test] fn test_process_deposit_invalid_proof_of_possession() { let mut state = BeaconState::default();