diff --git a/consensus/proto_array/src/bin.rs b/consensus/proto_array/src/bin.rs index ba83714ce77..e1d307affb4 100644 --- a/consensus/proto_array/src/bin.rs +++ b/consensus/proto_array/src/bin.rs @@ -6,6 +6,18 @@ fn main() { write_test_def_to_yaml("no_votes.yaml", get_no_votes_test_definition()); write_test_def_to_yaml("ffg_01.yaml", get_ffg_case_01_test_definition()); write_test_def_to_yaml("ffg_02.yaml", get_ffg_case_02_test_definition()); + write_test_def_to_yaml( + "execution_status_01.yaml", + get_execution_status_test_definition_01(), + ); + write_test_def_to_yaml( + "execution_status_02.yaml", + get_execution_status_test_definition_02(), + ); + write_test_def_to_yaml( + "execution_status_03.yaml", + get_execution_status_test_definition_03(), + ); } fn write_test_def_to_yaml(filename: &str, def: ForkChoiceTestDefinition) { diff --git a/consensus/proto_array/src/fork_choice_test_definition.rs b/consensus/proto_array/src/fork_choice_test_definition.rs index e28fc67718f..fd90d539037 100644 --- a/consensus/proto_array/src/fork_choice_test_definition.rs +++ b/consensus/proto_array/src/fork_choice_test_definition.rs @@ -1,11 +1,16 @@ +mod execution_status; mod ffg_updates; mod no_votes; mod votes; use crate::proto_array_fork_choice::{Block, ExecutionStatus, ProtoArrayForkChoice}; use serde_derive::{Deserialize, Serialize}; -use types::{AttestationShufflingId, Checkpoint, Epoch, EthSpec, Hash256, MainnetEthSpec, Slot}; +use types::{ + AttestationShufflingId, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, Hash256, + MainnetEthSpec, Slot, +}; +pub use execution_status::*; pub use ffg_updates::*; pub use no_votes::*; pub use votes::*; @@ -18,6 +23,13 @@ pub enum Operation { justified_state_balances: Vec, expected_head: Hash256, }, + ProposerBoostFindHead { + justified_checkpoint: Checkpoint, + finalized_checkpoint: Checkpoint, + justified_state_balances: Vec, + expected_head: Hash256, + proposer_boost_root: Hash256, + }, InvalidFindHead { justified_checkpoint: Checkpoint, finalized_checkpoint: Checkpoint, @@ -40,6 +52,14 @@ pub enum Operation { prune_threshold: usize, expected_len: usize, }, + InvalidatePayload { + head_block_root: Hash256, + latest_valid_ancestor_root: Option, + }, + AssertWeight { + block_root: Hash256, + weight: u64, + }, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -52,9 +72,11 @@ pub struct ForkChoiceTestDefinition { impl ForkChoiceTestDefinition { pub fn run(self) { + let mut spec = MainnetEthSpec::default_spec(); + spec.proposer_score_boost = Some(50); + let junk_shuffling_id = AttestationShufflingId::from_components(Epoch::new(0), Hash256::zero()); - let execution_status = ExecutionStatus::irrelevant(); let mut fork_choice = ProtoArrayForkChoice::new( self.finalized_block_slot, Hash256::zero(), @@ -62,7 +84,7 @@ impl ForkChoiceTestDefinition { self.finalized_checkpoint, junk_shuffling_id.clone(), junk_shuffling_id, - execution_status, + ExecutionStatus::Unknown(ExecutionBlockHash::zero()), ) .expect("should create fork choice struct"); @@ -80,7 +102,7 @@ impl ForkChoiceTestDefinition { finalized_checkpoint, &justified_state_balances, Hash256::zero(), - &MainnetEthSpec::default_spec(), + &spec, ) .map_err(|e| e) .unwrap_or_else(|e| { @@ -89,7 +111,34 @@ impl ForkChoiceTestDefinition { assert_eq!( head, expected_head, - "Operation at index {} failed checks. Operation: {:?}", + "Operation at index {} failed head check. Operation: {:?}", + op_index, op + ); + check_bytes_round_trip(&fork_choice); + } + Operation::ProposerBoostFindHead { + justified_checkpoint, + finalized_checkpoint, + justified_state_balances, + expected_head, + proposer_boost_root, + } => { + let head = fork_choice + .find_head::( + justified_checkpoint, + finalized_checkpoint, + &justified_state_balances, + proposer_boost_root, + &spec, + ) + .map_err(|e| e) + .unwrap_or_else(|e| { + panic!("find_head op at index {} returned error {}", op_index, e) + }); + + assert_eq!( + head, expected_head, + "Operation at index {} failed head check. Operation: {:?}", op_index, op ); check_bytes_round_trip(&fork_choice); @@ -104,7 +153,7 @@ impl ForkChoiceTestDefinition { finalized_checkpoint, &justified_state_balances, Hash256::zero(), - &MainnetEthSpec::default_spec(), + &spec, ); assert!( @@ -138,7 +187,10 @@ impl ForkChoiceTestDefinition { ), justified_checkpoint, finalized_checkpoint, - execution_status, + // All blocks are imported optimistically. + execution_status: ExecutionStatus::Unknown(ExecutionBlockHash::from_root( + root, + )), }; fork_choice.process_block(block).unwrap_or_else(|e| { panic!( @@ -183,22 +235,41 @@ impl ForkChoiceTestDefinition { expected_len ); } + Operation::InvalidatePayload { + head_block_root, + latest_valid_ancestor_root, + } => fork_choice + .process_execution_payload_invalidation( + head_block_root, + latest_valid_ancestor_root, + ) + .unwrap(), + Operation::AssertWeight { block_root, weight } => assert_eq!( + fork_choice.get_weight(&block_root).unwrap(), + weight, + "block weight" + ), } } } } -/// Gives a hash that is not the zero hash (unless i is `usize::max_value)`. -fn get_hash(i: u64) -> Hash256 { +/// Gives a root that is not the zero hash (unless i is `usize::max_value)`. +fn get_root(i: u64) -> Hash256 { Hash256::from_low_u64_be(i + 1) } +/// Gives a hash that is not the zero hash (unless i is `usize::max_value)`. +fn get_hash(i: u64) -> ExecutionBlockHash { + ExecutionBlockHash::from_root(get_root(i)) +} + /// Gives a checkpoint with a root that is not the zero hash (unless i is `usize::max_value)`. /// `Epoch` will always equal `i`. fn get_checkpoint(i: u64) -> Checkpoint { Checkpoint { epoch: Epoch::new(i), - root: get_hash(i), + root: get_root(i), } } diff --git a/consensus/proto_array/src/fork_choice_test_definition/execution_status.rs b/consensus/proto_array/src/fork_choice_test_definition/execution_status.rs new file mode 100644 index 00000000000..f1b0e512d7d --- /dev/null +++ b/consensus/proto_array/src/fork_choice_test_definition/execution_status.rs @@ -0,0 +1,1092 @@ +use super::*; + +pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition { + let balances = vec![1; 2]; + let mut ops = vec![]; + + // Ensure that the head starts at the finalized block. + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(0), + }); + + // Add a block with a hash of 2. + // + // 0 + // / + // 2 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(2), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is 2 + // + // 0 + // / + // head-> 2 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a block with a hash of 1 that comes off the genesis block (this is a fork compared + // to the previous block). + // + // 0 + // / \ + // 2 1 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(1), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a vote to block 1 + // + // 0 + // / \ + // 2 1 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 0, + block_root: get_root(1), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is now 1, because 1 has a vote. + // + // 0 + // / \ + // 2 1 <- head + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(1), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + + // Add a vote to block 2 + // + // 0 + // / \ + // +vote-> 2 1 + ops.push(Operation::ProcessAttestation { + validator_index: 1, + block_root: get_root(2), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is 2 since 1 and 2 both have a vote + // + // 0 + // / \ + // head-> 2 1 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + + // Add block 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 + ops.push(Operation::ProcessBlock { + slot: Slot::new(2), + root: get_root(3), + parent_root: get_root(1), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + // | + // 3 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + // Move validator #0 vote from 1 to 3 + // + // 0 + // / \ + // 2 1 <- -vote + // | + // 3 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 0, + block_root: get_root(3), + target_epoch: Epoch::new(3), + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + // | + // 3 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 1, + }); + + // Invalidate the payload of 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 <- INVALID + ops.push(Operation::InvalidatePayload { + head_block_root: get_root(3), + latest_valid_ancestor_root: Some(get_hash(1)), + }); + + // Ensure that the head is still 2. + // + // 0 + // / \ + // head-> 2 1 + // | + // 3 <- INVALID + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Invalidation of 3 should have removed upstream weight. + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 1, + }); + // Invalidation of 3 should have removed upstream weight. + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 0, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + // Invalidation should have removed weight. + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + // Move a vote from 2 to 1. This is slashable, but that's not relevant here. + // + // 0 + // / \ + // -vote-> 2 1 <- +vote + // | + // 3 <- INVALID + ops.push(Operation::ProcessAttestation { + validator_index: 1, + block_root: get_root(1), + target_epoch: Epoch::new(3), + }); + + // Ensure that the head has switched back to 1 + // + // 0 + // / \ + // 2 1 <-head + // | + // 3 <- INVALID + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances, + expected_head: get_root(1), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + // Invalidation should have removed weight. + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + ForkChoiceTestDefinition { + finalized_block_slot: Slot::new(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + operations: ops, + } +} + +pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition { + let balances = vec![1; 2]; + let mut ops = vec![]; + + // Ensure that the head starts at the finalized block. + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(0), + }); + + // Add a block with a hash of 2. + // + // 0 + // / + // 2 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(2), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is 2 + // + // 0 + // / + // head-> 2 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a block with a hash of 1 that comes off the genesis block (this is a fork compared + // to the previous block). + // + // 0 + // / \ + // 2 1 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(1), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a vote to block 1 + // + // 0 + // / \ + // 2 1 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 0, + block_root: get_root(1), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is now 1, because 1 has a vote. + // + // 0 + // / \ + // 2 1 <- head + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(1), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + + // Add a vote to block 2 + // + // 0 + // / \ + // +vote-> 2 1 + ops.push(Operation::ProcessAttestation { + validator_index: 1, + block_root: get_root(2), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is 2 since 1 and 2 both have a vote + // + // 0 + // / \ + // head-> 2 1 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + + // Add block 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 + ops.push(Operation::ProcessBlock { + slot: Slot::new(2), + root: get_root(3), + parent_root: get_root(1), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + // | + // 3 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 1, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + // Move validator #0 vote from 1 to 3 + // + // 0 + // / \ + // 2 1 <- -vote + // | + // 3 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 0, + block_root: get_root(3), + target_epoch: Epoch::new(3), + }); + + // Move validator #1 vote from 2 to 3 + // + // 0 + // / \ + // -vote->2 1 + // | + // 3 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 1, + block_root: get_root(3), + target_epoch: Epoch::new(3), + }); + + // Ensure that the head is now 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 <-head + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(3), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 2, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 2, + }); + + // Invalidate the payload of 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 <- INVALID + ops.push(Operation::InvalidatePayload { + head_block_root: get_root(3), + latest_valid_ancestor_root: Some(get_hash(1)), + }); + + // Ensure that the head is now 2. + // + // 0 + // / \ + // head-> 2 1 + // | + // 3 <- INVALID + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances, + expected_head: get_root(2), + }); + + // Invalidation of 3 should have removed upstream weight. + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 0, + }); + // Invalidation of 3 should have removed upstream weight. + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 0, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + // Invalidation should have removed weight. + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + ForkChoiceTestDefinition { + finalized_block_slot: Slot::new(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + operations: ops, + } +} + +pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition { + let balances = vec![1_000; 2_000]; + let mut ops = vec![]; + + // Ensure that the head starts at the finalized block. + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(0), + }); + + // Add a block with a hash of 2. + // + // 0 + // / + // 2 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(2), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is 2 + // + // 0 + // / + // head-> 2 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a block with a hash of 1 that comes off the genesis block (this is a fork compared + // to the previous block). + // + // 0 + // / \ + // 2 1 + ops.push(Operation::ProcessBlock { + slot: Slot::new(1), + root: get_root(1), + parent_root: get_root(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is still 2 + // + // 0 + // / \ + // head-> 2 1 + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(2), + }); + + // Add a vote to block 1 + // + // 0 + // / \ + // 2 1 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 0, + block_root: get_root(1), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is now 1, because 1 has a vote. + // + // 0 + // / \ + // 2 1 <- head + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(1), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 1_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 1_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + + // Add another vote to 1 + // + // 0 + // / \ + // 2 1 <- +vote + ops.push(Operation::ProcessAttestation { + validator_index: 1, + block_root: get_root(1), + target_epoch: Epoch::new(2), + }); + + // Ensure that the head is 1. + // + // 0 + // / \ + // 2 1 <- head + ops.push(Operation::FindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(1), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 2_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + + // Add block 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 + ops.push(Operation::ProcessBlock { + slot: Slot::new(2), + root: get_root(3), + parent_root: get_root(1), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + }); + + // Ensure that the head is now 3, applying a proposer boost to 3 as well. + // + // 0 + // / \ + // 2 1 + // | + // 3 <- head + ops.push(Operation::ProposerBoostFindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances.clone(), + expected_head: get_root(3), + proposer_boost_root: get_root(3), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 33_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 33_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(3), + // This is a "magic number" generated from `calculate_proposer_boost`. + weight: 31_000, + }); + + // Invalidate the payload of 3. + // + // 0 + // / \ + // 2 1 + // | + // 3 <- INVALID + ops.push(Operation::InvalidatePayload { + head_block_root: get_root(3), + latest_valid_ancestor_root: Some(get_hash(1)), + }); + + // Ensure that the head is now 1, maintaining the proposer boost on the invalid block. + // + // 0 + // / \ + // 2 1 <- head + // | + // 3 <- INVALID + ops.push(Operation::ProposerBoostFindHead { + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + justified_state_balances: balances, + expected_head: get_root(1), + proposer_boost_root: get_root(3), + }); + + ops.push(Operation::AssertWeight { + block_root: get_root(0), + weight: 2_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(1), + weight: 2_000, + }); + ops.push(Operation::AssertWeight { + block_root: get_root(2), + weight: 0, + }); + // The proposer boost should be reverted due to the invalid payload. + ops.push(Operation::AssertWeight { + block_root: get_root(3), + weight: 0, + }); + + ForkChoiceTestDefinition { + finalized_block_slot: Slot::new(0), + justified_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + finalized_checkpoint: Checkpoint { + epoch: Epoch::new(1), + root: get_root(0), + }, + operations: ops, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_01() { + let test = get_execution_status_test_definition_01(); + test.run(); + } + + #[test] + fn test_02() { + let test = get_execution_status_test_definition_02(); + test.run(); + } + + #[test] + fn test_03() { + let test = get_execution_status_test_definition_03(); + test.run(); + } +} diff --git a/consensus/proto_array/src/fork_choice_test_definition/ffg_updates.rs b/consensus/proto_array/src/fork_choice_test_definition/ffg_updates.rs index a129064504d..77211a86a7d 100644 --- a/consensus/proto_array/src/fork_choice_test_definition/ffg_updates.rs +++ b/consensus/proto_array/src/fork_choice_test_definition/ffg_updates.rs @@ -9,7 +9,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(0), + expected_head: get_root(0), }); // Build the following tree (stick? lol). @@ -23,22 +23,22 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition { // 3 <- just: 2, fin: 1 ops.push(Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(1), - parent_root: get_hash(0), + root: get_root(1), + parent_root: get_root(0), justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(2), - parent_root: get_hash(1), + root: get_root(2), + parent_root: get_root(1), justified_checkpoint: get_checkpoint(1), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(3), - root: get_hash(3), - parent_root: get_hash(2), + root: get_root(3), + parent_root: get_root(2), justified_checkpoint: get_checkpoint(2), finalized_checkpoint: get_checkpoint(1), }); @@ -56,7 +56,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(3), + expected_head: get_root(3), }); // Ensure that with justified epoch 1 we find 2 @@ -72,7 +72,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(1), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Ensure that with justified epoch 2 we find 3 @@ -88,7 +88,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(2), finalized_checkpoint: get_checkpoint(1), justified_state_balances: balances, - expected_head: get_hash(3), + expected_head: get_root(3), }); // END OF TESTS @@ -109,7 +109,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(0), + expected_head: get_root(0), }); // Build the following tree. @@ -129,48 +129,48 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { // Left branch ops.push(Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(1), - parent_root: get_hash(0), + root: get_root(1), + parent_root: get_root(0), justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(3), - parent_root: get_hash(1), + root: get_root(3), + parent_root: get_root(1), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(1), + root: get_root(1), }, finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(3), - root: get_hash(5), - parent_root: get_hash(3), + root: get_root(5), + parent_root: get_root(3), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(1), + root: get_root(1), }, finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(4), - root: get_hash(7), - parent_root: get_hash(5), + root: get_root(7), + parent_root: get_root(5), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(1), + root: get_root(1), }, finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(5), - root: get_hash(9), - parent_root: get_hash(7), + root: get_root(9), + parent_root: get_root(7), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(3), + root: get_root(3), }, finalized_checkpoint: get_checkpoint(0), }); @@ -178,42 +178,42 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { // Right branch ops.push(Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(2), - parent_root: get_hash(0), + root: get_root(2), + parent_root: get_root(0), justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(4), - parent_root: get_hash(2), + root: get_root(4), + parent_root: get_root(2), justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(3), - root: get_hash(6), - parent_root: get_hash(4), + root: get_root(6), + parent_root: get_root(4), justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(4), - root: get_hash(8), - parent_root: get_hash(6), + root: get_root(8), + parent_root: get_root(6), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(2), + root: get_root(2), }, finalized_checkpoint: get_checkpoint(0), }); ops.push(Operation::ProcessBlock { slot: Slot::new(5), - root: get_hash(10), - parent_root: get_hash(8), + root: get_root(10), + parent_root: get_root(8), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(4), + root: get_root(4), }, finalized_checkpoint: get_checkpoint(0), }); @@ -235,23 +235,23 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above, but with justified epoch 2. ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(4), + root: get_root(4), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above, but with justified epoch 3 (should be invalid). ops.push(Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(3), - root: get_hash(6), + root: get_root(6), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), @@ -272,7 +272,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { // 9 10 ops.push(Operation::ProcessAttestation { validator_index: 0, - block_root: get_hash(1), + block_root: get_root(1), target_epoch: Epoch::new(0), }); @@ -293,23 +293,23 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Save as above but justified epoch 2. ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(3), + root: get_root(3), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Save as above but justified epoch 3 (should fail). ops.push(Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(3), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), @@ -330,7 +330,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { // 9 10 ops.push(Operation::ProcessAttestation { validator_index: 1, - block_root: get_hash(2), + block_root: get_root(2), target_epoch: Epoch::new(0), }); @@ -351,23 +351,23 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above but justified epoch 2. ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(4), + root: get_root(4), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above but justified epoch 3 (should fail). ops.push(Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(3), - root: get_hash(6), + root: get_root(6), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), @@ -389,27 +389,27 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(0), - root: get_hash(1), + root: get_root(1), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Same as above but justified epoch 2. ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(3), + root: get_root(3), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Same as above but justified epoch 3 (should fail). ops.push(Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(3), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), @@ -432,23 +432,23 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition { justified_checkpoint: get_checkpoint(0), finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above but justified epoch 2. ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(4), + root: get_root(4), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Same as above but justified epoch 3 (should fail). ops.push(Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(3), - root: get_hash(6), + root: get_root(6), }, finalized_checkpoint: get_checkpoint(0), justified_state_balances: balances, diff --git a/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs b/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs index 0fbcafc5d4a..a60b3e6b368 100644 --- a/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs +++ b/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs @@ -24,7 +24,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 2 Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(2), + root: get_root(2), parent_root: Hash256::zero(), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), @@ -50,7 +50,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }, // Add block 1 // @@ -59,8 +59,8 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 2 1 Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(1), - parent_root: get_hash(0), + root: get_root(1), + parent_root: get_root(0), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), root: Hash256::zero(), @@ -85,7 +85,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }, // Add block 3 // @@ -96,8 +96,8 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 3 Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(3), - parent_root: get_hash(1), + root: get_root(3), + parent_root: get_root(1), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), root: Hash256::zero(), @@ -124,7 +124,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }, // Add block 4 // @@ -135,8 +135,8 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 4 3 Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(4), - parent_root: get_hash(2), + root: get_root(4), + parent_root: get_root(2), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), root: Hash256::zero(), @@ -163,7 +163,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(4), + expected_head: get_root(4), }, // Add block 5 with a justified epoch of 2 // @@ -176,8 +176,8 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 5 <- justified epoch = 2 Operation::ProcessBlock { slot: Slot::new(3), - root: get_hash(5), - parent_root: get_hash(4), + root: get_root(5), + parent_root: get_root(4), justified_checkpoint: get_checkpoint(2), finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), @@ -203,7 +203,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(4), + expected_head: get_root(4), }, // Ensure there is an error when starting from a block that has the wrong justified epoch. // @@ -217,7 +217,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { Operation::InvalidFindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), @@ -241,7 +241,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances.clone(), - expected_head: get_hash(5), + expected_head: get_root(5), }, // Add block 6 // @@ -256,8 +256,8 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { // 6 Operation::ProcessBlock { slot: Slot::new(4), - root: get_hash(6), - parent_root: get_hash(5), + root: get_root(6), + parent_root: get_root(5), justified_checkpoint: get_checkpoint(2), finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), @@ -282,7 +282,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition { root: Hash256::zero(), }, justified_state_balances: balances, - expected_head: get_hash(6), + expected_head: get_root(6), }, ]; diff --git a/consensus/proto_array/src/fork_choice_test_definition/votes.rs b/consensus/proto_array/src/fork_choice_test_definition/votes.rs index f65177a8497..58ac6af60ba 100644 --- a/consensus/proto_array/src/fork_choice_test_definition/votes.rs +++ b/consensus/proto_array/src/fork_choice_test_definition/votes.rs @@ -8,14 +8,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(0), + expected_head: get_root(0), }); // Add a block with a hash of 2. @@ -25,15 +25,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 2 ops.push(Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(2), - parent_root: get_hash(0), + root: get_root(2), + parent_root: get_root(0), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, }); @@ -45,14 +45,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Add a block with a hash of 1 that comes off the genesis block (this is a fork compared @@ -63,15 +63,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 2 1 ops.push(Operation::ProcessBlock { slot: Slot::new(1), - root: get_hash(1), - parent_root: get_hash(0), + root: get_root(1), + parent_root: get_root(0), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, }); @@ -83,14 +83,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Add a vote to block 1 @@ -100,7 +100,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 2 1 <- +vote ops.push(Operation::ProcessAttestation { validator_index: 0, - block_root: get_hash(1), + block_root: get_root(1), target_epoch: Epoch::new(2), }); @@ -112,14 +112,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(1), + expected_head: get_root(1), }); // Add a vote to block 2 @@ -129,7 +129,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // +vote-> 2 1 ops.push(Operation::ProcessAttestation { validator_index: 1, - block_root: get_hash(2), + block_root: get_root(2), target_epoch: Epoch::new(2), }); @@ -141,14 +141,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Add block 3. @@ -160,15 +160,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 3 ops.push(Operation::ProcessBlock { slot: Slot::new(2), - root: get_hash(3), - parent_root: get_hash(1), + root: get_root(3), + parent_root: get_root(1), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, }); @@ -182,14 +182,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Move validator #0 vote from 1 to 3 @@ -201,7 +201,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 3 <- +vote ops.push(Operation::ProcessAttestation { validator_index: 0, - block_root: get_hash(3), + block_root: get_root(3), target_epoch: Epoch::new(3), }); @@ -215,14 +215,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(2), + expected_head: get_root(2), }); // Move validator #1 vote from 2 to 1 (this is an equivocation, but fork choice doesn't @@ -235,7 +235,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 3 ops.push(Operation::ProcessAttestation { validator_index: 1, - block_root: get_hash(1), + block_root: get_root(1), target_epoch: Epoch::new(3), }); @@ -249,14 +249,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(3), + expected_head: get_root(3), }); // Add block 4. @@ -270,15 +270,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 4 ops.push(Operation::ProcessBlock { slot: Slot::new(3), - root: get_hash(4), - parent_root: get_hash(3), + root: get_root(4), + parent_root: get_root(3), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, }); @@ -294,14 +294,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(4), + expected_head: get_root(4), }); // Add block 5, which has a justified epoch of 2. @@ -317,15 +317,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 5 <- justified epoch = 2 ops.push(Operation::ProcessBlock { slot: Slot::new(4), - root: get_hash(5), - parent_root: get_hash(4), + root: get_root(5), + parent_root: get_root(4), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(1), + root: get_root(1), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(1), + root: get_root(1), }, }); @@ -343,14 +343,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(4), + expected_head: get_root(4), }); // Add block 6, which has a justified epoch of 0. @@ -366,15 +366,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 5 6 <- justified epoch = 0 ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(6), - parent_root: get_hash(4), + root: get_root(6), + parent_root: get_root(4), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, }); @@ -391,12 +391,12 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // +2 vote-> 5 6 ops.push(Operation::ProcessAttestation { validator_index: 0, - block_root: get_hash(5), + block_root: get_root(5), target_epoch: Epoch::new(4), }); ops.push(Operation::ProcessAttestation { validator_index: 1, - block_root: get_hash(5), + block_root: get_root(5), target_epoch: Epoch::new(4), }); @@ -420,41 +420,41 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 9 ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(7), - parent_root: get_hash(5), + root: get_root(7), + parent_root: get_root(5), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, }); ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(8), - parent_root: get_hash(7), + root: get_root(8), + parent_root: get_root(7), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, }); ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(9), - parent_root: get_hash(8), + root: get_root(9), + parent_root: get_root(8), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, }); @@ -479,14 +479,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, justified_state_balances: balances.clone(), - expected_head: get_hash(6), + expected_head: get_root(6), }); // Change fork-choice justified epoch to 1, and the start block to 5 and ensure that 9 is @@ -512,14 +512,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Change fork-choice justified epoch to 1, and the start block to 5 and ensure that 9 is @@ -544,12 +544,12 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 9 <- +2 votes ops.push(Operation::ProcessAttestation { validator_index: 0, - block_root: get_hash(9), + block_root: get_root(9), target_epoch: Epoch::new(5), }); ops.push(Operation::ProcessAttestation { validator_index: 1, - block_root: get_hash(9), + block_root: get_root(9), target_epoch: Epoch::new(5), }); @@ -572,15 +572,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 9 10 ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(10), - parent_root: get_hash(8), + root: get_root(10), + parent_root: get_root(8), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, }); @@ -588,14 +588,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Introduce 2 more validators into the system @@ -620,12 +620,12 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 9 10 <- +2 votes ops.push(Operation::ProcessAttestation { validator_index: 2, - block_root: get_hash(10), + block_root: get_root(10), target_epoch: Epoch::new(5), }); ops.push(Operation::ProcessAttestation { validator_index: 3, - block_root: get_hash(10), + block_root: get_root(10), target_epoch: Epoch::new(5), }); @@ -649,14 +649,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Set the balances of the last two validators to zero @@ -674,14 +674,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Set the balances of the last two validators back to 1 @@ -699,14 +699,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(10), + expected_head: get_root(10), }); // Remove the last two validators @@ -725,19 +725,19 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Ensure that pruning below the prune threshold does not prune. ops.push(Operation::Prune { - finalized_root: get_hash(5), + finalized_root: get_root(5), prune_threshold: usize::max_value(), expected_len: 11, }); @@ -746,14 +746,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Ensure that pruning above the prune threshold does prune. @@ -775,7 +775,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // / \ // 9 10 ops.push(Operation::Prune { - finalized_root: get_hash(5), + finalized_root: get_root(5), prune_threshold: 1, expected_len: 6, }); @@ -784,14 +784,14 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances.clone(), - expected_head: get_hash(9), + expected_head: get_root(9), }); // Add block 11 @@ -807,15 +807,15 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { // 11 ops.push(Operation::ProcessBlock { slot: Slot::new(0), - root: get_hash(11), - parent_root: get_hash(9), + root: get_root(11), + parent_root: get_root(9), justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, }); @@ -833,25 +833,25 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition { ops.push(Operation::FindHead { justified_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(2), - root: get_hash(5), + root: get_root(5), }, justified_state_balances: balances, - expected_head: get_hash(11), + expected_head: get_root(11), }); ForkChoiceTestDefinition { finalized_block_slot: Slot::new(0), justified_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, finalized_checkpoint: Checkpoint { epoch: Epoch::new(1), - root: get_hash(0), + root: get_root(0), }, operations: ops, } diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index 1c140f38a2c..1f5b997f670 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -312,6 +312,15 @@ impl ProtoArrayForkChoice { } } + /// Returns the weight of a given block. + pub fn get_weight(&self, block_root: &Hash256) -> Option { + let block_index = self.proto_array.indices.get(block_root)?; + self.proto_array + .nodes + .get(*block_index) + .map(|node| node.weight) + } + /// See `ProtoArray` documentation. pub fn is_descendant(&self, ancestor_root: Hash256, descendant_root: Hash256) -> bool { self.proto_array