2020-10-08 12:43:23 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2020 Fluence Labs Limited
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#![warn(rust_2018_idioms)]
|
|
|
|
#![deny(
|
|
|
|
dead_code,
|
|
|
|
nonstandard_style,
|
|
|
|
unused_imports,
|
|
|
|
unused_mut,
|
|
|
|
unused_variables,
|
|
|
|
unused_unsafe,
|
|
|
|
unreachable_patterns
|
|
|
|
)]
|
|
|
|
|
2021-05-16 22:52:22 +03:00
|
|
|
pub mod executed_state;
|
|
|
|
|
2021-05-10 14:25:34 +03:00
|
|
|
pub use avm_server::ne_vec::NEVec;
|
|
|
|
pub use avm_server::AVMConfig;
|
|
|
|
pub use avm_server::AVMError;
|
|
|
|
pub use avm_server::CallServiceClosure;
|
|
|
|
pub use avm_server::IType;
|
|
|
|
pub use avm_server::IValue;
|
|
|
|
pub use avm_server::InterpreterOutcome;
|
|
|
|
pub use avm_server::ParticleParameters;
|
|
|
|
pub use avm_server::AVM;
|
2020-10-08 12:43:23 +03:00
|
|
|
|
2021-05-16 22:52:22 +03:00
|
|
|
pub use air::execution_trace::ExecutionTrace;
|
|
|
|
|
2020-10-30 20:29:05 +03:00
|
|
|
use std::collections::HashMap;
|
2020-10-08 12:43:23 +03:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
2021-05-16 22:52:22 +03:00
|
|
|
pub(self) type JValue = serde_json::Value;
|
2020-10-30 20:29:05 +03:00
|
|
|
|
2021-05-10 14:25:34 +03:00
|
|
|
pub fn create_avm(call_service: CallServiceClosure, current_peer_id: impl Into<String>) -> AVM {
|
2020-10-30 20:29:05 +03:00
|
|
|
let tmp_dir = std::env::temp_dir();
|
|
|
|
|
2021-05-10 14:25:34 +03:00
|
|
|
let config = AVMConfig {
|
|
|
|
air_wasm_path: PathBuf::from("../target/wasm32-wasi/debug/air_interpreter_server.wasm"),
|
2020-12-28 00:12:11 +03:00
|
|
|
call_service,
|
2020-10-15 17:31:56 +03:00
|
|
|
current_peer_id: current_peer_id.into(),
|
2021-06-30 18:58:54 +03:00
|
|
|
vault_dir: tmp_dir.join("vault"),
|
2020-10-30 20:29:05 +03:00
|
|
|
particle_data_store: tmp_dir,
|
2021-06-30 18:58:54 +03:00
|
|
|
logging_mask: i32::MAX,
|
2020-10-08 12:43:23 +03:00
|
|
|
};
|
|
|
|
|
2021-05-10 14:25:34 +03:00
|
|
|
AVM::new(config).expect("vm should be created")
|
2020-10-08 12:43:23 +03:00
|
|
|
}
|
|
|
|
|
2020-12-28 00:12:11 +03:00
|
|
|
pub fn unit_call_service() -> CallServiceClosure {
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(|_| -> Option<IValue> {
|
2020-10-08 12:43:23 +03:00
|
|
|
Some(IValue::Record(
|
2021-01-12 13:04:25 +03:00
|
|
|
NEVec::new(vec![
|
2020-10-08 12:43:23 +03:00
|
|
|
IValue::S32(0),
|
|
|
|
IValue::String(String::from("\"test\"")),
|
|
|
|
])
|
|
|
|
.unwrap(),
|
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-12-28 00:12:11 +03:00
|
|
|
pub fn echo_string_call_service() -> CallServiceClosure {
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(|args| -> Option<IValue> {
|
|
|
|
let arg = match &args.function_args[2] {
|
2020-10-08 12:43:23 +03:00
|
|
|
IValue::String(str) => str,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let arg: Vec<String> = serde_json::from_str(arg).unwrap();
|
2021-02-11 15:39:37 +03:00
|
|
|
let arg = serde_json::to_string(&arg[0]).unwrap();
|
2020-10-08 12:43:23 +03:00
|
|
|
|
|
|
|
Some(IValue::Record(
|
2021-02-11 15:39:37 +03:00
|
|
|
NEVec::new(vec![IValue::S32(0), IValue::String(arg)]).unwrap(),
|
2020-10-08 12:43:23 +03:00
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-12-28 00:12:11 +03:00
|
|
|
pub fn echo_number_call_service() -> CallServiceClosure {
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(|args| -> Option<IValue> {
|
|
|
|
let arg = match &args.function_args[2] {
|
2020-10-08 12:43:23 +03:00
|
|
|
IValue::String(str) => str,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let arg: Vec<String> = serde_json::from_str(arg).unwrap();
|
|
|
|
|
|
|
|
Some(IValue::Record(
|
2021-01-12 13:04:25 +03:00
|
|
|
NEVec::new(vec![IValue::S32(0), IValue::String(arg[0].clone())]).unwrap(),
|
2020-10-08 12:43:23 +03:00
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
2020-10-30 20:29:05 +03:00
|
|
|
|
2020-12-28 00:12:11 +03:00
|
|
|
pub fn set_variable_call_service(json: impl Into<String>) -> CallServiceClosure {
|
2020-10-30 20:29:05 +03:00
|
|
|
let json = json.into();
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(move |_| -> Option<IValue> {
|
2020-10-30 20:29:05 +03:00
|
|
|
Some(IValue::Record(
|
2021-01-12 13:04:25 +03:00
|
|
|
NEVec::new(vec![IValue::S32(0), IValue::String(json.clone())]).unwrap(),
|
2020-10-30 20:29:05 +03:00
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-12-28 00:12:11 +03:00
|
|
|
pub fn set_variables_call_service(ret_mapping: HashMap<String, String>) -> CallServiceClosure {
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(move |args| -> Option<IValue> {
|
|
|
|
let arg_name = match &args.function_args[2] {
|
2020-10-30 20:29:05 +03:00
|
|
|
IValue::String(json_str) => {
|
|
|
|
let json = serde_json::from_str(json_str).expect("a valid json");
|
|
|
|
match json {
|
|
|
|
JValue::Array(array) => match array.first() {
|
|
|
|
Some(JValue::String(str)) => str.to_string(),
|
|
|
|
_ => String::from("default"),
|
|
|
|
},
|
|
|
|
_ => String::from("default"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => String::from("default"),
|
|
|
|
};
|
|
|
|
|
|
|
|
let result = ret_mapping
|
|
|
|
.get(&arg_name)
|
|
|
|
.cloned()
|
2020-12-22 21:05:04 +03:00
|
|
|
.unwrap_or_else(|| String::from(r#""test""#));
|
2020-10-30 20:29:05 +03:00
|
|
|
|
|
|
|
Some(IValue::Record(
|
2021-01-12 13:04:25 +03:00
|
|
|
NEVec::new(vec![IValue::S32(0), IValue::String(result)]).unwrap(),
|
2020-10-30 20:29:05 +03:00
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-02-16 20:04:00 +03:00
|
|
|
pub fn fallible_call_service(fallible_service_id: impl Into<String>) -> CallServiceClosure {
|
|
|
|
let fallible_service_id = fallible_service_id.into();
|
|
|
|
|
2021-06-30 18:58:54 +03:00
|
|
|
Box::new(move |args| -> Option<IValue> {
|
|
|
|
let builtin_service = match &args.function_args[0] {
|
2021-02-16 20:04:00 +03:00
|
|
|
IValue::String(str) => str,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
|
|
|
|
// return a error for service with such id
|
|
|
|
if builtin_service == &fallible_service_id {
|
|
|
|
Some(IValue::Record(
|
|
|
|
NEVec::new(vec![IValue::S32(1), IValue::String(String::from("error"))]).unwrap(),
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
// return success for services with other ids
|
|
|
|
Some(IValue::Record(
|
|
|
|
NEVec::new(vec![
|
|
|
|
IValue::S32(0),
|
|
|
|
IValue::String(String::from(r#""res""#)),
|
|
|
|
])
|
|
|
|
.unwrap(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-10-30 20:29:05 +03:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! call_vm {
|
2020-11-11 14:31:53 +03:00
|
|
|
($vm:expr, $init_peer_id:expr, $script:expr, $prev_data:expr, $data:expr) => {
|
|
|
|
match $vm.call_with_prev_data($init_peer_id, $script, $prev_data, $data) {
|
2020-11-03 17:43:58 +03:00
|
|
|
Ok(v) => v,
|
|
|
|
Err(err) => panic!("VM call failed: {}", err),
|
|
|
|
}
|
2020-10-30 20:29:05 +03:00
|
|
|
};
|
|
|
|
}
|