Skip to content

Commit 3ee8a74

Browse files
committed
import func can decrease gas in metering
1 parent d0e76c4 commit 3ee8a74

File tree

2 files changed

+100
-7
lines changed

2 files changed

+100
-7
lines changed

packages/vm/src/lib.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ where
189189
let import_object = imports! {
190190
"env" => {
191191
"gas" => Function::new_native_with_env(&store, owasm_env.clone(), |env: &Environment<E>, gas: u32| {
192-
// env.with_mut_vm(|vm| {
193-
// vm.consume_gas(gas)
194-
// })
192+
env.with_mut_vm(|vm| {
193+
vm.consume_gas(gas)
194+
})
195195
}),
196196
"get_span_size" => Function::new_native_with_env(&store, owasm_env.clone(), |env: &Environment<E>| {
197197
env.with_vm(|vm| {
@@ -203,6 +203,7 @@ where
203203
let span_size = vm.env.get_span_size();
204204
// consume gas equal size of span when read calldata
205205
vm.consume_gas(span_size as u32)?;
206+
env.decrease_gas_left(span_size as u32)?;
206207

207208
let memory = env.memory()?;
208209
require_mem_range(memory.size().bytes().0, (ptr + span_size) as usize)?;
@@ -226,6 +227,7 @@ where
226227

227228
// consume gas equal size of span when save data to memory
228229
vm.consume_gas(span_size as u32)?;
230+
env.decrease_gas_left(span_size as u32)?;
229231

230232
let memory = env.memory()?;
231233
require_mem_range(memory.size().bytes().0, (ptr + span_size) as usize)?;
@@ -269,6 +271,7 @@ where
269271

270272
// consume gas equal size of span when write calldata for raw request
271273
vm.consume_gas(span_size as u32)?;
274+
env.decrease_gas_left(span_size as u32)?;
272275

273276
let memory = env.memory()?;
274277
require_mem_range(memory.size().bytes().0, (ptr + span_size) as usize)?;
@@ -287,6 +290,7 @@ where
287290
let span_size = vm.env.get_span_size();
288291
// consume gas equal size of span when read data from report
289292
vm.consume_gas(span_size as u32)?;
293+
env.decrease_gas_left(span_size as u32)?;
290294

291295
let memory = env.memory()?;
292296
require_mem_range(memory.size().bytes().0, (ptr + span_size) as usize)?;
@@ -304,6 +308,7 @@ where
304308
env.with_mut_vm(|vm| -> Result<u32, Error>{
305309
// consume gas relatively to the function running time (~12ms)
306310
vm.consume_gas(500000)?;
311+
env.decrease_gas_left(500000)?;
307312

308313
let y: Vec<u8> = get_from_mem(env, y_ptr, y_len)?;
309314
let pi: Vec<u8>= get_from_mem(env, pi_ptr, pi_len)?;
@@ -361,7 +366,7 @@ mod test {
361366

362367
impl vm::Env for MockEnv {
363368
fn get_span_size(&self) -> i64 {
364-
100_000
369+
30000
365370
}
366371
fn get_calldata(&self) -> Result<Vec<u8>, Error> {
367372
Ok(vec![1])
@@ -505,7 +510,7 @@ mod test {
505510
}
506511

507512
#[test]
508-
fn test_gas_used() {
513+
fn test_simple_gas_used() {
509514
let wasm = wat2wasm(
510515
r#"(module
511516
(type (func (param i64 i64 i64 i64) (result)))
@@ -534,6 +539,42 @@ mod test {
534539
assert_eq!(gas_used, 1000015 as u32);
535540
}
536541

542+
// #[test]
543+
// fn test_ask_count_gas_used() {
544+
// let wasm = wat2wasm(
545+
// r#"(module
546+
// (type (func (param i64 i64 i64 i64)))
547+
// (import "env" "ask_external_data" (func $ask_external_data (type 0)))
548+
// (func
549+
// (local $idx i32)
550+
// (i64.const 1)
551+
// (i64.const 1)
552+
// (i64.const 1048576)
553+
// (i64.const 4)
554+
// call 0
555+
// (local.set $idx (i32.const 0))
556+
// (block
557+
// (loop
558+
// (local.set $idx (local.get $idx) (i32.const 1) (i32.add) )
559+
// (br_if 0 (i32.lt_u (local.get $idx) (i32.const 100000)))
560+
// )
561+
// )
562+
// )
563+
// (func (;"execute": Resolves with result "beeb";)
564+
// )
565+
// (memory 17)
566+
// (data (i32.const 1048576) "beeb") (;str = "beeb";)
567+
// (export "prepare" (func 1))
568+
// (export "execute" (func 2)))
569+
// "#,
570+
// );
571+
// let code = compile(&wasm).unwrap();
572+
// let mut cache = Cache::new(CacheOptions { cache_size: 10000 });
573+
// let env = MockEnv {};
574+
// let gas_used = run(&mut cache, &code, 4294967290, true, env).unwrap();
575+
// assert_eq!(gas_used, 1000015 as u32);
576+
// }
577+
537578
#[test]
538579
fn test_run_time() {
539580
let wasm = wat2wasm(
@@ -571,8 +612,7 @@ mod test {
571612
let now = Instant::now();
572613
let _gas_used = run(&mut cache, &new_code, 4294967290, true, env).unwrap();
573614
let elapsed_time_2 = now.elapsed();
574-
575-
assert_eq!(elapsed_time.as_micros(), elapsed_time_2.as_micros());
615+
assert_eq!(true, elapsed_time.as_micros() > elapsed_time_2.as_micros());
576616
}
577617

578618
#[test]

packages/vm/src/vm.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use crate::error::Error;
2+
use std::borrow::Borrow;
23
use std::ptr::NonNull;
34
use std::sync::{Arc, Mutex, RwLock};
45

6+
use cosmwasm_vm::{VmError, VmResult};
57
use wasmer::{Instance, Memory, WasmerEnv};
8+
use wasmer_middlewares::metering::{get_remaining_points, set_remaining_points, MeteringPoints};
69

710
pub trait Env {
811
/// Returns the maximum span size value.
@@ -122,6 +125,56 @@ where
122125
data.wasmer_instance = instance;
123126
}
124127

128+
pub fn with_wasmer_instance<C, R>(&self, callback: C) -> VmResult<R>
129+
where
130+
C: FnOnce(&Instance) -> VmResult<R>,
131+
{
132+
self.with_context_data(|context_data| match context_data.wasmer_instance {
133+
Some(instance_ptr) => {
134+
let instance_ref = unsafe { instance_ptr.as_ref() };
135+
callback(instance_ref)
136+
}
137+
None => Err(VmError::UninitializedContextData { kind: "wasmer_instance".to_string() }),
138+
})
139+
}
140+
141+
fn with_context_data<C, R>(&self, callback: C) -> R
142+
where
143+
C: FnOnce(&ContextData) -> R,
144+
{
145+
let guard = self.data.as_ref().read().unwrap();
146+
let context_data = guard.borrow();
147+
callback(context_data)
148+
}
149+
150+
pub fn get_gas_left(&self) -> u64 {
151+
self.with_wasmer_instance(|instance| {
152+
Ok(match get_remaining_points(instance) {
153+
MeteringPoints::Remaining(count) => count,
154+
MeteringPoints::Exhausted => 0,
155+
})
156+
})
157+
.expect("Wasmer instance is not set. This is a bug in the lifecycle.")
158+
}
159+
160+
pub fn set_gas_left(&self, new_value: u64) {
161+
self.with_wasmer_instance(|instance| {
162+
set_remaining_points(instance, new_value);
163+
Ok(())
164+
})
165+
.expect("Wasmer instance is not set. This is a bug in the lifecycle.")
166+
}
167+
168+
pub fn decrease_gas_left(&self, gas_used: u32) -> Result<(), Error> {
169+
let gas_left = self.get_gas_left();
170+
if gas_used as u64 > gas_left {
171+
Err(Error::OutOfGasError)
172+
} else {
173+
self.set_gas_left(gas_left.saturating_sub(gas_used.into()));
174+
Ok(())
175+
}
176+
}
177+
125178
pub fn memory(&self) -> Result<Memory, Error> {
126179
let data = self.data.as_ref().read().unwrap();
127180
match data.wasmer_instance {

0 commit comments

Comments
 (0)