Merge branch 'master' into evm
Conflicts: src/evm/tests.rs src/executive.rs
This commit is contained in:
commit
a1a4c5a068
@ -205,7 +205,6 @@ impl Account {
|
|||||||
match (self.code_hash.is_none(), self.code_cache.is_empty()) {
|
match (self.code_hash.is_none(), self.code_cache.is_empty()) {
|
||||||
(true, true) => self.code_hash = Some(SHA3_EMPTY),
|
(true, true) => self.code_hash = Some(SHA3_EMPTY),
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
println!("Writing into DB {:?}", self.code_cache);
|
|
||||||
self.code_hash = Some(db.insert(&self.code_cache));
|
self.code_hash = Some(db.insert(&self.code_cache));
|
||||||
},
|
},
|
||||||
(false, _) => {},
|
(false, _) => {},
|
||||||
|
21
src/block.rs
21
src/block.rs
@ -126,6 +126,15 @@ impl<'x, 'y> OpenBlock<'x, 'y> {
|
|||||||
/// Alter the timestamp of the block.
|
/// Alter the timestamp of the block.
|
||||||
pub fn set_timestamp(&mut self, timestamp: u64) { self.block.header.set_timestamp(timestamp); }
|
pub fn set_timestamp(&mut self, timestamp: u64) { self.block.header.set_timestamp(timestamp); }
|
||||||
|
|
||||||
|
/// Alter the difficulty for the block.
|
||||||
|
pub fn set_difficulty(&mut self, a: U256) { self.block.header.set_difficulty(a); }
|
||||||
|
|
||||||
|
/// Alter the gas limit for the block.
|
||||||
|
pub fn set_gas_limit(&mut self, a: U256) { self.block.header.set_gas_limit(a); }
|
||||||
|
|
||||||
|
/// Alter the gas limit for the block.
|
||||||
|
pub fn set_gas_used(&mut self, a: U256) { self.block.header.set_gas_used(a); }
|
||||||
|
|
||||||
/// Alter the extra_data for the block.
|
/// Alter the extra_data for the block.
|
||||||
pub fn set_extra_data(&mut self, extra_data: Bytes) -> Result<(), BlockError> {
|
pub fn set_extra_data(&mut self, extra_data: Bytes) -> Result<(), BlockError> {
|
||||||
if extra_data.len() > self.engine.maximum_extra_data_size() {
|
if extra_data.len() > self.engine.maximum_extra_data_size() {
|
||||||
@ -158,7 +167,7 @@ impl<'x, 'y> OpenBlock<'x, 'y> {
|
|||||||
author: self.block.header.author.clone(),
|
author: self.block.header.author.clone(),
|
||||||
timestamp: self.block.header.timestamp,
|
timestamp: self.block.header.timestamp,
|
||||||
difficulty: self.block.header.difficulty.clone(),
|
difficulty: self.block.header.difficulty.clone(),
|
||||||
last_hashes: self.last_hashes.clone(),
|
last_hashes: self.last_hashes.clone(), // TODO: should be a reference.
|
||||||
gas_used: self.block.archive.last().map(|t| t.receipt.gas_used).unwrap_or(U256::from(0)),
|
gas_used: self.block.archive.last().map(|t| t.receipt.gas_used).unwrap_or(U256::from(0)),
|
||||||
gas_limit: self.block.header.gas_limit.clone(),
|
gas_limit: self.block.header.gas_limit.clone(),
|
||||||
}
|
}
|
||||||
@ -169,6 +178,7 @@ impl<'x, 'y> OpenBlock<'x, 'y> {
|
|||||||
/// If valid, it will be executed, and archived together with the receipt.
|
/// If valid, it will be executed, and archived together with the receipt.
|
||||||
pub fn push_transaction(&mut self, t: Transaction, h: Option<H256>) -> Result<&Receipt, Error> {
|
pub fn push_transaction(&mut self, t: Transaction, h: Option<H256>) -> Result<&Receipt, Error> {
|
||||||
let env_info = self.env_info();
|
let env_info = self.env_info();
|
||||||
|
// info!("env_info says gas_used={}", env_info.gas_used);
|
||||||
match self.block.state.apply(&env_info, self.engine, &t) {
|
match self.block.state.apply(&env_info, self.engine, &t) {
|
||||||
Ok(receipt) => {
|
Ok(receipt) => {
|
||||||
self.block.archive_set.insert(h.unwrap_or_else(||t.hash()));
|
self.block.archive_set.insert(h.unwrap_or_else(||t.hash()));
|
||||||
@ -255,10 +265,19 @@ impl IsBlock for SealedBlock {
|
|||||||
|
|
||||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||||
pub fn enact<'x, 'y>(block_bytes: &[u8], engine: &'x Engine, db: OverlayDB, parent: &Header, last_hashes: &'y LastHashes) -> Result<ClosedBlock<'x, 'y>, Error> {
|
pub fn enact<'x, 'y>(block_bytes: &[u8], engine: &'x Engine, db: OverlayDB, parent: &Header, last_hashes: &'y LastHashes) -> Result<ClosedBlock<'x, 'y>, Error> {
|
||||||
|
{
|
||||||
|
let header = BlockView::new(block_bytes).header_view();
|
||||||
|
let s = State::from_existing(db.clone(), parent.state_root().clone(), engine.account_start_nonce());
|
||||||
|
trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author()));
|
||||||
|
}
|
||||||
|
|
||||||
let block = BlockView::new(block_bytes);
|
let block = BlockView::new(block_bytes);
|
||||||
let header = block.header_view();
|
let header = block.header_view();
|
||||||
let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author(), header.extra_data());
|
let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author(), header.extra_data());
|
||||||
|
b.set_difficulty(header.difficulty());
|
||||||
|
b.set_gas_limit(header.gas_limit());
|
||||||
b.set_timestamp(header.timestamp());
|
b.set_timestamp(header.timestamp());
|
||||||
|
// info!("enact: Enacting #{}. env_info={:?}", header.number(), b.env_info());
|
||||||
for t in block.transactions().into_iter() { try!(b.push_transaction(t, None)); }
|
for t in block.transactions().into_iter() { try!(b.push_transaction(t, None)); }
|
||||||
for u in block.uncles().into_iter() { try!(b.push_uncle(u)); }
|
for u in block.uncles().into_iter() { try!(b.push_uncle(u)); }
|
||||||
Ok(b.close())
|
Ok(b.close())
|
||||||
|
@ -142,14 +142,13 @@ impl Client {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
// build last hashes
|
// build last hashes
|
||||||
let mut last = self.chain.read().unwrap().best_block_hash();
|
|
||||||
let mut last_hashes = LastHashes::new();
|
let mut last_hashes = LastHashes::new();
|
||||||
last_hashes.resize(256, H256::new());
|
last_hashes.resize(256, H256::new());
|
||||||
|
last_hashes[0] = header.parent_hash.clone();
|
||||||
for i in 0..255 {
|
for i in 0..255 {
|
||||||
match self.chain.read().unwrap().block_details(&last) {
|
match self.chain.read().unwrap().block_details(&last_hashes[i]) {
|
||||||
Some(details) => {
|
Some(details) => {
|
||||||
last_hashes[i + 1] = details.parent.clone();
|
last_hashes[i + 1] = details.parent.clone();
|
||||||
last = details.parent.clone();
|
|
||||||
},
|
},
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,8 @@ impl Engine for Ethash {
|
|||||||
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + x!(1) + (header.gas_used * x!(6) / x!(5)) / bound_divisor)
|
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + x!(1) + (header.gas_used * x!(6) / x!(5)) / bound_divisor)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
/// Apply the block reward on finalisation of the block.
|
||||||
|
@ -7,10 +7,10 @@ use env_info::*;
|
|||||||
|
|
||||||
pub trait Ext {
|
pub trait Ext {
|
||||||
/// Returns a value for given key.
|
/// Returns a value for given key.
|
||||||
fn sload(&self, key: &H256) -> H256;
|
fn storage_at(&self, key: &H256) -> H256;
|
||||||
|
|
||||||
/// Stores a value for given key.
|
/// Stores a value for given key.
|
||||||
fn sstore(&mut self, key: H256, value: H256);
|
fn set_storage_at(&mut self, key: H256, value: H256);
|
||||||
|
|
||||||
/// Returns address balance.
|
/// Returns address balance.
|
||||||
fn balance(&self, address: &Address) -> U256;
|
fn balance(&self, address: &Address) -> U256;
|
||||||
|
@ -301,7 +301,7 @@ impl Interpreter {
|
|||||||
instructions::SSTORE => {
|
instructions::SSTORE => {
|
||||||
let address = H256::from(stack.peek(0));
|
let address = H256::from(stack.peek(0));
|
||||||
let newval = stack.peek(1);
|
let newval = stack.peek(1);
|
||||||
let val = U256::from(ext.sload(&address).as_slice());
|
let val = U256::from(ext.storage_at(&address).as_slice());
|
||||||
|
|
||||||
let gas = if self.is_zero(&val) && !self.is_zero(newval) {
|
let gas = if self.is_zero(&val) && !self.is_zero(newval) {
|
||||||
schedule.sstore_set_gas
|
schedule.sstore_set_gas
|
||||||
@ -618,13 +618,13 @@ impl Interpreter {
|
|||||||
},
|
},
|
||||||
instructions::SLOAD => {
|
instructions::SLOAD => {
|
||||||
let key = H256::from(&stack.pop_back());
|
let key = H256::from(&stack.pop_back());
|
||||||
let word = U256::from(ext.sload(&key).as_slice());
|
let word = U256::from(ext.storage_at(&key).as_slice());
|
||||||
stack.push(word);
|
stack.push(word);
|
||||||
},
|
},
|
||||||
instructions::SSTORE => {
|
instructions::SSTORE => {
|
||||||
let key = H256::from(&stack.pop_back());
|
let key = H256::from(&stack.pop_back());
|
||||||
let word = H256::from(&stack.pop_back());
|
let word = H256::from(&stack.pop_back());
|
||||||
ext.sstore(key, word);
|
ext.set_storage_at(key, word);
|
||||||
},
|
},
|
||||||
instructions::PC => {
|
instructions::PC => {
|
||||||
stack.push(U256::from(code.position - 1));
|
stack.push(U256::from(code.position - 1));
|
||||||
|
@ -175,14 +175,14 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> {
|
|||||||
fn sload(&self, index: *const evmjit::I256, out_value: *mut evmjit::I256) {
|
fn sload(&self, index: *const evmjit::I256, out_value: *mut evmjit::I256) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let i = H256::from_jit(&*index);
|
let i = H256::from_jit(&*index);
|
||||||
let o = self.ext.sload(&i);
|
let o = self.ext.storage_at(&i);
|
||||||
*out_value = o.into_jit();
|
*out_value = o.into_jit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sstore(&mut self, index: *const evmjit::I256, value: *const evmjit::I256) {
|
fn sstore(&mut self, index: *const evmjit::I256, value: *const evmjit::I256) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.ext.sstore(H256::from_jit(&*index), H256::from_jit(&*value));
|
self.ext.set_storage_at(H256::from_jit(&*index), H256::from_jit(&*value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ impl Default for Schedule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ext for FakeExt {
|
impl Ext for FakeExt {
|
||||||
fn sload(&self, key: &H256) -> H256 {
|
fn storage_at(&self, key: &H256) -> H256 {
|
||||||
self.store.get(key).unwrap_or(&H256::new()).clone()
|
self.store.get(key).unwrap_or(&H256::new()).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sstore(&mut self, key: H256, value: H256) {
|
fn set_storage_at(&mut self, key: H256, value: H256) {
|
||||||
self.store.insert(key, value);
|
self.store.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,7 @@ impl<'a> Executive<'a> {
|
|||||||
|
|
||||||
// at first, transfer value to destination
|
// at first, transfer value to destination
|
||||||
self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value);
|
self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value);
|
||||||
|
debug!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
||||||
|
|
||||||
if self.engine.is_builtin(¶ms.code_address) {
|
if self.engine.is_builtin(¶ms.code_address) {
|
||||||
// if destination is builtin, try to execute it
|
// if destination is builtin, try to execute it
|
||||||
@ -200,7 +201,11 @@ impl<'a> Executive<'a> {
|
|||||||
let mut ext = self.to_externalities(params, &mut unconfirmed_substate, OutputPolicy::Return(output));
|
let mut ext = self.to_externalities(params, &mut unconfirmed_substate, OutputPolicy::Return(output));
|
||||||
self.engine.vm_factory().create().exec(¶ms, &mut ext)
|
self.engine.vm_factory().create().exec(¶ms, &mut ext)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
trace!("exec: sstore-clears={}\n", unconfirmed_substate.refunds_count);
|
||||||
|
trace!("exec: substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
|
||||||
self.enact_result(&res, substate, unconfirmed_substate, backup);
|
self.enact_result(&res, substate, unconfirmed_substate, backup);
|
||||||
|
trace!("exec: new substate={:?}\n", substate);
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
// otherwise, nothing
|
// otherwise, nothing
|
||||||
@ -240,20 +245,24 @@ impl<'a> Executive<'a> {
|
|||||||
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count;
|
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count;
|
||||||
// refunds from contract suicides
|
// refunds from contract suicides
|
||||||
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
|
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
|
||||||
|
let refunds_bound = sstore_refunds + suicide_refunds;
|
||||||
|
|
||||||
// real ammount to refund
|
// real ammount to refund
|
||||||
let gas_left = match &result { &Ok(x) => x, _ => x!(0) };
|
let gas_left_prerefund = match &result { &Ok(x) => x, _ => x!(0) };
|
||||||
let refund = cmp::min(sstore_refunds + suicide_refunds, (t.gas - gas_left) / U256::from(2)) + gas_left;
|
let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) / U256::from(2));
|
||||||
let refund_value = refund * t.gas_price;
|
let gas_left = gas_left_prerefund + refunded;
|
||||||
trace!("Refunding sender: sstore0s: {}, suicides: {}, gas_left: {}, refund: {}, refund_value: {}, sender: {}", sstore_refunds, suicide_refunds, gas_left, refund, refund_value, t.sender().unwrap());
|
|
||||||
self.state.add_balance(&t.sender().unwrap(), &refund_value);
|
|
||||||
|
|
||||||
// fees earned by author
|
let gas_used = t.gas - gas_left;
|
||||||
let fees = t.gas - refund;
|
let refund_value = gas_left * t.gas_price;
|
||||||
let fees_value = fees * t.gas_price;
|
let fees_value = gas_used * t.gas_price;
|
||||||
let author = &self.info.author;
|
|
||||||
self.state.add_balance(author, &fees_value);
|
trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
|
||||||
trace!("Compensating author: fees: {}, fees_value: {}, author: {}", fees, fees_value, author);
|
t.gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
|
||||||
|
|
||||||
|
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, t.sender().unwrap());
|
||||||
|
self.state.add_balance(&t.sender().unwrap(), &refund_value);
|
||||||
|
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
||||||
|
self.state.add_balance(&self.info.author, &fees_value);
|
||||||
|
|
||||||
// perform suicides
|
// perform suicides
|
||||||
for address in substate.suicides.iter() {
|
for address in substate.suicides.iter() {
|
||||||
@ -261,8 +270,6 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.kill_account(address);
|
self.state.kill_account(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
let gas_used = t.gas - gas_left;
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
||||||
// TODO [ToDr] BadJumpDestination @debris - how to handle that?
|
// TODO [ToDr] BadJumpDestination @debris - how to handle that?
|
||||||
@ -280,16 +287,16 @@ impl<'a> Executive<'a> {
|
|||||||
contracts_created: vec![]
|
contracts_created: vec![]
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Ok(_) => {
|
_ => {
|
||||||
Ok(Executed {
|
Ok(Executed {
|
||||||
gas: t.gas,
|
gas: t.gas,
|
||||||
gas_used: gas_used,
|
gas_used: gas_used,
|
||||||
refunded: refund,
|
refunded: refunded,
|
||||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||||
logs: substate.logs,
|
logs: substate.logs,
|
||||||
contracts_created: substate.contracts_created
|
contracts_created: substate.contracts_created,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,15 +60,19 @@ impl<'a> Externalities<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Ext for Externalities<'a> {
|
impl<'a> Ext for Externalities<'a> {
|
||||||
fn sload(&self, key: &H256) -> H256 {
|
fn storage_at(&self, key: &H256) -> H256 {
|
||||||
|
trace!("ext: storage_at({}, {}) == {}\n", self.params.address, key, U256::from(self.state.storage_at(&self.params.address, key).as_slice()));
|
||||||
self.state.storage_at(&self.params.address, key)
|
self.state.storage_at(&self.params.address, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sstore(&mut self, key: H256, value: H256) {
|
fn set_storage_at(&mut self, key: H256, value: H256) {
|
||||||
|
let old = self.state.storage_at(&self.params.address, &key);
|
||||||
// if SSTORE nonzero -> zero, increment refund count
|
// if SSTORE nonzero -> zero, increment refund count
|
||||||
if value == H256::new() && self.state.storage_at(&self.params.address, &key) != H256::new() {
|
if value.is_zero() && !old.is_zero() {
|
||||||
|
trace!("ext: additional refund. {} -> {}\n", self.substate.refunds_count, self.substate.refunds_count + x!(1));
|
||||||
self.substate.refunds_count = self.substate.refunds_count + U256::one();
|
self.substate.refunds_count = self.substate.refunds_count + U256::one();
|
||||||
}
|
}
|
||||||
|
trace!("ext: set_storage_at({}, {}): {} -> {}\n", self.params.address, key, U256::from(old.as_slice()), U256::from(value.as_slice()));
|
||||||
self.state.set_storage(&self.params.address, key, value)
|
self.state.set_storage(&self.params.address, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +84,14 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
match *number < U256::from(self.info.number) && number.low_u64() >= cmp::max(256, self.info.number) - 256 {
|
match *number < U256::from(self.info.number) && number.low_u64() >= cmp::max(256, self.info.number) - 256 {
|
||||||
true => {
|
true => {
|
||||||
let index = self.info.number - number.low_u64() - 1;
|
let index = self.info.number - number.low_u64() - 1;
|
||||||
self.info.last_hashes[index as usize].clone()
|
let r = self.info.last_hashes[index as usize].clone();
|
||||||
|
trace!("ext: blockhash({}) -> {} self.info.number={}\n", number, r, self.info.number);
|
||||||
|
r
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
trace!("ext: blockhash({}) -> null self.info.number={}\n", number, self.info.number);
|
||||||
|
H256::from(&U256::zero())
|
||||||
},
|
},
|
||||||
false => H256::from(&U256::zero()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +133,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
output: &mut [u8]) -> Result<(U256, bool), evm::Error> {
|
output: &mut [u8]) -> Result<(U256, bool), evm::Error> {
|
||||||
|
|
||||||
let mut gas_cost = *call_gas;
|
let mut gas_cost = *call_gas;
|
||||||
let mut call_gas = *call_gas;
|
let mut call_gas = *call_gas;
|
||||||
|
|
||||||
@ -138,7 +148,10 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
call_gas = call_gas + U256::from(self.schedule.call_stipend);
|
call_gas = call_gas + U256::from(self.schedule.call_stipend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Externalities::call(gas={}, call_gas={}, recv={}, value={}, data={}, code={})\n", gas, call_gas, receive_address, value, data.pretty(), code_address);
|
||||||
|
|
||||||
if gas_cost > *gas {
|
if gas_cost > *gas {
|
||||||
|
debug!("Externalities::call: OutOfGas gas_cost={}, gas={}", gas_cost, gas);
|
||||||
return Err(evm::Error::OutOfGas);
|
return Err(evm::Error::OutOfGas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +159,8 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
// if balance is insufficient or we are too deep, return
|
// if balance is insufficient or we are too deep, return
|
||||||
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
|
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
|
||||||
return Ok((gas + call_gas, true));
|
debug!("Externalities::call: OutOfCash bal({})={}, value={}", self.params.address, self.state.balance(&self.params.address), value);
|
||||||
|
return Ok((gas + call_gas, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -161,8 +175,13 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
data: Some(data.to_vec()),
|
data: Some(data.to_vec()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
|
||||||
match ex.call(¶ms, self.substate, BytesRef::Fixed(output)) {
|
trace!("Externalities::call: BEFORE: bal({})={}, bal({})={}\n", params.sender, self.state.balance(¶ms.sender), params.address, self.state.balance(¶ms.address));
|
||||||
|
trace!("Externalities::call: CALLING: params={:?}\n", params);
|
||||||
|
let r = Executive::from_parent(self.state, self.info, self.engine, self.depth).call(¶ms, self.substate, BytesRef::Fixed(output));
|
||||||
|
trace!("Externalities::call: AFTER: bal({})={}, bal({})={}\n", params.sender, self.state.balance(¶ms.sender), params.address, self.state.balance(¶ms.address));
|
||||||
|
|
||||||
|
match r {
|
||||||
Ok(gas_left) => Ok((gas + gas_left, true)),
|
Ok(gas_left) => Ok((gas + gas_left, true)),
|
||||||
_ => Ok((gas, false))
|
_ => Ok((gas, false))
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,9 @@ impl Header {
|
|||||||
|
|
||||||
pub fn state_root(&self) -> &H256 { &self.state_root }
|
pub fn state_root(&self) -> &H256 { &self.state_root }
|
||||||
pub fn receipts_root(&self) -> &H256 { &self.receipts_root }
|
pub fn receipts_root(&self) -> &H256 { &self.receipts_root }
|
||||||
|
pub fn gas_limit(&self) -> &U256 { &self.gas_limit }
|
||||||
|
|
||||||
|
pub fn difficulty(&self) -> &U256 { &self.difficulty }
|
||||||
pub fn seal(&self) -> &Vec<Bytes> { &self.seal }
|
pub fn seal(&self) -> &Vec<Bytes> { &self.seal }
|
||||||
|
|
||||||
// TODO: seal_at, set_seal_at &c.
|
// TODO: seal_at, set_seal_at &c.
|
||||||
@ -79,6 +81,10 @@ impl Header {
|
|||||||
|
|
||||||
pub fn set_extra_data(&mut self, a: Bytes) { if a != self.extra_data { self.extra_data = a; self.note_dirty(); } }
|
pub fn set_extra_data(&mut self, a: Bytes) { if a != self.extra_data { self.extra_data = a; self.note_dirty(); } }
|
||||||
|
|
||||||
|
pub fn set_gas_used(&mut self, a: U256) { self.gas_used = a; self.note_dirty(); }
|
||||||
|
pub fn set_gas_limit(&mut self, a: U256) { self.gas_limit = a; self.note_dirty(); }
|
||||||
|
|
||||||
|
pub fn set_difficulty(&mut self, a: U256) { self.difficulty = a; self.note_dirty(); }
|
||||||
pub fn set_seal(&mut self, a: Vec<Bytes>) { self.seal = a; self.note_dirty(); }
|
pub fn set_seal(&mut self, a: Vec<Bytes>) { self.seal = a; self.note_dirty(); }
|
||||||
|
|
||||||
/// Get the hash of this header (sha3 of the RLP).
|
/// Get the hash of this header (sha3 of the RLP).
|
||||||
|
19
src/state.rs
19
src/state.rs
@ -3,6 +3,7 @@ use engine::Engine;
|
|||||||
use executive::Executive;
|
use executive::Executive;
|
||||||
use pod_account::*;
|
use pod_account::*;
|
||||||
use pod_state::*;
|
use pod_state::*;
|
||||||
|
use state_diff::*;
|
||||||
|
|
||||||
pub type ApplyResult = Result<Receipt, Error>;
|
pub type ApplyResult = Result<Receipt, Error>;
|
||||||
|
|
||||||
@ -106,12 +107,16 @@ impl State {
|
|||||||
|
|
||||||
/// Add `incr` to the balance of account `a`.
|
/// Add `incr` to the balance of account `a`.
|
||||||
pub fn add_balance(&mut self, a: &Address, incr: &U256) {
|
pub fn add_balance(&mut self, a: &Address, incr: &U256) {
|
||||||
self.require(a, false).add_balance(incr)
|
let old = self.balance(a);
|
||||||
|
self.require(a, false).add_balance(incr);
|
||||||
|
trace!("state: add_balance({}, {}): {} -> {}\n", a, incr, old, self.balance(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtract `decr` from the balance of account `a`.
|
/// Subtract `decr` from the balance of account `a`.
|
||||||
pub fn sub_balance(&mut self, a: &Address, decr: &U256) {
|
pub fn sub_balance(&mut self, a: &Address, decr: &U256) {
|
||||||
self.require(a, false).sub_balance(decr)
|
let old = self.balance(a);
|
||||||
|
self.require(a, false).sub_balance(decr);
|
||||||
|
trace!("state: sub_balance({}, {}): {} -> {}\n", a, decr, old, self.balance(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
|
/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
|
||||||
@ -139,8 +144,13 @@ impl State {
|
|||||||
/// Execute a given transaction.
|
/// Execute a given transaction.
|
||||||
/// This will change the state accordingly.
|
/// This will change the state accordingly.
|
||||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult {
|
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult {
|
||||||
|
|
||||||
|
let old = self.to_pod();
|
||||||
|
|
||||||
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
||||||
//println!("Executed: {:?}", e);
|
//println!("Executed: {:?}", e);
|
||||||
|
|
||||||
|
debug!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
||||||
self.commit();
|
self.commit();
|
||||||
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
||||||
debug!("Transaction receipt: {:?}", receipt);
|
debug!("Transaction receipt: {:?}", receipt);
|
||||||
@ -219,8 +229,9 @@ impl State {
|
|||||||
/// Pull account `a` in our cache from the trie DB and return it.
|
/// Pull account `a` in our cache from the trie DB and return it.
|
||||||
/// `require_code` requires that the code be cached, too.
|
/// `require_code` requires that the code be cached, too.
|
||||||
fn get(&self, a: &Address, require_code: bool) -> Ref<Option<Account>> {
|
fn get(&self, a: &Address, require_code: bool) -> Ref<Option<Account>> {
|
||||||
self.cache.borrow_mut().entry(a.clone()).or_insert_with(||
|
self.cache.borrow_mut().entry(a.clone()).or_insert_with(|| {
|
||||||
SecTrieDB::new(&self.db, &self.root).get(&a).map(|rlp| Account::from_rlp(rlp)));
|
SecTrieDB::new(&self.db, &self.root).get(&a).map(|rlp| Account::from_rlp(rlp))
|
||||||
|
});
|
||||||
if require_code {
|
if require_code {
|
||||||
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
|
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
|
||||||
account.cache_code(&self.db);
|
account.cache_code(&self.db);
|
||||||
|
@ -2,6 +2,7 @@ use common::*;
|
|||||||
|
|
||||||
/// State changes which should be applied in finalize,
|
/// State changes which should be applied in finalize,
|
||||||
/// after transaction is fully executed.
|
/// after transaction is fully executed.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Substate {
|
pub struct Substate {
|
||||||
/// Any accounts that have suicided.
|
/// Any accounts that have suicided.
|
||||||
pub suicides: HashSet<Address>,
|
pub suicides: HashSet<Address>,
|
||||||
|
@ -60,12 +60,12 @@ impl<'a> TestExt<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Ext for TestExt<'a> {
|
impl<'a> Ext for TestExt<'a> {
|
||||||
fn sload(&self, key: &H256) -> H256 {
|
fn storage_at(&self, key: &H256) -> H256 {
|
||||||
self.ext.sload(key)
|
self.ext.storage_at(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sstore(&mut self, key: H256, value: H256) {
|
fn set_storage_at(&mut self, key: H256, value: H256) {
|
||||||
self.ext.sstore(key, value)
|
self.ext.set_storage_at(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> U256 {
|
fn balance(&self, address: &Address) -> U256 {
|
||||||
|
@ -115,18 +115,18 @@ pub fn verify_block_family<BC>(header: &Header, bytes: &[u8], engine: &Engine, b
|
|||||||
|
|
||||||
/// Phase 4 verification. Check block information against transaction enactment results,
|
/// Phase 4 verification. Check block information against transaction enactment results,
|
||||||
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
|
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
|
||||||
if expected.state_root != got.state_root {
|
if expected.gas_used != got.gas_used {
|
||||||
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root.clone(), found: got.state_root.clone() })))
|
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used, found: got.gas_used })))
|
||||||
}
|
}
|
||||||
if expected.receipts_root != got.receipts_root {
|
if expected.receipts_root != got.receipts_root {
|
||||||
return Err(From::from(BlockError::InvalidReceiptsStateRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() })))
|
return Err(From::from(BlockError::InvalidReceiptsStateRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() })))
|
||||||
}
|
}
|
||||||
|
if expected.state_root != got.state_root {
|
||||||
|
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root.clone(), found: got.state_root.clone() })))
|
||||||
|
}
|
||||||
if expected.log_bloom != got.log_bloom {
|
if expected.log_bloom != got.log_bloom {
|
||||||
return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom.clone(), found: got.log_bloom.clone() })))
|
return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom.clone(), found: got.log_bloom.clone() })))
|
||||||
}
|
}
|
||||||
if expected.gas_used != got.gas_used {
|
|
||||||
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used, found: got.gas_used })))
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user