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

Commit

Permalink
Merge pull request #673 from ethcore/boxjdb
Browse files Browse the repository at this point in the history
JournalDB -> Box<JournalDB>, and it's a trait.
  • Loading branch information
NikVolf committed Mar 11, 2016
2 parents eaf2219 + 5499f45 commit 03a4f9e
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 95 deletions.
22 changes: 11 additions & 11 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub struct SealedBlock {

impl<'x> OpenBlock<'x> {
/// Create a new OpenBlock ready for transaction pushing.
pub fn new(engine: &'x Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes, author: Address, extra_data: Bytes) -> Self {
pub fn new(engine: &'x Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, extra_data: Bytes) -> Self {
let mut r = OpenBlock {
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())),
engine: engine,
Expand Down Expand Up @@ -317,7 +317,7 @@ impl ClosedBlock {
}

/// Drop this object and return the underlieing database.
pub fn drain(self) -> JournalDB { self.block.state.drop().1 }
pub fn drain(self) -> Box<JournalDB> { self.block.state.drop().1 }
}

impl SealedBlock {
Expand All @@ -331,18 +331,18 @@ impl SealedBlock {
}

/// Drop this object and return the underlieing database.
pub fn drain(self) -> JournalDB { self.block.state.drop().1 }
pub fn drain(self) -> Box<JournalDB> { self.block.state.drop().1 }
}

impl IsBlock for SealedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
}

/// Enact the block given by block header, transactions and uncles
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
let s = State::from_existing(db.clone(), parent.state_root().clone(), engine.account_start_nonce());
let s = State::from_existing(db.spawn(), parent.state_root().clone(), engine.account_start_nonce());
trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author()));
}
}
Expand All @@ -357,20 +357,20 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
let block = BlockView::new(block_bytes);
let header = block.header();
enact(&header, &block.transactions(), &block.uncles(), engine, db, parent, last_hashes)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
let view = BlockView::new(&block.bytes);
enact(&block.header, &block.transactions, &view.uncles(), engine, db, parent, last_hashes)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<SealedBlock, Error> {
pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<SealedBlock, Error> {
let header = BlockView::new(block_bytes).header_view();
Ok(try!(try!(enact_bytes(block_bytes, engine, db, parent, last_hashes)).seal(engine, header.seal())))
}
Expand All @@ -389,7 +389,7 @@ mod tests {
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let last_hashes = vec![genesis_header.hash()];
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]);
let b = b.close();
Expand All @@ -404,14 +404,14 @@ mod tests {

let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), vec![]).close().seal(engine.deref(), vec![]).unwrap();
let orig_bytes = b.rlp_bytes();
let orig_db = b.drain();

let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let e = enact_and_seal(&orig_bytes, engine.deref(), db, &genesis_header, vec![genesis_header.hash()]).unwrap();

