From 002be83510e2630668af3796418105c1c8a04f84 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 26 Aug 2020 15:42:48 +1000 Subject: [PATCH] Add tests for block roots --- beacon_node/http_api/tests/tests.rs | 175 ++++++++++++++++++---------- common/eth2/src/lib.rs | 11 ++ 2 files changed, 127 insertions(+), 59 deletions(-) diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index 2a9a9257379..ebb1df24414 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -100,7 +100,57 @@ impl ApiTester { } } - pub async fn test_beacon_state_root(self, state_ids: &[StateId]) -> Self { + fn get_state(&self, state_id: StateId) -> Option> { + match state_id { + StateId::Head => Some(self.chain.head().unwrap().beacon_state), + StateId::Genesis => self + .chain + .get_state(&self.chain.genesis_state_root, None) + .unwrap(), + StateId::Finalized => { + let finalized_slot = self + .chain + .head_info() + .unwrap() + .finalized_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + let root = self + .chain + .state_root_at_slot(finalized_slot) + .unwrap() + .unwrap(); + + self.chain.get_state(&root, Some(finalized_slot)).unwrap() + } + StateId::Justified => { + let justified_slot = self + .chain + .head_info() + .unwrap() + .current_justified_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + let root = self + .chain + .state_root_at_slot(justified_slot) + .unwrap() + .unwrap(); + + self.chain.get_state(&root, Some(justified_slot)).unwrap() + } + StateId::Slot(slot) => { + let root = self.chain.state_root_at_slot(slot).unwrap().unwrap(); + + self.chain.get_state(&root, Some(slot)).unwrap() + } + StateId::Root(root) => self.chain.get_state(&root, None).unwrap(), + } + } + + pub async fn test_beacon_states_root(self, state_ids: &[StateId]) -> Self { for &state_id in state_ids { let result = self .client @@ -144,7 +194,7 @@ impl ApiTester { self } - pub async fn test_beacon_state_fork(self, state_ids: &[StateId]) -> Self { + pub async fn test_beacon_states_fork(self, state_ids: &[StateId]) -> Self { for &state_id in state_ids { let result = self .client @@ -161,57 +211,7 @@ impl ApiTester { self } - fn get_state(&self, state_id: StateId) -> Option> { - match state_id { - StateId::Head => Some(self.chain.head().unwrap().beacon_state), - StateId::Genesis => self - .chain - .get_state(&self.chain.genesis_state_root, None) - .unwrap(), - StateId::Finalized => { - let finalized_slot = self - .chain - .head_info() - .unwrap() - .finalized_checkpoint - .epoch - .start_slot(E::slots_per_epoch()); - - let root = self - .chain - .state_root_at_slot(finalized_slot) - .unwrap() - .unwrap(); - - self.chain.get_state(&root, Some(finalized_slot)).unwrap() - } - StateId::Justified => { - let justified_slot = self - .chain - .head_info() - .unwrap() - .current_justified_checkpoint - .epoch - .start_slot(E::slots_per_epoch()); - - let root = self - .chain - .state_root_at_slot(justified_slot) - .unwrap() - .unwrap(); - - self.chain.get_state(&root, Some(justified_slot)).unwrap() - } - StateId::Slot(slot) => { - let root = self.chain.state_root_at_slot(slot).unwrap().unwrap(); - - self.chain.get_state(&root, Some(slot)).unwrap() - } - StateId::Root(root) => self.chain.get_state(&root, None).unwrap(), - } - } - - pub async fn test_beacon_state_finality_checkpoints(self, state_ids: &[StateId]) -> Self { + pub async fn test_beacon_states_finality_checkpoints(self, state_ids: &[StateId]) -> Self { for &state_id in state_ids { let result = self .client @@ -233,6 +233,40 @@ impl ApiTester { self } + + fn get_block_root(&self, block_id: BlockId) -> Option { + match block_id { + BlockId::Head => Some(self.chain.head_info().unwrap().block_root), + BlockId::Genesis => Some(self.chain.genesis_block_root), + BlockId::Finalized => Some(self.chain.head_info().unwrap().finalized_checkpoint.root), + BlockId::Justified => Some( + self.chain + .head_info() + .unwrap() + .current_justified_checkpoint + .root, + ), + BlockId::Slot(slot) => self.chain.block_root_at_slot(slot).unwrap(), + BlockId::Root(root) => Some(root), + } + } + + pub async fn test_beacon_blocks_root(self, block_ids: &[BlockId]) -> Self { + for &block_id in block_ids { + let result = self + .client + .beacon_blocks_root(block_id) + .await + .unwrap() + .map(|res| res.data.root); + + let expected = self.get_block_root(block_id); + + assert_eq!(result, expected, "{:?}", block_id); + } + + self + } } fn interesting_state_ids() -> Vec { @@ -251,23 +285,46 @@ fn interesting_state_ids() -> Vec { ] } +fn interesting_block_ids() -> Vec { + vec![ + BlockId::Head, + BlockId::Genesis, + BlockId::Finalized, + BlockId::Justified, + BlockId::Slot(Slot::new(0)), + BlockId::Slot(Slot::new(32)), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[0])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[1])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[2])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[3])), + BlockId::Root(Hash256::zero()), + ] +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_root() { + ApiTester::new() + .test_beacon_states_root(&interesting_state_ids()) + .await; +} + #[tokio::test(core_threads = 2)] -async fn beacon_state_root() { +async fn beacon_states_fork() { ApiTester::new() - .test_beacon_state_root(&interesting_state_ids()) + .test_beacon_states_fork(&interesting_state_ids()) .await; } #[tokio::test(core_threads = 2)] -async fn beacon_state_fork() { +async fn beacon_states_finality_checkpoints() { ApiTester::new() - .test_beacon_state_fork(&interesting_state_ids()) + .test_beacon_states_finality_checkpoints(&interesting_state_ids()) .await; } #[tokio::test(core_threads = 2)] -async fn beacon_state_finality_checkpoints() { +async fn beacon_blocks_root() { ApiTester::new() - .test_beacon_state_finality_checkpoints(&interesting_state_ids()) + .test_beacon_blocks_root(&interesting_block_ids()) .await; } diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index d121ea44554..7c1775e9b5d 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -78,4 +78,15 @@ impl BeaconNodeClient { self.get_opt(&format!("beacon/states/{}/finality_checkpoints", state_id)) .await } + + /// `GET beacon/blocks/{block_id}/root` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn beacon_blocks_root( + &self, + block_id: BlockId, + ) -> Result>, Error> { + self.get_opt(&format!("beacon/blocks/{}/root", block_id)) + .await + } }