LocalizedLogEntry and Filter in ethcore module
This commit is contained in:
parent
7e5e56de40
commit
b01652f3e7
@ -226,7 +226,11 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) {
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) {
|
||||||
let address = self.origin_info.address.clone();
|
let address = self.origin_info.address.clone();
|
||||||
self.substate.logs.push(LogEntry::new(address, topics, data.to_vec()));
|
self.substate.logs.push(LogEntry {
|
||||||
|
address: address,
|
||||||
|
topics: topics,
|
||||||
|
data: data.to_vec()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suicide(&mut self, refund_address: &Address) {
|
fn suicide(&mut self, refund_address: &Address) {
|
||||||
|
152
ethcore/src/filter.rs
Normal file
152
ethcore/src/filter.rs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (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 util::hash::*;
|
||||||
|
use util::sha3::*;
|
||||||
|
use client::BlockId;
|
||||||
|
|
||||||
|
/// Blockchain log filter data.
|
||||||
|
pub struct Filter {
|
||||||
|
/// Blockchain will be searched from this block.
|
||||||
|
from_block: BlockId,
|
||||||
|
|
||||||
|
/// Till this block.
|
||||||
|
to_block: BlockId,
|
||||||
|
|
||||||
|
/// Search addresses.
|
||||||
|
///
|
||||||
|
/// If None, match all.
|
||||||
|
/// If specified, log must be produced by one of these addresses.
|
||||||
|
address: Option<Vec<Address>>,
|
||||||
|
|
||||||
|
/// Search topics.
|
||||||
|
///
|
||||||
|
/// If None, match all.
|
||||||
|
/// If specified, log must contain one of these topics.
|
||||||
|
topics: [Option<Vec<H256>>; 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Filter {
|
||||||
|
/// Returns combinations of each address and topic.
|
||||||
|
pub fn bloom_possibilities(&self) -> Vec<H2048> {
|
||||||
|
let blooms = match self.address {
|
||||||
|
Some(ref addresses) if !addresses.is_empty() =>
|
||||||
|
addresses.iter().map(|ref address| {
|
||||||
|
let mut bloom = H2048::new();
|
||||||
|
bloom.shift_bloomed(&address.sha3());
|
||||||
|
bloom
|
||||||
|
}).collect(),
|
||||||
|
_ => vec![H2048::new()]
|
||||||
|
};
|
||||||
|
|
||||||
|
self.topics.iter().fold(blooms, | bs, topic | match *topic {
|
||||||
|
None => bs,
|
||||||
|
Some(ref topics) => bs.into_iter().map(|bloom| {
|
||||||
|
topics.into_iter().map(|topic| {
|
||||||
|
let mut b = bloom.clone();
|
||||||
|
b.shift_bloomed(&topic.sha3());
|
||||||
|
b
|
||||||
|
}).collect::<Vec<H2048>>()
|
||||||
|
}).flat_map(|m| m).collect()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::str::FromStr;
|
||||||
|
use util::hash::*;
|
||||||
|
use filter::Filter;
|
||||||
|
use client::BlockId;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bloom_possibilities_none() {
|
||||||
|
let none_filter = Filter {
|
||||||
|
from_block: BlockId::Earliest,
|
||||||
|
to_block: BlockId::Latest,
|
||||||
|
address: None,
|
||||||
|
topics: [None, None, None, None]
|
||||||
|
};
|
||||||
|
|
||||||
|
let possibilities = none_filter.bloom_possibilities();
|
||||||
|
assert_eq!(possibilities.len(), 1);
|
||||||
|
assert!(possibilities[0].is_zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
// block 399849
|
||||||
|
#[test]
|
||||||
|
fn test_bloom_possibilities_single_address_and_topic() {
|
||||||
|
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()]),
|
||||||
|
None, None, None
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let possibilities = filter.bloom_possibilities();
|
||||||
|
assert_eq!(possibilities, vec![H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bloom_possibilities_single_address_and_many_topics() {
|
||||||
|
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("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]),
|
||||||
|
None, None
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let possibilities = filter.bloom_possibilities();
|
||||||
|
assert_eq!(possibilities, vec![H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bloom_possibilites_multiple_addresses_and_topics() {
|
||||||
|
let filter = Filter {
|
||||||
|
from_block: BlockId::Earliest,
|
||||||
|
to_block: BlockId::Latest,
|
||||||
|
address: Some(vec![
|
||||||
|
Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(),
|
||||||
|
Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(),
|
||||||
|
]),
|
||||||
|
topics: [
|
||||||
|
Some(vec![
|
||||||
|
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
|
||||||
|
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()
|
||||||
|
]),
|
||||||
|
Some(vec![
|
||||||
|
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(),
|
||||||
|
H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()
|
||||||
|
]),
|
||||||
|
Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]),
|
||||||
|
None
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// number of possibilites should be equal 2 * 2 * 2 * 1 = 8
|
||||||
|
let possibilities = filter.bloom_possibilities();
|
||||||
|
assert_eq!(possibilities.len(), 8);
|
||||||
|
assert_eq!(possibilities[0], H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -131,6 +131,7 @@ mod substate;
|
|||||||
mod executive;
|
mod executive;
|
||||||
mod externalities;
|
mod externalities;
|
||||||
mod verification;
|
mod verification;
|
||||||
|
mod filter;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -38,15 +38,6 @@ impl Encodable for LogEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LogEntry {
|
impl LogEntry {
|
||||||
/// Create a new log entry.
|
|
||||||
pub fn new(address: Address, topics: Vec<H256>, data: Bytes) -> LogEntry {
|
|
||||||
LogEntry {
|
|
||||||
address: address,
|
|
||||||
topics: topics,
|
|
||||||
data: data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates the bloom of this log entry.
|
/// Calculates the bloom of this log entry.
|
||||||
pub fn bloom(&self) -> LogBloom {
|
pub fn bloom(&self) -> LogBloom {
|
||||||
self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3()))
|
self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3()))
|
||||||
@ -65,6 +56,31 @@ impl FromJson for LogEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Log localized in a blockchain.
|
||||||
|
#[derive(Default, Debug, PartialEq)]
|
||||||
|
pub struct LocalizedLogEntry {
|
||||||
|
/// Plain log entry.
|
||||||
|
pub entry: LogEntry,
|
||||||
|
/// Block in which this log was created.
|
||||||
|
pub block_hash: H256,
|
||||||
|
/// Block number.
|
||||||
|
pub block_number: usize,
|
||||||
|
/// Hash of transaction in which this log was created.
|
||||||
|
pub transaction_hash: H256,
|
||||||
|
/// Index of transaction within block.
|
||||||
|
pub transaction_index: usize,
|
||||||
|
/// Log position in the block.
|
||||||
|
pub log_index: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for LocalizedLogEntry {
|
||||||
|
type Target = LogEntry;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use util::*;
|
use util::*;
|
||||||
@ -74,7 +90,11 @@ mod tests {
|
|||||||
fn test_empty_log_bloom() {
|
fn test_empty_log_bloom() {
|
||||||
let bloom = H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
|
let bloom = H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let log = LogEntry::new(address, vec![], vec![]);
|
let log = LogEntry {
|
||||||
|
address: address,
|
||||||
|
topics: vec![],
|
||||||
|
data: vec![]
|
||||||
|
};
|
||||||
assert_eq!(log.bloom(), bloom);
|
assert_eq!(log.bloom(), bloom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,11 @@ fn test_basic() {
|
|||||||
let r = Receipt::new(
|
let r = Receipt::new(
|
||||||
x!("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee"),
|
x!("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee"),
|
||||||
x!(0x40cae),
|
x!(0x40cae),
|
||||||
vec![LogEntry::new(
|
vec![LogEntry {
|
||||||
x!("dcf421d093428b096ca501a7cd1a740855a7976f"),
|
address: x!("dcf421d093428b096ca501a7cd1a740855a7976f"),
|
||||||
vec![],
|
topics: vec![],
|
||||||
vec![0u8; 32]
|
data: vec![0u8; 32]
|
||||||
)]
|
}]
|
||||||
);
|
);
|
||||||
assert_eq!(&encode(&r)[..], &expected[..]);
|
assert_eq!(&encode(&r)[..], &expected[..]);
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,21 @@ mod tests {
|
|||||||
fn accrue() {
|
fn accrue() {
|
||||||
let mut sub_state = Substate::new();
|
let mut sub_state = Substate::new();
|
||||||
sub_state.contracts_created.push(address_from_u64(1u64));
|
sub_state.contracts_created.push(address_from_u64(1u64));
|
||||||
sub_state.logs.push(LogEntry::new(address_from_u64(1u64), vec![], vec![]));
|
sub_state.logs.push(LogEntry {
|
||||||
|
address: address_from_u64(1u64),
|
||||||
|
topics: vec![],
|
||||||
|
data: vec![]
|
||||||
|
});
|
||||||
sub_state.sstore_clears_count = x!(5);
|
sub_state.sstore_clears_count = x!(5);
|
||||||
sub_state.suicides.insert(address_from_u64(10u64));
|
sub_state.suicides.insert(address_from_u64(10u64));
|
||||||
|
|
||||||
let mut sub_state_2 = Substate::new();
|
let mut sub_state_2 = Substate::new();
|
||||||
sub_state_2.contracts_created.push(address_from_u64(2u64));
|
sub_state_2.contracts_created.push(address_from_u64(2u64));
|
||||||
sub_state_2.logs.push(LogEntry::new(address_from_u64(1u64), vec![], vec![]));
|
sub_state_2.logs.push(LogEntry {
|
||||||
|
address: address_from_u64(1u64),
|
||||||
|
topics: vec![],
|
||||||
|
data: vec![]
|
||||||
|
});
|
||||||
sub_state_2.sstore_clears_count = x!(7);
|
sub_state_2.sstore_clears_count = x!(7);
|
||||||
|
|
||||||
sub_state.accrue(sub_state_2);
|
sub_state.accrue(sub_state_2);
|
||||||
|
Loading…
Reference in New Issue
Block a user