feat(air,air-cli): pretty-printing binary interpreter data (#794)

Add new interpreter method `to_human_readable_data` and `air data` subcommand to convert binary data to JSON with indentation.
This commit is contained in:
Ivan Boldyrev 2024-01-11 14:46:16 +04:00 committed by GitHub
parent 0a680f8d2e
commit d6b1da9bdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 302 additions and 76 deletions

102
Cargo.lock generated
View File

@ -40,7 +40,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -61,7 +61,7 @@ checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -192,7 +192,7 @@ dependencies = [
"polyplets", "polyplets",
"rkyv", "rkyv",
"rmp-serde", "rmp-serde",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"serde_bytes", "serde_bytes",
"serde_json", "serde_json",
@ -285,7 +285,7 @@ dependencies = [
"object-pool", "object-pool",
"once_cell", "once_cell",
"rand_chacha 0.3.1", "rand_chacha 0.3.1",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.10.8", "sha2 0.10.8",
@ -455,7 +455,7 @@ dependencies = [
"polyplets", "polyplets",
"pretty_assertions 0.6.1", "pretty_assertions 0.6.1",
"rkyv", "rkyv",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum",
@ -470,6 +470,7 @@ name = "aquavm-air-cli"
version = "0.6.1" version = "0.6.1"
dependencies = [ dependencies = [
"air-beautifier", "air-beautifier",
"air-interpreter-data",
"air-interpreter-interface", "air-interpreter-interface",
"air-interpreter-sede", "air-interpreter-sede",
"air-test-utils", "air-test-utils",
@ -483,6 +484,7 @@ dependencies = [
"fluence-keypair", "fluence-keypair",
"itertools", "itertools",
"near-sdk", "near-sdk",
"semver 1.0.21",
"serde", "serde",
"serde_json", "serde_json",
"termcolor", "termcolor",
@ -701,7 +703,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -718,7 +720,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1060,7 +1062,7 @@ dependencies = [
"proc-macro-crate 2.0.1", "proc-macro-crate 2.0.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
"syn_derive", "syn_derive",
] ]
@ -1411,7 +1413,7 @@ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1452,7 +1454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1878,7 +1880,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1902,7 +1904,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1913,7 +1915,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1981,7 +1983,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2202,7 +2204,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -3405,7 +3407,7 @@ dependencies = [
"multimap 0.8.3", "multimap 0.8.3",
"once_cell", "once_cell",
"paste", "paste",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"thiserror", "thiserror",
"wasmer-interface-types-fl", "wasmer-interface-types-fl",
@ -3450,7 +3452,7 @@ dependencies = [
"marine-module-interface", "marine-module-interface",
"marine-wasm-backend-traits", "marine-wasm-backend-traits",
"nom", "nom",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"thiserror", "thiserror",
"walrus 0.20.3", "walrus 0.20.3",
@ -3500,7 +3502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a84be3c30abaa13df50cdaceb6b62ca806ac8a10fd5bacfeb4371ec1bd0f5101" checksum = "a84be3c30abaa13df50cdaceb6b62ca806ac8a10fd5bacfeb4371ec1bd0f5101"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"semver 1.0.20", "semver 1.0.21",
] ]
[[package]] [[package]]
@ -3514,7 +3516,7 @@ dependencies = [
"derivative", "derivative",
"marine-rs-sdk-main", "marine-rs-sdk-main",
"marine-wasm-backend-traits", "marine-wasm-backend-traits",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"thiserror", "thiserror",
"walrus 0.20.3", "walrus 0.20.3",
@ -3530,7 +3532,7 @@ dependencies = [
"itertools", "itertools",
"marine-it-interfaces", "marine-it-interfaces",
"nom", "nom",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"thiserror", "thiserror",
"walrus 0.19.0", "walrus 0.19.0",
@ -3863,7 +3865,7 @@ checksum = "e4ac4e2d843390b1a007ad206022b4252d0fe3756d8b6609bc025cce07949bc5"
dependencies = [ dependencies = [
"borsh 1.1.2", "borsh 1.1.2",
"schemars", "schemars",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
] ]
@ -4188,7 +4190,7 @@ checksum = "84c1eda300e2e78f4f945ae58117d49e806899f4a51ee2faa09eda5ebc2e6571"
dependencies = [ dependencies = [
"quote", "quote",
"serde", "serde",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -4211,7 +4213,7 @@ dependencies = [
"fs2", "fs2",
"near-rpc-error-core 0.17.0", "near-rpc-error-core 0.17.0",
"serde", "serde",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -4269,7 +4271,7 @@ dependencies = [
"serde_json", "serde_json",
"strum", "strum",
"strum_macros", "strum_macros",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -4524,7 +4526,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -4716,7 +4718,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -4944,9 +4946,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.70" version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -5071,9 +5073,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.33" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -5467,7 +5469,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [ dependencies = [
"semver 1.0.20", "semver 1.0.21",
] ]
[[package]] [[package]]
@ -5654,18 +5656,18 @@ checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.20" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.193" version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -5691,13 +5693,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.193" version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -5730,7 +5732,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -5787,7 +5789,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -5799,7 +5801,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -6079,9 +6081,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.41" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -6097,7 +6099,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -6231,7 +6233,7 @@ checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -6355,7 +6357,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -6562,7 +6564,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -7035,7 +7037,7 @@ dependencies = [
"log", "log",
"nom", "nom",
"safe-transmute", "safe-transmute",
"semver 1.0.20", "semver 1.0.21",
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
@ -7764,7 +7766,7 @@ checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -7784,7 +7786,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.41", "syn 2.0.48",
] ]
[[package]] [[package]]

View File

@ -88,3 +88,12 @@ pub fn invoke_tracing(
pub fn ast(script: String) -> String { pub fn ast(script: String) -> String {
ast::ast(script) ast::ast(script)
} }
/// Like ast, this function is intended to be run localy by tools.
#[marine]
pub fn to_human_readable_data(data: Vec<u8>) -> String {
match air::to_human_readable_data(data) {
Ok(text) => text,
Err(err) => err.to_string(),
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2024 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::preparation_step::check_version_compatibility;
use air_interpreter_data::InterpreterData;
use air_interpreter_data::InterpreterDataEnvelope;
use serde_json::json;
use std::error::Error as StdError;
pub fn to_human_readable_data(data: Vec<u8>) -> Result<String, Box<dyn StdError>> {
let envelope = InterpreterDataEnvelope::try_from_slice(&data)?;
check_version_compatibility(&envelope.versions)?;
let data = InterpreterData::try_from_slice(&envelope.inner_data)?;
// TODO convert value store strings to JSON
let envelope_json = json!({
"versions": envelope.versions,
"data": data,
});
// it may produce quite a big string (whitespaces, escaping, etc), but this function
// is intended to be executed on user machine, not on chain or in a cloud.
Ok(serde_json::to_string_pretty(&envelope_json)?)
}

View File

@ -28,6 +28,7 @@
mod execution_step; mod execution_step;
mod farewell_step; mod farewell_step;
mod human_readable_data;
mod preparation_step; mod preparation_step;
mod runner; mod runner;
mod signing_step; mod signing_step;
@ -63,6 +64,7 @@ pub use preparation_step::min_supported_version;
pub use preparation_step::PreparationError; pub use preparation_step::PreparationError;
pub use utils::ToErrorCode; pub use utils::ToErrorCode;
pub use crate::human_readable_data::to_human_readable_data;
pub use crate::runner::execute_air; pub use crate::runner::execute_air;
pub mod interpreter_data { pub mod interpreter_data {

View File

@ -22,6 +22,7 @@ pub use errors::PreparationError;
pub use interpreter_versions::interpreter_version; pub use interpreter_versions::interpreter_version;
pub use interpreter_versions::min_supported_version; pub use interpreter_versions::min_supported_version;
pub(crate) use preparation::check_version_compatibility;
pub(crate) use preparation::parse_data; pub(crate) use preparation::parse_data;
pub(crate) use preparation::prepare; pub(crate) use preparation::prepare;
pub(crate) use preparation::ParsedDataPair; pub(crate) use preparation::ParsedDataPair;

View File

@ -76,4 +76,8 @@ pub enum RunnerError {
/// Invalid secret key. /// Invalid secret key.
#[error(transparent)] #[error(transparent)]
KeyError(eyre::Error), KeyError(eyre::Error),
/// Errors from auxiliary calls.
#[error("{0}")]
Aux(String),
} }

View File

@ -17,6 +17,7 @@
use crate::RunnerError; use crate::RunnerError;
use crate::RunnerResult; use crate::RunnerResult;
use air_interpreter_interface::try_as_string;
use air_interpreter_interface::CallResultsRepr; use air_interpreter_interface::CallResultsRepr;
use air_interpreter_interface::InterpreterOutcome; use air_interpreter_interface::InterpreterOutcome;
use air_interpreter_sede::ToSerialized; use air_interpreter_sede::ToSerialized;
@ -171,6 +172,20 @@ impl AVMRunner {
Ok(outcome) Ok(outcome)
} }
pub fn to_human_readable_data(&mut self, data: Vec<u8>) -> RunnerResult<String> {
let args = vec![IValue::ByteArray(data)];
let result = self.marine.call_with_ivalues(
&self.wasm_filename,
"to_human_readable_data",
&args,
<_>::default(),
)?;
let result = try_as_one_value_vec(result)?;
let outcome = try_as_string(result, "result").map_err(RunnerError::Aux)?;
Ok(outcome)
}
pub fn memory_stats(&self) -> AVMMemoryStats { pub fn memory_stats(&self) -> AVMMemoryStats {
let stats = self.marine.module_memory_stats(); let stats = self.marine.module_memory_stats();

View File

@ -116,7 +116,7 @@ fn try_as_i64(ivalue: IValue, field_name: &str) -> Result<i64, String> {
} }
#[cfg(feature = "marine")] #[cfg(feature = "marine")]
fn try_as_string(ivalue: IValue, field_name: &str) -> Result<String, String> { pub fn try_as_string(ivalue: IValue, field_name: &str) -> Result<String, String> {
match ivalue { match ivalue {
IValue::String(value) => Ok(value), IValue::String(value) => Ok(value),
v => Err(format!("expected a string for {field_name}, got {v:?}")), v => Err(format!("expected a string for {field_name}, got {v:?}")),

View File

@ -15,12 +15,14 @@ air-beautifier = { version = "0.4.1", path = "../../../crates/beautifier" }
avm-data-store = { version = "0.7.5", path = "../../../crates/data-store" } avm-data-store = { version = "0.7.5", path = "../../../crates/data-store" }
avm-interface = { version = "0.31.0", path = "../../../avm/interface" } avm-interface = { version = "0.31.0", path = "../../../avm/interface" }
air-interpreter-interface = { version = "0.17.0", path = "../../../crates/air-lib/interpreter-interface", default-features = false } air-interpreter-interface = { version = "0.17.0", path = "../../../crates/air-lib/interpreter-interface", default-features = false }
air-interpreter-data = { version = "0.16.0", path = "../../../crates/air-lib/interpreter-data" }
air-interpreter-sede = { version = "0.1.0", path = "../../../crates/air-lib/interpreter-sede", default-features = false } air-interpreter-sede = { version = "0.1.0", path = "../../../crates/air-lib/interpreter-sede", default-features = false }
air-test-utils = { version = "0.14.1",path = "../../../crates/air-lib/test-utils", optional = true } air-test-utils = { version = "0.14.1",path = "../../../crates/air-lib/test-utils", optional = true }
anyhow = "1.0.79" anyhow = "1.0.79"
clap = { version = "4.4.7", features = ["derive", "env"] } clap = { version = "4.4.7", features = ["derive", "env"] }
itertools = "0.10.5" itertools = "0.10.5"
semver = "1.0.21"
serde = { version = "1.0.190", features = ["derive"] } serde = { version = "1.0.190", features = ["derive"] }
serde_json = "1.0.108" serde_json = "1.0.108"
tracing = "0.1.40" tracing = "0.1.40"

119
tools/cli/air/src/data.rs Normal file
View File

@ -0,0 +1,119 @@
/*
* Copyright 2024 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 anyhow::Context;
use clap::Parser;
use std::path::Path;
use std::path::PathBuf;
use crate::trace::run::load_data;
use crate::trace::run::runner::DataToHumanReadable;
#[derive(clap::Args, Debug, Copy, Clone)]
#[group(multiple = false)]
struct ModeArgs {
#[arg(long)]
native: bool,
#[cfg(feature = "wasm")]
#[arg(long)]
wasm: bool,
}
enum Mode {
Native,
#[cfg(feature = "wasm")]
Wasm,
}
impl From<ModeArgs> for Option<Mode> {
fn from(value: ModeArgs) -> Self {
if value.native {
return Some(Mode::Native);
}
#[cfg(feature = "wasm")]
if value.wasm {
return Some(Mode::Wasm);
}
None
}
}
#[derive(Parser)]
#[clap(about = "Print human-readable AquaVM data")]
pub(crate) struct Args {
#[clap(
long = "interpreter",
env = "AIR_INTERPRETER_WASM_PATH",
default_value = "target/wasm32-wasi/release/air_interpreter_server.wasm"
)]
air_interpreter_path: PathBuf,
#[clap(flatten)]
mode: ModeArgs,
// TODO be able to read from stdin
#[arg(help = "Input path")]
input: PathBuf,
}
pub(crate) fn to_human_readable_data(args: Args) -> Result<(), Box<dyn std::error::Error>> {
init_tracing("warn");
let data: Vec<u8> = load_data(&args.input)?;
if data.is_empty() {
Err(anyhow::anyhow!("empty input data: {:?}", args.input))?;
}
let mut runner = create_runner(args.mode.into(), &args.air_interpreter_path)?;
let out = runner.to_human_readable(data)?;
println!("{out}");
Ok(())
}
fn init_tracing(tracing_params: &str) {
let builder = tracing_subscriber::fmt()
.with_env_filter(tracing_params)
.with_writer(std::io::stderr);
builder.init();
}
fn create_runner(
mode: Option<Mode>,
_air_interpreter_wasm_path: &Path,
) -> anyhow::Result<Box<dyn DataToHumanReadable>> {
#[cfg(not(feature = "wasm"))]
let default_mode = Mode::Native;
#[cfg(feature = "wasm")]
let default_mode = Mode::Wasm;
let mode = mode.unwrap_or(default_mode);
let runner = match mode {
Mode::Native => crate::trace::run::native::create_native_avm_runner()
.context("Failed to instantiate a native AVM")? as _,
#[cfg(feature = "wasm")]
Mode::Wasm => {
crate::trace::run::wasm::create_wasm_avm_runner(_air_interpreter_wasm_path, None)
.context("Failed to instantiate WASM AVM")? as _
}
};
Ok(runner)
}

View File

@ -27,6 +27,7 @@
)] )]
mod beautify; mod beautify;
mod data;
mod trace; mod trace;
use clap::Parser; use clap::Parser;
@ -42,17 +43,21 @@ struct Cli {
enum Subcommand { enum Subcommand {
#[clap(alias = "b")] #[clap(alias = "b")]
Beautify(self::beautify::Args), Beautify(self::beautify::Args),
#[clap(alias = "d")]
Data(self::data::Args),
#[clap(alias = "r")] #[clap(alias = "r")]
Run(self::trace::run::Args), Run(self::trace::run::Args),
#[clap(alias = "s")] #[clap(alias = "s")]
Stats(self::trace::stats::Args), Stats(self::trace::stats::Args),
} }
fn main() -> anyhow::Result<()> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse(); let args = Cli::parse();
match args.subcommand { match args.subcommand {
Subcommand::Run(args) => self::trace::run::run(args), Subcommand::Beautify(args) => self::beautify::beautify(args)?,
Subcommand::Stats(args) => self::trace::stats::stats(args), Subcommand::Data(args) => self::data::to_human_readable_data(args)?,
Subcommand::Beautify(args) => self::beautify::beautify(args), Subcommand::Run(args) => self::trace::run::run(args)?,
Subcommand::Stats(args) => self::trace::stats::stats(args)?,
} }
Ok(())
} }

View File

@ -15,27 +15,28 @@
*/ */
mod data; mod data;
mod native; pub(crate) mod native;
#[cfg(feature = "near")] #[cfg(feature = "near")]
mod near; mod near;
#[cfg(feature = "risc0")] #[cfg(feature = "risc0")]
mod risc0; mod risc0;
mod runner;
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
mod wasm; pub(crate) mod wasm;
pub(crate) mod runner;
use self::runner::AirRunner; use self::runner::AirRunner;
use avm_interface::CallResults; use avm_interface::CallResults;
use anyhow::Context as _; use anyhow::Context as _;
use clap::{Parser, Subcommand}; use clap::Parser;
use clap::Subcommand;
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
use zeroize::Zeroize; use zeroize::Zeroize;
use std::{ use std::io::Read;
io::Read, use std::path::Path;
path::{Path, PathBuf}, use std::path::PathBuf;
};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(about = "Run AIR script with AquaVM")] #[clap(about = "Run AIR script with AquaVM")]
@ -241,21 +242,21 @@ fn create_runner(
let default_mode = Mode::Wasm; let default_mode = Mode::Wasm;
let mode = mode.unwrap_or(default_mode); let mode = mode.unwrap_or(default_mode);
match mode { let runner = match mode {
Mode::Native => { Mode::Native => self::native::create_native_avm_runner()
self::native::create_native_avm_runner().context("Failed to instantiate a native AVM") .context("Failed to instantiate a native AVM")? as _,
}
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
Mode::Wasm => { Mode::Wasm => {
self::wasm::create_wasm_avm_runner(_air_interpreter_wasm_path, _max_heap_size) self::wasm::create_wasm_avm_runner(_air_interpreter_wasm_path, _max_heap_size)
.context("Failed to instantiate WASM AVM") .context("Failed to instantiate WASM AVM")? as _
} }
#[cfg(feature = "near")] #[cfg(feature = "near")]
Mode::Near => self::near::create_near_runner(_air_contract_wasm_path) Mode::Near => self::near::create_near_runner(_air_contract_wasm_path)
.context("Failed to instantiate NEAR AVM"), .context("Failed to instantiate NEAR AVM")?,
#[cfg(feature = "risc0")] #[cfg(feature = "risc0")]
Mode::Risc0 => Ok(Box::new(self::risc0::Risc0Runner::new())), Mode::Risc0 => Box::new(self::risc0::Risc0Runner::new()),
} };
Ok(runner)
} }
// TODO This is a copy of function from air_interpreter/marine.rs. It should be moved to the marine_rs_sdk. // TODO This is a copy of function from air_interpreter/marine.rs. It should be moved to the marine_rs_sdk.
@ -297,8 +298,8 @@ fn load_data_or_default(
} }
} }
fn load_data(data_path: &Path) -> anyhow::Result<Vec<u8>> { pub(crate) fn load_data(data_path: &Path) -> anyhow::Result<Vec<u8>> {
Ok(std::fs::read(data_path)?) std::fs::read(data_path).with_context(|| data_path.to_string_lossy().into_owned())
} }
fn load_keypair_ed25519(path: &PathBuf) -> Result<KeyPair, anyhow::Error> { fn load_keypair_ed25519(path: &PathBuf) -> Result<KeyPair, anyhow::Error> {

View File

@ -15,12 +15,15 @@
*/ */
use super::runner::AirRunner; use super::runner::AirRunner;
use super::runner::DataToHumanReadable;
use air_interpreter_interface::CallResultsRepr; use air_interpreter_interface::CallResultsRepr;
use air_interpreter_interface::RunParameters; use air_interpreter_interface::RunParameters;
use avm_interface::raw_outcome::RawAVMOutcome; use avm_interface::raw_outcome::RawAVMOutcome;
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
struct NativeAvmRunner {} use std::error::Error as StdError;
pub(crate) struct NativeAvmRunner {}
impl AirRunner for NativeAvmRunner { impl AirRunner for NativeAvmRunner {
fn call_tracing( fn call_tracing(
@ -70,6 +73,12 @@ impl AirRunner for NativeAvmRunner {
} }
} }
pub(crate) fn create_native_avm_runner() -> anyhow::Result<Box<dyn AirRunner>> { impl DataToHumanReadable for NativeAvmRunner {
fn to_human_readable(&mut self, data: Vec<u8>) -> Result<String, Box<dyn StdError>> {
air::to_human_readable_data(data)
}
}
pub(crate) fn create_native_avm_runner() -> anyhow::Result<Box<NativeAvmRunner>> {
Ok(Box::new(NativeAvmRunner {})) Ok(Box::new(NativeAvmRunner {}))
} }

View File

@ -18,6 +18,8 @@ use avm_interface::raw_outcome::RawAVMOutcome;
use avm_interface::CallResults; use avm_interface::CallResults;
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
use std::error::Error as StdError;
pub(crate) trait AirRunner { pub(crate) trait AirRunner {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn call_tracing( fn call_tracing(
@ -36,3 +38,7 @@ pub(crate) trait AirRunner {
particle_id: String, particle_id: String,
) -> anyhow::Result<RawAVMOutcome>; ) -> anyhow::Result<RawAVMOutcome>;
} }
pub(crate) trait DataToHumanReadable {
fn to_human_readable(&mut self, data: Vec<u8>) -> Result<String, Box<dyn StdError>>;
}

View File

@ -13,9 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
use super::runner::AirRunner; use super::runner::AirRunner;
use super::runner::DataToHumanReadable;
use air_test_utils::avm_runner::AVMRunner; use air_test_utils::avm_runner::AVMRunner;
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
use std::error::Error as StdError;
use std::path::Path; use std::path::Path;
pub(crate) struct WasmAvmRunner(AVMRunner); pub(crate) struct WasmAvmRunner(AVMRunner);
@ -58,10 +62,16 @@ impl AirRunner for WasmAvmRunner {
} }
} }
impl DataToHumanReadable for WasmAvmRunner {
fn to_human_readable(&mut self, data: Vec<u8>) -> Result<String, Box<dyn StdError>> {
Ok(self.0.to_human_readable_data(data)?)
}
}
pub(crate) fn create_wasm_avm_runner( pub(crate) fn create_wasm_avm_runner(
air_interpreter_wasm_path: &Path, air_interpreter_wasm_path: &Path,
max_heap_size: Option<u64>, max_heap_size: Option<u64>,
) -> anyhow::Result<Box<dyn AirRunner>> { ) -> anyhow::Result<Box<WasmAvmRunner>> {
Ok(Box::new(WasmAvmRunner(AVMRunner::new( Ok(Box::new(WasmAvmRunner(AVMRunner::new(
air_interpreter_wasm_path.to_owned(), air_interpreter_wasm_path.to_owned(),
max_heap_size, max_heap_size,