[beta] Backports (#8011)

* Hardware-wallet/usb-subscribe-refactor (#7860)

* Hardware-wallet fix

* More fine-grained initilization of callbacks by vendorID, productID and usb class
* Each device manufacturer gets a seperate handle thread each
* Replaced "dummy for loop" with a delay to wait for the device to boot-up properly
* Haven't been very carefully with checking dependencies cycles etc
* Inline comments explaining where shortcuts have been taken
* Need to test this on Windows machine and with Ledger (both models)

Signed-off-by: niklasad1 <niklasadolfsson1@gmail.com>

* Validate product_id of detected ledger devices

* closed_device => unlocked_device

* address comments

* add target in debug

* Address feedback

* Remove thread joining in HardwareWalletManager
* Remove thread handlers in HardwareWalletManager because this makes them unused

* fixed broken logs (#7934)

* fixed broken logs

* bring back old lock order

* removed bloom groups from blockchain

* revert unrelated changes

* simplify blockchain_block_blooms

* Bump WS (#7952)

* Calculate proper keccak256/sha3 using parity. (#7953)

* Increase max download limit to 128MB (#7965)

* fetch: increase max download limit to 64MB

* parity: increase download size limit for updater service

* Detect too large packets in snapshot sync. (#7977)

* fix traces, removed bloomchain crate, closes #7228, closes #7167 (#7979)

* Remvoe generator.rs

* Make block generator easier to use (#7888)

* Make block generator easier to use

* applied review suggestions

* rename BlockMetadata -> BlockOptions

* removed redundant uses of blockchain generator and genereator.next().unwrap() calls
This commit is contained in:
Tomasz Drwięga
2018-02-28 14:59:04 +01:00
committed by Rando
parent 3d6670972f
commit 86f6cea29d
34 changed files with 819 additions and 1473 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -23,8 +23,6 @@ pub struct CacheSize {
pub block_details: usize,
/// Transaction addresses cache size.
pub transaction_addresses: usize,
/// Blooms cache size.
pub blocks_blooms: usize,
/// Block receipts size.
pub block_receipts: usize,
}
@@ -32,6 +30,6 @@ pub struct CacheSize {
impl CacheSize {
/// Total amount used by the cache.
pub fn total(&self) -> usize {
self.blocks + self.block_details + self.transaction_addresses + self.blocks_blooms + self.block_receipts
self.blocks + self.block_details + self.transaction_addresses + self.block_receipts
}
}

View File

@@ -18,8 +18,6 @@
use std::ops;
use std::io::Write;
use bloomchain;
use blooms::{GroupPosition, BloomGroup};
use db::Key;
use engines::epoch::{Transition as EpochTransition};
use header::BlockNumber;
@@ -39,8 +37,6 @@ pub enum ExtrasIndex {
BlockHash = 1,
/// Transaction address index
TransactionAddress = 2,
/// Block blooms index
BlocksBlooms = 3,
/// Block receipts index
BlockReceipts = 4,
/// Epoch transition data index.
@@ -88,46 +84,6 @@ impl Key<BlockDetails> for H256 {
}
}
pub struct LogGroupKey([u8; 6]);
impl ops::Deref for LogGroupKey {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct LogGroupPosition(GroupPosition);
impl From<bloomchain::group::GroupPosition> for LogGroupPosition {
fn from(position: bloomchain::group::GroupPosition) -> Self {
LogGroupPosition(From::from(position))
}
}
impl HeapSizeOf for LogGroupPosition {
fn heap_size_of_children(&self) -> usize {
self.0.heap_size_of_children()
}
}
impl Key<BloomGroup> for LogGroupPosition {
type Target = LogGroupKey;
fn key(&self) -> Self::Target {
let mut result = [0u8; 6];
result[0] = ExtrasIndex::BlocksBlooms as u8;
result[1] = self.0.level;
result[2] = (self.0.index >> 24) as u8;
result[3] = (self.0.index >> 16) as u8;
result[4] = (self.0.index >> 8) as u8;
result[5] = self.0.index as u8;
LogGroupKey(result)
}
}
impl Key<TransactionAddress> for H256 {
type Target = H264;

View File

@@ -0,0 +1,218 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain generator for tests.
use std::collections::VecDeque;
use bigint::prelude::{U256, H256, H2048 as Bloom};
use bytes::Bytes;
use header::Header;
use rlp::encode;
use transaction::SignedTransaction;
use views::BlockView;
/// Helper structure, used for encoding blocks.
#[derive(Default, Clone, RlpEncodable)]
pub struct Block {
pub header: Header,
pub transactions: Vec<SignedTransaction>,
pub uncles: Vec<Header>
}
impl Block {
#[inline]
pub fn header(&self) -> Header {
self.header.clone()
}
#[inline]
pub fn hash(&self) -> H256 {
BlockView::new(&self.encoded()).header_view().hash()
}
#[inline]
pub fn number(&self) -> u64 {
self.header.number()
}
#[inline]
pub fn encoded(&self) -> Bytes {
encode(self).into_vec()
}
}
#[derive(Debug)]
pub struct BlockOptions {
pub difficulty: U256,
pub bloom: Bloom,
pub transactions: Vec<SignedTransaction>,
}
impl Default for BlockOptions {
fn default() -> Self {
BlockOptions {
difficulty: 10.into(),
bloom: Bloom::default(),
transactions: Vec::new(),
}
}
}
#[derive(Clone)]
pub struct BlockBuilder {
blocks: VecDeque<Block>,
}
impl BlockBuilder {
pub fn genesis() -> Self {
let mut blocks = VecDeque::with_capacity(1);
blocks.push_back(Block::default());
BlockBuilder {
blocks,
}
}
#[inline]
pub fn add_block(&self) -> Self {
self.add_block_with(|| BlockOptions::default())
}
#[inline]
pub fn add_blocks(&self, count: usize) -> Self {
self.add_blocks_with(count, || BlockOptions::default())
}
#[inline]
pub fn add_block_with<T>(&self, get_metadata: T) -> Self where T: Fn() -> BlockOptions {
self.add_blocks_with(1, get_metadata)
}
#[inline]
pub fn add_block_with_difficulty<T>(&self, difficulty: T) -> Self where T: Into<U256> {
let difficulty = difficulty.into();
self.add_blocks_with(1, move || BlockOptions {
difficulty,
..Default::default()
})
}
#[inline]
pub fn add_block_with_transactions<T>(&self, transactions: T) -> Self
where T: IntoIterator<Item = SignedTransaction> {
let transactions = transactions.into_iter().collect::<Vec<_>>();
self.add_blocks_with(1, || BlockOptions {
transactions: transactions.clone(),
..Default::default()
})
}
#[inline]
pub fn add_block_with_bloom(&self, bloom: Bloom) -> Self {
self.add_blocks_with(1, move || BlockOptions {
bloom,
..Default::default()
})
}
pub fn add_blocks_with<T>(&self, count: usize, get_metadata: T) -> Self where T: Fn() -> BlockOptions {
assert!(count > 0, "There must be at least 1 block");
let mut parent_hash = self.last().hash();
let mut parent_number = self.last().number();
let mut blocks = VecDeque::with_capacity(count);
for _ in 0..count {
let mut block = Block::default();
let metadata = get_metadata();
let block_number = parent_number + 1;
block.header.set_parent_hash(parent_hash);
block.header.set_number(block_number);
block.header.set_log_bloom(metadata.bloom);
block.header.set_difficulty(metadata.difficulty);
block.transactions = metadata.transactions;
parent_hash = block.hash();
parent_number = block_number;
blocks.push_back(block);
}
BlockBuilder {
blocks,
}
}
#[inline]
pub fn last(&self) -> &Block {
self.blocks.back().expect("There is always at least 1 block")
}
}
#[derive(Clone)]
pub struct BlockGenerator {
builders: VecDeque<BlockBuilder>,
}
impl BlockGenerator {
pub fn new<T>(builders: T) -> Self where T: IntoIterator<Item = BlockBuilder> {
BlockGenerator {
builders: builders.into_iter().collect(),
}
}
}
impl Iterator for BlockGenerator {
type Item = Block;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.builders.front_mut() {
Some(ref mut builder) => {
if let Some(block) = builder.blocks.pop_front() {
return Some(block);
}
},
None => return None,
}
self.builders.pop_front();
}
}
}
#[cfg(test)]
mod tests {
use super::{BlockBuilder, BlockOptions, BlockGenerator};
#[test]
fn test_block_builder() {
let genesis = BlockBuilder::genesis();
let block_1 = genesis.add_block();
let block_1001 = block_1.add_blocks(1000);
let block_1002 = block_1001.add_block_with(|| BlockOptions::default());
let generator = BlockGenerator::new(vec![genesis, block_1, block_1001, block_1002]);
assert_eq!(generator.count(), 1003);
}
#[test]
fn test_block_builder_fork() {
let genesis = BlockBuilder::genesis();
let block_10a = genesis.add_blocks(10);
let block_11b = genesis.add_blocks(11);
assert_eq!(block_10a.last().number(), 10);
assert_eq!(block_11b.last().number(), 11);
}
}

View File

@@ -1,72 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use rlp::*;
use bigint::hash::{H256, H2048};
use bytes::Bytes;
use header::Header;
use transaction::SignedTransaction;
use super::fork::Forkable;
use super::bloom::WithBloom;
use super::complete::CompleteBlock;
use super::transaction::WithTransaction;
/// Helper structure, used for encoding blocks.
#[derive(Default)]
pub struct Block {
pub header: Header,
pub transactions: Vec<SignedTransaction>,
pub uncles: Vec<Header>
}
impl Encodable for Block {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.header);
s.append_list(&self.transactions);
s.append_list(&self.uncles);
}
}
impl Forkable for Block {
fn fork(mut self, fork_number: usize) -> Self where Self: Sized {
let difficulty = self.header.difficulty().clone() - fork_number.into();
self.header.set_difficulty(difficulty);
self
}
}
impl WithBloom for Block {
fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized {
self.header.set_log_bloom(bloom);
self
}
}
impl WithTransaction for Block {
fn with_transaction(mut self, transaction: SignedTransaction) -> Self where Self: Sized {
self.transactions.push(transaction);
self
}
}
impl CompleteBlock for Block {
fn complete(mut self, parent_hash: H256) -> Bytes {
self.header.set_parent_hash(parent_hash);
encode(&self).into_vec()
}
}

View File

@@ -1,35 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bigint::hash::H2048;
pub trait WithBloom {
fn with_bloom(self, bloom: H2048) -> Self where Self: Sized;
}
pub struct Bloom<'a, I> where I: 'a {
pub iter: &'a mut I,
pub bloom: H2048,
}
impl<'a, I> Iterator for Bloom<'a, I> where I: Iterator, <I as Iterator>::Item: WithBloom {
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|item| item.with_bloom(self.bloom.clone()))
}
}

View File

@@ -1,52 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bigint::hash::H256;
use bytes::Bytes;
use views::BlockView;
#[derive(Default, Clone)]
pub struct BlockFinalizer {
parent_hash: H256
}
impl BlockFinalizer {
pub fn fork(&self) -> Self {
self.clone()
}
}
pub trait CompleteBlock {
fn complete(self, parent_hash: H256) -> Bytes;
}
pub struct Complete<'a, I> where I: 'a {
pub iter: &'a mut I,
pub finalizer: &'a mut BlockFinalizer,
}
impl<'a, I> Iterator for Complete<'a, I> where I: Iterator, <I as Iterator>::Item: CompleteBlock {
type Item = Bytes;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|item| {
let rlp = item.complete(self.finalizer.parent_hash.clone());
self.finalizer.parent_hash = BlockView::new(&rlp).header_view().hash();
rlp
})
}
}

View File

@@ -1,42 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
pub trait Forkable {
fn fork(self, fork_number: usize) -> Self where Self: Sized;
}
pub struct Fork<I> {
pub iter: I,
pub fork_number: usize,
}
impl<I> Clone for Fork<I> where I: Iterator + Clone {
fn clone(&self) -> Self {
Fork {
iter: self.iter.clone(),
fork_number: self.fork_number
}
}
}
impl<I> Iterator for Fork<I> where I: Iterator, <I as Iterator>::Item: Forkable {
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|item| item.fork(self.fork_number))
}
}

View File

@@ -1,179 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bigint::prelude::U256;
use bigint::hash::H2048;
use bytes::Bytes;
use header::BlockNumber;
use transaction::SignedTransaction;
use super::fork::Fork;
use super::bloom::Bloom;
use super::complete::{BlockFinalizer, CompleteBlock, Complete};
use super::block::Block;
use super::transaction::Transaction;
/// Chain iterator interface.
pub trait ChainIterator: Iterator + Sized {
/// Should be called to create a fork of current iterator.
/// Blocks generated by fork will have lower difficulty than current chain.
fn fork(&self, fork_number: usize) -> Fork<Self> where Self: Clone;
/// Should be called to make every consecutive block have given bloom.
fn with_bloom(&mut self, bloom: H2048) -> Bloom<Self>;
/// Should be called to make every consecutive block have given transaction.
fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction<Self>;
/// Should be called to complete block. Without complete, block may have incorrect hash.
fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self>;
/// Completes and generates block.
fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option<Bytes> where Self::Item: CompleteBlock;
}
impl<I> ChainIterator for I where I: Iterator + Sized {
fn fork(&self, fork_number: usize) -> Fork<Self> where I: Clone {
Fork {
iter: self.clone(),
fork_number: fork_number
}
}
fn with_bloom(&mut self, bloom: H2048) -> Bloom<Self> {
Bloom {
iter: self,
bloom: bloom
}
}
fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction<Self> {
Transaction {
iter: self,
transaction: transaction,
}
}
fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self> {
Complete {
iter: self,
finalizer: finalizer
}
}
fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option<Bytes> where <I as Iterator>::Item: CompleteBlock {
self.complete(finalizer).next()
}
}
/// Blockchain generator.
#[derive(Clone)]
pub struct ChainGenerator {
/// Next block number.
number: BlockNumber,
/// Next block difficulty.
difficulty: U256,
}
impl ChainGenerator {
fn prepare_block(&self) -> Block {
let mut block = Block::default();
block.header.set_number(self.number);
block.header.set_difficulty(self.difficulty);
block
}
}
impl Default for ChainGenerator {
fn default() -> Self {
ChainGenerator {
number: 0,
difficulty: 1000.into(),
}
}
}
impl Iterator for ChainGenerator {
type Item = Block;
fn next(&mut self) -> Option<Self::Item> {
let block = self.prepare_block();
self.number += 1;
Some(block)
}
}
mod tests {
use bigint::hash::{H256, H2048};
use views::BlockView;
use blockchain::generator::{ChainIterator, ChainGenerator, BlockFinalizer};
#[test]
fn canon_chain_generator() {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
let genesis_rlp = canon_chain.generate(&mut finalizer).unwrap();
let genesis = BlockView::new(&genesis_rlp);
assert_eq!(genesis.header_view().parent_hash(), H256::default());
assert_eq!(genesis.header_view().number(), 0);
let b1_rlp = canon_chain.generate(&mut finalizer).unwrap();
let b1 = BlockView::new(&b1_rlp);
assert_eq!(b1.header_view().parent_hash(), genesis.header_view().hash());
assert_eq!(b1.header_view().number(), 1);
let mut fork_chain = canon_chain.fork(1);
let b2_rlp_fork = fork_chain.generate(&mut finalizer.fork()).unwrap();
let b2_fork = BlockView::new(&b2_rlp_fork);
assert_eq!(b2_fork.header_view().parent_hash(), b1.header_view().hash());
assert_eq!(b2_fork.header_view().number(), 2);
let b2_rlp = canon_chain.generate(&mut finalizer).unwrap();
let b2 = BlockView::new(&b2_rlp);
assert_eq!(b2.header_view().parent_hash(), b1.header_view().hash());
assert_eq!(b2.header_view().number(), 2);
assert!(b2.header_view().difficulty() > b2_fork.header_view().difficulty());
}
#[test]
fn with_bloom_generator() {
let bloom = H2048([0x1; 256]);
let mut gen = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
let block0_rlp = gen.with_bloom(bloom).generate(&mut finalizer).unwrap();
let block1_rlp = gen.generate(&mut finalizer).unwrap();
let block0 = BlockView::new(&block0_rlp);
let block1 = BlockView::new(&block1_rlp);
assert_eq!(block0.header_view().number(), 0);
assert_eq!(block0.header_view().parent_hash(), H256::default());
assert_eq!(block1.header_view().number(), 1);
assert_eq!(block1.header_view().parent_hash(), block0.header_view().hash());
}
#[test]
fn generate_1000_blocks() {
let generator = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
let blocks: Vec<_> = generator.take(1000).complete(&mut finalizer).collect();
assert_eq!(blocks.len(), 1000);
}
}

View File

@@ -1,27 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain generator for tests.
mod bloom;
mod block;
mod complete;
mod fork;
pub mod generator;
mod transaction;
pub use self::complete::BlockFinalizer;
pub use self::generator::{ChainIterator, ChainGenerator};

View File

@@ -1,35 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use transaction::SignedTransaction;
pub trait WithTransaction {
fn with_transaction(self, transaction: SignedTransaction) -> Self where Self: Sized;
}
pub struct Transaction<'a, I> where I: 'a {
pub iter: &'a mut I,
pub transaction: SignedTransaction,
}
impl <'a, I> Iterator for Transaction<'a, I> where I: Iterator, <I as Iterator>::Item: WithTransaction {
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|item| item.with_transaction(self.transaction.clone()))
}
}

