Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

blockchain import_route #645

Merged
merged 5 commits into from
Mar 10, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion ethcore/src/blockchain/block_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use util::numbers::{U256,H256};
use header::BlockNumber;

/// Brief info about inserted block.
#[derive(Clone)]
pub struct BlockInfo {
/// Block hash.
pub hash: H256,
Expand All @@ -30,6 +31,7 @@ pub struct BlockInfo {
}

/// Describes location of newly inserted block.
#[derive(Clone)]
pub enum BlockLocation {
/// It's part of the canon chain.
CanonChain,
Expand All @@ -42,6 +44,8 @@ pub enum BlockLocation {
/// Hash of the newest common ancestor with old canon chain.
ancestor: H256,
/// Hashes of the blocks between ancestor and this block.
route: Vec<H256>
route: Vec<H256>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enacted

/// Hashes of the blocks which were invalidated.
old_route: Vec<H256>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

retracted

}
}
55 changes: 41 additions & 14 deletions ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use blockchain::best_block::BestBlock;
use blockchain::bloom_indexer::BloomIndexer;
use blockchain::tree_route::TreeRoute;
use blockchain::update::ExtrasUpdate;
use blockchain::CacheSize;
use blockchain::{CacheSize, ImportRoute};

const BLOOM_INDEX_SIZE: usize = 16;
const BLOOM_LEVELS: u8 = 3;
Expand Down Expand Up @@ -414,14 +414,14 @@ 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: Vec<Receipt>) {
pub fn insert_block(&self, bytes: &[u8], receipts: Vec<Receipt>) -> ImportRoute {
// create views onto rlp
let block = BlockView::new(bytes);
let header = block.header_view();
let hash = header.sha3();

if self.is_known(&hash) {
return;
return ImportRoute::none();
}

// store block in db
Expand All @@ -435,8 +435,10 @@ impl BlockChain {
block_receipts: self.prepare_block_receipts_update(receipts, &info),
transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info),
blocks_blooms: self.prepare_block_blooms_update(bytes, &info),
info: info
info: info.clone(),
});

ImportRoute::from(info)
}

