Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add an error code on the metering middleware #1951

Merged
merged 1 commit into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 31 additions & 23 deletions examples/metering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ use wasmer::CompilerConfig;
use wasmer::{imports, wat2wasm, Instance, Module, Store};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_jit::JIT;
use wasmer_middlewares::metering::{get_remaining_points, set_remaining_points, Metering};
use wasmer_middlewares::{
metering::{get_remaining_points, set_remaining_points, MeteringPoints},
Metering,
};

fn main() -> anyhow::Result<()> {
// Let's declare the Wasm module.
Expand Down Expand Up @@ -55,11 +58,10 @@ fn main() -> anyhow::Result<()> {

// Now let's create our metering middleware.
//
// `Metering` needs to be configured with a limit (the gas limit) and
// a cost function.
// `Metering` needs to be configured with a limit and a cost function.
//
// For each `Operator`, the metering middleware will call the cost
// function and subtract the cost from the gas.
// function and subtract the cost from the remaining points.
let metering = Arc::new(Metering::new(10, cost_function));
let mut compiler_config = Cranelift::default();
compiler_config.push_middleware(metering);
Expand Down Expand Up @@ -93,14 +95,17 @@ fn main() -> anyhow::Result<()> {
println!("Calling `add_one` function once...");
add_one.call(1)?;

// As you can see here, after the first call we have 6 remaining gas points.
// As you can see here, after the first call we have 6 remaining points.
//
// This is correct, here are the details of how it has been computed:
// * `local.get $value` is a `Operator::LocalGet` which costs 1 point;
// * `i32.const` is a `Operator::I32Const` which costs 1 point;
// * `i32.add` is a `Operator::I32Add` which costs 2 points.
let remaining_points_after_first_call = get_remaining_points(&instance);
assert_eq!(remaining_points_after_first_call, 6);
assert_eq!(
remaining_points_after_first_call,
MeteringPoints::Remaining(6)
);

println!(
"Remaining points after the first call: {:?}",
Expand All @@ -110,18 +115,21 @@ fn main() -> anyhow::Result<()> {
println!("Calling `add_one` function twice...");
add_one.call(1)?;

// We spent 4 more gas points with the second call.
// We spent 4 more points with the second call.
// We have 2 remaining points.
let remaining_points_after_second_call = get_remaining_points(&instance);
assert_eq!(remaining_points_after_second_call, 2);
assert_eq!(
remaining_points_after_second_call,
MeteringPoints::Remaining(2)
);

println!(
"Remaining points after the second call: {:?}",
remaining_points_after_second_call
);

// Because calling our `add_one` function consumes 4 gas points,
// calling it a third time will fail: we already consume 8 gas
// Because calling our `add_one` function consumes 4 points,
// calling it a third time will fail: we already consume 8
// points, there are only two remaining.
println!("Calling `add_one` function a third time...");
match add_one.call(1) {
Expand All @@ -132,27 +140,27 @@ fn main() -> anyhow::Result<()> {
);
}
Err(_) => {
println!("Calling `add_one` failed: not enough gas points remaining.");
}
}
println!("Calling `add_one` failed.");

// Becasue the previous call failed, it did not consume any gas point.
// We still have 2 remaining points.
let remaining_points_after_third_call = get_remaining_points(&instance);
assert_eq!(remaining_points_after_third_call, 2);
// Because the last needed more than the remaining points, we should have an error.
let remaining_points = get_remaining_points(&instance);

println!(
"Remaining points after third call: {:?}",
remaining_points_after_third_call
);
match remaining_points {
MeteringPoints::Remaining(..) => {
bail!("No metering error: there are remaining points")
}
MeteringPoints::Exhausted => println!("Not enough points remaining"),
}
}
}

// Now let's see how we can set a new limit...
println!("Set new remaining points points to 10");
println!("Set new remaining points to 10");
let new_limit = 10;
set_remaining_points(&instance, new_limit);

let remaining_points = get_remaining_points(&instance);
assert_eq!(remaining_points, new_limit);
assert_eq!(remaining_points, MeteringPoints::Remaining(new_limit));

println!("Remaining points: {:?}", remaining_points);

Expand Down
Loading