mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 00:31:02 +00:00
Adding Bridges code as git subtree. (#2515)
* Add instructions. * Squashed 'bridges/' content from commit 345e84a21 git-subtree-dir: bridges git-subtree-split: 345e84a2146b56628e9888c9f5e129cb40e868a9 * Remove bridges workspace file to avoid confusing Cargo. * Add some bridges primitives to Polkadot workspace. * Improve docs.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
name = "pallet-message-lane-rpc"
|
||||
description = "Module that provides RPC methods specific to message-lane pallet."
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
derive_more = "0.99.2"
|
||||
futures = { version = "0.3.5", features = ["compat"] }
|
||||
jsonrpc-core = "15.1.0"
|
||||
jsonrpc-core-client = "15.1.0"
|
||||
jsonrpc-derive = "15.1.0"
|
||||
log = "0.4.11"
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-runtime = { path = "../../../primitives/runtime" }
|
||||
bp-message-lane = { path = "../../../primitives/message-lane" }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Possible errors and results of message-lane RPC calls.
|
||||
|
||||
/// Future Result type.
|
||||
pub type FutureResult<T> = jsonrpc_core::BoxFuture<T>;
|
||||
|
||||
/// State RPC errors.
|
||||
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||
pub enum Error {
|
||||
/// When unknown instance id is passed.
|
||||
#[display(fmt = "Message lane instance is unknown")]
|
||||
UnknownInstance,
|
||||
/// Client error.
|
||||
#[display(fmt = "Client error: {}", _0)]
|
||||
Client(Box<dyn std::error::Error + Send>),
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Error::UnknownInstance => None,
|
||||
Error::Client(ref err) => Some(&**err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for jsonrpc_core::Error {
|
||||
fn from(e: Error) -> Self {
|
||||
const UNKNOW_INSTANCE_CODE: i64 = 1;
|
||||
|
||||
match e {
|
||||
Error::UnknownInstance => jsonrpc_core::Error {
|
||||
code: jsonrpc_core::ErrorCode::ServerError(UNKNOW_INSTANCE_CODE),
|
||||
message: "Unknown instance passed".into(),
|
||||
data: None,
|
||||
},
|
||||
Error::Client(e) => jsonrpc_core::Error {
|
||||
code: jsonrpc_core::ErrorCode::InternalError,
|
||||
message: format!("Unknown error occured: {}", e),
|
||||
data: Some(format!("{:?}", e).into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Module that provides RPC methods specific to message-lane pallet.
|
||||
|
||||
use crate::error::{Error, FutureResult};
|
||||
|
||||
use bp_message_lane::{LaneId, MessageNonce};
|
||||
use bp_runtime::InstanceId;
|
||||
use futures::{FutureExt, TryFutureExt};
|
||||
use jsonrpc_core::futures::Future as _;
|
||||
use jsonrpc_derive::rpc;
|
||||
use sc_client_api::Backend as BackendT;
|
||||
use sp_blockchain::{Error as BlockchainError, HeaderBackend};
|
||||
use sp_core::{storage::StorageKey, Bytes};
|
||||
use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT};
|
||||
use sp_state_machine::prove_read;
|
||||
use sp_trie::StorageProof;
|
||||
use std::sync::Arc;
|
||||
|
||||
mod error;
|
||||
|
||||
/// Trie-based storage proof that the message(s) with given key(s) have been sent by the bridged chain.
|
||||
/// SCALE-encoded trie nodes array `Vec<Vec<u8>>`.
|
||||
pub type MessagesProof = Bytes;
|
||||
|
||||
/// Trie-based storage proof that the message(s) with given key(s) have been received by the bridged chain.
|
||||
/// SCALE-encoded trie nodes array `Vec<Vec<u8>>`.
|
||||
pub type MessagesDeliveryProof = Bytes;
|
||||
|
||||
/// Runtime adapter.
|
||||
pub trait Runtime: Send + Sync + 'static {
|
||||
/// Return runtime storage key for given message. May return None if instance is unknown.
|
||||
fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option<StorageKey>;
|
||||
/// Return runtime storage key for outbound lane state. May return None if instance is unknown.
|
||||
fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option<StorageKey>;
|
||||
/// Return runtime storage key for inbound lane state. May return None if instance is unknown.
|
||||
fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option<StorageKey>;
|
||||
}
|
||||
|
||||
/// Provides RPC methods for interacting with message-lane pallet.
|
||||
#[rpc]
|
||||
pub trait MessageLaneApi<BlockHash> {
|
||||
/// Returns storage proof of messages in given inclusive range. The state of outbound
|
||||
/// lane is included in the proof if `include_outbound_lane_state` is true.
|
||||
#[rpc(name = "messageLane_proveMessages")]
|
||||
fn prove_messages(
|
||||
&self,
|
||||
instance: InstanceId,
|
||||
lane: LaneId,
|
||||
begin: MessageNonce,
|
||||
end: MessageNonce,
|
||||
include_outbound_lane_state: bool,
|
||||
block: Option<BlockHash>,
|
||||
) -> FutureResult<MessagesProof>;
|
||||
|
||||
/// Returns proof-of-message(s) delivery.
|
||||
#[rpc(name = "messageLane_proveMessagesDelivery")]
|
||||
fn prove_messages_delivery(
|
||||
&self,
|
||||
instance: InstanceId,
|
||||
lane: LaneId,
|
||||
block: Option<BlockHash>,
|
||||
) -> FutureResult<MessagesDeliveryProof>;
|
||||
}
|
||||
|
||||
/// Implements the MessageLaneApi trait for interacting with message lanes.
|
||||
pub struct MessageLaneRpcHandler<Block, Backend, R> {
|
||||
backend: Arc<Backend>,
|
||||
runtime: Arc<R>,
|
||||
_phantom: std::marker::PhantomData<Block>,
|
||||
}
|
||||
|
||||
impl<Block, Backend, R> MessageLaneRpcHandler<Block, Backend, R> {
|
||||
/// Creates new mesage lane RPC handler.
|
||||
pub fn new(backend: Arc<Backend>, runtime: Arc<R>) -> Self {
|
||||
Self {
|
||||
backend,
|
||||
runtime,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, Backend, R> MessageLaneApi<Block::Hash> for MessageLaneRpcHandler<Block, Backend, R>
|
||||
where
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block> + 'static,
|
||||
R: Runtime,
|
||||
{
|
||||
fn prove_messages(
|
||||
&self,
|
||||
instance: InstanceId,
|
||||
lane: LaneId,
|
||||
begin: MessageNonce,
|
||||
end: MessageNonce,
|
||||
include_outbound_lane_state: bool,
|
||||
block: Option<Block::Hash>,
|
||||
) -> FutureResult<MessagesProof> {
|
||||
let runtime = self.runtime.clone();
|
||||
let outbound_lane_data_key = if include_outbound_lane_state {
|
||||
Some(runtime.outbound_lane_data_key(&instance, &lane))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let messages_count = if end >= begin { end - begin + 1 } else { 0 };
|
||||
Box::new(
|
||||
prove_keys_read(
|
||||
self.backend.clone(),
|
||||
block,
|
||||
(begin..=end)
|
||||
.map(move |nonce| runtime.message_key(&instance, &lane, nonce))
|
||||
.chain(outbound_lane_data_key.into_iter()),
|
||||
)
|
||||
.boxed()
|
||||
.compat()
|
||||
.map(move |proof| {
|
||||
let serialized_proof = serialize_storage_proof(proof);
|
||||
log::trace!(
|
||||
"Generated proof of {} messages. Size: {}",
|
||||
messages_count,
|
||||
serialized_proof.len()
|
||||
);
|
||||
serialized_proof
|
||||
})
|
||||
.map_err(Into::into),
|
||||
)
|
||||
}
|
||||
|
||||
fn prove_messages_delivery(
|
||||
&self,
|
||||
instance: InstanceId,
|
||||
lane: LaneId,
|
||||
block: Option<Block::Hash>,
|
||||
) -> FutureResult<MessagesDeliveryProof> {
|
||||
Box::new(
|
||||
prove_keys_read(
|
||||
self.backend.clone(),
|
||||
block,
|
||||
vec![self.runtime.inbound_lane_data_key(&instance, &lane)],
|
||||
)
|
||||
.boxed()
|
||||
.compat()
|
||||
.map(|proof| {
|
||||
let serialized_proof = serialize_storage_proof(proof);
|
||||
log::trace!("Generated message delivery proof. Size: {}", serialized_proof.len());
|
||||
serialized_proof
|
||||
})
|
||||
.map_err(Into::into),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async fn prove_keys_read<Block, Backend>(
|
||||
backend: Arc<Backend>,
|
||||
block: Option<Block::Hash>,
|
||||
keys: impl IntoIterator<Item = Option<StorageKey>>,
|
||||
) -> Result<StorageProof, Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block> + 'static,
|
||||
{
|
||||
let block = unwrap_or_best(&*backend, block);
|
||||
let state = backend.state_at(BlockId::Hash(block)).map_err(blockchain_err)?;
|
||||
let keys = keys
|
||||
.into_iter()
|
||||
.map(|key| key.ok_or(Error::UnknownInstance).map(|key| key.0))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let storage_proof = prove_read(state, keys)
|
||||
.map_err(BlockchainError::Execution)
|
||||
.map_err(blockchain_err)?;
|
||||
Ok(storage_proof)
|
||||
}
|
||||
|
||||
fn serialize_storage_proof(proof: StorageProof) -> Bytes {
|
||||
let raw_nodes: Vec<Vec<_>> = proof.iter_nodes().map(Into::into).collect();
|
||||
raw_nodes.encode().into()
|
||||
}
|
||||
|
||||
fn unwrap_or_best<Block: BlockT>(backend: &impl BackendT<Block>, block: Option<Block::Hash>) -> Block::Hash {
|
||||
match block {
|
||||
Some(block) => block,
|
||||
None => backend.blockchain().info().best_hash,
|
||||
}
|
||||
}
|
||||
|
||||
fn blockchain_err(err: BlockchainError) -> Error {
|
||||
Error::Client(Box::new(err))
|
||||
}
|
||||
Reference in New Issue
Block a user