From 8612eab9a1e6a713b04f86e624c5501fcf1c1808 Mon Sep 17 00:00:00 2001 From: Miguel Naveira <47919901+mrnaveira@users.noreply.github.com> Date: Wed, 13 Dec 2023 09:47:23 +0000 Subject: [PATCH] feat: add version to template WASMs (#835) Description --- * Updated the template definition in the ABI to include the Tari version it was compiled on * Validator nodes call this new function when loading a new template WASM for execution, and check the version against the engine's own version. For now, no errors are returned even if they don't match, only logging is performed. Motivation and Context --- We want to know the Tari version (i.e. the Cargo package version of the project) that a template was compiled with, as this determines the engine calls that it may request during execution. The goal is to be able to detect version incompatibilities when executing. For now this PR only adds the version to the template WASMs and logs version match/mismatch, no error is returned. In the future this setup will allow us to load the appropriate `template_lib` version (and/or other dependencies) for each template and avoid incompatibilities. How Has This Been Tested? --- Launching a local network and inspecting the VN logs when executing a transaction for the Tari version messages What process can a PR reviewer use to test or verify this change? --- Inspect the VN logs when executing a transaction for the Tari version messages Breaking Changes --- - [ ] None - [ ] Requires data directory to be deleted - [x] Breaking change: the Template ABI changes so all templates (included the built-in ones) must be recompiled --- dan_layer/engine/src/flow/flow_factory.rs | 3 +++ dan_layer/engine/src/wasm/process.rs | 20 +++++++++++++++++++ dan_layer/template_abi/src/types.rs | 7 +++++++ dan_layer/template_macros/src/template/abi.rs | 3 +++ 4 files changed, 33 insertions(+) diff --git a/dan_layer/engine/src/flow/flow_factory.rs b/dan_layer/engine/src/flow/flow_factory.rs index 8f82a58c6..cdae7ee07 100644 --- a/dan_layer/engine/src/flow/flow_factory.rs +++ b/dan_layer/engine/src/flow/flow_factory.rs @@ -16,6 +16,8 @@ use crate::{ template::LoadedTemplate, }; +pub const TARI_VERSION: &str = env!("CARGO_PKG_VERSION"); + #[derive(Debug, Clone)] pub struct FlowFactory { name: String, @@ -29,6 +31,7 @@ impl FlowFactory { ) -> Result { let template_def = TemplateDef::V1(TemplateDefV1 { template_name: flow_definition.name.clone(), + tari_version: TARI_VERSION.to_owned(), functions: vec![FunctionDef { name: "main".to_string(), arguments: flow_definition diff --git a/dan_layer/engine/src/wasm/process.rs b/dan_layer/engine/src/wasm/process.rs index 77c32a3ab..7d9890a12 100644 --- a/dan_layer/engine/src/wasm/process.rs +++ b/dan_layer/engine/src/wasm/process.rs @@ -54,7 +54,10 @@ use crate::{ LoadedWasmTemplate, }, }; + const LOG_TARGET: &str = "tari::dan::engine::wasm::process"; +pub const ENGINE_TARI_VERSION: &str = env!("CARGO_PKG_VERSION"); + #[derive(Debug)] pub struct WasmProcess { module: LoadedWasmTemplate, @@ -69,6 +72,7 @@ impl WasmProcess { let tari_engine = Function::new_native_with_env(store, env.clone(), Self::tari_engine_entrypoint); let resolver = env.create_resolver(store, tari_engine); let instance = Instance::new(module.wasm_module(), &resolver)?; + Self::validate_template_tari_version(&module)?; env.init_with_instance(&instance)?; Ok(Self { module, env, instance }) } @@ -203,6 +207,22 @@ impl WasmProcess { fn encoded_abi_context(&self) -> Vec { encode(&AbiContext {}).unwrap() } + + /// Determine if the version of the template_lib crate in the WASM is valid. + /// This is just a placeholder that logs the result, as we don't manage version incompatiblities yet + fn validate_template_tari_version(module: &LoadedWasmTemplate) -> Result<(), WasmExecutionError> { + let template_tari_version = module.template_def().tari_version(); + + if template_tari_version == ENGINE_TARI_VERSION { + log::info!(target: LOG_TARGET, "The Tari version version in the template WASM (\"{}\") matches the one used in the engine", template_tari_version); + } else { + // For now we are going to ignore version mismatches + // In the future we could load a different version of the template_lib in the engine + log::warn!(target: LOG_TARGET, "The Tari version in the template WASM (\"{}\") does not matches the one used in the engine (\"{}\")", template_tari_version, ENGINE_TARI_VERSION); + } + + Ok(()) + } } impl Invokable for WasmProcess { diff --git a/dan_layer/template_abi/src/types.rs b/dan_layer/template_abi/src/types.rs index b64e3f606..6c9558ac7 100644 --- a/dan_layer/template_abi/src/types.rs +++ b/dan_layer/template_abi/src/types.rs @@ -36,6 +36,12 @@ impl TemplateDef { } } + pub fn tari_version(&self) -> &str { + match self { + TemplateDef::V1(def) => def.tari_version.as_str(), + } + } + pub fn get_function(&self, name: &str) -> Option<&FunctionDef> { match self { TemplateDef::V1(def) => def.get_function(name), @@ -52,6 +58,7 @@ impl TemplateDef { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TemplateDefV1 { pub template_name: String, + pub tari_version: String, pub functions: Vec, } diff --git a/dan_layer/template_macros/src/template/abi.rs b/dan_layer/template_macros/src/template/abi.rs index 34a5a836e..1216bebe9 100644 --- a/dan_layer/template_macros/src/template/abi.rs +++ b/dan_layer/template_macros/src/template/abi.rs @@ -34,11 +34,14 @@ use tari_template_abi::{ use crate::template::ast::{TemplateAst, TypeAst}; +pub const TARI_VERSION: &str = env!("CARGO_PKG_VERSION"); + pub fn generate_abi(ast: &TemplateAst) -> Result { let template_name_as_str = ast.template_name.to_string(); let template_def = TemplateDef::V1(TemplateDefV1 { template_name: template_name_as_str.clone(), + tari_version: TARI_VERSION.to_owned(), functions: ast .get_functions() .map(|func| {