Skip to content

Commit

Permalink
Create a draft implementation of Cache::analyze
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Jan 19, 2021
1 parent 9dc0721 commit 12645ca
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ workflows:
- update-wasmer
- metering-restart
- load-wasm-speed
- cache-analyze
deploy:
jobs:
- build_and_upload_devcontracts:
Expand Down
11 changes: 11 additions & 0 deletions packages/vm/benches/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ fn bench_cache(c: &mut Criterion) {
});
});

group.bench_function("analyze", |b| {
let mut cache: Cache<MockApi, MockStorage, MockQuerier> =
unsafe { Cache::new(options.clone()).unwrap() };
let checksum = cache.save_wasm(CONTRACT).unwrap();

b.iter(|| {
let result = cache.analyze(&checksum);
assert!(result.is_ok());
});
});

group.bench_function("instantiate from fs", |b| {
let non_memcache = CacheOptions {
base_dir: TempDir::new().unwrap().into_path(),
Expand Down
49 changes: 49 additions & 0 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use parity_wasm;
use parity_wasm::elements::Deserialize;
use std::collections::HashSet;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::{Read, Write};
Expand Down Expand Up @@ -50,6 +52,10 @@ pub struct Cache<A: Api, S: Storage, Q: Querier> {
type_querier: PhantomData<Q>,
}

pub struct AnalysisReport {
pub has_ibc_entry_points: bool,
}

impl<A, S, Q> Cache<A, S, Q>
where
A: Api + 'static, // 'static is needed by `impl<…> Instance`
Expand Down Expand Up @@ -119,6 +125,49 @@ where
}
}

/// Performs static anlyzation on this Wasm without compiling or instantiating it.
///
/// Once the contract was stored via [`save_wasm`], this can be called at any point in time.
/// It does not depend on any caching of the contract.
pub fn analyze(&self, checksum: &Checksum) -> VmResult<AnalysisReport> {
let path = self.wasm_path.join(checksum.to_hex());
let mut file = File::open(path).map_err(|e| {
VmError::cache_err(format!("Error opening Wasm file for reading: {}", e))
})?;
let module = parity_wasm::elements::Module::deserialize(&mut file).map_err(|err| {
VmError::static_validation_err(format!(
"Wasm bytecode could not be deserialized. Deserialization error: \"{}\"",
err
))
})?;

// Get exported functions
let entries: HashSet<String> =
module
.export_section()
.map_or(HashSet::default(), |export_section| {
export_section
.entries()
.iter()
.filter_map(|entry| match entry.internal() {
parity_wasm::elements::Internal::Function(_) => {
Some(entry.field().to_string())
}
_ => None,
})
.collect()
});
let has_ibc_entry_points = entries.contains("ibc_channel_open")
&& entries.contains("ibc_channel_connect")
&& entries.contains("ibc_channel_close")
&& entries.contains("ibc_packet_receive")
&& entries.contains("ibc_packet_ack")
&& entries.contains("ibc_packet_timeout");
Ok(AnalysisReport {
has_ibc_entry_points,
})
}

/// Pins a Module that was previously stored via save_wasm.
///
/// The module is lookup first in the memory cache, and then in the file system cache.
Expand Down
2 changes: 1 addition & 1 deletion packages/vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod testing;
mod wasm_backend;

pub use crate::backend::{Api, Backend, BackendError, BackendResult, GasInfo, Querier, Storage};
pub use crate::cache::{Cache, CacheOptions, Stats};
pub use crate::cache::{AnalysisReport, Cache, CacheOptions, Stats};
pub use crate::calls::{
call_handle, call_handle_raw, call_init, call_init_raw, call_migrate, call_migrate_raw,
call_query, call_query_raw,
Expand Down

0 comments on commit 12645ca

Please sign in to comment.