Wasm runtime update (#7356)
* call augmented, wasm-tests updated * fix all call tests * fix comments
This commit is contained in:
parent
d80dd81d77
commit
82340c058a
@ -1 +1 @@
|
||||
Subproject commit d6185ea16eaba7ff685c069c2064819f9549c4d7
|
||||
Subproject commit d9d6133c1bc5dca4c74c9eb758a39546a0d46b45
|
@ -69,17 +69,17 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
||||
),
|
||||
Static(
|
||||
"_ccall",
|
||||
&[I32; 6],
|
||||
&[I64, I32, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_dcall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_scall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
|
@ -111,6 +111,7 @@ impl vm::Vm for WasmInterpreter {
|
||||
address: params.address,
|
||||
sender: params.sender,
|
||||
origin: params.origin,
|
||||
code_address: params.code_address,
|
||||
value: params.value.value(),
|
||||
},
|
||||
&self.program,
|
||||
|
@ -104,6 +104,7 @@ pub struct RuntimeContext {
|
||||
pub address: Address,
|
||||
pub sender: Address,
|
||||
pub origin: Address,
|
||||
pub code_address: Address,
|
||||
pub value: U256,
|
||||
}
|
||||
|
||||
@ -305,6 +306,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// method signature:
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// val_ptr: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
@ -323,6 +325,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// signature (same as static call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
@ -330,7 +333,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
// result_len: u32,
|
||||
// ) -> i32
|
||||
|
||||
self.do_call(false, CallType::CallCode, context)
|
||||
self.do_call(false, CallType::DelegateCall, context)
|
||||
}
|
||||
|
||||
fn do_call(
|
||||
@ -363,6 +366,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
let address = self.pop_address(&mut context)?;
|
||||
trace!(target: "wasm", " address: {:?}", address);
|
||||
|
||||
let gas = context.value_stack.pop_as::<i64>()? as u64;
|
||||
trace!(target: "wasm", " gas: {:?}", gas);
|
||||
|
||||
if let Some(ref val) = val {
|
||||
let address_balance = self.ext.balance(&self.context.address)
|
||||
.map_err(|_| UserTrap::BalanceQueryError)?;
|
||||
@ -377,16 +383,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
let mut result = Vec::with_capacity(result_alloc_len as usize);
|
||||
result.resize(result_alloc_len as usize, 0);
|
||||
let gas = self.gas_left()
|
||||
.map_err(|_| UserTrap::InvalidGasState)?
|
||||
.into();
|
||||
|
||||
// todo: optimize to use memory views once it's in
|
||||
let payload = self.memory.get(input_ptr, input_len as usize)?;
|
||||
|
||||
self.charge(|_| gas.into())?;
|
||||
|
||||
let call_result = self.ext.call(
|
||||
&gas,
|
||||
&self.context.sender,
|
||||
&self.context.address,
|
||||
&gas.into(),
|
||||
match call_type { CallType::DelegateCall => &self.context.sender, _ => &self.context.address },
|
||||
match call_type { CallType::Call | CallType::StaticCall => &address, _ => &self.context.address },
|
||||
val,
|
||||
&payload,
|
||||
&address,
|
||||
@ -396,12 +402,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
match call_result {
|
||||
vm::MessageCallResult::Success(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some(0i32.into()))
|
||||
},
|
||||
vm::MessageCallResult::Reverted(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some((-1i32).into()))
|
||||
},
|
||||
@ -416,6 +426,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
{
|
||||
// signature (same as code call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
|
@ -60,7 +60,7 @@ fn empty() {
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(99_982));
|
||||
assert_eq!(gas_left, U256::from(96_678));
|
||||
}
|
||||
|
||||
// This test checks if the contract deserializes payload header properly.
|
||||
@ -112,7 +112,7 @@ fn logger() {
|
||||
U256::from(1_000_000_000),
|
||||
"Logger sets 0x04 key to the trasferred value"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(19_147));
|
||||
assert_eq!(gas_left, U256::from(15_860));
|
||||
}
|
||||
|
||||
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
|
||||
@ -147,7 +147,7 @@ fn identity() {
|
||||
sender,
|
||||
"Idenity test contract does not return the sender passed"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(99_844));
|
||||
assert_eq!(gas_left, U256::from(96_540));
|
||||
}
|
||||
|
||||
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
|
||||
@ -180,7 +180,7 @@ fn dispersion() {
|
||||
result,
|
||||
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_393));
|
||||
assert_eq!(gas_left, U256::from(96_116));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -208,7 +208,7 @@ fn suicide_not() {
|
||||
result,
|
||||
vec![0u8]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_725));
|
||||
assert_eq!(gas_left, U256::from(96_461));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -240,7 +240,7 @@ fn suicide() {
|
||||
};
|
||||
|
||||
assert!(ext.suicides.contains(&refund));
|
||||
assert_eq!(gas_left, U256::from(96_687));
|
||||
assert_eq!(gas_left, U256::from(96_429));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -270,7 +270,7 @@ fn create() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
gas: U256::from(65_899),
|
||||
gas: U256::from(62_545),
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
value: Some(1_000_000_000.into()),
|
||||
@ -278,9 +278,52 @@ fn create() {
|
||||
code_address: None,
|
||||
}
|
||||
));
|
||||
assert_eq!(gas_left, U256::from(65_892));
|
||||
assert_eq!(gas_left, U256::from(62_538));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_msg() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
params.address = receiver.clone();
|
||||
params.code_address = contract_address.clone();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("call.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas_left) => gas_left,
|
||||
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(33_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
value: Some(1000000000.into()),
|
||||
data: vec![129u8, 123, 113, 107, 101, 97],
|
||||
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
}
|
||||
));
|
||||
|
||||
assert_eq!(gas_left, U256::from(95_699));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_code() {
|
||||
@ -312,7 +355,7 @@ fn call_code() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
value: None,
|
||||
@ -324,7 +367,7 @@ fn call_code() {
|
||||
// siphash result
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 4198595614);
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -333,6 +376,7 @@ fn call_static() {
|
||||
|
||||
let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
@ -341,6 +385,7 @@ fn call_static() {
|
||||
params.code = Some(Arc::new(load_sample!("call_static.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
params.value = ActionValue::transfer(1_000_000_000);
|
||||
params.code_address = contract_address.clone();
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
@ -357,9 +402,9 @@ fn call_static() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
value: None,
|
||||
data: vec![1u8, 2, 3, 5, 7, 11],
|
||||
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
@ -370,7 +415,7 @@ fn call_static() {
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 317632590);
|
||||
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
// Realloc test
|
||||
@ -393,7 +438,7 @@ fn realloc() {
|
||||
}
|
||||
};
|
||||
assert_eq!(result, vec![0u8; 2]);
|
||||
assert_eq!(gas_left, U256::from(96_723));
|
||||
assert_eq!(gas_left, U256::from(96_445));
|
||||
}
|
||||
|
||||
// Tests that contract's ability to read from a storage
|
||||
@ -419,7 +464,7 @@ fn storage_read() {
|
||||
};
|
||||
|
||||
assert_eq!(Address::from(&result[12..32]), address);
|
||||
assert_eq!(gas_left, U256::from(99_767));
|
||||
assert_eq!(gas_left, U256::from(96_463));
|
||||
}
|
||||
|
||||
// Tests keccak calculation
|
||||
@ -445,7 +490,7 @@ fn keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
// memcpy test.
|
||||
@ -477,7 +522,7 @@ fn memcpy() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memmove test.
|
||||
@ -509,7 +554,7 @@ fn memmove() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memset test
|
||||
@ -534,7 +579,7 @@ fn memset() {
|
||||
};
|
||||
|
||||
assert_eq!(result, vec![228u8; 8192]);
|
||||
assert_eq!(gas_left, U256::from(72_196));
|
||||
assert_eq!(gas_left, U256::from(71_921));
|
||||
}
|
||||
|
||||
macro_rules! reqrep_test {
|
||||
@ -591,7 +636,7 @@ fn math_add() {
|
||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_524));
|
||||
assert_eq!(gas_left, U256::from(95_384));
|
||||
}
|
||||
|
||||
// multiplication
|
||||
@ -613,7 +658,7 @@ fn math_mul() {
|
||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(94_674));
|
||||
assert_eq!(gas_left, U256::from(94_374));
|
||||
}
|
||||
|
||||
// subtraction
|
||||
@ -635,7 +680,7 @@ fn math_sub() {
|
||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_516));
|
||||
assert_eq!(gas_left, U256::from(95_372));
|
||||
}
|
||||
|
||||
// subtraction with overflow
|
||||
@ -677,7 +722,7 @@ fn math_div() {
|
||||
U256::from_dec_str("1125000").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(88_514));
|
||||
assert_eq!(gas_left, U256::from(88_356));
|
||||
}
|
||||
|
||||
// This test checks the ability of wasm contract to invoke
|
||||
@ -765,7 +810,7 @@ fn externs() {
|
||||
"Gas limit requested and returned does not match"
|
||||
);
|
||||
|
||||
assert_eq!(gas_left, U256::from(94_858));
|
||||
assert_eq!(gas_left, U256::from(95_321));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -791,7 +836,7 @@ fn embedded_keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
/// This test checks the correctness of log extern
|
||||
@ -826,5 +871,5 @@ fn events() {
|
||||
assert_eq!(&log_entry.data, b"gnihtemos");
|
||||
|
||||
assert_eq!(&result, b"gnihtemos");
|
||||
assert_eq!(gas_left, U256::from(79_637));
|
||||
assert_eq!(gas_left, U256::from(79_206));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user