Unverified Commit e6ad6652 authored by Bastian Köcher's avatar Bastian Köcher Committed by GitHub
Browse files

Switch parachain interface to new `runtime_interface` macro (#665)



* Make use of `runtime_interface` for parachain externalities

This also changes the encoding of the `ValidationResult` return value to
match the default encoding used in Substrate.

* Fix compilation for web

* Update `Cargo.lock`

* Include feedback

* Move proc macro

* Update parachain/src/lib.rs
Co-Authored-By: asynchronous rob's avatarRobert Habermeier <rphmeier@gmail.com>
Co-authored-by: asynchronous rob's avatarRobert Habermeier <rphmeier@gmail.com>
parent b2509f9d
Pipeline #73886 passed with stages
in 17 minutes and 55 seconds
......@@ -29,7 +29,8 @@ dependencies = [
"ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"polkadot-collator 0.7.15",
"polkadot-parachain 0.7.15",
"polkadot-primitives 0.7.15",
......@@ -2623,7 +2624,6 @@ name = "lock_api"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -3500,14 +3500,6 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-wasm"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-wasm"
version = "0.41.0"
......@@ -3542,6 +3534,15 @@ dependencies = [
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.4.0"
......@@ -3583,6 +3584,19 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "paste"
version = "0.1.6"
......@@ -3803,18 +3817,21 @@ name = "polkadot-parachain"
version = "0.7.15"
dependencies = [
"adder 0.7.15",
"derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)",
"halt 0.7.15",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sc-executor 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
"shared_memory 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shared_memory 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-core 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"sp-externalities 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"sp-io 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"sp-runtime-interface 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"sp-std 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)",
"tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -5412,19 +5429,32 @@ dependencies = [
[[package]]
name = "shared_memory"
version = "0.8.2"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memrange 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"shared_memory_derive 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"theban_interval_tree 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shared_memory_derive"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shell32-sys"
version = "0.1.2"
......@@ -6897,16 +6927,6 @@ dependencies = [
"web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmi"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmi"
version = "0.6.2"
......@@ -6920,14 +6940,6 @@ dependencies = [
"wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmi-validation"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmi-validation"
version = "0.3.0"
......@@ -7556,14 +7568,15 @@ dependencies = [
"checksum parity-scale-codec-derive 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "492ac3aa93d6caa5d20e4e3e0b75d08e2dcd9dd8a50d19529548b6fe11b3f295"
"checksum parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f"
"checksum parity-util-mem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8174d85e62c4d615fddd1ef67966bdc5757528891d0742f15b131ad04667b3f9"
"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc"
"checksum parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865"
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7"
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c"
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49"
"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9"
......@@ -7683,7 +7696,8 @@ dependencies = [
"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
"checksum shared_memory 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "be289420c5900abb177b756f39625ca7a0df68069cfb242fb31feb6e8c480f04"
"checksum shared_memory 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3ab0cdff84d6c66fc9e268010ea6508e58ee942575afb66f2cf194bb218bb4"
"checksum shared_memory_derive 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767a14f1304be2f0b04e69860252f8ae9cfae0afaa9cc07b675147c43425dd3a"
"checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
......@@ -7829,9 +7843,7 @@ dependencies = [
"checksum wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "ca0b78d6d3be8589b95d1d49cdc0794728ca734adf36d7c9f07e6459508bb53d"
"checksum wasm-bindgen-webidl 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "3126356474ceb717c8fb5549ae387c9fbf4872818454f4d87708bee997214bb5"
"checksum wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa3e01d234bb71760e685cfafa5e2c96f8ad877c161a721646356651069e26ac"
"checksum wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aebbaef470840d157a5c47c8c49f024da7b1b80e90ff729ca982b2b80447e78b"
"checksum wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff"
"checksum wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab380192444b3e8522ae79c0a1976e42a82920916ccdfbce3def89f456ea33f3"
"checksum wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93"
"checksum wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c702914acda5feeeffbc29e4d953e5b9ce79d8b98da4dbf18a77086e116c5470"
"checksum wasmtime-debug 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5008729ad53f75020f28fa0d682269335d6f0eac0b3ffafe31f185b2f33aca74"
......
......@@ -7,17 +7,20 @@ edition = "2018"
[dependencies]
codec = { package = "parity-scale-codec", version = "1.1.0", default-features = false, features = [ "derive" ] }
wasmi = { version = "0.4.5", optional = true }
derive_more = { version = "0.14.1", optional = true }
serde = { version = "1.0.102", default-features = false, features = [ "derive" ] }
derive_more = { version = "0.99.2", optional = true }
serde = { version = "1.0.102", default-features = false, features = [ "derive" ], optional = true }
rstd = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master", default-features = false }
sp-runtime-interface = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master", default-features = false }
sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true }
lazy_static = { version = "1.4.0", optional = true }
parking_lot = { version = "0.7.1", optional = true }
parking_lot = { version = "0.10.0", optional = true }
log = { version = "0.4.8", optional = true }
[target.'cfg(not(target_os = "unknown"))'.dependencies]
shared_memory = { version = "0.8.2", optional = true }
shared_memory = { version = "0.10.0", optional = true }
[dev-dependencies]
tiny-keccak = "1.5.0"
......@@ -29,7 +32,6 @@ default = ["std"]
wasm-api = []
std = [
"codec/std",
"wasmi",
"derive_more",
"serde/std",
"rstd/std",
......@@ -37,5 +39,9 @@ std = [
"sp-core/std",
"lazy_static",
"parking_lot",
"log"
"log",
"sp-runtime-interface/std",
"sp-externalities",
"sc-executor",
"sp-io",
]
......@@ -22,40 +22,40 @@
//! ## Parachain WASM
//!
//! Polkadot parachain WASM is in the form of a module which imports a memory
//! instance and exports a function `validate`.
//! instance and exports a function `validate_block`.
//!
//! `validate` accepts as input two `i32` values, representing a pointer/length pair
//! respectively, that encodes `ValidationParams`.
//! respectively, that encodes [`ValidationParams`].
//!
//! `validate` returns an `i32` which is a pointer to a little-endian 32-bit integer denoting a length.
//! Subtracting the length from the initial pointer will give a new pointer to the actual return data,
//! `validate` returns an `u64` which is a pointer to an `u8` array and its length.
//! The data in the array is expected to be a SCALE encoded [`ValidationResult`].
//!
//! ASCII-diagram demonstrating the return data format:
//!
//! ```ignore
//! [return data][len (LE-u32)]
//! ^~~returned pointer
//! [pointer][length]
//! 32bit 32bit
//! ^~~ returned pointer & length
//! ```
//!
//! The `wasm_api` module (enabled only with the wasm-api feature) provides utilities
//! for setting up a parachain WASM module in Rust.
//! The wasm-api (enabled only when `std` feature is not enabled and `wasm-api` feature is enabled)
//! provides utilities for setting up a parachain WASM module in Rust.
#![cfg_attr(not(feature = "std"), no_std)]
/// Re-export of parity-codec.
pub use codec;
#[cfg(feature = "std")]
pub mod wasm_executor;
#[cfg(feature = "wasm-api")]
pub mod wasm_api;
mod wasm_api;
use rstd::vec::Vec;
use rstd::{vec::Vec, cmp::Ordering};
use codec::{Encode, Decode, CompactAs};
use sp_core::{RuntimeDebug, TypeId};
#[cfg(all(not(feature = "std"), feature = "wasm-api"))]
pub use wasm_api::*;
/// Validation parameters for evaluating the parachain validity function.
// TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220)
#[derive(PartialEq, Eq, Decode)]
......@@ -155,7 +155,8 @@ pub trait AccountIdConversion<AccountId>: Sized {
fn try_from_account(a: &AccountId) -> Option<Self>;
}
/// Format is b"para" ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to fill AccountId.
/// Format is b"para" ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing
/// zeroes to fill AccountId.
impl<T: Encode + Decode + Default> AccountIdConversion<T> for Id {
fn into_account(&self) -> T {
(b"para", self).using_encoded(|b|
......@@ -177,24 +178,6 @@ impl<T: Encode + Decode + Default> AccountIdConversion<T> for Id {
}
}
/// An incoming message.
#[derive(PartialEq, Eq, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Encode))]
pub struct IncomingMessage {
/// The source parachain.
pub source: Id,
/// The data of the message.
pub data: Vec<u8>,
}
/// A reference to a message.
pub struct MessageRef<'a> {
/// The target parachain.
pub target: Id,
/// Underlying data of the message.
pub data: &'a [u8],
}
/// Which origin a parachain's message to the relay chain should be dispatched from.
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
......@@ -224,16 +207,8 @@ impl rstd::convert::TryFrom<u8> for ParachainDispatchOrigin {
}
}
/// A reference to an upward message.
pub struct UpwardMessageRef<'a> {
/// The origin type.
pub origin: ParachainDispatchOrigin,
/// Underlying data of the message.
pub data: &'a [u8],
}
/// A message from a parachain to its Relay Chain.
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime_interface::pass_by::PassByCodec)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct UpwardMessage {
/// The origin for the message to be sent from.
......@@ -241,3 +216,43 @@ pub struct UpwardMessage {
/// The message data.
pub data: Vec<u8>,
}
/// An incoming message.
#[derive(PartialEq, Eq, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Encode))]
pub struct IncomingMessage {
/// The source parachain.
pub source: Id,
/// The data of the message.
pub data: Vec<u8>,
}
/// A message targeted to a specific parachain.
#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime_interface::pass_by::PassByCodec)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct TargetedMessage {
/// The target parachain.
pub target: Id,
/// The message data.
pub data: Vec<u8>,
}
impl AsRef<[u8]> for TargetedMessage {
fn as_ref(&self) -> &[u8] {
&self.data[..]
}
}
impl PartialOrd for TargetedMessage {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.target.cmp(&other.target))
}
}
impl Ord for TargetedMessage {
fn cmp(&self, other: &Self) -> Ordering {
self.target.cmp(&other.target)
}
}
......@@ -16,13 +16,31 @@
//! Utilities for writing parachain WASM.
use codec::{Encode, Decode};
use super::{ValidationParams, ValidationResult, MessageRef, UpwardMessageRef};
use crate::{TargetedMessage, UpwardMessage};
use sp_runtime_interface::runtime_interface;
#[cfg(feature = "std")]
use sp_externalities::ExternalitiesExt;
/// The parachain api for posting messages.
// Either activate on `std` to get access to the `HostFunctions` or when `wasm-api` is given and on
// `no_std`.
#[cfg(any(feature = "std", all(not(feature = "std"), feature = "wasm-api")))]
#[runtime_interface]
pub trait Parachain {
/// Post a message to another parachain.
fn post_message(&mut self, msg: TargetedMessage) {
self.extension::<crate::wasm_executor::ParachainExt>()
.expect("No `ParachainExt` associated with the current context.")
.post_message(msg)
.expect("Failed to post message")
}
mod ll {
extern "C" {
pub(super) fn ext_post_message(target: u32, data_ptr: *const u8, data_len: u32);
pub(super) fn ext_post_upward_message(origin: u32, data_ptr: *const u8, data_len: u32);
/// Post a message to this parachain's relay chain.
fn post_upward_message(&mut self, msg: UpwardMessage) {
self.extension::<crate::wasm_executor::ParachainExt>()
.expect("No `ParachainExt` associated with the current context.")
.post_upward_message(msg)
.expect("Failed to post upward message")
}
}
......@@ -30,43 +48,18 @@ mod ll {
///
/// Offset and length must have been provided by the validation
/// function's entry point.
pub unsafe fn load_params(params: *const u8, len: usize) -> ValidationParams {
#[cfg(not(feature = "std"))]
pub unsafe fn load_params(params: *const u8, len: usize) -> crate::ValidationParams {
let mut slice = rstd::slice::from_raw_parts(params, len);
ValidationParams::decode(&mut slice).expect("Invalid input data")
codec::Decode::decode(&mut slice).expect("Invalid input data")
}
/// Allocate the validation result in memory, getting the return-pointer back.
///
/// As described in the crate docs, this is a pointer to the appended length
/// of the vector.
pub fn write_result(result: ValidationResult) -> usize {
let mut encoded = result.encode();
let len = encoded.len();
assert!(len <= u32::max_value() as usize, "Len too large for parachain-WASM abi");
(len as u32).using_encoded(|s| encoded.extend(s));
// do not alter `encoded` beyond this point. may reallocate.
let end_ptr = &encoded[len] as *const u8 as usize;
// leak so it doesn't get zeroed.
rstd::mem::forget(encoded);
end_ptr
}
/// Post a message to another parachain.
pub fn post_message(message: MessageRef) {
let data_ptr = message.data.as_ptr();
let data_len = message.data.len();
unsafe { ll::ext_post_message(message.target.into(), data_ptr, data_len as u32) }
}
/// Post a message to this parachain's relay chain.
pub fn post_upward_message(message: UpwardMessageRef) {
let data_ptr = message.data.as_ptr();
let data_len = message.data.len();
unsafe { ll::ext_post_upward_message(u32::from(message.origin as u8), data_ptr, data_len as u32) }
#[cfg(not(feature = "std"))]
pub fn write_result(result: &crate::ValidationResult) -> u64 {
sp_core::to_substrate_wasm_fn_return_value(&result)
}
......@@ -20,16 +20,10 @@
//! Assuming the parameters are correct, this module provides a wrapper around
//! a WASM VM for re-execution of a parachain candidate.
use std::{cell::RefCell, fmt, convert::TryInto};
use crate::codec::{Decode, Encode};
use wasmi::{
self, Module, ModuleInstance, Trap, MemoryInstance, MemoryDescriptor, MemoryRef,
ModuleImportResolver, RuntimeValue, Externals, Error as WasmError, ValueType,
memory_units::{self, Bytes, Pages, RoundUpTo}
};
use super::{
ValidationParams, ValidationResult, MessageRef, UpwardMessageRef,
UpwardMessage, IncomingMessage};
use std::any::{TypeId, Any};
use crate::{ValidationParams, ValidationResult, UpwardMessage, TargetedMessage};
use codec::{Decode, Encode};
use sp_core::storage::{ChildStorageKey, ChildInfo};
#[cfg(not(target_os = "unknown"))]
pub use validation_host::{run_worker, EXECUTION_TIMEOUT_SEC};
......@@ -40,12 +34,16 @@ mod validation_host;
const MAX_RUNTIME_MEM: usize = 1024 * 1024 * 1024; // 1 GiB
const MAX_CODE_MEM: usize = 16 * 1024 * 1024; // 16 MiB
mod ids {
/// Post a message to another parachain.
pub const POST_MESSAGE: usize = 1;
sp_externalities::decl_extension! {
/// The extension that is registered at the `Externalities` when validating a parachain state
/// transition.
pub(crate) struct ParachainExt(Box<dyn Externalities>);
}
/// Post a message to this parachain's relay chain.
pub const POST_UPWARD_MESSAGE: usize = 2;
impl ParachainExt {
pub fn new<T: Externalities + 'static>(ext: T) -> Self {
Self(Box::new(ext))
}
}
/// WASM code execution mode.
......@@ -63,16 +61,16 @@ pub enum ExecutionMode {
/// Error type for the wasm executor
#[derive(Debug, derive_more::Display, derive_more::From)]
pub enum Error {
/// Wasm error
Wasm(WasmError),
/// Externalities error
Externalities(ExternalitiesError),
/// Code size it too large.
#[display(fmt = "WASM code is {} bytes, max allowed is {}", _0, MAX_CODE_MEM)]
CodeTooLarge(usize),
/// Wasm executor error.
#[display(fmt = "WASM executor error: {:?}", _0)]
WasmExecutor(sc_executor::error::Error),
/// Call data is too large.
#[display(fmt = "Validation parameters are {} bytes, max allowed is {}", _0, MAX_RUNTIME_MEM)]
#[from(ignore)]
ParamsTooLarge(usize),
/// Code size it too large.
#[display(fmt = "WASM code is {} bytes, max allowed is {}", _0, MAX_CODE_MEM)]
CodeTooLarge(usize),
/// Bad return data or type.
#[display(fmt = "Validation function returned invalid data.")]
BadReturn,
......@@ -84,372 +82,177 @@ pub enum Error {
System(Box<dyn std::error::Error>),
#[display(fmt = "WASM worker error: {}", _0)]
External(String),
#[display(fmt = "Shared memory error: {}", _0)]
#[cfg(not(target_os = "unknown"))]
SharedMem(shared_memory::SharedMemError),
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Wasm(ref err) => Some(err),
Error::Externalities(ref err) => Some(err),
Error::WasmExecutor(ref err) => Some(err),
Error::Io(ref err) => Some(err),
Error::System(ref err) => Some(&**err),
#[cfg(not(target_os = "unknown"))]
Error::SharedMem(ref err) => Some(err),
_ => None,
}
}
}
/// Errors that can occur in externalities of parachain validation.
#[derive(Debug, Clone)]
pub enum ExternalitiesError {
/// Unable to post a message due to the given reason.
CannotPostMessage(&'static str),
}
/// Externalities for parachain validation.
pub trait Externalities {
pub trait Externalities: Send {
/// Called when a message is to be posted to another parachain.
fn post_message(&mut self, message: MessageRef) -> Result<(), ExternalitiesError>;
fn post_message(&mut self, message: TargetedMessage) -> Result<(), String>;
/// Called when a message is to be posted to the parachain's relay chain.
fn post_upward_message(&mut self, message: UpwardMessageRef) -> Result<(), ExternalitiesError>;
fn post_upward_message(&mut self, message: UpwardMessage) -> Result<(), String>;
}
impl fmt::Display for ExternalitiesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ExternalitiesError::CannotPostMessage(ref s)
=> write!(f, "Cannot post message: {}", s),
}
/// Validate a candidate under the given validation code.
///
/// This will fail if the validation code is not a proper parachain validation module.
pub fn validate_candidate<E: Externalities + 'static>(
validation_code: &[u8],
params: ValidationParams,
ext: E,
options: ExecutionMode,
) -> Result<ValidationResult, Error> {
match options {
ExecutionMode::Local => {
validate_candidate_internal(validation_code, &params.encode(), ext)
},
#[cfg(not(target_os = "unknown"))]
ExecutionMode::Remote => {
validation_host::validate_candidate(validation_code, params, ext, false)
},
#[cfg(not(target_os = "unknown"))]
ExecutionMode::RemoteTest => {
validation_host::validate_candidate(validation_code, params, ext, true)
},
#[cfg(target_os = "unknown")]
ExecutionMode::Remote =>
Err(Error::System("Remote validator not available".to_string().into())),
#[cfg(target_os = "unknown")]
ExecutionMode::RemoteTest =>
Err(Error::System("Remote validator not available".to_string().into())),
}
}
impl wasmi::HostError for ExternalitiesError {}
impl std::error::Error for ExternalitiesError {}
/// The host functions provided by the wasm executor to the parachain wasm blob.