View File

@@ -2,8 +2,7 @@ use std::collections::HashMap;
use bigint::hash::H256;
use header::BlockNumber;
use blockchain::block_info::BlockInfo;
use blooms::BloomGroup;
use super::extras::{BlockDetails, BlockReceipts, TransactionAddress, LogGroupPosition};
use blockchain::extras::{BlockDetails, BlockReceipts, TransactionAddress};
/// Block extras update info.
pub struct ExtrasUpdate<'a> {
@@ -19,8 +18,6 @@ pub struct ExtrasUpdate<'a> {
pub block_details: HashMap<H256, BlockDetails>,
/// Modified block receipts.
pub block_receipts: HashMap<H256, BlockReceipts>,
/// Modified blocks blooms.
pub blocks_blooms: HashMap<LogGroupPosition, BloomGroup>,
/// Modified transaction addresses (None signifies removed transactions).
pub transactions_addresses: HashMap<H256, Option<TransactionAddress>>,
}

View File

@@ -1,74 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bloomchain::group as bc;
use rlp::*;
use heapsize::HeapSizeOf;
use super::Bloom;
/// Represents group of X consecutive blooms.
#[derive(Debug, Clone)]
pub struct BloomGroup {
blooms: Vec<Bloom>,
}
impl From<bc::BloomGroup> for BloomGroup {
fn from(group: bc::BloomGroup) -> Self {
let blooms = group.blooms
.into_iter()
.map(From::from)
.collect();
BloomGroup {
blooms: blooms
}
}
}
impl Into<bc::BloomGroup> for BloomGroup {
fn into(self) -> bc::BloomGroup {
let blooms = self.blooms
.into_iter()
.map(Into::into)
.collect();
bc::BloomGroup {
blooms: blooms
}
}
}
impl Decodable for BloomGroup {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let blooms = rlp.as_list()?;
let group = BloomGroup {
blooms: blooms
};
Ok(group)
}
}
impl Encodable for BloomGroup {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.blooms);
}
}
impl HeapSizeOf for BloomGroup {
fn heap_size_of_children(&self) -> usize {
self.blooms.heap_size_of_children()
}
}

