Skip to content

Commit e4b98aa

Browse files
cdetrioaxic
authored andcommitted
inline metering with injected gas function
1 parent 5c8c8cb commit e4b98aa

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
@@ -122,6 +122,51 @@ impl Counter {
122122

123123
}
124124

125+
fn inject_inline_gas(module: elements::Module) -> elements::Module {
126+
use parity_wasm::elements::Instruction::*;
127+
128+
static DEFAULT_START_GAS: i32 = 2000000000; // 4 billion is too big for signed integer
129+
130+
let global_gas_index = module.globals_space() as u32;
131+
println!("total globals before injecting gas global: {:?}", global_gas_index);
132+
133+
let b = builder::from_module(module);
134+
135+
let mut b2 = b.global().mutable()
136+
.value_type().i32().init_expr(elements::Instruction::I32Const(DEFAULT_START_GAS))
137+
.build()
138+
.export()
139+
.field("gas_global")
140+
.internal().global(global_gas_index)
141+
.build();
142+
143+
b2.push_function(
144+
builder::function()
145+
.signature().param().i32().build()
146+
.body()
147+
.with_locals(vec![elements::Local::new(1, elements::ValueType::I32)])
148+
.with_instructions(elements::Instructions::new(vec![
149+
GetGlobal(global_gas_index),
150+
GetLocal(0), // local 0 is the input param
151+
I32Sub,
152+
TeeLocal(1), // save deducted gas to local, because stack item will be consumed by i32.lte_s
153+
I32Const(0 as i32),
154+
I32LtS,
155+
If(elements::BlockType::NoResult),
156+
Unreachable,
157+
End,
158+
GetLocal(1), // put deducted gas back on stack
159+
SetGlobal(global_gas_index), // save to global
160+
End,
161+
]))
162+
.build()
163+
.build()
164+
);
165+
166+
b2.build()
167+
168+
}
169+
125170
fn inject_grow_counter(instructions: &mut elements::Instructions, grow_counter_func: u32) -> usize {
126171
use parity_wasm::elements::Instruction::*;
127172
let mut counter = 0;
@@ -292,8 +337,12 @@ pub fn inject_counter(
292337
pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
293338
-> Result<elements::Module, elements::Module>
294339
{
340+
let mbuilder = builder::from_module(module);
341+
let mut module = mbuilder.build();
342+
343+
/*
344+
// we are doing inline gas metering, so disable the external metering
295345
// Injecting gas counting external
296-
let mut mbuilder = builder::from_module(module);
297346
let import_sig = mbuilder.push_signature(
298347
builder::signature()
299348
.param().i64()
@@ -315,7 +364,16 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
315364
// (substract all imports that are NOT functions)
316365
317366
let gas_func = module.import_count(elements::ImportCountType::Function) as u32 - 1;
318-
let total_func = module.functions_space() as u32;
367+
*/
368+
369+
370+
// for inline gas function
371+
let gas_func = module.functions_space() as u32;
372+
373+
// need to inject inline gas function after the metering statements,
374+
// or the gas function itself with be metered and recursively call itself
375+
376+
let total_func = gas_func + 1;
319377
let mut need_grow_counter = false;
320378
let mut error = false;
321379

@@ -357,6 +415,9 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
357415

358416
if error { return Err(module); }
359417

418+
// metering calls have been injected, now inject inline gas func
419+
module = inject_inline_gas(module);
420+
360421
if need_grow_counter { Ok(add_grow_counter(module, rules, gas_func)) } else { Ok(module) }
361422
}
362423

0 commit comments

Comments
 (0)