executive returns addresses of contracts created during execution
This commit is contained in:
parent
51610480b0
commit
36e250bcc9
@ -21,6 +21,8 @@ struct Substate {
|
|||||||
logs: Vec<LogEntry>,
|
logs: Vec<LogEntry>,
|
||||||
/// Refund counter of SSTORE nonzero->zero.
|
/// Refund counter of SSTORE nonzero->zero.
|
||||||
refunds_count: U256,
|
refunds_count: U256,
|
||||||
|
/// Created contracts.
|
||||||
|
contracts_created: Vec<Address>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Substate {
|
impl Substate {
|
||||||
@ -30,6 +32,7 @@ impl Substate {
|
|||||||
suicides: HashSet::new(),
|
suicides: HashSet::new(),
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
refunds_count: U256::zero(),
|
refunds_count: U256::zero(),
|
||||||
|
contracts_created: vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,6 +58,13 @@ pub struct Executed {
|
|||||||
|
|
||||||
/// Execution ended running out of gas.
|
/// Execution ended running out of gas.
|
||||||
pub out_of_gas: bool,
|
pub out_of_gas: bool,
|
||||||
|
/// Addresses of contracts created during execution of transaction.
|
||||||
|
/// Ordered from earliest creation.
|
||||||
|
///
|
||||||
|
/// eg. sender creates contract A and A in constructor creates contract B
|
||||||
|
///
|
||||||
|
/// B creation ends first, and it will be the first element of the vector.
|
||||||
|
pub contracts_created: Vec<Address>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction execution result.
|
/// Transaction execution result.
|
||||||
@ -217,6 +227,7 @@ impl<'a> Executive<'a> {
|
|||||||
cumulative_gas_used: self.info.gas_used + t.gas,
|
cumulative_gas_used: self.info.gas_used + t.gas,
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
out_of_gas: true,
|
out_of_gas: true,
|
||||||
|
contracts_created: vec![]
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Ok(gas_left) => {
|
Ok(gas_left) => {
|
||||||
@ -250,6 +261,7 @@ impl<'a> Executive<'a> {
|
|||||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||||
logs: substate.logs,
|
logs: substate.logs,
|
||||||
out_of_gas: false,
|
out_of_gas: false,
|
||||||
|
contracts_created: substate.contracts_created
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,6 +417,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self, gas: u64, data: &[u8]) -> Result<u64, evm::Error> {
|
fn ret(&mut self, gas: u64, data: &[u8]) -> Result<u64, evm::Error> {
|
||||||
|
println!("ret");
|
||||||
match &mut self.output {
|
match &mut self.output {
|
||||||
&mut OutputPolicy::Return(ref mut slice) => unsafe {
|
&mut OutputPolicy::Return(ref mut slice) => unsafe {
|
||||||
let len = cmp::min(slice.len(), data.len());
|
let len = cmp::min(slice.len(), data.len());
|
||||||
@ -427,6 +440,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
}
|
}
|
||||||
let address = &self.params.address;
|
let address = &self.params.address;
|
||||||
self.state.init_code(address, code);
|
self.state.init_code(address, code);
|
||||||
|
self.substate.contracts_created.push(address.clone());
|
||||||
Ok(gas - return_cost)
|
Ok(gas - return_cost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,13 +477,15 @@ mod tests {
|
|||||||
use super::Substate;
|
use super::Substate;
|
||||||
|
|
||||||
struct TestEngine {
|
struct TestEngine {
|
||||||
spec: Spec
|
spec: Spec,
|
||||||
|
stack_limit: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestEngine {
|
impl TestEngine {
|
||||||
fn new() -> TestEngine {
|
fn new(stack_limit: usize) -> TestEngine {
|
||||||
TestEngine {
|
TestEngine {
|
||||||
spec: ethereum::new_frontier()
|
spec: ethereum::new_frontier(),
|
||||||
|
stack_limit: stack_limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,7 +495,7 @@ mod tests {
|
|||||||
fn spec(&self) -> &Spec { &self.spec }
|
fn spec(&self) -> &Spec { &self.spec }
|
||||||
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
|
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
|
||||||
let mut schedule = Schedule::new_frontier();
|
let mut schedule = Schedule::new_frontier();
|
||||||
schedule.stack_limit = 0;
|
schedule.stack_limit = self.stack_limit;
|
||||||
schedule
|
schedule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,7 +521,7 @@ mod tests {
|
|||||||
let mut state = State::new_temp();
|
let mut state = State::new_temp();
|
||||||
state.add_balance(&sender, &U256::from(0x100u64));
|
state.add_balance(&sender, &U256::from(0x100u64));
|
||||||
let info = EnvInfo::new();
|
let info = EnvInfo::new();
|
||||||
let engine = TestEngine::new();
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -517,12 +533,16 @@ mod tests {
|
|||||||
assert_eq!(state.storage_at(&address, &H256::new()), H256::from(&U256::from(0xf9u64)));
|
assert_eq!(state.storage_at(&address, &H256::new()), H256::from(&U256::from(0xf9u64)));
|
||||||
assert_eq!(state.balance(&sender), U256::from(0xf9));
|
assert_eq!(state.balance(&sender), U256::from(0xf9));
|
||||||
assert_eq!(state.balance(&address), U256::from(0x7));
|
assert_eq!(state.balance(&address), U256::from(0x7));
|
||||||
|
// 0 cause contract hasn't returned
|
||||||
|
assert_eq!(substate.contracts_created.len(), 0);
|
||||||
|
|
||||||
// TODO: just test state root.
|
// TODO: just test state root.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_contract() {
|
fn test_create_contract() {
|
||||||
|
// code:
|
||||||
|
//
|
||||||
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||||
// 60 00 - push 0
|
// 60 00 - push 0
|
||||||
// 52
|
// 52
|
||||||
@ -532,6 +552,16 @@ mod tests {
|
|||||||
// f0 - create
|
// f0 - create
|
||||||
// 60 00 - push 0
|
// 60 00 - push 0
|
||||||
// 55 sstore
|
// 55 sstore
|
||||||
|
//
|
||||||
|
// other code:
|
||||||
|
//
|
||||||
|
// 60 10 - push 16
|
||||||
|
// 80 - duplicate first stack item
|
||||||
|
// 60 0c - push 12
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 39 - copy current code to memory
|
||||||
|
// 60 00 - push 0
|
||||||
|
// f3 - return
|
||||||
|
|
||||||
let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
|
let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -545,10 +575,11 @@ mod tests {
|
|||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = code.clone();
|
params.code = code.clone();
|
||||||
|
params.value = U256::from(100);
|
||||||
let mut state = State::new_temp();
|
let mut state = State::new_temp();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100));
|
||||||
let info = EnvInfo::new();
|
let info = EnvInfo::new();
|
||||||
let engine = TestEngine::new();
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -557,6 +588,58 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(47_976));
|
assert_eq!(gas_left, U256::from(47_976));
|
||||||
|
assert_eq!(substate.contracts_created.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_contract_without_stack_limit() {
|
||||||
|
// code:
|
||||||
|
//
|
||||||
|
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 52
|
||||||
|
// 60 1d - push 29
|
||||||
|
// 60 03 - push 3
|
||||||
|
// 60 17 - push 17
|
||||||
|
// f0 - create
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 55 sstore
|
||||||
|
//
|
||||||
|
// other code:
|
||||||
|
//
|
||||||
|
// 60 10 - push 16
|
||||||
|
// 80 - duplicate first stack item
|
||||||
|
// 60 0c - push 12
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 39 - copy current code to memory
|
||||||
|
// 60 00 - push 0
|
||||||
|
// f3 - return
|
||||||
|
|
||||||
|
let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
|
||||||
|
|
||||||
|
let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
|
let address = contract_address(&sender, &U256::zero());
|
||||||
|
let next_address = contract_address(&address, &U256::zero());
|
||||||
|
let mut params = ActionParams::new();
|
||||||
|
params.address = address.clone();
|
||||||
|
params.sender = sender.clone();
|
||||||
|
params.origin = sender.clone();
|
||||||
|
params.gas = U256::from(100_000);
|
||||||
|
params.code = code.clone();
|
||||||
|
params.value = U256::from(100);
|
||||||
|
let mut state = State::new_temp();
|
||||||
|
state.add_balance(&sender, &U256::from(100));
|
||||||
|
let info = EnvInfo::new();
|
||||||
|
let engine = TestEngine::new(1024);
|
||||||
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
|
ex.create(¶ms, &mut substate).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(substate.contracts_created.len(), 1);
|
||||||
|
assert_eq!(substate.contracts_created[0], next_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -605,7 +688,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from(100_000));
|
state.add_balance(&sender, &U256::from(100_000));
|
||||||
|
|
||||||
let info = EnvInfo::new();
|
let info = EnvInfo::new();
|
||||||
let engine = TestEngine::new();
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -647,7 +730,7 @@ mod tests {
|
|||||||
let mut state = State::new_temp();
|
let mut state = State::new_temp();
|
||||||
state.init_code(&address, code.clone());
|
state.init_code(&address, code.clone());
|
||||||
let info = EnvInfo::new();
|
let info = EnvInfo::new();
|
||||||
let engine = TestEngine::new();
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
|
Loading…
Reference in New Issue
Block a user