use crate::logic::errors::PrepareError;
use unc_parameters::vm::{Config, VMKind};
mod prepare_v0;
mod prepare_v1;
mod prepare_v2;
pub fn prepare_contract(
original_code: &[u8],
config: &Config,
kind: VMKind,
) -> Result<Vec<u8>, PrepareError> {
let prepare = config.limit_config.contract_prepare_version;
assert!(
(kind != VMKind::UncVm) || (prepare == crate::logic::ContractPrepareVersion::V2),
"UncVM only works with contract prepare version V2",
);
let features = crate::features::WasmFeatures::from(prepare);
match prepare {
crate::logic::ContractPrepareVersion::V0 => {
prepare_v1::validate_contract(original_code, features, config)?;
prepare_v0::prepare_contract(original_code, config)
}
crate::logic::ContractPrepareVersion::V1 => {
prepare_v1::validate_contract(original_code, features, config)?;
prepare_v1::prepare_contract(original_code, config)
}
crate::logic::ContractPrepareVersion::V2 => {
prepare_v2::prepare_contract(original_code, features, config, kind)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::{test_vm_config, with_vm_variants};
use assert_matches::assert_matches;
fn parse_and_prepare_wat(
config: &Config,
vm_kind: VMKind,
wat: &str,
) -> Result<Vec<u8>, PrepareError> {
let wasm = wat::parse_str(wat).unwrap();
prepare_contract(wasm.as_ref(), &config, vm_kind)
}
#[test]
fn internal_memory_declaration() {
let config = test_vm_config();
with_vm_variants(&config, |kind| {
let r = parse_and_prepare_wat(&config, kind, r#"(module (memory 1 1))"#);
assert_matches!(r, Ok(_));
})
}
#[test]
fn memory_imports() {
let config = test_vm_config();
assert_eq!(config.limit_config.max_memory_pages, 2048);
with_vm_variants(&config, |kind| {
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "env" "memory" (memory 1 1)))"#,
);
assert_matches!(r, Err(PrepareError::Memory));
let r = parse_and_prepare_wat(&config, kind, r#"(module)"#);
assert_matches!(r, Ok(_));
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "env" "memory" (memory 17 1)))"#,
);
assert_matches!(r, Err(PrepareError::Deserialization));
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "env" "memory" (memory 1)))"#,
);
assert_matches!(r, Err(PrepareError::Memory));
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "env" "memory" (memory 1 33)))"#,
);
assert_matches!(r, Err(PrepareError::Memory));
})
}
#[test]
fn multiple_valid_memory_are_disabled() {
let config = test_vm_config();
with_vm_variants(&config, |kind| {
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module
(import "env" "memory" (memory 1 2048))
(import "env" "memory" (memory 1 2048))
)"#,
);
assert_matches!(r, Err(_));
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module
(import "env" "memory" (memory 1 2048))
(memory 1)
)"#,
);
assert_matches!(r, Err(_));
})
}
#[test]
fn imports() {
let config = test_vm_config();
with_vm_variants(&config, |kind| {
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "another_module" "memory" (memory 1 1)))"#,
);
assert_matches!(r, Err(PrepareError::Instantiate));
let r = parse_and_prepare_wat(
&config,
kind,
r#"(module (import "env" "gas" (func (param i32))))"#,
);
assert_matches!(r, Ok(_));
})
}
}