Merge pull request #3719 from ethcore/engine-block-ordering

Engine block ordering
This commit is contained in:
Gav Wood 2016-12-05 10:37:36 -08:00 committed by GitHub
commit ad36743122
10 changed files with 88 additions and 45 deletions

View File

@ -34,6 +34,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;
@ -198,6 +199,9 @@ pub struct BlockChain {
pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>, pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>,
pending_block_details: RwLock<HashMap<H256, BlockDetails>>, pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>, pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
// Used for block ordering.
engine: Arc<Engine>,
} }
impl BlockProvider for BlockChain { impl BlockProvider for BlockChain {
@ -415,9 +419,8 @@ impl<'a> Iterator for AncestryIter<'a> {
} }
impl BlockChain { impl BlockChain {
#[cfg_attr(feature="dev", allow(useless_let_if_seq))] /// Create new instance of blockchain from given Genesis and block picking rules of Engine.
/// Create new instance of blockchain from given Genesis pub fn new(config: Config, genesis: &[u8], db: Arc<Database>, engine: Arc<Engine>) -> BlockChain {
pub fn new(config: Config, genesis: &[u8], db: Arc<Database>) -> 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);
@ -442,6 +445,7 @@ impl BlockChain {
pending_block_hashes: RwLock::new(HashMap::new()), pending_block_hashes: RwLock::new(HashMap::new()),
pending_block_details: RwLock::new(HashMap::new()), pending_block_details: 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
@ -858,13 +862,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"
@ -1319,11 +1322,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
@ -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());
assert_eq!(bc.best_block_number(), 0); assert_eq!(bc.best_block_number(), 0);
// when // when
@ -1360,7 +1368,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());
@ -1391,7 +1399,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();
@ -1427,7 +1435,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] {
@ -1489,7 +1497,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![]);
@ -1577,7 +1585,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![]);
@ -1639,7 +1647,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![]);
@ -1755,7 +1763,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![]);
@ -1766,7 +1774,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);
} }
@ -1821,7 +1829,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();
@ -1881,7 +1889,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(),
@ -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 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);
@ -2042,7 +2050,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();
@ -2061,7 +2069,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);
} }
@ -2078,7 +2086,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

@ -164,7 +164,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().expect("DB path could not be converted to string.")).map_err(ClientError::Database))); let db = Arc::new(try!(Database::open(&db_config, &path.to_str().expect("DB path could not be converted to string.")).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 trie_spec = match config.fat_db { let trie_spec = match config.fat_db {
@ -787,7 +787,7 @@ impl snapshot::DatabaseRestore for Client {
let cache_size = state_db.cache_size(); let cache_size = state_db.cache_size();
*state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE), cache_size); *state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE), cache_size);
*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

@ -21,7 +21,7 @@ use std::sync::Weak;
use std::time::{UNIX_EPOCH, Duration}; use std::time::{UNIX_EPOCH, Duration};
use util::*; use util::*;
use ethkey::{verify_address, Signature}; use ethkey::{verify_address, Signature};
use rlp::{UntrustedRlp, View, encode}; use rlp::{Rlp, UntrustedRlp, View, encode};
use account_provider::AccountProvider; use account_provider::AccountProvider;
use block::*; use block::*;
use spec::CommonParams; use spec::CommonParams;
@ -35,6 +35,8 @@ use service::ClientIoMessage;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use env_info::EnvInfo; use env_info::EnvInfo;
use builtin::Builtin; use builtin::Builtin;
use blockchain::extras::BlockDetails;
use views::HeaderView;
/// `AuthorityRound` params. /// `AuthorityRound` params.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -272,7 +274,6 @@ impl Engine for AuthorityRound {
} }
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// Don't calculate difficulty for genesis blocks.
if header.number() == 0 { if header.number() == 0 {
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
} }
@ -284,10 +285,6 @@ impl Engine for AuthorityRound {
try!(Err(BlockError::DoubleVote(header.author().clone()))); try!(Err(BlockError::DoubleVote(header.author().clone())));
} }
// Check difficulty is correct given the two timestamps.
if header.difficulty() != parent.difficulty() {
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: *parent.difficulty(), found: *header.difficulty() })))
}
let gas_limit_divisor = self.our_params.gas_limit_bound_divisor; let gas_limit_divisor = self.our_params.gas_limit_bound_divisor;
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
@ -310,6 +307,19 @@ impl Engine for AuthorityRound {
let mut guard = self.message_channel.lock(); let mut guard = self.message_channel.lock();
*guard = Some(message_channel); *guard = Some(message_channel);
} }
fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
let new_number = new_header.number();
let best_number = best_header.number();
if new_number != best_number {
new_number > best_number
} else {
// Take the oldest step at given height.
let new_step: usize = Rlp::new(&new_header.seal()[0]).as_val();
let best_step: usize = Rlp::new(&best_header.seal()[0]).as_val();
new_step < best_step
}
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -38,6 +38,9 @@ use io::IoChannel;
use service::ClientIoMessage; use service::ClientIoMessage;
use header::Header; use header::Header;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use ethereum::ethash;
use blockchain::extras::BlockDetails;
use views::HeaderView;
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based.
/// Provides hooks into each of the major parts of block import. /// Provides hooks into each of the major parts of block import.
@ -146,5 +149,9 @@ pub trait Engine : Sync + Send {
/// Add a channel for communication with Client which can be used for sealing. /// Add a channel for communication with Client which can be used for sealing.
fn register_message_channel(&self, _message_channel: IoChannel<ClientIoMessage>) {} fn register_message_channel(&self, _message_channel: IoChannel<ClientIoMessage>) {}
// TODO: sealing stuff - though might want to leave this for later.
/// Check if new block should be chosen as the one in chain.
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
ethash::is_new_best_block(best_total_difficulty, parent_details, new_header)
}
} }

