extras refactored
This commit is contained in:
parent
3862d639bc
commit
2251c469b8
38
src/block.rs
38
src/block.rs
@ -5,6 +5,7 @@ use util::sha3::*;
|
|||||||
use blockheader::*;
|
use blockheader::*;
|
||||||
use state::*;
|
use state::*;
|
||||||
use transaction::*;
|
use transaction::*;
|
||||||
|
use extras::*;
|
||||||
|
|
||||||
/// view onto block rlp
|
/// view onto block rlp
|
||||||
pub struct BlockView<'a> {
|
pub struct BlockView<'a> {
|
||||||
@ -12,40 +13,73 @@ pub struct BlockView<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BlockView<'a> {
|
impl<'a> BlockView<'a> {
|
||||||
|
/// Creates new view onto block from raw bytes
|
||||||
pub fn new(bytes: &'a [u8]) -> BlockView<'a> {
|
pub fn new(bytes: &'a [u8]) -> BlockView<'a> {
|
||||||
BlockView {
|
BlockView {
|
||||||
rlp: Rlp::new(bytes)
|
rlp: Rlp::new(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates new view onto block from rlp
|
||||||
pub fn new_from_rlp(rlp: Rlp<'a>) -> BlockView<'a> {
|
pub fn new_from_rlp(rlp: Rlp<'a>) -> BlockView<'a> {
|
||||||
BlockView {
|
BlockView {
|
||||||
rlp: rlp
|
rlp: rlp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rlp(&self) -> &Rlp<'a> { &self.rlp }
|
/// Return reference to underlaying rlp
|
||||||
pub fn header(&self) -> Header { self.rlp.val_at(0) }
|
pub fn rlp(&self) -> &Rlp<'a> {
|
||||||
|
&self.rlp
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new Header object from header rlp
|
||||||
|
pub fn header(&self) -> Header {
|
||||||
|
self.rlp.val_at(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new header view obto block head rlp
|
||||||
pub fn header_view(&self) -> HeaderView<'a> {
|
pub fn header_view(&self) -> HeaderView<'a> {
|
||||||
HeaderView::new_from_rlp(self.rlp.at(0))
|
HeaderView::new_from_rlp(self.rlp.at(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return List of transactions in given block
|
||||||
pub fn transactions(&self) -> Vec<Transaction> {
|
pub fn transactions(&self) -> Vec<Transaction> {
|
||||||
self.rlp.val_at(1)
|
self.rlp.val_at(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return transaction hashes
|
||||||
pub fn transaction_hashes(&self) -> Vec<H256> {
|
pub fn transaction_hashes(&self) -> Vec<H256> {
|
||||||
self.rlp.at(1).iter().map(|rlp| rlp.raw().sha3()).collect()
|
self.rlp.at(1).iter().map(|rlp| rlp.raw().sha3()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return list of uncles of given block
|
||||||
pub fn uncles(&self) -> Vec<Header> {
|
pub fn uncles(&self) -> Vec<Header> {
|
||||||
self.rlp.val_at(2)
|
self.rlp.val_at(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return list of uncle hashes of given block
|
||||||
pub fn uncle_hashes(&self) -> Vec<H256> {
|
pub fn uncle_hashes(&self) -> Vec<H256> {
|
||||||
self.rlp.at(2).iter().map(|rlp| rlp.raw().sha3()).collect()
|
self.rlp.at(2).iter().map(|rlp| rlp.raw().sha3()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return BlockDetaile object of given block
|
||||||
|
/// note* children is always an empty vector,
|
||||||
|
/// cause we can't deducate them from rlp.
|
||||||
|
pub fn block_details(&self) -> BlockDetails {
|
||||||
|
let header = self.header_view();
|
||||||
|
BlockDetails {
|
||||||
|
number: header.number(),
|
||||||
|
total_difficulty: header.difficulty(),
|
||||||
|
parent: header.parent_hash(),
|
||||||
|
children: vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Hashable for BlockView<'a> {
|
||||||
|
fn sha3(&self) -> H256 {
|
||||||
|
self.header_view().sha3()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Active model of a block within the blockchain
|
/// Active model of a block within the blockchain
|
||||||
|
@ -8,15 +8,11 @@ use util::hash::*;
|
|||||||
use util::uint::*;
|
use util::uint::*;
|
||||||
use util::rlp::*;
|
use util::rlp::*;
|
||||||
use util::hashdb::*;
|
use util::hashdb::*;
|
||||||
use util::overlaydb::*;
|
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
use util::bytes::*;
|
use util::bytes::*;
|
||||||
use util::squeeze::*;
|
use util::squeeze::*;
|
||||||
use blockheader::*;
|
use blockheader::*;
|
||||||
use block::*;
|
use block::*;
|
||||||
use verifiedblock::*;
|
|
||||||
use importroute::*;
|
|
||||||
use account::*;
|
|
||||||
use genesis::*;
|
use genesis::*;
|
||||||
use extras::*;
|
use extras::*;
|
||||||
use transaction::*;
|
use transaction::*;
|
||||||
@ -31,24 +27,17 @@ pub struct CacheSize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockChain {
|
pub struct BlockChain {
|
||||||
// rlp list of 3
|
|
||||||
genesis_block: Bytes,
|
|
||||||
// genesis block header
|
|
||||||
_genesis_header: Bytes,
|
|
||||||
genesis_hash: H256,
|
|
||||||
_genesis_state: HashMap<Address, Account>,
|
|
||||||
|
|
||||||
last_block_number: Cell<U256>,
|
last_block_number: Cell<U256>,
|
||||||
|
|
||||||
// block cache
|
// block cache
|
||||||
blocks: RefCell<HashMap<H256, Bytes>>,
|
blocks: RefCell<HashMap<H256, Bytes>>,
|
||||||
|
|
||||||
// extra caches
|
// extra caches
|
||||||
block_details: Extras<H256, BlockDetails>,
|
block_details: RefCell<HashMap<H256, BlockDetails>>,
|
||||||
block_hashes: Extras<U256, H256>,
|
block_hashes: RefCell<HashMap<U256, H256>>,
|
||||||
transaction_addresses: Extras<H256, TransactionAddress>,
|
transaction_addresses: RefCell<HashMap<H256, TransactionAddress>>,
|
||||||
block_logs: Extras<H256, BlockLogBlooms>,
|
block_logs: RefCell<HashMap<H256, BlockLogBlooms>>,
|
||||||
blocks_blooms: Extras<H256, BlocksBlooms>,
|
blocks_blooms: RefCell<HashMap<H256, BlocksBlooms>>,
|
||||||
|
|
||||||
extras_db: DB,
|
extras_db: DB,
|
||||||
blocks_db: DB
|
blocks_db: DB
|
||||||
@ -74,24 +63,15 @@ impl BlockChain {
|
|||||||
/// let genesis = Genesis::new_frontier();
|
/// let genesis = Genesis::new_frontier();
|
||||||
/// let bc = BlockChain::new(genesis, &dir);
|
/// let bc = BlockChain::new(genesis, &dir);
|
||||||
/// let genesis_hash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3";
|
/// let genesis_hash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3";
|
||||||
/// assert_eq!(bc.genesis_hash(), &H256::from_str(genesis_hash).unwrap());
|
/// assert_eq!(bc.genesis_hash(), H256::from_str(genesis_hash).unwrap());
|
||||||
/// assert!(bc.is_known(bc.genesis_hash()));
|
/// assert!(bc.is_known(&bc.genesis_hash()));
|
||||||
/// assert_eq!(bc.genesis_hash(), &bc.block_hash(&U256::from(0u8)).unwrap());
|
/// assert_eq!(bc.genesis_hash(), bc.block_hash(&U256::from(0u8)).unwrap());
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(genesis: Genesis, path: &Path) -> BlockChain {
|
pub fn new(genesis: Genesis, path: &Path) -> BlockChain {
|
||||||
let (genesis_block, genesis_state) = genesis.drain();
|
let (genesis_block, _genesis_state) = genesis.drain();
|
||||||
|
|
||||||
let genesis_header = BlockView::new(&genesis_block).header_view().rlp().raw().to_vec();
|
|
||||||
let genesis_hash = HeaderView::new(&genesis_header).sha3();
|
|
||||||
|
|
||||||
let genesis_details = BlockDetails {
|
|
||||||
number: U256::from(0u64),
|
|
||||||
total_difficulty: HeaderView::new(&genesis_header).difficulty(),
|
|
||||||
parent: H256::new(),
|
|
||||||
children: vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// open dbs
|
||||||
let mut extras_path = path.to_path_buf();
|
let mut extras_path = path.to_path_buf();
|
||||||
extras_path.push("extras");
|
extras_path.push("extras");
|
||||||
let extras_db = DB::open_default(extras_path.to_str().unwrap()).unwrap();
|
let extras_db = DB::open_default(extras_path.to_str().unwrap()).unwrap();
|
||||||
@ -100,34 +80,41 @@ impl BlockChain {
|
|||||||
blocks_path.push("blocks");
|
blocks_path.push("blocks");
|
||||||
let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap();
|
let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap();
|
||||||
|
|
||||||
{
|
let bc = BlockChain {
|
||||||
let batch = WriteBatch::new();
|
|
||||||
batch.put(&genesis_hash.to_extras_slice(ExtrasIndex::BlockDetails), &encode(&genesis_details)).unwrap();
|
|
||||||
batch.put(&U256::from(0u8).to_extras_slice(ExtrasIndex::BlockHash), &encode(&genesis_hash)).unwrap();
|
|
||||||
extras_db.write(batch).unwrap();
|
|
||||||
|
|
||||||
blocks_db.put(&genesis_hash, &genesis_block).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockChain {
|
|
||||||
genesis_block: genesis_block,
|
|
||||||
_genesis_header: genesis_header,
|
|
||||||
genesis_hash: genesis_hash,
|
|
||||||
_genesis_state: genesis_state,
|
|
||||||
last_block_number: Cell::new(U256::from(0u8)),
|
last_block_number: Cell::new(U256::from(0u8)),
|
||||||
blocks: RefCell::new(HashMap::new()),
|
blocks: RefCell::new(HashMap::new()),
|
||||||
block_details: Extras::new(ExtrasIndex::BlockDetails),
|
block_details: RefCell::new(HashMap::new()),
|
||||||
block_hashes: Extras::new(ExtrasIndex::BlockHash),
|
block_hashes: RefCell::new(HashMap::new()),
|
||||||
transaction_addresses: Extras::new(ExtrasIndex::TransactionAddress),
|
transaction_addresses: RefCell::new(HashMap::new()),
|
||||||
block_logs: Extras::new(ExtrasIndex::BlockLogBlooms),
|
block_logs: RefCell::new(HashMap::new()),
|
||||||
blocks_blooms: Extras::new(ExtrasIndex::BlocksBlooms),
|
blocks_blooms: RefCell::new(HashMap::new()),
|
||||||
extras_db: extras_db,
|
extras_db: extras_db,
|
||||||
blocks_db: blocks_db
|
blocks_db: blocks_db
|
||||||
}
|
};
|
||||||
|
|
||||||
|
bc.insert_block(&genesis_block);
|
||||||
|
bc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_block(&self, _block: &[u8], _db: &OverlayDB) -> ImportRoute {
|
/// Inserts the block into backing cache database.
|
||||||
unimplemented!();
|
/// Expects the block to be valid and already verified.
|
||||||
|
/// If the block is already known, does nothing.
|
||||||
|
pub fn insert_block(&self, bytes: &[u8]) {
|
||||||
|
let block = BlockView::new(bytes);
|
||||||
|
let header = block.header_view();
|
||||||
|
|
||||||
|
if self.is_known(&header.sha3()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hash = block.sha3();
|
||||||
|
|
||||||
|
self.blocks_db.put(&hash, &bytes).unwrap();
|
||||||
|
|
||||||
|
let batch = WriteBatch::new();
|
||||||
|
batch.put_extras(&hash, &block.block_details());
|
||||||
|
batch.put_extras(&header.number(), &hash);
|
||||||
|
self.extras_db.write(batch).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the given block is known
|
/// Returns true if the given block is known
|
||||||
@ -143,8 +130,8 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns reference to genesis hash
|
/// Returns reference to genesis hash
|
||||||
pub fn genesis_hash(&self) -> &H256 {
|
pub fn genesis_hash(&self) -> H256 {
|
||||||
&self.genesis_hash
|
self.block_hash(&U256::from(0u8)).expect("Genesis hash should always exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the partial-header of a block
|
/// Get the partial-header of a block
|
||||||
@ -224,8 +211,8 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_extras<K, T>(&self, hash: &K, cache: &Extras<K, T>) -> Option<T> where
|
fn query_extras<K, T>(&self, hash: &K, cache: &RefCell<HashMap<K, T>>) -> Option<T> where
|
||||||
T: Clone + Decodable,
|
T: Clone + Decodable + ExtrasIndexable,
|
||||||
K: ExtrasSliceConvertable + Eq + Hash + Clone {
|
K: ExtrasSliceConvertable + Eq + Hash + Clone {
|
||||||
{
|
{
|
||||||
let read = cache.borrow();
|
let read = cache.borrow();
|
||||||
@ -235,22 +222,16 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = self.extras_db.get(&hash.to_extras_slice(cache.index()))
|
self.extras_db.get_extras(hash).map(| t: T | {
|
||||||
.expect("Low level database error. Some issue with disk?");
|
|
||||||
|
|
||||||
match opt {
|
|
||||||
Some(b) => {
|
|
||||||
let t: T = decode(&b);
|
|
||||||
let mut write = cache.borrow_mut();
|
let mut write = cache.borrow_mut();
|
||||||
write.insert(hash.clone(), t.clone());
|
write.insert(hash.clone(), t.clone());
|
||||||
Some(t)
|
t
|
||||||
},
|
})
|
||||||
None => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_extras_exist<K, T>(&self, hash: &K, cache: &Extras<K, T>) -> bool where
|
fn query_extras_exist<K, T>(&self, hash: &K, cache: &RefCell<HashMap<K, T>>) -> bool where
|
||||||
K: ExtrasSliceConvertable + Eq + Hash + Clone {
|
K: ExtrasSliceConvertable + Eq + Hash + Clone,
|
||||||
|
T: ExtrasIndexable {
|
||||||
{
|
{
|
||||||
let read = cache.borrow();
|
let read = cache.borrow();
|
||||||
match read.get(hash) {
|
match read.get(hash) {
|
||||||
@ -259,10 +240,7 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = self.extras_db.get(&hash.to_extras_slice(cache.index()))
|
self.extras_db.extras_exists::<_, T>(hash)
|
||||||
.expect("Low level database error. Some issue with disk?");
|
|
||||||
|
|
||||||
opt.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current cache size
|
/// Get current cache size
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::hash::Hash;
|
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
|
use rocksdb::{DB, Writable};
|
||||||
use util::uint::*;
|
use util::uint::*;
|
||||||
use util::hash::*;
|
use util::hash::*;
|
||||||
use util::rlp::*;
|
use util::rlp::*;
|
||||||
|
|
||||||
/// workaround for lack of integer templates in Rust
|
/// Represents index of extra data in database
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ExtrasIndex {
|
pub enum ExtrasIndex {
|
||||||
BlockDetails = 0,
|
BlockDetails = 0,
|
||||||
@ -17,26 +14,51 @@ pub enum ExtrasIndex {
|
|||||||
BlocksBlooms = 4
|
BlocksBlooms = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
/// rw locked extra data with slice suffix
|
/// trait used to write Extras data to db
|
||||||
// consifer if arc needed here, since blockchain itself will be wrapped
|
pub trait ExtrasWritable {
|
||||||
pub struct Extras<K, T>(RefCell<HashMap<K, T>>, ExtrasIndex) where K: Eq + Hash;
|
fn put_extras<K, T>(&self, hash: &K, value: &T) where
|
||||||
|
T: ExtrasIndexable + Encodable,
|
||||||
impl<K, T> Extras<K, T> where K: Eq + Hash {
|
K: ExtrasSliceConvertable;
|
||||||
pub fn new(i: ExtrasIndex) -> Extras<K, T> {
|
|
||||||
Extras(RefCell::new(HashMap::new()), i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(&self) -> ExtrasIndex { self.1 }
|
/// trait used to read Extras data from db
|
||||||
|
pub trait ExtrasReadable {
|
||||||
|
fn get_extras<K, T>(&self, hash: &K) -> Option<T> where
|
||||||
|
T: ExtrasIndexable + Decodable,
|
||||||
|
K: ExtrasSliceConvertable;
|
||||||
|
|
||||||
|
fn extras_exists<K, T>(&self, hash: &K) -> bool where
|
||||||
|
T: ExtrasIndexable,
|
||||||
|
K: ExtrasSliceConvertable;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, T> Deref for Extras<K, T> where K : Eq + Hash {
|
impl<W> ExtrasWritable for W where W: Writable {
|
||||||
type Target = RefCell<HashMap<K, T>>;
|
fn put_extras<K, T>(&self, hash: &K, value: &T) where
|
||||||
|
T: ExtrasIndexable + Encodable,
|
||||||
|
K: ExtrasSliceConvertable {
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
self.put(&hash.to_extras_slice(T::extras_index()), &encode(value)).unwrap()
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtrasReadable for DB {
|
||||||
|
fn get_extras<K, T>(&self, hash: &K) -> Option<T> where
|
||||||
|
T: ExtrasIndexable + Decodable,
|
||||||
|
K: ExtrasSliceConvertable {
|
||||||
|
|
||||||
|
self.get(&hash.to_extras_slice(T::extras_index())).unwrap()
|
||||||
|
.map(|v| decode(&v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extras_exists<K, T>(&self, hash: &K) -> bool where
|
||||||
|
T: ExtrasIndexable,
|
||||||
|
K: ExtrasSliceConvertable {
|
||||||
|
|
||||||
|
self.get(&hash.to_extras_slice(T::extras_index())).unwrap().is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implementations should convert arbitrary type to database key slice
|
||||||
pub trait ExtrasSliceConvertable {
|
pub trait ExtrasSliceConvertable {
|
||||||
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
|
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
|
||||||
}
|
}
|
||||||
@ -55,7 +77,18 @@ impl ExtrasSliceConvertable for U256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Types implementing this trait can be indexed in extras database
|
||||||
|
pub trait ExtrasIndexable {
|
||||||
|
fn extras_index() -> ExtrasIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtrasIndexable for H256 {
|
||||||
|
fn extras_index() -> ExtrasIndex {
|
||||||
|
ExtrasIndex::BlockHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Familial details concerning a block
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BlockDetails {
|
pub struct BlockDetails {
|
||||||
pub number: U256,
|
pub number: U256,
|
||||||
@ -64,6 +97,12 @@ pub struct BlockDetails {
|
|||||||
pub children: Vec<H256>
|
pub children: Vec<H256>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtrasIndexable for BlockDetails {
|
||||||
|
fn extras_index() -> ExtrasIndex {
|
||||||
|
ExtrasIndex::BlockDetails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HeapSizeOf for BlockDetails {
|
impl HeapSizeOf for BlockDetails {
|
||||||
fn heap_size_of_children(&self) -> usize {
|
fn heap_size_of_children(&self) -> usize {
|
||||||
self.children.heap_size_of_children()
|
self.children.heap_size_of_children()
|
||||||
@ -94,11 +133,18 @@ impl Encodable for BlockDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Log blooms of certain block
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BlockLogBlooms {
|
pub struct BlockLogBlooms {
|
||||||
pub blooms: Vec<H2048>
|
pub blooms: Vec<H2048>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtrasIndexable for BlockLogBlooms {
|
||||||
|
fn extras_index() -> ExtrasIndex {
|
||||||
|
ExtrasIndex::BlockLogBlooms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HeapSizeOf for BlockLogBlooms {
|
impl HeapSizeOf for BlockLogBlooms {
|
||||||
fn heap_size_of_children(&self) -> usize {
|
fn heap_size_of_children(&self) -> usize {
|
||||||
self.blooms.heap_size_of_children()
|
self.blooms.heap_size_of_children()
|
||||||
@ -121,10 +167,17 @@ impl Encodable for BlockLogBlooms {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Neighboring log blooms on certain level
|
||||||
pub struct BlocksBlooms {
|
pub struct BlocksBlooms {
|
||||||
pub blooms: [H2048; 16]
|
pub blooms: [H2048; 16]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtrasIndexable for BlocksBlooms {
|
||||||
|
fn extras_index() -> ExtrasIndex {
|
||||||
|
ExtrasIndex::BlocksBlooms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HeapSizeOf for BlocksBlooms {
|
impl HeapSizeOf for BlocksBlooms {
|
||||||
fn heap_size_of_children(&self) -> usize { 0 }
|
fn heap_size_of_children(&self) -> usize { 0 }
|
||||||
}
|
}
|
||||||
@ -160,12 +213,19 @@ impl Encodable for BlocksBlooms {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents address of certain transaction within block
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TransactionAddress {
|
pub struct TransactionAddress {
|
||||||
pub block_hash: H256,
|
pub block_hash: H256,
|
||||||
pub index: u64
|
pub index: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtrasIndexable for TransactionAddress {
|
||||||
|
fn extras_index() -> ExtrasIndex {
|
||||||
|
ExtrasIndex::TransactionAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HeapSizeOf for TransactionAddress {
|
impl HeapSizeOf for TransactionAddress {
|
||||||
fn heap_size_of_children(&self) -> usize { 0 }
|
fn heap_size_of_children(&self) -> usize { 0 }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user