Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cache::save_wasm_unchecked #1742

Merged
merged 1 commit into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ and this project adheres to
([#1647])
- cosmwasm-std: Add `FromStr` impl for `Coin`. ([#1684])
- cosmwasm-std: Add `Coins` helper to handle multiple coins. ([#1687])
- cosmwasm-vm: Add `Cache::save_wasm_unchecked` to save Wasm blobs that have
been checked before. This is useful for state-sync where we know the Wasm code
was checked when it was first uploaded. ([#1635])

[#1635]: https://github.com/CosmWasm/cosmwasm/pull/1635
[#1647]: https://github.com/CosmWasm/cosmwasm/pull/1647
[#1684]: https://github.com/CosmWasm/cosmwasm/pull/1684
[#1687]: https://github.com/CosmWasm/cosmwasm/pull/1687
Expand Down
55 changes: 44 additions & 11 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,27 @@ where
}
}

/// Takes a Wasm bytecode and stores it to the cache.
///
/// This performs static checks, compiles the bytescode to a module and
/// stores the Wasm file on disk.
///
/// This does the same as [`save_wasm_unchecked`] plus the static checks.
/// When a Wasm blob is stored the first time, use this function.
pub fn save_wasm(&self, wasm: &[u8]) -> VmResult<Checksum> {
check_wasm(wasm, &self.available_capabilities)?;
self.save_wasm_unchecked(wasm)
}

/// Takes a Wasm bytecode and stores it to the cache.
///
/// This compiles the bytescode to a module and
/// stores the Wasm file on disk.
///
/// This does the same as [`save_wasm`] but without the static checks.
/// When a Wasm blob is stored which was previously checked (e.g. as part of state sync),
/// use this function.
pub fn save_wasm_unchecked(&self, wasm: &[u8]) -> VmResult<Checksum> {
let module = compile(wasm, None, &[])?;

let mut cache = self.inner.lock().unwrap();
Expand Down Expand Up @@ -446,6 +465,14 @@ mod tests {

static CONTRACT: &[u8] = include_bytes!("../testdata/hackatom.wasm");
static IBC_CONTRACT: &[u8] = include_bytes!("../testdata/ibc_reflect.wasm");
// Invalid because it doesn't contain required memory and exports
static INVALID_CONTRACT_WAT: &str = r#"(module
(type $t0 (func (param i32) (result i32)))
(func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
get_local $p0
i32.const 1
i32.add))
"#;

fn default_capabilities() -> HashSet<String> {
capabilities_from_csv("iterator,staking")
Expand Down Expand Up @@ -504,17 +531,7 @@ mod tests {

#[test]
fn save_wasm_rejects_invalid_contract() {
// Invalid because it doesn't contain required memory and exports
let wasm = wat::parse_str(
r#"(module
(type $t0 (func (param i32) (result i32)))
(func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
get_local $p0
i32.const 1
i32.add))
"#,
)
.unwrap();
let wasm = wat::parse_str(INVALID_CONTRACT_WAT).unwrap();

let cache: Cache<MockApi, MockStorage, MockQuerier> =
unsafe { Cache::new(make_testing_options()).unwrap() };
Expand Down Expand Up @@ -545,6 +562,22 @@ mod tests {
assert_eq!(cache.stats().misses, 0);
}

#[test]
fn save_wasm_unchecked_works() {
let cache: Cache<MockApi, MockStorage, MockQuerier> =
unsafe { Cache::new(make_testing_options()).unwrap() };
cache.save_wasm_unchecked(CONTRACT).unwrap();
}

#[test]
fn save_wasm_unchecked_accepts_invalid_contract() {
let wasm = wat::parse_str(INVALID_CONTRACT_WAT).unwrap();

let cache: Cache<MockApi, MockStorage, MockQuerier> =
unsafe { Cache::new(make_testing_options()).unwrap() };
cache.save_wasm_unchecked(&wasm).unwrap();
}

#[test]
fn load_wasm_works() {
let cache: Cache<MockApi, MockStorage, MockQuerier> =
Expand Down
Loading