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: Robert Habermeier <rphmeier@gmail.com>

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
Bastian Köcher
2020-01-08 20:44:50 +01:00
committed by GitHub
parent 10f1f3a381
commit 06386558ae
16 changed files with 468 additions and 609 deletions
+76 -48
View File
@@ -21,17 +21,23 @@
use std::sync::Arc;
use polkadot_primitives::{BlakeTwo256, Block, Hash, HashT, BlockId, Balance, parachain::{
CollatorId, ConsolidatedIngress, StructuredUnroutedIngress, CandidateReceipt, CollationInfo, ParachainHost,
Id as ParaId, Collation, TargetedMessage, OutgoingMessages, UpwardMessage, FeeSchedule, ErasureChunk,
HeadData, PoVBlock,
}};
use polkadot_erasure_coding::{self as erasure};
use polkadot_primitives::{
BlakeTwo256, Block, Hash, HashT, BlockId, Balance,
parachain::{
CollatorId, ConsolidatedIngress, StructuredUnroutedIngress, CandidateReceipt, CollationInfo,
ParachainHost, Id as ParaId, Collation, OutgoingMessages, FeeSchedule, ErasureChunk,
HeadData, PoVBlock,
},
};
use polkadot_erasure_coding as erasure;
use runtime_primitives::traits::ProvideRuntimeApi;
use parachain::{wasm_executor::{self, ExternalitiesError, ExecutionMode}, MessageRef, UpwardMessageRef};
use parachain::{
wasm_executor::{self, ExecutionMode}, TargetedMessage, UpwardMessage,
};
use trie::TrieConfiguration;
use futures::prelude::*;
use log::debug;
use parking_lot::Mutex;
/// Encapsulates connections to collators and allows collation on any parachain.
///
@@ -239,7 +245,7 @@ fn check_egress(
Ok(OutgoingMessages { outgoing_messages: outgoing })
}
struct Externalities {
struct ExternalitiesInner {
parachain_index: ParaId,
outgoing: Vec<TargetedMessage>,
upward: Vec<UpwardMessage>,
@@ -248,41 +254,44 @@ struct Externalities {
fee_schedule: FeeSchedule,
}
impl wasm_executor::Externalities for Externalities {
fn post_message(&mut self, message: MessageRef) -> Result<(), ExternalitiesError> {
let target: ParaId = message.target.into();
if target == self.parachain_index {
return Err(ExternalitiesError::CannotPostMessage("posted message to self"));
impl wasm_executor::Externalities for ExternalitiesInner {
fn post_message(&mut self, message: TargetedMessage) -> Result<(), String> {
if message.target == self.parachain_index {
return Err("posted message to self".into())
}
self.apply_message_fee(message.data.len())?;
self.outgoing.push(TargetedMessage {
target,
data: message.data.to_vec(),
});
self.outgoing.push(message);
Ok(())
}
fn post_upward_message(&mut self, message: UpwardMessageRef)
-> Result<(), ExternalitiesError>
{
fn post_upward_message(&mut self, message: UpwardMessage) -> Result<(), String> {
self.apply_message_fee(message.data.len())?;
self.upward.push(UpwardMessage {
origin: message.origin,
data: message.data.to_vec(),
});
self.upward.push(message);
Ok(())
}
}
impl Externalities {
fn apply_message_fee(&mut self, message_len: usize) -> Result<(), ExternalitiesError> {
impl ExternalitiesInner {
fn new(parachain_index: ParaId, free_balance: Balance, fee_schedule: FeeSchedule) -> Self {
Self {
parachain_index,
free_balance,
fee_schedule,
fees_charged: 0,
upward: Vec::new(),
outgoing: Vec::new(),
}
}
fn apply_message_fee(&mut self, message_len: usize) -> Result<(), String> {
let fee = self.fee_schedule.compute_fee(message_len);
let new_fees_charged = self.fees_charged.saturating_add(fee);
if new_fees_charged > self.free_balance {
Err(ExternalitiesError::CannotPostMessage("could not cover fee."))
Err("could not cover fee.".into())
} else {
self.fees_charged = new_fees_charged;
Ok(())
@@ -291,7 +300,7 @@ impl Externalities {
// Performs final checks of validity, producing the outgoing message data.
fn final_checks(
self,
&mut self,
upward_messages: &[UpwardMessage],
egress_queue_roots: &[(ParaId, Hash)],
fees_charged: Option<Balance>,
@@ -313,7 +322,7 @@ impl Externalities {
}
let messages = check_egress(
self.outgoing,
std::mem::replace(&mut self.outgoing, Vec::new()),
&egress_queue_roots[..],
)?;
@@ -321,6 +330,27 @@ impl Externalities {
}
}
#[derive(Clone)]
struct Externalities(Arc<Mutex<ExternalitiesInner>>);
impl Externalities {
fn new(parachain_index: ParaId, free_balance: Balance, fee_schedule: FeeSchedule) -> Self {
Self(Arc::new(Mutex::new(
ExternalitiesInner::new(parachain_index, free_balance, fee_schedule)
)))
}
}
impl wasm_executor::Externalities for Externalities {
fn post_message(&mut self, message: TargetedMessage) -> Result<(), String> {
self.0.lock().post_message(message)
}
fn post_upward_message(&mut self, message: UpwardMessage) -> Result<(), String> {
self.0.lock().post_upward_message(message)
}
}
/// Validate an erasure chunk against an expected root.
pub fn validate_chunk(
root: &Hash,
@@ -425,19 +455,17 @@ fn do_validation<P>(
.collect()
};
let mut ext = Externalities {
parachain_index: para_id.clone(),
outgoing: Vec::new(),
upward: Vec::new(),
free_balance: chain_status.balance,
fee_schedule: chain_status.fee_schedule,
fees_charged: 0,
};
let ext = Externalities::new(para_id.clone(), chain_status.balance, chain_status.fee_schedule);
match wasm_executor::validate_candidate(&validation_code, params, &mut ext, ExecutionMode::Remote) {
match wasm_executor::validate_candidate(
&validation_code,
params,
ext.clone(),
ExecutionMode::Remote,
) {
Ok(result) => {
if result.head_data == head_data.0 {
let (messages, fees) = ext.final_checks(
let (messages, fees) = ext.0.lock().final_checks(
upward_messages,
queue_roots,
fees_charged
@@ -634,7 +662,7 @@ mod tests {
#[test]
fn ext_rejects_local_message() {
let mut ext = Externalities {
let mut ext = ExternalitiesInner {
parachain_index: 5.into(),
outgoing: Vec::new(),
upward: Vec::new(),
@@ -646,13 +674,13 @@ mod tests {
},
};
assert!(ext.post_message(MessageRef { target: 1.into(), data: &[] }).is_ok());
assert!(ext.post_message(MessageRef { target: 5.into(), data: &[] }).is_err());
assert!(ext.post_message(TargetedMessage { target: 1.into(), data: Vec::new() }).is_ok());
assert!(ext.post_message(TargetedMessage { target: 5.into(), data: Vec::new() }).is_err());
}
#[test]
fn ext_checks_upward_messages() {
let ext = || Externalities {
let ext = || ExternalitiesInner {
parachain_index: 5.into(),
outgoing: Vec::new(),
upward: vec![
@@ -742,7 +770,7 @@ mod tests {
#[test]
fn ext_checks_fees_and_updates_correctly() {
let mut ext = Externalities {
let mut ext = ExternalitiesInner {
parachain_index: 5.into(),
outgoing: Vec::new(),
upward: vec![
@@ -759,15 +787,15 @@ mod tests {
ext.apply_message_fee(100).unwrap();
assert_eq!(ext.fees_charged, 2000);
ext.post_message(MessageRef {
ext.post_message(TargetedMessage {
target: 1.into(),
data: &[0u8; 100],
data: vec![0u8; 100],
}).unwrap();
assert_eq!(ext.fees_charged, 4000);
ext.post_upward_message(UpwardMessageRef {
ext.post_upward_message(UpwardMessage {
origin: ParachainDispatchOrigin::Signed,
data: &[0u8; 100],
data: vec![0u8; 100],
}).unwrap();
assert_eq!(ext.fees_charged, 6000);