storing block receitps in db, client logs method implementation

This commit is contained in:
debris 2016-02-17 12:35:37 +01:00
parent b01652f3e7
commit 5826a34ebb
8 changed files with 236 additions and 29 deletions

View File

@ -50,7 +50,9 @@ pub struct CacheSize {
/// Logs cache size. /// Logs cache size.
pub block_logs: usize, pub block_logs: usize,
/// Blooms cache size. /// Blooms cache size.
pub blocks_blooms: usize pub blocks_blooms: usize,
/// Block receipts size.
pub block_receipts: usize
} }
struct BloomIndexer { struct BloomIndexer {
@ -147,6 +149,9 @@ pub trait BlockProvider {
/// Get the address of transaction with given hash. /// Get the address of transaction with given hash.
fn transaction_address(&self, hash: &H256) -> Option<TransactionAddress>; fn transaction_address(&self, hash: &H256) -> Option<TransactionAddress>;
/// Get receipts of block with given hash.
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts>;
/// Get the partial-header of a block. /// Get the partial-header of a block.
fn block_header(&self, hash: &H256) -> Option<Header> { fn block_header(&self, hash: &H256) -> Option<Header> {
self.block(hash).map(|bytes| BlockView::new(&bytes).header()) self.block(hash).map(|bytes| BlockView::new(&bytes).header())
@ -223,6 +228,7 @@ pub struct BlockChain {
transaction_addresses: RwLock<HashMap<H256, TransactionAddress>>, transaction_addresses: RwLock<HashMap<H256, TransactionAddress>>,
block_logs: RwLock<HashMap<H256, BlockLogBlooms>>, block_logs: RwLock<HashMap<H256, BlockLogBlooms>>,
blocks_blooms: RwLock<HashMap<H256, BlocksBlooms>>, blocks_blooms: RwLock<HashMap<H256, BlocksBlooms>>,
block_receipts: RwLock<HashMap<H256, BlockReceipts>>,
extras_db: DB, extras_db: DB,
blocks_db: DB, blocks_db: DB,
@ -287,6 +293,11 @@ impl BlockProvider for BlockChain {
self.query_extras(hash, &self.transaction_addresses) self.query_extras(hash, &self.transaction_addresses)
} }
/// Get receipts of block with given hash.
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
self.query_extras(hash, &self.block_receipts)
}
/// Returns numbers of blocks containing given bloom. /// Returns numbers of blocks containing given bloom.
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber> { fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber> {
let filter = ChainFilter::new(self, self.bloom_indexer.index_size(), self.bloom_indexer.levels()); let filter = ChainFilter::new(self, self.bloom_indexer.index_size(), self.bloom_indexer.levels());
@ -348,6 +359,7 @@ impl BlockChain {
transaction_addresses: RwLock::new(HashMap::new()), transaction_addresses: RwLock::new(HashMap::new()),
block_logs: RwLock::new(HashMap::new()), block_logs: RwLock::new(HashMap::new()),
blocks_blooms: RwLock::new(HashMap::new()), blocks_blooms: RwLock::new(HashMap::new()),
block_receipts: RwLock::new(HashMap::new()),
extras_db: extras_db, extras_db: extras_db,
blocks_db: blocks_db, blocks_db: blocks_db,
cache_man: RwLock::new(cache_man), cache_man: RwLock::new(cache_man),
@ -504,7 +516,7 @@ impl BlockChain {
/// Inserts the block into backing cache database. /// Inserts the block into backing cache database.
/// Expects the block to be valid and already verified. /// Expects the block to be valid and already verified.
/// If the block is already known, does nothing. /// If the block is already known, does nothing.
pub fn insert_block(&self, bytes: &[u8], receipts: &[Receipt]) { pub fn insert_block(&self, bytes: &[u8], receipts: Vec<Receipt>) {
// create views onto rlp // create views onto rlp
let block = BlockView::new(bytes); let block = BlockView::new(bytes);
let header = block.header_view(); let header = block.header_view();
@ -546,8 +558,7 @@ impl BlockChain {
/// Transforms block into WriteBatch that may be written into database /// Transforms block into WriteBatch that may be written into database
/// Additionally, if it's new best block it returns new best block object. /// Additionally, if it's new best block it returns new best block object.
//fn block_to_extras_insert_batch(&self, bytes: &[u8], _receipts: &[Receipt]) -> (WriteBatch, Option<BestBlock>, BlockDetails) { fn block_to_extras_update(&self, bytes: &[u8], receipts: Vec<Receipt>) -> ExtrasUpdate {
fn block_to_extras_update(&self, bytes: &[u8], _receipts: &[Receipt]) -> ExtrasUpdate {
// create views onto rlp // create views onto rlp
let block = BlockView::new(bytes); let block = BlockView::new(bytes);
let header = block.header_view(); let header = block.header_view();
@ -585,11 +596,8 @@ impl BlockChain {
}); });
} }
// save blooms (is it really required?). maybe store receipt whole instead? // update block receipts
//let blooms: Vec<H2048> = receipts.iter().map(|r| r.log_bloom.clone()).collect(); batch.put_extras(&hash, &BlockReceipts::new(receipts));
//batch.put_extras(&hash, &BlockLogBlooms {
//blooms: blooms
//});
// if it's not new best block, just return // if it's not new best block, just return
if !is_new_best { if !is_new_best {
@ -741,7 +749,8 @@ impl BlockChain {
block_details: self.block_details.read().unwrap().heap_size_of_children(), block_details: self.block_details.read().unwrap().heap_size_of_children(),
transaction_addresses: self.transaction_addresses.read().unwrap().heap_size_of_children(), transaction_addresses: self.transaction_addresses.read().unwrap().heap_size_of_children(),
block_logs: self.block_logs.read().unwrap().heap_size_of_children(), block_logs: self.block_logs.read().unwrap().heap_size_of_children(),
blocks_blooms: self.blocks_blooms.read().unwrap().heap_size_of_children() blocks_blooms: self.blocks_blooms.read().unwrap().heap_size_of_children(),
block_receipts: self.block_receipts.read().unwrap().heap_size_of_children()
} }
} }
@ -773,6 +782,7 @@ impl BlockChain {
let mut transaction_addresses = self.transaction_addresses.write().unwrap(); let mut transaction_addresses = self.transaction_addresses.write().unwrap();
let mut block_logs = self.block_logs.write().unwrap(); let mut block_logs = self.block_logs.write().unwrap();
let mut blocks_blooms = self.blocks_blooms.write().unwrap(); let mut blocks_blooms = self.blocks_blooms.write().unwrap();
let mut block_receipts = self.block_receipts.write().unwrap();
for id in cache_man.cache_usage.pop_back().unwrap().into_iter() { for id in cache_man.cache_usage.pop_back().unwrap().into_iter() {
cache_man.in_use.remove(&id); cache_man.in_use.remove(&id);
@ -782,6 +792,7 @@ impl BlockChain {
CacheID::Extras(ExtrasIndex::TransactionAddress, h) => { transaction_addresses.remove(&h); }, CacheID::Extras(ExtrasIndex::TransactionAddress, h) => { transaction_addresses.remove(&h); },
CacheID::Extras(ExtrasIndex::BlockLogBlooms, h) => { block_logs.remove(&h); }, CacheID::Extras(ExtrasIndex::BlockLogBlooms, h) => { block_logs.remove(&h); },
CacheID::Extras(ExtrasIndex::BlocksBlooms, h) => { blocks_blooms.remove(&h); }, CacheID::Extras(ExtrasIndex::BlocksBlooms, h) => { blocks_blooms.remove(&h); },
CacheID::Extras(ExtrasIndex::BlockReceipts, h) => { block_receipts.remove(&h); },
_ => panic!(), _ => panic!(),
} }
} }
@ -823,7 +834,7 @@ mod tests {
let first = "f90285f90219a03caa2203f3d7c136c0295ed128a7d31cea520b1ca5e27afe17d0853331798942a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0d45893a296c1490a978e0bd321b5f2635d8280365c1fe9f693d65f233e791344a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefd882560b845627cb99a00102030405060708091011121314151617181920212223242526272829303132a08ccb2837fb2923bd97e8f2d08ea32012d6e34be018c73e49a0f98843e8f47d5d88e53be49fec01012ef866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ba0cb088b8d2ff76a7b2c6616c9d02fb6b7a501afbf8b69d7180b09928a1b80b5e4a06448fe7476c606582039bb72a9f6f4b4fad18507b8dfbd00eebbe151cc573cd2c0".from_hex().unwrap(); let first = "f90285f90219a03caa2203f3d7c136c0295ed128a7d31cea520b1ca5e27afe17d0853331798942a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0d45893a296c1490a978e0bd321b5f2635d8280365c1fe9f693d65f233e791344a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefd882560b845627cb99a00102030405060708091011121314151617181920212223242526272829303132a08ccb2837fb2923bd97e8f2d08ea32012d6e34be018c73e49a0f98843e8f47d5d88e53be49fec01012ef866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ba0cb088b8d2ff76a7b2c6616c9d02fb6b7a501afbf8b69d7180b09928a1b80b5e4a06448fe7476c606582039bb72a9f6f4b4fad18507b8dfbd00eebbe151cc573cd2c0".from_hex().unwrap();
bc.insert_block(&first, &[]); bc.insert_block(&first, vec![]);
let first_hash = H256::from_str("a940e5af7d146b3b917c953a82e1966b906dace3a4e355b5b0a4560190357ea1").unwrap(); let first_hash = H256::from_str("a940e5af7d146b3b917c953a82e1966b906dace3a4e355b5b0a4560190357ea1").unwrap();
@ -856,10 +867,10 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let bc = BlockChain::new(&genesis, temp.as_path()); let bc = BlockChain::new(&genesis, temp.as_path());
bc.insert_block(&b1, &[]); bc.insert_block(&b1, vec![]);
bc.insert_block(&b2, &[]); bc.insert_block(&b2, vec![]);
bc.insert_block(&b3a, &[]); bc.insert_block(&b3a, vec![]);
bc.insert_block(&b3b, &[]); bc.insert_block(&b3b, vec![]);
assert_eq!(bc.best_block_hash(), best_block_hash); assert_eq!(bc.best_block_hash(), best_block_hash);
assert_eq!(bc.block_number(&genesis_hash).unwrap(), 0); assert_eq!(bc.block_number(&genesis_hash).unwrap(), 0);
@ -936,7 +947,7 @@ mod tests {
{ {
let bc = BlockChain::new(&genesis, temp.as_path()); let bc = BlockChain::new(&genesis, temp.as_path());
assert_eq!(bc.best_block_hash(), genesis_hash); assert_eq!(bc.best_block_hash(), genesis_hash);
bc.insert_block(&b1, &[]); bc.insert_block(&b1, vec![]);
assert_eq!(bc.best_block_hash(), b1_hash); assert_eq!(bc.best_block_hash(), b1_hash);
} }
@ -995,7 +1006,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let bc = BlockChain::new(&genesis, temp.as_path()); let bc = BlockChain::new(&genesis, temp.as_path());
bc.insert_block(&b1, &[]); bc.insert_block(&b1, vec![]);
let transactions = bc.transactions(&b1_hash).unwrap(); let transactions = bc.transactions(&b1_hash).unwrap();
assert_eq!(transactions.len(), 7); assert_eq!(transactions.len(), 7);
@ -1026,13 +1037,13 @@ mod tests {
assert_eq!(blocks_b1, vec![]); assert_eq!(blocks_b1, vec![]);
assert_eq!(blocks_b2, vec![]); assert_eq!(blocks_b2, vec![]);
bc.insert_block(&b1, &[]); bc.insert_block(&b1, vec![]);
let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3);
let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3);
assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b1, vec![1]);
assert_eq!(blocks_b2, vec![]); assert_eq!(blocks_b2, vec![]);
bc.insert_block(&b2, &[]); bc.insert_block(&b2, vec![]);
let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3);
let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3);
assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b1, vec![1]);

View File

@ -33,7 +33,9 @@ use env_info::LastHashes;
use verification::*; use verification::*;
use block::*; use block::*;
use transaction::LocalizedTransaction; use transaction::LocalizedTransaction;
use extras::TransactionAddress; use extras::{TransactionAddress, BlockReceipts};
use filter::Filter;
use log_entry::LocalizedLogEntry;
pub use blockchain::TreeRoute; pub use blockchain::TreeRoute;
/// Uniquely identifies block. /// Uniquely identifies block.
@ -147,6 +149,9 @@ pub trait BlockChainClient : Sync + Send {
/// Returns numbers of blocks containing given bloom. /// Returns numbers of blocks containing given bloom.
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option<Vec<BlockNumber>>; fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option<Vec<BlockNumber>>;
/// Returns logs matching given filter.
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
} }
#[derive(Default, Clone, Debug, Eq, PartialEq)] #[derive(Default, Clone, Debug, Eq, PartialEq)]
@ -307,7 +312,7 @@ impl Client {
good_blocks.push(header.hash().clone()); good_blocks.push(header.hash().clone());
self.chain.write().unwrap().insert_block(&block.bytes, result.block().receipts()); //TODO: err here? self.chain.write().unwrap().insert_block(&block.bytes, result.block().receipts().clone()); //TODO: err here?
let ancient = if header.number() >= HISTORY { Some(header.number() - HISTORY) } else { None }; let ancient = if header.number() >= HISTORY { Some(header.number() - HISTORY) } else { None };
match result.drain().commit(header.number(), &header.hash(), ancient.map(|n|(n, self.chain.read().unwrap().block_hash(n).unwrap()))) { match result.drain().commit(header.number(), &header.hash(), ancient.map(|n|(n, self.chain.read().unwrap().block_hash(n).unwrap()))) {
Ok(_) => (), Ok(_) => (),
@ -474,6 +479,50 @@ impl BlockChainClient for Client {
_ => None _ => None
} }
} }
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let mut blocks = filter.bloom_possibilities().iter()
.map(|bloom| self.blocks_with_bloom(bloom, filter.from_block.clone(), filter.to_block.clone()))
.filter_map(|m| m)
.flat_map(|m| m)
// remove duplicate elements
.collect::<HashSet<u64>>()
.into_iter()
.collect::<Vec<u64>>();
blocks.sort();
blocks.into_iter()
.map(|number| self.chain.read().unwrap().block_hash(number).map(|hash| (number, hash)))
.filter_map(|m| m)
.map(|(number, hash)| self.chain.read().unwrap().block_receipts(&hash).map(|r| (number, hash, r.receipts)))
.filter_map(|m| m)
.map(|(number, hash, receipts)| {
let mut log_index = 0;
receipts.into_iter()
.enumerate()
.map(|(index, receipt)| {
log_index += receipt.logs.len();
receipt.logs.into_iter()
.enumerate()
.filter(|tuple| filter.matches(&tuple.1))
.map(|(i, log)| LocalizedLogEntry {
entry: log,
block_hash: hash.clone(),
block_number: number as usize,
transaction_hash: H256::new(),
transaction_index: index,
log_index: log_index
})
.collect::<Vec<LocalizedLogEntry>>()
})
.flat_map(|m| m)
.collect::<Vec<LocalizedLogEntry>>()
})
.flat_map(|m| m)
.collect()
}
} }
impl MayPanic for Client { impl MayPanic for Client {

View File

@ -16,9 +16,10 @@
//! Blockchain DB extras. //! Blockchain DB extras.
use rocksdb::{DB, Writable};
use util::*; use util::*;
use header::BlockNumber; use header::BlockNumber;
use rocksdb::{DB, Writable}; use receipt::Receipt;
/// Represents index of extra data in database /// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
@ -32,7 +33,9 @@ pub enum ExtrasIndex {
/// Block log blooms index /// Block log blooms index
BlockLogBlooms = 3, BlockLogBlooms = 3,
/// Block blooms index /// Block blooms index
BlocksBlooms = 4 BlocksBlooms = 4,
/// Block receipts index
BlockReceipts
} }
/// trait used to write Extras data to db /// trait used to write Extras data to db
@ -307,3 +310,43 @@ impl Encodable for TransactionAddress {
s.append(&self.index); s.append(&self.index);
} }
} }
/// Contains all block receipts.
#[derive(Clone)]
pub struct BlockReceipts {
pub receipts: Vec<Receipt>
}
impl BlockReceipts {
pub fn new(receipts: Vec<Receipt>) -> Self {
BlockReceipts {
receipts: receipts
}
}
}
impl Decodable for BlockReceipts {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
Ok(BlockReceipts {
receipts: try!(Decodable::decode(decoder))
})
}
}
impl Encodable for BlockReceipts {
fn rlp_append(&self, s: &mut RlpStream) {
s.append(&self.receipts);
}
}
impl HeapSizeOf for BlockReceipts {
fn heap_size_of_children(&self) -> usize {
self.receipts.heap_size_of_children()
}
}
impl ExtrasIndexable for BlockReceipts {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockReceipts
}
}

