mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 15:11:02 +00:00
Squashed 'bridges/' changes from 23dda62482..407bf44a8a
407bf44a8a add missing license header (#1204) 9babb19810 Custom relay strategy (#1198) c287872a11 fix clippy things (#1200) 3a40e62789 Expose some const value and type (#1186) 32b61476d1 increase sleep before connectingMillau (#1195) aabe7041fa revert messages transactions mortality (#1194) 3651f4f909 Message transactions mortality (#1191) 364d6e155d Bump dependencies (#1180) f0389acc08 cargo +nightly fmt --all (#1192) b270b6a016 Unify error enums in substrate and ethereum clients with `thiserror` (#1094) 58c4946f74 Limit max call size of Rialto/Millau runtimes (#1187) fd56a8cd56 Add UI to the deployment (#1047) 16f01dc736 Westend -> Millau alerts are pending before notifications are sent (#1184) 5628c11ece replace collective flip with babe randomness in Rialto (#1188) 1094a63b00 ignore another (pretty bad) RUSTSEC (#1185) 379fe323ea fix/ignore cargo deny issues (#1183) 92af5e6e64 additional log in finality relay + rephrase "failed" (#1182) b996a3b681 Rialto parachain in test deployments (#1178) 28d9332b44 Resubmit transactions strategy for Polkadot/Kusama (#1175) d0172c6847 Playing with CI (#1179) fb6f42456d fix checks order when registering parachain (#1177) ee828c005a Register-parachain subcommand of substrate-relay (#1170) 8cd2b1a112 Token swap pallet benchmarks (#1174) bb811accb1 fix collision with westend bridge (#1172) 8d2fba70ed add token swaps to test deployments (#1169) b6d1bdfe2c publish rialto parachain collator image (#1171) 834ae4a10a Fix OutboundLaneData types (#1159) 5ee0ea1626 copypasted -> copied (#1168) c3bb835f18 fix spelling (#1167) f90d041dc9 Upgrade `jsonrpsee` to v0.3 (#1051) 598c9b6d0d add some basic tests for swap tokens (#1164) 05e88c61f5 publish images when tag of specific format(e.g. v2021-09-27 + v2021-09-27-1) is published (#1166) 7f3f94a6e0 Fix CI again (#1165) ff37de332f Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153) 36fbba839b fix clippy warning (#1163) 16da44d018 explicit wasm build (#1158) c9c8226449 Match substrate's fmt (#1148) 2fdd7f3e5e Fix/ignore clippy warnings (#1157) 43dfcc2686 Adding LookupAddress (#1156) 951eaa5582 Add rialto-parachain runtime and node (#1142) 803d266d61 Rename MessageId -> BridgeMessageId (#1152) 5f234484fc Box large arguments of GRANDPA pallet (#1154) cf9abc1011 Fix spelling (#1150) ab83ba2e58 Relay subcommand that performs token RLT <> MLAU token swap (#1141) 832536caf0 Polkadot <> Kusama relayers (#1122) 6d0daa8975 Add `OnMessageAccepted` callback (#1134) 5d03a20b3e Integrate token swap pallet into Millau runtime (#1099) ea4cfa833e Adding MultiAddress type and ValidationCodeHash (#1139) c20325a784 Add tests for `Raw` and `BridgeSendMessage` enum `Call` variants (#1125) 6d802416e2 increase pause before pining Rialto nodes (#1137) b54fa56b62 calculate fee using full message payload (#1132) ca5d8178f5 Add parachain pallets to rialto runtime (#1053) 9eaae4142e fix transaction resubmitter limits for Millau -> Rialto transactions (#1135) 9d4e17783c add --mandatory-headers-only cli option to complex relay (#1129) 1c5e0ec1cb Add local CI info to README (#1131) a8e0929e14 chore: spellchecker fixes (#1130) 3b8e2118e3 set fee for importing mandatory headers to zero (#1127) 49bba9aa52 another bunch of words for spellchecker (#1128) 8a72eafef6 Increase pause before messages generation start (#1126) 1f0ba9a191 Move some associated types from relay_substrate_client::Chain to bp_runtime::Chain (#1087) 74bc1a5b54 Transactions resubmitter (#1083) 21ba001f26 log max balance drop when sending message (#1117) 638a7ddffa Code Cleaning (#1124) be6555c51b Fix buildah logout (#1120) 87539c4a98 Format code work (#1116) 526fe7fdd7 fix spelling (#1119) bd4ce7f241 Fix spelling (#1118) 3c1147858e added missing constants to Kusama/Polkadot primitives (#1114) 52093b22ab Fix delivery transaction estimation used by rational relayer (#1109) 77a2f2fbed Remove fund account checks from upgrade. (#1111) 824334802b Rename param and update comment (#1108) d7784bfe06 Fix spellcheck (#1110) 0b18f5906a Refactor substrate messages source and substrate messages target (#1105) b27240bbff fix compilation (#1107) 9697da4fe8 Emit mortal transactions from relay (#1073) b29396c077 Change vault vars type to env vars (#1084) 35e0bbdc0c Make clippy mandatory. (#1103) a517e8541f Remove unused deps (#1102) 873dae608a Remove unnessary deps (#1101) 13450b74ee Stored conversion rate updater (#1005) 74389829f3 [BREAKING] Migrate messages pallet to frame v2 (#1088) 424da938dd README fix (#1100) 865744c909 upgrade currency exchange pallet to frame v2 (#1097) b5038148b3 Add missing docs (#1095) 0791e911c1 Common crate for substrate-relay (#1082) 3834c9d880 Update high-level-overview.md (#1093) c93553face Increase the time window for messaging alerts. (#1092) 8b9cc3cecd migrate pallet-shift-session-manager to frame v2 (#1090) dc91813c22 migrate eth PoA pallet to frame v2 (#1091) f16bb098cc Migrate dispatch pallet to frame v2 (#1089) 19f4325348 Bridge/This Chain Ids should be exposed as constants on pallet level. (#1085) 6381122df7 Change ChainSpec::from_genesis for Rialto and Millau chains to reflect the chain names. (#1079) 0f1d33e973 Make CI happy again (#1086) 238e65d96f fix typo (#1080) fc008457b6 Token-swap-over-bridge pallet (#944) 3fb97fa5ef Fix full spellcheck (#1076) eae4ed7170 fixed wrong trace (#1075) 219a0fad04 merge two weight-related loops in messages pallet (#1071) fc85632fdb increase_message_fee depends on stored mesage size (#1066) 530f37a23b companion for https://github.com/paritytech/polkadot/pull/3507 (#1067) 53b8cba683 sc_basic_authorship=trace for millau nodes (#1074) 9874e05e98 Improve traces of message generator scripts (#1069) 7b5ee84fbb extract message_details impl into runtime common (#1070) 5a4aed5a8b refund weight for mot pruning messages (#1062) 90e3d1e111 Fix Westend -> Millau sync (#1064) 427d30ddfc When restarting client, also "restart" tokio runtime (#1065) d47c05eeef Change get pipeline sensitive variables from Vault instead of GitLab settings (#1063) d775a85415 use tokio reactor to execute jsonrpsee futures (#1061) 15c8cd61cb Use BABE to author blocks on Rialto (previously: Aura) (#1050) 5186293500 Allow reading suri && password override from file (#1059) b506298262 Update jsonrpsee reference (#1049) 1734d00517 enable weight fee adjustent in Rialto/Millau (#1044) 607265afae Pay dispatch fee at target chain cli option (#1043) ce79ef91be bump dependencies before start referencing polkadot repo (#1048) 924fa24f6d Cli option for greedy relayer + run no-losses relayer by default (#1042) e21eba7b59 Yrong README Fixup + M1 Fixes (#1045) 20d08204a2 Confirm delivery detects when more than expected messages are confirmed (#1039) 994b846b52 pre and post dispatch weights of OnDeliveryConfirmed callback (#1040) 1dd5297e84 give real value to Rialto and Millau tokens (#1038) 035bee8715 Use real conversion rate in greedy relayer strategy (#1035) 9cfaecd0f7 fixed metrics prefix (#1037) 1d8d224937 Use kebab-case for bridge arguments (#1036) f30a4c79a6 Shared reference to conversion rate metric value (#1034) c34d7a5cbb estimate transaction fee (#1015) 93404b18bb change alert period from 2m to 10m for Westend -> Millau (GRANDPA or public node itself is lagging sometimes) (#1032) git-subtree-dir: bridges git-subtree-split: 407bf44a8a5f4e60aceef2dc755cd9ff09929ac3
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
[package]
|
||||
name = "relay-substrate-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "1.6.5", features = ["attributes"] }
|
||||
async-trait = "0.1.40"
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
||||
jsonrpsee-proc-macros = "=0.2.0-alpha.6"
|
||||
jsonrpsee-ws-client = "=0.2.0-alpha.6"
|
||||
log = "0.4.11"
|
||||
num-traits = "0.2"
|
||||
rand = "0.7"
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-header-chain = { path = "../../primitives/header-chain" }
|
||||
bp-messages = { path = "../../primitives/messages" }
|
||||
bp-runtime = { path = "../../primitives/runtime" }
|
||||
finality-relay = { path = "../finality" }
|
||||
headers-relay = { path = "../headers" }
|
||||
relay-utils = { path = "../utils" }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
#[dev-dependencies]
|
||||
futures = "0.3.7"
|
||||
@@ -1,107 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use bp_runtime::Chain as ChainBase;
|
||||
use frame_support::Parameter;
|
||||
use jsonrpsee_ws_client::{DeserializeOwned, Serialize};
|
||||
use num_traits::{CheckedSub, SaturatingAdd, Zero};
|
||||
use sp_core::{storage::StorageKey, Pair};
|
||||
use sp_runtime::{
|
||||
generic::SignedBlock,
|
||||
traits::{
|
||||
AtLeast32Bit, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member,
|
||||
},
|
||||
EncodedJustification,
|
||||
};
|
||||
use std::{fmt::Debug, time::Duration};
|
||||
|
||||
/// Substrate-based chain from minimal relay-client point of view.
|
||||
pub trait Chain: ChainBase + Clone {
|
||||
/// Chain name.
|
||||
const NAME: &'static str;
|
||||
/// Average block interval.
|
||||
///
|
||||
/// How often blocks are produced on that chain. It's suggested to set this value
|
||||
/// to match the block time of the chain.
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration;
|
||||
|
||||
/// The user account identifier type for the runtime.
|
||||
type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default;
|
||||
/// Index of a transaction used by the chain.
|
||||
type Index: Parameter
|
||||
+ Member
|
||||
+ MaybeSerialize
|
||||
+ Debug
|
||||
+ Default
|
||||
+ MaybeDisplay
|
||||
+ DeserializeOwned
|
||||
+ AtLeast32Bit
|
||||
+ Copy;
|
||||
/// Block type.
|
||||
type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>;
|
||||
/// The aggregated `Call` type.
|
||||
type Call: Dispatchable + Debug;
|
||||
/// Balance of an account in native tokens.
|
||||
///
|
||||
/// The chain may suport multiple tokens, but this particular type is for token that is used
|
||||
/// to pay for transaction dispatch, to reward different relayers (headers, messages), etc.
|
||||
type Balance: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + SaturatingAdd + Zero;
|
||||
}
|
||||
|
||||
/// Substrate-based chain with `frame_system::Config::AccountData` set to
|
||||
/// the `pallet_balances::AccountData<Balance>`.
|
||||
pub trait ChainWithBalances: Chain {
|
||||
/// Return runtime storage key for getting `frame_system::AccountInfo` of given account.
|
||||
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey;
|
||||
}
|
||||
|
||||
/// Block with justification.
|
||||
pub trait BlockWithJustification<Header> {
|
||||
/// Return block header.
|
||||
fn header(&self) -> Header;
|
||||
/// Return block justification, if known.
|
||||
fn justification(&self) -> Option<&EncodedJustification>;
|
||||
}
|
||||
|
||||
/// Substrate-based chain transactions signing scheme.
|
||||
pub trait TransactionSignScheme {
|
||||
/// Chain that this scheme is to be used.
|
||||
type Chain: Chain;
|
||||
/// Type of key pairs used to sign transactions.
|
||||
type AccountKeyPair: Pair;
|
||||
/// Signed transaction.
|
||||
type SignedTransaction;
|
||||
|
||||
/// Create transaction for given runtime call, signed by given account.
|
||||
fn sign_transaction(
|
||||
genesis_hash: <Self::Chain as ChainBase>::Hash,
|
||||
signer: &Self::AccountKeyPair,
|
||||
signer_nonce: <Self::Chain as Chain>::Index,
|
||||
call: <Self::Chain as Chain>::Call,
|
||||
) -> Self::SignedTransaction;
|
||||
}
|
||||
|
||||
impl<Block: BlockT> BlockWithJustification<Block::Header> for SignedBlock<Block> {
|
||||
fn header(&self) -> Block::Header {
|
||||
self.block.header().clone()
|
||||
}
|
||||
|
||||
fn justification(&self) -> Option<&EncodedJustification> {
|
||||
self.justifications
|
||||
.as_ref()
|
||||
.and_then(|j| j.get(sp_finality_grandpa::GRANDPA_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Substrate node client.
|
||||
|
||||
use crate::chain::{Chain, ChainWithBalances};
|
||||
use crate::rpc::Substrate;
|
||||
use crate::{ConnectionParams, Error, Result};
|
||||
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use codec::Decode;
|
||||
use frame_system::AccountInfo;
|
||||
use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned};
|
||||
use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder};
|
||||
use num_traits::Zero;
|
||||
use pallet_balances::AccountData;
|
||||
use relay_utils::relay_loop::RECONNECT_DELAY;
|
||||
use sp_core::{storage::StorageKey, Bytes};
|
||||
use sp_trie::StorageProof;
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities";
|
||||
const MAX_SUBSCRIPTION_CAPACITY: usize = 4096;
|
||||
|
||||
/// Opaque justifications subscription type.
|
||||
pub type JustificationsSubscription = Subscription<Bytes>;
|
||||
|
||||
/// Opaque GRANDPA authorities set.
|
||||
pub type OpaqueGrandpaAuthoritiesSet = Vec<u8>;
|
||||
|
||||
/// Substrate client type.
|
||||
///
|
||||
/// Cloning `Client` is a cheap operation.
|
||||
pub struct Client<C: Chain> {
|
||||
/// Client connection params.
|
||||
params: ConnectionParams,
|
||||
/// Substrate RPC client.
|
||||
client: Arc<RpcClient>,
|
||||
/// Genesis block hash.
|
||||
genesis_hash: C::Hash,
|
||||
/// If several tasks are submitting their transactions simultaneously using `submit_signed_extrinsic`
|
||||
/// method, they may get the same transaction nonce. So one of transactions will be rejected
|
||||
/// from the pool. This lock is here to prevent situations like that.
|
||||
submit_signed_extrinsic_lock: Arc<Mutex<()>>,
|
||||
}
|
||||
|
||||
impl<C: Chain> Clone for Client<C> {
|
||||
fn clone(&self) -> Self {
|
||||
Client {
|
||||
params: self.params.clone(),
|
||||
client: self.client.clone(),
|
||||
genesis_hash: self.genesis_hash,
|
||||
submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain> std::fmt::Debug for Client<C> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.debug_struct("Client")
|
||||
.field("genesis_hash", &self.genesis_hash)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain> Client<C> {
|
||||
/// Returns client that is able to call RPCs on Substrate node over websocket connection.
|
||||
///
|
||||
/// This function will keep connecting to given Sustrate node until connection is established
|
||||
/// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again.
|
||||
pub async fn new(params: ConnectionParams) -> Self {
|
||||
loop {
|
||||
match Self::try_connect(params.clone()).await {
|
||||
Ok(client) => return client,
|
||||
Err(error) => log::error!(
|
||||
target: "bridge",
|
||||
"Failed to connect to {} node: {:?}. Going to retry in {}s",
|
||||
C::NAME,
|
||||
error,
|
||||
RECONNECT_DELAY.as_secs(),
|
||||
),
|
||||
}
|
||||
|
||||
async_std::task::sleep(RECONNECT_DELAY).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection
|
||||
/// has been established or error otherwise.
|
||||
pub async fn try_connect(params: ConnectionParams) -> Result<Self> {
|
||||
let client = Self::build_client(params.clone()).await?;
|
||||
|
||||
let number: C::BlockNumber = Zero::zero();
|
||||
let genesis_hash = Substrate::<C>::chain_get_block_hash(&*client, number).await?;
|
||||
|
||||
Ok(Self {
|
||||
params,
|
||||
client,
|
||||
genesis_hash,
|
||||
submit_signed_extrinsic_lock: Arc::new(Mutex::new(())),
|
||||
})
|
||||
}
|
||||
|
||||
/// Reopen client connection.
|
||||
pub async fn reconnect(&mut self) -> Result<()> {
|
||||
self.client = Self::build_client(self.params.clone()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build client to use in connection.
|
||||
async fn build_client(params: ConnectionParams) -> Result<Arc<RpcClient>> {
|
||||
let uri = format!(
|
||||
"{}://{}:{}",
|
||||
if params.secure { "wss" } else { "ws" },
|
||||
params.host,
|
||||
params.port,
|
||||
);
|
||||
let client = RpcClientBuilder::default()
|
||||
.max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY)
|
||||
.build(&uri)
|
||||
.await?;
|
||||
|
||||
Ok(Arc::new(client))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain> Client<C> {
|
||||
/// Returns true if client is connected to at least one peer and is in synced state.
|
||||
pub async fn ensure_synced(&self) -> Result<()> {
|
||||
let health = Substrate::<C>::system_health(&*self.client).await?;
|
||||
let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0);
|
||||
if is_synced {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ClientNotSynced(health))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return hash of the genesis block.
|
||||
pub fn genesis_hash(&self) -> &C::Hash {
|
||||
&self.genesis_hash
|
||||
}
|
||||
|
||||
/// Return hash of the best finalized block.
|
||||
pub async fn best_finalized_header_hash(&self) -> Result<C::Hash> {
|
||||
Ok(Substrate::<C>::chain_get_finalized_head(&*self.client).await?)
|
||||
}
|
||||
|
||||
/// Returns the best Substrate header.
|
||||
pub async fn best_header(&self) -> Result<C::Header>
|
||||
where
|
||||
C::Header: DeserializeOwned,
|
||||
{
|
||||
Ok(Substrate::<C>::chain_get_header(&*self.client, None).await?)
|
||||
}
|
||||
|
||||
/// Get a Substrate block from its hash.
|
||||
pub async fn get_block(&self, block_hash: Option<C::Hash>) -> Result<C::SignedBlock> {
|
||||
Ok(Substrate::<C>::chain_get_block(&*self.client, block_hash).await?)
|
||||
}
|
||||
|
||||
/// Get a Substrate header by its hash.
|
||||
pub async fn header_by_hash(&self, block_hash: C::Hash) -> Result<C::Header>
|
||||
where
|
||||
C::Header: DeserializeOwned,
|
||||
{
|
||||
Ok(Substrate::<C>::chain_get_header(&*self.client, block_hash).await?)
|
||||
}
|
||||
|
||||
/// Get a Substrate block hash by its number.
|
||||
pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result<C::Hash> {
|
||||
Ok(Substrate::<C>::chain_get_block_hash(&*self.client, number).await?)
|
||||
}
|
||||
|
||||
/// Get a Substrate header by its number.
|
||||
pub async fn header_by_number(&self, block_number: C::BlockNumber) -> Result<C::Header>
|
||||
where
|
||||
C::Header: DeserializeOwned,
|
||||
{
|
||||
let block_hash = Self::block_hash_by_number(self, block_number).await?;
|
||||
Ok(Self::header_by_hash(self, block_hash).await?)
|
||||
}
|
||||
|
||||
/// Return runtime version.
|
||||
pub async fn runtime_version(&self) -> Result<RuntimeVersion> {
|
||||
Ok(Substrate::<C>::state_runtime_version(&*self.client).await?)
|
||||
}
|
||||
|
||||
/// Read value from runtime storage.
|
||||
pub async fn storage_value<T: Decode>(&self, storage_key: StorageKey) -> Result<Option<T>> {
|
||||
Substrate::<C>::state_get_storage(&*self.client, storage_key)
|
||||
.await?
|
||||
.map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed))
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// Return native tokens balance of the account.
|
||||
pub async fn free_native_balance(&self, account: C::AccountId) -> Result<C::Balance>
|
||||
where
|
||||
C: ChainWithBalances,
|
||||
{
|
||||
let storage_key = C::account_info_storage_key(&account);
|
||||
let encoded_account_data = Substrate::<C>::state_get_storage(&*self.client, storage_key)
|
||||
.await?
|
||||
.ok_or(Error::AccountDoesNotExist)?;
|
||||
let decoded_account_data =
|
||||
AccountInfo::<C::Index, AccountData<C::Balance>>::decode(&mut &encoded_account_data.0[..])
|
||||
.map_err(Error::ResponseParseFailed)?;
|
||||
Ok(decoded_account_data.data.free)
|
||||
}
|
||||
|
||||
/// Get the nonce of the given Substrate account.
|
||||
///
|
||||
/// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address.
|
||||
pub async fn next_account_index(&self, account: C::AccountId) -> Result<C::Index> {
|
||||
Ok(Substrate::<C>::system_account_next_index(&*self.client, account).await?)
|
||||
}
|
||||
|
||||
/// Submit unsigned extrinsic for inclusion in a block.
|
||||
///
|
||||
/// Note: The given transaction needs to be SCALE encoded beforehand.
|
||||
pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result<C::Hash> {
|
||||
let tx_hash = Substrate::<C>::author_submit_extrinsic(&*self.client, transaction).await?;
|
||||
log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash);
|
||||
Ok(tx_hash)
|
||||
}
|
||||
|
||||
/// Submit an extrinsic signed by given account.
|
||||
///
|
||||
/// All calls of this method are synchronized, so there can't be more than one active
|
||||
/// `submit_signed_extrinsic()` call. This guarantees that no nonces collision may happen
|
||||
/// if all client instances are clones of the same initial `Client`.
|
||||
///
|
||||
/// Note: The given transaction needs to be SCALE encoded beforehand.
|
||||
pub async fn submit_signed_extrinsic(
|
||||
&self,
|
||||
extrinsic_signer: C::AccountId,
|
||||
prepare_extrinsic: impl FnOnce(C::Index) -> Bytes,
|
||||
) -> Result<C::Hash> {
|
||||
let _guard = self.submit_signed_extrinsic_lock.lock().await;
|
||||
let transaction_nonce = self.next_account_index(extrinsic_signer).await?;
|
||||
let extrinsic = prepare_extrinsic(transaction_nonce);
|
||||
let tx_hash = Substrate::<C>::author_submit_extrinsic(&*self.client, extrinsic).await?;
|
||||
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
||||
Ok(tx_hash)
|
||||
}
|
||||
|
||||
/// Get the GRANDPA authority set at given block.
|
||||
pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result<OpaqueGrandpaAuthoritiesSet> {
|
||||
let call = SUB_API_GRANDPA_AUTHORITIES.to_string();
|
||||
let data = Bytes(Vec::new());
|
||||
|
||||
let encoded_response = Substrate::<C>::state_call(&*self.client, call, data, Some(block)).await?;
|
||||
let authority_list = encoded_response.0;
|
||||
|
||||
Ok(authority_list)
|
||||
}
|
||||
|
||||
/// Execute runtime call at given block.
|
||||
pub async fn state_call(&self, method: String, data: Bytes, at_block: Option<C::Hash>) -> Result<Bytes> {
|
||||
Substrate::<C>::state_call(&*self.client, method, data, at_block)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Returns storage proof of given storage keys.
|
||||
pub async fn prove_storage(&self, keys: Vec<StorageKey>, at_block: C::Hash) -> Result<StorageProof> {
|
||||
Substrate::<C>::state_prove_storage(&*self.client, keys, Some(at_block))
|
||||
.await
|
||||
.map(|proof| StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect()))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Return new justifications stream.
|
||||
pub async fn subscribe_justifications(&self) -> Result<JustificationsSubscription> {
|
||||
Ok(self
|
||||
.client
|
||||
.subscribe(
|
||||
"grandpa_subscribeJustifications",
|
||||
JsonRpcParams::NoParams,
|
||||
"grandpa_unsubscribeJustifications",
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Substrate node RPC errors.
|
||||
|
||||
use jsonrpsee_ws_client::Error as RpcError;
|
||||
use relay_utils::MaybeConnectionError;
|
||||
use sc_rpc_api::system::Health;
|
||||
|
||||
/// Result type used by Substrate client.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Errors that can occur only when interacting with
|
||||
/// a Substrate node through RPC.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// An error that can occur when making a request to
|
||||
/// an JSON-RPC server.
|
||||
RpcError(RpcError),
|
||||
/// The response from the server could not be SCALE decoded.
|
||||
ResponseParseFailed(codec::Error),
|
||||
/// The Substrate bridge pallet has not yet been initialized.
|
||||
UninitializedBridgePallet,
|
||||
/// Account does not exist on the chain.
|
||||
AccountDoesNotExist,
|
||||
/// Runtime storage is missing mandatory ":code:" entry.
|
||||
MissingMandatoryCodeEntry,
|
||||
/// The client we're connected to is not synced, so we can't rely on its state.
|
||||
ClientNotSynced(Health),
|
||||
/// An error has happened when we have tried to parse storage proof.
|
||||
StorageProofError(bp_runtime::StorageProofError),
|
||||
/// Custom logic error.
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Self::RpcError(ref e) => Some(e),
|
||||
Self::ResponseParseFailed(ref e) => Some(e),
|
||||
Self::UninitializedBridgePallet => None,
|
||||
Self::AccountDoesNotExist => None,
|
||||
Self::MissingMandatoryCodeEntry => None,
|
||||
Self::ClientNotSynced(_) => None,
|
||||
Self::StorageProofError(_) => None,
|
||||
Self::Custom(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpcError> for Error {
|
||||
fn from(error: RpcError) -> Self {
|
||||
Error::RpcError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeConnectionError for Error {
|
||||
fn is_connection_error(&self) -> bool {
|
||||
matches!(
|
||||
*self,
|
||||
Error::RpcError(RpcError::TransportError(_))
|
||||
// right now if connection to the ws server is dropped (after it is already established),
|
||||
// we're getting this error
|
||||
| Error::RpcError(RpcError::Internal(_))
|
||||
| Error::RpcError(RpcError::RestartNeeded(_))
|
||||
| Error::ClientNotSynced(_),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
Self::RpcError(e) => e.to_string(),
|
||||
Self::ResponseParseFailed(e) => e.to_string(),
|
||||
Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(),
|
||||
Self::AccountDoesNotExist => "Account does not exist on the chain".into(),
|
||||
Self::MissingMandatoryCodeEntry => "Mandatory :code: entry is missing from runtime storage".into(),
|
||||
Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e),
|
||||
Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health),
|
||||
Self::Custom(e) => e.clone(),
|
||||
};
|
||||
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for String {
|
||||
fn from(error: Error) -> String {
|
||||
error.to_string()
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Default generic implementation of finality source for basic Substrate client.
|
||||
|
||||
use crate::chain::{BlockWithJustification, Chain};
|
||||
use crate::client::Client;
|
||||
use crate::error::Error;
|
||||
use crate::sync_header::SyncHeader;
|
||||
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use async_trait::async_trait;
|
||||
use bp_header_chain::justification::GrandpaJustification;
|
||||
use codec::Decode;
|
||||
use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader};
|
||||
use futures::stream::{unfold, Stream, StreamExt};
|
||||
use relay_utils::relay_loop::Client as RelayClient;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use std::{marker::PhantomData, pin::Pin};
|
||||
|
||||
/// Shared updatable reference to the maximal header number that we want to sync from the source.
|
||||
pub type RequiredHeaderNumberRef<C> = Arc<Mutex<<C as bp_runtime::Chain>::BlockNumber>>;
|
||||
|
||||
/// Substrate node as finality source.
|
||||
pub struct FinalitySource<C: Chain, P> {
|
||||
client: Client<C>,
|
||||
maximal_header_number: Option<RequiredHeaderNumberRef<C>>,
|
||||
_phantom: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<C: Chain, P> FinalitySource<C, P> {
|
||||
/// Create new headers source using given client.
|
||||
pub fn new(client: Client<C>, maximal_header_number: Option<RequiredHeaderNumberRef<C>>) -> Self {
|
||||
FinalitySource {
|
||||
client,
|
||||
maximal_header_number,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns reference to the underlying RPC client.
|
||||
pub fn client(&self) -> &Client<C> {
|
||||
&self.client
|
||||
}
|
||||
|
||||
/// Returns best finalized block number.
|
||||
pub async fn on_chain_best_finalized_block_number(&self) -> Result<C::BlockNumber, Error> {
|
||||
// we **CAN** continue to relay finality proofs if source node is out of sync, because
|
||||
// target node may be missing proofs that are already available at the source
|
||||
let finalized_header_hash = self.client.best_finalized_header_hash().await?;
|
||||
let finalized_header = self.client.header_by_hash(finalized_header_hash).await?;
|
||||
Ok(*finalized_header.number())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain, P> Clone for FinalitySource<C, P> {
|
||||
fn clone(&self) -> Self {
|
||||
FinalitySource {
|
||||
client: self.client.clone(),
|
||||
maximal_header_number: self.maximal_header_number.clone(),
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: Chain, P: FinalitySyncPipeline> RelayClient for FinalitySource<C, P> {
|
||||
type Error = Error;
|
||||
|
||||
async fn reconnect(&mut self) -> Result<(), Error> {
|
||||
self.client.reconnect().await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P> SourceClient<P> for FinalitySource<C, P>
|
||||
where
|
||||
C: Chain,
|
||||
C::BlockNumber: relay_utils::BlockNumberBase,
|
||||
P: FinalitySyncPipeline<
|
||||
Hash = C::Hash,
|
||||
Number = C::BlockNumber,
|
||||
Header = SyncHeader<C::Header>,
|
||||
FinalityProof = GrandpaJustification<C::Header>,
|
||||
>,
|
||||
P::Header: SourceHeader<C::BlockNumber>,
|
||||
{
|
||||
type FinalityProofsStream = Pin<Box<dyn Stream<Item = GrandpaJustification<C::Header>> + Send>>;
|
||||
|
||||
async fn best_finalized_block_number(&self) -> Result<P::Number, Error> {
|
||||
let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?;
|
||||
// never return block number larger than requested. This way we'll never sync headers
|
||||
// past `maximal_header_number`
|
||||
if let Some(ref maximal_header_number) = self.maximal_header_number {
|
||||
let maximal_header_number = *maximal_header_number.lock().await;
|
||||
if finalized_header_number > maximal_header_number {
|
||||
finalized_header_number = maximal_header_number;
|
||||
}
|
||||
}
|
||||
Ok(finalized_header_number)
|
||||
}
|
||||
|
||||
async fn header_and_finality_proof(
|
||||
&self,
|
||||
number: P::Number,
|
||||
) -> Result<(P::Header, Option<P::FinalityProof>), Error> {
|
||||
let header_hash = self.client.block_hash_by_number(number).await?;
|
||||
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
||||
|
||||
let justification = signed_block
|
||||
.justification()
|
||||
.map(|raw_justification| GrandpaJustification::<C::Header>::decode(&mut raw_justification.as_slice()))
|
||||
.transpose()
|
||||
.map_err(Error::ResponseParseFailed)?;
|
||||
|
||||
Ok((signed_block.header().into(), justification))
|
||||
}
|
||||
|
||||
async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, Error> {
|
||||
Ok(unfold(
|
||||
self.client.clone().subscribe_justifications().await?,
|
||||
move |mut subscription| async move {
|
||||
loop {
|
||||
let next_justification = subscription.next().await?;
|
||||
let decoded_justification =
|
||||
GrandpaJustification::<C::Header>::decode(&mut &next_justification.0[..]);
|
||||
|
||||
let justification = match decoded_justification {
|
||||
Ok(j) => j,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
target: "bridge",
|
||||
"Failed to decode justification target from the {} justifications stream: {:?}",
|
||||
P::SOURCE_NAME,
|
||||
err,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
return Some((justification, subscription));
|
||||
}
|
||||
},
|
||||
)
|
||||
.boxed())
|
||||
}
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Pallet provides a set of guard functions that are running in background threads
|
||||
//! and are aborting process if some condition fails.
|
||||
|
||||
use crate::{Chain, ChainWithBalances, Client};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use num_traits::CheckedSub;
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
/// Guards environment.
|
||||
#[async_trait]
|
||||
pub trait Environment<C: ChainWithBalances>: Send + Sync + 'static {
|
||||
/// Return current runtime version.
|
||||
async fn runtime_version(&mut self) -> Result<RuntimeVersion, String>;
|
||||
/// Return free native balance of the account on the chain.
|
||||
async fn free_native_balance(&mut self, account: C::AccountId) -> Result<C::Balance, String>;
|
||||
|
||||
/// Return current time.
|
||||
fn now(&self) -> Instant {
|
||||
Instant::now()
|
||||
}
|
||||
/// Sleep given amount of time.
|
||||
async fn sleep(&mut self, duration: Duration) {
|
||||
async_std::task::sleep(duration).await
|
||||
}
|
||||
/// Abort current process. Called when guard condition check fails.
|
||||
async fn abort(&mut self) {
|
||||
std::process::abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// Abort when runtime spec version is different from specified.
|
||||
pub fn abort_on_spec_version_change<C: ChainWithBalances>(mut env: impl Environment<C>, expected_spec_version: u32) {
|
||||
async_std::task::spawn(async move {
|
||||
loop {
|
||||
let actual_spec_version = env.runtime_version().await;
|
||||
match actual_spec_version {
|
||||
Ok(version) if version.spec_version == expected_spec_version => (),
|
||||
Ok(version) => {
|
||||
log::error!(
|
||||
target: "bridge-guard",
|
||||
"{} runtime spec version has changed from {} to {}. Aborting relay",
|
||||
C::NAME,
|
||||
expected_spec_version,
|
||||
version.spec_version,
|
||||
);
|
||||
|
||||
env.abort().await;
|
||||
}
|
||||
Err(error) => log::warn!(
|
||||
target: "bridge-guard",
|
||||
"Failed to read {} runtime version: {:?}. Relay may need to be stopped manually",
|
||||
C::NAME,
|
||||
error,
|
||||
),
|
||||
}
|
||||
|
||||
env.sleep(conditions_check_delay::<C>()).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Abort if, during a 24 hours, free balance of given account is decreased at least by given value.
|
||||
/// Other components may increase (or decrease) balance of account and it WILL affect logic of the guard.
|
||||
pub fn abort_when_account_balance_decreased<C: ChainWithBalances>(
|
||||
mut env: impl Environment<C>,
|
||||
account_id: C::AccountId,
|
||||
maximal_decrease: C::Balance,
|
||||
) {
|
||||
const DAY: Duration = Duration::from_secs(60 * 60 * 24);
|
||||
|
||||
async_std::task::spawn(async move {
|
||||
let mut balances = VecDeque::new();
|
||||
|
||||
loop {
|
||||
let current_time = env.now();
|
||||
|
||||
// remember balances that are beyound 24h border
|
||||
let time_border = current_time - DAY;
|
||||
while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) {
|
||||
balances.pop_front();
|
||||
}
|
||||
|
||||
// read balance of the account
|
||||
let current_balance = env.free_native_balance(account_id.clone()).await;
|
||||
|
||||
// remember balance and check difference
|
||||
match current_balance {
|
||||
Ok(current_balance) => {
|
||||
// remember balance
|
||||
balances.push_back((current_time, current_balance));
|
||||
|
||||
// check if difference between current and oldest balance is too large
|
||||
let (oldest_time, oldest_balance) =
|
||||
balances.front().expect("pushed to queue couple of lines above; qed");
|
||||
let balances_difference = oldest_balance.checked_sub(¤t_balance);
|
||||
if balances_difference > Some(maximal_decrease) {
|
||||
log::error!(
|
||||
target: "bridge-guard",
|
||||
"Balance of {} account {:?} has decreased from {:?} to {:?} in {} minutes. Aborting relay",
|
||||
C::NAME,
|
||||
account_id,
|
||||
oldest_balance,
|
||||
current_balance,
|
||||
current_time.duration_since(*oldest_time).as_secs() / 60,
|
||||
);
|
||||
|
||||
env.abort().await;
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
target: "bridge-guard",
|
||||
"Failed to read {} account {:?} balance: {:?}. Relay may need to be stopped manually",
|
||||
C::NAME,
|
||||
account_id,
|
||||
error,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
env.sleep(conditions_check_delay::<C>()).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Delay between conditions check.
|
||||
fn conditions_check_delay<C: Chain>() -> Duration {
|
||||
C::AVERAGE_BLOCK_INTERVAL * (10 + rand::random::<u32>() % 10)
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: ChainWithBalances> Environment<C> for Client<C> {
|
||||
async fn runtime_version(&mut self) -> Result<RuntimeVersion, String> {
|
||||
Client::<C>::runtime_version(self).await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
async fn free_native_balance(&mut self, account: C::AccountId) -> Result<C::Balance, String> {
|
||||
Client::<C>::free_native_balance(self, account)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::{
|
||||
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
|
||||
future::FutureExt,
|
||||
stream::StreamExt,
|
||||
SinkExt,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct TestChain;
|
||||
|
||||
impl bp_runtime::Chain for TestChain {
|
||||
type BlockNumber = u32;
|
||||
type Hash = sp_core::H256;
|
||||
type Hasher = sp_runtime::traits::BlakeTwo256;
|
||||
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
|
||||
}
|
||||
|
||||
impl Chain for TestChain {
|
||||
const NAME: &'static str = "Test";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
|
||||
|
||||
type AccountId = u32;
|
||||
type Index = u32;
|
||||
type SignedBlock =
|
||||
sp_runtime::generic::SignedBlock<sp_runtime::generic::Block<Self::Header, sp_runtime::OpaqueExtrinsic>>;
|
||||
type Call = ();
|
||||
type Balance = u32;
|
||||
}
|
||||
|
||||
impl ChainWithBalances for TestChain {
|
||||
fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
struct TestEnvironment {
|
||||
runtime_version_rx: UnboundedReceiver<RuntimeVersion>,
|
||||
free_native_balance_rx: UnboundedReceiver<u32>,
|
||||
slept_tx: UnboundedSender<()>,
|
||||
aborted_tx: UnboundedSender<()>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Environment<TestChain> for TestEnvironment {
|
||||
async fn runtime_version(&mut self) -> Result<RuntimeVersion, String> {
|
||||
Ok(self.runtime_version_rx.next().await.unwrap_or_default())
|
||||
}
|
||||
|
||||
async fn free_native_balance(&mut self, _account: u32) -> Result<u32, String> {
|
||||
Ok(self.free_native_balance_rx.next().await.unwrap_or_default())
|
||||
}
|
||||
|
||||
async fn sleep(&mut self, _duration: Duration) {
|
||||
let _ = self.slept_tx.send(()).await;
|
||||
}
|
||||
|
||||
async fn abort(&mut self) {
|
||||
let _ = self.aborted_tx.send(()).await;
|
||||
// simulate process abort :)
|
||||
async_std::task::sleep(Duration::from_secs(60)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aborts_when_spec_version_is_changed() {
|
||||
async_std::task::block_on(async {
|
||||
let (
|
||||
(mut runtime_version_tx, runtime_version_rx),
|
||||
(_free_native_balance_tx, free_native_balance_rx),
|
||||
(slept_tx, mut slept_rx),
|
||||
(aborted_tx, mut aborted_rx),
|
||||
) = (unbounded(), unbounded(), unbounded(), unbounded());
|
||||
abort_on_spec_version_change(
|
||||
TestEnvironment {
|
||||
runtime_version_rx,
|
||||
free_native_balance_rx,
|
||||
slept_tx,
|
||||
aborted_tx,
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
// client responds with wrong version
|
||||
runtime_version_tx
|
||||
.send(RuntimeVersion {
|
||||
spec_version: 42,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// then the `abort` function is called
|
||||
aborted_rx.next().await;
|
||||
// and we do not reach the `sleep` function call
|
||||
assert!(slept_rx.next().now_or_never().is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_aborts_when_spec_version_is_unchanged() {
|
||||
async_std::task::block_on(async {
|
||||
let (
|
||||
(mut runtime_version_tx, runtime_version_rx),
|
||||
(_free_native_balance_tx, free_native_balance_rx),
|
||||
(slept_tx, mut slept_rx),
|
||||
(aborted_tx, mut aborted_rx),
|
||||
) = (unbounded(), unbounded(), unbounded(), unbounded());
|
||||
abort_on_spec_version_change(
|
||||
TestEnvironment {
|
||||
runtime_version_rx,
|
||||
free_native_balance_rx,
|
||||
slept_tx,
|
||||
aborted_tx,
|
||||
},
|
||||
42,
|
||||
);
|
||||
|
||||
// client responds with the same version
|
||||
runtime_version_tx
|
||||
.send(RuntimeVersion {
|
||||
spec_version: 42,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// then the `sleep` function is called
|
||||
slept_rx.next().await;
|
||||
// and the `abort` function is not called
|
||||
assert!(aborted_rx.next().now_or_never().is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aborts_when_balance_is_too_low() {
|
||||
async_std::task::block_on(async {
|
||||
let (
|
||||
(_runtime_version_tx, runtime_version_rx),
|
||||
(mut free_native_balance_tx, free_native_balance_rx),
|
||||
(slept_tx, mut slept_rx),
|
||||
(aborted_tx, mut aborted_rx),
|
||||
) = (unbounded(), unbounded(), unbounded(), unbounded());
|
||||
abort_when_account_balance_decreased(
|
||||
TestEnvironment {
|
||||
runtime_version_rx,
|
||||
free_native_balance_rx,
|
||||
slept_tx,
|
||||
aborted_tx,
|
||||
},
|
||||
0,
|
||||
100,
|
||||
);
|
||||
|
||||
// client responds with initial balance
|
||||
free_native_balance_tx.send(1000).await.unwrap();
|
||||
|
||||
// then the guard sleeps
|
||||
slept_rx.next().await;
|
||||
|
||||
// and then client responds with updated balance, which is too low
|
||||
free_native_balance_tx.send(899).await.unwrap();
|
||||
|
||||
// then the `abort` function is called
|
||||
aborted_rx.next().await;
|
||||
// and we do not reach next `sleep` function call
|
||||
assert!(slept_rx.next().now_or_never().is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_aborts_when_balance_is_enough() {
|
||||
async_std::task::block_on(async {
|
||||
let (
|
||||
(_runtime_version_tx, runtime_version_rx),
|
||||
(mut free_native_balance_tx, free_native_balance_rx),
|
||||
(slept_tx, mut slept_rx),
|
||||
(aborted_tx, mut aborted_rx),
|
||||
) = (unbounded(), unbounded(), unbounded(), unbounded());
|
||||
abort_when_account_balance_decreased(
|
||||
TestEnvironment {
|
||||
runtime_version_rx,
|
||||
free_native_balance_rx,
|
||||
slept_tx,
|
||||
aborted_tx,
|
||||
},
|
||||
0,
|
||||
100,
|
||||
);
|
||||
|
||||
// client responds with initial balance
|
||||
free_native_balance_tx.send(1000).await.unwrap();
|
||||
|
||||
// then the guard sleeps
|
||||
slept_rx.next().await;
|
||||
|
||||
// and then client responds with updated balance, which is enough
|
||||
free_native_balance_tx.send(950).await.unwrap();
|
||||
|
||||
// then the `sleep` function is called
|
||||
slept_rx.next().await;
|
||||
// and `abort` is not called
|
||||
assert!(aborted_rx.next().now_or_never().is_none());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Default generic implementation of headers source for basic Substrate client.
|
||||
|
||||
use crate::chain::{BlockWithJustification, Chain};
|
||||
use crate::client::Client;
|
||||
use crate::error::Error;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use headers_relay::{
|
||||
sync_loop::SourceClient,
|
||||
sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader},
|
||||
};
|
||||
use relay_utils::relay_loop::Client as RelayClient;
|
||||
use sp_runtime::{traits::Header as HeaderT, EncodedJustification};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Substrate node as headers source.
|
||||
pub struct HeadersSource<C: Chain, P> {
|
||||
client: Client<C>,
|
||||
_phantom: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<C: Chain, P> HeadersSource<C, P> {
|
||||
/// Create new headers source using given client.
|
||||
pub fn new(client: Client<C>) -> Self {
|
||||
HeadersSource {
|
||||
client,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain, P> Clone for HeadersSource<C, P> {
|
||||
fn clone(&self) -> Self {
|
||||
HeadersSource {
|
||||
client: self.client.clone(),
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: Chain, P: HeadersSyncPipeline> RelayClient for HeadersSource<C, P> {
|
||||
type Error = Error;
|
||||
|
||||
async fn reconnect(&mut self) -> Result<(), Error> {
|
||||
self.client.reconnect().await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P> SourceClient<P> for HeadersSource<C, P>
|
||||
where
|
||||
C: Chain,
|
||||
C::BlockNumber: relay_utils::BlockNumberBase,
|
||||
C::Header: Into<P::Header>,
|
||||
P: HeadersSyncPipeline<Extra = (), Completion = EncodedJustification, Hash = C::Hash, Number = C::BlockNumber>,
|
||||
P::Header: SourceHeader<C::Hash, C::BlockNumber>,
|
||||
{
|
||||
async fn best_block_number(&self) -> Result<P::Number, Error> {
|
||||
// we **CAN** continue to relay headers if source node is out of sync, because
|
||||
// target node may be missing headers that are already available at the source
|
||||
Ok(*self.client.best_header().await?.number())
|
||||
}
|
||||
|
||||
async fn header_by_hash(&self, hash: P::Hash) -> Result<P::Header, Error> {
|
||||
self.client
|
||||
.header_by_hash(hash)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn header_by_number(&self, number: P::Number) -> Result<P::Header, Error> {
|
||||
self.client
|
||||
.header_by_number(number)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn header_completion(&self, id: HeaderIdOf<P>) -> Result<(HeaderIdOf<P>, Option<P::Completion>), Error> {
|
||||
let hash = id.1;
|
||||
let signed_block = self.client.get_block(Some(hash)).await?;
|
||||
let grandpa_justification = signed_block.justification().cloned();
|
||||
|
||||
Ok((id, grandpa_justification))
|
||||
}
|
||||
|
||||
async fn header_extra(&self, id: HeaderIdOf<P>, _header: QueuedHeader<P>) -> Result<(HeaderIdOf<P>, ()), Error> {
|
||||
Ok((id, ()))
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Tools to interact with Substrate node using RPC methods.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod chain;
|
||||
mod client;
|
||||
mod error;
|
||||
mod rpc;
|
||||
mod sync_header;
|
||||
|
||||
pub mod finality_source;
|
||||
pub mod guard;
|
||||
pub mod headers_source;
|
||||
pub mod metrics;
|
||||
|
||||
pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme};
|
||||
pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet};
|
||||
pub use crate::error::{Error, Result};
|
||||
pub use crate::sync_header::SyncHeader;
|
||||
pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf};
|
||||
|
||||
/// Header id used by the chain.
|
||||
pub type HeaderIdOf<C> = relay_utils::HeaderId<HashOf<C>, BlockNumberOf<C>>;
|
||||
|
||||
/// Substrate-over-websocket connection params.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConnectionParams {
|
||||
/// Websocket server hostname.
|
||||
pub host: String,
|
||||
/// Websocket server TCP port.
|
||||
pub port: u16,
|
||||
/// Use secure websocket connection.
|
||||
pub secure: bool,
|
||||
}
|
||||
|
||||
impl Default for ConnectionParams {
|
||||
fn default() -> Self {
|
||||
ConnectionParams {
|
||||
host: "localhost".into(),
|
||||
port: 9944,
|
||||
secure: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::chain::Chain;
|
||||
use crate::client::Client;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use codec::Decode;
|
||||
use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64};
|
||||
use sp_core::storage::StorageKey;
|
||||
use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Storage value update interval (in blocks).
|
||||
const UPDATE_INTERVAL_IN_BLOCKS: u32 = 5;
|
||||
|
||||
/// Metric that represents fixed-point runtime storage value as float gauge.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FloatStorageValueMetric<C: Chain, T: Clone> {
|
||||
client: Client<C>,
|
||||
storage_key: StorageKey,
|
||||
maybe_default_value: Option<T>,
|
||||
metric: Gauge<F64>,
|
||||
}
|
||||
|
||||
impl<C: Chain, T: Decode + FixedPointNumber> FloatStorageValueMetric<C, T> {
|
||||
/// Create new metric.
|
||||
pub fn new(
|
||||
registry: &Registry,
|
||||
prefix: Option<&str>,
|
||||
client: Client<C>,
|
||||
storage_key: StorageKey,
|
||||
maybe_default_value: Option<T>,
|
||||
name: String,
|
||||
help: String,
|
||||
) -> Result<Self, PrometheusError> {
|
||||
Ok(FloatStorageValueMetric {
|
||||
client,
|
||||
storage_key,
|
||||
maybe_default_value,
|
||||
metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: Chain, T> StandaloneMetrics for FloatStorageValueMetric<C, T>
|
||||
where
|
||||
T: 'static + Decode + Send + Sync + FixedPointNumber,
|
||||
{
|
||||
fn update_interval(&self) -> Duration {
|
||||
C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS
|
||||
}
|
||||
|
||||
async fn update(&self) {
|
||||
relay_utils::metrics::set_gauge_value(
|
||||
&self.metric,
|
||||
self.client
|
||||
.storage_value::<T>(self.storage_key.clone())
|
||||
.await
|
||||
.map(|maybe_storage_value| {
|
||||
maybe_storage_value.or(self.maybe_default_value).map(|storage_value| {
|
||||
storage_value.into_inner().unique_saturated_into() as f64
|
||||
/ T::DIV.unique_saturated_into() as f64
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//! Contains several Substrate-specific metrics that may be exposed by relay.
|
||||
|
||||
pub use float_storage_value::FloatStorageValueMetric;
|
||||
pub use storage_proof_overhead::StorageProofOverheadMetric;
|
||||
|
||||
mod float_storage_value;
|
||||
mod storage_proof_overhead;
|
||||
@@ -1,104 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::chain::Chain;
|
||||
use crate::client::Client;
|
||||
use crate::error::Error;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, U64};
|
||||
use sp_core::storage::StorageKey;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use sp_storage::well_known_keys::CODE;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Storage proof overhead update interval (in blocks).
|
||||
const UPDATE_INTERVAL_IN_BLOCKS: u32 = 100;
|
||||
|
||||
/// Metric that represents extra size of storage proof as unsigned integer gauge.
|
||||
///
|
||||
/// There's one thing to keep in mind when using this metric: the overhead may be slightly
|
||||
/// different for other values, but this metric gives a good estimation.
|
||||
#[derive(Debug)]
|
||||
pub struct StorageProofOverheadMetric<C: Chain> {
|
||||
client: Client<C>,
|
||||
metric: Gauge<U64>,
|
||||
}
|
||||
|
||||
impl<C: Chain> Clone for StorageProofOverheadMetric<C> {
|
||||
fn clone(&self) -> Self {
|
||||
StorageProofOverheadMetric {
|
||||
client: self.client.clone(),
|
||||
metric: self.metric.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain> StorageProofOverheadMetric<C> {
|
||||
/// Create new metric instance with given name and help.
|
||||
pub fn new(
|
||||
registry: &Registry,
|
||||
prefix: Option<&str>,
|
||||
client: Client<C>,
|
||||
name: String,
|
||||
help: String,
|
||||
) -> Result<Self, PrometheusError> {
|
||||
Ok(StorageProofOverheadMetric {
|
||||
client,
|
||||
metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns approximate storage proof size overhead.
|
||||
async fn compute_storage_proof_overhead(&self) -> Result<usize, Error> {
|
||||
let best_header_hash = self.client.best_finalized_header_hash().await?;
|
||||
let best_header = self.client.header_by_hash(best_header_hash).await?;
|
||||
|
||||
let storage_proof = self
|
||||
.client
|
||||
.prove_storage(vec![StorageKey(CODE.to_vec())], best_header_hash)
|
||||
.await?;
|
||||
let storage_proof_size: usize = storage_proof.clone().iter_nodes().map(|n| n.len()).sum();
|
||||
|
||||
let storage_value_reader =
|
||||
bp_runtime::StorageProofChecker::<C::Hasher>::new(*best_header.state_root(), storage_proof)
|
||||
.map_err(Error::StorageProofError)?;
|
||||
let maybe_encoded_storage_value = storage_value_reader
|
||||
.read_value(CODE)
|
||||
.map_err(Error::StorageProofError)?;
|
||||
let encoded_storage_value_size = maybe_encoded_storage_value
|
||||
.ok_or(Error::MissingMandatoryCodeEntry)?
|
||||
.len();
|
||||
|
||||
Ok(storage_proof_size - encoded_storage_value_size)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: Chain> StandaloneMetrics for StorageProofOverheadMetric<C> {
|
||||
fn update_interval(&self) -> Duration {
|
||||
C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS
|
||||
}
|
||||
|
||||
async fn update(&self) {
|
||||
relay_utils::metrics::set_gauge_value(
|
||||
&self.metric,
|
||||
self.compute_storage_proof_overhead()
|
||||
.await
|
||||
.map(|overhead| Some(overhead as u64)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! The most generic Substrate node RPC interface.
|
||||
|
||||
use crate::chain::Chain;
|
||||
|
||||
use sc_rpc_api::{state::ReadProof, system::Health};
|
||||
use sp_core::{
|
||||
storage::{StorageData, StorageKey},
|
||||
Bytes,
|
||||
};
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
jsonrpsee_proc_macros::rpc_client_api! {
|
||||
pub(crate) Substrate<C: Chain> {
|
||||
#[rpc(method = "system_health", positional_params)]
|
||||
fn system_health() -> Health;
|
||||
#[rpc(method = "chain_getHeader", positional_params)]
|
||||
fn chain_get_header(block_hash: Option<C::Hash>) -> C::Header;
|
||||
#[rpc(method = "chain_getFinalizedHead", positional_params)]
|
||||
fn chain_get_finalized_head() -> C::Hash;
|
||||
#[rpc(method = "chain_getBlock", positional_params)]
|
||||
fn chain_get_block(block_hash: Option<C::Hash>) -> C::SignedBlock;
|
||||
#[rpc(method = "chain_getBlockHash", positional_params)]
|
||||
fn chain_get_block_hash(block_number: Option<C::BlockNumber>) -> C::Hash;
|
||||
#[rpc(method = "system_accountNextIndex", positional_params)]
|
||||
fn system_account_next_index(account_id: C::AccountId) -> C::Index;
|
||||
#[rpc(method = "author_submitExtrinsic", positional_params)]
|
||||
fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash;
|
||||
#[rpc(method = "state_call", positional_params)]
|
||||
fn state_call(method: String, data: Bytes, at_block: Option<C::Hash>) -> Bytes;
|
||||
#[rpc(method = "state_getStorage", positional_params)]
|
||||
fn state_get_storage(key: StorageKey) -> Option<StorageData>;
|
||||
#[rpc(method = "state_getReadProof", positional_params)]
|
||||
fn state_prove_storage(keys: Vec<StorageKey>, hash: Option<C::Hash>) -> ReadProof<C::Hash>;
|
||||
#[rpc(method = "state_getRuntimeVersion", positional_params)]
|
||||
fn state_runtime_version() -> RuntimeVersion;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use bp_header_chain::find_grandpa_authorities_scheduled_change;
|
||||
use finality_relay::SourceHeader as FinalitySourceHeader;
|
||||
use headers_relay::sync_types::SourceHeader;
|
||||
use num_traits::{CheckedSub, One};
|
||||
use relay_utils::HeaderId;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
|
||||
/// Generic wrapper for `sp_runtime::traits::Header` based headers, that
|
||||
/// implements `headers_relay::sync_types::SourceHeader` and may be used in headers sync directly.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SyncHeader<Header>(Header);
|
||||
|
||||
impl<Header> SyncHeader<Header> {
|
||||
/// Extracts wrapped header from self.
|
||||
pub fn into_inner(self) -> Header {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Header> std::ops::Deref for SyncHeader<Header> {
|
||||
type Target = Header;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Header> From<Header> for SyncHeader<Header> {
|
||||
fn from(header: Header) -> Self {
|
||||
Self(header)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Header: HeaderT> SourceHeader<Header::Hash, Header::Number> for SyncHeader<Header> {
|
||||
fn id(&self) -> HeaderId<Header::Hash, Header::Number> {
|
||||
relay_utils::HeaderId(*self.0.number(), self.hash())
|
||||
}
|
||||
|
||||
fn parent_id(&self) -> HeaderId<Header::Hash, Header::Number> {
|
||||
relay_utils::HeaderId(
|
||||
self.number()
|
||||
.checked_sub(&One::one())
|
||||
.expect("should never be called for genesis header"),
|
||||
*self.parent_hash(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Header: HeaderT> FinalitySourceHeader<Header::Number> for SyncHeader<Header> {
|
||||
fn number(&self) -> Header::Number {
|
||||
*self.0.number()
|
||||
}
|
||||
|
||||
fn is_mandatory(&self) -> bool {
|
||||
find_grandpa_authorities_scheduled_change(&self.0).is_some()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user