Recursive test (#9042)

This commit is contained in:
Sergey Pepyakin 2018-07-05 10:09:01 +03:00 committed by Nikolay Volf
parent 71bbcd54ff
commit 4839294c86
4 changed files with 70 additions and 30 deletions

6
Cargo.lock generated
View File

@ -3763,12 +3763,12 @@ dependencies = [
"parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0", "vm 0.1.0",
"wasmi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "wasmi" name = "wasmi"
version = "0.2.1" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4191,7 +4191,7 @@ dependencies = [
"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d"
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum wasmi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "076dfb6fe482466f13c191c1ae658692665886776073867881e4ae52bcbc8b4a" "checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3"
"checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2" "checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2"
"checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c" "checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"

@ -1 +1 @@
Subproject commit fb111c82deff8759f54a5038d07cecc77cb5a663 Subproject commit 474110de59a0f632b20615256c913b144c49354c

View File

@ -12,4 +12,4 @@ libc = "0.2"
pwasm-utils = "0.2.2" pwasm-utils = "0.2.2"
vm = { path = "../vm" } vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" } ethcore-logger = { path = "../../logger" }
wasmi = "0.2.1" wasmi = "0.3.0"

View File

@ -86,7 +86,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap() test_finalize(interpreter.exec(params, &mut ext)).unwrap()
}; };
assert_eq!(gas_left, U256::from(98462)); assert_eq!(gas_left, U256::from(96_926));
} }
// This test checks if the contract deserializes payload header properly. // This test checks if the contract deserializes payload header properly.
@ -138,7 +138,7 @@ fn logger() {
U256::from(1_000_000_000), U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value" "Logger sets 0x04 key to the trasferred value"
); );
assert_eq!(gas_left, U256::from(17_578)); assert_eq!(gas_left, U256::from(16_181));
} }
// This test checks if the contract can allocate memory and pass pointer to the result stream properly. // This test checks if the contract can allocate memory and pass pointer to the result stream properly.
@ -173,7 +173,7 @@ fn identity() {
sender, sender,
"Idenity test contract does not return the sender passed" "Idenity test contract does not return the sender passed"
); );
assert_eq!(gas_left, U256::from(98_408)); assert_eq!(gas_left, U256::from(96_883));
} }
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with // Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
@ -207,7 +207,7 @@ fn dispersion() {
result, result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0] vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
); );
assert_eq!(gas_left, U256::from(94_013)); assert_eq!(gas_left, U256::from(92_371));
} }
#[test] #[test]
@ -235,7 +235,7 @@ fn suicide_not() {
result, result,
vec![0u8] vec![0u8]
); );
assert_eq!(gas_left, U256::from(94_984)); assert_eq!(gas_left, U256::from(93_378));
} }
#[test] #[test]
@ -267,7 +267,7 @@ fn suicide() {
}; };
assert!(ext.suicides.contains(&refund)); assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(94_925)); assert_eq!(gas_left, U256::from(93_348));
} }
#[test] #[test]
@ -297,7 +297,7 @@ fn create() {
assert!(ext.calls.contains( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Create, call_type: FakeCallType::Create,
gas: U256::from(60_914), gas: U256::from(59_269),
sender_address: None, sender_address: None,
receive_address: None, receive_address: None,
value: Some(1_000_000_000.into()), value: Some(1_000_000_000.into()),
@ -305,7 +305,7 @@ fn create() {
code_address: None, code_address: None,
} }
)); ));
assert_eq!(gas_left, U256::from(60_900)); assert_eq!(gas_left, U256::from(59_212));
} }
#[test] #[test]
@ -349,7 +349,7 @@ fn call_msg() {
} }
)); ));
assert_eq!(gas_left, U256::from(93_511)); assert_eq!(gas_left, U256::from(91_672));
} }
#[test] #[test]
@ -394,7 +394,7 @@ fn call_code() {
// siphash result // siphash result
let res = LittleEndian::read_u32(&result[..]); let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614); assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(92_381)); assert_eq!(gas_left, U256::from(90_038));
} }
#[test] #[test]
@ -442,7 +442,7 @@ fn call_static() {
let res = LittleEndian::read_u32(&result[..]); let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590); assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(92_381)); assert_eq!(gas_left, U256::from(90_043));
} }
// Realloc test // Realloc test
@ -465,7 +465,7 @@ fn realloc() {
} }
}; };
assert_eq!(result, vec![0u8; 2]); assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(94_372)); assert_eq!(gas_left, U256::from(92_842));
} }
#[test] #[test]
@ -486,8 +486,8 @@ fn alloc() {
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
} }
}; };
assert_eq!(result, vec![5u8; 1024*450]); assert_eq!(result, vec![5u8; 1024*400]);
assert_eq!(gas_left, U256::from(6_506_844)); assert_eq!(gas_left, U256::from(6_893_883));
} }
// Tests that contract's ability to read from a storage // Tests that contract's ability to read from a storage
@ -515,7 +515,7 @@ fn storage_read() {
}; };
assert_eq!(Address::from(&result[12..32]), address); assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(98_298)); assert_eq!(gas_left, U256::from(96_833));
} }
// Tests keccak calculation // Tests keccak calculation
@ -541,7 +541,7 @@ fn keccak() {
}; };
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_240)); assert_eq!(gas_left, U256::from(84_134));
} }
// math_* tests check the ability of wasm contract to perform big integer operations // math_* tests check the ability of wasm contract to perform big integer operations
@ -570,7 +570,7 @@ fn math_add() {
U256::from_dec_str("1888888888888888888888888888887").unwrap(), U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(93_814)); assert_eq!(gas_left, U256::from(92_086));
} }
// multiplication // multiplication
@ -592,7 +592,7 @@ fn math_mul() {
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(93_300)); assert_eq!(gas_left, U256::from(91_414));
} }
// subtraction // subtraction
@ -614,7 +614,7 @@ fn math_sub() {
U256::from_dec_str("111111111111111111111111111111").unwrap(), U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(93_826)); assert_eq!(gas_left, U256::from(92_086));
} }
// subtraction with overflow // subtraction with overflow
@ -656,7 +656,7 @@ fn math_div() {
U256::from_dec_str("1125000").unwrap(), U256::from_dec_str("1125000").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(90_603)); assert_eq!(gas_left, U256::from(87_376));
} }
#[test] #[test]
@ -684,7 +684,7 @@ fn storage_metering() {
}; };
// 0 -> not 0 // 0 -> not 0
assert_eq!(gas_left, U256::from(74_338)); assert_eq!(gas_left, U256::from(72_399));
// #2 // #2
@ -703,7 +703,7 @@ fn storage_metering() {
}; };
// not 0 -> not 0 // not 0 -> not 0
assert_eq!(gas_left, U256::from(89_338)); assert_eq!(gas_left, U256::from(87_399));
} }
// This test checks the ability of wasm contract to invoke // This test checks the ability of wasm contract to invoke
@ -791,7 +791,7 @@ fn externs() {
"Gas limit requested and returned does not match" "Gas limit requested and returned does not match"
); );
assert_eq!(gas_left, U256::from(92_110)); assert_eq!(gas_left, U256::from(90_435));
} }
#[test] #[test]
@ -817,7 +817,7 @@ fn embedded_keccak() {
}; };
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_240)); assert_eq!(gas_left, U256::from(84_134));
} }
/// This test checks the correctness of log extern /// This test checks the correctness of log extern
@ -852,5 +852,45 @@ fn events() {
assert_eq!(&log_entry.data, b"gnihtemos"); assert_eq!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos"); assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(81_292)); assert_eq!(gas_left, U256::from(81_351));
}
#[test]
fn recursive() {
::ethcore_logger::init_log();
let code = load_sample!("recursive.wasm");
let mut params = ActionParams::default();
params.gas = U256::from(100_000_000);
params.code = Some(Arc::new(code));
params.data = Some({
// `recursive` expects only one 32-bit word in LE that
// represents an iteration count.
//
// We pick a relative big number to definitely hit stack overflow.
use byteorder::WriteBytesExt;
let mut data = vec![];
data.write_u32::<LittleEndian>(100000).unwrap();
data
});
let mut ext = FakeExt::new().with_wasm();
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext);
// We expect that stack overflow will occur and it should be generated by
// deterministic stack metering. Exceeding deterministic stack height limit
// always ends with a trap generated by `unreachable` instruction.
match result {
Err(trap) => {
let err_description = trap.to_string();
assert!(
err_description.contains("Unreachable"),
"err_description: {} should contain 'Unreachable'",
err_description
);
},
_ => panic!("this test should trap"),
}
} }