diff --git a/src/state/transition/new_active_state.rs b/src/state/transition/new_active_state.rs index bb0e79cb3..748d77552 100644 --- a/src/state/transition/new_active_state.rs +++ b/src/state/transition/new_active_state.rs @@ -7,6 +7,7 @@ use super::block::Block; use super::utils::types::Sha256Digest; use super::utils::logging::Logger; use super::config::Config; +use super::super::pubkeystore::verify_block; use super::rlp; use super::attestors::{ @@ -15,19 +16,33 @@ use super::attestors::{ }; use super::ffg::update_ffg_and_crosslink_progress; +/// Computes the active state generated by applying a new block +/// to a parent block. +/// +/// The `CrystallizedState` and `ActiveState` represented by +/// parent_block.state_hash must also be supplied. +/// +/// # Panics +/// Will panic if the block verification or state transition fails. +/// Some situations may include; signature verification failure or +/// insufficient active validators. pub fn compute_new_active_state( cry_state: &CrystallizedState, act_state: &ActiveState, parent_block: &Block, - block: &Block, + new_block: &Block, config: &Config, log: &Logger) -> ActiveState { + /* + * For the present state pair, determine the proposer and attester + * set for the newly presented block (`new_block`). + */ let (attestation_indicies, proposer) = get_attesters_and_proposer( &cry_state, &act_state, - &block.skip_count, + &new_block.skip_count, &config, &log); @@ -35,41 +50,79 @@ pub fn compute_new_active_state( "attesters_count" => attestation_indicies.len(), "proposer_index" => proposer); + /* + * Ensure that the new_block bitfield accurately represents the + * public keys which have signed the previous block. I.e., for each + * `true` bit in the new_block bitfield, ensure the corresponding + * attester has signed the aggregate signature. + * + * As it is possible for there to be no attesters, an option + * is returned. The option unwraps to a vec of validator indicies + * which attested to the block. + */ let parent_block_rlp = rlp::encode(parent_block); let attesters_option = process_attestations( &cry_state.active_validators, &attestation_indicies, - &block.attestation_bitfield, + &new_block.attestation_bitfield, &parent_block_rlp.to_vec(), - &block.attestation_aggregate_sig); + &new_block.attestation_aggregate_sig); + let attesters = attesters_option.expect("No attesters available."); - - // TODO: bls verify signature here. + /* + * Ensure the new_block has been signed by the proposer dictated + * by the state pair. + */ + let verified = verify_block(&new_block, &proposer); + assert!(verified, "Block sig verification failed."); + info!(log, "verified block signature"; + "proposer_index" => proposer); + + /* + * Collect all the aggregate votes and partial crosslinks + * into a new vec of partial crosslinks. Each entry in this + * new vec will be unique for the "shard_id" field -- each of these + * entries will contain the binary AND of all attestation bitfields + * for that relevant shard_id. + * + * During this process, the aggregate signatures are tested + * against each attester in the respective bitfields (i.e., + * signatures are verified). + * + * Also returned is a count of all validators who attested to a + * shard, as well as a bitfield representing the same thing. + */ let (partial_crosslinks, ffg_voter_bitfield, total_new_voters) = update_ffg_and_crosslink_progress( &cry_state, &act_state.partial_crosslinks, &act_state.ffg_voter_bitfield, - &block.shard_aggregate_votes, + &new_block.shard_aggregate_votes, &config); - let attesters = match attesters_option { - None => panic!("No attestors available"), - Some(x) => x - }; - + /* + * Create a new RecentProposerRecord, with a reward determined + * by: + * + * - The number of attestations to last_block. + * - The number of crosslink attestations present in the + * previous active_state and new_block. + */ let proposer = RecentPropserRecord { index: proposer, randao_commitment: Sha256Digest::zero(), balance_delta: (attesters.len() + total_new_voters) as i64 }; - + + /* + * Determine fields for the new active state, then return it. + */ let height = act_state.height + 1; - let randao = act_state.randao.bitxor(block.randao_reveal); + let randao = act_state.randao.bitxor(new_block.randao_reveal); let mut recent_attesters = act_state.recent_attesters.to_vec(); recent_attesters.extend_from_slice(&attesters); - let total_skip_count = act_state.total_skip_count + block.skip_count; + let total_skip_count = act_state.total_skip_count + new_block.skip_count; let mut recent_proposers = act_state.recent_proposers.to_vec(); recent_proposers.push(proposer); @@ -81,5 +134,4 @@ pub fn compute_new_active_state( partial_crosslinks, total_skip_count, recent_proposers - } -} + } }