WASM libraries bump (#7970)
* update wasmi, parity-wasm, wasm-utils to latest version * Update to new wasmi & error handling * also utilize new stack limiter * fix typo * replace dependency url * Cargo.lock update
This commit is contained in:
parent
3f33370e7d
commit
e0a21e5aae
25
Cargo.lock
generated
25
Cargo.lock
generated
@ -1553,6 +1553,11 @@ dependencies = [
|
|||||||
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memory_units"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memorydb"
|
name = "memorydb"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -2292,7 +2297,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-wasm"
|
name = "parity-wasm"
|
||||||
version = "0.23.0"
|
version = "0.27.2"
|
||||||
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)",
|
||||||
@ -3500,16 +3505,16 @@ dependencies = [
|
|||||||
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-wasm 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vm 0.1.0",
|
"vm 0.1.0",
|
||||||
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
||||||
"wasmi 0.0.0 (git+https://github.com/pepyakin/wasmi)",
|
"wasmi 0.0.0 (git+https://github.com/paritytech/wasmi)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-utils"
|
name = "wasm-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/paritytech/wasm-utils#6fdc1c4ed47a6acb0a4774da505a416dd637bc6d"
|
source = "git+https://github.com/paritytech/wasm-utils#9527b969a4928f6293369380defc7982493a678c"
|
||||||
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)",
|
||||||
"clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3517,16 +3522,17 @@ dependencies = [
|
|||||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-wasm 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmi"
|
name = "wasmi"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/pepyakin/wasmi#551c99273042deaad869c17798060e2212deacab"
|
source = "git+https://github.com/paritytech/wasmi#7c88c6ad651ec6a6aa00b08e61c70853161a0a99"
|
||||||
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)",
|
||||||
"parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-wasm 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3728,6 +3734,7 @@ dependencies = [
|
|||||||
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
||||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||||
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
||||||
|
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
|
||||||
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||||
"checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160"
|
"checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160"
|
||||||
"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae"
|
"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae"
|
||||||
@ -3764,7 +3771,7 @@ dependencies = [
|
|||||||
"checksum parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=1a58bf4836c84e1632e27ef607b5a388abd2bf2d)" = "<none>"
|
"checksum parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=1a58bf4836c84e1632e27ef607b5a388abd2bf2d)" = "<none>"
|
||||||
"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4c067dfa1a17fe71ab2ca26b18c52dcbd0f4fc04)" = "<none>"
|
"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4c067dfa1a17fe71ab2ca26b18c52dcbd0f4fc04)" = "<none>"
|
||||||
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=ac243b5ce9ce10d5f9f6137e974f195e8403b68e)" = "<none>"
|
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=ac243b5ce9ce10d5f9f6137e974f195e8403b68e)" = "<none>"
|
||||||
"checksum parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ba4b1d4236b76694f6ab8d8d00cdbe1e37c6dd1b5c803d26721f27e097d4d9"
|
"checksum parity-wasm 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3c21b85fed4e8490e716b7fcb247185ec201f28845be6e749ab864401463c7"
|
||||||
"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
|
"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
|
||||||
"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
|
"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
|
||||||
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
|
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
|
||||||
@ -3886,7 +3893,7 @@ dependencies = [
|
|||||||
"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 wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)" = "<none>"
|
"checksum wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)" = "<none>"
|
||||||
"checksum wasmi 0.0.0 (git+https://github.com/pepyakin/wasmi)" = "<none>"
|
"checksum wasmi 0.0.0 (git+https://github.com/paritytech/wasmi)" = "<none>"
|
||||||
"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"
|
||||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
@ -119,8 +119,8 @@ pub struct Schedule {
|
|||||||
|
|
||||||
/// Wasm cost table
|
/// Wasm cost table
|
||||||
pub struct WasmCosts {
|
pub struct WasmCosts {
|
||||||
/// Arena allocator cost, per byte
|
/// Default opcode cost
|
||||||
pub alloc: u32,
|
pub regular: u32,
|
||||||
/// Div operations multiplier.
|
/// Div operations multiplier.
|
||||||
pub div: u32,
|
pub div: u32,
|
||||||
/// Div operations multiplier.
|
/// Div operations multiplier.
|
||||||
@ -135,17 +135,18 @@ pub struct WasmCosts {
|
|||||||
pub initial_mem: u32,
|
pub initial_mem: u32,
|
||||||
/// Grow memory cost, per page (64kb)
|
/// Grow memory cost, per page (64kb)
|
||||||
pub grow_mem: u32,
|
pub grow_mem: u32,
|
||||||
|
/// Max stack height (native WebAssembly stack limiter)
|
||||||
|
pub max_stack_height: u32,
|
||||||
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
||||||
pub opcodes_mul: u32,
|
pub opcodes_mul: u32,
|
||||||
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
||||||
pub opcodes_div: u32,
|
pub opcodes_div: u32,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WasmCosts {
|
impl Default for WasmCosts {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
WasmCosts {
|
WasmCosts {
|
||||||
alloc: 2,
|
regular: 1,
|
||||||
div: 16,
|
div: 16,
|
||||||
mul: 4,
|
mul: 4,
|
||||||
mem: 2,
|
mem: 2,
|
||||||
@ -153,6 +154,7 @@ impl Default for WasmCosts {
|
|||||||
static_address: 40,
|
static_address: 40,
|
||||||
initial_mem: 4096,
|
initial_mem: 4096,
|
||||||
grow_mem: 8192,
|
grow_mem: 8192,
|
||||||
|
max_stack_height: 64*1024,
|
||||||
opcodes_mul: 3,
|
opcodes_mul: 3,
|
||||||
opcodes_div: 8,
|
opcodes_div: 8,
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
ethereum-types = "0.2"
|
ethereum-types = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
parity-wasm = "0.23"
|
parity-wasm = "0.27"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
|
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
|
||||||
vm = { path = "../vm" }
|
vm = { path = "../vm" }
|
||||||
ethcore-logger = { path = "../../logger" }
|
ethcore-logger = { path = "../../logger" }
|
||||||
wasmi = { git = "https://github.com/pepyakin/wasmi" }
|
wasmi = { git = "https://github.com/paritytech/wasmi" }
|
@ -19,7 +19,7 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use wasmi::{
|
use wasmi::{
|
||||||
self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor,
|
self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor,
|
||||||
MemoryRef, MemoryInstance,
|
MemoryRef, MemoryInstance, memory_units,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Internal ids all functions runtime supports. This is just a glue for wasmi interpreter
|
/// Internal ids all functions runtime supports. This is just a glue for wasmi interpreter
|
||||||
@ -219,7 +219,10 @@ impl ImportResolver {
|
|||||||
let mut mem_ref = self.memory.borrow_mut();
|
let mut mem_ref = self.memory.borrow_mut();
|
||||||
if mem_ref.is_none() {
|
if mem_ref.is_none() {
|
||||||
*mem_ref = Some(
|
*mem_ref = Some(
|
||||||
MemoryInstance::alloc(0, Some(0)).expect("Memory allocation (0, 0) should not fail; qed")
|
MemoryInstance::alloc(
|
||||||
|
memory_units::Pages(0),
|
||||||
|
Some(memory_units::Pages(0)),
|
||||||
|
).expect("Memory allocation (0, 0) should not fail; qed")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +232,7 @@ impl ImportResolver {
|
|||||||
|
|
||||||
/// Returns memory size module initially requested
|
/// Returns memory size module initially requested
|
||||||
pub fn memory_size(&self) -> Result<u32, Error> {
|
pub fn memory_size(&self) -> Result<u32, Error> {
|
||||||
Ok(self.memory_ref().size())
|
Ok(self.memory_ref().current_size().0 as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +284,10 @@ impl wasmi::ModuleImportResolver for ImportResolver {
|
|||||||
{
|
{
|
||||||
Err(Error::Instantiation("Module requested too much memory".to_owned()))
|
Err(Error::Instantiation("Module requested too much memory".to_owned()))
|
||||||
} else {
|
} else {
|
||||||
let mem = MemoryInstance::alloc(descriptor.initial(), descriptor.maximum())?;
|
let mem = MemoryInstance::alloc(
|
||||||
|
memory_units::Pages(descriptor.initial() as usize),
|
||||||
|
descriptor.maximum().map(|x| memory_units::Pages(x as usize)),
|
||||||
|
)?;
|
||||||
*self.memory.borrow_mut() = Some(mem.clone());
|
*self.memory.borrow_mut() = Some(mem.clone());
|
||||||
Ok(mem)
|
Ok(mem)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ mod panic_payload;
|
|||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
use vm::{GasLeft, ReturnData, ActionParams};
|
use vm::{GasLeft, ReturnData, ActionParams};
|
||||||
use wasmi::Error as InterpreterError;
|
use wasmi::{Error as InterpreterError, Trap};
|
||||||
|
|
||||||
use runtime::{Runtime, RuntimeContext};
|
use runtime::{Runtime, RuntimeContext};
|
||||||
|
|
||||||
@ -42,17 +42,29 @@ use ethereum_types::U256;
|
|||||||
|
|
||||||
/// Wrapped interpreter error
|
/// Wrapped interpreter error
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error(InterpreterError);
|
pub enum Error {
|
||||||
|
Interpreter(InterpreterError),
|
||||||
|
Trap(Trap),
|
||||||
|
}
|
||||||
|
|
||||||
impl From<InterpreterError> for Error {
|
impl From<InterpreterError> for Error {
|
||||||
fn from(e: InterpreterError) -> Self {
|
fn from(e: InterpreterError) -> Self {
|
||||||
Error(e)
|
Error::Interpreter(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Trap> for Error {
|
||||||
|
fn from(e: Trap) -> Self {
|
||||||
|
Error::Trap(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for vm::Error {
|
impl From<Error> for vm::Error {
|
||||||
fn from(e: Error) -> Self {
|
fn from(e: Error) -> Self {
|
||||||
vm::Error::Wasm(format!("Wasm runtime error: {:?}", e.0))
|
match e {
|
||||||
|
Error::Interpreter(e) => vm::Error::Wasm(format!("Wasm runtime error: {:?}", e)),
|
||||||
|
Error::Trap(e) => vm::Error::Wasm(format!("Wasm contract trap: {:?}", e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +82,14 @@ impl vm::Vm for WasmInterpreter {
|
|||||||
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||||
let (module, data) = parser::payload(¶ms, ext.schedule().wasm())?;
|
let (module, data) = parser::payload(¶ms, ext.schedule().wasm())?;
|
||||||
|
|
||||||
let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error)?;
|
let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?;
|
||||||
|
|
||||||
let instantiation_resolover = env::ImportResolver::with_limit(16);
|
let instantiation_resolver = env::ImportResolver::with_limit(16);
|
||||||
|
|
||||||
let module_instance = wasmi::ModuleInstance::new(
|
let module_instance = wasmi::ModuleInstance::new(
|
||||||
&loaded_module,
|
&loaded_module,
|
||||||
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolover)
|
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolver)
|
||||||
).map_err(Error)?;
|
).map_err(Error::Interpreter)?;
|
||||||
|
|
||||||
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
|
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
|
||||||
U256::from(ext.schedule().wasm().opcodes_mul);
|
U256::from(ext.schedule().wasm().opcodes_mul);
|
||||||
@ -87,13 +99,13 @@ impl vm::Vm for WasmInterpreter {
|
|||||||
return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas (wasm adjusted) >= 2^64".to_owned()));
|
return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas (wasm adjusted) >= 2^64".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let initial_memory = instantiation_resolover.memory_size().map_err(Error)?;
|
let initial_memory = instantiation_resolver.memory_size().map_err(Error::Interpreter)?;
|
||||||
trace!(target: "wasm", "Contract requested {:?} pages of initial memory", initial_memory);
|
trace!(target: "wasm", "Contract requested {:?} pages of initial memory", initial_memory);
|
||||||
|
|
||||||
let (gas_left, result) = {
|
let (gas_left, result) = {
|
||||||
let mut runtime = Runtime::with_params(
|
let mut runtime = Runtime::with_params(
|
||||||
ext,
|
ext,
|
||||||
instantiation_resolover.memory_ref(),
|
instantiation_resolver.memory_ref(),
|
||||||
// cannot overflow, checked above
|
// cannot overflow, checked above
|
||||||
adjusted_gas.low_u64(),
|
adjusted_gas.low_u64(),
|
||||||
data.to_vec(),
|
data.to_vec(),
|
||||||
@ -114,33 +126,27 @@ impl vm::Vm for WasmInterpreter {
|
|||||||
assert!(runtime.schedule().wasm().initial_mem < 1 << 16);
|
assert!(runtime.schedule().wasm().initial_mem < 1 << 16);
|
||||||
runtime.charge(|s| initial_memory as u64 * s.wasm().initial_mem as u64)?;
|
runtime.charge(|s| initial_memory as u64 * s.wasm().initial_mem as u64)?;
|
||||||
|
|
||||||
let module_instance = module_instance.run_start(&mut runtime).map_err(Error)?;
|
let module_instance = module_instance.run_start(&mut runtime).map_err(Error::Trap)?;
|
||||||
|
|
||||||
match module_instance.invoke_export("call", &[], &mut runtime) {
|
let invoke_result = module_instance.invoke_export("call", &[], &mut runtime);
|
||||||
Ok(_) => { },
|
|
||||||
Err(InterpreterError::Host(boxed)) => {
|
let mut suicide = false;
|
||||||
match boxed.downcast_ref::<runtime::Error>() {
|
if let Err(InterpreterError::Trap(ref trap)) = invoke_result {
|
||||||
None => {
|
if let wasmi::TrapKind::Host(ref boxed) = *trap.kind() {
|
||||||
return Err(vm::Error::Wasm("Invalid user error used in interpreter".to_owned()));
|
let ref runtime_err = boxed.downcast_ref::<runtime::Error>()
|
||||||
}
|
.expect("Host errors other than runtime::Error never produced; qed");
|
||||||
Some(runtime_err) => {
|
|
||||||
match *runtime_err {
|
if let runtime::Error::Suicide = **runtime_err { suicide = true; }
|
||||||
runtime::Error::Suicide => {
|
|
||||||
// Suicide uses trap to break execution
|
|
||||||
}
|
|
||||||
ref any_err => {
|
|
||||||
trace!(target: "wasm", "Error executing contract: {:?}", boxed);
|
|
||||||
return Err(vm::Error::from(Error::from(InterpreterError::Host(Box::new(any_err.clone())))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !suicide {
|
||||||
|
if let Err(e) = invoke_result {
|
||||||
|
trace!(target: "wasm", "Error executing contract: {:?}", e);
|
||||||
|
return Err(vm::Error::from(Error::from(e)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
trace!(target: "wasm", "Error executing contract: {:?}", err);
|
|
||||||
return Err(vm::Error::from(Error::from(err)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(
|
(
|
||||||
runtime.gas_left().expect("Cannot fail since it was not updated since last charge"),
|
runtime.gas_left().expect("Cannot fail since it was not updated since last charge"),
|
||||||
runtime.into_result(),
|
runtime.into_result(),
|
||||||
|
@ -22,14 +22,18 @@ use parity_wasm::elements::{self, Deserialize};
|
|||||||
use parity_wasm::peek_size;
|
use parity_wasm::peek_size;
|
||||||
|
|
||||||
fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set {
|
fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set {
|
||||||
rules::Set::new({
|
rules::Set::new(
|
||||||
let mut vals = ::std::collections::HashMap::with_capacity(4);
|
wasm_costs.regular,
|
||||||
vals.insert(rules::InstructionType::Load, wasm_costs.mem as u32);
|
{
|
||||||
vals.insert(rules::InstructionType::Store, wasm_costs.mem as u32);
|
let mut vals = ::std::collections::HashMap::with_capacity(8);
|
||||||
vals.insert(rules::InstructionType::Div, wasm_costs.div as u32);
|
vals.insert(rules::InstructionType::Load, rules::Metering::Fixed(wasm_costs.mem as u32));
|
||||||
vals.insert(rules::InstructionType::Mul, wasm_costs.mul as u32);
|
vals.insert(rules::InstructionType::Store, rules::Metering::Fixed(wasm_costs.mem as u32));
|
||||||
|
vals.insert(rules::InstructionType::Div, rules::Metering::Fixed(wasm_costs.div as u32));
|
||||||
|
vals.insert(rules::InstructionType::Mul, rules::Metering::Fixed(wasm_costs.mul as u32));
|
||||||
vals
|
vals
|
||||||
}).with_grow_cost(wasm_costs.grow_mem)
|
})
|
||||||
|
.with_grow_cost(wasm_costs.grow_mem)
|
||||||
|
.with_forbidden_floats()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Splits payload to code and data according to params.params_type, also
|
/// Splits payload to code and data according to params.params_type, also
|
||||||
@ -71,7 +75,12 @@ pub fn payload<'a>(params: &'a vm::ActionParams, wasm_costs: &vm::WasmCosts)
|
|||||||
let contract_module = wasm_utils::inject_gas_counter(
|
let contract_module = wasm_utils::inject_gas_counter(
|
||||||
deserialized_module,
|
deserialized_module,
|
||||||
&gas_rules(wasm_costs),
|
&gas_rules(wasm_costs),
|
||||||
);
|
).map_err(|_| vm::Error::Wasm(format!("Wasm contract error: bytecode invalid")))?;
|
||||||
|
|
||||||
|
let contract_module = wasm_utils::stack_height::inject_limiter(
|
||||||
|
contract_module,
|
||||||
|
wasm_costs.max_stack_height,
|
||||||
|
).map_err(|_| vm::Error::Wasm(format!("Wasm contract error: stack limiter failure")))?;
|
||||||
|
|
||||||
let data = match params.params_type {
|
let data = match params.params_type {
|
||||||
vm::ParamsType::Embedded => {
|
vm::ParamsType::Embedded => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use ethereum_types::{U256, H256, Address};
|
use ethereum_types::{U256, H256, Address};
|
||||||
use vm::{self, CallType};
|
use vm::{self, CallType};
|
||||||
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError};
|
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind};
|
||||||
use super::panic_payload;
|
use super::panic_payload;
|
||||||
|
|
||||||
pub struct RuntimeContext {
|
pub struct RuntimeContext {
|
||||||
@ -52,15 +52,40 @@ pub enum Error {
|
|||||||
Other,
|
Other,
|
||||||
/// Syscall signature mismatch
|
/// Syscall signature mismatch
|
||||||
InvalidSyscall,
|
InvalidSyscall,
|
||||||
|
/// Unreachable instruction encountered
|
||||||
|
Unreachable,
|
||||||
|
/// Invalid virtual call
|
||||||
|
InvalidVirtualCall,
|
||||||
|
/// Division by zero
|
||||||
|
DivisionByZero,
|
||||||
|
/// Invalid conversion to integer
|
||||||
|
InvalidConversionToInt,
|
||||||
|
/// Stack overflow
|
||||||
|
StackOverflow,
|
||||||
/// Panic with message
|
/// Panic with message
|
||||||
Panic(String),
|
Panic(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl wasmi::HostError for Error { }
|
impl wasmi::HostError for Error { }
|
||||||
|
|
||||||
|
impl From<Trap> for Error {
|
||||||
|
fn from(trap: Trap) -> Self {
|
||||||
|
match *trap.kind() {
|
||||||
|
TrapKind::Unreachable => Error::Unreachable,
|
||||||
|
TrapKind::MemoryAccessOutOfBounds => Error::MemoryAccessViolation,
|
||||||
|
TrapKind::TableAccessOutOfBounds | TrapKind::ElemUninitialized => Error::InvalidVirtualCall,
|
||||||
|
TrapKind::DivisionByZero => Error::DivisionByZero,
|
||||||
|
TrapKind::InvalidConversionToInt => Error::InvalidConversionToInt,
|
||||||
|
TrapKind::UnexpectedSignature => Error::InvalidVirtualCall,
|
||||||
|
TrapKind::StackOverflow => Error::StackOverflow,
|
||||||
|
TrapKind::Host(_) => Error::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<InterpreterError> for Error {
|
impl From<InterpreterError> for Error {
|
||||||
fn from(interpreter_err: InterpreterError) -> Self {
|
fn from(err: InterpreterError) -> Self {
|
||||||
match interpreter_err {
|
match err {
|
||||||
InterpreterError::Value(_) => Error::InvalidSyscall,
|
InterpreterError::Value(_) => Error::InvalidSyscall,
|
||||||
InterpreterError::Memory(_) => Error::MemoryAccessViolation,
|
InterpreterError::Memory(_) => Error::MemoryAccessViolation,
|
||||||
_ => Error::Other,
|
_ => Error::Other,
|
||||||
@ -85,6 +110,11 @@ impl ::std::fmt::Display for Error {
|
|||||||
Error::Log => write!(f, "Error occured while logging an event"),
|
Error::Log => write!(f, "Error occured while logging an event"),
|
||||||
Error::InvalidSyscall => write!(f, "Invalid syscall signature encountered at runtime"),
|
Error::InvalidSyscall => write!(f, "Invalid syscall signature encountered at runtime"),
|
||||||
Error::Other => write!(f, "Other unspecified error"),
|
Error::Other => write!(f, "Other unspecified error"),
|
||||||
|
Error::Unreachable => write!(f, "Unreachable instruction encountered"),
|
||||||
|
Error::InvalidVirtualCall => write!(f, "Invalid virtual call"),
|
||||||
|
Error::DivisionByZero => write!(f, "Division by zero"),
|
||||||
|
Error::StackOverflow => write!(f, "Stack overflow"),
|
||||||
|
Error::InvalidConversionToInt => write!(f, "Invalid conversion to integer"),
|
||||||
Error::Panic(ref msg) => write!(f, "Panic: {}", msg),
|
Error::Panic(ref msg) => write!(f, "Panic: {}", msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,8 +233,8 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Read from the storage to wasm memory
|
/// Read from the storage to wasm memory
|
||||||
pub fn storage_read(&mut self, args: RuntimeArgs) -> Result<()>
|
pub fn storage_read(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let key = self.h256_at(args.nth(0)?)?;
|
let key = self.h256_at(args.nth_checked(0)?)?;
|
||||||
let val_ptr: u32 = args.nth(1)?;
|
let val_ptr: u32 = args.nth_checked(1)?;
|
||||||
|
|
||||||
let val = self.ext.storage_at(&key).map_err(|_| Error::StorageReadError)?;
|
let val = self.ext.storage_at(&key).map_err(|_| Error::StorageReadError)?;
|
||||||
|
|
||||||
@ -218,8 +248,8 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Write to storage from wasm memory
|
/// Write to storage from wasm memory
|
||||||
pub fn storage_write(&mut self, args: RuntimeArgs) -> Result<()>
|
pub fn storage_write(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let key = self.h256_at(args.nth(0)?)?;
|
let key = self.h256_at(args.nth_checked(0)?)?;
|
||||||
let val_ptr: u32 = args.nth(1)?;
|
let val_ptr: u32 = args.nth_checked(1)?;
|
||||||
|
|
||||||
let val = self.h256_at(val_ptr)?;
|
let val = self.h256_at(val_ptr)?;
|
||||||
let former_val = self.ext.storage_at(&key).map_err(|_| Error::StorageUpdateError)?;
|
let former_val = self.ext.storage_at(&key).map_err(|_| Error::StorageUpdateError)?;
|
||||||
@ -250,8 +280,8 @@ impl<'a> Runtime<'a> {
|
|||||||
/// * pointer in sandboxed memory where result is
|
/// * pointer in sandboxed memory where result is
|
||||||
/// * the length of the result
|
/// * the length of the result
|
||||||
pub fn ret(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn ret(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let ptr: u32 = args.nth(0)?;
|
let ptr: u32 = args.nth_checked(0)?;
|
||||||
let len: u32 = args.nth(1)?;
|
let len: u32 = args.nth_checked(1)?;
|
||||||
|
|
||||||
trace!(target: "wasm", "Contract ret: {} bytes @ {}", len, ptr);
|
trace!(target: "wasm", "Contract ret: {} bytes @ {}", len, ptr);
|
||||||
|
|
||||||
@ -273,7 +303,7 @@ impl<'a> Runtime<'a> {
|
|||||||
|
|
||||||
/// Report gas cost with the params passed in wasm stack
|
/// Report gas cost with the params passed in wasm stack
|
||||||
fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
|
fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let amount: u32 = args.nth(0)?;
|
let amount: u32 = args.nth_checked(0)?;
|
||||||
if self.charge_gas(amount as u64) {
|
if self.charge_gas(amount as u64) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -288,7 +318,7 @@ impl<'a> Runtime<'a> {
|
|||||||
|
|
||||||
/// Write input bytes to the memory location using the passed pointer
|
/// Write input bytes to the memory location using the passed pointer
|
||||||
fn fetch_input(&mut self, args: RuntimeArgs) -> Result<()> {
|
fn fetch_input(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let ptr: u32 = args.nth(0)?;
|
let ptr: u32 = args.nth_checked(0)?;
|
||||||
self.memory.set(ptr, &self.args[..])?;
|
self.memory.set(ptr, &self.args[..])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -298,8 +328,8 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Contract can invoke this when he encounters unrecoverable error.
|
/// Contract can invoke this when he encounters unrecoverable error.
|
||||||
fn panic(&mut self, args: RuntimeArgs) -> Result<()>
|
fn panic(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let payload_ptr: u32 = args.nth(0)?;
|
let payload_ptr: u32 = args.nth_checked(0)?;
|
||||||
let payload_len: u32 = args.nth(1)?;
|
let payload_len: u32 = args.nth_checked(1)?;
|
||||||
|
|
||||||
let raw_payload = self.memory.get(payload_ptr, payload_len as usize)?;
|
let raw_payload = self.memory.get(payload_ptr, payload_len as usize)?;
|
||||||
let payload = panic_payload::decode(&raw_payload);
|
let payload = panic_payload::decode(&raw_payload);
|
||||||
@ -333,26 +363,26 @@ impl<'a> Runtime<'a> {
|
|||||||
{
|
{
|
||||||
trace!(target: "wasm", "runtime: CALL({:?})", call_type);
|
trace!(target: "wasm", "runtime: CALL({:?})", call_type);
|
||||||
|
|
||||||
let gas: u64 = args.nth(0)?;
|
let gas: u64 = args.nth_checked(0)?;
|
||||||
trace!(target: "wasm", " gas: {:?}", gas);
|
trace!(target: "wasm", " gas: {:?}", gas);
|
||||||
|
|
||||||
let address = self.address_at(args.nth(1)?)?;
|
let address = self.address_at(args.nth_checked(1)?)?;
|
||||||
trace!(target: "wasm", " address: {:?}", address);
|
trace!(target: "wasm", " address: {:?}", address);
|
||||||
|
|
||||||
let vofs = if use_val { 1 } else { 0 };
|
let vofs = if use_val { 1 } else { 0 };
|
||||||
let val = if use_val { Some(self.u256_at(args.nth(2)?)?) } else { None };
|
let val = if use_val { Some(self.u256_at(args.nth_checked(2)?)?) } else { None };
|
||||||
trace!(target: "wasm", " val: {:?}", val);
|
trace!(target: "wasm", " val: {:?}", val);
|
||||||
|
|
||||||
let input_ptr: u32 = args.nth(2 + vofs)?;
|
let input_ptr: u32 = args.nth_checked(2 + vofs)?;
|
||||||
trace!(target: "wasm", " input_ptr: {:?}", input_ptr);
|
trace!(target: "wasm", " input_ptr: {:?}", input_ptr);
|
||||||
|
|
||||||
let input_len: u32 = args.nth(3 + vofs)?;
|
let input_len: u32 = args.nth_checked(3 + vofs)?;
|
||||||
trace!(target: "wasm", " input_len: {:?}", input_len);
|
trace!(target: "wasm", " input_len: {:?}", input_len);
|
||||||
|
|
||||||
let result_ptr: u32 = args.nth(4 + vofs)?;
|
let result_ptr: u32 = args.nth_checked(4 + vofs)?;
|
||||||
trace!(target: "wasm", " result_ptr: {:?}", result_ptr);
|
trace!(target: "wasm", " result_ptr: {:?}", result_ptr);
|
||||||
|
|
||||||
let result_alloc_len: u32 = args.nth(5 + vofs)?;
|
let result_alloc_len: u32 = args.nth_checked(5 + vofs)?;
|
||||||
trace!(target: "wasm", " result_len: {:?}", result_alloc_len);
|
trace!(target: "wasm", " result_len: {:?}", result_alloc_len);
|
||||||
|
|
||||||
if let Some(ref val) = val {
|
if let Some(ref val) = val {
|
||||||
@ -453,7 +483,7 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Returns value (in Wei) passed to contract
|
/// Returns value (in Wei) passed to contract
|
||||||
pub fn value(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn value(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let val = self.context.value;
|
let val = self.context.value;
|
||||||
self.return_u256_ptr(args.nth(0)?, val)
|
self.return_u256_ptr(args.nth_checked(0)?, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new contract
|
/// Creates a new contract
|
||||||
@ -470,13 +500,13 @@ impl<'a> Runtime<'a> {
|
|||||||
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||||
//
|
//
|
||||||
trace!(target: "wasm", "runtime: CREATE");
|
trace!(target: "wasm", "runtime: CREATE");
|
||||||
let endowment = self.u256_at(args.nth(0)?)?;
|
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||||
trace!(target: "wasm", " val: {:?}", endowment);
|
trace!(target: "wasm", " val: {:?}", endowment);
|
||||||
let code_ptr: u32 = args.nth(1)?;
|
let code_ptr: u32 = args.nth_checked(1)?;
|
||||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||||
let code_len: u32 = args.nth(2)?;
|
let code_len: u32 = args.nth_checked(2)?;
|
||||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||||
let result_ptr: u32 = args.nth(3)?;
|
let result_ptr: u32 = args.nth_checked(3)?;
|
||||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||||
|
|
||||||
let code = self.memory.get(code_ptr, code_len as usize)?;
|
let code = self.memory.get(code_ptr, code_len as usize)?;
|
||||||
@ -518,8 +548,8 @@ impl<'a> Runtime<'a> {
|
|||||||
|
|
||||||
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
|
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let msg_ptr: u32 = args.nth(0)?;
|
let msg_ptr: u32 = args.nth_checked(0)?;
|
||||||
let msg_len: u32 = args.nth(1)?;
|
let msg_len: u32 = args.nth_checked(1)?;
|
||||||
|
|
||||||
let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?)
|
let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?)
|
||||||
.map_err(|_| Error::BadUtf8)?;
|
.map_err(|_| Error::BadUtf8)?;
|
||||||
@ -532,7 +562,7 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Pass suicide to state runtime
|
/// Pass suicide to state runtime
|
||||||
pub fn suicide(&mut self, args: RuntimeArgs) -> Result<()>
|
pub fn suicide(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let refund_address = self.address_at(args.nth(0)?)?;
|
let refund_address = self.address_at(args.nth_checked(0)?)?;
|
||||||
|
|
||||||
if self.ext.exists(&refund_address).map_err(|_| Error::SuicideAbort)? {
|
if self.ext.exists(&refund_address).map_err(|_| Error::SuicideAbort)? {
|
||||||
trace!(target: "wasm", "Suicide: refund to existing address {}", refund_address);
|
trace!(target: "wasm", "Suicide: refund to existing address {}", refund_address);
|
||||||
@ -551,8 +581,8 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Signature: `fn blockhash(number: i64, dest: *mut u8)`
|
/// Signature: `fn blockhash(number: i64, dest: *mut u8)`
|
||||||
pub fn blockhash(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn blockhash(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
self.adjusted_charge(|schedule| schedule.blockhash_gas as u64)?;
|
self.adjusted_charge(|schedule| schedule.blockhash_gas as u64)?;
|
||||||
let hash = self.ext.blockhash(&U256::from(args.nth::<u64>(0)?));
|
let hash = self.ext.blockhash(&U256::from(args.nth_checked::<u64>(0)?));
|
||||||
self.memory.set(args.nth(1)?, &*hash)?;
|
self.memory.set(args.nth_checked(1)?, &*hash)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -565,37 +595,37 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Signature: `fn coinbase(dest: *mut u8)`
|
/// Signature: `fn coinbase(dest: *mut u8)`
|
||||||
pub fn coinbase(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn coinbase(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let coinbase = self.ext.env_info().author;
|
let coinbase = self.ext.env_info().author;
|
||||||
self.return_address_ptr(args.nth(0)?, coinbase)
|
self.return_address_ptr(args.nth_checked(0)?, coinbase)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `fn difficulty(dest: *mut u8)`
|
/// Signature: `fn difficulty(dest: *mut u8)`
|
||||||
pub fn difficulty(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn difficulty(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let difficulty = self.ext.env_info().difficulty;
|
let difficulty = self.ext.env_info().difficulty;
|
||||||
self.return_u256_ptr(args.nth(0)?, difficulty)
|
self.return_u256_ptr(args.nth_checked(0)?, difficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `fn gaslimit(dest: *mut u8)`
|
/// Signature: `fn gaslimit(dest: *mut u8)`
|
||||||
pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let gas_limit = self.ext.env_info().gas_limit;
|
let gas_limit = self.ext.env_info().gas_limit;
|
||||||
self.return_u256_ptr(args.nth(0)?, gas_limit)
|
self.return_u256_ptr(args.nth_checked(0)?, gas_limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `fn address(dest: *mut u8)`
|
/// Signature: `fn address(dest: *mut u8)`
|
||||||
pub fn address(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn address(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let address = self.context.address;
|
let address = self.context.address;
|
||||||
self.return_address_ptr(args.nth(0)?, address)
|
self.return_address_ptr(args.nth_checked(0)?, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `sender(dest: *mut u8)`
|
/// Signature: `sender(dest: *mut u8)`
|
||||||
pub fn sender(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn sender(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let sender = self.context.sender;
|
let sender = self.context.sender;
|
||||||
self.return_address_ptr(args.nth(0)?, sender)
|
self.return_address_ptr(args.nth_checked(0)?, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `origin(dest: *mut u8)`
|
/// Signature: `origin(dest: *mut u8)`
|
||||||
pub fn origin(&mut self, args: RuntimeArgs) -> Result<()> {
|
pub fn origin(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||||
let origin = self.context.origin;
|
let origin = self.context.origin;
|
||||||
self.return_address_ptr(args.nth(0)?, origin)
|
self.return_address_ptr(args.nth_checked(0)?, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature: `timestamp() -> i64`
|
/// Signature: `timestamp() -> i64`
|
||||||
@ -607,10 +637,10 @@ impl<'a> Runtime<'a> {
|
|||||||
/// Signature: `fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32)`
|
/// Signature: `fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32)`
|
||||||
pub fn elog(&mut self, args: RuntimeArgs) -> Result<()>
|
pub fn elog(&mut self, args: RuntimeArgs) -> Result<()>
|
||||||
{
|
{
|
||||||
let topic_ptr: u32 = args.nth(0)?;
|
let topic_ptr: u32 = args.nth_checked(0)?;
|
||||||
let topic_count: u32 = args.nth(1)?;
|
let topic_count: u32 = args.nth_checked(1)?;
|
||||||
let data_ptr: u32 = args.nth(2)?;
|
let data_ptr: u32 = args.nth_checked(2)?;
|
||||||
let data_len: u32 = args.nth(3)?;
|
let data_len: u32 = args.nth_checked(3)?;
|
||||||
|
|
||||||
if topic_count > 4 {
|
if topic_count > 4 {
|
||||||
return Err(Error::Log.into());
|
return Err(Error::Log.into());
|
||||||
@ -643,7 +673,7 @@ impl<'a> Runtime<'a> {
|
|||||||
|
|
||||||
mod ext_impl {
|
mod ext_impl {
|
||||||
|
|
||||||
use wasmi::{Externals, RuntimeArgs, RuntimeValue, Error};
|
use wasmi::{Externals, RuntimeArgs, RuntimeValue, Trap};
|
||||||
use env::ids::*;
|
use env::ids::*;
|
||||||
|
|
||||||
macro_rules! void {
|
macro_rules! void {
|
||||||
@ -663,7 +693,7 @@ mod ext_impl {
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: usize,
|
index: usize,
|
||||||
args: RuntimeArgs,
|
args: RuntimeArgs,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Trap> {
|
||||||
match index {
|
match index {
|
||||||
STORAGE_WRITE_FUNC => void!(self.storage_write(args)),
|
STORAGE_WRITE_FUNC => void!(self.storage_write(args)),
|
||||||
STORAGE_READ_FUNC => void!(self.storage_read(args)),
|
STORAGE_READ_FUNC => void!(self.storage_read(args)),
|
||||||
|
Loading…
Reference in New Issue
Block a user