Skip to content

Commit 205dbe0

Browse files
spike
1 parent 38d2305 commit 205dbe0

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

consensus/src/marshal/ancestry.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use futures::{
99
};
1010
use pin_project::pin_project;
1111
use std::{
12+
collections::VecDeque,
1213
future::Future,
1314
pin::Pin,
1415
sync::Arc,
@@ -22,6 +23,39 @@ pub trait Ancestry<B: Block>: Stream<Item = B> + Send + Unpin + 'static {
2223
fn peek(&self) -> Option<&B>;
2324
}
2425

26+
/// Creates an ancestry stream from a fixed sequence of blocks.
27+
///
28+
/// Blocks are yielded in iterator order and no parent fetching is performed. This is useful when
29+
/// the caller already has the complete ancestry needed by an application.
30+
pub fn from_iter<B>(blocks: impl IntoIterator<Item = B>) -> impl Ancestry<B>
31+
where
32+
B: Block,
33+
{
34+
BoundedAncestry {
35+
blocks: blocks.into_iter().collect(),
36+
}
37+
}
38+
39+
struct BoundedAncestry<B: Block> {
40+
blocks: VecDeque<B>,
41+
}
42+
43+
impl<B: Block> Unpin for BoundedAncestry<B> {}
44+
45+
impl<B: Block> Ancestry<B> for BoundedAncestry<B> {
46+
fn peek(&self) -> Option<&B> {
47+
self.blocks.front()
48+
}
49+
}
50+
51+
impl<B: Block> Stream for BoundedAncestry<B> {
52+
type Item = B;
53+
54+
fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
55+
Poll::Ready(self.blocks.pop_front())
56+
}
57+
}
58+
2559
/// An interface for providing parent blocks.
2660
pub trait BlockProvider: Send + 'static {
2761
/// The block type the provider walks.
@@ -384,6 +418,34 @@ mod test {
384418
});
385419
}
386420

421+
#[test]
422+
fn test_from_iter_available_through_ancestry_trait() {
423+
fn peek_height(ancestry: impl Ancestry<Block<Sha256Digest, ()>>) -> Option<Height> {
424+
ancestry.peek().map(Heightable::height)
425+
}
426+
427+
let block = Block::new::<Sha256>((), Sha256Digest::EMPTY, Height::new(1), 1);
428+
let ancestry = from_iter([block.clone()]);
429+
430+
assert_eq!(peek_height(ancestry), Some(block.height()));
431+
}
432+
433+
#[test]
434+
fn test_from_iter_yields_blocks_in_order_and_peeks_next() {
435+
deterministic::Runner::default().start(|_| async move {
436+
let parent = Block::new::<Sha256>((), Sha256Digest::EMPTY, Height::new(1), 1);
437+
let child = Block::new::<Sha256>((), parent.digest(), Height::new(2), 2);
438+
let mut ancestry = from_iter([child.clone(), parent.clone()]);
439+
440+
assert_eq!(ancestry.peek(), Some(&child));
441+
assert_eq!(ancestry.next().await, Some(child));
442+
assert_eq!(ancestry.peek(), Some(&parent));
443+
assert_eq!(ancestry.next().await, Some(parent));
444+
assert_eq!(ancestry.peek(), None);
445+
assert_eq!(ancestry.next().await, None);
446+
});
447+
}
448+
387449
#[test]
388450
fn test_yields_genesis_and_stops() {
389451
deterministic::Runner::default().start(|context| async move {

0 commit comments

Comments
 (0)