From 724117547205d8ccc742d325b542af8f3df801b8 Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 22 Dec 2020 21:05:04 +0300 Subject: [PATCH] Introduce security tetraplets (#32) --- .circleci/config.yml | 11 +- Cargo.lock | 222 +++- Cargo.toml | 9 +- crates/air-parser/Cargo.toml | 2 +- crates/air-parser/src/ast.rs | 20 +- crates/air-parser/src/lalrpop/aqua.lalrpop | 27 +- crates/air-parser/src/lalrpop/aqua.rs | 497 ++++----- crates/air-parser/src/lalrpop/tests.rs | 58 +- crates/polyplets/Cargo.toml | 13 + crates/polyplets/src/lib.rs | 32 + crates/polyplets/src/tetraplet.rs | 52 + crates/polyplets/src/triplet.rs | 27 + crates/stepper-interface/Cargo.toml | 2 +- crates/test-module/Cargo.toml | 2 +- crates/test-module/src/main.rs | 11 +- crates/test-utils/Cargo.toml | 2 +- crates/test-utils/src/lib.rs | 6 +- stepper-lib/Cargo.toml | 6 +- stepper-lib/src/air/call.rs | 79 +- stepper-lib/src/air/call/parsed_call.rs | 161 --- stepper-lib/src/air/call/resolved_call.rs | 167 +++ stepper-lib/src/air/call/triplet.rs | 81 +- stepper-lib/src/air/call/utils.rs | 75 +- stepper-lib/src/air/execution_context.rs | 4 +- stepper-lib/src/air/fold.rs | 147 +-- stepper-lib/src/air/fold/iterable.rs | 250 +++++ stepper-lib/src/air/fold/jvaluable_result.rs | 201 ++++ stepper-lib/src/air/fold/utils.rs | 149 +++ stepper-lib/src/air/resolve.rs | 126 +-- stepper-lib/src/air/xor.rs | 22 +- stepper-lib/src/build_targets/fce_target.rs | 14 +- .../src/build_targets/wasm_bindgen_target.rs | 12 +- stepper-lib/src/call_evidence/context.rs | 7 + stepper-lib/src/call_evidence/state.rs | 2 +- stepper-lib/src/errors.rs | 44 +- stepper-lib/src/lib.rs | 23 +- stepper-lib/src/stepper_outcome.rs | 34 + stepper-lib/tests/air_basic.rs | 23 +- stepper-lib/tests/build_test_binaries.sh | 10 + stepper-lib/tests/call_evidence_basic.rs | 23 +- stepper-lib/tests/dashboard.rs | 2 +- stepper-lib/tests/scripts/create_service.clj | 19 + .../script.clj => scripts/dashboard.clj} | 0 stepper-lib/tests/security_tetraplets.rs | 301 ++++++ .../auth_module/Cargo.lock | 960 ++++++++++++++++++ .../auth_module/Cargo.toml | 15 + .../auth_module/src/main.rs | 43 + .../log_storage/Cargo.lock | 960 ++++++++++++++++++ .../log_storage/Cargo.toml | 15 + .../log_storage/src/main.rs | 41 + stepper/Cargo.toml | 3 +- 51 files changed, 4168 insertions(+), 844 deletions(-) create mode 100644 crates/polyplets/Cargo.toml create mode 100644 crates/polyplets/src/lib.rs create mode 100644 crates/polyplets/src/tetraplet.rs create mode 100644 crates/polyplets/src/triplet.rs delete mode 100644 stepper-lib/src/air/call/parsed_call.rs create mode 100644 stepper-lib/src/air/call/resolved_call.rs create mode 100644 stepper-lib/src/air/fold/iterable.rs create mode 100644 stepper-lib/src/air/fold/jvaluable_result.rs create mode 100644 stepper-lib/src/air/fold/utils.rs create mode 100644 stepper-lib/src/stepper_outcome.rs create mode 100755 stepper-lib/tests/build_test_binaries.sh create mode 100644 stepper-lib/tests/scripts/create_service.clj rename stepper-lib/tests/{dashboard/script.clj => scripts/dashboard.clj} (100%) create mode 100644 stepper-lib/tests/security_tetraplets.rs create mode 100644 stepper-lib/tests/security_tetraplets/auth_module/Cargo.lock create mode 100644 stepper-lib/tests/security_tetraplets/auth_module/Cargo.toml create mode 100644 stepper-lib/tests/security_tetraplets/auth_module/src/main.rs create mode 100644 stepper-lib/tests/security_tetraplets/log_storage/Cargo.lock create mode 100644 stepper-lib/tests/security_tetraplets/log_storage/Cargo.toml create mode 100644 stepper-lib/tests/security_tetraplets/log_storage/src/main.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 4042c7ae..04dfcefe 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,10 +21,13 @@ jobs: rustup component add clippy cargo install fcli - cd stepper - fce build --features fce - cd .. + # build a Wasm binary for stepper + (cd stepper; fce build --features fce) + + # build Wasm binaries for tests + (cd stepper-lib/tests/; ./build_test_binaries.sh) + cargo fmt --all -- --check --color always cargo check cargo test --release @@ -37,6 +40,6 @@ jobs: key: aqua01-{{ checksum "Cargo.lock" }} workflows: version: 2 - arqada: + aqua: jobs: - aqua diff --git a/Cargo.lock b/Cargo.lock index 47c3edfa..de9d4c82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,7 +42,7 @@ checksum = "68803225a7b13e47191bab76f2687382b60d259e8cf37f6e1893658b84bb9479" name = "aqua-test-module" version = "0.1.0" dependencies = [ - "fluence", + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -50,7 +50,7 @@ name = "aqua-test-utils" version = "0.1.0" dependencies = [ "aquamarine-vm", - "fluence", + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json", ] @@ -58,8 +58,9 @@ dependencies = [ name = "aquamarine" version = "0.1.3" dependencies = [ - "fluence", + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log", + "serde", "serde_json", "stepper-interface 0.1.0", "stepper-lib", @@ -68,14 +69,14 @@ dependencies = [ [[package]] name = "aquamarine-vm" -version = "0.1.3" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +version = "0.1.5" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" dependencies = [ - "fluence-faas", + "fluence-faas 0.1.17 (git+https://github.com/fluencelabs/fce)", "maplit", "serde", "serde_json", - "stepper-interface 0.1.0 (git+https://github.com/fluencelabs/aquamarine?branch=wit)", + "stepper-interface 0.1.0 (git+https://github.com/fluencelabs/aquamarine)", ] [[package]] @@ -629,13 +630,36 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fce" -version = "0.1.13" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +version = "0.1.14" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" dependencies = [ "boolinator", - "fce-utils", - "fce-wit-interfaces", - "fce-wit-parser", + "fce-utils 0.1.0 (git+https://github.com/fluencelabs/fce)", + "fce-wit-interfaces 0.1.9 (git+https://github.com/fluencelabs/fce)", + "fce-wit-parser 0.1.11 (git+https://github.com/fluencelabs/fce)", + "log", + "multi-map", + "multimap", + "parity-wasm", + "pwasm-utils", + "safe-transmute", + "serde", + "wasmer-interface-types-fl", + "wasmer-runtime-core-fl", + "wasmer-runtime-fl", + "wasmer-wasi-fl", +] + +[[package]] +name = "fce" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6101e9c7bd51f7478c41c2c1ce2405ef9e87fac5576c012877d5a9feed628a61" +dependencies = [ + "boolinator", + "fce-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fce-wit-interfaces 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fce-wit-parser 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log", "multi-map", "multimap", @@ -652,12 +676,28 @@ dependencies = [ [[package]] name = "fce-utils" version = "0.1.0" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" + +[[package]] +name = "fce-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdd9d63fa5f87e03514ba8ca3bb91a25121bbf1c63a26df710f166ab8f274f7" [[package]] name = "fce-wit-interfaces" -version = "0.1.8" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +version = "0.1.9" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" +dependencies = [ + "multimap", + "wasmer-interface-types-fl", +] + +[[package]] +name = "fce-wit-interfaces" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fcd89f62accf83a87dbea298caaed542b6c556380103116b6b89717382a8f21" dependencies = [ "multimap", "wasmer-interface-types-fl", @@ -665,11 +705,25 @@ dependencies = [ [[package]] name = "fce-wit-parser" -version = "0.1.10" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +version = "0.1.11" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" dependencies = [ "anyhow", - "fce-wit-interfaces", + "fce-wit-interfaces 0.1.9 (git+https://github.com/fluencelabs/fce)", + "serde", + "walrus", + "wasmer-interface-types-fl", + "wasmer-runtime-core-fl", +] + +[[package]] +name = "fce-wit-parser" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064d9e93e4b588385e77582be61b6d7aaeb352b0af7b33ab9807d61ee606f4e5" +dependencies = [ + "anyhow", + "fce-wit-interfaces 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "walrus", "wasmer-interface-types-fl", @@ -684,22 +738,71 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "fluence" -version = "0.2.12" -source = "git+https://github.com/fluencelabs/rust-sdk#a555291c1ceca0b9c959240e1d311d0e3309eda3" +version = "0.2.13" +source = "git+https://github.com/fluencelabs/rust-sdk#71591f412cb65879d74e8c38838e827ab74d8802" dependencies = [ - "fluence-sdk-macro 0.2.12 (git+https://github.com/fluencelabs/rust-sdk)", - "fluence-sdk-main 0.2.12 (git+https://github.com/fluencelabs/rust-sdk)", + "fluence-sdk-macro 0.2.13 (git+https://github.com/fluencelabs/rust-sdk)", + "fluence-sdk-main 0.2.13 (git+https://github.com/fluencelabs/rust-sdk)", +] + +[[package]] +name = "fluence" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "083f40a5d000b28b74f10d824925eccf1fbdf6dbb8881e6d052c6183b2bc615e" +dependencies = [ + "fluence-sdk-macro 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "fluence-sdk-main 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fluence-app-service" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5d68695059de51743eddcd98a0ba77ec3af7fa51b2eb5fcb35edce05ff1144" +dependencies = [ + "fluence-faas 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "maplit", + "serde", + "serde_derive", + "serde_json", + "toml", + "wasmer-wasi-fl", ] [[package]] name = "fluence-faas" -version = "0.1.15" -source = "git+https://github.com/fluencelabs/fce#a039973835aed5c7c93a13e0b0c03e6632816e65" +version = "0.1.17" +source = "git+https://github.com/fluencelabs/fce#725f6e65f32b8503faae49c875187db6fbdc3d1e" dependencies = [ "cmd_lib", - "fce", - "fce-utils", - "fluence-sdk-main 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fce 0.1.14 (git+https://github.com/fluencelabs/fce)", + "fce-utils 0.1.0 (git+https://github.com/fluencelabs/fce)", + "fluence-sdk-main 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools", + "log", + "safe-transmute", + "serde", + "serde_derive", + "serde_json", + "toml", + "wasmer-interface-types-fl", + "wasmer-runtime-core-fl", + "wasmer-runtime-fl", + "wasmer-wasi-fl", +] + +[[package]] +name = "fluence-faas" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e1bc2abb01e97b5c1ce975d1b9b0e13582a4aa42cecfeb5e23879bc2a1ac3b" +dependencies = [ + "cmd_lib", + "fce 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "fce-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fluence-sdk-main 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "itertools", "log", "safe-transmute", @@ -715,47 +818,46 @@ dependencies = [ [[package]] name = "fluence-sdk-macro" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44e1668ecf3d45026bae6dd7a8e4045a9b1742a4f30db205954802e74cbcc4c" +version = "0.2.13" +source = "git+https://github.com/fluencelabs/rust-sdk#71591f412cb65879d74e8c38838e827ab74d8802" dependencies = [ - "fluence-sdk-wit 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fluence-sdk-wit 0.2.13 (git+https://github.com/fluencelabs/rust-sdk)", ] [[package]] name = "fluence-sdk-macro" -version = "0.2.12" -source = "git+https://github.com/fluencelabs/rust-sdk#a555291c1ceca0b9c959240e1d311d0e3309eda3" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f79abced6cdfdd7089b0accad0d9c760bf9d2e82ae1bec851383e061cb40790" dependencies = [ - "fluence-sdk-wit 0.2.12 (git+https://github.com/fluencelabs/rust-sdk)", + "fluence-sdk-wit 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fluence-sdk-main" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71397005d09f96b188f33d1189d0fd2163fe54882b57979ddbdcdc28167e1107" +version = "0.2.13" +source = "git+https://github.com/fluencelabs/rust-sdk#71591f412cb65879d74e8c38838e827ab74d8802" dependencies = [ - "fluence-sdk-macro 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fluence-sdk-macro 0.2.13 (git+https://github.com/fluencelabs/rust-sdk)", "log", "serde", ] [[package]] name = "fluence-sdk-main" -version = "0.2.12" -source = "git+https://github.com/fluencelabs/rust-sdk#a555291c1ceca0b9c959240e1d311d0e3309eda3" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2348d5b5000012f9da835e52f7473e08dff6345e9beba2e80a91b801e48ac0b6" dependencies = [ - "fluence-sdk-macro 0.2.12 (git+https://github.com/fluencelabs/rust-sdk)", + "fluence-sdk-macro 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log", "serde", ] [[package]] name = "fluence-sdk-wit" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa333b56081139078aa62d9d5e6ac8ed5fb49578139788740742c1c7e1b4c112" +version = "0.2.13" +source = "git+https://github.com/fluencelabs/rust-sdk#71591f412cb65879d74e8c38838e827ab74d8802" dependencies = [ "proc-macro2", "quote", @@ -767,8 +869,9 @@ dependencies = [ [[package]] name = "fluence-sdk-wit" -version = "0.2.12" -source = "git+https://github.com/fluencelabs/rust-sdk#a555291c1ceca0b9c959240e1d311d0e3309eda3" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da5f51cddeae52ff5b91d1a5d8be90e54629f4887f89f8d7501b829b374fe6a" dependencies = [ "proc-macro2", "quote", @@ -977,9 +1080,8 @@ dependencies = [ [[package]] name = "jsonpath_lib" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a" +version = "0.2.5" +source = "git+https://github.com/fluencelabs/jsonpath?branch=fluence#538b433ae2ccbd882ff02fcff22ea16be779fb6f" dependencies = [ "array_tool", "env_logger", @@ -1262,6 +1364,14 @@ dependencies = [ "web-sys", ] +[[package]] +name = "polyplets" +version = "0.1.0" +dependencies = [ + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1370,9 +1480,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "7.0.3" +version = "7.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" +checksum = "beb71f708fe39b2c5e98076204c3cc094ee5a4c12c4cdb119a2b72dc34164f41" dependencies = [ "bitflags", "cc", @@ -1605,8 +1715,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stepper-interface" version = "0.1.0" +source = "git+https://github.com/fluencelabs/aquamarine#b967a63abca9742d6764e9b27926025d5e2b2efb" dependencies = [ - "fluence", + "fluence 0.2.13 (git+https://github.com/fluencelabs/rust-sdk)", "serde", "wasmer-interface-types-fl", ] @@ -1614,9 +1725,8 @@ dependencies = [ [[package]] name = "stepper-interface" version = "0.1.0" -source = "git+https://github.com/fluencelabs/aquamarine?branch=wit#839008fb8b42abe4cab18f85db49766341a52326" dependencies = [ - "fluence", + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "wasmer-interface-types-fl", ] @@ -1631,11 +1741,13 @@ dependencies = [ "criterion", "csv", "env_logger", - "fluence", + "fluence 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "fluence-app-service", "jsonpath_lib", "log", "maplit", "once_cell", + "polyplets", "pretty_assertions", "serde", "serde_derive", diff --git a/Cargo.toml b/Cargo.toml index 0f39de8a..efa284ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,19 @@ [workspace] members = [ "crates/air-parser", + "crates/polyplets", "crates/stepper-interface", "crates/test-module", "crates/test-utils", "stepper", - "stepper-lib", + "stepper-lib" ] -exclude = [ "crates/air-interpreter-wasm" ] +exclude = [ + "crates/air-interpreter-wasm", + "stepper-lib/tests/security_tetraplets/auth_module", + "stepper-lib/tests/security_tetraplets/log_storage", +] [profile.release] opt-level = 3 diff --git a/crates/air-parser/Cargo.toml b/crates/air-parser/Cargo.toml index f1df1663..db392421 100644 --- a/crates/air-parser/Cargo.toml +++ b/crates/air-parser/Cargo.toml @@ -14,7 +14,7 @@ codespan = "0.9.5" codespan-reporting = "0.9.5" # TODO: hide serde behind feature -serde = "1.0.117" +serde = { version = "1.0.117", features = ["rc"] } [dev-dependencies] fstrings = "0.2.3" diff --git a/crates/air-parser/src/ast.rs b/crates/air-parser/src/ast.rs index 795e8754..c323ebe9 100644 --- a/crates/air-parser/src/ast.rs +++ b/crates/air-parser/src/ast.rs @@ -14,7 +14,9 @@ * limitations under the License. */ +use serde::Deserialize; use serde::Serialize; + use std::rc::Rc; #[allow(clippy::large_enum_variant)] // for Null and Error variants @@ -32,26 +34,26 @@ pub enum Instruction<'i> { #[derive(Serialize, Debug, PartialEq, Eq)] pub enum PeerPart<'i> { - PeerPk(Value<'i>), - PeerPkWithServiceId(Value<'i>, Value<'i>), + PeerPk(InstructionValue<'i>), + PeerPkWithServiceId(InstructionValue<'i>, InstructionValue<'i>), } #[derive(Serialize, Debug, PartialEq, Eq)] pub enum FunctionPart<'i> { - FuncName(Value<'i>), - ServiceIdWithFuncName(Value<'i>, Value<'i>), + FuncName(InstructionValue<'i>), + ServiceIdWithFuncName(InstructionValue<'i>, InstructionValue<'i>), } #[derive(Serialize, Debug, PartialEq, Eq)] pub struct Call<'i> { pub peer_part: PeerPart<'i>, pub function_part: FunctionPart<'i>, - pub args: Vec>, + pub args: Rc>>, pub output: CallOutput<'i>, } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] -pub enum Value<'i> { +#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)] +pub enum InstructionValue<'i> { Variable(&'i str), Literal(&'i str), JsonPath { variable: &'i str, path: &'i str }, @@ -59,7 +61,7 @@ pub enum Value<'i> { InitPeerId, } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Serialize, Debug, Hash, PartialEq, Eq, Clone)] pub enum CallOutput<'i> { Scalar(&'i str), Accumulator(&'i str), @@ -77,7 +79,7 @@ pub struct Xor<'i>(pub Box>, pub Box>); #[derive(Serialize, Debug, PartialEq, Eq)] pub struct Fold<'i> { - pub iterable: Value<'i>, + pub iterable: InstructionValue<'i>, pub iterator: &'i str, pub instruction: Rc>, } diff --git a/crates/air-parser/src/lalrpop/aqua.lalrpop b/crates/air-parser/src/lalrpop/aqua.lalrpop index 7268c074..00c269d2 100644 --- a/crates/air-parser/src/lalrpop/aqua.lalrpop +++ b/crates/air-parser/src/lalrpop/aqua.lalrpop @@ -17,10 +17,11 @@ pub Instr: Box> = { "(" "call" ")" => { let output = output.unwrap_or(CallOutput::None); + let args = Rc::new(args); Box::new(Instruction::Call(Call{peer_part: p, function_part: f, args, output})) }, - "(" "fold" ")" => { + "(" "fold" ")" => { let instruction = Rc::new(*i); Box::new(Instruction::Fold(Fold{ iterable, iterator, instruction })) }, @@ -30,7 +31,7 @@ pub Instr: Box> = { ! => { errors.push(<>); Box::new(Instruction::Error) }, } -Args: Vec> = { +Args: Vec> = { "[" )*> "]" => args } @@ -51,23 +52,23 @@ Output: CallOutput<'input> = { => CallOutput::Accumulator(&o[..o.len()-2]), }; -Function = Value; -PeerId = Value; -ServiceId = Value; -Arg = Value; +Function = InstructionValue; +PeerId = InstructionValue; +ServiceId = InstructionValue; +Arg = InstructionValue; -Value: Value<'input> = { - "\"" "\"" => Value::Literal(""), // TODO: signal absence somehow? - "\"" "\"" => Value::Literal(v), - => Value::Variable(v), +InstructionValue: InstructionValue<'input> = { + "\"" "\"" => InstructionValue::Literal(""), // TODO: signal absence somehow? + "\"" "\"" => InstructionValue::Literal(v), + => InstructionValue::Variable(v), => { let mut path = v.splitn(2, "."); let variable = path.next().expect("must contain dot"); let path = path.next().expect("contain component after dot"); - Value::JsonPath { variable, path } + InstructionValue::JsonPath { variable, path } }, - CURRENT_PEER_ID => Value::CurrentPeerId, - INIT_PEER_ID => Value::InitPeerId, + CURRENT_PEER_ID => InstructionValue::CurrentPeerId, + INIT_PEER_ID => InstructionValue::InitPeerId, } diff --git a/crates/air-parser/src/lalrpop/aqua.rs b/crates/air-parser/src/lalrpop/aqua.rs index 1afbc0d3..2148a3a6 100644 --- a/crates/air-parser/src/lalrpop/aqua.rs +++ b/crates/air-parser/src/lalrpop/aqua.rs @@ -1,5 +1,5 @@ // auto-generated: "lalrpop 0.19.1" -// sha256: 277841baab4e6580203330bf544b74ea91f8e86d259cbf2ec9dd7e33b059e5ce +// sha256: 237333575ccdd2fa95ee13e3e744cfc521444ca39a3a6a4451ed66ec0d4a1 use crate::ast::*; use crate::lalrpop::parser::InstructionError; use lalrpop_util::ErrorRecovery; @@ -27,9 +27,9 @@ mod __parse__Instr { { Variant0(&'input str), Variant1(__lalrpop_util::ErrorRecovery, InstructionError>), - Variant2(Value<'input>), - Variant3(::std::vec::Vec>), - Variant4(Vec>), + Variant2(InstructionValue<'input>), + Variant3(::std::vec::Vec>), + Variant4(Vec>), Variant5(FunctionPart<'input>), Variant6(Box>), Variant7(CallOutput<'input>), @@ -90,19 +90,19 @@ mod __parse__Instr { // State 25 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 26 - -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, 0, 0, 0, -32, -32, -32, -32, 0, + -24, -24, -24, -24, -24, 0, 0, 0, 0, 0, 0, 0, 0, -24, -24, -24, -24, 0, // State 27 - -27, -27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -27, -27, -27, -27, 0, + -32, -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -32, -32, -32, -32, 0, // State 28 - -26, -26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -26, -26, -26, -26, 0, + -33, -33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -33, -33, -33, -33, 0, // State 29 -6, -6, -6, -6, -6, 0, 0, 0, 0, 0, 0, 0, 0, -6, -6, -6, -6, -6, // State 30 - -34, -34, -34, -34, -34, 0, 0, 0, 0, 0, 0, 0, 0, -34, -34, -34, -34, 0, + -26, -26, -26, -26, -26, 0, 0, 0, 0, 0, 0, 0, 0, -26, -26, -26, -26, 0, // State 31 - -35, -35, -35, -35, -35, 0, 0, 0, 0, 0, 0, 0, 0, -35, -35, -35, -35, 0, + -27, -27, -27, -27, -27, 0, 0, 0, 0, 0, 0, 0, 0, -27, -27, -27, -27, 0, // State 32 - -33, -33, -33, -33, -33, 0, 0, 0, 0, 0, 0, 0, 0, -33, -33, -33, -33, 0, + -25, -25, -25, -25, -25, 0, 0, 0, 0, 0, 0, 0, 0, -25, -25, -25, -25, 0, // State 33 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 34 @@ -114,7 +114,7 @@ mod __parse__Instr { // State 37 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 38 - -30, -30, -30, -30, -30, 0, 0, 0, 0, 0, 0, 0, 0, -30, -30, -30, -30, 0, + -22, -22, -22, -22, -22, 0, 0, 0, 0, 0, 0, 0, 0, -22, -22, -22, -22, 0, // State 39 0, -19, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -19, // State 40 @@ -124,9 +124,9 @@ mod __parse__Instr { // State 42 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 43 - -29, 0, -29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -29, -29, -29, -29, 0, + -35, 0, -35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -35, -35, -35, -35, 0, // State 44 - -31, -31, -31, -31, -31, 0, 0, 0, 0, 0, 0, 0, 0, -31, -31, -31, -31, 0, + -23, -23, -23, -23, -23, 0, 0, 0, 0, 0, 0, 0, 0, -23, -23, -23, -23, 0, // State 45 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 46 @@ -138,13 +138,13 @@ mod __parse__Instr { // State 49 0, -15, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, // State 50 - 0, 0, -22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 51 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 52 0, -17, -17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, // State 53 - 0, 0, -23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 54 -4, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4, -4, -4, 0, // State 55 @@ -154,7 +154,7 @@ mod __parse__Instr { // State 57 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 58 - -28, -28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -28, -28, -28, -28, 0, + -34, -34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -34, -34, -34, -34, 0, // State 59 0, -18, -18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -18, // State 60 @@ -329,22 +329,22 @@ mod __parse__Instr { 17 => 46, _ => 11, }, - 9 => 51, - 11 => match state { - 1 => 27, - _ => 16, - }, - 12 => 7, - 13 => match state { - 16 => 45, - _ => 20, - }, - 14 => match state { + 9 => match state { 2 => 10, 7 | 20 => 36, 15..=16 => 43, 19 | 21 => 55, - _ => 28, + _ => 27, + }, + 10 => 51, + 12 => match state { + 1 => 28, + _ => 16, + }, + 13 => 7, + 14 => match state { + 16 => 45, + _ => 20, }, _ => 0, } @@ -662,80 +662,80 @@ mod __parse__Instr { } 21 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 9, } } 22 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 9, } } 23 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 10, + nonterminal_produced: 9, } } 24 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 10, + states_to_pop: 1, + nonterminal_produced: 9, } } 25 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 11, + nonterminal_produced: 9, } } 26 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 12, + nonterminal_produced: 9, } } 27 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 12, + states_to_pop: 1, + nonterminal_produced: 10, } } 28 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 13, + nonterminal_produced: 10, } } 29 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 14, + states_to_pop: 1, + nonterminal_produced: 11, } } 30 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 14, + states_to_pop: 0, + nonterminal_produced: 11, } } 31 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 14, + nonterminal_produced: 12, } } 32 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 14, + nonterminal_produced: 13, } } 33 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 14, + states_to_pop: 4, + nonterminal_produced: 13, } } 34 => { @@ -993,6 +993,17 @@ mod __parse__Instr { _ => __symbol_type_mismatch() } } + fn __pop_Variant2< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, InstructionValue<'input>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant2(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } fn __pop_Variant9< 'input, >( @@ -1004,22 +1015,11 @@ mod __parse__Instr { _ => __symbol_type_mismatch() } } - fn __pop_Variant2< - 'input, - >( - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> - ) -> (usize, Value<'input>, usize) - { - match __symbols.pop() { - Some((__l, __Symbol::Variant2(__v), __r)) => (__l, __v, __r), - _ => __symbol_type_mismatch() - } - } fn __pop_Variant4< 'input, >( __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> - ) -> (usize, Vec>, usize) + ) -> (usize, Vec>, usize) { match __symbols.pop() { Some((__l, __Symbol::Variant4(__v), __r)) => (__l, __v, __r), @@ -1052,7 +1052,7 @@ mod __parse__Instr { 'input, >( __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> - ) -> (usize, ::std::vec::Vec>, usize) + ) -> (usize, ::std::vec::Vec>, usize) { match __symbols.pop() { Some((__l, __Symbol::Variant3(__v), __r)) => (__l, __v, __r), @@ -1196,7 +1196,7 @@ mod __parse__Instr { _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) { - // Arg = Value => ActionFn(19); + // Arg = InstructionValue => ActionFn(19); let __sym0 = __pop_Variant2(__symbols); let __start = __sym0.0.clone(); let __end = __sym0.2.clone(); @@ -1300,7 +1300,7 @@ mod __parse__Instr { _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) { - // Function = Value => ActionFn(16); + // Function = InstructionValue => ActionFn(16); let __sym0 = __pop_Variant2(__symbols); let __start = __sym0.0.clone(); let __end = __sym0.2.clone(); @@ -1442,7 +1442,7 @@ mod __parse__Instr { _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) { - // Instr = "(", "fold", Value, Alphanumeric, Instr, ")" => ActionFn(5); + // Instr = "(", "fold", InstructionValue, Alphanumeric, Instr, ")" => ActionFn(5); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant6(__symbols); @@ -1530,6 +1530,125 @@ mod __parse__Instr { __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) + { + // InstructionValue = "\"", "\"" => ActionFn(20); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action20::<>(errors, input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (2, 9) + } + pub(crate) fn __reduce22< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) + { + // InstructionValue = "\"", Alphanumeric, "\"" => ActionFn(21); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action21::<>(errors, input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (3, 9) + } + pub(crate) fn __reduce23< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) + { + // InstructionValue = Alphanumeric => ActionFn(22); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action22::<>(errors, input, __sym0); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (1, 9) + } + pub(crate) fn __reduce24< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) + { + // InstructionValue = JSON_PATH => ActionFn(23); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action23::<>(errors, input, __sym0); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (1, 9) + } + pub(crate) fn __reduce25< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) + { + // InstructionValue = CURRENT_PEER_ID => ActionFn(24); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action24::<>(errors, input, __sym0); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (1, 9) + } + pub(crate) fn __reduce26< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) + { + // InstructionValue = INIT_PEER_ID => ActionFn(25); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action25::<>(errors, input, __sym0); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (1, 9) + } + pub(crate) fn __reduce27< + 'input, + 'err, + >( + errors: &'err mut Vec, InstructionError>>, + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<(&'input (), &'err ())>, + ) -> (usize, usize) { // Output = Alphanumeric => ActionFn(14); let __sym0 = __pop_Variant0(__symbols); @@ -1537,9 +1656,9 @@ mod __parse__Instr { let __end = __sym0.2.clone(); let __nt = super::__action14::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); - (1, 9) + (1, 10) } - pub(crate) fn __reduce22< + pub(crate) fn __reduce28< 'input, 'err, >( @@ -1556,9 +1675,9 @@ mod __parse__Instr { let __end = __sym0.2.clone(); let __nt = super::__action15::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); - (1, 9) + (1, 10) } - pub(crate) fn __reduce23< + pub(crate) fn __reduce29< 'input, 'err, >( @@ -1575,9 +1694,9 @@ mod __parse__Instr { let __end = __sym0.2.clone(); let __nt = super::__action30::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant8(__nt), __end)); - (1, 10) + (1, 11) } - pub(crate) fn __reduce24< + pub(crate) fn __reduce30< 'input, 'err, >( @@ -1593,9 +1712,9 @@ mod __parse__Instr { let __end = __start.clone(); let __nt = super::__action31::<>(errors, input, &__start, &__end); __symbols.push((__start, __Symbol::Variant8(__nt), __end)); - (0, 10) + (0, 11) } - pub(crate) fn __reduce25< + pub(crate) fn __reduce31< 'input, 'err, >( @@ -1606,15 +1725,15 @@ mod __parse__Instr { _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) { - // PeerId = Value => ActionFn(17); + // PeerId = InstructionValue => ActionFn(17); let __sym0 = __pop_Variant2(__symbols); let __start = __sym0.0.clone(); let __end = __sym0.2.clone(); let __nt = super::__action17::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 11) + (1, 12) } - pub(crate) fn __reduce26< + pub(crate) fn __reduce32< 'input, 'err, >( @@ -1631,9 +1750,9 @@ mod __parse__Instr { let __end = __sym0.2.clone(); let __nt = super::__action12::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant9(__nt), __end)); - (1, 12) + (1, 13) } - pub(crate) fn __reduce27< + pub(crate) fn __reduce33< 'input, 'err, >( @@ -1654,126 +1773,7 @@ mod __parse__Instr { let __end = __sym3.2.clone(); let __nt = super::__action13::<>(errors, input, __sym0, __sym1, __sym2, __sym3); __symbols.push((__start, __Symbol::Variant9(__nt), __end)); - (4, 12) - } - pub(crate) fn __reduce28< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // ServiceId = Value => ActionFn(18); - let __sym0 = __pop_Variant2(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym0.2.clone(); - let __nt = super::__action18::<>(errors, input, __sym0); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 13) - } - pub(crate) fn __reduce29< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // Value = "\"", "\"" => ActionFn(20); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym1.2.clone(); - let __nt = super::__action20::<>(errors, input, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (2, 14) - } - pub(crate) fn __reduce30< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // Value = "\"", Alphanumeric, "\"" => ActionFn(21); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym2.2.clone(); - let __nt = super::__action21::<>(errors, input, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (3, 14) - } - pub(crate) fn __reduce31< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // Value = Alphanumeric => ActionFn(22); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym0.2.clone(); - let __nt = super::__action22::<>(errors, input, __sym0); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 14) - } - pub(crate) fn __reduce32< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // Value = JSON_PATH => ActionFn(23); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym0.2.clone(); - let __nt = super::__action23::<>(errors, input, __sym0); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 14) - } - pub(crate) fn __reduce33< - 'input, - 'err, - >( - errors: &'err mut Vec, InstructionError>>, - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: ::std::marker::PhantomData<(&'input (), &'err ())>, - ) -> (usize, usize) - { - // Value = CURRENT_PEER_ID => ActionFn(24); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0.clone(); - let __end = __sym0.2.clone(); - let __nt = super::__action24::<>(errors, input, __sym0); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 14) + (4, 13) } pub(crate) fn __reduce34< 'input, @@ -1786,11 +1786,11 @@ mod __parse__Instr { _: ::std::marker::PhantomData<(&'input (), &'err ())>, ) -> (usize, usize) { - // Value = INIT_PEER_ID => ActionFn(25); - let __sym0 = __pop_Variant0(__symbols); + // ServiceId = InstructionValue => ActionFn(18); + let __sym0 = __pop_Variant2(__symbols); let __start = __sym0.0.clone(); let __end = __sym0.2.clone(); - let __nt = super::__action25::<>(errors, input, __sym0); + let __nt = super::__action18::<>(errors, input, __sym0); __symbols.push((__start, __Symbol::Variant2(__nt), __end)); (1, 14) } @@ -1909,13 +1909,14 @@ fn __action4< (_, _, _): (usize, &'input str, usize), (_, p, _): (usize, PeerPart<'input>, usize), (_, f, _): (usize, FunctionPart<'input>, usize), - (_, args, _): (usize, Vec>, usize), + (_, args, _): (usize, Vec>, usize), (_, output, _): (usize, ::std::option::Option>, usize), (_, _, _): (usize, &'input str, usize), ) -> Box> { { let output = output.unwrap_or(CallOutput::None); + let args = Rc::new(args); Box::new(Instruction::Call(Call{peer_part: p, function_part: f, args, output})) } } @@ -1929,7 +1930,7 @@ fn __action5< input: &'input str, (_, _, _): (usize, &'input str, usize), (_, _, _): (usize, &'input str, usize), - (_, iterable, _): (usize, Value<'input>, usize), + (_, iterable, _): (usize, InstructionValue<'input>, usize), (_, iterator, _): (usize, &'input str, usize), (_, i, _): (usize, Box>, usize), (_, _, _): (usize, &'input str, usize), @@ -1993,9 +1994,9 @@ fn __action9< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, _, _): (usize, &'input str, usize), - (_, args, _): (usize, ::std::vec::Vec>, usize), + (_, args, _): (usize, ::std::vec::Vec>, usize), (_, _, _): (usize, &'input str, usize), -) -> Vec> +) -> Vec> { args } @@ -2007,7 +2008,7 @@ fn __action10< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, f, _): (usize, Value<'input>, usize), + (_, f, _): (usize, InstructionValue<'input>, usize), ) -> FunctionPart<'input> { FunctionPart::FuncName(f) @@ -2021,8 +2022,8 @@ fn __action11< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, _, _): (usize, &'input str, usize), - (_, sid, _): (usize, Value<'input>, usize), - (_, f, _): (usize, Value<'input>, usize), + (_, sid, _): (usize, InstructionValue<'input>, usize), + (_, f, _): (usize, InstructionValue<'input>, usize), (_, _, _): (usize, &'input str, usize), ) -> FunctionPart<'input> { @@ -2036,7 +2037,7 @@ fn __action12< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, pid, _): (usize, Value<'input>, usize), + (_, pid, _): (usize, InstructionValue<'input>, usize), ) -> PeerPart<'input> { PeerPart::PeerPk(pid) @@ -2050,8 +2051,8 @@ fn __action13< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, _, _): (usize, &'input str, usize), - (_, pid, _): (usize, Value<'input>, usize), - (_, sid, _): (usize, Value<'input>, usize), + (_, pid, _): (usize, InstructionValue<'input>, usize), + (_, sid, _): (usize, InstructionValue<'input>, usize), (_, _, _): (usize, &'input str, usize), ) -> PeerPart<'input> { @@ -2091,8 +2092,8 @@ fn __action16< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> Value<'input> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> InstructionValue<'input> { __0 } @@ -2104,8 +2105,8 @@ fn __action17< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> Value<'input> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> InstructionValue<'input> { __0 } @@ -2117,8 +2118,8 @@ fn __action18< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> Value<'input> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> InstructionValue<'input> { __0 } @@ -2130,8 +2131,8 @@ fn __action19< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> Value<'input> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> InstructionValue<'input> { __0 } @@ -2145,9 +2146,9 @@ fn __action20< input: &'input str, (_, __0, _): (usize, &'input str, usize), (_, __1, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { - Value::Literal("") + InstructionValue::Literal("") } #[allow(unused_variables)] @@ -2160,9 +2161,9 @@ fn __action21< (_, _, _): (usize, &'input str, usize), (_, v, _): (usize, &'input str, usize), (_, _, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { - Value::Literal(v) + InstructionValue::Literal(v) } #[allow(unused_variables)] @@ -2173,9 +2174,9 @@ fn __action22< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, v, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { - Value::Variable(v) + InstructionValue::Variable(v) } #[allow(unused_variables)] @@ -2186,13 +2187,13 @@ fn __action23< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, v, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { { let mut path = v.splitn(2, "."); let variable = path.next().expect("must contain dot"); let path = path.next().expect("contain component after dot"); - Value::JsonPath { variable, path } + InstructionValue::JsonPath { variable, path } } } @@ -2204,9 +2205,9 @@ fn __action24< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, __0, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { - Value::CurrentPeerId + InstructionValue::CurrentPeerId } #[allow(unused_variables)] @@ -2217,9 +2218,9 @@ fn __action25< errors: &'err mut Vec, InstructionError>>, input: &'input str, (_, __0, _): (usize, &'input str, usize), -) -> Value<'input> +) -> InstructionValue<'input> { - Value::InitPeerId + InstructionValue::InitPeerId } #[allow(unused_variables)] @@ -2244,7 +2245,7 @@ fn __action27< input: &'input str, __lookbehind: &usize, __lookahead: &usize, -) -> ::std::vec::Vec> +) -> ::std::vec::Vec> { vec![] } @@ -2256,8 +2257,8 @@ fn __action28< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, v, _): (usize, ::std::vec::Vec>, usize), -) -> ::std::vec::Vec> + (_, v, _): (usize, ::std::vec::Vec>, usize), +) -> ::std::vec::Vec> { v } @@ -2269,8 +2270,8 @@ fn __action29< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> Value<'input> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> InstructionValue<'input> { __0 } @@ -2309,8 +2310,8 @@ fn __action32< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, __0, _): (usize, Value<'input>, usize), -) -> ::std::vec::Vec> + (_, __0, _): (usize, InstructionValue<'input>, usize), +) -> ::std::vec::Vec> { vec![__0] } @@ -2322,9 +2323,9 @@ fn __action33< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - (_, v, _): (usize, ::std::vec::Vec>, usize), - (_, e, _): (usize, Value<'input>, usize), -) -> ::std::vec::Vec> + (_, v, _): (usize, ::std::vec::Vec>, usize), + (_, e, _): (usize, InstructionValue<'input>, usize), +) -> ::std::vec::Vec> { { let mut v = v; v.push(e); v } } @@ -2336,8 +2337,8 @@ fn __action34< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - __0: (usize, Value<'input>, usize), -) -> ::std::vec::Vec> + __0: (usize, InstructionValue<'input>, usize), +) -> ::std::vec::Vec> { let __start0 = __0.0.clone(); let __end0 = __0.2.clone(); @@ -2361,9 +2362,9 @@ fn __action35< >( errors: &'err mut Vec, InstructionError>>, input: &'input str, - __0: (usize, ::std::vec::Vec>, usize), - __1: (usize, Value<'input>, usize), -) -> ::std::vec::Vec> + __0: (usize, ::std::vec::Vec>, usize), + __1: (usize, InstructionValue<'input>, usize), +) -> ::std::vec::Vec> { let __start0 = __1.0.clone(); let __end0 = __1.2.clone(); @@ -2390,7 +2391,7 @@ fn __action36< input: &'input str, __0: (usize, &'input str, usize), __1: (usize, &'input str, usize), -) -> Vec> +) -> Vec> { let __start0 = __0.2.clone(); let __end0 = __1.0.clone(); @@ -2418,9 +2419,9 @@ fn __action37< errors: &'err mut Vec, InstructionError>>, input: &'input str, __0: (usize, &'input str, usize), - __1: (usize, ::std::vec::Vec>, usize), + __1: (usize, ::std::vec::Vec>, usize), __2: (usize, &'input str, usize), -) -> Vec> +) -> Vec> { let __start0 = __1.0.clone(); let __end0 = __1.2.clone(); @@ -2450,7 +2451,7 @@ fn __action38< __1: (usize, &'input str, usize), __2: (usize, PeerPart<'input>, usize), __3: (usize, FunctionPart<'input>, usize), - __4: (usize, Vec>, usize), + __4: (usize, Vec>, usize), __5: (usize, CallOutput<'input>, usize), __6: (usize, &'input str, usize), ) -> Box> @@ -2487,7 +2488,7 @@ fn __action39< __1: (usize, &'input str, usize), __2: (usize, PeerPart<'input>, usize), __3: (usize, FunctionPart<'input>, usize), - __4: (usize, Vec>, usize), + __4: (usize, Vec>, usize), __5: (usize, &'input str, usize), ) -> Box> { diff --git a/crates/air-parser/src/lalrpop/tests.rs b/crates/air-parser/src/lalrpop/tests.rs index 8330c7ed..fddac791 100644 --- a/crates/air-parser/src/lalrpop/tests.rs +++ b/crates/air-parser/src/lalrpop/tests.rs @@ -17,8 +17,8 @@ use crate::ast::*; use CallOutput::*; use FunctionPart::*; +use InstructionValue::*; use PeerPart::*; -use Value::*; use fstrings::f; use std::rc::Rc; @@ -40,13 +40,13 @@ fn parse_seq() { Instruction::Call(Call { peer_part: PeerPk(Variable("peerid")), function_part: FuncName(Variable("function")), - args: vec![], + args: Rc::new(vec![]), output: Scalar("output"), }), Instruction::Call(Call { peer_part: PeerPk(Literal("id")), function_part: FuncName(Literal("f")), - args: vec![Literal("hello"), Variable("name")], + args: Rc::new(vec![Literal("hello"), Variable("name")]), output: None, }), ); @@ -70,20 +70,20 @@ fn parse_seq_seq() { Instruction::Call(Call { peer_part: PeerPk(Variable("peerid")), function_part: FuncName(Variable("function")), - args: vec![], + args: Rc::new(vec![]), output: None, }), Instruction::Call(Call { peer_part: PeerPkWithServiceId(Variable("peerid"), Variable("serviceA")), function_part: ServiceIdWithFuncName(Literal("serviceB"), Variable("function")), - args: vec![], + args: Rc::new(vec![]), output: None, }), ), Instruction::Call(Call { peer_part: PeerPk(Literal("id")), function_part: FuncName(Literal("f")), - args: vec![Literal("hello"), Variable("name")], + args: Rc::new(vec![Literal("hello"), Variable("name")]), output: Accumulator("output"), }), ); @@ -102,7 +102,7 @@ fn parse_json_path() { path: "$.a", }), function_part: FuncName(Literal("f")), - args: vec![Literal("hello"), Variable("name")], + args: Rc::new(vec![Literal("hello"), Variable("name")]), output: Accumulator("void"), }); assert_eq!(instruction, expected); @@ -124,7 +124,7 @@ fn parse_json_path_complex() { path: "$.[1]", }), function_part: FuncName(Literal("f")), - args: vec![], + args: Rc::new(vec![]), output: Scalar("void"), }), Instruction::Call(Call { @@ -133,7 +133,7 @@ fn parse_json_path_complex() { path: r#"$.abc["c"].cde[a][0].cde["bcd"]"#, }), function_part: FuncName(Literal("f")), - args: vec![], + args: Rc::new(vec![]), output: Scalar("void"), }), ); @@ -152,7 +152,7 @@ fn json_path_square_braces() { path: r#"$["peer_id"]"#, }), function_part: ServiceIdWithFuncName(Literal("return"), Literal("")), - args: vec![ + args: Rc::new(vec![ JsonPath { variable: "u", path: r#"$["peer_id"].cde[0]["abc"].abc"#, @@ -161,7 +161,7 @@ fn json_path_square_braces() { variable: "u", path: r#"$["name"]"#, }, - ], + ]), output: Accumulator("void"), }); @@ -213,7 +213,7 @@ fn parse_fold() { ) "#; let instruction = parse(&source_code.as_ref()); - let expected = fold(Value::Variable("iterable"), "i", null()); + let expected = fold(InstructionValue::Variable("iterable"), "i", null()); assert_eq!(instruction, expected); } @@ -228,7 +228,11 @@ fn parse_fold_with_xor_par_seq() { let source_code = source_fold_with(name); let instruction = parse(&source_code.as_ref()); let instr = binary_instruction(*name); - let expected = fold(Value::Variable("iterable"), "i", instr(null(), null())); + let expected = fold( + InstructionValue::Variable("iterable"), + "i", + instr(null(), null()), + ); assert_eq!(instruction, expected); } } @@ -248,13 +252,13 @@ fn parse_current_init_peer_id() { Literal("local_service_id"), Literal("local_fn_name"), ), - args: vec![], + args: Rc::new(vec![]), output: None, }), Instruction::Call(Call { peer_part: PeerPk(InitPeerId), function_part: ServiceIdWithFuncName(Literal("service_id"), Literal("fn_name")), - args: vec![], + args: Rc::new(vec![]), output: None, }), ); @@ -280,13 +284,13 @@ fn seq_par_call() { Literal("local_service_id"), Literal("local_fn_name"), ), - args: vec![], + args: Rc::new(vec![]), output: Scalar("result_1"), }), Instruction::Call(Call { peer_part: PeerPk(Literal("remote_peer_id")), function_part: ServiceIdWithFuncName(Literal("service_id"), Literal("fn_name")), - args: vec![], + args: Rc::new(vec![]), output: Scalar("g"), }), ), @@ -296,7 +300,7 @@ fn seq_par_call() { Literal("local_service_id"), Literal("local_fn_name"), ), - args: vec![], + args: Rc::new(vec![]), output: Scalar("result_2"), }), ); @@ -333,20 +337,20 @@ fn seq_with_empty_and_dash() { Instruction::Call(Call { peer_part: PeerPk(Literal("set_variables")), function_part: ServiceIdWithFuncName(Literal(""), Literal("")), - args: vec![Literal("module-bytes")], + args: Rc::new(vec![Literal("module-bytes")]), output: Scalar("module-bytes"), }), Instruction::Call(Call { peer_part: PeerPk(Literal("set_variables")), function_part: ServiceIdWithFuncName(Literal(""), Literal("")), - args: vec![Literal("module_config")], + args: Rc::new(vec![Literal("module_config")]), output: Scalar("module_config"), }), ), Instruction::Call(Call { peer_part: PeerPk(Literal("set_variables")), function_part: ServiceIdWithFuncName(Literal(""), Literal("")), - args: vec![Literal("blueprint")], + args: Rc::new(vec![Literal("blueprint")]), output: Scalar("blueprint"), }), ), @@ -354,27 +358,27 @@ fn seq_with_empty_and_dash() { Instruction::Call(Call { peer_part: PeerPk(Literal("A")), function_part: ServiceIdWithFuncName(Literal("add_module"), Literal("")), - args: vec![Variable("module-bytes"), Variable("module_config")], + args: Rc::new(vec![Variable("module-bytes"), Variable("module_config")]), output: Scalar("module"), }), seq( Instruction::Call(Call { peer_part: PeerPk(Literal("A")), function_part: ServiceIdWithFuncName(Literal("add_blueprint"), Literal("")), - args: vec![Variable("blueprint")], + args: Rc::new(vec![Variable("blueprint")]), output: Scalar("blueprint_id"), }), seq( Instruction::Call(Call { peer_part: PeerPk(Literal("A")), function_part: ServiceIdWithFuncName(Literal("create"), Literal("")), - args: vec![Variable("blueprint_id")], + args: Rc::new(vec![Variable("blueprint_id")]), output: Scalar("service_id"), }), Instruction::Call(Call { peer_part: PeerPk(Literal("remote_peer_id")), function_part: ServiceIdWithFuncName(Literal(""), Literal("")), - args: vec![Variable("service_id")], + args: Rc::new(vec![Variable("service_id")]), output: Scalar("client_result"), }), ), @@ -394,7 +398,7 @@ fn no_output() { let expected = Instruction::Call(Call { peer_part: PeerPk(Variable("peer")), function_part: ServiceIdWithFuncName(Variable("service"), Variable("fname")), - args: vec![], + args: Rc::new(vec![]), output: None, }); assert_eq!(instruction, expected); @@ -456,7 +460,7 @@ fn null() -> Instruction<'static> { Instruction::Null(Null) } fn fold<'a>( - iterable: Value<'a>, + iterable: InstructionValue<'a>, iterator: &'a str, instruction: Instruction<'a>, ) -> Instruction<'a> { diff --git a/crates/polyplets/Cargo.toml b/crates/polyplets/Cargo.toml new file mode 100644 index 00000000..e83e5a4a --- /dev/null +++ b/crates/polyplets/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "polyplets" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" + +[lib] +name = "polyplets" +path = "src/lib.rs" + +[dependencies] +fluence = { version = "=0.2.13", features = ["logger"] } +serde = { version = "1.0.118", features = ["rc"] } diff --git a/crates/polyplets/src/lib.rs b/crates/polyplets/src/lib.rs new file mode 100644 index 00000000..f880fa69 --- /dev/null +++ b/crates/polyplets/src/lib.rs @@ -0,0 +1,32 @@ +/* + * 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 +)] + +mod tetraplet; +mod triplet; + +pub use tetraplet::SecurityTetraplet; +pub use triplet::ResolvedTriplet; diff --git a/crates/polyplets/src/tetraplet.rs b/crates/polyplets/src/tetraplet.rs new file mode 100644 index 00000000..8f1d002f --- /dev/null +++ b/crates/polyplets/src/tetraplet.rs @@ -0,0 +1,52 @@ +/* + * 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 crate::ResolvedTriplet; + +use serde::Deserialize; +use serde::Serialize; +use std::rc::Rc; + +/// Describes an origin returned corresponding value. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct SecurityTetraplet { + /// Describes origin of the value in the network. + #[serde(flatten)] + pub triplet: Rc, + + /// Value was produced by applying this `json_path` to the output from `call_service`. + pub json_path: String, +} + +impl SecurityTetraplet { + /// Create a tetraplet for string literals defined in the script + /// such as variable here `(call ("" "") "" ["variable_1"])`. + pub fn literal_tetraplet(init_peer_id: String) -> Self { + let triplet = ResolvedTriplet { + // these variables represent the initiator peer + peer_pk: init_peer_id, + service_id: String::new(), + function_name: String::new(), + }; + let triplet = Rc::new(triplet); + + Self { + triplet, + // json path can't be applied to the string literals + json_path: String::new(), + } + } +} diff --git a/crates/polyplets/src/triplet.rs b/crates/polyplets/src/triplet.rs new file mode 100644 index 00000000..32f914a2 --- /dev/null +++ b/crates/polyplets/src/triplet.rs @@ -0,0 +1,27 @@ +/* + * 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 serde::Deserialize; +use serde::Serialize; + +/// ResolvedTriplet represents peer network location with all +/// variables, literals and etc resolved into final string. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct ResolvedTriplet { + pub peer_pk: String, + pub service_id: String, + pub function_name: String, +} diff --git a/crates/stepper-interface/Cargo.toml b/crates/stepper-interface/Cargo.toml index 6a6cfbc7..f2015505 100644 --- a/crates/stepper-interface/Cargo.toml +++ b/crates/stepper-interface/Cargo.toml @@ -10,7 +10,7 @@ name = "stepper_interface" path = "src/lib.rs" [dependencies] -fluence = { git = "https://github.com/fluencelabs/rust-sdk" } +fluence = "=0.2.13" wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.20" } serde = "1.0.118" diff --git a/crates/test-module/Cargo.toml b/crates/test-module/Cargo.toml index d8706af4..9fa5ddbe 100644 --- a/crates/test-module/Cargo.toml +++ b/crates/test-module/Cargo.toml @@ -9,4 +9,4 @@ name = "aqua_test_module" path = "src/main.rs" [dependencies] -fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] } +fluence = { version = "=0.2.13", features = ["logger"] } diff --git a/crates/test-module/src/main.rs b/crates/test-module/src/main.rs index 68d58808..69efe766 100644 --- a/crates/test-module/src/main.rs +++ b/crates/test-module/src/main.rs @@ -36,10 +36,15 @@ pub struct CallServiceResult { } #[fce] -pub fn call_service(service_id: String, fn_name: String, args: String) -> CallServiceResult { +pub fn call_service( + service_id: String, + fn_name: String, + args: String, + tetraplets: String, +) -> CallServiceResult { println!( - "call service invoked with:\n service_id: {}\n fn_name: {}\n args: {:?}", - service_id, fn_name, args + "call service invoked with:\n service_id: {}\n fn_name: {}\n args: {}\n tetraples: {}", + service_id, fn_name, args, tetraplets ); CallServiceResult { diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index f369e2fc..45c8f777 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -9,6 +9,6 @@ name = "aqua_test_utils" path = "src/lib.rs" [dependencies] -fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] } +fluence = { version = "=0.2.13", features = ["logger"] } aquamarine-vm = { git = "https://github.com/fluencelabs/fce", branch = "master", features = ["raw-aquamarine-vm-api"] } serde_json = "1.0.56" diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index 15adf4dc..c1313136 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -46,7 +46,7 @@ pub fn create_aqua_vm( ) -> AquamarineVM { let call_service_descriptor = HostImportDescriptor { host_exported_func: call_service, - argument_types: vec![IType::String, IType::String, IType::String], + argument_types: vec![IType::String, IType::String, IType::String, IType::String], output_type: Some(IType::Record(0)), error_handler: None, }; @@ -138,10 +138,10 @@ pub fn set_variables_call_service(ret_mapping: HashMap) -> HostE let result = ret_mapping .get(&arg_name) .cloned() - .unwrap_or(String::from(r#""test""#)); + .unwrap_or_else(|| String::from(r#""test""#)); Some(IValue::Record( - Vec1::new(vec![IValue::S32(0), IValue::String(result.clone())]).unwrap(), + Vec1::new(vec![IValue::S32(0), IValue::String(result)]).unwrap(), )) }) } diff --git a/stepper-lib/Cargo.toml b/stepper-lib/Cargo.toml index efc09430..6718162a 100644 --- a/stepper-lib/Cargo.toml +++ b/stepper-lib/Cargo.toml @@ -10,13 +10,14 @@ path = "src/lib.rs" [dependencies] air-parser = { path = "../crates/air-parser" } -fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] } +fluence = { version = "=0.2.13", features = ["logger"] } +polyplets = { path = "../crates/polyplets" } stepper-interface = { path = "../crates/stepper-interface" } serde = { version = "1.0.116", features = [ "derive", "rc" ] } serde_derive = "1.0.116" -jsonpath_lib = "0.2.5" +jsonpath_lib = { git = "https://github.com/fluencelabs/jsonpath", branch = "fluence" } boolinator = "2.4.0" log = "0.4.11" @@ -27,6 +28,7 @@ wasm-bindgen = "=0.2.65" [dev_dependencies] aqua-test-utils = { path = "../crates/test-utils" } +fluence-app-service = "=0.1.17" criterion = "0.3.3" csv = "1.1.5" diff --git a/stepper-lib/src/air/call.rs b/stepper-lib/src/air/call.rs index b4bfb479..016d60e5 100644 --- a/stepper-lib/src/air/call.rs +++ b/stepper-lib/src/air/call.rs @@ -14,17 +14,17 @@ * limitations under the License. */ -mod parsed_call; +mod resolved_call; mod triplet; mod utils; -use parsed_call::ParsedCall; +use resolved_call::ResolvedCall; use super::CallEvidenceCtx; use super::ExecutionCtx; use crate::log_instruction; +use crate::AquamarineError::JValueJsonPathError; use crate::AquamarineError::VariableNotFound; -use crate::AquamarineError::VariableNotInJsonPath; use crate::Result; use air_parser::ast::Call; @@ -44,15 +44,15 @@ impl<'i> super::ExecutableInstruction<'i> for Call<'i> { fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> { log_instruction!(call, exec_ctx, call_ctx); - let parsed_call = match ParsedCall::new(self, exec_ctx) { - Ok(parsed_call) => parsed_call, + let resolved_call = match ResolvedCall::new(self, exec_ctx) { + Ok(resolved_call) => resolved_call, // to support lazy variable evaluation Err(VariableNotFound(variable_name)) => { log::trace!(r#"variable with name "{}" not found, waiting"#, variable_name); exec_ctx.subtree_complete = false; return Ok(()); } - Err(VariableNotInJsonPath(variable, json_path, json_path_err)) => { + Err(JValueJsonPathError(variable, json_path, json_path_err)) => { log::trace!( r#"variable not found with json path "{}" in {:?} with error "{:?}", waiting"#, json_path, @@ -65,7 +65,7 @@ impl<'i> super::ExecutableInstruction<'i> for Call<'i> { Err(err) => return Err(err), }; - parsed_call.execute(exec_ctx, call_ctx) + resolved_call.execute(exec_ctx, call_ctx) } } @@ -85,50 +85,48 @@ mod tests { use std::rc::Rc; + // Check that %current_peer_id% alias works correctly (by comparing result with it and explicit peer id). + // Additionally, check that empty string for data does the same as empty call path. #[test] fn current_peer_id_call() { use crate::call_evidence::CallResult::*; use crate::call_evidence::EvidenceState::*; - let mut vm = create_aqua_vm(unit_call_service(), "test_peer_id"); + let vm_peer_id = String::from("test_peer_id"); + let mut vm = create_aqua_vm(unit_call_service(), vm_peer_id.clone()); - let script = String::from( + let service_id = String::from("local_service_id"); + let function_name = String::from("local_fn_name"); + let script = format!( r#" - (call %current_peer_id% ("local_service_id" "local_fn_name") [] result_name) + (call %current_peer_id% ("{}" "{}") [] result_name) "#, + service_id, function_name ); let res = call_vm!(vm, "asd", script.clone(), "[]", "[]"); let call_path: CallEvidencePath = serde_json::from_slice(&res.data).expect("should be a valid json"); + let executed_call_state = Call(Executed(Rc::new(JValue::String(String::from("test"))))); assert_eq!(call_path.len(), 1); - assert_eq!( - call_path[0], - Call(Executed(Rc::new(JValue::String(String::from("test"))))) - ); + assert_eq!(call_path[0], executed_call_state); assert!(res.next_peer_pks.is_empty()); + let script = format!( + r#" + (call "{}" ("{}" "{}") [] result_name) + "#, + vm_peer_id, service_id, function_name + ); + + let res = call_vm!(vm, "asd", script.clone(), "[]", "[]"); + // test that empty string for data works let res_with_empty_string = call_vm!(vm, "asd", script, "", ""); assert_eq!(res_with_empty_string, res); - - let script = String::from( - r#" - (call "test_peer_id" ("local_service_id" "local_fn_name") [] result_name) - "#, - ); - - let res = call_vm!(vm, "asd", script, "[]", "[]"); - let call_path: CallEvidencePath = serde_json::from_slice(&res.data).expect("should be a valid json"); - - assert_eq!(call_path.len(), 1); - assert_eq!( - call_path[0], - Call(Executed(Rc::new(JValue::String(String::from("test"))))) - ); - assert!(res.next_peer_pks.is_empty()); } + // Check that specifying remote peer id in call will result its appearing in next_peer_pks. #[test] fn remote_peer_id_call() { use crate::call_evidence::CallResult::*; @@ -151,6 +149,7 @@ mod tests { assert_eq!(res.next_peer_pks, vec![remote_peer_id]); } + // Check that setting variables works as expected. #[test] fn variables() { let mut vm = create_aqua_vm(unit_call_service(), "remote_peer_id"); @@ -171,6 +170,7 @@ mod tests { assert!(res.next_peer_pks.is_empty()); } + // Check that string literals can be used as call parameters. #[test] fn string_parameters() { use crate::call_evidence::CallResult::*; @@ -187,16 +187,25 @@ mod tests { )) }); - let mut vm = create_aqua_vm(call_service, "A"); - let mut set_variable_vm = create_aqua_vm(set_variable_call_service(r#""arg3_value""#), "set_variable"); + let vm_peer_id = String::from("A"); + let mut vm = create_aqua_vm(call_service, vm_peer_id.clone()); - let script = String::from( + let set_variable_vm_peer_id = String::from("set_variable"); + let mut set_variable_vm = create_aqua_vm( + set_variable_call_service(r#""arg3_value""#), + set_variable_vm_peer_id.clone(), + ); + + let service_id = String::from("some_service_id"); + let function_name = String::from("local_fn_name"); + let script = format!( r#" (seq - (call "set_variable" ("some_service_id" "local_fn_name") [] arg3) - (call "A" ("some_service_id" "local_fn_name") ["arg1" "arg2" arg3] result) + (call "{}" ("{}" "{}") [] arg3) + (call "{}" ("{}" "{}") ["arg1" "arg2" arg3] result) ) "#, + set_variable_vm_peer_id, service_id, function_name, vm_peer_id, service_id, function_name ); let res = call_vm!(set_variable_vm, "asd", script.clone(), "[]", "[]"); diff --git a/stepper-lib/src/air/call/parsed_call.rs b/stepper-lib/src/air/call/parsed_call.rs deleted file mode 100644 index accdcc90..00000000 --- a/stepper-lib/src/air/call/parsed_call.rs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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. - */ - -#![allow(unused_unsafe)] // for wasm_bindgen target where calling FFI is safe - -use super::triplet::{ResolvedTriplet, Triplet}; -use super::utils::{set_local_call_result, set_remote_call_result}; -use super::Call; - -use crate::air::resolve::resolve_jvalue; -use crate::air::ExecutionCtx; -use crate::build_targets::CALL_SERVICE_SUCCESS; -use crate::call_evidence::{CallEvidenceCtx, CallResult, EvidenceState}; -use crate::log_targets::EVIDENCE_CHANGING; -use crate::AquamarineError; -use crate::JValue; -use crate::Result; - -use air_parser::ast::{CallOutput, Value}; - -use std::rc::Rc; - -#[derive(Debug, PartialEq, Eq)] -pub(super) struct ParsedCall<'i> { - peer_pk: String, - service_id: String, - function_name: String, - function_arg_paths: Vec>, - output: CallOutput<'i>, -} - -impl<'i> ParsedCall<'i> { - /// Builds `ParsedCall` from `Call` by transforming `PeerPart` & `FunctionPart` into `ResolvedTriplet` - pub(super) fn new(raw_call: &Call<'i>, exec_ctx: &ExecutionCtx<'i>) -> Result { - let triplet = Triplet::try_from(&raw_call.peer_part, &raw_call.function_part)?; - #[rustfmt::skip] - let ResolvedTriplet { peer_pk, service_id, function_name } = triplet.resolve(exec_ctx)?; - - Ok(Self { - peer_pk, - service_id, - function_name, - function_arg_paths: raw_call.args.clone(), - output: raw_call.output.clone(), - }) - } - - pub(super) fn execute(self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> { - let should_execute = self.prepare_evidence_state(exec_ctx, call_ctx)?; - if !should_execute { - return Ok(()); - } - - if self.peer_pk != exec_ctx.current_peer_id { - set_remote_call_result(self.peer_pk, exec_ctx, call_ctx); - - return Ok(()); - } - - let function_args = self.function_arg_paths.iter(); - let function_args: Result> = function_args.map(|v| resolve_jvalue(v, exec_ctx)).collect(); - let function_args = JValue::Array(function_args?).to_string(); - - let result = unsafe { crate::call_service(self.service_id, self.function_name, function_args) }; - - if result.ret_code != CALL_SERVICE_SUCCESS { - call_ctx - .new_path - .push_back(EvidenceState::Call(CallResult::CallServiceFailed( - result.result.clone(), - ))); - return Err(AquamarineError::LocalServiceError(result.result)); - } - - let result: JValue = serde_json::from_str(&result.result) - .map_err(|e| AquamarineError::CallServiceResultDeserializationError(result, e))?; - let result = Rc::new(result); - set_local_call_result(self.output, exec_ctx, result.clone())?; - - let new_evidence_state = EvidenceState::Call(CallResult::Executed(result)); - log::trace!( - target: EVIDENCE_CHANGING, - " adding new call evidence state {:?}", - new_evidence_state - ); - call_ctx.new_path.push_back(new_evidence_state); - - Ok(()) - } - - pub(super) fn prepare_evidence_state( - &self, - exec_ctx: &mut ExecutionCtx<'i>, - call_ctx: &mut CallEvidenceCtx, - ) -> Result { - use crate::call_evidence::CallResult::*; - use crate::call_evidence::EvidenceState::*; - - if call_ctx.current_subtree_size == 0 { - log::trace!(target: EVIDENCE_CHANGING, " previous call evidence state wasn't found"); - return Ok(true); - } - - call_ctx.current_subtree_size -= 1; - // unwrap is safe here, because current_subtree_size depends on current_path len, - // and it's been checked previously - let prev_state = call_ctx.current_path.pop_front().unwrap(); - - log::trace!( - target: EVIDENCE_CHANGING, - " previous call evidence state found {:?}", - prev_state - ); - - match &prev_state { - // this call was failed on one of the previous executions, - // here it's needed to bubble this special error up - Call(CallServiceFailed(err_msg)) => { - let err_msg = err_msg.clone(); - call_ctx.new_path.push_back(prev_state); - exec_ctx.subtree_complete = false; - Err(AquamarineError::LocalServiceError(err_msg)) - } - Call(RequestSent(..)) => { - // check whether current node can execute this call - let is_current_peer = self.peer_pk == exec_ctx.current_peer_id; - if is_current_peer { - Ok(true) - } else { - exec_ctx.subtree_complete = false; - call_ctx.new_path.push_back(prev_state); - Ok(false) - } - } - // this instruction's been already executed - Call(Executed(result)) => { - set_local_call_result(self.output.clone(), exec_ctx, result.clone())?; - call_ctx.new_path.push_back(prev_state); - Ok(false) - } - // state has inconsistent order - return a error, call shouldn't be executed - par_state @ Par(..) => Err(AquamarineError::InvalidEvidenceState( - par_state.clone(), - String::from("call"), - )), - } - } -} diff --git a/stepper-lib/src/air/call/resolved_call.rs b/stepper-lib/src/air/call/resolved_call.rs new file mode 100644 index 00000000..df1509ba --- /dev/null +++ b/stepper-lib/src/air/call/resolved_call.rs @@ -0,0 +1,167 @@ +/* + * 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. + */ + +#![allow(unused_unsafe)] // for wasm_bindgen target where calling FFI is safe + +use super::triplet::Triplet; +use super::utils::*; +use super::Call; +use crate::air::ExecutionCtx; +use crate::build_targets::CALL_SERVICE_SUCCESS; +use crate::call_evidence::{CallEvidenceCtx, CallResult, EvidenceState}; +use crate::log_targets::EVIDENCE_CHANGING; +use crate::AquamarineError; +use crate::JValue; +use crate::Result; +use crate::SecurityTetraplet; + +use air_parser::ast::{CallOutput, InstructionValue}; +use polyplets::ResolvedTriplet; + +use std::rc::Rc; + +/// Represents Call instruction with resolved internal parts. +#[derive(Clone)] +pub(super) struct ResolvedCall<'i> { + triplet: Rc, + function_arg_paths: Rc>>, + output: CallOutput<'i>, +} + +struct ResolvedArguments { + call_arguments: String, + tetraplets: Vec>, +} + +impl<'i> ResolvedCall<'i> { + /// Build `ResolvedCall` from `Call` by transforming `PeerPart` & `FunctionPart` into `ResolvedTriplet`. + pub(super) fn new(raw_call: &Call<'i>, exec_ctx: &ExecutionCtx<'i>) -> Result { + let triplet = Triplet::try_from(&raw_call.peer_part, &raw_call.function_part)?; + let triplet = triplet.resolve(exec_ctx)?; + let triplet = Rc::new(triplet); + + Ok(Self { + triplet, + function_arg_paths: raw_call.args.clone(), + output: raw_call.output.clone(), + }) + } + + /// Executes resolved instruction, updates contexts based on a execution result. + pub(super) fn execute(self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> { + use AquamarineError::CallServiceResultDeserializationError as DeError; + use CallResult::*; + use EvidenceState::Call; + + let should_execute = self.prepare_evidence_state(exec_ctx, call_ctx)?; + if !should_execute { + return Ok(()); + } + + // call can be executed only on peers with such peer_id + if self.triplet.peer_pk != exec_ctx.current_peer_id { + set_remote_call_result(self.triplet.peer_pk.clone(), exec_ctx, call_ctx); + + return Ok(()); + } + + let ResolvedArguments { + call_arguments, + tetraplets, + } = self.resolve_args(exec_ctx)?; + + let tetraplets = serde_json::to_string(&tetraplets).expect("default serializer shouldn't fail"); + + let service_result = unsafe { + crate::call_service( + // copying here is necessary because of current limitations of rust-sdk + self.triplet.service_id.clone(), + self.triplet.function_name.clone(), + call_arguments, + tetraplets, + ) + }; + + // check that service call succeeded + if service_result.ret_code != CALL_SERVICE_SUCCESS { + call_ctx + .new_path + .push_back(Call(CallServiceFailed(service_result.result.clone()))); + return Err(AquamarineError::LocalServiceError(service_result.result)); + } + + let result: JValue = serde_json::from_str(&service_result.result).map_err(|e| DeError(service_result, e))?; + let result = Rc::new(result); + + set_local_call_result(result.clone(), self.triplet.clone(), &self.output, exec_ctx)?; + let new_evidence_state = Call(Executed(result)); + + log::trace!( + target: EVIDENCE_CHANGING, + " adding new call evidence state {:?}", + new_evidence_state + ); + + call_ctx.new_path.push_back(new_evidence_state); + + Ok(()) + } + + /// Determine whether this call should be really called and adjust prev call evidence path accordingly. + fn prepare_evidence_state(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result { + if call_ctx.current_subtree_size == 0 { + log::trace!(target: EVIDENCE_CHANGING, " previous call evidence state wasn't found"); + return Ok(true); + } + + call_ctx.current_subtree_size -= 1; + // unwrap is safe here, because current_subtree_size depends on current_path len, + // and it's been checked previously + let prev_state = call_ctx.current_path.pop_front().unwrap(); + + log::trace!( + target: EVIDENCE_CHANGING, + " previous call evidence state found {:?}", + prev_state + ); + + handle_prev_state(&self.triplet, &self.output, prev_state, exec_ctx, call_ctx) + } + + /// Prepare arguments of this call instruction by resolving and preparing their security tetraplets. + fn resolve_args(&self, exec_ctx: &ExecutionCtx<'i>) -> Result { + use crate::air::resolve::resolve_to_args; + + let function_args = self.function_arg_paths.iter(); + let mut call_arguments = Vec::new(); + let mut tetraplets = Vec::new(); + for instruction_value in function_args { + let (arg, tetraplet) = resolve_to_args(instruction_value, exec_ctx)?; + call_arguments.push(arg); + tetraplets.push(tetraplet); + } + + let call_arguments = JValue::Array(call_arguments); + let call_arguments = call_arguments.to_string(); + + let resolved_arguments = ResolvedArguments { + call_arguments, + tetraplets, + }; + + Ok(resolved_arguments) + } +} diff --git a/stepper-lib/src/air/call/triplet.rs b/stepper-lib/src/air/call/triplet.rs index bd97616f..bd248834 100644 --- a/stepper-lib/src/air/call/triplet.rs +++ b/stepper-lib/src/air/call/triplet.rs @@ -15,25 +15,19 @@ */ use crate::air::ExecutionCtx; -use crate::{AquamarineError, Result}; +use crate::AquamarineError; +use crate::JValue; +use crate::Result; -use crate::air::resolve::resolve_value; -use air_parser::ast::{FunctionPart, PeerPart, Value}; +use air_parser::ast::{FunctionPart, InstructionValue, PeerPart}; +use polyplets::ResolvedTriplet; -/// Triplet represents a location of the executable code in the network -/// It is build from `PeerPart` and `FunctionPart` of a `Call` instruction +/// Triplet represents a location of the executable code in the network. +/// It is build from `PeerPart` and `FunctionPart` of a `Call` instruction. pub(super) struct Triplet<'a, 'i> { - pub(super) peer_pk: &'a Value<'i>, - pub(super) service_id: &'a Value<'i>, - pub(super) function_name: &'a Value<'i>, -} - -/// ResolvedTriplet represents same location as `Triplet`, but with all -/// variables, literals and etc resolved into final `String` -pub(super) struct ResolvedTriplet { - pub(super) peer_pk: String, - pub(super) service_id: String, - pub(super) function_name: String, + pub(super) peer_pk: &'a InstructionValue<'i>, + pub(super) service_id: &'a InstructionValue<'i>, + pub(super) function_name: &'a InstructionValue<'i>, } impl<'a, 'i> Triplet<'a, 'i> { @@ -62,16 +56,16 @@ impl<'a, 'i> Triplet<'a, 'i> { }) } - /// Resolve variables, literals, etc in the `Triplet`, and build a `ResolvedTriplet` - pub fn resolve(self, ctx: &'a ExecutionCtx<'i>) -> Result { + /// Resolve variables, literals, etc in the `Triplet`, and build a `ResolvedTriplet`. + pub fn resolve(self, ctx: &ExecutionCtx<'i>) -> Result { let Triplet { peer_pk, service_id, function_name, } = self; - let peer_pk = resolve_value(peer_pk, ctx)?.as_ref().to_string(); - let service_id = resolve_value(service_id, ctx)?.as_ref().to_string(); - let function_name = resolve_value(function_name, ctx)?.as_ref().to_string(); + let peer_pk = resolve_to_string(peer_pk, ctx)?; + let service_id = resolve_to_string(service_id, ctx)?; + let function_name = resolve_to_string(function_name, ctx)?; Ok(ResolvedTriplet { peer_pk, @@ -80,3 +74,48 @@ impl<'a, 'i> Triplet<'a, 'i> { }) } } + +/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc. +// TODO: return Rc to avoid excess cloning +fn resolve_to_string<'i>(value: &InstructionValue<'i>, ctx: &ExecutionCtx<'i>) -> Result { + use crate::air::resolve::resolve_to_jvaluable; + + let resolved = match value { + InstructionValue::CurrentPeerId => ctx.current_peer_id.clone(), + InstructionValue::InitPeerId => ctx.init_peer_id.clone(), + InstructionValue::Literal(value) => value.to_string(), + InstructionValue::Variable(name) => { + let resolved = resolve_to_jvaluable(name, ctx)?; + let jvalue = resolved.into_jvalue(); + jvalue_to_string(jvalue)? + } + InstructionValue::JsonPath { variable, path } => { + let resolved = resolve_to_jvaluable(variable, ctx)?; + let resolved = resolved.apply_json_path(path)?; + vec_to_string(resolved, path)? + } + }; + + Ok(resolved) +} + +fn jvalue_to_string(jvalue: JValue) -> Result { + use AquamarineError::IncompatibleJValueType; + + match jvalue { + JValue::String(s) => Ok(s), + _ => Err(IncompatibleJValueType(jvalue, "string")), + } +} + +fn vec_to_string(values: Vec<&JValue>, json_path: &str) -> Result { + if values.is_empty() { + return Err(AquamarineError::VariableNotFound(json_path.to_string())); + } + + if values.len() != 1 { + return Err(AquamarineError::MultipleValuesInJsonPath(json_path.to_string())); + } + + jvalue_to_string(values[0].clone()) +} diff --git a/stepper-lib/src/air/call/utils.rs b/stepper-lib/src/air/call/utils.rs index 7f8253c2..c90d1edb 100644 --- a/stepper-lib/src/air/call/utils.rs +++ b/stepper-lib/src/air/call/utils.rs @@ -19,24 +19,30 @@ use crate::call_evidence::CallEvidenceCtx; use crate::call_evidence::CallResult; use crate::call_evidence::EvidenceState; use crate::log_targets::EVIDENCE_CHANGING; -use crate::AValue; use crate::AquamarineError; use crate::JValue; +use crate::ResolvedCallResult; use crate::Result; use air_parser::ast::CallOutput; +use polyplets::ResolvedTriplet; -use std::{cell::RefCell, rc::Rc}; +use std::rc::Rc; -/// Writes result of a local `Call` instruction to `ExecutionCtx` at `output` +/// Writes result of a local `Call` instruction to `ExecutionCtx` at `output`. pub(super) fn set_local_call_result<'i>( - output: CallOutput<'i>, - exec_ctx: &mut ExecutionCtx<'i>, result: Rc, + triplet: Rc, + output: &CallOutput<'i>, + exec_ctx: &mut ExecutionCtx<'i>, ) -> Result<()> { + use crate::AValue; + use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; use AquamarineError::*; + let executed_result = ResolvedCallResult { result, triplet }; + match output { CallOutput::Scalar(name) => { if let Some(fold_block_name) = exec_ctx.met_folds.back() { @@ -45,12 +51,12 @@ pub(super) fn set_local_call_result<'i>( _ => unreachable!("fold block data must be represented as fold cursor"), }; - fold_state.met_variables.insert(name, result.clone()); + fold_state.met_variables.insert(name, executed_result.clone()); } match exec_ctx.data_cache.entry(name.to_string()) { Vacant(entry) => { - entry.insert(AValue::JValueRef(result)); + entry.insert(AValue::JValueRef(executed_result)); } Occupied(mut entry) => { // check that current execution flow is inside a fold block @@ -65,7 +71,7 @@ pub(super) fn set_local_call_result<'i>( _ => return Err(ShadowingError(entry.key().clone())), }; - entry.insert(AValue::JValueRef(result)); + entry.insert(AValue::JValueRef(executed_result)); } }; } @@ -73,11 +79,11 @@ pub(super) fn set_local_call_result<'i>( match exec_ctx.data_cache.entry(name.to_string()) { Occupied(mut entry) => match entry.get_mut() { // if result is an array, insert result to the end of the array - AValue::JValueAccumulatorRef(values) => values.borrow_mut().push(result), - v => return Err(IncompatibleAValueType(format!("{:?}", v), String::from("Array"))), + AValue::JValueAccumulatorRef(values) => values.borrow_mut().push(executed_result), + v => return Err(IncompatibleAValueType(format!("{}", v), String::from("Array"))), }, Vacant(entry) => { - entry.insert(AValue::JValueAccumulatorRef(RefCell::new(vec![result]))); + entry.insert(AValue::JValueAccumulatorRef(RefCell::new(vec![executed_result]))); } }; } @@ -104,3 +110,50 @@ pub(super) fn set_remote_call_result<'i>( ); call_ctx.new_path.push_back(new_evidence_state); } + +/// This function looks at the existing call state, validates it, +/// and returns Ok(true) if the call should be executed further. +pub(super) fn handle_prev_state<'i>( + triplet: &Rc, + output: &CallOutput<'i>, + prev_state: EvidenceState, + exec_ctx: &mut ExecutionCtx<'i>, + call_ctx: &mut CallEvidenceCtx, +) -> Result { + use crate::call_evidence::CallResult::*; + use crate::call_evidence::EvidenceState::*; + + match &prev_state { + // this call was failed on one of the previous executions, + // here it's needed to bubble this special error up + Call(CallServiceFailed(err_msg)) => { + let err_msg = err_msg.clone(); + call_ctx.new_path.push_back(prev_state); + exec_ctx.subtree_complete = false; + Err(AquamarineError::LocalServiceError(err_msg)) + } + Call(RequestSent(..)) => { + let peer_pk = triplet.peer_pk.as_str(); + // check whether current node can execute this call + let is_current_peer = peer_pk == exec_ctx.current_peer_id; + if is_current_peer { + Ok(true) + } else { + exec_ctx.subtree_complete = false; + call_ctx.new_path.push_back(prev_state); + Ok(false) + } + } + // this instruction's been already executed + Call(Executed(result)) => { + set_local_call_result(result.clone(), triplet.clone(), output, exec_ctx)?; + call_ctx.new_path.push_back(prev_state); + Ok(false) + } + // state has inconsistent order - return a error, call shouldn't be executed + par_state @ Par(..) => Err(AquamarineError::InvalidEvidenceState( + par_state.clone(), + String::from("call"), + )), + } +} diff --git a/stepper-lib/src/air/execution_context.rs b/stepper-lib/src/air/execution_context.rs index c06fa58e..27f1705a 100644 --- a/stepper-lib/src/air/execution_context.rs +++ b/stepper-lib/src/air/execution_context.rs @@ -21,10 +21,10 @@ use std::collections::VecDeque; use std::fmt::Display; use std::fmt::Formatter; -/// Execution context contains all necessary information needed to execute aqua script. -#[derive(Clone, Default, Debug)] +/// Contains all necessary state needed to execute aqua script. pub(crate) struct ExecutionCtx<'i> { /// Contains all set variables. + // TODO: use shared string (Rc) to avoid copying. pub data_cache: HashMap>, /// Set of peer public keys that should receive resulted data. diff --git a/stepper-lib/src/air/fold.rs b/stepper-lib/src/air/fold.rs index aa4052f9..34422eda 100644 --- a/stepper-lib/src/air/fold.rs +++ b/stepper-lib/src/air/fold.rs @@ -14,68 +14,59 @@ * limitations under the License. */ -use super::resolve::resolve_jvalue; +mod iterable; +mod jvaluable_result; +mod utils; + +use iterable::*; +pub(crate) use jvaluable_result::JValuable; + use super::CallEvidenceCtx; use super::ExecutionCtx; use super::Instruction; use crate::log_instruction; use crate::AValue; use crate::AquamarineError; -use crate::JValue; +use crate::ResolvedCallResult; use crate::Result; -use air_parser::ast::{Fold, Next}; +use air_parser::ast::Fold; +use air_parser::ast::Next; use std::collections::HashMap; use std::rc::Rc; -/* - (fold Iterable i - (par - (call fn [i] acc[]) - (next i) - ) - ) -*/ +use utils::IterableValue; -#[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct FoldState<'i> { - // TODO: maybe change to bidirectional iterator - pub(crate) cursor: usize, - pub(crate) iterable: Rc, + pub(crate) iterable: IterableValue, pub(crate) instr_head: Rc>, // map of met variables inside this (not any inner) fold block with their initial values - pub(crate) met_variables: HashMap<&'i str, Rc>, + pub(crate) met_variables: HashMap<&'i str, ResolvedCallResult>, +} + +impl<'i> FoldState<'i> { + pub fn new(iterable: IterableValue, instr_head: Rc>) -> Self { + Self { + iterable, + instr_head, + met_variables: HashMap::new(), + } + } } impl<'i> super::ExecutableInstruction<'i> for Fold<'i> { fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> { - use AquamarineError::*; + use AquamarineError::MultipleFoldStates; log_instruction!(fold, exec_ctx, call_ctx); - // TODO: implement and call resolve_avalue to reuse existing Rc's - let iterable = resolve_jvalue(&self.iterable, exec_ctx)?; - // check that value exists and has array type - let iterable = match &iterable { - JValue::Array(ref array) => { - if array.is_empty() { - // skip fold if array is empty - return Ok(()); - } - - iterable - } - v => return Err(IncompatibleJValueType(v.clone(), String::from("Array"))), + let iterable = match utils::construct_iterable_value(&self.iterable, exec_ctx)? { + Some(iterable) => iterable, + None => return Ok(()), }; - let fold_state = FoldState { - cursor: 0, - // TODO: reuse existing Rc from JValueRef, if there was some - iterable: Rc::new(iterable), - instr_head: self.instruction.clone(), - met_variables: HashMap::new(), - }; + let fold_state = FoldState::new(iterable, self.instruction.clone()); let previous_value = exec_ctx .data_cache @@ -88,29 +79,7 @@ impl<'i> super::ExecutableInstruction<'i> for Fold<'i> { self.instruction.execute(exec_ctx, call_ctx)?; - let fold_state = match exec_ctx.data_cache.remove(self.iterator) { - Some(AValue::JValueFoldCursor(fold_state)) => fold_state, - _ => unreachable!("fold cursor is changed only inside fold block"), - }; - - for (variable_name, _) in fold_state.met_variables { - exec_ctx.data_cache.remove(variable_name); - } - exec_ctx.met_folds.pop_back(); - - if let Some(fold_block_name) = exec_ctx.met_folds.back() { - let fold_state = match exec_ctx.data_cache.get(*fold_block_name) { - Some(AValue::JValueFoldCursor(fold_state)) => fold_state, - _ => unreachable!("fold block data must be represented as fold cursor"), - }; - - let mut upper_fold_values = HashMap::new(); - for (variable_name, variable) in fold_state.met_variables.iter() { - upper_fold_values.insert(variable_name.to_string(), AValue::JValueRef(variable.clone())); - } - - exec_ctx.data_cache.extend(upper_fold_values); - } + cleanup_variables(exec_ctx, &self.iterator); Ok(()) } @@ -118,6 +87,7 @@ impl<'i> super::ExecutableInstruction<'i> for Fold<'i> { impl<'i> super::ExecutableInstruction<'i> for Next<'i> { fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> { + use AquamarineError::FoldStateNotFound; use AquamarineError::IncompatibleAValueType; log_instruction!(next, exec_ctx, call_ctx); @@ -126,24 +96,21 @@ impl<'i> super::ExecutableInstruction<'i> for Next<'i> { let avalue = exec_ctx .data_cache .get_mut(iterator_name) - .ok_or_else(|| AquamarineError::FoldStateNotFound(iterator_name.to_string()))?; + .ok_or_else(|| FoldStateNotFound(iterator_name.to_string()))?; + let fold_state = match avalue { AValue::JValueFoldCursor(state) => state, v => { + // it's not possible to use unreachable here + // because at now next syntactically could be used without fold return Err(IncompatibleAValueType( - format!("{:?}", v), + format!("{}", v), String::from("JValueFoldCursor"), - )) + )); } }; - let value_len = match fold_state.iterable.as_ref() { - JValue::Array(array) => array.len(), - _ => unreachable!("iterable value shouldn't changed inside fold"), - }; - fold_state.cursor += 1; - if value_len == 0 || value_len <= fold_state.cursor { - fold_state.cursor -= 1; + if !fold_state.iterable.next() { // just do nothing to exit return Ok(()); } @@ -153,7 +120,9 @@ impl<'i> super::ExecutableInstruction<'i> for Next<'i> { // get the same fold state again because of borrow checker match exec_ctx.data_cache.get_mut(iterator_name) { - Some(AValue::JValueFoldCursor(fold_state)) => fold_state.cursor -= 1, + // move iterator back to provide correct value for possible subtree after next + // (for example for cases such as right fold) + Some(AValue::JValueFoldCursor(fold_state)) => fold_state.iterable.prev(), _ => unreachable!("iterator value shouldn't changed inside fold"), }; @@ -161,9 +130,36 @@ impl<'i> super::ExecutableInstruction<'i> for Next<'i> { } } +fn cleanup_variables(exec_ctx: &mut ExecutionCtx<'_>, iterator: &str) { + let fold_state = match exec_ctx.data_cache.remove(iterator) { + Some(AValue::JValueFoldCursor(fold_state)) => fold_state, + _ => unreachable!("fold cursor is changed only inside fold block"), + }; + + for (variable_name, _) in fold_state.met_variables { + exec_ctx.data_cache.remove(variable_name); + } + exec_ctx.met_folds.pop_back(); + + // TODO: fix 3 or more inner folds behaviour + if let Some(fold_block_name) = exec_ctx.met_folds.back() { + let fold_state = match exec_ctx.data_cache.get(*fold_block_name) { + Some(AValue::JValueFoldCursor(fold_state)) => fold_state, + _ => unreachable!("fold block data must be represented as fold cursor"), + }; + + let mut upper_fold_values = HashMap::new(); + for (variable_name, variable) in fold_state.met_variables.iter() { + upper_fold_values.insert(variable_name.to_string(), AValue::JValueRef(variable.clone())); + } + + exec_ctx.data_cache.extend(upper_fold_values); + } +} + #[cfg(test)] mod tests { - use crate::call_evidence::CallEvidencePath; + use crate::CallEvidencePath; use crate::JValue; use aqua_test_utils::call_vm; @@ -177,6 +173,7 @@ mod tests { use serde_json::json; use std::rc::Rc; + // Check that #[test] fn lfold() { env_logger::try_init().ok(); @@ -233,7 +230,9 @@ mod tests { )"#, ); + println!("set variables\n"); let res = call_vm!(set_variable_vm, "", rfold.clone(), "[]", "[]"); + println!("execute rfold\n"); let res = call_vm!(vm, "", rfold, "[]", res.data); let res: CallEvidencePath = serde_json::from_slice(&res.data).expect("should be valid call evidence path"); @@ -293,6 +292,7 @@ mod tests { } #[test] + #[ignore] fn inner_fold_with_same_iterator() { let mut vm = create_aqua_vm(set_variable_call_service(r#"["1","2","3","4","5"]"#), "set_variable"); @@ -352,6 +352,7 @@ mod tests { } #[test] + #[ignore] fn json_path() { use crate::call_evidence::CallResult::*; use crate::call_evidence::EvidenceState::*; @@ -366,7 +367,7 @@ mod tests { r#" (seq (call "set_variable" ("" "") [] Iterable) - (fold Iterable.$["array"] i + (fold Iterable.$["array"]! i (seq (call "A" ("" "") [i] acc[]) (next i) diff --git a/stepper-lib/src/air/fold/iterable.rs b/stepper-lib/src/air/fold/iterable.rs new file mode 100644 index 00000000..6d37c485 --- /dev/null +++ b/stepper-lib/src/air/fold/iterable.rs @@ -0,0 +1,250 @@ +/* + * 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 crate::JValue; +use crate::ResolvedCallResult; +use crate::SecurityTetraplet; + +use std::rc::Rc; + +/// This trait represent bidirectional iterator and +/// is used to abstract values used in fold as iterables. +pub(crate) trait Iterable<'ctx> { + /// Represent iterable type. + type Item; + + /// Move inner iterator to the next value and return true if it exists, + /// does nothing and return false otherwise. + fn next(&mut self) -> bool; + + /// Move inner iterator to the previous value and return true if it exists, + /// does nothing and return false otherwise. + fn prev(&mut self) -> bool; + + /// Return current iterable value if Iterable value is not empty and None otherwise. + fn peek(&'ctx self) -> Option; +} + +/// Combines all possible iterable item types. +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) enum IterableItemType<'ctx> { + RefRef((&'ctx JValue, &'ctx SecurityTetraplet)), + RefValue((&'ctx JValue, SecurityTetraplet)), + RcValue((Rc, SecurityTetraplet)), +} + +/// Used for iterating over JValue of array type. +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) struct IterableResolvedCall { + pub(crate) call_result: ResolvedCallResult, + pub(crate) cursor: usize, + pub(crate) len: usize, +} + +impl IterableResolvedCall { + pub(crate) fn init(call_result: ResolvedCallResult, len: usize) -> Self { + Self { + call_result, + cursor: 0, + len, + } + } +} + +/// Used for iterating over accumulator with JValues. +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) struct IterableVecResolvedCall { + pub(crate) call_results: Vec, + pub(crate) cursor: usize, +} + +impl IterableVecResolvedCall { + pub(crate) fn init(call_results: Vec) -> Self { + Self { + call_results, + cursor: 0, + } + } +} + +/// Used for iterating over a result of applied to a JValue json path. +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) struct IterableJsonPathResult { + pub(crate) jvalues: Vec, + // consider adding index for each tetraplet + pub(crate) tetraplet: SecurityTetraplet, + pub(crate) cursor: usize, +} + +impl IterableJsonPathResult { + pub(crate) fn init(jvalues: Vec, tetraplet: SecurityTetraplet) -> Self { + Self { + jvalues, + tetraplet, + cursor: 0, + } + } +} + +/// Used for iterating over a result of applied to an accumulator json path. +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) struct IterableVecJsonPathResult { + pub(crate) jvalues: Vec, + pub(crate) tetraplets: Vec, + pub(crate) cursor: usize, +} + +impl IterableVecJsonPathResult { + pub(crate) fn init(jvalues: Vec, tetraplets: Vec) -> Self { + // TODO: add assert on length + Self { + jvalues, + tetraplets, + cursor: 0, + } + } +} + +macro_rules! foldable_next { + ($self: expr, $len:expr) => {{ + if $self.cursor + 1 < $len { + $self.cursor += 1; + true + } else { + false + } + }}; +} + +macro_rules! foldable_prev { + ($self: expr) => {{ + if $self.cursor >= 1 { + $self.cursor -= 1; + true + } else { + false + } + }}; +} + +impl<'ctx> Iterable<'ctx> for IterableResolvedCall { + type Item = IterableItemType<'ctx>; + + fn next(&mut self) -> bool { + foldable_next!(self, self.len) + } + + fn prev(&mut self) -> bool { + foldable_prev!(self) + } + + fn peek(&'ctx self) -> Option { + use std::ops::Deref; + + if self.len == 0 { + return None; + } + + let triplet = self.call_result.triplet.clone(); + let tetraplet = SecurityTetraplet { + triplet, + // TODO: consider set json_path to the current cursor here + json_path: String::new(), + }; + + let jvalue = match &self.call_result.result.deref() { + JValue::Array(array) => &array[self.cursor], + _ => unimplemented!("this jvalue is set only by fold instruction, so it must have an array type"), + }; + + let result = IterableItemType::RefValue((jvalue, tetraplet)); + Some(result) + } +} + +impl<'ctx> Iterable<'ctx> for IterableVecResolvedCall { + type Item = IterableItemType<'ctx>; + + fn next(&mut self) -> bool { + foldable_next!(self, self.call_results.len()) + } + + fn prev(&mut self) -> bool { + foldable_prev!(self) + } + + fn peek(&'ctx self) -> Option { + if self.call_results.is_empty() { + return None; + } + + let ResolvedCallResult { result, triplet } = self.call_results[self.cursor].clone(); + let tetraplet = SecurityTetraplet { + triplet, + json_path: String::new(), + }; + + let result = IterableItemType::RcValue((result, tetraplet)); + Some(result) + } +} + +impl<'ctx> Iterable<'ctx> for IterableJsonPathResult { + type Item = IterableItemType<'ctx>; + + fn next(&mut self) -> bool { + foldable_next!(self, self.jvalues.len()) + } + + fn prev(&mut self) -> bool { + foldable_prev!(self) + } + + fn peek(&'ctx self) -> Option { + if self.jvalues.is_empty() { + return None; + } + + let jvalue = &self.jvalues[self.cursor]; + let result = IterableItemType::RefRef((jvalue, &self.tetraplet)); + + Some(result) + } +} + +impl<'ctx> Iterable<'ctx> for IterableVecJsonPathResult { + type Item = IterableItemType<'ctx>; + + fn next(&mut self) -> bool { + foldable_next!(self, self.jvalues.len()) + } + + fn prev(&mut self) -> bool { + foldable_prev!(self) + } + + fn peek(&'ctx self) -> Option { + if self.jvalues.is_empty() { + return None; + } + + let jvalue = &self.jvalues[self.cursor]; + let tetraplet = &self.tetraplets[self.cursor]; + let result = IterableItemType::RefRef((jvalue, tetraplet)); + + Some(result) + } +} diff --git a/stepper-lib/src/air/fold/jvaluable_result.rs b/stepper-lib/src/air/fold/jvaluable_result.rs new file mode 100644 index 00000000..7e408a11 --- /dev/null +++ b/stepper-lib/src/air/fold/jvaluable_result.rs @@ -0,0 +1,201 @@ +/* + * 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 crate::air::fold::IterableItemType; +use crate::JValue; +use crate::ResolvedCallResult; +use crate::Result; +use crate::SecurityTetraplet; + +use std::borrow::Cow; +use std::ops::Deref; + +/// Represent a value that could be transform to a JValue with or without tetraplets. +pub(crate) trait JValuable { + /// Applies json path to the internal value, produces JValue. + fn apply_json_path(&self, json_path: &str) -> Result>; + + /// Applies json path to the internal value, produces JValue with tetraplet. + fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec)>; + + /// Return internal value as borrowed if it's possible, owned otherwise. + fn as_jvalue(&self) -> Cow<'_, JValue>; + + /// Convert this boxed value to an owned JValue. + fn into_jvalue(self: Box) -> JValue; + + /// Return tetraplets associating with internal value. + fn as_tetraplets(&self) -> Vec; +} + +impl<'ctx> JValuable for IterableItemType<'ctx> { + fn apply_json_path(&self, json_path: &str) -> Result> { + use crate::AquamarineError::JValueJsonPathError as JsonPathError; + use jsonpath_lib::select; + use IterableItemType::*; + + let jvalue = match self { + RefRef((jvalue, _)) => *jvalue, + RefValue((jvalue, _)) => jvalue, + RcValue((jvalue, _)) => jvalue.deref(), + }; + + let selected_jvalues = + select(jvalue, json_path).map_err(|e| JsonPathError(jvalue.clone(), String::from(json_path), e))?; + Ok(selected_jvalues) + } + + fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec)> { + use crate::AquamarineError::JValueJsonPathError as JsonPathError; + use jsonpath_lib::select; + use IterableItemType::*; + + let (jvalue, tetraplet) = match self { + RefRef((jvalue, tetraplet)) => (*jvalue, *tetraplet), + RefValue((jvalue, tetraplet)) => (*jvalue, tetraplet), + RcValue((jvalue, tetraplet)) => (jvalue.deref(), tetraplet), + }; + + let selected_jvalues = + select(jvalue, json_path).map_err(|e| JsonPathError(jvalue.clone(), String::from(json_path), e))?; + Ok((selected_jvalues, vec![tetraplet.clone()])) + } + + fn as_jvalue(&self) -> Cow<'_, JValue> { + use IterableItemType::*; + + match self { + RefRef((jvalue, _)) => Cow::Borrowed(jvalue), + RefValue((jvalue, _)) => Cow::Borrowed(jvalue), + RcValue((jvalue, _)) => Cow::Borrowed(jvalue.deref()), + } + } + + fn into_jvalue(self: Box) -> JValue { + use IterableItemType::*; + + match *self { + RefRef((jvalue, _)) => jvalue.deref().clone(), + RefValue((jvalue, _)) => jvalue.clone(), + RcValue((jvalue, _)) => jvalue.deref().clone(), + } + } + + fn as_tetraplets(&self) -> Vec { + use IterableItemType::*; + + // these clones are needed because rust-sdk allows passing arguments only by value + match self { + RefRef((_, tetraplet)) => { + let tetraplet = tetraplet.deref().clone(); + vec![tetraplet] + } + RefValue((_, tetraplet)) => vec![(*tetraplet).clone()], + RcValue((_, tetraplet)) => vec![(*tetraplet).clone()], + } + } +} + +impl JValuable for ResolvedCallResult { + fn apply_json_path(&self, json_path: &str) -> Result> { + use crate::AquamarineError::JValueJsonPathError as JsonPathError; + use jsonpath_lib::select; + + let selected_jvalues = select(&self.result, json_path) + .map_err(|e| JsonPathError(self.result.deref().clone(), String::from(json_path), e))?; + Ok(selected_jvalues) + } + + fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec)> { + use crate::AquamarineError::JValueJsonPathError as JsonPathError; + use jsonpath_lib::select; + + let selected_jvalues = select(&self.result, json_path) + .map_err(|e| JsonPathError(self.result.deref().clone(), String::from(json_path), e))?; + + let tetraplet = SecurityTetraplet { + triplet: self.triplet.clone(), + json_path: json_path.to_string(), + }; + + Ok((selected_jvalues, vec![tetraplet])) + } + + fn as_jvalue(&self) -> Cow<'_, JValue> { + Cow::Borrowed(&self.result) + } + + fn into_jvalue(self: Box) -> JValue { + self.result.deref().clone() + } + + fn as_tetraplets(&self) -> Vec { + let tetraplet = SecurityTetraplet { + triplet: self.triplet.clone(), + json_path: String::new(), + }; + + vec![tetraplet] + } +} + +impl JValuable for std::cell::Ref<'_, Vec> { + fn apply_json_path(&self, json_path: &str) -> Result> { + use jsonpath_lib::select_with_iter; + + let (selected_values, _) = select_with_iter(self.iter().map(|r| r.result.deref()), json_path).unwrap(); + + Ok(selected_values) + } + + fn apply_json_path_with_tetraplets(&self, json_path: &str) -> Result<(Vec<&JValue>, Vec)> { + use jsonpath_lib::select_with_iter; + + let (selected_values, tetraplet_indices) = + select_with_iter(self.iter().map(|r| r.result.deref()), json_path).unwrap(); + let tetraplets = tetraplet_indices + .into_iter() + .map(|id| self[id].triplet.clone()) + .map(|triplet| SecurityTetraplet { + triplet, + json_path: json_path.to_string(), + }) + .collect::>(); + + Ok((selected_values, tetraplets)) + } + + fn as_jvalue(&self) -> Cow<'_, JValue> { + let jvalue_array = self.iter().map(|r| r.result.deref().clone()).collect::>(); + Cow::Owned(JValue::Array(jvalue_array)) + } + + fn into_jvalue(self: Box) -> JValue { + let jvalue_array = self.iter().map(|r| r.result.deref().clone()).collect::>(); + JValue::Array(jvalue_array) + } + + fn as_tetraplets(&self) -> Vec { + self.iter() + // this cloned is needed because of rust-sdk allows passing arguments only by value + .map(|r| r.triplet.clone()) + .map(|triplet| SecurityTetraplet { + triplet, + json_path: String::new(), + }) + .collect::>() + } +} diff --git a/stepper-lib/src/air/fold/utils.rs b/stepper-lib/src/air/fold/utils.rs new file mode 100644 index 00000000..ea198706 --- /dev/null +++ b/stepper-lib/src/air/fold/utils.rs @@ -0,0 +1,149 @@ +/* + * 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 super::iterable::*; +use super::Iterable; +use super::IterableItemType; +use crate::air::ExecutionCtx; +use crate::AValue; +use crate::AquamarineError; +use crate::JValue; +use crate::Result; +use crate::SecurityTetraplet; + +use air_parser::ast::InstructionValue; + +use std::ops::Deref; + +pub(super) type IterableValue = Box Iterable<'ctx, Item = IterableItemType<'ctx>>>; + +/// Constructs iterable value for given instruction value, +/// return Some if iterable isn't empty and None otherwise. +pub(super) fn construct_iterable_value<'ctx>( + value: &InstructionValue<'ctx>, + exec_ctx: &ExecutionCtx<'ctx>, +) -> Result> { + match value { + InstructionValue::Variable(name) => handle_instruction_variable(exec_ctx, name), + 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"), + } +} + +fn handle_instruction_variable<'ctx>( + exec_ctx: &ExecutionCtx<'ctx>, + variable_name: &str, +) -> Result> { + use AquamarineError::IncompatibleJValueType; + + 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)) => { + let acc = acc.borrow(); + if acc.is_empty() { + return Ok(None); + } + + let call_results = acc.iter().cloned().collect::>(); + let foldable = IterableVecResolvedCall::init(call_results); + Box::new(foldable) + } + _ => { + return Err(AquamarineError::InstructionError(String::from( + "At now, it isn't possible to use fold iterator in other folds", + ))) + } + }; + + Ok(Some(iterable)) +} + +fn handle_instruction_json_path<'ctx>( + exec_ctx: &ExecutionCtx<'ctx>, + variable: &str, + path: &str, +) -> Result> { + use AquamarineError::JValueAccJsonPathError; + use AquamarineError::JValueJsonPathError; + + let iterable: IterableValue = match exec_ctx.data_cache.get(variable) { + Some(AValue::JValueRef(variable)) => { + use jsonpath_lib::select; + + 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)) => { + use jsonpath_lib::select_with_iter; + + let acc = acc.borrow(); + if acc.is_empty() { + return Ok(None); + } + + let (jvalues, tetraplet_indices) = select_with_iter(acc.iter().map(|v| v.result.deref()), &path) + .map_err(|e| JValueAccJsonPathError(acc.clone(), path.to_string(), e))?; + let jvalues = jvalues.into_iter().cloned().collect(); + let tetraplets = tetraplet_indices + .iter() + .map(|&id| &acc[id].triplet) + .map(|triplet| SecurityTetraplet { + triplet: triplet.clone(), + json_path: path.to_string(), + }) + .collect::>(); + + let foldable = IterableVecJsonPathResult::init(jvalues, tetraplets); + Box::new(foldable) + } + _ => { + return Err(AquamarineError::InstructionError(String::from( + "At now, it isn't possible to use fold iterator in other folds", + ))) + } + }; + + Ok(Some(iterable)) +} diff --git a/stepper-lib/src/air/resolve.rs b/stepper-lib/src/air/resolve.rs index c11be911..4631bf2c 100644 --- a/stepper-lib/src/air/resolve.rs +++ b/stepper-lib/src/air/resolve.rs @@ -14,108 +14,68 @@ * limitations under the License. */ +use super::fold::JValuable; use super::ExecutionCtx; use crate::AValue; use crate::AquamarineError; use crate::JValue; use crate::Result; +use crate::SecurityTetraplet; -use air_parser::ast::Value; +use air_parser::ast::InstructionValue; -use std::borrow::Cow; +/// Resolve value to called function arguments. +pub(crate) fn resolve_to_args<'i>( + value: &InstructionValue<'i>, + ctx: &ExecutionCtx<'i>, +) -> Result<(JValue, Vec)> { + fn handle_string_arg<'i>(arg: &str, ctx: &ExecutionCtx<'i>) -> Result<(JValue, Vec)> { + let jvalue = JValue::String(arg.to_string()); + let tetraplet = SecurityTetraplet::literal_tetraplet(ctx.init_peer_id.clone()); -/// Resolve value to JValue, similar to `resolve_value` -pub(crate) fn resolve_jvalue<'i>(value: &Value<'i>, ctx: &ExecutionCtx<'i>) -> Result { - let value = match value { - Value::CurrentPeerId => JValue::String(ctx.current_peer_id.clone()), - Value::InitPeerId => JValue::String(ctx.init_peer_id.clone()), - Value::Literal(value) => JValue::String(value.to_string()), - Value::Variable(name) => resolve_variable(name, ctx)?, - Value::JsonPath { variable, path } => { - let value = resolve_variable(variable, ctx)?; - apply_json_path(value, path)? + Ok((jvalue, vec![tetraplet])) + } + + match value { + InstructionValue::CurrentPeerId => handle_string_arg(ctx.current_peer_id.as_str(), ctx), + InstructionValue::InitPeerId => handle_string_arg(ctx.init_peer_id.as_str(), ctx), + InstructionValue::Literal(value) => handle_string_arg(value, ctx), + InstructionValue::Variable(name) => { + let resolved = resolve_to_jvaluable(name, ctx)?; + let tetraplets = resolved.as_tetraplets(); + let jvalue = resolved.into_jvalue(); + + Ok((jvalue, tetraplets)) } - }; + InstructionValue::JsonPath { variable, path } => { + let resolved = resolve_to_jvaluable(variable, ctx)?; + let (jvalue, tetraplets) = resolved.apply_json_path_with_tetraplets(path)?; + let jvalue = jvalue.into_iter().cloned().collect::>(); + let jvalue = JValue::Array(jvalue); - Ok(value) + Ok((jvalue, tetraplets)) + } + } } -/// Takes variable's value from `ExecutionCtx::data_cache` -/// TODO: maybe return &'i JValue? -pub(crate) fn resolve_variable<'exec_ctx, 'i>(variable: &'i str, ctx: &'exec_ctx ExecutionCtx<'i>) -> Result { +/// Constructs jvaluable result from `ExecutionCtx::data_cache` by name. +pub(crate) fn resolve_to_jvaluable<'name, 'i, 'ctx>( + name: &'name str, + ctx: &'ctx ExecutionCtx<'i>, +) -> Result> { use AquamarineError::VariableNotFound; let value = ctx .data_cache - .get(variable) - .ok_or_else(|| VariableNotFound(variable.to_string()))?; + .get(name) + .ok_or_else(|| VariableNotFound(name.to_string()))?; match value { + AValue::JValueRef(value) => Ok(Box::new(value.clone())), + AValue::JValueAccumulatorRef(acc) => Ok(Box::new(acc.borrow())), AValue::JValueFoldCursor(fold_state) => { - if let JValue::Array(array) = fold_state.iterable.as_ref() { - Ok(array[fold_state.cursor].clone()) - } else { - unreachable!("fold state must be well-formed because it is changed only by stepper") - } - } - AValue::JValueRef(value) => Ok(value.as_ref().clone()), - AValue::JValueAccumulatorRef(acc) => { - let owned_acc = acc.borrow().iter().map(|v| v.as_ref()).cloned().collect::>(); - Ok(JValue::Array(owned_acc)) + let peeked_value = fold_state.iterable.peek().unwrap(); + Ok(Box::new(peeked_value)) } } } - -/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc -pub(crate) fn resolve_value<'i, 'a: 'i>(value: &'a Value<'i>, ctx: &'a ExecutionCtx<'i>) -> Result> { - let resolved = match value { - Value::CurrentPeerId => Cow::Borrowed(ctx.current_peer_id.as_str()), - Value::InitPeerId => Cow::Borrowed(ctx.init_peer_id.as_str()), - Value::Literal(value) => Cow::Borrowed(*value), - Value::Variable(name) => { - let resolved = resolve_variable(name, ctx)?; - let resolved = require_string(resolved)?; - Cow::Owned(resolved) - } - Value::JsonPath { variable, path } => { - let resolved = resolve_variable(variable, ctx)?; - let resolved = apply_json_path(resolved, path)?; - let resolved = require_string(resolved)?; - Cow::Owned(resolved) - } - }; - - Ok(resolved) -} - -pub(crate) fn require_string(value: JValue) -> Result { - if let JValue::String(s) = value { - Ok(s) - } else { - Err(AquamarineError::IncompatibleJValueType(value, "string".to_string())) - } -} - -pub(crate) fn apply_json_path(jvalue: JValue, json_path: &str) -> Result { - let values = find_by_json_path(&jvalue, json_path)?; - if values.is_empty() { - return Err(AquamarineError::VariableNotFound(json_path.to_string())); - } - - if values.len() != 1 { - return Err(AquamarineError::MultipleValuesInJsonPath(json_path.to_string())); - } - - // TODO: sure need this clone? - Ok(values[0].clone()) -} - -/// Applies `json_path` to `jvalue` -fn find_by_json_path<'jvalue, 'json_path>( - jvalue: &'jvalue JValue, - json_path: &'json_path str, -) -> Result> { - use AquamarineError::VariableNotInJsonPath as JsonPathError; - - jsonpath_lib::select(jvalue, json_path).map_err(|e| JsonPathError(jvalue.clone(), String::from(json_path), e)) -} diff --git a/stepper-lib/src/air/xor.rs b/stepper-lib/src/air/xor.rs index 60421b38..61f9c994 100644 --- a/stepper-lib/src/air/xor.rs +++ b/stepper-lib/src/air/xor.rs @@ -89,13 +89,11 @@ mod tests { let res = call_vm!(vm, "asd", script, "[]", "[]"); let call_path: CallEvidencePath = serde_json::from_slice(&res.data).expect("should be valid json"); + let executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("res"))))); assert_eq!(call_path.len(), 2); assert_eq!(call_path[0], Call(CallServiceFailed(String::from(r#""error""#)))); - assert_eq!( - call_path[1], - Call(Executed(Rc::new(JValue::String(String::from("res"))))) - ); + assert_eq!(call_path[1], executed_call_result); let script = String::from( r#" @@ -109,10 +107,7 @@ mod tests { let call_path: CallEvidencePath = serde_json::from_slice(&res.data).expect("should be valid json"); assert_eq!(call_path.len(), 1); - assert_eq!( - call_path[0], - Call(Executed(Rc::new(JValue::String(String::from("res"))))) - ); + assert_eq!(call_path[0], executed_call_result); } #[test] @@ -121,7 +116,7 @@ mod tests { use crate::call_evidence::EvidenceState::*; let fallible_service_id = String::from("service_id_1"); - let mut vm = create_aqua_vm(fallible_call_service(fallible_service_id), ""); + let mut vm = create_aqua_vm(fallible_call_service(fallible_service_id.clone()), ""); let script = String::from( r#" @@ -147,15 +142,16 @@ mod tests { let result_path: CallEvidencePath = serde_json::from_slice(&result.data).expect("should be valid json"); let res = String::from("res"); + let executed_call_result = Rc::new(JValue::String(res)); let right_path = vec![ Par(2, 2), - Call(Executed(Rc::new(JValue::String(res.clone())))), - Call(Executed(Rc::new(JValue::String(res.clone())))), + Call(Executed(executed_call_result.clone())), + Call(Executed(executed_call_result.clone())), Par(1, 0), Call(CallServiceFailed(String::from(r#""error""#))), - Call(Executed(Rc::new(JValue::String(res.clone())))), - Call(Executed(Rc::new(JValue::String(res)))), + Call(Executed(executed_call_result.clone())), + Call(Executed(executed_call_result.clone())), ]; assert_eq!(result_path, right_path); diff --git a/stepper-lib/src/build_targets/fce_target.rs b/stepper-lib/src/build_targets/fce_target.rs index a8fc6684..f7e38ef6 100644 --- a/stepper-lib/src/build_targets/fce_target.rs +++ b/stepper-lib/src/build_targets/fce_target.rs @@ -15,16 +15,24 @@ */ use super::CallServiceResult; + +use fluence::fce; + use std::env::VarError; const CURRENT_PEER_ID_ENV_NAME: &str = "CURRENT_PEER_ID"; -pub fn get_current_peer_id() -> std::result::Result { +pub(crate) fn get_current_peer_id() -> std::result::Result { std::env::var(CURRENT_PEER_ID_ENV_NAME) } -#[fluence::fce] +#[fce] #[link(wasm_import_module = "host")] extern "C" { - pub(crate) fn call_service(service_id: String, fn_name: String, args: String) -> CallServiceResult; + pub(crate) fn call_service( + service_id: String, + fn_name: String, + args: String, + tetraplets: String, + ) -> CallServiceResult; } diff --git a/stepper-lib/src/build_targets/wasm_bindgen_target.rs b/stepper-lib/src/build_targets/wasm_bindgen_target.rs index 2cbc0b68..11079c96 100644 --- a/stepper-lib/src/build_targets/wasm_bindgen_target.rs +++ b/stepper-lib/src/build_targets/wasm_bindgen_target.rs @@ -17,9 +17,15 @@ use wasm_bindgen::__rt::std::env::VarError; use wasm_bindgen::prelude::*; -pub(crate) fn call_service(service_id: String, fn_name: String, args: String) -> super::CallServiceResult { - let result = call_service_impl(service_id, fn_name, args); +pub(crate) fn call_service( + service_id: String, + fn_name: String, + args: String, + security_tetraplets: String, +) -> super::CallServiceResult { + let result = call_service_impl(service_id, fn_name, args, security_tetraplets); log::trace!("result {}", result); + serde_json::from_str(&result).expect("Cannot parse CallServiceResult") } @@ -36,5 +42,5 @@ extern "C" { #[wasm_bindgen(raw_module = "../src/call_service.ts")] extern "C" { #[link_name = "call_service"] - fn call_service_impl(service_id: String, fn_name: String, args: String) -> String; + fn call_service_impl(service_id: String, fn_name: String, args: String, security_tetraplets: String) -> String; } diff --git a/stepper-lib/src/call_evidence/context.rs b/stepper-lib/src/call_evidence/context.rs index e21a8750..a1e405e3 100644 --- a/stepper-lib/src/call_evidence/context.rs +++ b/stepper-lib/src/call_evidence/context.rs @@ -21,11 +21,18 @@ use serde::Serialize; use std::fmt::Display; use std::fmt::Formatter; +/// Encapsulates all necessary state regarding to the call pathes. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub(crate) struct CallEvidenceCtx { + /// Contains path (serialized tree of states) after merging current and previous data, + /// stepper used it to realize which instructions've been already executed. pub(crate) current_path: CallEvidencePath, + + /// Size of a current considered subtree inside current path. pub(crate) current_subtree_size: usize, + // TODO: consider change it to Vec for optimization + /// Accumulator for resulted path produced by the stepper after execution. pub(crate) new_path: CallEvidencePath, } diff --git a/stepper-lib/src/call_evidence/state.rs b/stepper-lib/src/call_evidence/state.rs index 3f12c746..3afec3e9 100644 --- a/stepper-lib/src/call_evidence/state.rs +++ b/stepper-lib/src/call_evidence/state.rs @@ -188,7 +188,7 @@ impl std::fmt::Display for EvidenceState { match self { Par(left, right) => write!(f, "Par({}, {})", left, right), Call(RequestSent(peer_id)) => write!(f, "RequestSent({})", peer_id), - Call(Executed(result)) => write!(f, "Executed({})", result), + Call(Executed(result)) => write!(f, "Executed({:?})", result), Call(CallServiceFailed(err_msg)) => write!(f, "CallServiceFailed({})", err_msg), } } diff --git a/stepper-lib/src/errors.rs b/stepper-lib/src/errors.rs index 35693fbf..82552e8c 100644 --- a/stepper-lib/src/errors.rs +++ b/stepper-lib/src/errors.rs @@ -18,6 +18,7 @@ use crate::build_targets::CallServiceResult; use crate::call_evidence::CallResult; use crate::call_evidence::EvidenceState; use crate::JValue; +use crate::ResolvedCallResult; use jsonpath_lib::JsonPathError; use serde_json::Error as SerdeJsonError; @@ -51,11 +52,14 @@ pub enum AquamarineError { /// Multiple values for such name found. MultipleVariablesFound(String), - /// Value with such path wasn't found in data with such error. - VariableNotInJsonPath(JValue, String, JsonPathError), + /// An error occurred while trying to apply json path to this JValue. + JValueJsonPathError(JValue, String, JsonPathError), + + /// An error occurred while trying to apply json path to this accumulator with JValue's. + JValueAccJsonPathError(Vec, String, JsonPathError), /// Provided JValue has incompatible with target type. - IncompatibleJValueType(JValue, String), + IncompatibleJValueType(JValue, &'static str), /// Provided AValue has incompatible with target type. IncompatibleAValueType(String, String), @@ -102,19 +106,20 @@ impl AquamarineError { AquamarineError::LocalServiceError(..) => 6, AquamarineError::VariableNotFound(..) => 7, AquamarineError::MultipleVariablesFound(..) => 8, - AquamarineError::VariableNotInJsonPath(..) => 9, - AquamarineError::IncompatibleJValueType(..) => 10, - AquamarineError::IncompatibleAValueType(..) => 11, - AquamarineError::MultipleValuesInJsonPath(..) => 12, - AquamarineError::FoldStateNotFound(..) => 13, - AquamarineError::MultipleFoldStates(..) => 14, - AquamarineError::InvalidEvidenceState(..) => 15, - AquamarineError::CallEvidenceDeserializationError(..) => 16, - AquamarineError::CallEvidenceSerializationError(..) => 17, - AquamarineError::IncompatibleEvidenceStates(..) => 18, - AquamarineError::IncompatibleCallResults(..) => 19, - AquamarineError::EvidencePathTooSmall(..) => 20, - AquamarineError::ShadowingError(_) => 21, + AquamarineError::JValueJsonPathError(..) => 9, + AquamarineError::JValueAccJsonPathError(..) => 10, + AquamarineError::IncompatibleJValueType(..) => 11, + AquamarineError::IncompatibleAValueType(..) => 12, + AquamarineError::MultipleValuesInJsonPath(..) => 13, + AquamarineError::FoldStateNotFound(..) => 14, + AquamarineError::MultipleFoldStates(..) => 15, + AquamarineError::InvalidEvidenceState(..) => 16, + AquamarineError::CallEvidenceDeserializationError(..) => 17, + AquamarineError::CallEvidenceSerializationError(..) => 18, + AquamarineError::IncompatibleEvidenceStates(..) => 19, + AquamarineError::IncompatibleCallResults(..) => 20, + AquamarineError::EvidencePathTooSmall(..) => 21, + AquamarineError::ShadowingError(_) => 22, } } } @@ -148,7 +153,12 @@ impl std::fmt::Display for AquamarineError { AquamarineError::MultipleVariablesFound(variable_name) => { write!(f, "multiple variables found for name {} in data", variable_name) } - AquamarineError::VariableNotInJsonPath(value, json_path, json_path_err) => write!( + AquamarineError::JValueJsonPathError(value, json_path, json_path_err) => write!( + f, + "variable with path {} not found in {:?} with error: {:?}", + json_path, value, json_path_err + ), + AquamarineError::JValueAccJsonPathError(value, json_path, json_path_err) => write!( f, "variable with path {} not found in {:?} with error: {:?}", json_path, value, json_path_err diff --git a/stepper-lib/src/lib.rs b/stepper-lib/src/lib.rs index 2e25e5af..88454366 100644 --- a/stepper-lib/src/lib.rs +++ b/stepper-lib/src/lib.rs @@ -41,24 +41,37 @@ pub use air_parser::ast::Instruction; pub use execution::execute_aqua; pub use execution::parse; +pub use polyplets::ResolvedTriplet; +pub use polyplets::SecurityTetraplet; + pub(crate) type Result = std::result::Result; pub(crate) type JValue = serde_json::Value; pub(crate) use build_targets::call_service; pub(crate) use build_targets::get_current_peer_id; +use serde::Deserialize; +use serde::Serialize; + use std::cell::RefCell; use std::fmt::Display; use std::fmt::Formatter; use std::rc::Rc; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct ResolvedCallResult { + pub result: Rc, + pub triplet: Rc, +} + pub(crate) enum AValue<'i> { - JValueRef(Rc), - JValueAccumulatorRef(RefCell>>), + JValueRef(ResolvedCallResult), + JValueAccumulatorRef(RefCell>), JValueFoldCursor(crate::air::FoldState<'i>), } +pub(crate) trait JValuable {} + impl<'i> Display for AValue<'i> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -70,8 +83,8 @@ impl<'i> Display for AValue<'i> { } write!(f, "]")?; } - AValue::JValueFoldCursor(fold_state) => { - write!(f, "cursor: {}, iterable: {}", fold_state.cursor, fold_state.iterable)?; + AValue::JValueFoldCursor(_) => { + write!(f, "cursor")?; } } diff --git a/stepper-lib/src/stepper_outcome.rs b/stepper-lib/src/stepper_outcome.rs new file mode 100644 index 00000000..763bcc14 --- /dev/null +++ b/stepper-lib/src/stepper_outcome.rs @@ -0,0 +1,34 @@ +/* + * 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 fluence::fce; +use serde::{Deserialize, Serialize}; + +pub const STEPPER_SUCCESS: i32 = 0; + +/// Describes a return value of the stepper. +#[fce] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct StepperOutcome { + /// A return code, where SUCCESS_ERROR_CODE means success. + pub ret_code: i32, + + /// Contains data if ret_code == 0, otherwise error message (that could be empty string). + pub data: String, + + /// Public keys of peers that should receive data. + pub next_peer_pks: Vec, +} diff --git a/stepper-lib/tests/air_basic.rs b/stepper-lib/tests/air_basic.rs index 99367485..cf938f6d 100644 --- a/stepper-lib/tests/air_basic.rs +++ b/stepper-lib/tests/air_basic.rs @@ -153,28 +153,7 @@ fn create_service() { let mut vm = create_aqua_vm(call_service, "A"); - let script = String::from( - r#" - (seq - (seq - (seq - (call "set_variables" ("" "") ["module_bytes"] module_bytes) - (call "set_variables" ("" "") ["module_config"] module_config) - ) - (call "set_variables" ("" "") ["blueprint"] blueprint) - ) - (seq - (call "A" ("add_module" "") [module_bytes module_config] module) - (seq - (call "A" ("add_blueprint" "") [blueprint] blueprint_id) - (seq - (call "A" ("create" "") [blueprint_id] service_id) - (call "remote_peer_id" ("" "") [service_id] client_result) - ) - ) - ) - )"#, - ); + let script = include_str!("./scripts/create_service.clj"); let res = call_vm!(set_variables_vm, "init_peer_id", script.clone(), "[]", "[]"); let res = call_vm!(vm, "init_peer_id", script, "[]", res.data); diff --git a/stepper-lib/tests/build_test_binaries.sh b/stepper-lib/tests/build_test_binaries.sh new file mode 100755 index 00000000..087b3455 --- /dev/null +++ b/stepper-lib/tests/build_test_binaries.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail + +for dir in ./security_tetraplets/*; do + # skip non-directory entries + [ -d "$dir" ] || continue + + (cd "$dir"; fce build) +done diff --git a/stepper-lib/tests/call_evidence_basic.rs b/stepper-lib/tests/call_evidence_basic.rs index 7509e055..7dbc14f3 100644 --- a/stepper-lib/tests/call_evidence_basic.rs +++ b/stepper-lib/tests/call_evidence_basic.rs @@ -202,28 +202,7 @@ fn evidence_create_service() { let mut vm = create_aqua_vm(call_service, "A"); - let script = String::from( - r#" - (seq - (seq - (seq - (call "set_variables" ("add_module" "") ["module_bytes"] module_bytes) - (call "set_variables" ("add_module" "") ["module_config"] module_config) - ) - (call "set_variables" ("add_module" "") ["blueprint"] blueprint) - ) - (seq - (call "A" ("add_module" "") [module_bytes module_config] module) - (seq - (call "A" ("add_blueprint" "") [blueprint] blueprint_id) - (seq - (call "A" ("create" "") [blueprint_id] service_id) - (call "remote_peer_id" ("" "") [service_id] client_result) - ) - ) - ) - )"#, - ); + let script = include_str!("./scripts/create_service.clj"); let add_module_response = String::from("add_module response"); let add_blueprint_response = String::from("add_blueprint response"); diff --git a/stepper-lib/tests/dashboard.rs b/stepper-lib/tests/dashboard.rs index d89da39d..a0402e15 100644 --- a/stepper-lib/tests/dashboard.rs +++ b/stepper-lib/tests/dashboard.rs @@ -182,7 +182,7 @@ struct AquaVMState { #[test] fn dashboard() { - let script = include_str!("dashboard/script.clj"); + let script = include_str!("./scripts/dashboard.clj"); let known_peer_ids = parse_peers(); let client_id = String::from("client_id"); diff --git a/stepper-lib/tests/scripts/create_service.clj b/stepper-lib/tests/scripts/create_service.clj new file mode 100644 index 00000000..d549c141 --- /dev/null +++ b/stepper-lib/tests/scripts/create_service.clj @@ -0,0 +1,19 @@ +(seq + (seq + (seq + (call "set_variables" ("add_module" "") ["module_bytes"] module_bytes) + (call "set_variables" ("add_module" "") ["module_config"] module_config) + ) + (call "set_variables" ("add_module" "") ["blueprint"] blueprint) + ) + (seq + (call "A" ("add_module" "") [module_bytes module_config] module) + (seq + (call "A" ("add_blueprint" "") [blueprint] blueprint_id) + (seq + (call "A" ("create" "") [blueprint_id] service_id) + (call "remote_peer_id" ("" "") [service_id] client_result) + ) + ) + ) + ) diff --git a/stepper-lib/tests/dashboard/script.clj b/stepper-lib/tests/scripts/dashboard.clj similarity index 100% rename from stepper-lib/tests/dashboard/script.clj rename to stepper-lib/tests/scripts/dashboard.clj diff --git a/stepper-lib/tests/security_tetraplets.rs b/stepper-lib/tests/security_tetraplets.rs new file mode 100644 index 00000000..18e15b2b --- /dev/null +++ b/stepper-lib/tests/security_tetraplets.rs @@ -0,0 +1,301 @@ +/* + * 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::HostExportedFunc; +use aqua_test_utils::IValue; +use aqua_test_utils::Vec1; +use polyplets::ResolvedTriplet; +use polyplets::SecurityTetraplet; + +use std::cell::RefCell; +use std::rc::Rc; + +type ArgTetraplets = Vec>; + +fn arg_host_function() -> (HostExportedFunc, Rc>) { + let arg_tetraplets = Rc::new(RefCell::new(ArgTetraplets::new())); + + let arg_tetraplets_inner = arg_tetraplets.clone(); + let host_function: HostExportedFunc = Box::new(move |_, args| -> Option { + let tetraplets = match &args[3] { + IValue::String(str) => str, + _ => unreachable!(), + }; + + let de_tetraplets: ArgTetraplets = + serde_json::from_str(tetraplets).expect("json deserialization shouldn't fail"); + *arg_tetraplets_inner.borrow_mut() = de_tetraplets; + + Some(IValue::Record( + Vec1::new(vec![IValue::S32(0), IValue::String(tetraplets.clone())]).unwrap(), + )) + }); + + (host_function, arg_tetraplets) +} + +#[test] +fn simple_fold() { + let return_numbers_call_service: HostExportedFunc = Box::new(|_, _| -> Option { + Some(IValue::Record( + Vec1::new(vec![ + IValue::S32(0), + IValue::String(String::from( + "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]", + )), + ]) + .unwrap(), + )) + }); + + let set_variable_vm_peer_id = String::from("some_peer_id_1"); + let mut set_variable_vm = create_aqua_vm(return_numbers_call_service, set_variable_vm_peer_id.clone()); + + let mut client_vms = Vec::new(); + for i in 1..=10 { + let (arg_host_func, arg_tetraplets) = arg_host_function(); + let vm = create_aqua_vm(arg_host_func, i.to_string()); + client_vms.push((vm, arg_tetraplets)) + } + + let service_id = String::from("some_service_id"); + let function_name = String::from("some_function_name"); + let script = format!( + r#" + (seq + (call "{}" ("{}" "{}") [] IterableResultPeer1) + (fold IterableResultPeer1 i + (par + (call i ("local_service_id" "local_fn_name") [i "some_text_literal"] acc[]) + (next i) + ) + ) + ) + "#, + set_variable_vm_peer_id, service_id, function_name + ); + + let init_peer_id = String::from("some_init_peer_id"); + let res = call_vm!(set_variable_vm, init_peer_id.clone(), script.clone(), "", ""); + let mut data = res.data; + + let first_arg_triplet = ResolvedTriplet { + peer_pk: set_variable_vm_peer_id, + service_id, + function_name, + }; + let first_arg_triplet = Rc::new(first_arg_triplet); + let first_arg_tetraplet = SecurityTetraplet { + triplet: first_arg_triplet, + json_path: String::new(), + }; + + let second_arg_triplet = ResolvedTriplet { + peer_pk: init_peer_id.clone(), + service_id: String::new(), + function_name: String::new(), + }; + let second_arg_triplet = Rc::new(second_arg_triplet); + let second_arg_tetraplet = SecurityTetraplet { + triplet: second_arg_triplet, + json_path: String::new(), + }; + + let right_tetraplets = vec![vec![first_arg_tetraplet], vec![second_arg_tetraplet]]; + let right_tetraplets = Rc::new(RefCell::new(right_tetraplets)); + for i in 0..10 { + let res = call_vm!(client_vms[i].0, init_peer_id.clone(), script.clone(), "[]", data); + data = res.data; + + assert_eq!(client_vms[i].1, right_tetraplets); + } +} + +#[test] +fn fold_json_path() { + let return_numbers_call_service: HostExportedFunc = Box::new(|_, _| -> Option { + Some(IValue::Record( + Vec1::new(vec![ + IValue::S32(0), + IValue::String(String::from( + "{\"arg\": [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\"]}", + )), + ]) + .unwrap(), + )) + }); + + let set_variable_vm_peer_id = String::from("some_peer_id_1"); + let mut set_variable_vm = create_aqua_vm(return_numbers_call_service, set_variable_vm_peer_id.clone()); + + let (arg_host_func, arg_tetraplets) = arg_host_function(); + let client_peer_id = String::from("client_id"); + let mut client_vm = create_aqua_vm(arg_host_func, client_peer_id.clone()); + + let service_id = String::from("some_service_id"); + let function_name = String::from("some_function_name"); + let script = format!( + r#" + (seq + (call "{}" ("{}" "{}") [] IterableResultPeer1) + (fold IterableResultPeer1.$.arg i + (par + (call "{}" ("local_service_id" "local_fn_name") [i "some_text_literal"] acc[]) + (next i) + ) + ) + ) + "#, + set_variable_vm_peer_id, service_id, function_name, client_peer_id + ); + + let init_peer_id = String::from("some_init_peer_id"); + let res = call_vm!(set_variable_vm, init_peer_id.clone(), script.clone(), "", ""); + + let first_arg_triplet = ResolvedTriplet { + peer_pk: set_variable_vm_peer_id, + service_id, + function_name, + }; + let first_arg_triplet = Rc::new(first_arg_triplet); + let first_arg_tetraplet = SecurityTetraplet { + triplet: first_arg_triplet, + json_path: String::from("$.arg"), + }; + + let second_arg_triplet = ResolvedTriplet { + peer_pk: init_peer_id.clone(), + service_id: String::new(), + function_name: String::new(), + }; + let second_arg_triplet = Rc::new(second_arg_triplet); + let second_arg_tetraplet = SecurityTetraplet { + triplet: second_arg_triplet, + json_path: String::new(), + }; + + let right_tetraplets = vec![vec![first_arg_tetraplet], vec![second_arg_tetraplet]]; + let right_tetraplets = Rc::new(RefCell::new(right_tetraplets)); + call_vm!(client_vm, init_peer_id.clone(), script.clone(), "[]", res.data); + assert_eq!(arg_tetraplets, right_tetraplets); +} + +use fluence_app_service::AppService; +use fluence_app_service::AppServiceConfig; +use fluence_app_service::FaaSConfig; + +use std::path::PathBuf; +use stepper_lib::{CallEvidencePath, CallResult, EvidenceState}; + +fn construct_service_config(module_name: impl Into) -> AppServiceConfig { + let module_name = module_name.into(); + let module_path = format!("./tests/security_tetraplets/{}/target/wasm32-wasi/debug/", module_name); + + let faas_config = FaaSConfig { + modules_dir: Some(PathBuf::from(module_path)), + modules_config: vec![(module_name, <_>::default())], + default_modules_config: None, + }; + + let service_base_dir = std::env::temp_dir(); + + let config = AppServiceConfig { + service_base_dir, + faas_config, + }; + + config +} + +#[test] +fn tetraplet_with_wasm_modules() { + use fluence::CallParameters; + use fluence::SecurityTetraplet as SDKTetraplet; + + let auth_module_name = String::from("auth_module"); + let auth_service_config = construct_service_config(auth_module_name.clone()); + let auth_service = AppService::new(auth_service_config, auth_module_name.clone(), <_>::default()).unwrap(); + + let log_module_name = String::from("log_storage"); + let log_service_config = construct_service_config(log_module_name.clone()); + let log_service = AppService::new(log_service_config, log_module_name.clone(), <_>::default()).unwrap(); + + let services = maplit::hashmap!( + "auth" => auth_service, + "log_storage" => log_service, + ); + let services = Rc::new(RefCell::new(services)); + + let services_inner = services.clone(); + let host_func: HostExportedFunc = Box::new(move |_, args: Vec| -> Option { + let service_id = match &args[0] { + IValue::String(str) => str, + _ => unreachable!(), + }; + + let function_name = match &args[1] { + IValue::String(str) => str, + _ => unreachable!(), + }; + + let service_args = match &args[2] { + IValue::String(str) => str, + _ => unreachable!(), + }; + + let tetraplets = match &args[3] { + IValue::String(str) => str, + _ => unreachable!(), + }; + + let tetraplets: Vec> = serde_json::from_str(tetraplets).unwrap(); + + let mut call_parameters = CallParameters::default(); + call_parameters.tetraplets = tetraplets; + + let service_args = serde_json::from_str(service_args).unwrap(); + let mut service = services_inner.borrow_mut(); + let service: &mut AppService = service.get_mut(service_id.as_str()).unwrap(); + + let result = service.call(function_name, service_args, call_parameters).unwrap(); + + Some(IValue::Record( + Vec1::new(vec![IValue::S32(0), IValue::String(result.to_string())]).unwrap(), + )) + }); + + let script = String::from( + r#" + (seq + (call %current_peer_id% ("auth" "is_authorized") [%init_peer_id%] auth_result) + (call %current_peer_id% ("log_storage" "delete") [auth_result.$.is_authorized "1"]) + ) + "#, + ); + + let mut vm = create_aqua_vm(host_func, "some peer_id"); + + const ADMIN_PEER_PK: &str = "12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE1"; + let result = call_vm!(vm, ADMIN_PEER_PK, script, "", ""); + let path: CallEvidencePath = serde_json::from_slice(&result.data).unwrap(); + let right_res = EvidenceState::Call(CallResult::Executed(Rc::new(serde_json::Value::String(String::from( + "Ok", + ))))); + + assert_eq!(path[1], right_res) +} diff --git a/stepper-lib/tests/security_tetraplets/auth_module/Cargo.lock b/stepper-lib/tests/security_tetraplets/auth_module/Cargo.lock new file mode 100644 index 00000000..a8059afe --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/auth_module/Cargo.lock @@ -0,0 +1,960 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "air-parser" +version = "0.1.0" +dependencies = [ + "codespan", + "codespan-reporting", + "lalrpop", + "lalrpop-util", + "regex", + "serde", +] + +[[package]] +name = "array_tool" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "ascii-canvas" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29" +dependencies = [ + "term", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "auth_module" +version = "0.1.0" +dependencies = [ + "fluence", + "stepper-lib", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + +[[package]] +name = "bumpalo" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "codespan" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ebaf6bb6a863ad6aa3a18729e9710c53d75df03306714d9cc1f7357a00cd789" +dependencies = [ + "codespan-reporting", +] + +[[package]] +name = "codespan-reporting" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "docopt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" +dependencies = [ + "lazy_static", + "regex", + "serde", + "strsim", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "ena" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fluence" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "083f40a5d000b28b74f10d824925eccf1fbdf6dbb8881e6d052c6183b2bc615e" +dependencies = [ + "fluence-sdk-macro", + "fluence-sdk-main", +] + +[[package]] +name = "fluence-sdk-macro" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f79abced6cdfdd7089b0accad0d9c760bf9d2e82ae1bec851383e061cb40790" +dependencies = [ + "fluence-sdk-wit", +] + +[[package]] +name = "fluence-sdk-main" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2348d5b5000012f9da835e52f7473e08dff6345e9beba2e80a91b801e48ac0b6" +dependencies = [ + "fluence-sdk-macro", + "log", + "serde", +] + +[[package]] +name = "fluence-sdk-wit" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da5f51cddeae52ff5b91d1a5d8be90e54629f4887f89f8d7501b829b374fe6a" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "uuid", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "hermit-abi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" + +[[package]] +name = "jsonpath_lib" +version = "0.2.5" +source = "git+https://github.com/fluencelabs/jsonpath?branch=fluence#538b433ae2ccbd882ff02fcff22ea16be779fb6f" +dependencies = [ + "array_tool", + "env_logger", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "lalrpop" +version = "0.19.1" +source = "git+https://github.com/fluencelabs/lalrpop?branch=cloneable_parser#486546b479b51ee370beec1d9e663dcbafa7cab1" +dependencies = [ + "ascii-canvas", + "atty", + "bit-set", + "diff", + "docopt", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax", + "serde", + "serde_derive", + "sha2", + "string_cache", + "term", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.1" +source = "git+https://github.com/fluencelabs/lalrpop?branch=cloneable_parser#486546b479b51ee370beec1d9e663dcbafa7cab1" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" + +[[package]] +name = "lexical-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if 0.1.10", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" + +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "polyplets" +version = "0.1.0" +dependencies = [ + "fluence", + "serde", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "safe-transmute" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b8b2cd387f744f69469aaed197954ba4c0ecdb31e02edf99b023e0df11178a" + +[[package]] +name = "serde" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "siphasher" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stepper-interface" +version = "0.1.0" +dependencies = [ + "fluence", + "serde", + "wasmer-interface-types-fl", +] + +[[package]] +name = "stepper-lib" +version = "0.1.3" +dependencies = [ + "air-parser", + "boolinator", + "fluence", + "jsonpath_lib", + "log", + "polyplets", + "serde", + "serde_derive", + "serde_json", + "stepper-interface", + "wasm-bindgen", +] + +[[package]] +name = "string_cache" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "syn" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "term" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +dependencies = [ + "byteorder", + "dirs", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +dependencies = [ + "rand", +] + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasm-bindgen" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edbcc9536ab7eababcc6d2374a0b7bfe13a2b6d562c5e07f370456b1a8f33d" +dependencies = [ + "cfg-if 0.1.10", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ed2fb8c84bfad20ea66b26a3743f3e7ba8735a69fe7d95118c33ec8fc1244d" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb071268b031a64d92fc6cf691715ca5a40950694d8f683c5bb43db7c730929e" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf592c807080719d1ff2f245a687cbadb3ed28b2077ed7084b47aba8b691f2c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b6c0220ded549d63860c78c38f3bcc558d1ca3f4efa74942c536ddbbb55e87" + +[[package]] +name = "wasmer-interface-types-fl" +version = "0.17.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88dcf40c0c547e4d085c539070dc2c0caef364ccf5a11056f1de13659c65ea04" +dependencies = [ + "log", + "nom", + "safe-transmute", + "serde", + "serde_json", + "wast", +] + +[[package]] +name = "wast" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9df3d716118a503b2f6bbb6ff46b21997ab0cc167b01de7a188e45e4b01e8d" +dependencies = [ + "leb128", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/stepper-lib/tests/security_tetraplets/auth_module/Cargo.toml b/stepper-lib/tests/security_tetraplets/auth_module/Cargo.toml new file mode 100644 index 00000000..42650153 --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/auth_module/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "auth_module" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" + +[[bin]] +name = "auth_module" +path = "src/main.rs" + +[dependencies] +stepper-lib = { path = "../../../../stepper-lib" } +fluence = { version = "=0.2.13", features = ["logger"] } + +[workspace] diff --git a/stepper-lib/tests/security_tetraplets/auth_module/src/main.rs b/stepper-lib/tests/security_tetraplets/auth_module/src/main.rs new file mode 100644 index 00000000..78aa0a3d --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/auth_module/src/main.rs @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#![allow(clippy::all)] + +use fluence::fce; + +#[fce] +pub struct CallServiceResult { + pub ret_code: i32, + pub result: String, +} + +const ADMIN_PEER_PK: &str = "12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE1"; + +fn main() {} + +#[fce] +struct AuthResult { + pub is_authorized: i32, +} + +#[fce] +fn is_authorized(user_peer_pk: String) -> AuthResult { + let is_authorized = user_peer_pk == ADMIN_PEER_PK; + + AuthResult { + is_authorized: is_authorized.into(), + } +} diff --git a/stepper-lib/tests/security_tetraplets/log_storage/Cargo.lock b/stepper-lib/tests/security_tetraplets/log_storage/Cargo.lock new file mode 100644 index 00000000..bd4a2be9 --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/log_storage/Cargo.lock @@ -0,0 +1,960 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "air-parser" +version = "0.1.0" +dependencies = [ + "codespan", + "codespan-reporting", + "lalrpop", + "lalrpop-util", + "regex", + "serde", +] + +[[package]] +name = "array_tool" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "ascii-canvas" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29" +dependencies = [ + "term", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + +[[package]] +name = "bumpalo" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "codespan" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ebaf6bb6a863ad6aa3a18729e9710c53d75df03306714d9cc1f7357a00cd789" +dependencies = [ + "codespan-reporting", +] + +[[package]] +name = "codespan-reporting" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "docopt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" +dependencies = [ + "lazy_static", + "regex", + "serde", + "strsim", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "ena" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fluence" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "083f40a5d000b28b74f10d824925eccf1fbdf6dbb8881e6d052c6183b2bc615e" +dependencies = [ + "fluence-sdk-macro", + "fluence-sdk-main", +] + +[[package]] +name = "fluence-sdk-macro" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f79abced6cdfdd7089b0accad0d9c760bf9d2e82ae1bec851383e061cb40790" +dependencies = [ + "fluence-sdk-wit", +] + +[[package]] +name = "fluence-sdk-main" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2348d5b5000012f9da835e52f7473e08dff6345e9beba2e80a91b801e48ac0b6" +dependencies = [ + "fluence-sdk-macro", + "log", + "serde", +] + +[[package]] +name = "fluence-sdk-wit" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da5f51cddeae52ff5b91d1a5d8be90e54629f4887f89f8d7501b829b374fe6a" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "uuid", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "hermit-abi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" + +[[package]] +name = "jsonpath_lib" +version = "0.2.5" +source = "git+https://github.com/fluencelabs/jsonpath?branch=fluence#538b433ae2ccbd882ff02fcff22ea16be779fb6f" +dependencies = [ + "array_tool", + "env_logger", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "lalrpop" +version = "0.19.1" +source = "git+https://github.com/fluencelabs/lalrpop?branch=cloneable_parser#486546b479b51ee370beec1d9e663dcbafa7cab1" +dependencies = [ + "ascii-canvas", + "atty", + "bit-set", + "diff", + "docopt", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax", + "serde", + "serde_derive", + "sha2", + "string_cache", + "term", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.1" +source = "git+https://github.com/fluencelabs/lalrpop?branch=cloneable_parser#486546b479b51ee370beec1d9e663dcbafa7cab1" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" + +[[package]] +name = "lexical-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if 0.1.10", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" + +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "log_storage" +version = "0.1.0" +dependencies = [ + "fluence", + "stepper-lib", +] + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "polyplets" +version = "0.1.0" +dependencies = [ + "fluence", + "serde", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "safe-transmute" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b8b2cd387f744f69469aaed197954ba4c0ecdb31e02edf99b023e0df11178a" + +[[package]] +name = "serde" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "siphasher" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stepper-interface" +version = "0.1.0" +dependencies = [ + "fluence", + "serde", + "wasmer-interface-types-fl", +] + +[[package]] +name = "stepper-lib" +version = "0.1.3" +dependencies = [ + "air-parser", + "boolinator", + "fluence", + "jsonpath_lib", + "log", + "polyplets", + "serde", + "serde_derive", + "serde_json", + "stepper-interface", + "wasm-bindgen", +] + +[[package]] +name = "string_cache" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "syn" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "term" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +dependencies = [ + "byteorder", + "dirs", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +dependencies = [ + "rand", +] + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasm-bindgen" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edbcc9536ab7eababcc6d2374a0b7bfe13a2b6d562c5e07f370456b1a8f33d" +dependencies = [ + "cfg-if 0.1.10", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ed2fb8c84bfad20ea66b26a3743f3e7ba8735a69fe7d95118c33ec8fc1244d" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb071268b031a64d92fc6cf691715ca5a40950694d8f683c5bb43db7c730929e" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf592c807080719d1ff2f245a687cbadb3ed28b2077ed7084b47aba8b691f2c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b6c0220ded549d63860c78c38f3bcc558d1ca3f4efa74942c536ddbbb55e87" + +[[package]] +name = "wasmer-interface-types-fl" +version = "0.17.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88dcf40c0c547e4d085c539070dc2c0caef364ccf5a11056f1de13659c65ea04" +dependencies = [ + "log", + "nom", + "safe-transmute", + "serde", + "serde_json", + "wast", +] + +[[package]] +name = "wast" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9df3d716118a503b2f6bbb6ff46b21997ab0cc167b01de7a188e45e4b01e8d" +dependencies = [ + "leb128", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/stepper-lib/tests/security_tetraplets/log_storage/Cargo.toml b/stepper-lib/tests/security_tetraplets/log_storage/Cargo.toml new file mode 100644 index 00000000..2f656999 --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/log_storage/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "log_storage" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" + +[[bin]] +name = "log_storage" +path = "src/main.rs" + +[dependencies] +stepper-lib = { path = "../../../../stepper-lib" } +fluence = { version = "=0.2.13", features = ["logger"] } + +[workspace] diff --git a/stepper-lib/tests/security_tetraplets/log_storage/src/main.rs b/stepper-lib/tests/security_tetraplets/log_storage/src/main.rs new file mode 100644 index 00000000..bb987d5b --- /dev/null +++ b/stepper-lib/tests/security_tetraplets/log_storage/src/main.rs @@ -0,0 +1,41 @@ +/* + * 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 fluence::fce; + +#[fce] +pub struct CallServiceResult { + pub ret_code: i32, + pub result: String, +} + +fn main() {} + +#[fce] +fn delete(is_authorized: Vec, _record_id: String) -> String { + let call_parameters = fluence::get_call_parameters(); + let tetraplets = call_parameters.tetraplets; + let tetraplet = &tetraplets[0]; + + if tetraplet[0].json_path != "$.is_authorized" { + return String::from("invalid json path in tetraplet"); + } + + match is_authorized[0] { + 1 => String::from("Ok"), + _ => String::from("not authorized"), + } +} diff --git a/stepper/Cargo.toml b/stepper/Cargo.toml index 33f42f18..11f49bc0 100644 --- a/stepper/Cargo.toml +++ b/stepper/Cargo.toml @@ -17,12 +17,13 @@ path = "src/fce.rs" stepper-lib = { path = "../stepper-lib" } stepper-interface = { path = "../crates/stepper-interface" } -fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] } +fluence = { version = "=0.2.13", features = ["logger"] } # Keep 0.2.65 until this is resolved https://github.com/rustwasm/wasm-pack/issues/886 wasm-bindgen = "=0.2.65" log = "0.4.11" +serde = { version = "1.0.116", features = [ "derive", "rc" ] } serde_json = "1.0" [features]