View File

@ -38,6 +38,12 @@ impl NullEngine {
} }
} }
impl Default for NullEngine {
fn default() -> Self {
Self::new(Default::default(), Default::default())
}
}
impl Engine for NullEngine { impl Engine for NullEngine {
fn name(&self) -> &str { fn name(&self) -> &str {
"NullEngine" "NullEngine"

View File

@ -21,6 +21,7 @@ use builtin::Builtin;
use env_info::EnvInfo; use env_info::EnvInfo;
use error::{BlockError, TransactionError, Error}; use error::{BlockError, TransactionError, Error};
use header::Header; use header::Header;
use views::HeaderView;
use state::CleanupMode; use state::CleanupMode;
use spec::CommonParams; use spec::CommonParams;
use transaction::SignedTransaction; use transaction::SignedTransaction;
@ -28,6 +29,7 @@ use engines::Engine;
use evm::Schedule; use evm::Schedule;
use ethjson; use ethjson;
use rlp::{self, UntrustedRlp, View}; use rlp::{self, UntrustedRlp, View};
use blockchain::extras::BlockDetails;
/// Ethash params. /// Ethash params.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -325,6 +327,15 @@ impl Engine for Ethash {
fn verify_transaction(&self, t: &SignedTransaction, _header: &Header) -> Result<(), Error> { fn verify_transaction(&self, t: &SignedTransaction, _header: &Header) -> Result<(), Error> {
t.sender().map(|_|()) // Perform EC recovery and cache sender t.sender().map(|_|()) // Perform EC recovery and cache sender
} }
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
is_new_best_block(best_total_difficulty, parent_details, new_header)
}
}
/// Check if a new block should replace the best blockchain block.
pub fn is_new_best_block(best_total_difficulty: U256, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
parent_details.total_difficulty + new_header.difficulty() > best_total_difficulty
} }
#[cfg_attr(feature="dev", allow(wrong_self_convention))] #[cfg_attr(feature="dev", allow(wrong_self_convention))]

View File

@ -81,6 +81,7 @@ struct Restoration {
struct RestorationParams<'a> { struct RestorationParams<'a> {
manifest: ManifestData, // manifest to base restoration on. manifest: ManifestData, // manifest to base restoration on.
pruning: Algorithm, // pruning algorithm for the database. pruning: Algorithm, // pruning algorithm for the database.
engine: Arc<Engine>, // consensus engine of the chain.
db_path: PathBuf, // database path db_path: PathBuf, // database path
db_config: &'a DatabaseConfig, // configuration for the database. db_config: &'a DatabaseConfig, // configuration for the database.
writer: Option<LooseWriter>, // writer for recovered snapshot. writer: Option<LooseWriter>, // writer for recovered snapshot.
@ -99,7 +100,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(), params.engine);
let blocks = try!(BlockRebuilder::new(chain, raw_db.clone(), &manifest)); let blocks = try!(BlockRebuilder::new(chain, raw_db.clone(), &manifest));
let root = manifest.state_root.clone(); let root = manifest.state_root.clone();
@ -420,6 +421,7 @@ impl Service {
let params = RestorationParams { let params = RestorationParams {
manifest: manifest, manifest: manifest,
pruning: self.pruning, pruning: self.pruning,
engine: self.engine.clone(),
db_path: self.restoration_db(), db_path: self.restoration_db(),
db_config: &self.db_config, db_config: &self.db_config,
writer: writer, writer: writer,

View File

@ -37,13 +37,14 @@ fn chunk_and_restore(amount: u64) {
let genesis = canon_chain.generate(&mut finalizer).unwrap(); let genesis = canon_chain.generate(&mut finalizer).unwrap();
let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
let engine = Arc::new(::engines::NullEngine::default());
let orig_path = RandomTempPath::create_dir(); let orig_path = RandomTempPath::create_dir();
let new_path = RandomTempPath::create_dir(); let new_path = RandomTempPath::create_dir();
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 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 = BlockChain::new(Default::default(), &genesis, old_db.clone(), engine.clone());
// build the blockchain. // build the blockchain.
let mut batch = old_db.transaction(); let mut batch = old_db.transaction();
@ -73,21 +74,20 @@ fn chunk_and_restore(amount: u64) {
// restore it. // restore it.
let new_db = Arc::new(Database::open(&db_cfg, new_path.as_str()).unwrap()); let new_db = Arc::new(Database::open(&db_cfg, new_path.as_str()).unwrap());
let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone()); let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone(), engine.clone());
let mut rebuilder = BlockRebuilder::new(new_chain, new_db.clone(), &manifest).unwrap(); let mut rebuilder = BlockRebuilder::new(new_chain, new_db.clone(), &manifest).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 flag = AtomicBool::new(true); let flag = AtomicBool::new(true);
for chunk_hash in &reader.manifest().block_hashes { for chunk_hash in &reader.manifest().block_hashes {
let compressed = reader.chunk(*chunk_hash).unwrap(); let compressed = reader.chunk(*chunk_hash).unwrap();
let chunk = snappy::decompress(&compressed).unwrap(); let chunk = snappy::decompress(&compressed).unwrap();
rebuilder.feed(&chunk, &engine, &flag).unwrap(); rebuilder.feed(&chunk, engine.as_ref(), &flag).unwrap();
} }
rebuilder.finalize(HashMap::new()).unwrap(); rebuilder.finalize(HashMap::new()).unwrap();
// and test it. // and test it.
let new_chain = BlockChain::new(Default::default(), &genesis, new_db); let new_chain = BlockChain::new(Default::default(), &genesis, new_db, engine);
assert_eq!(new_chain.best_block_hash(), best_hash); assert_eq!(new_chain.best_block_hash(), best_hash);
} }
@ -121,8 +121,8 @@ fn checks_flag() {
let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
let db = Arc::new(Database::open(&db_cfg, path.as_str()).unwrap()); let db = Arc::new(Database::open(&db_cfg, path.as_str()).unwrap());
let chain = BlockChain::new(Default::default(), &genesis, db.clone()); let engine = Arc::new(::engines::NullEngine::default());
let engine = ::engines::NullEngine::new(Default::default(), Default::default()); let chain = BlockChain::new(Default::default(), &genesis, db.clone(), engine.clone());
let manifest = ::snapshot::ManifestData { let manifest = ::snapshot::ManifestData {
state_hashes: Vec::new(), state_hashes: Vec::new(),
@ -134,7 +134,7 @@ fn checks_flag() {
let mut rebuilder = BlockRebuilder::new(chain, db.clone(), &manifest).unwrap(); let mut rebuilder = BlockRebuilder::new(chain, db.clone(), &manifest).unwrap();
match rebuilder.feed(&chunk, &engine, &AtomicBool::new(false)) { match rebuilder.feed(&chunk, engine.as_ref(), &AtomicBool::new(false)) {
Err(Error::Snapshot(SnapshotError::RestorationAborted)) => {} Err(Error::Snapshot(SnapshotError::RestorationAborted)) => {}
_ => panic!("Wrong result on abort flag set") _ => panic!("Wrong result on abort flag set")
} }

View File

@ -30,8 +30,7 @@ use ethjson;
use rlp::{Rlp, RlpStream, View, Stream}; use rlp::{Rlp, RlpStream, View, Stream};
/// Parameters common to all engines. /// Parameters common to all engines.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone, Default)]
#[cfg_attr(test, derive(Default))]
pub struct CommonParams { pub struct CommonParams {
/// Account start nonce. /// Account start nonce.
pub account_start_nonce: U256, pub account_start_nonce: U256,

View File

@ -286,7 +286,7 @@ fn new_db(path: &str) -> Arc<Database> {
pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockChain> { pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockChain> {
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(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone(), Spec::new_null().engine);
let mut batch = db.transaction(); let mut batch = db.transaction();
for block_order in 1..block_number { for block_order in 1..block_number {
@ -304,7 +304,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult<BlockCh
pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempResult<BlockChain> { pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempResult<BlockChain> {
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(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone(), Spec::new_null().engine);
let mut batch = db.transaction(); let mut batch = db.transaction();
@ -323,7 +323,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes
pub fn generate_dummy_empty_blockchain() -> GuardedTempResult<BlockChain> { pub fn generate_dummy_empty_blockchain() -> GuardedTempResult<BlockChain> {
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(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone(), Spec::new_null().engine);
GuardedTempResult::<BlockChain> { GuardedTempResult::<BlockChain> {
_temp: temp, _temp: temp,