Skip to content

Commit

Permalink
Merge #111
Browse files Browse the repository at this point in the history
111: 110 implement async calls r=damip a=Eitu33

#110

Co-authored-by: Thomas Plisson <[email protected]>
  • Loading branch information
bors[bot] and Thomas Plisson authored Mar 16, 2022
2 parents eb50c03 + eb1918d commit 0719439
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 17 deletions.
57 changes: 57 additions & 0 deletions src/abi_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,63 @@ pub(crate) fn assembly_script_get_time(env: &Env) -> ABIResult<i64> {
}
}

/// sends an async message
#[allow(clippy::too_many_arguments)]
pub(crate) fn assembly_script_send_message(
env: &Env,
target_address: i32,
target_handler: i32,
validity_start_period: i64,
validity_start_thread: i32,
validity_end_period: i64,
validity_end_thread: i32,
max_gas: i64,
gas_price: i64,
raw_coins: i64,
data: i32,
) -> ABIResult<()> {
sub_remaining_gas(env, settings::metering_send_message())?;
let validity_start: (u64, u8) = match (
validity_start_period.try_into(),
validity_start_thread.try_into(),
) {
(Ok(p), Ok(t)) => (p, t),
(Err(_), _) => abi_bail!("negative validity start period"),
(_, Err(_)) => abi_bail!("invalid validity start thread"),
};
let validity_end: (u64, u8) = match (
validity_end_period.try_into(),
validity_end_thread.try_into(),
) {
(Ok(p), Ok(t)) => (p, t),
(Err(_), _) => abi_bail!("negative validity end period"),
(_, Err(_)) => abi_bail!("invalid validity end thread"),
};
if max_gas.is_negative() {
abi_bail!("negative max gas");
}
if gas_price.is_negative() {
abi_bail!("negative gas price");
}
if raw_coins.is_negative() {
abi_bail!("negative coins")
}
let memory = get_memory!(env);
match env.interface.send_message(
&get_string(memory, target_address)?,
&get_string(memory, target_handler)?,
validity_start,
validity_end,
max_gas as u64,
gas_price as u64,
raw_coins as u64,
get_string(memory, data)?.as_bytes(),
) {
Err(err) => abi_bail!(err),
Ok(_) => Ok(()),
}
}

/// Tooling, return a StringPtr allocated from a String
fn pointer_from_string(env: &Env, value: &str) -> ABIResult<StringPtr> {
match StringPtr::alloc(&value.into(), &env.wasm_env) {
Expand Down
28 changes: 25 additions & 3 deletions src/execution_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ fn create_instance(limit: u64, module: &[u8], interface: &dyn Interface) -> Resu
"assembly_script_address_from_public_key" => Function::new_native_with_env(&store, env.clone(), assembly_script_address_from_public_key),
"assembly_script_unsafe_random" => Function::new_native_with_env(&store, env.clone(), assembly_script_unsafe_random),
"assembly_script_get_call_coins" => Function::new_native_with_env(&store, env.clone(), assembly_script_get_call_coins),
"assembly_script_get_time" => Function::new_native_with_env(&store, env, assembly_script_get_time),
"assembly_script_get_time" => Function::new_native_with_env(&store, env.clone(), assembly_script_get_time),
"assembly_script_send_message" => Function::new_native_with_env(&store, env, assembly_script_send_message),
},
};
let module = Module::new(&store, &module)?;
Expand Down Expand Up @@ -140,7 +141,7 @@ pub(crate) fn exec(
}
}