View File

@@ -1,42 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bloomchain::group as bc;
use heapsize::HeapSizeOf;
/// Represents `BloomGroup` position in database.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct GroupPosition {
/// Bloom level.
pub level: u8,
/// Group index.
pub index: u32,
}
impl From<bc::GroupPosition> for GroupPosition {
fn from(p: bc::GroupPosition) -> Self {
GroupPosition {
level: p.level as u8,
index: p.index as u32,
}
}
}
impl HeapSizeOf for GroupPosition {
fn heap_size_of_children(&self) -> usize {
0
}
}

View File

@@ -1673,17 +1673,8 @@ impl BlockChainClient for Client {
};
let chain = self.chain.read();
let blocks = filter.bloom_possibilities().iter()
.map(move |bloom| {
chain.blocks_with_bloom(bloom, from, to)
})
.flat_map(|m| m)
// remove duplicate elements
.collect::<HashSet<u64>>()
.into_iter()
.collect::<Vec<u64>>();
self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit)
let blocks = chain.blocks_with_blooms(&filter.bloom_possibilities(), from, to);
chain.logs(blocks, |entry| filter.matches(entry), filter.limit)
}
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {

View File

@@ -54,7 +54,6 @@
//! cargo build --release
//! ```
extern crate bloomchain;
extern crate bn;
extern crate byteorder;
extern crate crossbeam;
@@ -155,7 +154,6 @@ pub mod verification;
pub mod views;
mod cache_manager;
mod blooms;
mod basic_types;
mod pod_account;
mod state_db;

View File

@@ -57,6 +57,8 @@ pub enum Error {
VersionNotSupported(u64),
/// Max chunk size is to small to fit basic account data.
ChunkTooSmall,
/// Oversized chunk
ChunkTooLarge,
/// Snapshots not supported by the consensus engine.
SnapshotsUnsupported,
/// Bad epoch transition.
@@ -85,6 +87,7 @@ impl fmt::Display for Error {
Error::Trie(ref err) => err.fmt(f),
Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver),
Error::ChunkTooSmall => write!(f, "Chunk size is too small."),
Error::ChunkTooLarge => write!(f, "Chunk size is too large."),
Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."),
Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i),
Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg),

