commit
241db922f1
@ -14,6 +14,8 @@ impl Ethash {
|
|||||||
pub fn new_boxed(spec: Spec) -> Box<Engine> {
|
pub fn new_boxed(spec: Spec) -> Box<Engine> {
|
||||||
Box::new(Ethash{spec: spec})
|
Box::new(Ethash{spec: spec})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn u256_param(&self, name: &str) -> U256 { self.spec().engine_params.get(name).map(|a| decode(&a)).unwrap_or(U256::from(0u64)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine for Ethash {
|
impl Engine for Ethash {
|
||||||
@ -29,6 +31,20 @@ impl Engine for Ethash {
|
|||||||
fn spec(&self) -> &Spec { &self.spec }
|
fn spec(&self) -> &Spec { &self.spec }
|
||||||
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }
|
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }
|
||||||
|
|
||||||
|
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
|
||||||
|
header.difficulty = self.calculate_difficuty(header, parent);
|
||||||
|
header.gas_limit = {
|
||||||
|
let gas_floor_target: U256 = x!(3141562);
|
||||||
|
let gas_limit = parent.gas_limit;
|
||||||
|
let bound_divisor = self.u256_param("gasLimitBoundDivisor");
|
||||||
|
if gas_limit < gas_floor_target {
|
||||||
|
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - x!(1))
|
||||||
|
} else {
|
||||||
|
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + x!(1) + (header.gas_used * x!(6) / x!(5)) / bound_divisor)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
/// Apply the block reward on finalisation of the block.
|
||||||
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
||||||
fn on_close_block(&self, block: &mut Block) {
|
fn on_close_block(&self, block: &mut Block) {
|
||||||
@ -45,7 +61,6 @@ impl Engine for Ethash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||||
let min_difficulty = decode(self.spec().engine_params.get("minimumDifficulty").unwrap());
|
let min_difficulty = decode(self.spec().engine_params.get("minimumDifficulty").unwrap());
|
||||||
if header.difficulty < min_difficulty {
|
if header.difficulty < min_difficulty {
|
||||||
|
@ -266,7 +266,7 @@ impl<'a> Executive<'a> {
|
|||||||
let gas_left = match &result { &Ok(x) => x, _ => x!(0) };
|
let gas_left = 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 refund = cmp::min(sstore_refunds + suicide_refunds, (t.gas - gas_left) / U256::from(2)) + gas_left;
|
||||||
let refund_value = refund * t.gas_price;
|
let refund_value = refund * t.gas_price;
|
||||||
trace!("Refunding sender: gas_left: {}, refund: {}, refund_value: {}, sender: {}", gas_left, refund, refund_value, t.sender().unwrap());
|
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);
|
self.state.add_balance(&t.sender().unwrap(), &refund_value);
|
||||||
|
|
||||||
// fees earned by author
|
// fees earned by author
|
||||||
|
10
src/state.rs
10
src/state.rs
@ -142,7 +142,7 @@ impl State {
|
|||||||
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);
|
||||||
self.commit();
|
self.commit();
|
||||||
Ok(Receipt::new(self.root().clone(), e.gas_used, e.logs))
|
Ok(Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn revert(&mut self, backup: State) {
|
pub fn revert(&mut self, backup: State) {
|
||||||
@ -156,7 +156,7 @@ impl State {
|
|||||||
|
|
||||||
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
|
/// 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.
|
/// `accounts` is mutable because we may need to commit the code or storage and record that.
|
||||||
pub fn commit_into(db: &mut HashDB, mut root: H256, accounts: &mut HashMap<Address, Option<Account>>) -> H256 {
|
pub fn commit_into(db: &mut HashDB, root: &mut H256, accounts: &mut HashMap<Address, Option<Account>>) {
|
||||||
// first, commit the sub trees.
|
// first, commit the sub trees.
|
||||||
// TODO: is this necessary or can we dispense with the `ref mut a` for just `a`?
|
// TODO: is this necessary or can we dispense with the `ref mut a` for just `a`?
|
||||||
for (_, ref mut a) in accounts.iter_mut() {
|
for (_, ref mut a) in accounts.iter_mut() {
|
||||||
@ -170,7 +170,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut trie = SecTrieDBMut::from_existing(db, &mut root);
|
let mut trie = SecTrieDBMut::from_existing(db, root);
|
||||||
for (address, ref a) in accounts.iter() {
|
for (address, ref a) in accounts.iter() {
|
||||||
match a {
|
match a {
|
||||||
&&Some(ref account) => trie.insert(address, &account.rlp()),
|
&&Some(ref account) => trie.insert(address, &account.rlp()),
|
||||||
@ -178,13 +178,11 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commits our cached account changes into the trie.
|
/// Commits our cached account changes into the trie.
|
||||||
pub fn commit(&mut self) {
|
pub fn commit(&mut self) {
|
||||||
let r = self.root.clone(); // would prefer not to do this, really.
|
Self::commit_into(&mut self.db, &mut self.root, self.cache.borrow_mut().deref_mut());
|
||||||
self.root = Self::commit_into(&mut self.db, r, self.cache.borrow_mut().deref_mut());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Populate the state from `accounts`.
|
/// Populate the state from `accounts`.
|
||||||
|
@ -4,16 +4,30 @@ use pod_state::*;
|
|||||||
use state_diff::*;
|
use state_diff::*;
|
||||||
use ethereum;
|
use ethereum;
|
||||||
|
|
||||||
|
fn flush(s: String) {
|
||||||
|
::std::io::stdout().write(s.as_bytes()).unwrap();
|
||||||
|
::std::io::stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||||
let mut failed = Vec::new();
|
let mut failed = Vec::new();
|
||||||
|
|
||||||
let engine = ethereum::new_frontier_test().to_engine().unwrap();
|
let engine = ethereum::new_frontier_test().to_engine().unwrap();
|
||||||
|
|
||||||
|
flush(format!("\n"));
|
||||||
|
|
||||||
for (name, test) in json.as_object().unwrap() {
|
for (name, test) in json.as_object().unwrap() {
|
||||||
println!("name: {:?}", name);
|
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
let mut fail_unless = |cond: bool| if !cond && !fail { failed.push(name.to_string()); fail = true; true } else {false};
|
{
|
||||||
|
let mut fail_unless = |cond: bool| if !cond && !fail {
|
||||||
|
failed.push(name.to_string());
|
||||||
|
flush(format!("FAIL\n"));
|
||||||
|
fail = true;
|
||||||
|
true
|
||||||
|
} else {false};
|
||||||
|
|
||||||
|
flush(format!(" - {}...", name));
|
||||||
|
|
||||||
let t = Transaction::from_json(&test["transaction"]);
|
let t = Transaction::from_json(&test["transaction"]);
|
||||||
let env = EnvInfo::from_json(&test["env"]);
|
let env = EnvInfo::from_json(&test["env"]);
|
||||||
@ -35,22 +49,28 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
|
|
||||||
let mut s = State::new_temp();
|
let mut s = State::new_temp();
|
||||||
s.populate_from(pre);
|
s.populate_from(pre);
|
||||||
let r = s.apply(&env, engine.deref(), &t).unwrap();
|
s.commit();
|
||||||
|
let res = s.apply(&env, engine.deref(), &t);
|
||||||
|
|
||||||
if fail_unless(&r.state_root == &post_state_root) {
|
if fail_unless(s.root() == &post_state_root) {
|
||||||
println!("!!! {}: State mismatch (got: {}, expect: {}):", name, r.state_root, post_state_root);
|
println!("!!! {}: State mismatch (got: {}, expect: {}):", name, s.root(), post_state_root);
|
||||||
let our_post = s.to_pod();
|
let our_post = s.to_pod();
|
||||||
println!("Got:\n{}", our_post);
|
println!("Got:\n{}", our_post);
|
||||||
println!("Expect:\n{}", post);
|
println!("Expect:\n{}", post);
|
||||||
println!("Diff ---expect -> +++got:\n{}", StateDiff::diff_pod(&post, &our_post));
|
println!("Diff ---expect -> +++got:\n{}", StateDiff::diff_pod(&post, &our_post));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(r) = res {
|
||||||
if fail_unless(logs == r.logs) {
|
if fail_unless(logs == r.logs) {
|
||||||
println!("!!! {}: Logs mismatch:", name);
|
println!("!!! {}: Logs mismatch:", name);
|
||||||
println!("Got:\n{:?}", r.logs);
|
println!("Got:\n{:?}", r.logs);
|
||||||
println!("Expect:\n{:?}", logs);
|
println!("Expect:\n{:?}", logs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !fail {
|
||||||
|
flush(format!("ok\n"));
|
||||||
|
}
|
||||||
// TODO: Add extra APIs for output
|
// TODO: Add extra APIs for output
|
||||||
//if fail_unless(out == r.)
|
//if fail_unless(out == r.)
|
||||||
}
|
}
|
||||||
@ -58,8 +78,22 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
failed
|
failed
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_test!{StateTests_stExample, "StateTests/stExample"}
|
|
||||||
declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"}
|
declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"}
|
||||||
declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}
|
|
||||||
declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"}
|
declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"}
|
||||||
declare_test_ignore!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"}
|
declare_test_ignore!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"} //<< Out of stack
|
||||||
|
declare_test!{StateTests_stDelegatecallTest, "StateTests/stDelegatecallTest"} //<< FAIL - gas too high
|
||||||
|
declare_test!{StateTests_stExample, "StateTests/stExample"}
|
||||||
|
declare_test!{StateTests_stInitCodeTest, "StateTests/stInitCodeTest"}
|
||||||
|
declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}
|
||||||
|
declare_test!{StateTests_stMemoryStressTest, "StateTests/stMemoryStressTest"}
|
||||||
|
declare_test!{StateTests_stMemoryTest, "StateTests/stMemoryTest"}
|
||||||
|
declare_test!{StateTests_stPreCompiledContracts, "StateTests/stPreCompiledContracts"}
|
||||||
|
declare_test_ignore!{StateTests_stQuadraticComplexityTest, "StateTests/stQuadraticComplexityTest"} //<< Too long
|
||||||
|
declare_test_ignore!{StateTests_stRecursiveCreate, "StateTests/stRecursiveCreate"} //<< Out of stack
|
||||||
|
declare_test!{StateTests_stRefundTest, "StateTests/stRefundTest"}
|
||||||
|
declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"}
|
||||||
|
declare_test_ignore!{StateTests_stSpecialTest, "StateTests/stSpecialTest"} //<< Signal 11
|
||||||
|
declare_test_ignore!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"} //<< Signal 11
|
||||||
|
declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"}
|
||||||
|
declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"}
|
||||||
|
declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"}
|
||||||
|
Loading…
Reference in New Issue
Block a user