Skip to content

Commit d5c4b5b

Browse files
Ong-art IntelOng-art Intel
authored andcommitted
update wasmer & use gas metering middleware
1 parent efded66 commit d5c4b5b

File tree

2 files changed

+98
-12
lines changed

2 files changed

+98
-12
lines changed

packages/vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ assert_matches = "1.3.0"
1313
hex = "0.4"
1414
parity-wasm = "0.41"
1515
pwasm-utils = "0.12"
16-
wasmer = { version = "1.0.2", default-features = false, features = ["jit", "singlepass", "compiler"] }
16+
wasmer = { version = "2.3.0", default-features = false, features = ["jit", "singlepass", "compiler", "universal"] }
17+
wasmer-middlewares = "2.3.0"
1718
owasm-crypto = { path = "../crypto", version = "0.1.13" }
1819
tempfile = "3.1.0"
1920
clru = "0.2.0"

packages/vm/src/lib.rs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ pub use error::Error;
99
use parity_wasm::builder;
1010
use parity_wasm::elements::{self, External, MemoryType, Module};
1111
pub use std::ptr::NonNull;
12+
use std::sync::Arc;
13+
use wasmer::Universal;
14+
use wasmer_middlewares::metering::{get_remaining_points, MeteringPoints};
1215

1316
use pwasm_utils::{self, rules};
1417

15-
use wasmer::{imports, wasmparser, Function, Singlepass, Store, JIT};
18+
use wasmer::{
19+
imports, wasmparser, wasmparser::Operator, CompilerConfig, Function, Singlepass, Store, JIT,
20+
};
21+
use wasmer_middlewares::Metering;
1622

1723
use owasm_crypto::ecvrf;
1824

@@ -141,6 +147,11 @@ fn get_from_mem<E: vm::Env>(env: &Environment<E>, ptr: i64, len: i64) -> Result<
141147
Ok(memory.view()[ptr as usize..(ptr + len) as usize].iter().map(|cell| cell.get()).collect())
142148
}
143149

150+
fn cost(_operator: &Operator) -> u64 {
151+
// A flat fee for each operation
152+
1
153+
}
154+
144155
pub fn run<E>(
145156
cache: &mut Cache,
146157
code: &[u8],
@@ -153,8 +164,11 @@ where
153164
{
154165
let owasm_env = Environment::new(env, gas);
155166

156-
let compiler = Singlepass::new();
157-
let store = Store::new(&JIT::new(compiler).engine());
167+
let mut compiler = Singlepass::default();
168+
let metering = Arc::new(Metering::new(4294967290, cost));
169+
compiler.push_middleware(metering);
170+
let engine = Universal::new(compiler).engine();
171+
let store = Store::new(&engine);
158172

159173
let import_object = imports! {
160174
"env" => {
@@ -302,27 +316,68 @@ where
302316
return err.clone();
303317
}
304318

305-
owasm_env.with_vm(|vm| {
306-
if vm.out_of_gas() {
307-
return Error::OutOfGasError;
308-
}
309-
310-
Error::RuntimeError
311-
})
319+
match get_remaining_points(&instance) {
320+
MeteringPoints::Remaining(_) => Error::RuntimeError,
321+
MeteringPoints::Exhausted => Error::OutOfGasError,
322+
}
312323
})?;
313324

314-
Ok(owasm_env.with_vm(|vm| vm.gas_used))
325+
match get_remaining_points(&instance) {
326+
MeteringPoints::Remaining(count) => return Ok(gas - (count as u32)),
327+
MeteringPoints::Exhausted => return Ok(gas),
328+
};
329+
// Ok(owasm_env.with_vm(|vm| vm.gas_used))
315330
}
316331

317332
#[cfg(test)]
318333
mod test {
334+
use crate::cache::CacheOptions;
335+
319336
use super::*;
320337
use assert_matches::assert_matches;
321338
use parity_wasm::elements;
322339
use std::io::{Read, Write};
323340
use std::process::Command;
324341
use tempfile::NamedTempFile;
325342

343+
pub struct MockEnv {}
344+
345+
impl vm::Env for MockEnv {
346+
fn get_span_size(&self) -> i64 {
347+
100_000
348+
}
349+
fn get_calldata(&self) -> Result<Vec<u8>, Error> {
350+
Ok(vec![1])
351+
}
352+
fn set_return_data(&self, _: &[u8]) -> Result<(), Error> {
353+
Ok(())
354+
}
355+
fn get_ask_count(&self) -> i64 {
356+
10
357+
}
358+
fn get_min_count(&self) -> i64 {
359+
8
360+
}
361+
fn get_prepare_time(&self) -> i64 {
362+
100_000
363+
}
364+
fn get_execute_time(&self) -> Result<i64, Error> {
365+
Ok(100_000)
366+
}
367+
fn get_ans_count(&self) -> Result<i64, Error> {
368+
Ok(8)
369+
}
370+
fn ask_external_data(&self, _: i64, _: i64, _: &[u8]) -> Result<(), Error> {
371+
Ok(())
372+
}
373+
fn get_external_data_status(&self, _: i64, _: i64) -> Result<i64, Error> {
374+
Ok(1)
375+
}
376+
fn get_external_data(&self, _: i64, _: i64) -> Result<Vec<u8>, Error> {
377+
Ok(vec![1])
378+
}
379+
}
380+
326381
fn wat2wasm(wat: impl AsRef<[u8]>) -> Vec<u8> {
327382
let mut input_file = NamedTempFile::new().unwrap();
328383
let mut output_file = NamedTempFile::new().unwrap();
@@ -432,6 +487,36 @@ mod test {
432487
assert_eq!(code, expected);
433488
}
434489

490+
#[test]
491+
fn test_gas_used() {
492+
let wasm = wat2wasm(
493+
r#"(module
494+
(type (func (param i64 i64 i64 i64) (result)))
495+
(func
496+
(local $idx i32)
497+
(local.set $idx (i32.const 0))
498+
(block
499+
(loop
500+
(local.set $idx (local.get $idx) (i32.const 1) (i32.add) )
501+
(br_if 0 (i32.lt_u (local.get $idx) (i32.const 100000)))
502+
)
503+
)
504+
)
505+
(func (;"execute": Resolves with result "beeb";)
506+
)
507+
(memory 17)
508+
(data (i32.const 1048576) "beeb") (;str = "beeb";)
509+
(export "prepare" (func 0))
510+
(export "execute" (func 1)))
511+
"#,
512+
);
513+
let code = compile(&wasm).unwrap();
514+
let mut cache = Cache::new(CacheOptions { cache_size: 10000 });
515+
let env = MockEnv {};
516+
let gas_used = run(&mut cache, &code, 4294967290, true, env).unwrap();
517+
assert_eq!(gas_used, 1000015 as u32);
518+
}
519+
435520
#[test]
436521
fn test_inject_memory_no_memory() {
437522
let wasm = wat2wasm("(module)");

0 commit comments

Comments
 (0)