View File

@ -17,26 +17,27 @@
use util::hash::*; use util::hash::*;
use util::sha3::*; use util::sha3::*;
use client::BlockId; use client::BlockId;
use log_entry::LogEntry;
/// Blockchain log filter data. /// Blockchain log filter data.
pub struct Filter { pub struct Filter {
/// Blockchain will be searched from this block. /// Blockchain will be searched from this block.
from_block: BlockId, pub from_block: BlockId,
/// Till this block. /// Till this block.
to_block: BlockId, pub to_block: BlockId,
/// Search addresses. /// Search addresses.
/// ///
/// If None, match all. /// If None, match all.
/// If specified, log must be produced by one of these addresses. /// If specified, log must be produced by one of these addresses.
address: Option<Vec<Address>>, pub address: Option<Vec<Address>>,
/// Search topics. /// Search topics.
/// ///
/// If None, match all. /// If None, match all.
/// If specified, log must contain one of these topics. /// If specified, log must contain one of these topics.
topics: [Option<Vec<H256>>; 4] pub topics: [Option<Vec<H256>>; 4]
} }
impl Filter { impl Filter {
@ -63,6 +64,23 @@ impl Filter {
}).flat_map(|m| m).collect() }).flat_map(|m| m).collect()
}) })
} }
/// Returns true if given log entry matches filter.
pub fn matches(&self, log: &LogEntry) -> bool {
let matches = match self.address {
Some(ref addresses) if !addresses.is_empty() => addresses.iter().fold(false, |res, address| {
res || &log.address == address
}),
_ => true
};
matches && self.topics.iter().enumerate().fold(true, |res, (i, topic)| match *topic {
Some(ref topics) if !topics.is_empty() => res && topics.iter().fold(false, | acc, topic | {
acc || log.topics.get(i) == Some(topic)
}),
_ => res,
})
}
} }
#[cfg(test)] #[cfg(test)]
@ -71,6 +89,7 @@ mod tests {
use util::hash::*; use util::hash::*;
use filter::Filter; use filter::Filter;
use client::BlockId; use client::BlockId;
use log_entry::LogEntry;
#[test] #[test]
fn test_bloom_possibilities_none() { fn test_bloom_possibilities_none() {
@ -149,4 +168,49 @@ mod tests {
assert_eq!(possibilities[0], H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); assert_eq!(possibilities[0], H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap());
} }
#[test]
fn test_filter_matches() {
let filter = Filter {
from_block: BlockId::Earliest,
to_block: BlockId::Latest,
address: Some(vec![Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap()]),
topics: [
Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]),
Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa").unwrap()]),
None, None
]
};
let entry0 = LogEntry {
address: Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(),
topics: vec![
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa").unwrap(),
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
],
data: vec![]
};
let entry1 = LogEntry {
address: Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5e").unwrap(),
topics: vec![
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa").unwrap(),
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
],
data: vec![]
};
let entry2 = LogEntry {
address: Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(),
topics: vec![
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
],
data: vec![]
};
assert_eq!(filter.matches(&entry0), true);
assert_eq!(filter.matches(&entry1), false);
assert_eq!(filter.matches(&entry2), false);
}
} }

