Implement two last fold iterable usage scenarious (#51)

This commit is contained in:
vms 2020-12-25 16:20:25 +03:00 committed by GitHub
parent 5cb4cc0fb0
commit cdaa24dc03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 242 additions and 89 deletions

14
Cargo.lock generated
View File

@ -70,7 +70,7 @@ dependencies = [
[[package]] [[package]]
name = "aquamarine-vm" name = "aquamarine-vm"
version = "0.1.6" version = "0.1.6"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
dependencies = [ dependencies = [
"fluence-faas 0.1.18 (git+https://github.com/fluencelabs/fce)", "fluence-faas 0.1.18 (git+https://github.com/fluencelabs/fce)",
"maplit", "maplit",
@ -654,7 +654,7 @@ dependencies = [
[[package]] [[package]]
name = "fce" name = "fce"
version = "0.1.14" version = "0.1.14"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
dependencies = [ dependencies = [
"boolinator", "boolinator",
"fce-utils 0.1.0 (git+https://github.com/fluencelabs/fce)", "fce-utils 0.1.0 (git+https://github.com/fluencelabs/fce)",
@ -682,7 +682,7 @@ checksum = "dcdd9d63fa5f87e03514ba8ca3bb91a25121bbf1c63a26df710f166ab8f274f7"
[[package]] [[package]]
name = "fce-utils" name = "fce-utils"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
[[package]] [[package]]
name = "fce-wit-interfaces" name = "fce-wit-interfaces"
@ -697,7 +697,7 @@ dependencies = [
[[package]] [[package]]
name = "fce-wit-interfaces" name = "fce-wit-interfaces"
version = "0.1.9" version = "0.1.9"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
dependencies = [ dependencies = [
"multimap", "multimap",
"wasmer-interface-types-fl", "wasmer-interface-types-fl",
@ -720,7 +720,7 @@ dependencies = [
[[package]] [[package]]
name = "fce-wit-parser" name = "fce-wit-parser"
version = "0.1.11" version = "0.1.11"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"fce-wit-interfaces 0.1.9 (git+https://github.com/fluencelabs/fce)", "fce-wit-interfaces 0.1.9 (git+https://github.com/fluencelabs/fce)",
@ -788,7 +788,7 @@ dependencies = [
[[package]] [[package]]
name = "fluence-faas" name = "fluence-faas"
version = "0.1.18" version = "0.1.18"
source = "git+https://github.com/fluencelabs/fce?branch=master#f022a2dec4229f1dd739794e98a0e5d080ea13d5" source = "git+https://github.com/fluencelabs/fce#f022a2dec4229f1dd739794e98a0e5d080ea13d5"
dependencies = [ dependencies = [
"cmd_lib", "cmd_lib",
"fce 0.1.14 (git+https://github.com/fluencelabs/fce)", "fce 0.1.14 (git+https://github.com/fluencelabs/fce)",
@ -1685,7 +1685,7 @@ dependencies = [
[[package]] [[package]]
name = "stepper-interface" name = "stepper-interface"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/fluencelabs/aquamarine?branch=master#6e5efe4903fa6c89781ef2f20edabca281ff9011" source = "git+https://github.com/fluencelabs/aquamarine#5cb4cc0fb0c149a4bd3160dd0bac9c3d5ac3db7d"
dependencies = [ dependencies = [
"fluence", "fluence",
"serde", "serde",

View File

@ -18,7 +18,7 @@ mod iterable;
mod utils; mod utils;
pub(crate) use iterable::Iterable; pub(crate) use iterable::Iterable;
pub(crate) use iterable::IterableItemType; pub(crate) use iterable::IterableItem;
use super::CallEvidenceCtx; use super::CallEvidenceCtx;
use super::ExecutionCtx; use super::ExecutionCtx;

View File

@ -39,8 +39,11 @@ pub(crate) trait Iterable<'ctx> {
} }
/// Combines all possible iterable item types. /// Combines all possible iterable item types.
///
/// Iterable item is a variable that `fold` sets to each element of the collection it iterates
/// through, i.e., it is the `iterable` in the `(fold collection iterable instruction)` statement.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum IterableItemType<'ctx> { pub(crate) enum IterableItem<'ctx> {
RefRef((&'ctx JValue, &'ctx SecurityTetraplet)), RefRef((&'ctx JValue, &'ctx SecurityTetraplet)),
RefValue((&'ctx JValue, SecurityTetraplet)), RefValue((&'ctx JValue, SecurityTetraplet)),
RcValue((Rc<JValue>, SecurityTetraplet)), RcValue((Rc<JValue>, SecurityTetraplet)),
@ -141,7 +144,7 @@ macro_rules! foldable_prev {
} }
impl<'ctx> Iterable<'ctx> for IterableResolvedCall { impl<'ctx> Iterable<'ctx> for IterableResolvedCall {
type Item = IterableItemType<'ctx>; type Item = IterableItem<'ctx>;
fn next(&mut self) -> bool { fn next(&mut self) -> bool {
foldable_next!(self, self.len) foldable_next!(self, self.len)
@ -170,13 +173,13 @@ impl<'ctx> Iterable<'ctx> for IterableResolvedCall {
_ => unimplemented!("this jvalue is set only by fold instruction, so it must have an array type"), _ => unimplemented!("this jvalue is set only by fold instruction, so it must have an array type"),
}; };
let result = IterableItemType::RefValue((jvalue, tetraplet)); let result = IterableItem::RefValue((jvalue, tetraplet));
Some(result) Some(result)
} }
} }
impl<'ctx> Iterable<'ctx> for IterableVecResolvedCall { impl<'ctx> Iterable<'ctx> for IterableVecResolvedCall {
type Item = IterableItemType<'ctx>; type Item = IterableItem<'ctx>;
fn next(&mut self) -> bool { fn next(&mut self) -> bool {
foldable_next!(self, self.call_results.len()) foldable_next!(self, self.call_results.len())
@ -197,13 +200,13 @@ impl<'ctx> Iterable<'ctx> for IterableVecResolvedCall {
json_path: String::new(), json_path: String::new(),
}; };
let result = IterableItemType::RcValue((result, tetraplet)); let result = IterableItem::RcValue((result, tetraplet));
Some(result) Some(result)
} }
} }
impl<'ctx> Iterable<'ctx> for IterableJsonPathResult { impl<'ctx> Iterable<'ctx> for IterableJsonPathResult {
type Item = IterableItemType<'ctx>; type Item = IterableItem<'ctx>;
fn next(&mut self) -> bool { fn next(&mut self) -> bool {
foldable_next!(self, self.jvalues.len()) foldable_next!(self, self.jvalues.len())
@ -219,14 +222,14 @@ impl<'ctx> Iterable<'ctx> for IterableJsonPathResult {
} }
let jvalue = &self.jvalues[self.cursor]; let jvalue = &self.jvalues[self.cursor];
let result = IterableItemType::RefRef((jvalue, &self.tetraplet)); let result = IterableItem::RefRef((jvalue, &self.tetraplet));
Some(result) Some(result)
} }
} }
impl<'ctx> Iterable<'ctx> for IterableVecJsonPathResult { impl<'ctx> Iterable<'ctx> for IterableVecJsonPathResult {
type Item = IterableItemType<'ctx>; type Item = IterableItem<'ctx>;
fn next(&mut self) -> bool { fn next(&mut self) -> bool {
foldable_next!(self, self.jvalues.len()) foldable_next!(self, self.jvalues.len())
@ -243,7 +246,7 @@ impl<'ctx> Iterable<'ctx> for IterableVecJsonPathResult {
let jvalue = &self.jvalues[self.cursor]; let jvalue = &self.jvalues[self.cursor];
let tetraplet = &self.tetraplets[self.cursor]; let tetraplet = &self.tetraplets[self.cursor];
let result = IterableItemType::RefRef((jvalue, tetraplet)); let result = IterableItem::RefRef((jvalue, tetraplet));
Some(result) Some(result)
} }

View File

@ -16,19 +16,25 @@
use super::iterable::*; use super::iterable::*;
use super::Iterable; use super::Iterable;
use super::IterableItemType; use super::IterableItem;
use crate::air::ExecutionCtx; use crate::air::ExecutionCtx;
use crate::air::JValuable;
use crate::AValue; use crate::AValue;
use crate::AquamarineError; use crate::AquamarineError;
use crate::JValue; use crate::JValue;
use crate::ResolvedCallResult;
use crate::ResolvedTriplet;
use crate::Result; use crate::Result;
use crate::SecurityTetraplet; use crate::SecurityTetraplet;
use air_parser::ast::InstructionValue; use air_parser::ast::InstructionValue;
use jsonpath_lib::select;
use jsonpath_lib::select_with_iter;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc;
pub(super) type IterableValue = Box<dyn for<'ctx> Iterable<'ctx, Item = IterableItemType<'ctx>>>; pub(super) type IterableValue = Box<dyn for<'ctx> Iterable<'ctx, Item = IterableItem<'ctx>>>;
/// Constructs iterable value for given instruction value, /// Constructs iterable value for given instruction value,
/// return Some if iterable isn't empty and None otherwise. /// return Some if iterable isn't empty and None otherwise.
@ -36,10 +42,17 @@ pub(super) fn construct_iterable_value<'ctx>(
value: &InstructionValue<'ctx>, value: &InstructionValue<'ctx>,
exec_ctx: &ExecutionCtx<'ctx>, exec_ctx: &ExecutionCtx<'ctx>,
) -> Result<Option<IterableValue>> { ) -> Result<Option<IterableValue>> {
use AquamarineError::AIRParseError;
match value { match value {
InstructionValue::Variable(name) => handle_instruction_variable(exec_ctx, name), InstructionValue::Variable(name) => handle_instruction_variable(exec_ctx, name),
InstructionValue::JsonPath { variable, path } => handle_instruction_json_path(exec_ctx, variable, path), InstructionValue::JsonPath { variable, path } => handle_instruction_json_path(exec_ctx, variable, path),
_ => unreachable!("it's statically checked that other types of iterable value aren't possible here"), // TODO: check statically that it isn't possible to use string literals and so on as fold iterable
_ => {
return Err(AIRParseError(String::from(
"only variables could be used as fold iterables",
)))
}
} }
} }
@ -47,24 +60,8 @@ fn handle_instruction_variable<'ctx>(
exec_ctx: &ExecutionCtx<'ctx>, exec_ctx: &ExecutionCtx<'ctx>,
variable_name: &str, variable_name: &str,
) -> Result<Option<IterableValue>> { ) -> Result<Option<IterableValue>> {
use AquamarineError::IncompatibleJValueType; let iterable: Option<IterableValue> = match exec_ctx.data_cache.get(variable_name) {
Some(AValue::JValueRef(call_result)) => from_call_result(call_result.clone())?,
let iterable: IterableValue = match exec_ctx.data_cache.get(variable_name) {
Some(AValue::JValueRef(call_result)) => {
let len = match &call_result.result.deref() {
JValue::Array(array) => {
if array.is_empty() {
// skip fold if array is empty
return Ok(None);
}
array.len()
}
v => return Err(IncompatibleJValueType((*v).clone(), "array")),
};
let foldable = IterableResolvedCall::init(call_result.clone(), len);
Box::new(foldable)
}
Some(AValue::JValueAccumulatorRef(acc)) => { Some(AValue::JValueAccumulatorRef(acc)) => {
let acc = acc.borrow(); let acc = acc.borrow();
if acc.is_empty() { if acc.is_empty() {
@ -73,78 +70,123 @@ fn handle_instruction_variable<'ctx>(
let call_results = acc.iter().cloned().collect::<Vec<_>>(); let call_results = acc.iter().cloned().collect::<Vec<_>>();
let foldable = IterableVecResolvedCall::init(call_results); let foldable = IterableVecResolvedCall::init(call_results);
Box::new(foldable) Some(Box::new(foldable))
} }
_ => { Some(AValue::JValueFoldCursor(fold_state)) => {
return Err(AquamarineError::InstructionError(String::from( let iterable_value = fold_state.iterable.peek().unwrap();
"At now, it isn't possible to use fold iterator in other folds", let jvalue = iterable_value.as_jvalue();
))) let result = Rc::new(jvalue.into_owned());
let triplet = as_triplet(&iterable_value);
let call_result = ResolvedCallResult { result, triplet };
from_call_result(call_result)?
} }
_ => return Err(AquamarineError::VariableNotFound(variable_name.to_string())),
}; };
Ok(Some(iterable)) Ok(iterable)
}
/// Constructs iterable value from resolved call result.
fn from_call_result(call_result: ResolvedCallResult) -> Result<Option<IterableValue>> {
use AquamarineError::IncompatibleJValueType;
let len = match &call_result.result.deref() {
JValue::Array(array) => {
if array.is_empty() {
// skip fold if array is empty
return Ok(None);
}
array.len()
}
v => return Err(IncompatibleJValueType((*v).clone(), "array")),
};
let foldable = IterableResolvedCall::init(call_result, len);
let foldable = Box::new(foldable);
Ok(Some(foldable))
} }
fn handle_instruction_json_path<'ctx>( fn handle_instruction_json_path<'ctx>(
exec_ctx: &ExecutionCtx<'ctx>, exec_ctx: &ExecutionCtx<'ctx>,
variable: &str, variable_name: &str,
path: &str, json_path: &str,
) -> Result<Option<IterableValue>> { ) -> Result<Option<IterableValue>> {
use AquamarineError::JValueAccJsonPathError; use AquamarineError::JValueAccJsonPathError;
use AquamarineError::JValueJsonPathError;
let iterable: IterableValue = match exec_ctx.data_cache.get(variable) { let iterable: Option<IterableValue> = match exec_ctx.data_cache.get(variable_name) {
Some(AValue::JValueRef(variable)) => { Some(AValue::JValueRef(variable)) => {
use jsonpath_lib::select; let jvalues = apply_json_path(&variable.result, json_path)?;
from_jvalues(jvalues, variable.triplet.clone(), json_path)
let jvalues = select(&variable.result, path)
.map_err(|e| JValueJsonPathError(variable.result.deref().clone(), path.to_string(), e))?;
let len = jvalues.len();
if len == 0 {
return Ok(None);
}
let jvalues = jvalues.into_iter().cloned().collect();
let tetraplet = SecurityTetraplet {
triplet: variable.triplet.clone(),
json_path: path.to_string(),
};
let foldable = IterableJsonPathResult::init(jvalues, tetraplet);
Box::new(foldable)
} }
Some(AValue::JValueAccumulatorRef(acc)) => { Some(AValue::JValueAccumulatorRef(acc)) => {
use jsonpath_lib::select_with_iter;
let acc = acc.borrow(); let acc = acc.borrow();
if acc.is_empty() { if acc.is_empty() {
return Ok(None); return Ok(None);
} }
let acc_iter = acc.iter().map(|v| v.result.deref()); let acc_iter = acc.iter().map(|v| v.result.deref());
let (jvalues, tetraplet_indices) = select_with_iter(acc_iter, &path) let (jvalues, tetraplet_indices) = select_with_iter(acc_iter, &json_path)
.map_err(|e| JValueAccJsonPathError(acc.clone(), path.to_string(), e))?; .map_err(|e| JValueAccJsonPathError(acc.clone(), json_path.to_string(), e))?;
let jvalues = jvalues.into_iter().cloned().collect(); let jvalues = jvalues.into_iter().cloned().collect();
let tetraplets = tetraplet_indices let tetraplets = tetraplet_indices
.into_iter() .into_iter()
.map(|id| SecurityTetraplet { .map(|id| SecurityTetraplet {
triplet: acc[id].triplet.clone(), triplet: acc[id].triplet.clone(),
json_path: path.to_string(), json_path: json_path.to_string(),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let foldable = IterableVecJsonPathResult::init(jvalues, tetraplets); let foldable = IterableVecJsonPathResult::init(jvalues, tetraplets);
Box::new(foldable) Some(Box::new(foldable))
} }
_ => { Some(AValue::JValueFoldCursor(fold_state)) => {
return Err(AquamarineError::InstructionError(String::from( let iterable_value = fold_state.iterable.peek().unwrap();
"At now, it isn't possible to use fold iterator in other folds", let jvalues = iterable_value.apply_json_path(json_path)?;
))) let triplet = as_triplet(&iterable_value);
from_jvalues(jvalues, triplet, json_path)
} }
_ => return Err(AquamarineError::VariableNotFound(variable_name.to_string())),
}; };
Ok(Some(iterable)) Ok(iterable)
}
fn apply_json_path<'jvalue, 'str>(jvalue: &'jvalue JValue, json_path: &'str str) -> Result<Vec<&'jvalue JValue>> {
use AquamarineError::JValueJsonPathError;
select(jvalue, json_path).map_err(|e| JValueJsonPathError(jvalue.clone(), json_path.to_string(), e))
}
/// Applies json_path to provided jvalues and construct IterableValue from the result and given triplet.
fn from_jvalues(jvalues: Vec<&JValue>, triplet: Rc<ResolvedTriplet>, json_path: &str) -> Option<IterableValue> {
if jvalues.is_empty() {
return None;
}
let jvalues = jvalues.into_iter().cloned().collect();
let tetraplet = SecurityTetraplet {
triplet,
json_path: json_path.to_string(),
};
let foldable = IterableJsonPathResult::init(jvalues, tetraplet);
Some(Box::new(foldable))
}
fn as_triplet(iterable: &IterableItem<'_>) -> Rc<ResolvedTriplet> {
use IterableItem::*;
let tetraplet = match iterable {
RefRef((_, tetraplet)) => tetraplet,
RefValue((_, tetraplet)) => tetraplet,
RcValue((_, tetraplet)) => tetraplet,
};
// clone is cheap here, because triplet is under Rc
Rc::clone(&tetraplet.triplet)
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::air::fold::IterableItemType; use crate::air::fold::IterableItem;
use crate::JValue; use crate::JValue;
use crate::ResolvedCallResult; use crate::ResolvedCallResult;
use crate::Result; use crate::Result;
@ -44,10 +44,10 @@ pub(crate) trait JValuable {
fn as_tetraplets(&self) -> Vec<SecurityTetraplet>; fn as_tetraplets(&self) -> Vec<SecurityTetraplet>;
} }
impl<'ctx> JValuable for IterableItemType<'ctx> { impl<'ctx> JValuable for IterableItem<'ctx> {
fn apply_json_path(&self, json_path: &str) -> Result<Vec<&JValue>> { fn apply_json_path(&self, json_path: &str) -> Result<Vec<&JValue>> {
use crate::AquamarineError::JValueJsonPathError as JsonPathError; use crate::AquamarineError::JValueJsonPathError as JsonPathError;
use IterableItemType::*; use IterableItem::*;
let jvalue = match self { let jvalue = match self {
RefRef((jvalue, _)) => *jvalue, RefRef((jvalue, _)) => *jvalue,
@ -61,7 +61,7 @@ impl<'ctx> JValuable for IterableItemType<'ctx> {
} }
fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec<SecurityTetraplet>)> { fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec<SecurityTetraplet>)> {
use super::fold::IterableItemType::*; use super::fold::IterableItem::*;
use crate::AquamarineError::JValueJsonPathError as JsonPathError; use crate::AquamarineError::JValueJsonPathError as JsonPathError;
let (jvalue, tetraplet) = match self { let (jvalue, tetraplet) = match self {
@ -76,7 +76,7 @@ impl<'ctx> JValuable for IterableItemType<'ctx> {
} }
fn as_jvalue(&self) -> Cow<'_, JValue> { fn as_jvalue(&self) -> Cow<'_, JValue> {
use IterableItemType::*; use IterableItem::*;
match self { match self {
RefRef((jvalue, _)) => Cow::Borrowed(jvalue), RefRef((jvalue, _)) => Cow::Borrowed(jvalue),
@ -86,7 +86,7 @@ impl<'ctx> JValuable for IterableItemType<'ctx> {
} }
fn into_jvalue(self: Box<Self>) -> JValue { fn into_jvalue(self: Box<Self>) -> JValue {
use IterableItemType::*; use IterableItem::*;
match *self { match *self {
RefRef((jvalue, _)) => jvalue.deref().clone(), RefRef((jvalue, _)) => jvalue.deref().clone(),
@ -96,7 +96,7 @@ impl<'ctx> JValuable for IterableItemType<'ctx> {
} }
fn as_tetraplets(&self) -> Vec<SecurityTetraplet> { fn as_tetraplets(&self) -> Vec<SecurityTetraplet> {
use IterableItemType::*; use IterableItem::*;
// these clones are needed because rust-sdk allows passing arguments only by value // these clones are needed because rust-sdk allows passing arguments only by value
match self { match self {

View File

@ -0,0 +1,80 @@
/*
* 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.
*/
use aqua_test_utils::call_vm;
use aqua_test_utils::create_aqua_vm;
use aqua_test_utils::set_variables_call_service;
use serde_json::json;
#[test]
fn network_explore() {
//use stepper_lib::CallResult::*;
//use stepper_lib::EvidenceState::{self, *};
let relay_id = String::from("12D3KooWSpr929UacQSTUWQeK7CQPhcW2TSmLrGTdE1NcFWkuCvY");
let client_id = String::from("12D3KooWEDU1WwGtvHUKpGCaMjhcLWyCUq3MQiRKZBLLFcBVVMck");
let set_variables_state = maplit::hashmap!(
String::from("relay") => json!(relay_id).to_string(),
String::from("client") => json!(client_id).to_string(),
);
let client_call_service = set_variables_call_service(set_variables_state);
let mut client = create_aqua_vm(
client_call_service,
"12D3KooWEDU1WwGtvHUKpGCaMjhcLWyCUq3MQiRKZBLLFcBVVMck",
);
let client_1_id = String::from("12D3KooWFX27Tg3cNJkFk3W2iapnyRhwfwdQ4ZiTucsy1Go3MSGL");
let client_2_id = String::from("12D3KooWGNJoFmCNEHq8NpunB4pZSUh9UBHM53W1NwE7gM8L3RjZ");
let relay_call_service =
aqua_test_utils::set_variable_call_service(format!(r#"["{}", "{}"]"#, client_1_id, client_2_id));
let mut relay = create_aqua_vm(relay_call_service, relay_id.clone());
let client_1_call_service =
aqua_test_utils::set_variable_call_service(format!(r#"["{}", "{}"]"#, relay_id, client_2_id));
let mut client_1 = create_aqua_vm(client_1_call_service, client_1_id.clone());
let client_2_call_service =
aqua_test_utils::set_variable_call_service(format!(r#"["{}", "{}"]"#, relay_id, client_1_id));
let mut client_2 = create_aqua_vm(client_2_call_service, client_2_id.clone());
let script = include_str!("./scripts/network_explore.clj");
let client_res = call_vm!(client, "", script, "[]", "[]");
assert_eq!(client_res.next_peer_pks, vec![relay_id.clone()]);
let relay_res = call_vm!(relay, "", script, "", client_res.data);
assert_eq!(relay_res.next_peer_pks, vec![client_1_id.clone()]);
let client_1_res = call_vm!(client_1, "", script, "", relay_res.data.clone());
assert_eq!(client_1_res.next_peer_pks, vec![client_2_id.clone()]);
let client_2_res = call_vm!(client_2, "", script, "", client_1_res.data.clone());
assert_eq!(client_2_res.next_peer_pks, vec![relay_id.clone()]);
let relay_res = call_vm!(relay, "", script, relay_res.data, client_2_res.data.clone());
assert_eq!(relay_res.next_peer_pks, vec![client_2_id.clone()]);
let client_2_res = call_vm!(client_2, "", script, client_2_res.data, relay_res.data.clone());
assert_eq!(client_2_res.next_peer_pks, vec![relay_id.clone()]);
let relay_res = call_vm!(relay, "", script, relay_res.data, client_2_res.data);
assert_eq!(relay_res.next_peer_pks, vec![client_1_id.clone()]);
let client_1_res = call_vm!(client_1, "", script, client_1_res.data, relay_res.data);
assert_eq!(client_1_res.next_peer_pks, Vec::<String>::new());
}

View File

@ -0,0 +1,28 @@
(seq
(seq
(call "12D3KooWEDU1WwGtvHUKpGCaMjhcLWyCUq3MQiRKZBLLFcBVVMck" ("" "") ["relay"] relay)
(call "12D3KooWEDU1WwGtvHUKpGCaMjhcLWyCUq3MQiRKZBLLFcBVVMck" ("" "") ["client"] client)
)
(seq
(call relay ("dht" "neighborhood") [relay] neighs_top)
(seq
(fold neighs_top n
(seq
(call n ("dht" "neighborhood") [n] neighs_inner[])
(next n)
)
)
(fold neighs_inner ns
(seq
(fold ns n
(seq
(call n ("op" "identify") [] services[])
(next n)
)
)
(next ns)
)
)
)
)
)

View File

@ -397,9 +397,9 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]] [[package]]
name = "jsonpath_lib-fl" name = "jsonpath_lib-fl"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e81233a3c2e1f4579f1fdb856eeec115dcb23817374268212ebad691bd53e664" checksum = "243653439f0992adf0bbf6ed5b798966fdbacd417b9dcb025b50200ec20c17ff"
dependencies = [ dependencies = [
"array_tool", "array_tool",
"env_logger", "env_logger",

View File

@ -389,9 +389,9 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]] [[package]]
name = "jsonpath_lib-fl" name = "jsonpath_lib-fl"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e81233a3c2e1f4579f1fdb856eeec115dcb23817374268212ebad691bd53e664" checksum = "243653439f0992adf0bbf6ed5b798966fdbacd417b9dcb025b50200ec20c17ff"
dependencies = [ dependencies = [
"array_tool", "array_tool",
"env_logger", "env_logger",