diff --git a/chain/src/block.rs b/chain/src/block.rs index 5250c367..67e24379 100644 --- a/chain/src/block.rs +++ b/chain/src/block.rs @@ -64,6 +64,10 @@ impl Block { pub fn header(&self) -> &BlockHeader { &self.block_header } + + pub fn drain(self) -> (BlockHeader, Vec) { + (self.block_header, self.transactions) + } } #[cfg(test)] diff --git a/db/src/indexed_block.rs b/db/src/indexed_block.rs new file mode 100644 index 00000000..25a4a784 --- /dev/null +++ b/db/src/indexed_block.rs @@ -0,0 +1,77 @@ +use chain; +use primitives::hash::H256; + +pub struct IndexedBlock { + header: chain::BlockHeader, + header_hash: H256, + transactions: Vec, + // guaranteed to be the same length as transactions + transaction_hashes: Vec, +} + +impl From for IndexedBlock { + fn from(block: chain::Block) -> Self { + let (org_header, org_txs) = block.drain(); + let mut hashes = Vec::with_capacity(org_txs.len()); + for tx in org_txs.iter() { + hashes.push(tx.hash()) + } + let header_hash = org_header.hash(); + + IndexedBlock { + header: org_header, + header_hash: header_hash, + transactions: org_txs, + transaction_hashes: hashes, + } + } +} + +impl IndexedBlock { + pub fn transactions(&self) -> IndexedTransactions { + IndexedTransactions { + position: 0, + block: self, + } + } + + pub fn header(&self) -> &chain::BlockHeader { + &self.header + } + + pub fn hash(&self) -> &H256 { + &self.header_hash + } +} + +pub struct IndexedTransactions<'a> { + position: usize, + block: &'a IndexedBlock, +} + +impl<'a> Iterator for IndexedTransactions<'a> { + type Item = (&'a H256, &'a chain::Transaction); + + fn next(&mut self) -> Option<(&'a H256, &'a chain::Transaction)> { + if self.position >= self.block.transactions.len() { + None + } + else { + Some((&self.block.transaction_hashes[self.position], &self.block.transactions[self.position])) + } + } +} + +#[cfg(test)] +mod tests { + use test_data; + use super::IndexedBlock; + + #[test] + fn index() { + let block = test_data::block_h1(); + let indexed_block: IndexedBlock = block.clone().into(); + + assert_eq!(*indexed_block.transactions().nth(0).unwrap().0, block.transactions()[0].hash()); + } +} diff --git a/db/src/lib.rs b/db/src/lib.rs index 7d6f771c..e6b150c4 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -27,6 +27,7 @@ mod transaction_provider; mod transaction_meta_provider; mod error; mod update_context; +mod indexed_block; pub enum BlockRef { Number(u32), @@ -49,6 +50,7 @@ pub use transaction_provider::TransactionProvider; pub use transaction_meta_provider::TransactionMetaProvider; pub use block_stapler::{BlockStapler, BlockInsertedChain}; pub use block_provider::BlockProvider; +pub use indexed_block::{IndexedBlock, IndexedTransactions}; #[cfg(feature="dev")] pub use test_storage::TestStorage;