diff --git a/rust-evmjit/src/lib.rs b/rust-evmjit/src/lib.rs index 670509d87..a4381619b 100644 --- a/rust-evmjit/src/lib.rs +++ b/rust-evmjit/src/lib.rs @@ -127,6 +127,12 @@ impl ContextHandle { unsafe { std::slice::from_raw_parts(self.data_handle.call_data, self.data_handle.call_data_size as usize) } } + /// Returns address to which funds should be transfered after suicide. + pub fn suicide_refund_address(&self) -> JitI256 { + // evmjit reuses data_handle address field to store suicide address + self.data_handle.address + } + /// Returns gas left. pub fn gas_left(&self) -> u64 { self.data_handle.gas as u64 diff --git a/src/evm/ext.rs b/src/evm/ext.rs index b878c5819..631d4ed03 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -51,7 +51,8 @@ pub trait Ext { fn ret(&mut self, gas: u64, data: &[u8]) -> Result; /// Should be called when contract commits suicide. - fn suicide(&mut self); + /// Address to which funds should be refunded. + fn suicide(&mut self, refund_address: &Address); /// Returns schedule. fn schedule(&self) -> &Schedule; diff --git a/src/evm/jit.rs b/src/evm/jit.rs index b20b5542f..062eb88d1 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -347,8 +347,7 @@ impl evm::Evm for JitEvm { evmjit::ReturnCode::Stop => Ok(U256::from(context.gas_left())), evmjit::ReturnCode::Return => ext.ret(context.gas_left(), context.output_data()).map(|gas_left| U256::from(gas_left)), evmjit::ReturnCode::Suicide => { - // what if there is a suicide and we run out of gas just after? - ext.suicide(); + ext.suicide(&Address::from_jit(&context.suicide_refund_address())); Ok(U256::from(context.gas_left())) }, evmjit::ReturnCode::OutOfGas => Err(evm::Error::OutOfGas), diff --git a/src/evm/tests.rs b/src/evm/tests.rs index e3f81dd93..f514b089b 100644 --- a/src/evm/tests.rs +++ b/src/evm/tests.rs @@ -72,7 +72,7 @@ impl Ext for FakeExt { unimplemented!(); } - fn suicide(&mut self) { + fn suicide(&mut self, refund_address: &Address) { unimplemented!(); } diff --git a/src/executive.rs b/src/executive.rs index fe5be1e06..4cdaf6233 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -457,8 +457,10 @@ impl<'a> Ext for Externalities<'a> { self.substate.logs.push(LogEntry::new(address, topics, data)); } - fn suicide(&mut self) { + fn suicide(&mut self, refund_address: &Address) { let address = self.params.address.clone(); + let balance = self.balance(&address); + self.state.transfer_balance(&address, refund_address, &balance); self.substate.suicides.insert(address); } diff --git a/src/tests/executive.rs b/src/tests/executive.rs index 5d9aba05e..e76daa29e 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -139,8 +139,8 @@ impl<'a> Ext for TestExt<'a> { self.ext.ret(gas, data) } - fn suicide(&mut self) { - self.ext.suicide() + fn suicide(&mut self, refund_address: &Address) { + self.ext.suicide(refund_address) } fn schedule(&self) -> &Schedule { @@ -227,10 +227,20 @@ fn do_json_test(json_data: &[u8]) -> Vec { match res { Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."), Ok(gas_left) => { - println!("name: {}, gas_left : {:?}, expected: {:?}", name, gas_left, u256_from_json(&test["gas"])); + //println!("name: {}, gas_left : {:?}, expected: {:?}", name, gas_left, u256_from_json(&test["gas"])); fail_unless(!out_of_gas, "expected to run out of gas."); fail_unless(gas_left == u256_from_json(&test["gas"]), "gas_left is incorrect"); fail_unless(output == bytes_from_json(&test["out"]), "output is incorrect"); + + + test.find("post").map(|pre| for (addr, s) in pre.as_object().unwrap() { + let address = address_from_str(addr); + //let balance = u256_from_json(&s["balance"]); + + fail_unless(state.code(&address) == Some(bytes_from_json(&s["code"])), "code is incorrect"); + fail_unless(state.balance(&address) == u256_from_json(&s["balance"]), "balance is incorrect"); + }); + } } } @@ -247,11 +257,11 @@ fn do_json_test(json_data: &[u8]) -> Vec { declare_test!{ExecutiveTests_vmArithmeticTest, "VMTests/vmArithmeticTest"} declare_test!{ExecutiveTests_vmBitwiseLogicOperationTest, "VMTests/vmBitwiseLogicOperationTest"} // this one crashes with some vm internal error. Separately they pass. -//declare_test!{ExecutiveTests_vmBlockInfoTest, "VMTests/vmBlockInfoTest"} +declare_test_ignore!{ExecutiveTests_vmBlockInfoTest, "VMTests/vmBlockInfoTest"} declare_test!{ExecutiveTests_vmEnvironmentalInfoTest, "VMTests/vmEnvironmentalInfoTest"} declare_test!{ExecutiveTests_vmIOandFlowOperationsTest, "VMTests/vmIOandFlowOperationsTest"} // this one take way too long. -//declare_test!{ExecutiveTests_vmInputLimits, "VMTests/vmInputLimits"} +declare_test_ignore!{ExecutiveTests_vmInputLimits, "VMTests/vmInputLimits"} declare_test!{ExecutiveTests_vmLogTest, "VMTests/vmLogTest"} declare_test!{ExecutiveTests_vmPerformanceTest, "VMTests/vmPerformanceTest"} declare_test!{ExecutiveTests_vmPushDupSwapTest, "VMTests/vmPushDupSwapTest"}