assert_eq!(e.rlp_bytes(), orig_bytes);
Expand Down
12 changes: 6 additions & 6 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl ClientReport {
pub struct Client<V = CanonVerifier> where V: Verifier {
chain: Arc<BlockChain>,
engine: Arc<Box<Engine>>,
state_db: Mutex<JournalDB>,
state_db: Mutex<Box<JournalDB>>,
block_queue: BlockQueue,
report: RwLock<ClientReport>,
import_lock: Mutex<()>,
Expand Down Expand Up @@ -139,8 +139,8 @@ impl<V> Client<V> where V: Verifier {
state_path.push("state");

let engine = Arc::new(try!(spec.to_engine()));
let mut state_db = JournalDB::from_prefs(state_path.to_str().unwrap(), config.prefer_journal);
if state_db.is_empty() && engine.spec().ensure_db_good(&mut state_db) {
let mut state_db = Box::new(OptionOneDB::from_prefs(state_path.to_str().unwrap(), config.prefer_journal));
if state_db.is_empty() && engine.spec().ensure_db_good(state_db.deref_mut()) {
state_db.commit(0, &engine.spec().genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
}

Expand Down Expand Up @@ -212,7 +212,7 @@ impl<V> Client<V> where V: Verifier {
// Enact Verified Block
let parent = chain_has_parent.unwrap();
let last_hashes = self.build_last_hashes(header.parent_hash.clone());
let db = self.state_db.lock().unwrap().clone();
let db = self.state_db.lock().unwrap().spawn();

let enact_result = enact_verified(&block, engine, db, &parent, last_hashes);
if let Err(e) = enact_result {
Expand Down Expand Up @@ -311,7 +311,7 @@ impl<V> Client<V> where V: Verifier {

/// Get a copy of the best block's state.
pub fn state(&self) -> State {
State::from_existing(self.state_db.lock().unwrap().clone(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce())
State::from_existing(self.state_db.lock().unwrap().spawn(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce())
}

/// Get info on the cache.
Expand Down Expand Up @@ -380,7 +380,7 @@ impl<V> Client<V> where V: Verifier {
let h = self.chain.best_block_hash();
let mut b = OpenBlock::new(
self.engine.deref().deref(),
self.state_db.lock().unwrap().clone(),
self.state_db.lock().unwrap().spawn(),
match self.chain.block_header(&h) { Some(ref x) => x, None => {return;} },
self.build_last_hashes(h.clone()),
self.author(),
Expand Down
4 changes: 2 additions & 2 deletions ethcore/src/ethereum/ethash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ mod tests {
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let last_hashes = vec![genesis_header.hash()];
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]);
let b = b.close();
Expand All @@ -311,7 +311,7 @@ mod tests {
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let last_hashes = vec![genesis_header.hash()];
let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]);
let mut uncle = Header::new();
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ mod tests {
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
engine.spec().ensure_db_good(db.as_hashdb_mut());
let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce());
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000001")), U256::from(1u64));
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000002")), U256::from(1u64));
Expand Down
26 changes: 13 additions & 13 deletions ethcore/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub type ApplyResult = Result<Receipt, Error>;

/// Representation of the entire state of all accounts in the system.
pub struct State {
db: JournalDB,
db: Box<JournalDB>,
root: H256,
cache: RefCell<HashMap<Address, Option<Account>>>,
snapshots: RefCell<Vec<HashMap<Address, Option<Option<Account>>>>>,
Expand All @@ -41,11 +41,11 @@ pub struct State {
impl State {
/// Creates new state with empty state root
#[cfg(test)]
pub fn new(mut db: JournalDB, account_start_nonce: U256) -> State {
pub fn new(mut db: Box<JournalDB>, account_start_nonce: U256) -> State {
let mut root = H256::new();
{
// init trie and reset root too null
let _ = SecTrieDBMut::new(&mut db, &mut root);
let _ = SecTrieDBMut::new(db.as_hashdb_mut(), &mut root);
}

State {
Expand All @@ -58,10 +58,10 @@ impl State {
}

/// Creates new state with existing state root
pub fn from_existing(db: JournalDB, root: H256, account_start_nonce: U256) -> State {
pub fn from_existing(db: Box<JournalDB>, root: H256, account_start_nonce: U256) -> State {
{
// trie should panic! if root does not exist
let _ = SecTrieDB::new(&db, &root);
let _ = SecTrieDB::new(db.as_hashdb(), &root);
}

State {
Expand Down Expand Up @@ -126,7 +126,7 @@ impl State {
}

/// Destroy the current object and return root and database.
pub fn drop(self) -> (H256, JournalDB) {
pub fn drop(self) -> (H256, Box<JournalDB>) {
(self.root, self.db)
}

Expand All @@ -148,7 +148,7 @@ impl State {

/// Determine whether an account exists.
pub fn exists(&self, a: &Address) -> bool {
self.cache.borrow().get(&a).unwrap_or(&None).is_some() || SecTrieDB::new(&self.db, &self.root).contains(&a)
self.cache.borrow().get(&a).unwrap_or(&None).is_some() || SecTrieDB::new(self.db.as_hashdb(), &self.root).contains(&a)
}

/// Get the balance of account `a`.
Expand All @@ -163,7 +163,7 @@ impl State {

/// Mutate storage of account `address` so that it is `value` for `key`.
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
self.get(address, false).as_ref().map_or(H256::new(), |a|a.storage_at(&AccountDB::new(&self.db, address), key))
self.get(address, false).as_ref().map_or(H256::new(), |a|a.storage_at(&AccountDB::new(self.db.as_hashdb(), address), key))
}

/// Mutate storage of account `a` so that it is `value` for `key`.
Expand Down Expand Up @@ -253,7 +253,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(&mut self.db, &mut self.root, self.cache.borrow_mut().deref_mut());
Self::commit_into(self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut());
}

#[cfg(test)]
Expand Down Expand Up @@ -285,11 +285,11 @@ 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 {
self.insert_cache(a, SecTrieDB::new(&self.db, &self.root).get(&a).map(Account::from_rlp))
self.insert_cache(a, SecTrieDB::new(self.db.as_hashdb(), &self.root).get(&a).map(Account::from_rlp))
}
if require_code {
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
account.cache_code(&AccountDB::new(&self.db, a));
account.cache_code(&AccountDB::new(self.db.as_hashdb(), a));
}
}
unsafe { ::std::mem::transmute(self.cache.borrow().get(a).unwrap()) }
Expand All @@ -305,7 +305,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 {
self.insert_cache(a, SecTrieDB::new(&self.db, &self.root).get(&a).map(Account::from_rlp))
self.insert_cache(a, SecTrieDB::new(self.db.as_hashdb(), &self.root).get(&a).map(Account::from_rlp))
} else {
self.note_cache(a);
}
Expand All @@ -318,7 +318,7 @@ impl State {

unsafe { ::std::mem::transmute(self.cache.borrow_mut().get_mut(a).unwrap().as_mut().map(|account| {
if require_code {
account.cache_code(&AccountDB::new(&self.db, a));
account.cache_code(&AccountDB::new(self.db.as_hashdb(), a));
}
account
}).unwrap()) }
Expand Down
8 changes: 4 additions & 4 deletions ethcore/src/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ pub fn generate_dummy_empty_blockchain() -> GuardedTempResult<BlockChain> {
}
}

pub fn get_temp_journal_db() -> GuardedTempResult<JournalDB> {
pub fn get_temp_journal_db() -> GuardedTempResult<Box<JournalDB>> {
let temp = RandomTempPath::new();
let journal_db = JournalDB::new(temp.as_str());
let journal_db: Box<JournalDB> = Box::new(OptionOneDB::new(temp.as_str()));
GuardedTempResult {
_temp: temp,
result: Some(journal_db)
Expand All @@ -268,8 +268,8 @@ pub fn get_temp_state() -> GuardedTempResult<State> {
}
}

pub fn get_temp_journal_db_in(path: &Path) -> JournalDB {
JournalDB::new(path.to_str().unwrap())
pub fn get_temp_journal_db_in(path: &Path) -> Box<JournalDB> {
Box::new(OptionOneDB::new(path.to_str().unwrap()))
}

pub fn get_temp_state_in(path: &Path) -> State {
Expand Down
15 changes: 14 additions & 1 deletion util/src/hashdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use bytes::*;
use std::collections::HashMap;

/// Trait modelling datastore keyed by a 32-byte Keccak hash.
pub trait HashDB {
pub trait HashDB : AsHashDB {
/// Get the keys in the database together with number of underlying references.
fn keys(&self) -> HashMap<H256, i32>;

Expand Down Expand Up @@ -111,3 +111,16 @@ pub trait HashDB {
/// ```
fn remove(&mut self, key: &H256) { self.kill(key) }
}

/// Upcast trait.
pub trait AsHashDB {
/// Perform upcast to HashDB for anything that derives from HashDB.
fn as_hashdb(&self) -> &HashDB;
/// Perform mutable upcast to HashDB for anything that derives from HashDB.
fn as_hashdb_mut(&mut self) -> &mut HashDB;
}

impl<T: HashDB> AsHashDB for T {
fn as_hashdb(&self) -> &HashDB { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB { self }
}

0 comments on commit 03a4f9e

Please sign in to comment.