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

Various state copy optimizations #2172

Merged
merged 5 commits into from
Sep 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ pub struct ClosedBlock {
block: ExecutedBlock,
uncle_bytes: Bytes,
last_hashes: Arc<LastHashes>,
unclosed_state: State,
}

/// Just like `ClosedBlock` except that we can't reopen it and it's faster.
Expand Down Expand Up @@ -343,11 +342,12 @@ impl<'x> OpenBlock<'x> {
}
}

/// Turn this into a `ClosedBlock`. A `BlockChain` must be provided in order to figure out the uncles.
/// Turn this into a `ClosedBlock`.
pub fn close(self) -> ClosedBlock {
let mut s = self;

let unclosed_state = s.block.state.clone();
// take a snapshot so the engine's changes can be rolled back.
s.block.state.snapshot();

s.engine.on_close_block(&mut s.block);
s.block.base.header.set_transactions_root(ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect()));
Expand All @@ -362,14 +362,16 @@ impl<'x> OpenBlock<'x> {
block: s.block,
uncle_bytes: uncle_bytes,
last_hashes: s.last_hashes,
unclosed_state: unclosed_state,
}
}

/// Turn this into a `LockedBlock`. A BlockChain must be provided in order to figure out the uncles.
/// Turn this into a `LockedBlock`.
pub fn close_and_lock(self) -> LockedBlock {
let mut s = self;

// take a snapshot so the engine's changes can be rolled back.
s.block.state.snapshot();

s.engine.on_close_block(&mut s.block);
if s.block.base.header.transactions_root().is_zero() || s.block.base.header.transactions_root() == &SHA3_NULL_RLP {
s.block.base.header.set_transactions_root(ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect()));
Expand All @@ -381,14 +383,16 @@ impl<'x> OpenBlock<'x> {
if s.block.base.header.receipts_root().is_zero() || s.block.base.header.receipts_root() == &SHA3_NULL_RLP {
s.block.base.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().to_vec()).collect()));
}

s.block.base.header.set_state_root(s.block.state.root().clone());
s.block.base.header.set_log_bloom(s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator
s.block.base.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used));

LockedBlock {
ClosedBlock {
block: s.block,
uncle_bytes: uncle_bytes,
}
last_hashes: s.last_hashes,
}.lock()
}
}

Expand All @@ -409,20 +413,30 @@ impl ClosedBlock {
pub fn hash(&self) -> H256 { self.header().rlp_sha3(Seal::Without) }

/// Turn this into a `LockedBlock`, unable to be reopened again.
pub fn lock(self) -> LockedBlock {
pub fn lock(mut self) -> LockedBlock {
// finalize the changes made by the engine.
self.block.state.clear_snapshot();
if let Err(e) = self.block.state.commit() {
warn!("Error committing closed block's state: {:?}", e);
}

// set the state root here, after commit recalculates with the block
// rewards.
self.block.base.header.set_state_root(self.block.state.root().clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line cannot exist. it breaks mining.


LockedBlock {
block: self.block,
uncle_bytes: self.uncle_bytes,
}
}

/// Given an engine reference, reopen the `ClosedBlock` into an `OpenBlock`.
pub fn reopen(self, engine: &Engine) -> OpenBlock {
pub fn reopen(mut self, engine: &Engine) -> OpenBlock {
// revert rewards (i.e. set state back at last transaction's state).
let mut block = self.block;
block.state = self.unclosed_state;
self.block.state.revert_snapshot();

OpenBlock {
block: block,
block: self.block,
engine: engine,
last_hashes: self.last_hashes,
}
Expand Down
4 changes: 1 addition & 3 deletions ethcore/src/ethereum/ethash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,7 @@ impl Engine for Ethash {
for u in fields.uncles.iter() {
fields.state.add_balance(u.author(), &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)));
}
if let Err(e) = fields.state.commit() {
warn!("Encountered error on state commit: {}", e);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er... no.

}

fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
Expand Down
19 changes: 18 additions & 1 deletion ethcore/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,27 @@ impl fmt::Debug for State {

impl Clone for State {
fn clone(&self) -> State {
let cache = {
let mut cache = HashMap::new();
for (key, val) in self.cache.borrow().iter() {
let key = key.clone();
match *val {
Some(ref acc) if acc.is_dirty() => {
cache.insert(key, Some(acc.clone()));
},
None => {
cache.insert(key, None);
},
_ => {},
}
}
cache
};

State {
db: self.db.boxed_clone(),
root: self.root.clone(),
cache: RefCell::new(self.cache.borrow().clone()),
cache: RefCell::new(cache),
snapshots: RefCell::new(self.snapshots.borrow().clone()),
account_start_nonce: self.account_start_nonce.clone(),
factories: self.factories.clone(),
Expand Down