use Engine to order blockchain

This commit is contained in:
keorn 2016-10-05 14:29:35 +01:00
parent 76d7ec84bb
commit 67c24dcb95
4 changed files with 44 additions and 31 deletions

View File

@ -33,6 +33,7 @@ use blockchain::update::ExtrasUpdate;
use blockchain::{CacheSize, ImportRoute, Config}; use blockchain::{CacheSize, ImportRoute, Config};
use db::{self, Writable, Readable, CacheUpdatePolicy}; use db::{self, Writable, Readable, CacheUpdatePolicy};
use cache_manager::CacheManager; use cache_manager::CacheManager;
use engines::Engine;
const LOG_BLOOMS_LEVELS: usize = 3; const LOG_BLOOMS_LEVELS: usize = 3;
const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16; const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16;
@ -182,6 +183,8 @@ pub struct BlockChain {
pending_best_block: RwLock<Option<BestBlock>>, pending_best_block: RwLock<Option<BestBlock>>,
pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>, pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>,
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>, pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
engine: Arc<Engine>,
} }
impl BlockProvider for BlockChain { impl BlockProvider for BlockChain {
@ -387,8 +390,8 @@ impl<'a> Iterator for AncestryIter<'a> {
} }
impl BlockChain { impl BlockChain {
/// Create new instance of blockchain from given Genesis /// Create new instance of blockchain from given Genesis and block picking rules of Engine.
pub fn new(config: Config, genesis: &[u8], db: Arc<Database>) -> BlockChain { pub fn new(config: Config, genesis: &[u8], db: Arc<Database>, engine: Arc<Engine>) -> BlockChain {
// 400 is the avarage size of the key // 400 is the avarage size of the key
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400); let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);
@ -411,6 +414,7 @@ impl BlockChain {
pending_best_block: RwLock::new(None), pending_best_block: RwLock::new(None),
pending_block_hashes: RwLock::new(HashMap::new()), pending_block_hashes: RwLock::new(HashMap::new()),
pending_transaction_addresses: RwLock::new(HashMap::new()), pending_transaction_addresses: RwLock::new(HashMap::new()),
engine: engine,
}; };
// load best block // load best block
@ -799,13 +803,12 @@ impl BlockChain {
let number = header.number(); let number = header.number();
let parent_hash = header.parent_hash(); let parent_hash = header.parent_hash();
let parent_details = self.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash)); let parent_details = self.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash));
let total_difficulty = parent_details.total_difficulty + header.difficulty(); let is_new_best = self.engine.is_new_best_block(self.best_block_total_difficulty(), HeaderView::new(&self.best_block_header()), &parent_details, header);
let is_new_best = total_difficulty > self.best_block_total_difficulty();
BlockInfo { BlockInfo {
hash: hash, hash: hash,
number: number, number: number,
total_difficulty: total_difficulty, total_difficulty: parent_details.total_difficulty + header.difficulty(),
location: if is_new_best { location: if is_new_best {
// on new best block we need to make sure that all ancestors // on new best block we need to make sure that all ancestors
// are moved to "canon chain" // are moved to "canon chain"
@ -1226,11 +1229,16 @@ mod tests {
use views::BlockView; use views::BlockView;
use transaction::{Transaction, Action}; use transaction::{Transaction, Action};
use log_entry::{LogEntry, LocalizedLogEntry}; use log_entry::{LogEntry, LocalizedLogEntry};
use spec::Spec;
fn new_db(path: &str) -> Arc<Database> { fn new_db(path: &str) -> Arc<Database> {
Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path).unwrap()) Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path).unwrap())
} }
fn new_chain(genesis: &[u8], db: Arc<Database>) -> BlockChain {
BlockChain::new(Config::default(), genesis, db, Spec::new_null().engine)
}
#[test] #[test]
fn should_cache_best_block() { fn should_cache_best_block() {
// given // given
@ -1241,7 +1249,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
assert_eq!(bc.best_block_number(), 0); assert_eq!(bc.best_block_number(), 0);
// when // when
@ -1267,7 +1275,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
assert_eq!(bc.genesis_hash(), genesis_hash.clone()); assert_eq!(bc.genesis_hash(), genesis_hash.clone());
assert_eq!(bc.best_block_hash(), genesis_hash.clone()); assert_eq!(bc.best_block_hash(), genesis_hash.clone());
@ -1298,7 +1306,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut block_hashes = vec![genesis_hash.clone()]; let mut block_hashes = vec![genesis_hash.clone()];
let mut batch = db.transaction(); let mut batch = db.transaction();
@ -1334,7 +1342,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch =db.transaction(); let mut batch =db.transaction();
for b in &[&b1a, &b1b, &b2a, &b2b, &b3a, &b3b, &b4a, &b4b, &b5a, &b5b] { for b in &[&b1a, &b1b, &b2a, &b2b, &b3a, &b3b, &b4a, &b4b, &b5a, &b5b] {
@ -1396,7 +1404,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch = db.transaction(); let mut batch = db.transaction();
let _ = bc.insert_block(&mut batch, &b1a, vec![]); let _ = bc.insert_block(&mut batch, &b1a, vec![]);
@ -1484,7 +1492,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch = db.transaction(); let mut batch = db.transaction();
let _ = bc.insert_block(&mut batch, &b1a, vec![]); let _ = bc.insert_block(&mut batch, &b1a, vec![]);
@ -1546,7 +1554,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch = db.transaction(); let mut batch = db.transaction();
let ir1 = bc.insert_block(&mut batch, &b1, vec![]); let ir1 = bc.insert_block(&mut batch, &b1, vec![]);
@ -1662,7 +1670,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
{ {
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
assert_eq!(bc.best_block_hash(), genesis_hash); assert_eq!(bc.best_block_hash(), genesis_hash);
let mut batch =db.transaction(); let mut batch =db.transaction();
bc.insert_block(&mut batch, &first, vec![]); bc.insert_block(&mut batch, &first, vec![]);
@ -1673,7 +1681,7 @@ mod tests {
{ {
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
assert_eq!(bc.best_block_hash(), first_hash); assert_eq!(bc.best_block_hash(), first_hash);
} }
@ -1728,7 +1736,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch =db.transaction(); let mut batch =db.transaction();
bc.insert_block(&mut batch, &b1, vec![]); bc.insert_block(&mut batch, &b1, vec![]);
db.write(batch).unwrap(); db.write(batch).unwrap();
@ -1788,7 +1796,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
insert_block(&db, &bc, &b1, vec![Receipt { insert_block(&db, &bc, &b1, vec![Receipt {
state_root: H256::default(), state_root: H256::default(),
gas_used: 10_000.into(), gas_used: 10_000.into(),
@ -1892,7 +1900,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
@ -1949,7 +1957,7 @@ mod tests {
{ {
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
let mut batch =db.transaction(); let mut batch =db.transaction();
@ -1968,7 +1976,7 @@ mod tests {
// re-loading the blockchain should load the correct best block. // re-loading the blockchain should load the correct best block.
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
assert_eq!(bc.best_block_number(), 5); assert_eq!(bc.best_block_number(), 5);
} }
@ -1985,7 +1993,7 @@ mod tests {
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
let db = new_db(temp.as_str()); let db = new_db(temp.as_str());
let bc = BlockChain::new(Config::default(), &genesis, db.clone()); let bc = new_chain(&genesis, db.clone());
let mut batch =db.transaction(); let mut batch =db.transaction();
bc.insert_block(&mut batch, &first, vec![]); bc.insert_block(&mut batch, &first, vec![]);

View File

@ -23,7 +23,7 @@ use time::precise_time_ns;
// util // util
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock}; use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock};
use util::journaldb::{self, JournalDB}; use util::journaldb;
use util::{U256, H256, H520, Address, H2048, Uint}; use util::{U256, H256, H520, Address, H2048, Uint};
use util::sha3::*; use util::sha3::*;
use util::TrieFactory; use util::TrieFactory;
@ -170,7 +170,7 @@ impl Client {
let gb = spec.genesis_block(); let gb = spec.genesis_block();
let db = Arc::new(try!(Database::open(&db_config, &path.to_str().unwrap()).map_err(ClientError::Database))); let db = Arc::new(try!(Database::open(&db_config, &path.to_str().unwrap()).map_err(ClientError::Database)));
let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone())); let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone(), spec.engine.clone()));
let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone())); let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone()));
let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE); let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE);
@ -689,7 +689,7 @@ impl snapshot::DatabaseRestore for Client {
try!(db.restore(new_db)); try!(db.restore(new_db));
*state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE)); *state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE));
*chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone(), self.engine.clone()));
*tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone()); *tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone());
Ok(()) Ok(())
} }

