From d1351b2421b6f2ecec21db7211c7c88b18c8bdd2 Mon Sep 17 00:00:00 2001
From: Pavlo Khrystenko
Date: Fri, 8 Nov 2024 14:24:49 +0100
Subject: [PATCH 1/3] use "metadata_at_version"
closes #1858
---
macro/src/wasm_loader.rs | 47 ++++++++++++++++++++++++++++++++++------
1 file changed, 40 insertions(+), 7 deletions(-)
diff --git a/macro/src/wasm_loader.rs b/macro/src/wasm_loader.rs
index f8be106dce..4c55c46138 100644
--- a/macro/src/wasm_loader.rs
+++ b/macro/src/wasm_loader.rs
@@ -4,7 +4,7 @@
use std::{borrow::Cow, path::Path};
-use codec::Decode;
+use codec::{Decode, Encode};
use polkadot_sdk::{
sc_executor::{self, WasmExecutionMethod, WasmExecutor},
sc_executor_common::runtime_blob::RuntimeBlob,
@@ -39,17 +39,50 @@ fn call_and_decode(wasm_file: Vec) -> WasmMetadataResult {
let runtime_blob =
RuntimeBlob::new(&wasm_file).map_err(|e| CodegenError::Wasm(e.to_string()))?;
- let metadata_encoded = executor
- .uncached_call(runtime_blob, &mut ext, true, "Metadata_metadata", &[])
- .map_err(|_| CodegenError::Wasm("method \"Metadata_metadata\" doesnt exist".to_owned()))?;
- let metadata = >::decode(&mut &metadata_encoded[..]).map_err(CodegenError::Decode)?;
+ let version = executor
+ .uncached_call(
+ runtime_blob.clone(),
+ &mut ext,
+ true,
+ "Metadata_metadata_versions",
+ &[],
+ )
+ .map_err(|_| {
+ CodegenError::Wasm("method \"Metadata_metadata_versions\" doesnt exist".to_owned())
+ })?;
+ let mut versions = >::decode(&mut &version[..]).map_err(CodegenError::Decode)?;
- decode(metadata)
+ // Highest version will always be the last one in the vec
+ versions.sort();
+
+ let version = versions
+ .last()
+ .ok_or(CodegenError::Other(
+ "No metadata versions were returned".to_owned(),
+ ))
+ .map(|v| v.encode())?;
+
+ let encoded_metadata = executor
+ .uncached_call(
+ runtime_blob,
+ &mut ext,
+ false,
+ "Metadata_metadata_at_version",
+ &version,
+ )
+ .map_err(|e| {
+ dbg!(e);
+ CodegenError::Wasm("method \"Metadata_metadata_at_version\" doesnt exist".to_owned())
+ })?;
+
+ decode(encoded_metadata)
}
fn decode(encoded_metadata: Vec) -> WasmMetadataResult {
- Metadata::decode(&mut encoded_metadata.as_ref()).map_err(Into::into)
+ // We slice the first byte from the metadata because it's wrapped inside an option and we know that its always `Some`
+ let metadata = >::decode(&mut &encoded_metadata[1..]).map_err(CodegenError::Decode)?;
+ Metadata::decode(&mut metadata.as_ref()).map_err(Into::into)
}
fn maybe_decompress(file_contents: Vec) -> WasmMetadataResult> {
From fdb82e1e32b015ae6408455d24beef00ef9a0766 Mon Sep 17 00:00:00 2001
From: Pavlo Khrystenko
Date: Mon, 11 Nov 2024 13:07:16 +0100
Subject: [PATCH 2/3] review comments
---
macro/src/wasm_loader.rs | 174 +++++++++++++++++++++++++++------------
1 file changed, 121 insertions(+), 53 deletions(-)
diff --git a/macro/src/wasm_loader.rs b/macro/src/wasm_loader.rs
index 4c55c46138..3fb2f0b9df 100644
--- a/macro/src/wasm_loader.rs
+++ b/macro/src/wasm_loader.rs
@@ -14,6 +14,8 @@ use polkadot_sdk::{
};
use subxt_codegen::{CodegenError, Metadata};
+static SUPPORTED_METADATA_VERSIONS: [u32; 2] = [14, 15];
+
/// Result type shorthand
pub type WasmMetadataResult = Result;
@@ -26,63 +28,17 @@ pub fn from_wasm_file(wasm_file_path: &Path) -> WasmMetadataResult {
}
fn call_and_decode(wasm_file: Vec) -> WasmMetadataResult {
- let mut ext: sp_state_machine::BasicExternalities = Default::default();
+ let mut executor = Executor::new(&wasm_file)?;
- let executor: WasmExecutor = WasmExecutor::builder()
- .with_execution_method(WasmExecutionMethod::default())
- .with_offchain_heap_alloc_strategy(sc_executor::HeapAllocStrategy::Dynamic {
- maximum_pages: Some(64),
- })
- .with_max_runtime_instances(1)
- .with_runtime_cache_size(1)
- .build();
-
- let runtime_blob =
- RuntimeBlob::new(&wasm_file).map_err(|e| CodegenError::Wasm(e.to_string()))?;
-
- let version = executor
- .uncached_call(
- runtime_blob.clone(),
- &mut ext,
- true,
- "Metadata_metadata_versions",
- &[],
- )
- .map_err(|_| {
- CodegenError::Wasm("method \"Metadata_metadata_versions\" doesnt exist".to_owned())
- })?;
- let mut versions = >::decode(&mut &version[..]).map_err(CodegenError::Decode)?;
-
- // Highest version will always be the last one in the vec
- versions.sort();
-
- let version = versions
- .last()
- .ok_or(CodegenError::Other(
- "No metadata versions were returned".to_owned(),
- ))
- .map(|v| v.encode())?;
-
- let encoded_metadata = executor
- .uncached_call(
- runtime_blob,
- &mut ext,
- false,
- "Metadata_metadata_at_version",
- &version,
- )
- .map_err(|e| {
- dbg!(e);
- CodegenError::Wasm("method \"Metadata_metadata_at_version\" doesnt exist".to_owned())
- })?;
-
- decode(encoded_metadata)
+ if let Ok(versions) = executor.versions() {
+ executor.load_metadata_at_latest_version(versions)
+ } else {
+ executor.metadata()
+ }
}
fn decode(encoded_metadata: Vec) -> WasmMetadataResult {
- // We slice the first byte from the metadata because it's wrapped inside an option and we know that its always `Some`
- let metadata = >::decode(&mut &encoded_metadata[1..]).map_err(CodegenError::Decode)?;
- Metadata::decode(&mut metadata.as_ref()).map_err(Into::into)
+ Metadata::decode(&mut encoded_metadata.as_ref()).map_err(Into::into)
}
fn maybe_decompress(file_contents: Vec) -> WasmMetadataResult> {
@@ -90,3 +46,115 @@ fn maybe_decompress(file_contents: Vec) -> WasmMetadataResult> {
.map_err(|e| CodegenError::Wasm(e.to_string()))
.map(Cow::into_owned)
}
+
+struct Executor {
+ runtime_blob: RuntimeBlob,
+ executor: WasmExecutor,
+ externalities: sp_state_machine::BasicExternalities,
+}
+
+impl Executor {
+ fn new(wasm_file: &[u8]) -> WasmMetadataResult {
+ let externalities: sp_state_machine::BasicExternalities = Default::default();
+
+ let executor: WasmExecutor = WasmExecutor::builder()
+ .with_execution_method(WasmExecutionMethod::default())
+ .with_offchain_heap_alloc_strategy(sc_executor::HeapAllocStrategy::Dynamic {
+ maximum_pages: Some(64),
+ })
+ .with_max_runtime_instances(1)
+ .with_runtime_cache_size(1)
+ .build();
+
+ let runtime_blob =
+ RuntimeBlob::new(wasm_file).map_err(|e| CodegenError::Wasm(e.to_string()))?;
+
+ Ok(Self {
+ runtime_blob,
+ executor,
+ externalities,
+ })
+ }
+
+ fn versions(&mut self) -> WasmMetadataResult> {
+ let version = self
+ .executor
+ .uncached_call(
+ self.runtime_blob.clone(),
+ &mut self.externalities,
+ true,
+ "Metadata_metadata_versions",
+ &[],
+ )
+ .map_err(|_| {
+ CodegenError::Wasm("method \"Metadata_metadata_versions\" doesnt exist".to_owned())
+ })?;
+ let versions = >::decode(&mut &version[..])
+ .map_err(CodegenError::Decode)
+ .map(|x| {
+ x.into_iter()
+ .filter(|version| SUPPORTED_METADATA_VERSIONS.contains(version))
+ .collect::>()
+ })?;
+
+ if versions.is_empty() {
+ return Err(CodegenError::Other(
+ "No supported metadata versions were returned".to_owned(),
+ ));
+ }
+
+ Ok(versions)
+ }
+
+ fn metadata(&mut self) -> WasmMetadataResult {
+ let encoded_metadata = self
+ .executor
+ .uncached_call(
+ self.runtime_blob.clone(),
+ &mut self.externalities,
+ false,
+ "Metadata_metadata",
+ &[],
+ )
+ .map_err(|_| {
+ CodegenError::Wasm("method \"Metadata_metadata\" doesnt exist".to_owned())
+ })?;
+ let encoded_metadata =
+ >::decode(&mut &encoded_metadata[..]).map_err(CodegenError::Decode)?;
+ decode(encoded_metadata)
+ }
+
+ fn load_metadata_at_latest_version(
+ &mut self,
+ versions: Vec,
+ ) -> WasmMetadataResult {
+ let version = versions
+ .into_iter()
+ .max()
+ .expect("This is checked earlier and can't fail.");
+
+ let encoded_metadata = self
+ .executor
+ .uncached_call(
+ self.runtime_blob.clone(),
+ &mut self.externalities,
+ false,
+ "Metadata_metadata_at_version",
+ &version.encode(),
+ )
+ .map_err(|e| {
+ dbg!(e);
+ CodegenError::Wasm(
+ "method \"Metadata_metadata_at_version\" doesnt exist".to_owned(),
+ )
+ })?;
+ let Some(encoded_metadata) =
+