mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 17:31:03 +00:00
Allow parachains to send messages (#274)
* Slots module * Integrate slots * More drafting * Minor updates * Update parachains to use trati * More build fixes * Full code now compiles * Add renew bid function * Implement calculate_winner * Warning remove * Update gitignore * Test framework * Tests * Further testing * More tests, new parameterisation. * Fix and new test * Thread-safe tests * Test off-boarding and a fix. * Test onboarding * Allow late onboarding. * Another test and fix * Avoid println in nostd * Compact representation of paraids * Introduce documentation. * Introduce events. * Additional test and fix * Additional test * Tidy up line lengths. * Remove printlns * Use later substrate utils. * Allow parachains to send messages. * Fix build/test * Make slots work with latest substrate * Update runtime/src/slot_range.rs Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * Update runtime/src/slots.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Update runtime/src/slots.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Polish logic * Rewind to earlier substrate master * Remove dead code. * Fix build * Update substrate ref to master * Update to new inherent digests API * address grumbles * fix * Fix a warning. * Reworded a comment. * Check that receipt matches expectations * Add test for final checks * Split out queuing logic. * Test final piece of queuing logic * Fix up docs. * More docs fixes
This commit is contained in:
@@ -197,3 +197,37 @@ pub struct MessageRef<'a> {
|
||||
/// 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))]
|
||||
#[repr(u8)]
|
||||
pub enum ParachainDispatchOrigin {
|
||||
/// As a simple `Origin::Signed`, using `ParaId::account_id` as its value. This is good when
|
||||
/// interacting with standard modules such as `balances`.
|
||||
Signed,
|
||||
/// As the special `Origin::Parachain(ParaId)`. This is good when interacting with parachain-
|
||||
/// aware modules which need to succinctly verify that the origin is a parachain.
|
||||
Parachain,
|
||||
}
|
||||
|
||||
impl core::convert::TryFrom<u8> for ParachainDispatchOrigin {
|
||||
type Error = ();
|
||||
fn try_from(x: u8) -> core::result::Result<ParachainDispatchOrigin, ()> {
|
||||
const SIGNED: u8 = ParachainDispatchOrigin::Signed as u8;
|
||||
const PARACHAIN: u8 = ParachainDispatchOrigin::Parachain as u8;
|
||||
Ok(match x {
|
||||
SIGNED => ParachainDispatchOrigin::Signed,
|
||||
PARACHAIN => ParachainDispatchOrigin::Parachain,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 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],
|
||||
}
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
//! Utilities for writing parachain WASM.
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use super::{ValidationParams, ValidationResult, MessageRef};
|
||||
use super::{
|
||||
ValidationParams, ValidationResult, MessageRef, UpwardMessageRef, ParachainDispatchOrigin
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,3 +64,11 @@ pub fn post_message(message: MessageRef) {
|
||||
|
||||
unsafe { ll::ext_post_message(message.target.into_inner(), 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.as_ptr();
|
||||
let data_len = message.len();
|
||||
|
||||
unsafe { ll::ext_post_upward_message(message.origin as u8 as u32, data_ptr, data_len as u32) }
|
||||
}
|
||||
|
||||
@@ -20,20 +20,21 @@
|
||||
//! 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 codec::{Decode, Encode};
|
||||
|
||||
use wasmi::{self, Module, ModuleInstance, Trap, MemoryInstance, MemoryDescriptor, MemoryRef, ModuleImportResolver};
|
||||
use wasmi::{memory_units, RuntimeValue, Externals, Error as WasmError, ValueType};
|
||||
use wasmi::memory_units::{Bytes, Pages, RoundUpTo};
|
||||
|
||||
use super::{ValidationParams, ValidationResult, MessageRef};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
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};
|
||||
|
||||
mod ids {
|
||||
/// Post a message to another parachain.
|
||||
pub const POST_MESSAGE: usize = 1;
|
||||
|
||||
/// Post a message to this parachain's relay chain.
|
||||
pub const POST_UPWARDS_MESSAGE: usize = 2;
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
@@ -67,6 +68,9 @@ pub enum ExternalitiesError {
|
||||
pub trait Externalities {
|
||||
/// Called when a message is to be posted to another parachain.
|
||||
fn post_message(&mut self, message: MessageRef) -> Result<(), ExternalitiesError>;
|
||||
|
||||
/// Called when a message is to be posted to the parachain's relay chain.
|
||||
fn post_upward_message(&mut self, message: UpwardMessageRef) -> Result<(), ExternalitiesError>;
|
||||
}
|
||||
|
||||
impl fmt::Display for ExternalitiesError {
|
||||
@@ -96,7 +100,23 @@ impl ModuleImportResolver for Resolver {
|
||||
"ext_post_message" => {
|
||||
let index = ids::POST_MESSAGE;
|
||||
let (params, ret_ty): (&[ValueType], Option<ValueType>) =
|
||||
(&[ValueType::I32, ValueType::I32, ValueType::I32], None);
|
||||
(&[ValueType::I32, ValueType::I32, ValueType::I32], None);
|
||||
|
||||
if signature.params() != params && signature.return_type() != ret_ty {
|
||||
Err(WasmError::Instantiation(
|
||||
format!("Export {} has a bad signature", field_name)
|
||||
))
|
||||
} else {
|
||||
Ok(wasmi::FuncInstance::alloc_host(
|
||||
wasmi::Signature::new(¶ms[..], ret_ty),
|
||||
index,
|
||||
))
|
||||
}
|
||||
}
|
||||
"ext_upwards_post_message" => {
|
||||
let index = ids::POST_UPWARDS_MESSAGE;
|
||||
let (params, ret_ty): (&[ValueType], Option<ValueType>) =
|
||||
(&[ValueType::I32, ValueType::I32], None);
|
||||
|
||||
if signature.params() != params && signature.return_type() != ret_ty {
|
||||
Err(WasmError::Instantiation(
|
||||
@@ -172,6 +192,31 @@ impl<'a, E: 'a + Externalities> ValidationExternals<'a, E> {
|
||||
}
|
||||
})
|
||||
}
|
||||
/// Signature: post_upward_message(u32, *const u8, u32) -> None
|
||||
/// usage: post_upward_message(origin, data ptr, data len).
|
||||
/// Origin is the integer representation of the dispatch origin.
|
||||
/// Data is the raw data of the message.
|
||||
fn ext_post_upward_message(&mut self, args: ::wasmi::RuntimeArgs) -> Result<(), Trap> {
|
||||
let origin: u32 = args.nth_checked(0)?;
|
||||
let data_ptr: u32 = args.nth_checked(1)?;
|
||||
let data_len: u32 = args.nth_checked(2)?;
|
||||
|
||||
let (data_ptr, data_len) = (data_ptr as usize, data_len as usize);
|
||||
|
||||
self.memory.with_direct_access(|mem| {
|
||||
if mem.len() < (data_ptr + data_len) {
|
||||
Err(Trap::new(wasmi::TrapKind::MemoryAccessOutOfBounds))
|
||||
} else {
|
||||
let origin = (origin as u8).try_into()
|
||||
.map_err(|_| Trap::new(wasmi::TrapKind::UnexpectedSignature))?;
|
||||
let message = UpwardMessageRef { origin, data: &mem[data_ptr..][..data_len] };
|
||||
let res = self.externalities.post_upward_message(message);
|
||||
res.map_err(|e| Trap::new(wasmi::TrapKind::Host(
|
||||
Box::new(e) as Box<_>
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: 'a + Externalities> Externals for ValidationExternals<'a, E> {
|
||||
@@ -182,6 +227,7 @@ impl<'a, E: 'a + Externalities> Externals for ValidationExternals<'a, E> {
|
||||
) -> Result<Option<RuntimeValue>, Trap> {
|
||||
match index {
|
||||
ids::POST_MESSAGE => self.ext_post_message(args).map(|_| None),
|
||||
ids::POST_UPWARDS_MESSAGE => self.ext_post_upward_message(args).map(|_| None),
|
||||
_ => panic!("no externality at given index"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user