From b30b3b6a4d16e1e98d2baa1032c67e8b5e7e8f08 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 16 Dec 2020 10:08:10 +0100 Subject: [PATCH] Make get_remaining_points/set_remaining_points free functions --- examples/metering.rs | 14 +++--- lib/middlewares/src/lib.rs | 2 +- lib/middlewares/src/metering.rs | 78 +++++++++++++++++++-------------- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/examples/metering.rs b/examples/metering.rs index ed588dda372..48fcdad96bc 100644 --- a/examples/metering.rs +++ b/examples/metering.rs @@ -21,7 +21,7 @@ use wasmer::CompilerConfig; use wasmer::{imports, wat2wasm, Instance, Module, Store}; use wasmer_compiler_cranelift::Cranelift; use wasmer_engine_jit::JIT; -use wasmer_middlewares::Metering; +use wasmer_middlewares::{get_remaining_points, set_remaining_points, Metering}; fn main() -> anyhow::Result<()> { // Let's declare the Wasm module. @@ -62,7 +62,7 @@ fn main() -> anyhow::Result<()> { // function and subtract the cost from the gas. let metering = Arc::new(Metering::new(10, cost_function)); let mut compiler_config = Cranelift::default(); - compiler_config.push_middleware(metering.clone()); + compiler_config.push_middleware(metering); // Create a Store. // @@ -99,7 +99,7 @@ fn main() -> anyhow::Result<()> { // * `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 = metering.get_remaining_points(&instance); + let remaining_points_after_first_call = get_remaining_points(&instance); assert_eq!(remaining_points_after_first_call, 6); println!( @@ -112,7 +112,7 @@ fn main() -> anyhow::Result<()> { // We spent 4 more gas points with the second call. // We have 2 remaining points. - let remaining_points_after_second_call = metering.get_remaining_points(&instance); + let remaining_points_after_second_call = get_remaining_points(&instance); assert_eq!(remaining_points_after_second_call, 2); println!( @@ -138,7 +138,7 @@ fn main() -> anyhow::Result<()> { // Becasue the previous call failed, it did not consume any gas point. // We still have 2 remaining points. - let remaining_points_after_third_call = metering.get_remaining_points(&instance); + let remaining_points_after_third_call = get_remaining_points(&instance); assert_eq!(remaining_points_after_third_call, 2); println!( @@ -149,9 +149,9 @@ fn main() -> anyhow::Result<()> { // Now let's see how we can set a new limit... println!("Set new remaining points points to 10"); let new_limit = 10; - metering.set_remaining_points(&instance, new_limit); + set_remaining_points(&instance, new_limit); - let remaining_points = metering.get_remaining_points(&instance); + let remaining_points = get_remaining_points(&instance); assert_eq!(remaining_points, new_limit); println!("Remaining points: {:?}", remaining_points); diff --git a/lib/middlewares/src/lib.rs b/lib/middlewares/src/lib.rs index 884fcf82242..1fbfa1e40fa 100644 --- a/lib/middlewares/src/lib.rs +++ b/lib/middlewares/src/lib.rs @@ -1,3 +1,3 @@ pub mod metering; -pub use metering::Metering; +pub use metering::{get_remaining_points, set_remaining_points, Metering}; diff --git a/lib/middlewares/src/metering.rs b/lib/middlewares/src/metering.rs index 02cba07c03e..8efc7566222 100644 --- a/lib/middlewares/src/metering.rs +++ b/lib/middlewares/src/metering.rs @@ -53,31 +53,6 @@ impl u64 + Copy + Clone + Send + Sync> Metering { remaining_points_index: Mutex::new(None), } } - - /// Get the remaining points in an Instance. - /// - /// Important: the instance Module must been processed with the `Metering` middleware. - pub fn get_remaining_points(&self, instance: &Instance) -> u64 { - instance - .exports - .get_global("remaining_points") - .expect("Can't get `remaining_points` from Instance") - .get() - .try_into() - .expect("`remaining_points` from Instance has wrong type") - } - - /// Set the provided remaining points in an Instance. - /// - /// Important: the instance Module must been processed with the `Metering` middleware. - pub fn set_remaining_points(&self, instance: &Instance, points: u64) { - instance - .exports - .get_global("remaining_points") - .expect("Can't get `remaining_points` from Instance") - .set(points.into()) - .expect("Can't set `remaining_points` in Instance"); - } } impl u64 + Copy + Clone + Send + Sync> fmt::Debug for Metering { @@ -189,6 +164,43 @@ impl u64 + Copy + Clone + Send + Sync> FunctionMiddleware } } +/// Get the remaining points in an `Instance`. +/// +/// This can be used in a headless engine after an ahead of time compilation +/// as all required state lives in the instance. +/// +/// # Panic +/// +/// The instance Module must have been processed with the [`Metering`] middleware +/// at compile time, otherwise this will panic. +pub fn get_remaining_points(instance: &Instance) -> u64 { + instance + .exports + .get_global("remaining_points") + .expect("Can't get `remaining_points` from Instance") + .get() + .try_into() + .expect("`remaining_points` from Instance has wrong type") +} + +/// Set the provided remaining points in an `Instance`. +/// +/// This can be used in a headless engine after an ahead of time compilation +/// as all required state lives in the instance. +/// +/// # Panic +/// +/// The instance Module must have been processed with the [`Metering`] middleware +/// at compile time, otherwise this will panic. +pub fn set_remaining_points(instance: &Instance, points: u64) { + instance + .exports + .get_global("remaining_points") + .expect("Can't get `remaining_points` from Instance") + .set(points.into()) + .expect("Can't set `remaining_points` in Instance"); +} + #[cfg(test)] mod tests { use super::*; @@ -230,7 +242,7 @@ mod tests { // Instantiate let instance = Instance::new(&module, &imports! {}).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 10); + assert_eq!(get_remaining_points(&instance), 10); // First call // @@ -245,11 +257,11 @@ mod tests { .native::() .unwrap(); add_one.call(1).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 6); + assert_eq!(get_remaining_points(&instance), 6); // Second call add_one.call(1).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 2); + assert_eq!(get_remaining_points(&instance), 2); // Third call fails due to limit assert!(add_one.call(1).is_err()); @@ -268,7 +280,7 @@ mod tests { // Instantiate let instance = Instance::new(&module, &imports! {}).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 10); + assert_eq!(get_remaining_points(&instance), 10); let add_one = instance .exports .get_function("add_one") @@ -277,14 +289,14 @@ mod tests { .unwrap(); // Increase a bit to have enough for 3 calls - metering.set_remaining_points(&instance, 12); + set_remaining_points(&instance, 12); // Ensure we can use the new points now add_one.call(1).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 8); + assert_eq!(get_remaining_points(&instance), 8); add_one.call(1).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 4); + assert_eq!(get_remaining_points(&instance), 4); add_one.call(1).unwrap(); - assert_eq!(metering.get_remaining_points(&instance), 0); + assert_eq!(get_remaining_points(&instance), 0); } }