Skip to content

Commit

Permalink
Provide storage debuger for runtime (#301)
Browse files Browse the repository at this point in the history
* Expose storage from runtime

* Init ewasm_storage_debug macro

* Pretty print on storage

* typo

* documentation
  • Loading branch information
yanganto committed Feb 26, 2022
1 parent 49d24ab commit 9c75bfa
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 2 deletions.
2 changes: 1 addition & 1 deletion SewUp.wiki
Submodule SewUp.wiki updated from 092845 to 3e2cdc
10 changes: 9 additions & 1 deletion examples/kv-contract/src/lib.rs
Expand Up @@ -271,10 +271,14 @@ fn main() -> anyhow::Result<sewup::primitives::EwasmAny> {
mod tests {
use super::*;
use errors::KVError;
use sewup_derive::{ewasm_assert_eq, ewasm_assert_ok, ewasm_err_output, ewasm_fn_sig};
use sewup_derive::{
ewasm_assert_eq, ewasm_assert_ok, ewasm_err_output, ewasm_fn_sig, ewasm_storage_debug,
};

#[ewasm_test]
fn test_execute_storage_operations() {
ewasm_storage_debug!();

ewasm_assert_eq!(
non_register_function(),
ewasm_err_output!(KVError::UnknownHandle)
Expand Down Expand Up @@ -341,7 +345,11 @@ mod tests {
ewasm_assert_ok!(put_pair_to_bucket1(input_pair));
ewasm_assert_eq!(get_value_to_bucket1(100), new_expected_of_100_value);

ewasm_storage_debug!(point1);

ewasm_assert_ok!(drop_bucket_than_check());

ewasm_storage_debug!(point2);
}

#[ewasm_test]
Expand Down
20 changes: 20 additions & 0 deletions sewup-derive/src/lib.rs
Expand Up @@ -1615,6 +1615,7 @@ pub fn ewasm_test(attr: TokenStream, item: TokenStream) -> TokenStream {
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;
use sewup::runtimes::traits::RT;
fn _build_wasm(opt: Option<String>) -> String {
let cargo_cmd = format!("cargo build --release --target=wasm32-unknown-unknown {}", opt.unwrap_or_default());
Expand Down Expand Up @@ -2029,3 +2030,22 @@ pub fn ewasm_call_only_by(item: TokenStream) -> TokenStream {

output.into()
}

/// helps you inspect the storage in test
/// this will print out the detail of storage, you can add description on the storage debug or
/// leave it empty
/// ```compile_fail
/// ewasm_storage_debug!();
/// ewasm_storage_debug!(description);
/// ```
#[proc_macro]
pub fn ewasm_storage_debug(item: TokenStream) -> TokenStream {
let desc = item.to_string();
quote!({
let __cloned = _runtime.clone();
let __borrowed = __cloned.borrow();
let __storage = __borrowed.get_storage(&[0; 20]);
eprintln!("{}", sewup::utils::pretty_print_storage(#desc, __storage));
})
.into()
}
4 changes: 4 additions & 0 deletions sewup/src/runtimes/test.rs
Expand Up @@ -112,6 +112,10 @@ impl RT for TestRuntime {
self.execute(msg)?;
Ok(())
}

fn get_storage(&self, account: &[u8; 20]) -> Option<&HashMap<[u8; 32], [u8; 32]>> {
self.host.store.get(account)
}
}

#[derive(Default)]
Expand Down
4 changes: 4 additions & 0 deletions sewup/src/runtimes/traits.rs
Expand Up @@ -4,6 +4,7 @@
//!
//! Besides, the VMErrors, VMmessage VMresult are rust style wrarp for
//! evm_error, evm_message and evm_result
use std::collections::HashMap;

use anyhow::Result;
use evmc_sys::evmc_call_kind;
Expand Down Expand Up @@ -192,4 +193,7 @@ pub trait RT {

/// Deploy contract
fn deploy(&mut self, msg: VMMessage) -> Result<()>;

/// Get storage
fn get_storage(&self, account: &[u8; 20]) -> Option<&HashMap<[u8; 32], [u8; 32]>>;
}
33 changes: 33 additions & 0 deletions sewup/src/utils.rs
Expand Up @@ -126,6 +126,39 @@ where
}
}

pub fn pretty_print_storage(
desc: &str,
may_storage: Option<&std::collections::HashMap<[u8; 32], [u8; 32]>>,
) -> String {
match may_storage {
Some(storage) => {
let mut output = if desc.trim().is_empty() {
"Storage: \n".to_string()
} else {
format!("Storage at {}:\n", desc)
};
let mut chrunks = Vec::<([u8; 32], [u8; 32])>::new();
for (k, v) in storage.iter() {
chrunks.push((*k, *v));
}
chrunks.sort_by(|a, b| a.0.cmp(&b.0));
for (k, v) in chrunks.drain(..) {
let mut try_str = String::new();
for b in v.iter() {
if 31 < *b && *b < 127 {
try_str.push(*b as char);
} else {
try_str.push(' ');
}
}
output.push_str(&format!("{}|{}|{:?}\n", hex::encode(k), try_str, v));
}
output
}
None => "Storage not use at this moment".into(),
}
}

#[cfg(feature = "default")]
#[cfg(test)]
mod tests {
Expand Down

0 comments on commit 9c75bfa

Please sign in to comment.