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

PoC call function by param_arity #2115

Closed
wants to merge 1 commit into from
Closed
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
21 changes: 15 additions & 6 deletions packages/vm/src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Internal details to be used by instance.rs only
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::ptr::NonNull;
use std::rc::Rc;
Expand Down Expand Up @@ -208,20 +209,26 @@ impl<A: BackendApi, S: Storage, Q: Querier> Environment<A, S, Q> {
}

/// Calls a function with the given name and arguments.
///
/// The args is a map from arity to arguments. If the contract has an unexpected arity, an error is raised.
///
/// The number of return values is variable and controlled by the guest.
/// Usually we expect 0 or 1 return values. Use [`Self::call_function0`]
/// or [`Self::call_function1`] to ensure the number of return values is checked.
fn call_function(
&self,
store: &mut impl AsStoreMut,
name: &str,
args: &[Value],
args: HashMap<usize, &[Value]>,
) -> VmResult<Box<[Value]>> {
// Clone function before calling it to avoid dead locks
let func = self.with_wasmer_instance(|instance| {
let func = instance.exports.get_function(name)?;
Ok(func.clone())
})?;
let Some(args) = args.get(&func.param_arity(store)) else {
panic!("Wrong number of args")
};
self.increment_call_depth()?;
let res = func.call(store, args).map_err(|runtime_err| -> VmError {
self.with_wasmer_instance::<_, Never>(|instance| {
Expand All @@ -243,6 +250,7 @@ impl<A: BackendApi, S: Storage, Q: Querier> Environment<A, S, Q> {
name: &str,
args: &[Value],
) -> VmResult<()> {
let args = HashMap::from([(args.len(), args)]);
let result = self.call_function(store, name, args)?;
let expected = 0;
let actual = result.len();
Expand All @@ -258,6 +266,7 @@ impl<A: BackendApi, S: Storage, Q: Querier> Environment<A, S, Q> {
name: &str,
args: &[Value],
) -> VmResult<Value> {
let args = HashMap::from([(args.len(), args)]);
let result = self.call_function(store, name, args)?;
let expected = 1;
let actual = result.len();
Expand Down Expand Up @@ -741,9 +750,9 @@ mod tests {
let (env, mut store, _instance) = make_instance(TESTING_GAS_LIMIT);
leave_default_data(&env);

let result = env
.call_function(&mut store, "allocate", &[10u32.into()])
.unwrap();
let args = [Value::from(10u32)];
let args = HashMap::from([(args.len(), &args as &[Value])]);
let result = env.call_function(&mut store, "allocate", args).unwrap();
let ptr = ref_to_u32(&result[0]).unwrap();
assert!(ptr > 0);
}
Expand All @@ -756,7 +765,7 @@ mod tests {
// Clear context's wasmer_instance
env.set_wasmer_instance(None);

let res = env.call_function(&mut store, "allocate", &[]);
let res = env.call_function(&mut store, "allocate", HashMap::new());
match res.unwrap_err() {
VmError::UninitializedContextData { kind, .. } => assert_eq!(kind, "wasmer_instance"),
err => panic!("Unexpected error: {err:?}"),
Expand All @@ -768,7 +777,7 @@ mod tests {
let (env, mut store, _instance) = make_instance(TESTING_GAS_LIMIT);
leave_default_data(&env);

let res = env.call_function(&mut store, "doesnt_exist", &[]);
let res = env.call_function(&mut store, "doesnt_exist", HashMap::new());
match res.unwrap_err() {
VmError::ResolveErr { msg, .. } => {
assert_eq!(msg, "Could not get export: Missing export doesnt_exist");
Expand Down