@@ -9,10 +9,16 @@ pub use error::Error;
9
9
use parity_wasm:: builder;
10
10
use parity_wasm:: elements:: { self , External , MemoryType , Module } ;
11
11
pub use std:: ptr:: NonNull ;
12
+ use std:: sync:: Arc ;
13
+ use wasmer:: Universal ;
14
+ use wasmer_middlewares:: metering:: { get_remaining_points, MeteringPoints } ;
12
15
13
16
use pwasm_utils:: { self , rules} ;
14
17
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 ;
16
22
17
23
use owasm_crypto:: ecvrf;
18
24
@@ -141,6 +147,11 @@ fn get_from_mem<E: vm::Env>(env: &Environment<E>, ptr: i64, len: i64) -> Result<
141
147
Ok ( memory. view ( ) [ ptr as usize ..( ptr + len) as usize ] . iter ( ) . map ( |cell| cell. get ( ) ) . collect ( ) )
142
148
}
143
149
150
+ fn cost ( _operator : & Operator ) -> u64 {
151
+ // A flat fee for each operation
152
+ 1
153
+ }
154
+
144
155
pub fn run < E > (
145
156
cache : & mut Cache ,
146
157
code : & [ u8 ] ,
@@ -153,8 +164,11 @@ where
153
164
{
154
165
let owasm_env = Environment :: new ( env, gas) ;
155
166
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) ;
158
172
159
173
let import_object = imports ! {
160
174
"env" => {
@@ -302,27 +316,68 @@ where
302
316
return err. clone ( ) ;
303
317
}
304
318
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
+ }
312
323
} ) ?;
313
324
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))
315
330
}
316
331
317
332
#[ cfg( test) ]
318
333
mod test {
334
+ use crate :: cache:: CacheOptions ;
335
+
319
336
use super :: * ;
320
337
use assert_matches:: assert_matches;
321
338
use parity_wasm:: elements;
322
339
use std:: io:: { Read , Write } ;
323
340
use std:: process:: Command ;
324
341
use tempfile:: NamedTempFile ;
325
342
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
+
326
381
fn wat2wasm ( wat : impl AsRef < [ u8 ] > ) -> Vec < u8 > {
327
382
let mut input_file = NamedTempFile :: new ( ) . unwrap ( ) ;
328
383
let mut output_file = NamedTempFile :: new ( ) . unwrap ( ) ;
@@ -432,6 +487,36 @@ mod test {
432
487
assert_eq ! ( code, expected) ;
433
488
}
434
489
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
+
435
520
#[ test]
436
521
fn test_inject_memory_no_memory ( ) {
437
522
let wasm = wat2wasm ( "(module)" ) ;
0 commit comments