View File

@@ -77,6 +77,11 @@ mod traits;
// Try to have chunks be around 4MB (before compression)
const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
// Maximal chunk size (decompressed)
// Snappy::decompressed_len estimation may sometimes yield results greater
// than PREFERRED_CHUNK_SIZE so allow some threshold here.
const MAX_CHUNK_SIZE: usize = PREFERRED_CHUNK_SIZE / 4 * 5;
// Minimum supported state chunk version.
const MIN_SUPPORTED_STATE_CHUNK_VERSION: u64 = 1;
// current state chunk version.

View File

@@ -23,7 +23,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService};
use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE};
use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter};
use blockchain::BlockChain;
@@ -130,6 +130,11 @@ impl Restoration {
// feeds a state chunk, aborts early if `flag` becomes false.
fn feed_state(&mut self, hash: H256, chunk: &[u8], flag: &AtomicBool) -> Result<(), Error> {
if self.state_chunks_left.contains(&hash) {
let expected_len = snappy::decompressed_len(chunk)?;
if expected_len > MAX_CHUNK_SIZE {
trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE);
return Err(::snapshot::Error::ChunkTooLarge.into());
}
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
self.state.feed(&self.snappy_buffer[..len], flag)?;
@@ -147,6 +152,11 @@ impl Restoration {
// feeds a block chunk
fn feed_blocks(&mut self, hash: H256, chunk: &[u8], engine: &EthEngine, flag: &AtomicBool) -> Result<(), Error> {
if self.block_chunks_left.contains(&hash) {
let expected_len = snappy::decompressed_len(chunk)?;
if expected_len > MAX_CHUNK_SIZE {
trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE);
return Err(::snapshot::Error::ChunkTooLarge.into());
}
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
self.secondary.feed(&self.snappy_buffer[..len], engine, flag)?;

View File

@@ -19,7 +19,7 @@
use devtools::RandomTempPath;
use error::Error;
use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer};
use blockchain::generator::{BlockGenerator, BlockBuilder};
use blockchain::BlockChain;
use snapshot::{chunk_secondary, Error as SnapshotError, Progress, SnapshotComponents};
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
@@ -35,9 +35,10 @@ use std::sync::atomic::AtomicBool;
const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 };
fn chunk_and_restore(amount: u64) {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
let genesis = canon_chain.generate(&mut finalizer).unwrap();
let genesis = BlockBuilder::genesis();
let rest = genesis.add_blocks(amount as usize);
let generator = BlockGenerator::new(vec![rest]);
let genesis = genesis.last();
let engine = ::spec::Spec::new_test().engine;
let new_path = RandomTempPath::create_dir();
@@ -45,13 +46,12 @@ fn chunk_and_restore(amount: u64) {
snapshot_path.push("SNAP");
let old_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)));
let bc = BlockChain::new(Default::default(), &genesis, old_db.clone());
let bc = BlockChain::new(Default::default(), &genesis.encoded(), old_db.clone());
// build the blockchain.
let mut batch = DBTransaction::new();
for _ in 0..amount {
let block = canon_chain.generate(&mut finalizer).unwrap();
bc.insert_block(&mut batch, &block, vec![]);
for block in generator {
bc.insert_block(&mut batch, &block.encoded(), vec![]);
bc.commit();
}
@@ -82,7 +82,7 @@ fn chunk_and_restore(amount: u64) {
// restore it.
let new_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)));
let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone());
let new_chain = BlockChain::new(Default::default(), &genesis.encoded(), new_db.clone());
let mut rebuilder = SNAPSHOT_MODE.rebuilder(new_chain, new_db.clone(), &manifest).unwrap();
let reader = PackedReader::new(&snapshot_path).unwrap().unwrap();
@@ -97,15 +97,19 @@ fn chunk_and_restore(amount: u64) {
drop(rebuilder);
// and test it.
let new_chain = BlockChain::new(Default::default(), &genesis, new_db);
let new_chain = BlockChain::new(Default::default(), &genesis.encoded(), new_db);
assert_eq!(new_chain.best_block_hash(), best_hash);
}
#[test]
fn chunk_and_restore_500() { chunk_and_restore(500) }
fn chunk_and_restore_500() {
chunk_and_restore(500)
}
#[test]
fn chunk_and_restore_40k() { chunk_and_restore(40000) }
fn chunk_and_restore_4k() {
chunk_and_restore(4000)
}
#[test]
fn checks_flag() {
@@ -120,17 +124,12 @@ fn checks_flag() {
stream.append_empty_data().append_empty_data();
let genesis = {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
canon_chain.generate(&mut finalizer).unwrap()
};
let genesis = BlockBuilder::genesis();
let chunk = stream.out();
let db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)));
let engine = ::spec::Spec::new_test().engine;
let chain = BlockChain::new(Default::default(), &genesis, db.clone());
let chain = BlockChain::new(Default::default(), &genesis.last().encoded(), db.clone());
let manifest = ::snapshot::ManifestData {
version: 2,

View File

@@ -1,77 +0,0 @@
use bloomchain::Bloom;
use bloomchain::group::{BloomGroup, GroupPosition};
use basic_types::LogBloom;
/// Helper structure representing bloom of the trace.
#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloom(LogBloom);
impl From<LogBloom> for BlockTracesBloom {
fn from(bloom: LogBloom) -> BlockTracesBloom {
BlockTracesBloom(bloom)
}
}
impl From<Bloom> for BlockTracesBloom {
fn from(bloom: Bloom) -> BlockTracesBloom {
let bytes: [u8; 256] = bloom.into();
BlockTracesBloom(LogBloom::from(bytes))
}
}
impl Into<Bloom> for BlockTracesBloom {
fn into(self) -> Bloom {
let log = self.0;
Bloom::from(log.0)
}
}
/// Represents group of X consecutive blooms.
#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloomGroup {
blooms: Vec<BlockTracesBloom>,
}
impl From<BloomGroup> for BlockTracesBloomGroup {
fn from(group: BloomGroup) -> Self {
let blooms = group.blooms
.into_iter()
.map(From::from)
.collect();
BlockTracesBloomGroup {
blooms: blooms
}
}
}
impl Into<BloomGroup> for BlockTracesBloomGroup {
fn into(self) -> BloomGroup {
let blooms = self.blooms
.into_iter()
.map(Into::into)
.collect();
BloomGroup {
blooms: blooms
}
}
}
/// Represents `BloomGroup` position in database.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct TraceGroupPosition {
/// Bloom level.
pub level: u8,
/// Group index.
pub index: u32,
}
impl From<GroupPosition> for TraceGroupPosition {
fn from(p: GroupPosition) -> Self {
TraceGroupPosition {
level: p.level as u8,
index: p.index as u32,
}
}
}

