Fatdb integration with CLI (#1464)
* fatdb integration * --fat-db * rerun with --pruning=archive comment
This commit is contained in:
		
							parent
							
								
									0a513ad06e
								
							
						
					
					
						commit
						d8a4cca817
					
				| @ -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"); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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()); | ||||
|  | ||||
| @ -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<JournalDB>, | ||||
| 		parent: &Header, | ||||
| @ -231,7 +232,7 @@ impl<'x> OpenBlock<'x> { | ||||
| 		gas_range_target: (U256, U256), | ||||
| 		extra_data: Bytes, | ||||
| 	) -> Result<Self, Error> { | ||||
| 		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<U256>, | ||||
| 	vm_factory: &EvmFactory | ||||
| 	vm_factory: &EvmFactory, | ||||
| 	trie_factory: TrieFactory, | ||||
| ) -> Result<LockedBlock, Error> { | ||||
| 	{ | ||||
| 		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<U256>, | ||||
| 	vm_factory: &EvmFactory | ||||
| 	vm_factory: &EvmFactory, | ||||
| 	trie_factory: TrieFactory, | ||||
| ) -> Result<LockedBlock, Error> { | ||||
| 	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<U256>, | ||||
| 	vm_factory: &EvmFactory | ||||
| 	vm_factory: &EvmFactory, | ||||
| 	trie_factory: TrieFactory, | ||||
| ) -> Result<LockedBlock, Error> { | ||||
| 	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<U256>, | ||||
| 	vm_factory: &EvmFactory | ||||
| 	vm_factory: &EvmFactory, | ||||
| 	trie_factory: TrieFactory, | ||||
| ) -> Result<SealedBlock, Error> { | ||||
| 	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); | ||||
|  | ||||
| @ -94,6 +94,7 @@ pub struct Client { | ||||
| 	panic_handler: Arc<PanicHandler>, | ||||
| 	verifier: Box<Verifier>, | ||||
| 	vm_factory: Arc<EvmFactory>, | ||||
| 	trie_factory: TrieFactory, | ||||
| 	miner: Arc<Miner>, | ||||
| 	io_channel: IoChannel<NetSyncMessage>, | ||||
| 	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"), | ||||
|  | ||||
| @ -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.
 | ||||
|  | ||||
| @ -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(); | ||||
|  | ||||
| @ -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)); | ||||
|  | ||||
| @ -42,6 +42,7 @@ pub struct State { | ||||
| 	cache: RefCell<HashMap<Address, Option<Account>>>, | ||||
| 	snapshots: RefCell<Vec<HashMap<Address, Option<Option<Account>>>>>, | ||||
| 	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<JournalDB>, account_start_nonce: U256) -> State { | ||||
| 	pub fn new(mut db: Box<JournalDB>, 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<JournalDB>, root: H256, account_start_nonce: U256) -> Result<State, TrieError> { | ||||
| 	pub fn from_existing(db: Box<JournalDB>, root: H256, account_start_nonce: U256, trie_factory: TrieFactory) -> Result<State, TrieError> { | ||||
| 		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<Address, Option<Account>>) { | ||||
| 	pub fn commit_into(trie_factory: &TrieFactory, db: &mut HashDB, root: &mut H256, accounts: &mut HashMap<Address, Option<Account>>) { | ||||
| 		// 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<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)) | ||||
| 		} | ||||
| 		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)); | ||||
| } | ||||
|  | ||||
| @ -175,6 +175,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(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<State> { | ||||
| 	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<JournalDB> { | ||||
| 
 | ||||
| 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<Bytes> { | ||||
|  | ||||
| @ -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<String>, | ||||
| 	pub flag_db_cache_size: Option<usize>, | ||||
| 	pub flag_db_compaction: String, | ||||
| 	pub flag_fat_db: bool, | ||||
| } | ||||
| 
 | ||||
| pub fn print_version() { | ||||
|  | ||||
| @ -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)); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user