-use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, UnboundedCache};
+use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, UnboundedCache};
use crate::poll::{Validate, ValidatedBlockHeader};
use bitcoin::blockdata::block::{Block, BlockHeader};
without_blocks: Option<std::ops::RangeFrom<usize>>,
without_headers: bool,
malformed_headers: bool,
+ filtered_blocks: bool,
}
impl Blockchain {
Self { malformed_headers: true, ..self }
}
+ pub fn filtered_blocks(self) -> Self {
+ Self { filtered_blocks: true, ..self }
+ }
+
pub fn fork_at_height(&self, height: usize) -> Self {
assert!(height + 1 < self.blocks.len());
let mut blocks = self.blocks.clone();
})
}
- fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+ fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> {
Box::pin(async move {
for (height, block) in self.blocks.iter().enumerate() {
if block.header.block_hash() == *header_hash {
}
}
- return Ok(block.clone());
+ if self.filtered_blocks {
+ return Ok(BlockData::HeaderOnly(block.header.clone()));
+ } else {
+ return Ok(BlockData::FullBlock(block.clone()));
+ }
}
}
Err(BlockSourceError::transient("block not found"))
pub struct MockChainListener {
expected_blocks_connected: RefCell<VecDeque<BlockHeaderData>>,
+ expected_filtered_blocks_connected: RefCell<VecDeque<BlockHeaderData>>,
expected_blocks_disconnected: RefCell<VecDeque<BlockHeaderData>>,
}
pub fn new() -> Self {
Self {
expected_blocks_connected: RefCell::new(VecDeque::new()),
+ expected_filtered_blocks_connected: RefCell::new(VecDeque::new()),
expected_blocks_disconnected: RefCell::new(VecDeque::new()),
}
}
self
}
+ pub fn expect_filtered_block_connected(self, block: BlockHeaderData) -> Self {
+ self.expected_filtered_blocks_connected.borrow_mut().push_back(block);
+ self
+ }
+
pub fn expect_block_disconnected(self, block: BlockHeaderData) -> Self {
self.expected_blocks_disconnected.borrow_mut().push_back(block);
self
}
impl chain::Listen for MockChainListener {
- fn filtered_block_connected(&self, header: &BlockHeader, _txdata: &chain::transaction::TransactionData, height: u32) {
+ fn block_connected(&self, block: &Block, height: u32) {
match self.expected_blocks_connected.borrow_mut().pop_front() {
None => {
- panic!("Unexpected block connected: {:?}", header.block_hash());
+ panic!("Unexpected block connected: {:?}", block.block_hash());
+ },
+ Some(expected_block) => {
+ assert_eq!(block.block_hash(), expected_block.header.block_hash());
+ assert_eq!(height, expected_block.height);
+ },
+ }
+ }
+
+ fn filtered_block_connected(&self, header: &BlockHeader, _txdata: &chain::transaction::TransactionData, height: u32) {
+ match self.expected_filtered_blocks_connected.borrow_mut().pop_front() {
+ None => {
+ panic!("Unexpected filtered block connected: {:?}", header.block_hash());
},
Some(expected_block) => {
assert_eq!(header.block_hash(), expected_block.header.block_hash());
panic!("Expected blocks connected: {:?}", expected_blocks_connected);
}
+ let expected_filtered_blocks_connected = self.expected_filtered_blocks_connected.borrow();
+ if !expected_filtered_blocks_connected.is_empty() {
+ panic!("Expected filtered_blocks connected: {:?}", expected_filtered_blocks_connected);
+ }
+
let expected_blocks_disconnected = self.expected_blocks_disconnected.borrow();
if !expected_blocks_disconnected.is_empty() {
panic!("Expected blocks disconnected: {:?}", expected_blocks_disconnected);