Skip to content

Commit

Permalink
Parse the contract state version from the custom section
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Apr 25, 2024
1 parent ab31374 commit f1ae43c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ hex-literal = "0.4.1"
rand = "0.8"
tempfile = "3.1.0"
wat = "1.0"
wasm-encoder = "0.205.0"
clap = "4"
leb128 = "0.2"
target-lexicon = "0.12"
Expand Down
26 changes: 26 additions & 0 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ pub struct AnalysisReport {
pub entrypoints: BTreeSet<Entrypoint>,
/// The set of capabilities the contract requires.
pub required_capabilities: BTreeSet<String>,
/// The contract state version exported set by the contract developer
pub contract_state_version: Option<u64>,
}

impl<A, S, Q> Cache<A, S, Q>
Expand Down Expand Up @@ -320,6 +322,7 @@ where
required_capabilities: required_capabilities_from_module(&module)
.into_iter()
.collect(),
contract_state_version: module.contract_state_version,
})
}

Expand Down Expand Up @@ -584,6 +587,7 @@ mod tests {
use cosmwasm_std::{coins, Empty};
use std::fs::{create_dir_all, remove_dir_all};
use tempfile::TempDir;
use wasm_encoder::ComponentSection;

const TESTING_GAS_LIMIT: u64 = 500_000_000; // ~0.5ms
const TESTING_MEMORY_LIMIT: Size = Size::mebi(16);
Expand Down Expand Up @@ -1410,6 +1414,7 @@ mod tests {
E::Query
]),
required_capabilities: BTreeSet::new(),
contract_state_version: None,
}
);

Expand All @@ -1427,6 +1432,7 @@ mod tests {
"iterator".to_string(),
"stargate".to_string()
]),
contract_state_version: None,
}
);

Expand All @@ -1438,6 +1444,26 @@ mod tests {
has_ibc_entry_points: false,
entrypoints: BTreeSet::new(),
required_capabilities: BTreeSet::from(["iterator".to_string()]),
contract_state_version: None,
}
);

let mut wasm_with_version = EMPTY_CONTRACT.to_vec();
let custom_section = wasm_encoder::CustomSection {
name: "cw_state_version".into(),
data: b"21".into(),
};
custom_section.append_to_component(&mut wasm_with_version);

let checksum4 = cache.save_wasm(&wasm_with_version).unwrap();
let report4 = cache.analyze(&checksum4).unwrap();
assert_eq!(
report4,
AnalysisReport {
has_ibc_entry_points: false,
entrypoints: BTreeSet::new(),
required_capabilities: BTreeSet::from(["iterator".to_string()]),
contract_state_version: Some(21),
}
);
}
Expand Down
37 changes: 36 additions & 1 deletion packages/vm/src/parsed_wasm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt, mem};
use std::{fmt, mem, str};

use wasmer::wasmparser::{
BinaryReaderError, CompositeType, Export, FuncToValidate, FunctionBody, Import, MemoryType,
Expand Down Expand Up @@ -66,6 +66,8 @@ pub struct ParsedWasm<'a> {
pub total_func_params: usize,
/// Collections of functions that are potentially pending validation
pub func_validator: FunctionValidator<'a>,
/// Contract state version as defined in a custom section
pub contract_state_version: Option<u64>,
}

impl<'a> ParsedWasm<'a> {
Expand Down Expand Up @@ -108,6 +110,7 @@ impl<'a> ParsedWasm<'a> {
max_func_results: 0,
total_func_params: 0,
func_validator: FunctionValidator::Pending(OpaqueDebug::default()),
contract_state_version: None,
};

for p in Parser::new(0).parse_all(wasm) {
Expand Down Expand Up @@ -179,6 +182,17 @@ impl<'a> ParsedWasm<'a> {
Payload::ExportSection(e) => {
this.exports = e.into_iter().collect::<Result<Vec<_>, _>>()?;
}
Payload::CustomSection(reader) if reader.name() == "cw_state_version" => {
// This is supposed to be valid UTF-8
let raw_version = str::from_utf8(reader.data())
.map_err(|err| VmError::parse_err("str", err))?;

this.contract_state_version = Some(
raw_version
.parse()
.map_err(|err| VmError::parse_err("u64", err))?,
);
}
_ => {} // ignore everything else
}
}
Expand Down Expand Up @@ -214,3 +228,24 @@ impl<'a> ParsedWasm<'a> {
}
}
}

#[cfg(test)]
mod test {
use super::ParsedWasm;

#[test]
fn read_state_version() {
let wasm_data =
wat::parse_str(r#"( module ( @custom "cw_state_version" "42" ) )"#).unwrap();
let parsed = ParsedWasm::parse(&wasm_data).unwrap();

assert_eq!(parsed.contract_state_version, Some(42));
}

#[test]
fn read_state_version_fails() {
let wasm_data =
wat::parse_str(r#"( module ( @custom "cw_state_version" "not a number" ) )"#).unwrap();
assert!(ParsedWasm::parse(&wasm_data).is_err());
}
}

0 comments on commit f1ae43c

Please sign in to comment.