View File

@@ -15,7 +15,6 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Traces config.
use bloomchain::Config as BloomConfig;
/// Traces config.
#[derive(Debug, PartialEq, Clone)]
@@ -23,8 +22,6 @@ pub struct Config {
/// Indicates if tracing should be enabled or not.
/// If it's None, it will be automatically configured.
pub enabled: bool,
/// Traces blooms configuration.
pub blooms: BloomConfig,
/// Preferef cache-size.
pub pref_cache_size: usize,
/// Max cache-size.
@@ -35,10 +32,6 @@ impl Default for Config {
fn default() -> Self {
Config {
enabled: false,
blooms: BloomConfig {
levels: 3,
elements_per_index: 16,
},
pref_cache_size: 15 * 1024 * 1024,
max_cache_size: 20 * 1024 * 1024,
}

View File

@@ -15,19 +15,15 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Trace database.
use std::ops::Deref;
use std::collections::{HashMap, VecDeque};
use std::sync::Arc;
use bloomchain::{Number, Config as BloomConfig};
use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup};
use heapsize::HeapSizeOf;
use bigint::hash::{H256, H264};
use bigint::hash::{H256, H264, H2048 as Bloom};
use kvdb::{KeyValueDB, DBTransaction};
use parking_lot::RwLock;
use header::BlockNumber;
use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras};
use db::{self, Key, Writable, Readable, CacheUpdatePolicy};
use blooms;
use super::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces};
use cache_manager::CacheManager;
@@ -37,8 +33,8 @@ const TRACE_DB_VER: &'static [u8] = b"1.0";
enum TraceDBIndex {
/// Block traces index.
BlockTraces = 0,
/// Trace bloom group index.
BloomGroups = 1,
/// Blooms index.
Blooms = 2,
}
impl Key<FlatBlockTraces> for H256 {
@@ -52,80 +48,37 @@ impl Key<FlatBlockTraces> for H256 {
}
}
/// Wrapper around `blooms::GroupPosition` so it could be
/// uniquely identified in the database.
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
struct TraceGroupPosition(blooms::GroupPosition);
impl Key<Bloom> for H256 {
type Target = H264;
impl From<GroupPosition> for TraceGroupPosition {
fn from(position: GroupPosition) -> Self {
TraceGroupPosition(From::from(position))
}
}
impl HeapSizeOf for TraceGroupPosition {
fn heap_size_of_children(&self) -> usize {
0
}
}
/// Helper data structure created cause [u8; 6] does not implement Deref to &[u8].
pub struct TraceGroupKey([u8; 6]);
impl Deref for TraceGroupKey {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Key<blooms::BloomGroup> for TraceGroupPosition {
type Target = TraceGroupKey;
fn key(&self) -> Self::Target {
let mut result = [0u8; 6];
result[0] = TraceDBIndex::BloomGroups as u8;
result[1] = self.0.level;
result[2] = self.0.index as u8;
result[3] = (self.0.index >> 8) as u8;
result[4] = (self.0.index >> 16) as u8;
result[5] = (self.0.index >> 24) as u8;
TraceGroupKey(result)
fn key(&self) -> H264 {
let mut result = H264::default();
result[0] = TraceDBIndex::Blooms as u8;
result[1..33].copy_from_slice(self);
result
}
}
#[derive(Debug, Hash, Eq, PartialEq)]
enum CacheId {
Trace(H256),
Bloom(TraceGroupPosition),
Bloom(H256),
}
/// Trace database.
pub struct TraceDB<T> where T: DatabaseExtras {
// cache
traces: RwLock<HashMap<H256, FlatBlockTraces>>,
blooms: RwLock<HashMap<TraceGroupPosition, blooms::BloomGroup>>,
blooms: RwLock<HashMap<H256, Bloom>>,
cache_manager: RwLock<CacheManager<CacheId>>,
// db
tracesdb: Arc<KeyValueDB>,
// config,
bloom_config: BloomConfig,
// tracing enabled
enabled: bool,
// extras
extras: Arc<T>,
}
impl<T> BloomGroupDatabase for TraceDB<T> where T: DatabaseExtras {
fn blooms_at(&self, position: &GroupPosition) -> Option<BloomGroup> {
let position = TraceGroupPosition::from(position.clone());
let result = self.tracesdb.read_with_cache(db::COL_TRACE, &self.blooms, &position).map(Into::into);
self.note_used(CacheId::Bloom(position));
result
}
}
impl<T> TraceDB<T> where T: DatabaseExtras {
/// Creates new instance of `TraceDB`.
pub fn new(config: Config, tracesdb: Arc<KeyValueDB>, extras: Arc<T>) -> Self {
@@ -137,13 +90,12 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
tracesdb.write(batch).expect("failed to update version");
TraceDB {
traces: RwLock::new(HashMap::new()),
blooms: RwLock::new(HashMap::new()),
cache_manager: RwLock::new(CacheManager::new(config.pref_cache_size, config.max_cache_size, 10 * 1024)),
tracesdb: tracesdb,
bloom_config: config.blooms,
tracesdb,
enabled: config.enabled,
extras: extras,
extras,
traces: RwLock::default(),
blooms: RwLock::default(),
}
}
@@ -188,6 +140,12 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
result
}
fn bloom(&self, block_hash: &H256) -> Option<Bloom> {
let result = self.tracesdb.read_with_cache(db::COL_TRACE, &self.blooms, block_hash);
self.note_used(CacheId::Bloom(block_hash.clone()));
result
}
/// Returns vector of transaction traces for given block.
fn transactions_traces(&self, block_hash: &H256) -> Option<Vec<FlatTransactionTraces>> {
self.traces(block_hash).map(Into::into)
@@ -264,49 +222,16 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
return;
}
// now let's rebuild the blooms
if !request.enacted.is_empty() {
let range_start = request.block_number as Number + 1 - request.enacted.len();
let range_end = range_start + request.retracted;
let replaced_range = range_start..range_end;
let enacted_blooms = request.enacted
.iter()
// all traces are expected to be found here. That's why `expect` has been used
// instead of `filter_map`. If some traces haven't been found, it meens that
// traces database is corrupted or incomplete.
.map(|block_hash| if block_hash == &request.block_hash {
request.traces.bloom()
} else {
self.traces(block_hash).expect("Traces database is incomplete.").bloom()
})
.map(blooms::Bloom::from)
.map(Into::into)
.collect();
let chain = BloomGroupChain::new(self.bloom_config, self);
let trace_blooms = chain.replace(&replaced_range, enacted_blooms);
let blooms_to_insert = trace_blooms.into_iter()
.map(|p| (From::from(p.0), From::from(p.1)))
.collect::<HashMap<TraceGroupPosition, blooms::BloomGroup>>();
let blooms_keys: Vec<_> = blooms_to_insert.keys().cloned().collect();
let mut blooms = self.blooms.write();
batch.extend_with_cache(db::COL_TRACE, &mut *blooms, blooms_to_insert, CacheUpdatePolicy::Remove);
// note_used must be called after locking blooms to avoid cache/traces deadlock on garbage collection
for key in blooms_keys {
self.note_used(CacheId::Bloom(key));
}
}
// insert new block traces into the cache and the database
{
let mut traces = self.traces.write();
// it's important to use overwrite here,
// cause this value might be queried by hash later
batch.write_with_cache(db::COL_TRACE, &mut *traces, request.block_hash, request.traces, CacheUpdatePolicy::Overwrite);
// note_used must be called after locking traces to avoid cache/traces deadlock on garbage collection
self.note_used(CacheId::Trace(request.block_hash.clone()));
}
let mut traces = self.traces.write();
let mut blooms = self.blooms.write();
// it's important to use overwrite here,
// cause this value might be queried by hash later
batch.write_with_cache(db::COL_TRACE, &mut *blooms, request.block_hash, request.traces.bloom(), CacheUpdatePolicy::Overwrite);
batch.write_with_cache(db::COL_TRACE, &mut *traces, request.block_hash, request.traces, CacheUpdatePolicy::Overwrite);
// note_used must be called after locking traces to avoid cache/traces deadlock on garbage collection
self.note_used(CacheId::Trace(request.block_hash));
self.note_used(CacheId::Bloom(request.block_hash));
}
fn trace(&self, block_number: BlockNumber, tx_position: usize, trace_position: Vec<usize>) -> Option<LocalizedTrace> {
@@ -393,15 +318,17 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
}
fn filter(&self, filter: &Filter) -> Vec<LocalizedTrace> {
let chain = BloomGroupChain::new(self.bloom_config, self);
let numbers = chain.filter(filter);
numbers.into_iter()
.flat_map(|n| {
let number = n as BlockNumber;
let hash = self.extras.block_hash(number)
.expect("Expected to find block hash. Extras db is probably corrupted");
let traces = self.traces(&hash)
.expect("Expected to find a trace. Db is probably corrupted.");
let possibilities = filter.bloom_possibilities();
// + 1, cause filters are inclusive
(filter.range.start..filter.range.end + 1).into_iter()
.map(|n| n as BlockNumber)
.filter_map(|n| self.extras.block_hash(n).map(|hash| (n, hash)))
.filter(|&(_,ref hash)| {
let bloom = self.bloom(hash).expect("hash exists; qed");
possibilities.iter().any(|p| bloom.contains(p))
})
.flat_map(|(number, hash)| {
let traces = self.traces(&hash).expect("hash exists; qed");
self.matching_block_traces(filter, traces, hash, number)
})
.collect()

View File

@@ -16,7 +16,6 @@
//! Tracing
mod bloom;
mod config;
mod db;
mod executive_tracer;

View File

@@ -17,10 +17,10 @@
//! Trace filters type definitions
use std::ops::Range;
use bloomchain::{Filter as BloomFilter, Bloom, Number};
use hash::keccak;
use util::Address;
use bloomable::Bloomable;
use bigint::prelude::H2048 as Bloom;
use basic_types::LogBloom;
use trace::flat::FlatTrace;
use super::trace::{Action, Res};
@@ -87,22 +87,9 @@ pub struct Filter {
pub to_address: AddressesFilter,
}
impl BloomFilter for Filter {
fn bloom_possibilities(&self) -> Vec<Bloom> {
self.bloom_possibilities()
.into_iter()
.map(|b| Bloom::from(b.0))
.collect()
}
fn range(&self) -> Range<Number> {
self.range.clone()
}
}
impl Filter {
/// Returns combinations of each address.
fn bloom_possibilities(&self) -> Vec<LogBloom> {
pub fn bloom_possibilities(&self) -> Vec<Bloom> {
self.to_address.with_blooms(self.from_address.blooms())
}

View File

@@ -461,7 +461,7 @@ mod tests {
unimplemented!()
}
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
fn blocks_with_blooms(&self, _blooms: &[H2048], _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
unimplemented!()
}