Skip to content

Commit d036a6b

Browse files
committed
inline metering with injected gas function
1 parent 0638224 commit d036a6b

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

wasm-utils/cli/gas/main.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ fn main() {
1313
return;
1414
}
1515

16+
/*
1617
let memory_page_cost = 256 * 1024; // 256k gas for 1 page (64k) of memory
17-
18-
// let config = pwasm_utils::rules::Set::default()
19-
// .with_forbidden_floats() // Reject floating point opreations.
20-
// .with_grow_cost(memory_page_cost);
18+
let config = pwasm_utils::rules::Set::default()
19+
.with_forbidden_floats() // Reject floating point opreations.
20+
.with_grow_cost(memory_page_cost);
21+
*/
2122

2223
let config = pwasm_utils::rules::Set::default()
2324
.with_forbidden_floats();

wasm-utils/src/gas.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,51 @@ impl Counter {
136136
}
137137
}
138138

139+
fn inject_inline_gas(module: elements::Module) -> elements::Module {
140+
use parity_wasm::elements::Instruction::*;
141+
142+
static DEFAULT_START_GAS: i32 = 2000000000; // 4 billion is too big for signed integer
143+
144+
let global_gas_index = module.globals_space() as u32;
145+
println!("total globals before injecting gas global: {:?}", global_gas_index);
146+
147+
let b = builder::from_module(module);
148+
149+
let mut b2 = b.global().mutable()
150+
.value_type().i32().init_expr(elements::Instruction::I32Const(DEFAULT_START_GAS))
151+
.build()
152+
.export()
153+
.field("gas_global")
154+
.internal().global(global_gas_index)
155+
.build();
156+
157+
b2.push_function(
158+
builder::function()
159+
.signature().param().i32().build()
160+
.body()
161+
.with_locals(vec![elements::Local::new(1, elements::ValueType::I32)])
162+
.with_instructions(elements::Instructions::new(vec![
163+
GetGlobal(global_gas_index),
164+
GetLocal(0), // local 0 is the input param
165+
I32Sub,
166+
TeeLocal(1), // save deducted gas to local, because stack item will be consumed by i32.lte_s
167+
I32Const(0 as i32),
168+
I32LtS,
169+
If(elements::BlockType::NoResult),
170+
Unreachable,
171+
End,
172+
GetLocal(1), // put deducted gas back on stack
173+
SetGlobal(global_gas_index), // save to global
174+
End,
175+
]))
176+
.build()
177+
.build()
178+
);
179+
180+
b2.build()
181+
182+
}
183+
139184
fn inject_grow_counter(instructions: &mut elements::Instructions, grow_counter_func: u32) -> usize {
140185
use parity_wasm::elements::Instruction::*;
141186
let mut counter = 0;
@@ -312,8 +357,12 @@ pub fn inject_counter(
312357
pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
313358
-> Result<elements::Module, elements::Module>
314359
{
360+
let mbuilder = builder::from_module(module);
361+
let mut module = mbuilder.build();
362+
363+
/*
364+
// we are doing inline gas metering, so disable the external metering
315365
// Injecting gas counting external
316-
let mut mbuilder = builder::from_module(module);
317366
let import_sig = mbuilder.push_signature(
318367
builder::signature()
319368
.param().i32()
@@ -335,7 +384,16 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
335384
// (substract all imports that are NOT functions)
336385
337386
let gas_func = module.import_count(elements::ImportCountType::Function) as u32 - 1;
338-
let total_func = module.functions_space() as u32;
387+
*/
388+
389+
390+
// for inline gas function
391+
let gas_func = module.functions_space() as u32;
392+
393+
// need to inject inline gas function after the metering statements,
394+
// or the gas function itself with be metered and recursively call itself
395+
396+
let total_func = gas_func + 1;
339397
let mut need_grow_counter = false;
340398
let mut error = false;
341399

@@ -378,6 +436,9 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
378436

379437
if error { return Err(module); }
380438

439+
// metering calls have been injected, now inject inline gas func
440+
module = inject_inline_gas(module);
441+
381442
if need_grow_counter { Ok(add_grow_counter(module, rules, gas_func)) } else { Ok(module) }
382443
}
383444

0 commit comments

Comments
 (0)