executive output uses BytesRef
This commit is contained in:
parent
5f7a81a468
commit
87eb66183c
@ -160,7 +160,9 @@ impl<'a> Executive<'a> {
|
|||||||
code: self.state.code(address).unwrap_or(vec![]),
|
code: self.state.code(address).unwrap_or(vec![]),
|
||||||
data: t.data.clone(),
|
data: t.data.clone(),
|
||||||
};
|
};
|
||||||
self.call(¶ms, &mut substate, &mut [])
|
// TODO: move output upstream
|
||||||
|
let mut out = vec![];
|
||||||
|
self.call(¶ms, &mut substate, BytesRef::Flexible(&mut out))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,7 +174,7 @@ impl<'a> Executive<'a> {
|
|||||||
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
||||||
/// Modifies the substate and the output.
|
/// Modifies the substate and the output.
|
||||||
/// Returns either gas_left or `evm::Error`.
|
/// Returns either gas_left or `evm::Error`.
|
||||||
pub fn call(&mut self, params: &ActionParams, substate: &mut Substate, output: &mut [u8]) -> evm::Result {
|
pub fn call(&mut self, params: &ActionParams, substate: &mut Substate, mut output: BytesRef) -> evm::Result {
|
||||||
// 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);
|
||||||
|
|
||||||
@ -181,7 +183,7 @@ impl<'a> Executive<'a> {
|
|||||||
let cost = self.engine.cost_of_builtin(¶ms.address, ¶ms.data);
|
let cost = self.engine.cost_of_builtin(¶ms.address, ¶ms.data);
|
||||||
match cost <= params.gas {
|
match cost <= params.gas {
|
||||||
true => {
|
true => {
|
||||||
self.engine.execute_builtin(¶ms.address, ¶ms.data, output);
|
self.engine.execute_builtin(¶ms.address, ¶ms.data, &mut output);
|
||||||
Ok(params.gas - cost)
|
Ok(params.gas - cost)
|
||||||
},
|
},
|
||||||
false => Err(evm::Error::OutOfGas)
|
false => Err(evm::Error::OutOfGas)
|
||||||
@ -270,7 +272,7 @@ impl<'a> Executive<'a> {
|
|||||||
pub enum OutputPolicy<'a> {
|
pub enum OutputPolicy<'a> {
|
||||||
/// Return reference to fixed sized output.
|
/// Return reference to fixed sized output.
|
||||||
/// Used for message calls.
|
/// Used for message calls.
|
||||||
Return(&'a mut [u8]),
|
Return(BytesRef<'a>),
|
||||||
/// Init new contract as soon as `RETURN` is called.
|
/// Init new contract as soon as `RETURN` is called.
|
||||||
InitContract
|
InitContract
|
||||||
}
|
}
|
||||||
@ -405,7 +407,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
||||||
ex.call(¶ms, self.substate, output).map(|gas_left| {
|
ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| {
|
||||||
gas + gas_left.low_u64()
|
gas + gas_left.low_u64()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -416,11 +418,18 @@ 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> {
|
||||||
match &mut self.output {
|
match &mut self.output {
|
||||||
&mut OutputPolicy::Return(ref mut slice) => unsafe {
|
&mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe {
|
||||||
let len = cmp::min(slice.len(), data.len());
|
let len = cmp::min(slice.len(), data.len());
|
||||||
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
||||||
Ok(gas)
|
Ok(gas)
|
||||||
},
|
},
|
||||||
|
&mut OutputPolicy::Return(BytesRef::Flexible(ref mut vec)) => unsafe {
|
||||||
|
vec.clear();
|
||||||
|
vec.reserve(data.len());
|
||||||
|
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
||||||
|
vec.set_len(data.len());
|
||||||
|
Ok(gas)
|
||||||
|
},
|
||||||
&mut OutputPolicy::InitContract => {
|
&mut OutputPolicy::InitContract => {
|
||||||
let return_cost = data.len() as u64 * self.schedule.create_data_gas as u64;
|
let return_cost = data.len() as u64 * self.schedule.create_data_gas as u64;
|
||||||
if return_cost > gas {
|
if return_cost > gas {
|
||||||
@ -743,7 +752,7 @@ mod tests {
|
|||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.call(¶ms, &mut substate, &mut []).unwrap()
|
ex.call(¶ms, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(73_237));
|
assert_eq!(gas_left, U256::from(73_237));
|
||||||
@ -785,7 +794,7 @@ mod tests {
|
|||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.call(¶ms, &mut substate, &mut []).unwrap()
|
ex.call(¶ms, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(59_870));
|
assert_eq!(gas_left, U256::from(59_870));
|
||||||
|
@ -213,10 +213,11 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
}).is_none();
|
}).is_none();
|
||||||
|
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
let mut output = vec![];
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
let res = {
|
let res = {
|
||||||
let ex = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::Return(&mut []));
|
let ex = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
|
||||||
let mut test_ext = TestExt::new(ex);
|
let mut test_ext = TestExt::new(ex);
|
||||||
let evm = Factory::create();
|
let evm = Factory::create();
|
||||||
evm.exec(¶ms, &mut test_ext)
|
evm.exec(¶ms, &mut test_ext)
|
||||||
@ -226,9 +227,10 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
match res {
|
match res {
|
||||||
Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."),
|
Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."),
|
||||||
Ok(gas_left) => {
|
Ok(gas_left) => {
|
||||||
|
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(!out_of_gas, "expected to run out of gas.");
|
||||||
fail_unless(gas_left == u256_from_json(&test["gas"]), "gas_left is incorrect");
|
fail_unless(gas_left == u256_from_json(&test["gas"]), "gas_left is incorrect");
|
||||||
println!("name: {}, gas_left : {:?}, expected: {:?}", name, gas_left, u256_from_json(&test["gas"]));
|
fail_unless(output == bytes_from_json(&test["out"]), "output is incorrect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user