/// Applies extras update.
Expand Down Expand Up @@ -549,9 +551,14 @@ impl BlockChain {

match route.blocks.len() {
0 => BlockLocation::CanonChain,
_ => BlockLocation::BranchBecomingCanonChain {
ancestor: route.ancestor,
route: route.blocks.into_iter().skip(route.index).collect()
_ => {
let old_route = route.blocks.iter().take(route.index).cloned().collect::<Vec<H256>>();

BlockLocation::BranchBecomingCanonChain {
ancestor: route.ancestor,
route: route.blocks.into_iter().skip(route.index).collect(),
old_route: old_route.into_iter().rev().collect(),
}
}
}
} else {
Expand All @@ -572,7 +579,7 @@ impl BlockChain {
BlockLocation::CanonChain => {
block_hashes.insert(number, info.hash.clone());
},
BlockLocation::BranchBecomingCanonChain { ref ancestor, ref route } => {
BlockLocation::BranchBecomingCanonChain { ref ancestor, ref route, .. } => {
let ancestor_number = self.block_number(ancestor).unwrap();
let start_number = ancestor_number + 1;

Expand Down Expand Up @@ -661,7 +668,7 @@ impl BlockChain {
ChainFilter::new(self, self.bloom_indexer.index_size(), self.bloom_indexer.levels())
.add_bloom(&header.log_bloom(), header.number() as usize)
},
BlockLocation::BranchBecomingCanonChain { ref ancestor, ref route } => {
BlockLocation::BranchBecomingCanonChain { ref ancestor, ref route, .. } => {
let ancestor_number = self.block_number(ancestor).unwrap();
let start_number = ancestor_number + 1;

Expand Down Expand Up @@ -825,7 +832,7 @@ mod tests {
use rustc_serialize::hex::FromHex;
use util::hash::*;
use util::sha3::Hashable;
use blockchain::{BlockProvider, BlockChain, BlockChainConfig};
use blockchain::{BlockProvider, BlockChain, BlockChainConfig, ImportRoute};
use tests::helpers::*;
use devtools::*;
use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer};
Expand Down Expand Up @@ -943,10 +950,30 @@ mod tests {

let temp = RandomTempPath::new();
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
bc.insert_block(&b1, vec![]);
bc.insert_block(&b2, vec![]);
bc.insert_block(&b3a, vec![]);
bc.insert_block(&b3b, vec![]);
let ir1 = bc.insert_block(&b1, vec![]);
let ir2 = bc.insert_block(&b2, vec![]);
let ir3b = bc.insert_block(&b3b, vec![]);
let ir3a = bc.insert_block(&b3a, vec![]);

assert_eq!(ir1, ImportRoute {
validated_blocks: vec![b1_hash],
invalidated_blocks: vec![],
});

assert_eq!(ir2, ImportRoute {
validated_blocks: vec![b2_hash],
invalidated_blocks: vec![],
});

assert_eq!(ir3b, ImportRoute {
validated_blocks: vec![b3b_hash],
invalidated_blocks: vec![],
});

assert_eq!(ir3a, ImportRoute {
validated_blocks: vec![b3a_hash],
invalidated_blocks: vec![b3b_hash],
});

assert_eq!(bc.best_block_hash(), best_block_hash);
assert_eq!(bc.block_number(&genesis_hash).unwrap(), 0);
Expand Down
119 changes: 119 additions & 0 deletions ethcore/src/blockchain/import_route.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// 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/>.

//! Import route.

use util::hash::H256;
use blockchain::block_info::{BlockInfo, BlockLocation};

/// Import route for newly inserted block.
#[derive(Debug, PartialEq)]
pub struct ImportRoute {
/// Blocks that were invalidated by new block.
pub invalidated_blocks: Vec<H256>,
/// Blocks that were validted by new block.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

pub validated_blocks: Vec<H256>,
}

impl ImportRoute {
pub fn none() -> Self {
ImportRoute {
invalidated_blocks: vec![],
validated_blocks: vec![],
}
}
}

impl From<BlockInfo> for ImportRoute {
fn from(info: BlockInfo) -> ImportRoute {
match info.location {
BlockLocation::CanonChain => ImportRoute {
invalidated_blocks: vec![],
validated_blocks: vec![info.hash],
},
BlockLocation::Branch => ImportRoute::none(),
BlockLocation::BranchBecomingCanonChain { mut route, old_route, .. } => {
route.push(info.hash);
ImportRoute {
invalidated_blocks: old_route,
validated_blocks: route,
}
}
}
}
}

#[cfg(test)]
mod tests {
use util::hash::H256;
use util::numbers::U256;
use blockchain::block_info::{BlockInfo, BlockLocation};
use blockchain::ImportRoute;

#[test]
fn import_route_none() {
assert_eq!(ImportRoute::none(), ImportRoute {
validated_blocks: vec![],
invalidated_blocks: vec![],
});
}

#[test]
fn import_route_branch() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::Branch,
};

assert_eq!(ImportRoute::from(info), ImportRoute::none());
}

#[test]
fn import_route_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::CanonChain,
};

assert_eq!(ImportRoute::from(info), ImportRoute {
invalidated_blocks: vec![],
validated_blocks: vec![H256::from(U256::from(1))],
});
}

#[test]
fn import_route_branch_becoming_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(2)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::BranchBecomingCanonChain {
ancestor: H256::from(U256::from(0)),
route: vec![H256::from(U256::from(1))],
old_route: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
}
};

assert_eq!(ImportRoute::from(info), ImportRoute {
invalidated_blocks: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
validated_blocks: vec![H256::from(U256::from(1)), H256::from(U256::from(2))],
});
}
}
2 changes: 2 additions & 0 deletions ethcore/src/blockchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ mod tree_route;
mod update;
#[cfg(test)]
mod generator;
mod import_route;

pub use self::blockchain::{BlockProvider, BlockChain, BlockChainConfig};
pub use self::cache::CacheSize;
pub use self::tree_route::TreeRoute;
pub use self::import_route::ImportRoute;