mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-22 23:11:08 +00:00
Load latest metadata version from Wasm blobs. (#1859)
* use "metadata_at_version" closes #1858
This commit is contained in:
+116
-19
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use std::{borrow::Cow, path::Path};
|
use std::{borrow::Cow, path::Path};
|
||||||
|
|
||||||
use codec::Decode;
|
use codec::{Decode, Encode};
|
||||||
use polkadot_sdk::{
|
use polkadot_sdk::{
|
||||||
sc_executor::{self, WasmExecutionMethod, WasmExecutor},
|
sc_executor::{self, WasmExecutionMethod, WasmExecutor},
|
||||||
sc_executor_common::runtime_blob::RuntimeBlob,
|
sc_executor_common::runtime_blob::RuntimeBlob,
|
||||||
@@ -14,6 +14,8 @@ use polkadot_sdk::{
|
|||||||
};
|
};
|
||||||
use subxt_codegen::{CodegenError, Metadata};
|
use subxt_codegen::{CodegenError, Metadata};
|
||||||
|
|
||||||
|
static SUPPORTED_METADATA_VERSIONS: [u32; 2] = [14, 15];
|
||||||
|
|
||||||
/// Result type shorthand
|
/// Result type shorthand
|
||||||
pub type WasmMetadataResult<A> = Result<A, CodegenError>;
|
pub type WasmMetadataResult<A> = Result<A, CodegenError>;
|
||||||
|
|
||||||
@@ -26,26 +28,18 @@ pub fn from_wasm_file(wasm_file_path: &Path) -> WasmMetadataResult<Metadata> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call_and_decode(wasm_file: Vec<u8>) -> WasmMetadataResult<Metadata> {
|
fn call_and_decode(wasm_file: Vec<u8>) -> WasmMetadataResult<Metadata> {
|
||||||
let mut ext: sp_state_machine::BasicExternalities = Default::default();
|
let mut executor = Executor::new(&wasm_file)?;
|
||||||
|
|
||||||
let executor: WasmExecutor<sp_io::SubstrateHostFunctions> = WasmExecutor::builder()
|
if let Ok(versions) = executor.versions() {
|
||||||
.with_execution_method(WasmExecutionMethod::default())
|
let version = versions
|
||||||
.with_offchain_heap_alloc_strategy(sc_executor::HeapAllocStrategy::Dynamic {
|
.into_iter()
|
||||||
maximum_pages: Some(64),
|
.max()
|
||||||
})
|
.expect("This is checked earlier and can't fail.");
|
||||||
.with_max_runtime_instances(1)
|
|
||||||
.with_runtime_cache_size(1)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let runtime_blob =
|
executor.load_metadata_at_version(version)
|
||||||
RuntimeBlob::new(&wasm_file).map_err(|e| CodegenError::Wasm(e.to_string()))?;
|
} else {
|
||||||
let metadata_encoded = executor
|
executor.load_legacy_metadata()
|
||||||
.uncached_call(runtime_blob, &mut ext, true, "Metadata_metadata", &[])
|
}
|
||||||
.map_err(|_| CodegenError::Wasm("method \"Metadata_metadata\" doesnt exist".to_owned()))?;
|
|
||||||
|
|
||||||
let metadata = <Vec<u8>>::decode(&mut &metadata_encoded[..]).map_err(CodegenError::Decode)?;
|
|
||||||
|
|
||||||
decode(metadata)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode(encoded_metadata: Vec<u8>) -> WasmMetadataResult<Metadata> {
|
fn decode(encoded_metadata: Vec<u8>) -> WasmMetadataResult<Metadata> {
|
||||||
@@ -57,3 +51,106 @@ fn maybe_decompress(file_contents: Vec<u8>) -> WasmMetadataResult<Vec<u8>> {
|
|||||||
.map_err(|e| CodegenError::Wasm(e.to_string()))
|
.map_err(|e| CodegenError::Wasm(e.to_string()))
|
||||||
.map(Cow::into_owned)
|
.map(Cow::into_owned)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Executor {
|
||||||
|
runtime_blob: RuntimeBlob,
|
||||||
|
executor: WasmExecutor<sp_io::SubstrateHostFunctions>,
|
||||||
|
externalities: sp_state_machine::BasicExternalities,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Executor {
|
||||||
|
fn new(wasm_file: &[u8]) -> WasmMetadataResult<Self> {
|
||||||
|
let externalities: sp_state_machine::BasicExternalities = Default::default();
|
||||||
|
|
||||||
|
let executor: WasmExecutor<sp_io::SubstrateHostFunctions> = 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<Vec<u32>> {
|
||||||
|
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 = <Vec<u32>>::decode(&mut &version[..])
|
||||||
|
.map_err(CodegenError::Decode)
|
||||||
|
.map(|x| {
|
||||||
|
x.into_iter()
|
||||||
|
.filter(|version| SUPPORTED_METADATA_VERSIONS.contains(version))
|
||||||
|
.collect::<Vec<u32>>()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if versions.is_empty() {
|
||||||
|
return Err(CodegenError::Other(
|
||||||
|
"No supported metadata versions were returned".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(versions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_legacy_metadata(&mut self) -> WasmMetadataResult<Metadata> {
|
||||||
|
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 =
|
||||||
|
<Vec<u8>>::decode(&mut &encoded_metadata[..]).map_err(CodegenError::Decode)?;
|
||||||
|
decode(encoded_metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_metadata_at_version(&mut self, version: u32) -> WasmMetadataResult<Metadata> {
|
||||||
|
let encoded_metadata = self
|
||||||
|
.executor
|
||||||
|
.uncached_call(
|
||||||
|
self.runtime_blob.clone(),
|
||||||
|
&mut self.externalities,
|
||||||
|
false,
|
||||||
|
"Metadata_metadata_at_version",
|
||||||
|
&version.encode(),
|
||||||
|
)
|
||||||
|
.map_err(|_| {
|
||||||
|
CodegenError::Wasm(
|
||||||
|
"method \"Metadata_metadata_at_version\" doesnt exist".to_owned(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let Some(encoded_metadata) =
|
||||||
|
<Option<Vec<u8>>>::decode(&mut &encoded_metadata[..]).map_err(CodegenError::Decode)?
|
||||||
|
else {
|
||||||
|
return Err(CodegenError::Other(
|
||||||
|
format!("Received empty metadata at version: v{version}").to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
decode(encoded_metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user