Update block_store block_at_slot to return trait

This commit is contained in:
Paul Hauner 2019-01-08 17:04:49 +11:00
parent 96f4a30f64
commit feff7d3660
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C

View File

@ -52,23 +52,29 @@ impl<T: ClientDB> BeaconBlockStore<T> {
/// slot number. If the slot is skipped, the function will return None. /// slot number. If the slot is skipped, the function will return None.
/// ///
/// If a block is found, a tuple of (block_hash, serialized_block) is returned. /// If a block is found, a tuple of (block_hash, serialized_block) is returned.
///
/// Note: this function uses a loop instead of recursion as the compiler is over-strict when it
/// comes to recursion and the `impl Trait` pattern. See:
/// https://stackoverflow.com/questions/54032940/using-impl-trait-in-a-recursive-function
pub fn block_at_slot( pub fn block_at_slot(
&self, &self,
head_hash: &Hash256, head_hash: &Hash256,
slot: u64, slot: u64,
) -> Result<Option<(Hash256, BeaconBlock)>, BeaconBlockAtSlotError> { ) -> Result<Option<(Hash256, impl BeaconBlockReader)>, BeaconBlockAtSlotError> {
match self.get_reader(head_hash)? { let mut current_hash = *head_hash;
None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock),
Some(block_reader) => match block_reader.slot() { loop {
s if s == slot => { if let Some(block_reader) = self.get_reader(&current_hash)? {
let block = block_reader if block_reader.slot() == slot {
.into_beacon_block() break Ok(Some((current_hash, block_reader)));
.ok_or(BeaconBlockAtSlotError::InvalidBeaconBlock)?; } else if block_reader.slot() < slot {
Ok(Some((*head_hash, block))) break Ok(None);
} else {
current_hash = block_reader.parent_root();
}
} else {
break Err(BeaconBlockAtSlotError::UnknownBeaconBlock);
} }
s if s < slot => Ok(None),
_ => self.block_at_slot(&block_reader.parent_root(), slot),
},
} }
} }
} }
@ -207,11 +213,12 @@ mod tests {
// Test that certain slots can be reached from certain hashes. // Test that certain slots can be reached from certain hashes.
let test_cases = vec![(4, 4), (4, 3), (4, 2), (4, 1), (4, 0)]; let test_cases = vec![(4, 4), (4, 3), (4, 2), (4, 1), (4, 0)];
for (hashes_index, slot_index) in test_cases { for (hashes_index, slot_index) in test_cases {
let (matched_block_hash, _) = bs let (matched_block_hash, reader) = bs
.block_at_slot(&hashes[hashes_index], slots[slot_index]) .block_at_slot(&hashes[hashes_index], slots[slot_index])
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert_eq!(matched_block_hash, hashes[slot_index]); assert_eq!(matched_block_hash, hashes[slot_index]);
assert_eq!(reader.slot(), slots[slot_index]);
} }
let ssz = bs.block_at_slot(&hashes[4], 2).unwrap(); let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();