View File

@ -37,6 +37,24 @@ impl Encodable for LogEntry {
} }
} }
impl Decodable for LogEntry {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let entry = LogEntry {
address: try!(d.val_at(0)),
topics: try!(d.val_at(1)),
data: try!(d.val_at(2)),
};
Ok(entry)
}
}
impl HeapSizeOf for LogEntry {
fn heap_size_of_children(&self) -> usize {
self.topics.heap_size_of_children() + self.data.heap_size_of_children()
}
}
impl LogEntry { impl LogEntry {
/// Calculates the bloom of this log entry. /// Calculates the bloom of this log entry.
pub fn bloom(&self) -> LogBloom { pub fn bloom(&self) -> LogBloom {

View File

@ -55,6 +55,24 @@ impl Encodable for Receipt {
} }
} }
impl Decodable for Receipt {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let receipt = Receipt {
state_root: try!(d.val_at(0)),
gas_used: try!(d.val_at(1)),
log_bloom: try!(d.val_at(2)),
logs: try!(d.val_at(3)),
};
Ok(receipt)
}
}
impl HeapSizeOf for Receipt {
fn heap_size_of_children(&self) -> usize {
self.logs.heap_size_of_children()
}
}
#[test] #[test]
fn test_basic() { fn test_basic() {

View File

@ -224,7 +224,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockCh
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path()); let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path());
for block_order in 1..block_number { for block_order in 1..block_number {
bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash()), &[]); bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash()), vec![]);
} }
GuardedTempResult::<BlockChain> { GuardedTempResult::<BlockChain> {
@ -237,7 +237,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path()); let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path());
for block_order in 1..block_number { for block_order in 1..block_number {
bc.insert_block(&create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None), &[]); bc.insert_block(&create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None), vec![]);
} }
GuardedTempResult::<BlockChain> { GuardedTempResult::<BlockChain> {

View File

@ -306,6 +306,10 @@ mod tests {
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> { fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
unimplemented!() unimplemented!()
} }
fn block_receipts(&self, _hash: &H256) -> Option<BlockReceipts> {
unimplemented!()
}
} }
fn basic_test(bytes: &[u8], engine: &Engine) -> Result<(), Error> { fn basic_test(bytes: &[u8], engine: &Engine) -> Result<(), Error> {