storing block receitps in db, client logs method implementation
This commit is contained in:
parent
b01652f3e7
commit
5826a34ebb
@ -50,7 +50,9 @@ pub struct CacheSize {
|
||||
/// Logs cache size.
|
||||
pub block_logs: usize,
|
||||
/// Blooms cache size.
|
||||
pub blocks_blooms: usize
|
||||
pub blocks_blooms: usize,
|
||||
/// Block receipts size.
|
||||
pub block_receipts: usize
|
||||
}
|
||||
|
||||
struct BloomIndexer {
|
||||
@ -147,6 +149,9 @@ pub trait BlockProvider {
|
||||
/// Get the address of transaction with given hash.
|
||||
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.
|
||||
fn block_header(&self, hash: &H256) -> Option<Header> {
|
||||
self.block(hash).map(|bytes| BlockView::new(&bytes).header())
|
||||
@ -223,6 +228,7 @@ pub struct BlockChain {
|
||||
transaction_addresses: RwLock<HashMap<H256, TransactionAddress>>,
|
||||
block_logs: RwLock<HashMap<H256, BlockLogBlooms>>,
|
||||
blocks_blooms: RwLock<HashMap<H256, BlocksBlooms>>,
|
||||
block_receipts: RwLock<HashMap<H256, BlockReceipts>>,
|
||||
|
||||
extras_db: DB,
|
||||
blocks_db: DB,
|
||||
@ -287,6 +293,11 @@ impl BlockProvider for BlockChain {
|
||||
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.
|
||||
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());
|
||||
@ -348,6 +359,7 @@ impl BlockChain {
|
||||
transaction_addresses: RwLock::new(HashMap::new()),
|
||||
block_logs: RwLock::new(HashMap::new()),
|
||||
blocks_blooms: RwLock::new(HashMap::new()),
|
||||
block_receipts: RwLock::new(HashMap::new()),
|
||||
extras_db: extras_db,
|
||||
blocks_db: blocks_db,
|
||||
cache_man: RwLock::new(cache_man),
|
||||
@ -504,7 +516,7 @@ impl BlockChain {
|
||||
/// Inserts the block into backing cache database.
|
||||
/// Expects the block to be valid and already verified.
|
||||
/// 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
|
||||
let block = BlockView::new(bytes);
|
||||
let header = block.header_view();
|
||||
@ -546,8 +558,7 @@ impl BlockChain {
|
||||
|
||||
/// Transforms block into WriteBatch that may be written into database
|
||||
/// 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: &[Receipt]) -> ExtrasUpdate {
|
||||
fn block_to_extras_update(&self, bytes: &[u8], receipts: Vec<Receipt>) -> ExtrasUpdate {
|
||||
// create views onto rlp
|
||||
let block = BlockView::new(bytes);
|
||||
let header = block.header_view();
|
||||
@ -585,11 +596,8 @@ impl BlockChain {
|
||||
});
|
||||
}
|
||||
|
||||
// save blooms (is it really required?). maybe store receipt whole instead?
|
||||
//let blooms: Vec<H2048> = receipts.iter().map(|r| r.log_bloom.clone()).collect();
|
||||
//batch.put_extras(&hash, &BlockLogBlooms {
|
||||
//blooms: blooms
|
||||
//});
|
||||
// update block receipts
|
||||
batch.put_extras(&hash, &BlockReceipts::new(receipts));
|
||||
|
||||
// if it's not new best block, just return
|
||||
if !is_new_best {
|
||||
@ -741,7 +749,8 @@ impl BlockChain {
|
||||
block_details: self.block_details.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(),
|
||||
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 block_logs = self.block_logs.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() {
|
||||
cache_man.in_use.remove(&id);
|
||||
@ -782,6 +792,7 @@ impl BlockChain {
|
||||
CacheID::Extras(ExtrasIndex::TransactionAddress, h) => { transaction_addresses.remove(&h); },
|
||||
CacheID::Extras(ExtrasIndex::BlockLogBlooms, h) => { block_logs.remove(&h); },
|
||||
CacheID::Extras(ExtrasIndex::BlocksBlooms, h) => { blocks_blooms.remove(&h); },
|
||||
CacheID::Extras(ExtrasIndex::BlockReceipts, h) => { block_receipts.remove(&h); },
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
@ -823,7 +834,7 @@ mod tests {
|
||||
|
||||
let first = "f90285f90219a03caa2203f3d7c136c0295ed128a7d31cea520b1ca5e27afe17d0853331798942a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0d45893a296c1490a978e0bd321b5f2635d8280365c1fe9f693d65f233e791344a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefd882560b845627cb99a00102030405060708091011121314151617181920212223242526272829303132a08ccb2837fb2923bd97e8f2d08ea32012d6e34be018c73e49a0f98843e8f47d5d88e53be49fec01012ef866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ba0cb088b8d2ff76a7b2c6616c9d02fb6b7a501afbf8b69d7180b09928a1b80b5e4a06448fe7476c606582039bb72a9f6f4b4fad18507b8dfbd00eebbe151cc573cd2c0".from_hex().unwrap();
|
||||
|
||||
bc.insert_block(&first, &[]);
|
||||
bc.insert_block(&first, vec![]);
|
||||
|
||||
let first_hash = H256::from_str("a940e5af7d146b3b917c953a82e1966b906dace3a4e355b5b0a4560190357ea1").unwrap();
|
||||
|
||||
@ -856,10 +867,10 @@ mod tests {
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(&genesis, temp.as_path());
|
||||
bc.insert_block(&b1, &[]);
|
||||
bc.insert_block(&b2, &[]);
|
||||
bc.insert_block(&b3a, &[]);
|
||||
bc.insert_block(&b3b, &[]);
|
||||
bc.insert_block(&b1, vec![]);
|
||||
bc.insert_block(&b2, vec![]);
|
||||
bc.insert_block(&b3a, vec![]);
|
||||
bc.insert_block(&b3b, vec![]);
|
||||
|
||||
assert_eq!(bc.best_block_hash(), best_block_hash);
|
||||
assert_eq!(bc.block_number(&genesis_hash).unwrap(), 0);
|
||||
@ -936,7 +947,7 @@ mod tests {
|
||||
{
|
||||
let bc = BlockChain::new(&genesis, temp.as_path());
|
||||
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);
|
||||
}
|
||||
|
||||
@ -995,7 +1006,7 @@ mod tests {
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(&genesis, temp.as_path());
|
||||
bc.insert_block(&b1, &[]);
|
||||
bc.insert_block(&b1, vec![]);
|
||||
|
||||
let transactions = bc.transactions(&b1_hash).unwrap();
|
||||
assert_eq!(transactions.len(), 7);
|
||||
@ -1026,13 +1037,13 @@ mod tests {
|
||||
assert_eq!(blocks_b1, 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_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3);
|
||||
assert_eq!(blocks_b1, vec![1]);
|
||||
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_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3);
|
||||
assert_eq!(blocks_b1, vec![1]);
|
||||
|
@ -33,7 +33,9 @@ use env_info::LastHashes;
|
||||
use verification::*;
|
||||
use block::*;
|
||||
use transaction::LocalizedTransaction;
|
||||
use extras::TransactionAddress;
|
||||
use extras::{TransactionAddress, BlockReceipts};
|
||||
use filter::Filter;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
pub use blockchain::TreeRoute;
|
||||
|
||||
/// Uniquely identifies block.
|
||||
@ -147,6 +149,9 @@ pub trait BlockChainClient : Sync + Send {
|
||||
|
||||
/// Returns numbers of blocks containing given bloom.
|
||||
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)]
|
||||
@ -307,7 +312,7 @@ impl Client {
|
||||
|
||||
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 };
|
||||
match result.drain().commit(header.number(), &header.hash(), ancient.map(|n|(n, self.chain.read().unwrap().block_hash(n).unwrap()))) {
|
||||
Ok(_) => (),
|
||||
@ -474,6 +479,50 @@ impl BlockChainClient for Client {
|
||||
_ => 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 {
|
||||
|
@ -16,9 +16,10 @@
|
||||
|
||||
//! Blockchain DB extras.
|
||||
|
||||
use rocksdb::{DB, Writable};
|
||||
use util::*;
|
||||
use header::BlockNumber;
|
||||
use rocksdb::{DB, Writable};
|
||||
use receipt::Receipt;
|
||||
|
||||
/// Represents index of extra data in database
|
||||
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
|
||||
@ -32,7 +33,9 @@ pub enum ExtrasIndex {
|
||||
/// Block log blooms index
|
||||
BlockLogBlooms = 3,
|
||||
/// Block blooms index
|
||||
BlocksBlooms = 4
|
||||
BlocksBlooms = 4,
|
||||
/// Block receipts index
|
||||
BlockReceipts
|
||||
}
|
||||
|
||||
/// trait used to write Extras data to db
|
||||
@ -307,3 +310,43 @@ impl Encodable for TransactionAddress {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -17,26 +17,27 @@
|
||||
use util::hash::*;
|
||||
use util::sha3::*;
|
||||
use client::BlockId;
|
||||
use log_entry::LogEntry;
|
||||
|
||||
/// Blockchain log filter data.
|
||||
pub struct Filter {
|
||||
/// Blockchain will be searched from this block.
|
||||
from_block: BlockId,
|
||||
pub from_block: BlockId,
|
||||
|
||||
/// Till this block.
|
||||
to_block: BlockId,
|
||||
pub to_block: BlockId,
|
||||
|
||||
/// Search addresses.
|
||||
///
|
||||
/// If None, match all.
|
||||
/// If specified, log must be produced by one of these addresses.
|
||||
address: Option<Vec<Address>>,
|
||||
pub address: Option<Vec<Address>>,
|
||||
|
||||
/// Search topics.
|
||||
///
|
||||
/// If None, match all.
|
||||
/// If specified, log must contain one of these topics.
|
||||
topics: [Option<Vec<H256>>; 4]
|
||||
pub topics: [Option<Vec<H256>>; 4]
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
@ -63,6 +64,23 @@ impl Filter {
|
||||
}).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)]
|
||||
@ -71,6 +89,7 @@ mod tests {
|
||||
use util::hash::*;
|
||||
use filter::Filter;
|
||||
use client::BlockId;
|
||||
use log_entry::LogEntry;
|
||||
|
||||
#[test]
|
||||
fn test_bloom_possibilities_none() {
|
||||
@ -149,4 +168,49 @@ mod tests {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
/// Calculates the bloom of this log entry.
|
||||
pub fn bloom(&self) -> LogBloom {
|
||||
|
@ -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]
|
||||
fn test_basic() {
|
||||
|
@ -224,7 +224,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockCh
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path());
|
||||
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> {
|
||||
@ -237,7 +237,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path());
|
||||
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> {
|
||||
|
@ -306,6 +306,10 @@ mod tests {
|
||||
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn block_receipts(&self, _hash: &H256) -> Option<BlockReceipts> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn basic_test(bytes: &[u8], engine: &Engine) -> Result<(), Error> {
|
||||
|
Loading…
Reference in New Issue
Block a user