mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Embed runtime version as a custom section (#8688)
* emit a custom section from impl_runtime_apis! This change emits a custom section from the impl_runtime_apis! proc macro. Each implemented API will result to emitting a link section `runtime_apis`. During linking all sections with this name will be concatenated and placed into the final wasm binary under the same name. * Introduce `runtime_version` proc macro This macro takes an existing `RuntimeVersion` const declaration, parses it and emits the version information in form of a linking section. Ultimately such a linking section will result into a custom wasm section. * Parse custom wasm section for runtime version * Apply suggestions from code review Co-authored-by: David <dvdplm@gmail.com> * Fix sc-executor integration tests * Nits Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Refactor apis section deserialization * Fix version decoding * Reuse uncompressed value for CallInWasm * Log on decompression error * Simplify if * Reexport proc-macro from sp_version * Merge ReadRuntimeVersionExt * Export `read_embedded_version` * Fix test * Simplify searching for custom section Co-authored-by: David <dvdplm@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -26,7 +26,7 @@ use std::{
|
||||
pub use sp_externalities::{Externalities, ExternalitiesExt};
|
||||
|
||||
/// Code execution engine.
|
||||
pub trait CodeExecutor: Sized + Send + Sync + CallInWasm + Clone + 'static {
|
||||
pub trait CodeExecutor: Sized + Send + Sync + ReadRuntimeVersion + Clone + 'static {
|
||||
/// Externalities error type.
|
||||
type Error: Display + Debug + Send + Sync + 'static;
|
||||
|
||||
@@ -123,53 +123,42 @@ impl std::fmt::Display for CodeNotFound {
|
||||
}
|
||||
}
|
||||
|
||||
/// `Allow` or `Disallow` missing host functions when instantiating a WASM blob.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum MissingHostFunctions {
|
||||
/// Any missing host function will be replaced by a stub that returns an error when
|
||||
/// being called.
|
||||
Allow,
|
||||
/// Any missing host function will result in an error while instantiating the WASM blob,
|
||||
Disallow,
|
||||
}
|
||||
|
||||
impl MissingHostFunctions {
|
||||
/// Are missing host functions allowed?
|
||||
pub fn allowed(self) -> bool {
|
||||
matches!(self, Self::Allow)
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that can call a method in a WASM blob.
|
||||
pub trait CallInWasm: Send + Sync {
|
||||
/// Call the given `method` in the given `wasm_blob` using `call_data` (SCALE encoded arguments)
|
||||
/// to decode the arguments for the method.
|
||||
/// A trait that allows reading version information from the binary.
|
||||
pub trait ReadRuntimeVersion: Send + Sync {
|
||||
/// Reads the runtime version information from the given wasm code.
|
||||
///
|
||||
/// Returns the SCALE encoded return value of the method.
|
||||
/// The version information may be embedded into the wasm binary itself. If it is not present,
|
||||
/// then this function may fallback to the legacy way of reading the version.
|
||||
///
|
||||
/// # Note
|
||||
/// The legacy mechanism involves instantiating the passed wasm runtime and calling `Core_version`
|
||||
/// on it. This is a very expensive operation.
|
||||
///
|
||||
/// If `code_hash` is `Some(_)` the `wasm_code` module and instance will be cached internally,
|
||||
/// otherwise it is thrown away after the call.
|
||||
fn call_in_wasm(
|
||||
/// `ext` is only needed in case the calling into runtime happens. Otherwise it is ignored.
|
||||
///
|
||||
/// Compressed wasm blobs are supported and will be decompressed if needed. If uncompression fails,
|
||||
/// the error is returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the version information present in binary, but is corrupted - returns an error.
|
||||
///
|
||||
/// Otherwise, if there is no version information present, and calling into the runtime takes
|
||||
/// place, then an error would be returned if `Core_version` is not provided.
|
||||
fn read_runtime_version(
|
||||
&self,
|
||||
wasm_code: &[u8],
|
||||
code_hash: Option<Vec<u8>>,
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
ext: &mut dyn Externalities,
|
||||
missing_host_functions: MissingHostFunctions,
|
||||
) -> Result<Vec<u8>, String>;
|
||||
}
|
||||
|
||||
sp_externalities::decl_extension! {
|
||||
/// The call-in-wasm extension to register/retrieve from the externalities.
|
||||
pub struct CallInWasmExt(Box<dyn CallInWasm>);
|
||||
/// An extension that provides functionality to read version information from a given wasm blob.
|
||||
pub struct ReadRuntimeVersionExt(Box<dyn ReadRuntimeVersion>);
|
||||
}
|
||||
|
||||
impl CallInWasmExt {
|
||||
/// Creates a new instance of `Self`.
|
||||
pub fn new<T: CallInWasm + 'static>(inner: T) -> Self {
|
||||
impl ReadRuntimeVersionExt {
|
||||
/// Creates a new instance of the extension given a version determinator instance.
|
||||
pub fn new<T: ReadRuntimeVersion + 'static>(inner: T) -> Self {
|
||||
Self(Box::new(inner))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user