diff --git a/ethcore/src/account.rs b/ethcore/src/account.rs index 2edbf87ae..2db4ffcc0 100644 --- a/ethcore/src/account.rs +++ b/ethcore/src/account.rs @@ -214,8 +214,8 @@ impl Account { } /// Commit the `storage_overlay` to the backing DB and update `storage_root`. - pub fn commit_storage(&mut self, db: &mut AccountDBMut) { - let mut t = SecTrieDBMut::from_existing(db, &mut self.storage_root) + pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut AccountDBMut) { + let mut t = trie_factory.from_existing(db, &mut self.storage_root) .expect("Account storage_root initially set to zero (valid) and only altered by SecTrieDBMut. \ SecTrieDBMut would not set it to an invalid state root. Therefore the root is valid and DB creation \ using it will not fail."); @@ -275,7 +275,7 @@ mod tests { let rlp = { let mut a = Account::new_contract(69.into(), 0.into()); a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64))); - a.commit_storage(&mut db); + a.commit_storage(&Default::default(), &mut db); a.init_code(vec![]); a.commit_code(&mut db); a.rlp() @@ -313,7 +313,7 @@ mod tests { let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); - a.commit_storage(&mut db); + a.commit_storage(&Default::default(), &mut db); assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); } @@ -323,11 +323,11 @@ mod tests { let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); - a.commit_storage(&mut db); + a.commit_storage(&Default::default(), &mut db); a.set_storage(1.into(), 0x1234.into()); - a.commit_storage(&mut db); + a.commit_storage(&Default::default(), &mut db); a.set_storage(1.into(), 0.into()); - a.commit_storage(&mut db); + a.commit_storage(&Default::default(), &mut db); assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); } diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index 4426d3059..e487548a3 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -254,7 +254,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, last_hashes, None, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); assert!(b.try_seal(engine.deref(), seal).is_ok()); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 13a2024d9..9453e1350 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -222,6 +222,7 @@ impl<'x> OpenBlock<'x> { pub fn new( engine: &'x Engine, vm_factory: &'x EvmFactory, + trie_factory: TrieFactory, tracing: bool, db: Box, parent: &Header, @@ -231,7 +232,7 @@ impl<'x> OpenBlock<'x> { gas_range_target: (U256, U256), extra_data: Bytes, ) -> Result { - let state = try!(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())); + let state = try!(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(), trie_factory)); let mut r = OpenBlock { block: ExecutedBlock::new(state, tracing), engine: engine, @@ -481,16 +482,17 @@ pub fn enact( parent: &Header, last_hashes: LastHashes, dao_rescue_block_gas_limit: Option, - vm_factory: &EvmFactory + vm_factory: &EvmFactory, + trie_factory: TrieFactory, ) -> Result { { if ::log::max_log_level() >= ::log::LogLevel::Trace { - let s = try!(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce())); + let s = try!(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(), trie_factory.clone())); trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author())); } } - let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone())); + let mut b = try!(OpenBlock::new(engine, vm_factory, trie_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone())); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); @@ -509,11 +511,12 @@ pub fn enact_bytes( parent: &Header, last_hashes: LastHashes, dao_rescue_block_gas_limit: Option, - vm_factory: &EvmFactory + vm_factory: &EvmFactory, + trie_factory: TrieFactory, ) -> Result { let block = BlockView::new(block_bytes); let header = block.header(); - enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory) + enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory, trie_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header @@ -526,10 +529,11 @@ pub fn enact_verified( parent: &Header, last_hashes: LastHashes, dao_rescue_block_gas_limit: Option, - vm_factory: &EvmFactory + vm_factory: &EvmFactory, + trie_factory: TrieFactory, ) -> Result { let view = BlockView::new(&block.bytes); - enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory) + enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory, trie_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards @@ -542,10 +546,11 @@ pub fn enact_and_seal( parent: &Header, last_hashes: LastHashes, dao_rescue_block_gas_limit: Option, - vm_factory: &EvmFactory + vm_factory: &EvmFactory, + trie_factory: TrieFactory, ) -> Result { let header = BlockView::new(block_bytes).header_view(); - Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory)).seal(engine, header.seal()))) + Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory, trie_factory)).seal(engine, header.seal()))) } #[cfg(test)] @@ -565,7 +570,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); let _ = b.seal(engine.deref(), vec![]); } @@ -581,7 +586,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap() + let b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap() .close_and_lock().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); @@ -589,7 +594,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default(), Default::default()).unwrap(); assert_eq!(e.rlp_bytes(), orig_bytes); @@ -609,7 +614,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); + let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.extra_data = b"uncle1".to_vec(); let mut uncle2_header = Header::new(); @@ -624,7 +629,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default(), Default::default()).unwrap(); let bytes = e.rlp_bytes(); assert_eq!(bytes, orig_bytes); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 99617023a..bf1ae7f05 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -94,6 +94,7 @@ pub struct Client { panic_handler: Arc, verifier: Box, vm_factory: Arc, + trie_factory: TrieFactory, miner: Arc, io_channel: IoChannel, queue_transactions: AtomicUsize, @@ -175,6 +176,7 @@ impl Client { panic_handler: panic_handler, verifier: verification::new(config.verifier_type), vm_factory: Arc::new(EvmFactory::new(config.vm_type)), + trie_factory: TrieFactory::new(config.trie_spec), miner: miner, io_channel: message_channel, queue_transactions: AtomicUsize::new(0), @@ -233,7 +235,7 @@ impl Client { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().boxed_clone(); - let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(header.parent_hash.clone()), &self.vm_factory); + let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(header.parent_hash.clone()), &self.vm_factory, self.trie_factory.clone()); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -418,13 +420,17 @@ impl Client { let root = HeaderView::new(&header).state_root(); - State::from_existing(db, root, self.engine.account_start_nonce()).ok() + State::from_existing(db, root, self.engine.account_start_nonce(), self.trie_factory.clone()).ok() }) } /// Get a copy of the best block's state. pub fn state(&self) -> State { - State::from_existing(self.state_db.lock().unwrap().boxed_clone(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce()) + State::from_existing( + self.state_db.lock().unwrap().boxed_clone(), + HeaderView::new(&self.best_block_header()).state_root(), + self.engine.account_start_nonce(), + self.trie_factory.clone()) .expect("State root of best block header always valid.") } @@ -809,6 +815,7 @@ impl MiningBlockChainClient for Client { let mut open_block = OpenBlock::new( engine, &self.vm_factory, + self.trie_factory.clone(), false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. self.state_db.lock().unwrap().boxed_clone(), &self.chain.block_header(&h).expect("h is best block hash: so it's header must exist: qed"), diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 52a875a2f..6cb34c151 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -20,6 +20,7 @@ pub use trace::{Config as TraceConfig, Switch}; pub use evm::VMType; pub use verification::VerifierType; use util::journaldb; +use util::trie::TrieSpec; /// Client state db compaction profile #[derive(Debug, PartialEq)] @@ -45,6 +46,8 @@ pub struct ClientConfig { pub tracing: TraceConfig, /// VM type. pub vm_type: VMType, + /// Trie type. + pub trie_spec: TrieSpec, /// The JournalDB ("pruning") algorithm to use. pub pruning: journaldb::Algorithm, /// The name of the client instance. diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 84c2a9608..c438c33ca 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -325,7 +325,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -340,7 +340,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); + let mut b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index ed75576c6..d40ee8983 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -67,7 +67,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce()).unwrap(); + let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce(), Default::default()).unwrap(); assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000001")), U256::from(1u64)); assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000002")), U256::from(1u64)); assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000003")), U256::from(1u64)); diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 0c086ffc3..92a501e80 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -42,6 +42,7 @@ pub struct State { cache: RefCell>>, snapshots: RefCell>>>>, account_start_nonce: U256, + trie_factory: TrieFactory, } const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \ @@ -50,11 +51,11 @@ const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with v impl State { /// Creates new state with empty state root #[cfg(test)] - pub fn new(mut db: Box, account_start_nonce: U256) -> State { + pub fn new(mut db: Box, account_start_nonce: U256, trie_factory: TrieFactory) -> State { let mut root = H256::new(); { // init trie and reset root too null - let _ = SecTrieDBMut::new(db.as_hashdb_mut(), &mut root); + let _ = trie_factory.create(db.as_hashdb_mut(), &mut root); } State { @@ -63,22 +64,26 @@ impl State { cache: RefCell::new(HashMap::new()), snapshots: RefCell::new(Vec::new()), account_start_nonce: account_start_nonce, + trie_factory: trie_factory, } } /// Creates new state with existing state root - pub fn from_existing(db: Box, root: H256, account_start_nonce: U256) -> Result { + pub fn from_existing(db: Box, root: H256, account_start_nonce: U256, trie_factory: TrieFactory) -> Result { if !db.as_hashdb().contains(&root) { - Err(TrieError::InvalidStateRoot) - } else { - Ok(State { - db: db, - root: root, - cache: RefCell::new(HashMap::new()), - snapshots: RefCell::new(Vec::new()), - account_start_nonce: account_start_nonce, - }) + return Err(TrieError::InvalidStateRoot); } + + let state = State { + db: db, + root: root, + cache: RefCell::new(HashMap::new()), + snapshots: RefCell::new(Vec::new()), + account_start_nonce: account_start_nonce, + trie_factory: trie_factory, + }; + + Ok(state) } /// Create a recoverable snaphot of this state @@ -156,7 +161,7 @@ impl State { /// Determine whether an account exists. pub fn exists(&self, a: &Address) -> bool { - let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); + let db = self.trie_factory.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); self.cache.borrow().get(&a).unwrap_or(&None).is_some() || db.contains(&a) } @@ -242,7 +247,10 @@ impl State { for a in &addresses { if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { // Figure out if the balance has been reduced. - let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); + let maybe_original = self.trie_factory + .readonly(self.db.as_hashdb(), &self.root) + .expect(SEC_TRIE_DB_UNWRAP_STR) + .get(&a).map(Account::from_rlp); if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { return Err(Error::Transaction(TransactionError::DAORescue)); } @@ -262,14 +270,14 @@ impl State { /// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit. /// `accounts` is mutable because we may need to commit the code or storage and record that. #[cfg_attr(feature="dev", allow(match_ref_pats))] - pub fn commit_into(db: &mut HashDB, root: &mut H256, accounts: &mut HashMap>) { + pub fn commit_into(trie_factory: &TrieFactory, db: &mut HashDB, root: &mut H256, accounts: &mut HashMap>) { // first, commit the sub trees. // TODO: is this necessary or can we dispense with the `ref mut a` for just `a`? for (address, ref mut a) in accounts.iter_mut() { match a { &mut&mut Some(ref mut account) => { let mut account_db = AccountDBMut::new(db, address); - account.commit_storage(&mut account_db); + account.commit_storage(trie_factory, &mut account_db); account.commit_code(&mut account_db); } &mut&mut None => {} @@ -277,7 +285,7 @@ impl State { } { - let mut trie = SecTrieDBMut::from_existing(db, root).unwrap(); + let mut trie = trie_factory.from_existing(db, root).unwrap(); for (address, ref a) in accounts.iter() { match **a { Some(ref account) => trie.insert(address, &account.rlp()), @@ -290,7 +298,7 @@ impl State { /// Commits our cached account changes into the trie. pub fn commit(&mut self) { assert!(self.snapshots.borrow().is_empty()); - Self::commit_into(self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut()); + Self::commit_into(&self.trie_factory, self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut()); } #[cfg(test)] @@ -340,7 +348,7 @@ impl State { fn get<'a>(&'a self, a: &Address, require_code: bool) -> &'a Option { let have_key = self.cache.borrow().contains_key(a); if !have_key { - let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); + let db = self.trie_factory.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); self.insert_cache(a, db.get(&a).map(Account::from_rlp)) } if require_code { @@ -361,7 +369,7 @@ impl State { fn require_or_from<'a, F: FnOnce() -> Account, G: FnOnce(&mut Account)>(&self, a: &Address, require_code: bool, default: F, not_default: G) -> &'a mut Account { let have_key = self.cache.borrow().contains_key(a); if !have_key { - let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); + let db = self.trie_factory.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); self.insert_cache(a, db.get(&a).map(Account::from_rlp)) } else { self.note_cache(a); @@ -396,6 +404,7 @@ impl Clone for State { cache: RefCell::new(self.cache.borrow().clone()), snapshots: RefCell::new(self.snapshots.borrow().clone()), account_start_nonce: self.account_start_nonce.clone(), + trie_factory: self.trie_factory.clone(), } } } @@ -1179,7 +1188,7 @@ fn code_from_database() { state.drop() }; - let state = State::from_existing(db, root, U256::from(0u8)).unwrap(); + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec())); } @@ -1194,7 +1203,7 @@ fn storage_at_from_database() { state.drop() }; - let s = State::from_existing(db, root, U256::from(0u8)).unwrap(); + let s = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(s.storage_at(&a, &H256::from(&U256::from(01u64))), H256::from(&U256::from(69u64))); } @@ -1211,7 +1220,7 @@ fn get_from_database() { state.drop() }; - let state = State::from_existing(db, root, U256::from(0u8)).unwrap(); + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.nonce(&a), U256::from(1u64)); } @@ -1244,7 +1253,7 @@ fn remove_from_database() { }; let (root, db) = { - let mut state = State::from_existing(db, root, U256::from(0u8)).unwrap(); + let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.exists(&a), true); assert_eq!(state.nonce(&a), U256::from(1u64)); state.kill_account(&a); @@ -1254,7 +1263,7 @@ fn remove_from_database() { state.drop() }; - let state = State::from_existing(db, root, U256::from(0u8)).unwrap(); + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.exists(&a), false); assert_eq!(state.nonce(&a), U256::from(0u64)); } diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 70a644896..ad8058ac6 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -175,6 +175,7 @@ pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_numbe let mut b = OpenBlock::new( test_engine.deref(), &vm_factory, + Default::default(), false, db, &last_header, @@ -315,7 +316,7 @@ pub fn get_temp_state() -> GuardedTempResult { let journal_db = get_temp_journal_db_in(temp.as_path()); GuardedTempResult { _temp: temp, - result: Some(State::new(journal_db, U256::from(0u8))) + result: Some(State::new(journal_db, U256::from(0), Default::default())), } } @@ -325,7 +326,7 @@ pub fn get_temp_journal_db_in(path: &Path) -> Box { pub fn get_temp_state_in(path: &Path) -> State { let journal_db = get_temp_journal_db_in(path); - State::new(journal_db, U256::from(0u8)) + State::new(journal_db, U256::from(0), Default::default()) } pub fn get_good_dummy_block_seq(count: usize) -> Vec { diff --git a/parity/cli.rs b/parity/cli.rs index 7ebbcb0aa..ef9ce8ce3 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -203,6 +203,7 @@ Database Options: --db-compaction TYPE Database compaction type. TYPE may be one of: ssd - suitable for SSDs and fast HDDs; hdd - suitable for slow HDDs [default: ssd]. + --fat-db Fat database. Import/Export Options: --from BLOCK Export from block BLOCK, which may be an index or @@ -362,6 +363,7 @@ pub struct Args { pub flag_ipcapi: Option, pub flag_db_cache_size: Option, pub flag_db_compaction: String, + pub flag_fat_db: bool, } pub fn print_version() { diff --git a/parity/configuration.rs b/parity/configuration.rs index fb31bf7ad..96524f5ea 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -333,6 +333,14 @@ impl Configuration { _ => { die!("Invalid pruning method given."); } }; + if self.args.flag_fat_db { + if let journaldb::Algorithm::Archive = client_config.pruning { + client_config.trie_spec = TrieSpec::Fat; + } else { + die!("Fatdb is not supported. Please rerun with --pruning=archive") + } + } + // forced state db cache size if provided client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4));