View File

@ -32,6 +32,7 @@ use engines::Engine;
use error::Error; use error::Error;
use ids::BlockID; use ids::BlockID;
use service::ClientIoMessage; use service::ClientIoMessage;
use spec::Spec;
use io::IoChannel; use io::IoChannel;
@ -97,7 +98,7 @@ impl Restoration {
let raw_db = Arc::new(try!(Database::open(params.db_config, &*params.db_path.to_string_lossy()) let raw_db = Arc::new(try!(Database::open(params.db_config, &*params.db_path.to_string_lossy())
.map_err(UtilError::SimpleString))); .map_err(UtilError::SimpleString)));
let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone()); let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone(), Spec::new_null().engine);
let blocks = try!(BlockRebuilder::new(chain, manifest.block_number)); let blocks = try!(BlockRebuilder::new(chain, manifest.block_number));
let root = manifest.state_root.clone(); let root = manifest.state_root.clone();

View File

@ -28,6 +28,8 @@ use util::kvdb::{Database, DatabaseConfig};
use std::sync::Arc; use std::sync::Arc;
use spec::Spec;
fn chunk_and_restore(amount: u64) { fn chunk_and_restore(amount: u64) {
let mut canon_chain = ChainGenerator::default(); let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default(); let mut finalizer = BlockFinalizer::default();
@ -39,8 +41,10 @@ fn chunk_and_restore(amount: u64) {
let mut snapshot_path = new_path.as_path().to_owned(); let mut snapshot_path = new_path.as_path().to_owned();
snapshot_path.push("SNAP"); snapshot_path.push("SNAP");
let new_chain = |db| BlockChain::new(Default::default(), &genesis, db, Spec::new_null().engine);
let old_db = Arc::new(Database::open(&db_cfg, orig_path.as_str()).unwrap()); let old_db = Arc::new(Database::open(&db_cfg, orig_path.as_str()).unwrap());
let bc = BlockChain::new(Default::default(), &genesis, old_db.clone()); let bc = new_chain(old_db.clone());
// build the blockchain. // build the blockchain.
let mut batch = old_db.transaction(); let mut batch = old_db.transaction();
@ -67,9 +71,9 @@ fn chunk_and_restore(amount: u64) {
}).unwrap(); }).unwrap();
// restore it. // restore it.
let new_db = Arc::new(Database::open(&db_cfg, new_path.as_str()).unwrap()); let restored_db = Arc::new(Database::open(&db_cfg, new_path.as_str()).unwrap());
let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone()); let restored_chain = new_chain(restored_db.clone());
let mut rebuilder = BlockRebuilder::new(new_chain, amount).unwrap(); let mut rebuilder = BlockRebuilder::new(restored_chain, amount).unwrap();
let reader = PackedReader::new(&snapshot_path).unwrap().unwrap(); let reader = PackedReader::new(&snapshot_path).unwrap().unwrap();
let engine = ::engines::NullEngine::new(Default::default(), Default::default()); let engine = ::engines::NullEngine::new(Default::default(), Default::default());
for chunk_hash in &reader.manifest().block_hashes { for chunk_hash in &reader.manifest().block_hashes {
@ -81,8 +85,8 @@ fn chunk_and_restore(amount: u64) {
rebuilder.glue_chunks(); rebuilder.glue_chunks();
// and test it. // and test it.
let new_chain = BlockChain::new(Default::default(), &genesis, new_db); let restored_chain = new_chain(restored_db);
assert_eq!(new_chain.best_block_hash(), best_hash); assert_eq!(restored_chain.best_block_hash(), best_hash);
} }
#[test] #[test]