/// Library Input, take a`module` wasm builded with the massa environment,
/// Library Input, take a `module` wasm builded with the massa environment,
/// must have a main function inside written in AssemblyScript:
///
/// ```js
Expand All @@ -151,11 +152,32 @@ pub(crate) fn exec(
/// return 0;
/// }
/// ```
pub fn run(module: &[u8], limit: u64, interface: &dyn Interface) -> Result<u64> {
pub fn run_main(module: &[u8], limit: u64, interface: &dyn Interface) -> Result<u64> {
let instance = create_instance(limit, module, interface)?;
if instance.exports.contains(settings::MAIN) {
Ok(exec(limit, Some(instance), module, settings::MAIN, "", interface)?.remaining_gas)
} else {
Ok(limit)
}
}

/// Library Input, take a `module` wasm builded with the massa environment,
/// run a function of that module with the given parameter:
///
/// ```js
/// import { print } from "massa-sc-std";
///
/// export function hello_world(_args: string): i32 {
/// print("hello world");
/// return 0;
/// }
/// ```
pub fn run_function(
module: &[u8],
limit: u64,
function: &str,
param: &str,
interface: &dyn Interface,
) -> Result<u64> {
Ok(exec(limit, None, module, function, param, interface)?.remaining_gas)
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod settings;
mod tunable_memory;
mod types;

pub use execution_impl::run;
pub use execution_impl::{run_function, run_main};
pub use types::*;

#[cfg(test)]
Expand Down
6 changes: 6 additions & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ struct Metering {
pub get_call_coins: u64,
#[cornetto(const, 24)]
pub max_number_of_pages: u32,
#[cornetto(const, 100)]
pub send_message: u64,
}

pub(crate) fn metering_call() -> u64 {
Expand Down Expand Up @@ -165,6 +167,10 @@ pub(crate) fn max_number_of_pages() -> u32 {
METERING.max_number_of_pages()
}

pub(crate) fn metering_send_message() -> u64 {
METERING.send_message()
}

#[cfg(test)]
pub(crate) fn set_metering(call_price: u64) {
METERING._reset(call_price);
Expand Down
27 changes: 14 additions & 13 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// THIS FILE SHOULD TEST THE ABI, NOT THE MOCKED INTERFACE
use crate::{
run, settings,
run_main, settings,
types::{Interface, InterfaceClone},
};
use anyhow::{bail, Result};
Expand Down Expand Up @@ -95,23 +95,23 @@ fn test_caller() {
.update_module("get_string", module.as_ref())
.unwrap();
// test only if the module is valid
run(module, 20_000, &*interface).expect("Failed to run get_string.wat");
run_main(module, 20_000, &*interface).expect("Failed to run_main get_string.wat");
let module = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/caller.wat"
));
let a = run(module, 20_000, &*interface).expect("Failed to run caller.wat");
let a = run_main(module, 20_000, &*interface).expect("Failed to run_main caller.wat");
let prev_call_price = settings::metering_call();
settings::set_metering(0);
let b = run(module, 20_000, &*interface).expect("Failed to run caller.wat");
let b = run_main(module, 20_000, &*interface).expect("Failed to run_main caller.wat");
assert_eq!(a + prev_call_price, b);
let v_out = interface.raw_get_data("").unwrap();
let output = std::str::from_utf8(&v_out).unwrap();
assert_eq!(output, "hello you");

// Test now if we failed if metering is too hight
settings::set_metering(15_000);
run(module, 20_000, &*interface).expect_err("Expected to be out of operation gas");
run_main(module, 20_000, &*interface).expect_err("Expected to be out of operation gas");
}

#[test]
Expand All @@ -129,12 +129,13 @@ fn test_local_hello_name_caller() {
interface
.update_module("get_string", module.as_ref())
.unwrap();
run(module, 100, &*interface).expect("Failed to run get_string.wat");
run_main(module, 100, &*interface).expect("Failed to run_main get_string.wat");
let module = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/local_hello_name_caller.wat"
));
run(module, 20_000, &*interface).expect_err("Succeeded to run local_hello_name_caller.wat");
run_main(module, 20_000, &*interface)
.expect_err("Succeeded to run_main local_hello_name_caller.wat");
}

#[test]
Expand All @@ -148,12 +149,12 @@ fn test_module_creation() {
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/create_sc.wasm"
));
run(module, 100_000, &*interface).expect("Failed to run create_sc.wat");
run_main(module, 100_000, &*interface).expect("Failed to run_main create_sc.wat");
let module = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/caller.wat"
));
run(module, 20_000, &*interface).expect("Failed to run caller.wat");
run_main(module, 20_000, &*interface).expect("Failed to run_main caller.wat");
}

#[test]
Expand All @@ -167,12 +168,12 @@ fn test_not_enough_gas_error() {
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/create_sc.wasm"
));
run(module, 100_000, &*interface).expect("Failed to run create_sc.wat");
run_main(module, 100_000, &*interface).expect("Failed to run_main create_sc.wat");
let module = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/caller.wat"
));
match run(module, 10000, &*interface) {
match run_main(module, 10000, &*interface) {
Ok(_) => panic!("Shouldn't pass successfully =-("),
Err(err) => {
assert!(err
Expand All @@ -184,13 +185,13 @@ fn test_not_enough_gas_error() {

#[test]
#[serial]
fn test_run_without_main() {
fn test_run_main_without_main() {
settings::reset_metering();
let interface: Box<dyn Interface> =
Box::new(TestInterface(Arc::new(Mutex::new(Ledger::new()))));
let module = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/wasm/build/no_main.wasm"
));
run(module, 100_000, &*interface).expect_err("An error should spawn here");
run_main(module, 100_000, &*interface).expect_err("An error should spawn here");
}
28 changes: 28 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,34 @@ pub trait Interface: Send + Sync + InterfaceClone {
fn generate_event(&self, _event: String) -> Result<()> {
unimplemented!("generate_event")
}

/// Sends an async message
///
/// # Arguments
///
/// * `target_address` - Destination address hash in format string
/// * `target_handler` - Name of the message handling function
/// * `validity_start` - Tuple containing the period and thread of the validity start slot
/// * `validity_end` - Tuple containing the period and thread of the validity end slot
/// * `max_gas` - Maximum gas for the message execution
/// * `gas_price` - Price of one gas unit
/// * `coins` - Coins of the sender
/// * `data` - Message data
///
#[allow(clippy::too_many_arguments)]
fn send_message(
&self,
target_address: &str,
target_handler: &str,
validity_start: (u64, u8),
validity_end: (u64, u8),
max_gas: u64,
gas_price: u64,
raw_coins: u64,
data: &[u8],
) -> Result<()> {
unimplemented!("send_message")
}
}

impl dyn Interface {
Expand Down

0 comments on commit 0719439

Please sign in to comment.