diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 4b2246b21..3cde32e59 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -30,7 +30,7 @@ use blockchain::best_block::BestBlock; use types::tree_route::TreeRoute; use blockchain::update::ExtrasUpdate; use blockchain::{CacheSize, ImportRoute, Config}; -use db::{Writable, Readable, CacheUpdatePolicy}; +use db::{Writable, Readable, CacheUpdatePolicy, Key}; const LOG_BLOOMS_LEVELS: usize = 3; const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16; @@ -295,7 +295,34 @@ impl BlockChain { // load best block let best_block_hash = match bc.extras_db.get(b"best").unwrap() { - Some(best) => H256::from_slice(&best), + Some(best) => { + let best = H256::from_slice(&best); + let mut b = best.clone(); + let mut removed = 0; + let mut best_num = 0; + while !bc.blocks_db.get(&b).unwrap().is_some() { + // track back to the best block we have in the blocks database + let extras: BlockDetails = bc.extras_db.read(&b).unwrap(); + type DetailsKey = Key; + bc.extras_db.delete(&(DetailsKey::key(&b))).unwrap(); + b = extras.parent; + best_num = extras.number; + removed += 1; + } + if b != best { + let batch = DBTransaction::new(); + let range = (best_num + 1) as bc::Number .. (best_num + removed) as bc::Number; + let chain = bc::group::BloomGroupChain::new(bc.blooms_config, &bc); + let changes = chain.replace(&range, vec![]); + for (k, v) in changes.into_iter() { + batch.write(&LogGroupPosition::from(k), &BloomGroup::from(v)); + } + batch.put(b"best", &b).unwrap(); + bc.extras_db.write(batch).unwrap(); + info!("Restored mismatched best block. Was: {}, new: {}", best.hex(), b.hex()); + } + b + } None => { // best block does not exist // we need to insert genesis into the cache diff --git a/ethcore/src/blooms/bloom.rs b/ethcore/src/blooms/bloom.rs index 29f055c10..83d898ab5 100644 --- a/ethcore/src/blooms/bloom.rs +++ b/ethcore/src/blooms/bloom.rs @@ -20,7 +20,7 @@ use util::HeapSizeOf; use basic_types::LogBloom; /// Helper structure representing bloom of the trace. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Bloom(LogBloom); impl From for Bloom { diff --git a/ethcore/src/blooms/bloom_group.rs b/ethcore/src/blooms/bloom_group.rs index 6fa1d0761..8e2b87189 100644 --- a/ethcore/src/blooms/bloom_group.rs +++ b/ethcore/src/blooms/bloom_group.rs @@ -20,7 +20,7 @@ use util::HeapSizeOf; use super::Bloom; /// Represents group of X consecutive blooms. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct BloomGroup { blooms: Vec, } diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 07f5f9c27..5e5ddefde 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . //! Trace database. -use std::ptr; use std::ops::{Deref, DerefMut}; use std::collections::HashMap; use std::sync::{RwLock, Arc}; @@ -47,9 +46,7 @@ impl Key for H256 { fn key(&self) -> H264 { let mut result = H264::default(); result[0] = TraceDBIndex::BlockTraces as u8; - unsafe { - ptr::copy(self.as_ptr(), result.as_mut_ptr().offset(1), 32); - } + result[1..33].copy_from_slice(self); result } } @@ -84,9 +81,9 @@ impl Key for TraceGroupPosition { 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; + 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) } } diff --git a/ethcore/src/types/trace_types/filter.rs b/ethcore/src/types/trace_types/filter.rs index c02a15c03..d57efa5f3 100644 --- a/ethcore/src/types/trace_types/filter.rs +++ b/ethcore/src/types/trace_types/filter.rs @@ -30,7 +30,7 @@ use std::collections::VecDeque; /// Addresses filter. /// /// Used to create bloom possibilities and match filters. -#[derive(Binary)] +#[derive(Debug, Binary)] pub struct AddressesFilter { list: Vec
} @@ -76,7 +76,7 @@ impl AddressesFilter { } } -#[derive(Binary)] +#[derive(Debug, Binary)] /// Traces filter. pub struct Filter { /// Block range. diff --git a/util/src/network/host.rs b/util/src/network/host.rs index a48d1544c..75602d27f 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -435,6 +435,7 @@ impl Host where Message: Send + Sync + Clone { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; self.reserved_nodes.write().unwrap().insert(n.id.clone()); + self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { discovery.add_node(entry); @@ -758,7 +759,9 @@ impl Host where Message: Send + Sync + Clone { trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); if let UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) = e { if let Some(id) = s.id() { - self.nodes.write().unwrap().mark_as_useless(id); + if !self.reserved_nodes.read().unwrap().contains(id) { + self.nodes.write().unwrap().mark_as_useless(id); + } } } kill = true; @@ -892,7 +895,7 @@ impl Host where Message: Send + Sync + Clone { trace!(target: "network", "Removed from node table: {}", i); self.kill_connection(i, io, false); } - self.nodes.write().unwrap().update(node_changes); + self.nodes.write().unwrap().update(node_changes, &*self.reserved_nodes.read().unwrap()); } } diff --git a/util/src/network/node_table.rs b/util/src/network/node_table.rs index 416a0f8eb..5fd2a10e8 100644 --- a/util/src/network/node_table.rs +++ b/util/src/network/node_table.rs @@ -236,13 +236,15 @@ impl NodeTable { } /// Apply table changes coming from discovery - pub fn update(&mut self, mut update: TableUpdates) { + pub fn update(&mut self, mut update: TableUpdates, reserved: &HashSet) { for (_, node) in update.added.drain() { let mut entry = self.nodes.entry(node.id.clone()).or_insert_with(|| Node::new(node.id.clone(), node.endpoint.clone())); entry.endpoint = node.endpoint; } for r in update.removed { - self.nodes.remove(&r); + if !reserved.contains(&r) { + self.nodes.remove(&r); + } } }