Merge pull request #159 from sigp/spec-updates

Spec updates
This commit is contained in:
Paul Hauner 2019-01-22 09:11:21 +11:00 committed by GitHub
commit 289f4a7b21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 185 additions and 106 deletions

View File

@ -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());
}
}

View File

@ -21,7 +21,7 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result<BeaconState, Error> {
};
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<BeaconState, Error> {
/*
* 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<BeaconState, Error> {
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<BeaconState, Error> {
/*
* 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
*/

View File

@ -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<ValidatorRecord> {
};
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);
}

View File

@ -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
*/

View File

@ -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<T: RngCore> TestRandom<T> 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);
}
}

View File

@ -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<Hash256>,
pub latest_vdf_outputs: Vec<Hash256>,
pub shard_committees_at_slots: Vec<Vec<ShardCommittee>>,
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<CustodyChallenge>,
@ -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<T: RngCore> TestRandom<T> 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),

View File

@ -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,

View File

@ -159,12 +159,15 @@ impl<T: RngCore> TestRandom<T> 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()
}
}
}

View File

@ -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<u8> = 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<u8> = 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);
}
}
}

View File

@ -13,7 +13,7 @@ pub fn process_deposit(
state: &mut BeaconState,
deposit: &Deposit,
spec: &ChainSpec,
) -> Result<usize, ValidatorInductionError> {
) -> 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,38 +43,25 @@ 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 => {
let _index = state.validator_registry.len();
state.validator_registry.push(validator);
state.validator_balances.push(deposit_data.value);
Ok(state.validator_registry.len() - 1)
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<usize> {
for i in 0..state.validator_registry.len() {
if state.validator_balances[i] == 0 {
return Some(i);
}
}
None
}
#[cfg(test)]
mod tests {
@ -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();