mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 03:41:02 +00:00
staking miner: reuse ws conn for remote-ext (#4849)
* staking miner: use config for emergency solution Fixes #4678 * bump jsonrpsee * run `monitor_cmd_for` until the connection is closed * new tokio task for submit_and_watch xt * re-use header subscription * update jsonrpsee + simplify code * revert polkadot runtime changes * fix grumbles * Update utils/staking-miner/src/monitor.rs * staking miner: reuse ws conn for remote-ext * Revert "revert polkadot runtime changes" This reverts commit 5fddbbec40702c122b079526915cabac8facdbc1. * cargo fmt * revert unintentional change * revert unintentional change * add type SharedRpcClient * cargo fmt * fix nits * spelling * use tracing_subcriber and cleanup * remove some needless clones * fix some nits * fix spellcheck
This commit is contained in:
Generated
+33
-6
@@ -4111,6 +4111,15 @@ dependencies = [
|
|||||||
"regex-automata",
|
"regex-automata",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@@ -9170,7 +9179,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber 0.2.25",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10264,7 +10273,7 @@ dependencies = [
|
|||||||
"sp-std",
|
"sp-std",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber 0.2.25",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10379,7 +10388,6 @@ name = "staking-miner"
|
|||||||
version = "0.9.17"
|
version = "0.9.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger 0.9.0",
|
|
||||||
"frame-election-provider-support",
|
"frame-election-provider-support",
|
||||||
"frame-support",
|
"frame-support",
|
||||||
"frame-system",
|
"frame-system",
|
||||||
@@ -10407,6 +10415,7 @@ dependencies = [
|
|||||||
"sub-tokens",
|
"sub-tokens",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing-subscriber 0.3.8",
|
||||||
"westend-runtime",
|
"westend-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -10782,9 +10791,9 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
@@ -11086,7 +11095,7 @@ dependencies = [
|
|||||||
"ansi_term",
|
"ansi_term",
|
||||||
"chrono",
|
"chrono",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"matchers",
|
"matchers 0.0.1",
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.11.2",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -11100,6 +11109,24 @@ dependencies = [
|
|||||||
"tracing-serde",
|
"tracing-serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74786ce43333fcf51efe947aed9718fbe46d5c7328ec3f1029e818083966d9aa"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"lazy_static",
|
||||||
|
"matchers 0.1.0",
|
||||||
|
"regex",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "trie-db"
|
name = "trie-db"
|
||||||
version = "0.23.1"
|
version = "0.23.1"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "3.0", features = ["derive", "env"] }
|
clap = { version = "3.0", features = ["derive", "env"] }
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
||||||
env_logger = "0.9.0"
|
tracing-subscriber = { version = "0.3.8", features = ["env-filter"] }
|
||||||
jsonrpsee = { version = "0.8", features = ["ws-client"] }
|
jsonrpsee = { version = "0.8", features = ["ws-client", "macros"] }
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
paste = "1.0.6"
|
paste = "1.0.6"
|
||||||
serde = "1.0.136"
|
serde = "1.0.136"
|
||||||
|
|||||||
@@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
//! The dry-run command.
|
//! The dry-run command.
|
||||||
|
|
||||||
use crate::{
|
use crate::{prelude::*, rpc::*, signer::Signer, DryRunConfig, Error, SharedRpcClient};
|
||||||
prelude::*, rpc_helpers::*, signer::Signer, DryRunConfig, Error, SharedConfig, WsClient,
|
|
||||||
};
|
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::traits::Currency;
|
use frame_support::traits::Currency;
|
||||||
use jsonrpsee::rpc_params;
|
use sp_core::Bytes;
|
||||||
use sp_npos_elections::ElectionScore;
|
use sp_npos_elections::ElectionScore;
|
||||||
|
|
||||||
/// Forcefully create the snapshot. This can be used to compute the election at anytime.
|
/// Forcefully create the snapshot. This can be used to compute the election at anytime.
|
||||||
@@ -39,10 +37,10 @@ fn force_create_snapshot<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>>
|
|||||||
|
|
||||||
/// Helper method to print the encoded size of the snapshot.
|
/// Helper method to print the encoded size of the snapshot.
|
||||||
async fn print_info<T: EPM::Config>(
|
async fn print_info<T: EPM::Config>(
|
||||||
client: &WsClient,
|
rpc: &SharedRpcClient,
|
||||||
ext: &mut Ext,
|
ext: &mut Ext,
|
||||||
raw_solution: &EPM::RawSolution<EPM::SolutionOf<T>>,
|
raw_solution: &EPM::RawSolution<EPM::SolutionOf<T>>,
|
||||||
extrinsic: sp_core::Bytes,
|
extrinsic: &Bytes,
|
||||||
) where
|
) where
|
||||||
<T as EPM::Config>::Currency: Currency<T::AccountId, Balance = Balance>,
|
<T as EPM::Config>::Currency: Currency<T::AccountId, Balance = Balance>,
|
||||||
{
|
{
|
||||||
@@ -79,12 +77,8 @@ async fn print_info<T: EPM::Config>(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let info = rpc::<pallet_transaction_payment::RuntimeDispatchInfo<Balance>>(
|
let info = rpc.payment_query_info(&extrinsic, None).await;
|
||||||
client,
|
|
||||||
"payment_queryInfo",
|
|
||||||
rpc_params! { extrinsic },
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
log::info!(
|
log::info!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"payment_queryInfo: (fee = {}) {:?}",
|
"payment_queryInfo: (fee = {}) {:?}",
|
||||||
@@ -116,14 +110,13 @@ fn find_threshold<T: EPM::Config>(ext: &mut Ext, count: usize) {
|
|||||||
macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||||
/// Execute the dry-run command.
|
/// Execute the dry-run command.
|
||||||
pub(crate) async fn [<dry_run_cmd_ $runtime>](
|
pub(crate) async fn [<dry_run_cmd_ $runtime>](
|
||||||
client: &WsClient,
|
rpc: SharedRpcClient,
|
||||||
shared: SharedConfig,
|
|
||||||
config: DryRunConfig,
|
config: DryRunConfig,
|
||||||
signer: Signer,
|
signer: Signer,
|
||||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
let mut ext = crate::create_election_ext::<Runtime, Block>(
|
let mut ext = crate::create_election_ext::<Runtime, Block>(
|
||||||
shared.uri.clone(),
|
rpc.clone(),
|
||||||
config.at,
|
config.at,
|
||||||
vec!["Staking".to_string(), "System".to_string()],
|
vec!["Staking".to_string(), "System".to_string()],
|
||||||
).await?;
|
).await?;
|
||||||
@@ -131,7 +124,7 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
|||||||
|
|
||||||
let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext, false)?;
|
let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext, false)?;
|
||||||
|
|
||||||
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, config.at)
|
let nonce = crate::get_account_info::<Runtime>(&rpc, &signer.account, config.at)
|
||||||
.await?
|
.await?
|
||||||
.map(|i| i.nonce)
|
.map(|i| i.nonce)
|
||||||
.expect("signer account is checked to exist upon startup; it can only die if it \
|
.expect("signer account is checked to exist upon startup; it can only die if it \
|
||||||
@@ -143,7 +136,7 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
|||||||
let extrinsic = ext.execute_with(|| create_uxt(raw_solution.clone(), witness, signer.clone(), nonce, tip, era));
|
let extrinsic = ext.execute_with(|| create_uxt(raw_solution.clone(), witness, signer.clone(), nonce, tip, era));
|
||||||
|
|
||||||
let bytes = sp_core::Bytes(extrinsic.encode().to_vec());
|
let bytes = sp_core::Bytes(extrinsic.encode().to_vec());
|
||||||
print_info::<Runtime>(client, &mut ext, &raw_solution, bytes.clone()).await;
|
print_info::<Runtime>(&rpc, &mut ext, &raw_solution, &bytes).await;
|
||||||
|
|
||||||
let feasibility_result = ext.execute_with(|| {
|
let feasibility_result = ext.execute_with(|| {
|
||||||
EPM::Pallet::<Runtime>::feasibility_check(raw_solution.clone(), EPM::ElectionCompute::Signed)
|
EPM::Pallet::<Runtime>::feasibility_check(raw_solution.clone(), EPM::ElectionCompute::Signed)
|
||||||
@@ -157,9 +150,8 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
|||||||
});
|
});
|
||||||
log::info!(target: LOG_TARGET, "dispatch result is {:?}", dispatch_result);
|
log::info!(target: LOG_TARGET, "dispatch result is {:?}", dispatch_result);
|
||||||
|
|
||||||
let outcome = rpc_decode::<sp_runtime::ApplyExtrinsicResult>(client, "system_dryRun", rpc_params!{ bytes })
|
let dry_run_fut = rpc.dry_run(&bytes, None);
|
||||||
.await
|
let outcome: sp_runtime::ApplyExtrinsicResult = await_request_and_decode(dry_run_fut).await.map_err::<Error<Runtime>, _>(Into::into)?;
|
||||||
.map_err::<Error<Runtime>, _>(Into::into)?;
|
|
||||||
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", outcome);
|
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", outcome);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
//! The emergency-solution command.
|
//! The emergency-solution command.
|
||||||
|
|
||||||
use crate::{prelude::*, EmergencySolutionConfig, Error, SharedConfig};
|
use crate::{prelude::*, EmergencySolutionConfig, Error, SharedRpcClient};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! {
|
macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||||
/// Execute the emergency-solution command.
|
/// Execute the emergency-solution command.
|
||||||
pub(crate) async fn [<emergency_solution_cmd_ $runtime>](
|
pub(crate) async fn [<emergency_solution_cmd_ $runtime>](
|
||||||
shared: SharedConfig,
|
client: SharedRpcClient,
|
||||||
config: EmergencySolutionConfig,
|
config: EmergencySolutionConfig,
|
||||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
|
|
||||||
let mut ext = crate::create_election_ext::<Runtime, Block>(shared.uri.clone(), config.at, vec![]).await?;
|
let mut ext = crate::create_election_ext::<Runtime, Block>(client, config.at, vec![]).await?;
|
||||||
let (raw_solution, _witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext, false)?;
|
let (raw_solution, _witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext, false)?;
|
||||||
|
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ mod dry_run;
|
|||||||
mod emergency_solution;
|
mod emergency_solution;
|
||||||
mod monitor;
|
mod monitor;
|
||||||
mod prelude;
|
mod prelude;
|
||||||
mod rpc_helpers;
|
mod rpc;
|
||||||
mod signer;
|
mod signer;
|
||||||
|
|
||||||
pub(crate) use prelude::*;
|
pub(crate) use prelude::*;
|
||||||
@@ -43,8 +43,12 @@ use frame_election_provider_support::NposSolver;
|
|||||||
use frame_support::traits::Get;
|
use frame_support::traits::Get;
|
||||||
use jsonrpsee::ws_client::{WsClient, WsClientBuilder};
|
use jsonrpsee::ws_client::{WsClient, WsClientBuilder};
|
||||||
use remote_externalities::{Builder, Mode, OnlineConfig};
|
use remote_externalities::{Builder, Mode, OnlineConfig};
|
||||||
|
use rpc::{RpcApiClient, SharedRpcClient};
|
||||||
use sp_npos_elections::ExtendedBalance;
|
use sp_npos_elections::ExtendedBalance;
|
||||||
use sp_runtime::{traits::Block as BlockT, DeserializeOwned};
|
use sp_runtime::{traits::Block as BlockT, DeserializeOwned};
|
||||||
|
use tracing_subscriber::{fmt, EnvFilter};
|
||||||
|
|
||||||
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
pub(crate) enum AnyRuntime {
|
pub(crate) enum AnyRuntime {
|
||||||
Polkadot,
|
Polkadot,
|
||||||
@@ -90,10 +94,10 @@ macro_rules! construct_runtime_prelude {
|
|||||||
let extra: SignedExtra = crate::[<signed_ext_builder_ $runtime>](nonce, tip, era);
|
let extra: SignedExtra = crate::[<signed_ext_builder_ $runtime>](nonce, tip, era);
|
||||||
let raw_payload = SignedPayload::new(call, extra).expect("creating signed payload infallible; qed.");
|
let raw_payload = SignedPayload::new(call, extra).expect("creating signed payload infallible; qed.");
|
||||||
let signature = raw_payload.using_encoded(|payload| {
|
let signature = raw_payload.using_encoded(|payload| {
|
||||||
pair.clone().sign(payload)
|
pair.sign(payload)
|
||||||
});
|
});
|
||||||
let (call, extra, _) = raw_payload.deconstruct();
|
let (call, extra, _) = raw_payload.deconstruct();
|
||||||
let address = <Runtime as frame_system::Config>::Lookup::unlookup(account.clone());
|
let address = <Runtime as frame_system::Config>::Lookup::unlookup(account);
|
||||||
let extrinsic = UncheckedExtrinsic::new_signed(call, address, signature.into(), extra);
|
let extrinsic = UncheckedExtrinsic::new_signed(call, address, signature.into(), extra);
|
||||||
log::debug!(
|
log::debug!(
|
||||||
target: crate::LOG_TARGET, "constructed extrinsic {} with length {}",
|
target: crate::LOG_TARGET, "constructed extrinsic {} with length {}",
|
||||||
@@ -229,7 +233,7 @@ macro_rules! any_runtime_unit {
|
|||||||
enum Error<T: EPM::Config> {
|
enum Error<T: EPM::Config> {
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
JsonRpsee(#[from] jsonrpsee::core::Error),
|
JsonRpsee(#[from] jsonrpsee::core::Error),
|
||||||
RpcHelperError(#[from] rpc_helpers::RpcHelperError),
|
RpcHelperError(#[from] rpc::RpcHelperError),
|
||||||
Codec(#[from] codec::Error),
|
Codec(#[from] codec::Error),
|
||||||
Crypto(sp_core::crypto::SecretStringError),
|
Crypto(sp_core::crypto::SecretStringError),
|
||||||
RemoteExternalities(&'static str),
|
RemoteExternalities(&'static str),
|
||||||
@@ -368,7 +372,7 @@ struct Opt {
|
|||||||
/// Build the Ext at hash with all the data of `ElectionProviderMultiPhase` and any additional
|
/// Build the Ext at hash with all the data of `ElectionProviderMultiPhase` and any additional
|
||||||
/// pallets.
|
/// pallets.
|
||||||
async fn create_election_ext<T: EPM::Config, B: BlockT + DeserializeOwned>(
|
async fn create_election_ext<T: EPM::Config, B: BlockT + DeserializeOwned>(
|
||||||
uri: String,
|
client: SharedRpcClient,
|
||||||
at: Option<B::Hash>,
|
at: Option<B::Hash>,
|
||||||
additional: Vec<String>,
|
additional: Vec<String>,
|
||||||
) -> Result<Ext, Error<T>> {
|
) -> Result<Ext, Error<T>> {
|
||||||
@@ -381,7 +385,7 @@ async fn create_election_ext<T: EPM::Config, B: BlockT + DeserializeOwned>(
|
|||||||
pallets.extend(additional);
|
pallets.extend(additional);
|
||||||
Builder::<B>::new()
|
Builder::<B>::new()
|
||||||
.mode(Mode::Online(OnlineConfig {
|
.mode(Mode::Online(OnlineConfig {
|
||||||
transport: uri.into(),
|
transport: client.into_inner().into(),
|
||||||
at,
|
at,
|
||||||
pallets,
|
pallets,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -493,13 +497,13 @@ fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
|
pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
|
||||||
client: &WsClient,
|
rpc: &SharedRpcClient,
|
||||||
) -> Result<(), Error<T>> {
|
) -> Result<(), Error<T>> {
|
||||||
let linked_version = T::Version::get();
|
let linked_version = T::Version::get();
|
||||||
let on_chain_version =
|
let on_chain_version = rpc
|
||||||
rpc_helpers::rpc::<sp_version::RuntimeVersion>(client, "state_getRuntimeVersion", None)
|
.runtime_version(None)
|
||||||
.await
|
.await
|
||||||
.expect("runtime version RPC should always work; qed");
|
.expect("runtime version RPC should always work; qed");
|
||||||
|
|
||||||
log::debug!(target: LOG_TARGET, "linked version {:?}", linked_version);
|
log::debug!(target: LOG_TARGET, "linked version {:?}", linked_version);
|
||||||
log::debug!(target: LOG_TARGET, "on-chain version {:?}", on_chain_version);
|
log::debug!(target: LOG_TARGET, "on-chain version {:?}", on_chain_version);
|
||||||
@@ -517,20 +521,13 @@ pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
env_logger::Builder::from_default_env()
|
fmt().with_env_filter(EnvFilter::from_default_env()).init();
|
||||||
.format_module_path(true)
|
|
||||||
.format_level(true)
|
|
||||||
.init();
|
|
||||||
let Opt { shared, command } = Opt::parse();
|
let Opt { shared, command } = Opt::parse();
|
||||||
log::debug!(target: LOG_TARGET, "attempting to connect to {:?}", shared.uri);
|
log::debug!(target: LOG_TARGET, "attempting to connect to {:?}", shared.uri);
|
||||||
|
|
||||||
let client = loop {
|
let rpc = loop {
|
||||||
let maybe_client = WsClientBuilder::default()
|
match SharedRpcClient::new(&shared.uri).await {
|
||||||
.connection_timeout(std::time::Duration::new(20, 0))
|
|
||||||
.max_request_body_size(u32::MAX)
|
|
||||||
.build(&shared.uri)
|
|
||||||
.await;
|
|
||||||
match maybe_client {
|
|
||||||
Ok(client) => break client,
|
Ok(client) => break client,
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@@ -538,14 +535,12 @@ async fn main() {
|
|||||||
"failed to connect to client due to {:?}, retrying soon..",
|
"failed to connect to client due to {:?}, retrying soon..",
|
||||||
why
|
why
|
||||||
);
|
);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(2500));
|
tokio::time::sleep(std::time::Duration::from_millis(2500)).await;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let chain = rpc_helpers::rpc::<String>(&client, "system_chain", None)
|
let chain: String = rpc.system_chain().await.expect("system_chain infallible; qed.");
|
||||||
.await
|
|
||||||
.expect("system_chain infallible; qed.");
|
|
||||||
match chain.to_lowercase().as_str() {
|
match chain.to_lowercase().as_str() {
|
||||||
"polkadot" | "development" => {
|
"polkadot" | "development" => {
|
||||||
sp_core::crypto::set_default_ss58_version(
|
sp_core::crypto::set_default_ss58_version(
|
||||||
@@ -591,26 +586,26 @@ async fn main() {
|
|||||||
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);
|
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);
|
||||||
|
|
||||||
any_runtime_unit! {
|
any_runtime_unit! {
|
||||||
check_versions::<Runtime>(&client).await
|
check_versions::<Runtime>(&rpc).await
|
||||||
};
|
};
|
||||||
|
|
||||||
let signer_account = any_runtime! {
|
let signer_account = any_runtime! {
|
||||||
signer::signer_uri_from_string::<Runtime>(&shared.seed, &client)
|
signer::signer_uri_from_string::<Runtime>(&shared.seed, &rpc)
|
||||||
.await
|
.await
|
||||||
.expect("Provided account is invalid, terminating.")
|
.expect("Provided account is invalid, terminating.")
|
||||||
};
|
};
|
||||||
|
|
||||||
let outcome = any_runtime! {
|
let outcome = any_runtime! {
|
||||||
match command.clone() {
|
match command {
|
||||||
Command::Monitor(c) => monitor_cmd(client, shared, c, signer_account).await
|
Command::Monitor(cmd) => monitor_cmd(rpc, cmd, signer_account).await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
log::error!(target: LOG_TARGET, "Monitor error: {:?}", e);
|
log::error!(target: LOG_TARGET, "Monitor error: {:?}", e);
|
||||||
}),
|
}),
|
||||||
Command::DryRun(c) => dry_run_cmd(&client, shared, c, signer_account).await
|
Command::DryRun(cmd) => dry_run_cmd(rpc, cmd, signer_account).await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
log::error!(target: LOG_TARGET, "DryRun error: {:?}", e);
|
log::error!(target: LOG_TARGET, "DryRun error: {:?}", e);
|
||||||
}),
|
}),
|
||||||
Command::EmergencySolution(c) => emergency_solution_cmd(shared.clone(), c).await
|
Command::EmergencySolution(cmd) => emergency_solution_cmd(rpc, cmd).await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e);
|
log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -16,28 +16,21 @@
|
|||||||
|
|
||||||
//! The monitor command.
|
//! The monitor command.
|
||||||
|
|
||||||
use crate::{prelude::*, rpc_helpers::*, signer::Signer, Error, MonitorConfig, SharedConfig};
|
use crate::{prelude::*, rpc::*, signer::Signer, Error, MonitorConfig, SharedRpcClient};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use jsonrpsee::{
|
use jsonrpsee::core::Error as RpcError;
|
||||||
core::{
|
|
||||||
client::{Subscription, SubscriptionClientT},
|
|
||||||
Error as RpcError,
|
|
||||||
},
|
|
||||||
rpc_params,
|
|
||||||
ws_client::WsClient,
|
|
||||||
};
|
|
||||||
use sc_transaction_pool_api::TransactionStatus;
|
use sc_transaction_pool_api::TransactionStatus;
|
||||||
use sp_core::storage::StorageKey;
|
use sp_core::storage::StorageKey;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
/// Ensure that now is the signed phase.
|
/// Ensure that now is the signed phase.
|
||||||
async fn ensure_signed_phase<T: EPM::Config, B: BlockT>(
|
async fn ensure_signed_phase<T: EPM::Config, B: BlockT<Hash = Hash>>(
|
||||||
client: &WsClient,
|
rpc: &SharedRpcClient,
|
||||||
at: B::Hash,
|
at: B::Hash,
|
||||||
) -> Result<(), Error<T>> {
|
) -> Result<(), Error<T>> {
|
||||||
let key = StorageKey(EPM::CurrentPhase::<T>::hashed_key().to_vec());
|
let key = StorageKey(EPM::CurrentPhase::<T>::hashed_key().to_vec());
|
||||||
let phase = get_storage::<EPM::Phase<BlockNumber>>(client, rpc_params! {key, at})
|
let phase = rpc
|
||||||
|
.get_storage_and_decode::<EPM::Phase<BlockNumber>>(&key, Some(at))
|
||||||
.await
|
.await
|
||||||
.map_err::<Error<T>, _>(Into::into)?
|
.map_err::<Error<T>, _>(Into::into)?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@@ -71,23 +64,21 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
|
|
||||||
/// The monitor command.
|
/// The monitor command.
|
||||||
pub(crate) async fn [<monitor_cmd_ $runtime>](
|
pub(crate) async fn [<monitor_cmd_ $runtime>](
|
||||||
client: WsClient,
|
rpc: SharedRpcClient,
|
||||||
shared: SharedConfig,
|
|
||||||
config: MonitorConfig,
|
config: MonitorConfig,
|
||||||
signer: Signer,
|
signer: Signer,
|
||||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
type StakingMinerError = Error<$crate::[<$runtime _runtime_exports>]::Runtime>;
|
type StakingMinerError = Error<$crate::[<$runtime _runtime_exports>]::Runtime>;
|
||||||
|
|
||||||
let (sub, unsub) = if config.listen == "head" {
|
let heads_subscription = ||
|
||||||
("chain_subscribeNewHeads", "chain_unsubscribeNewHeads")
|
if config.listen == "head" {
|
||||||
} else {
|
rpc.subscribe_new_heads()
|
||||||
("chain_subscribeFinalizedHeads", "chain_unsubscribeFinalizedHeads")
|
} else {
|
||||||
};
|
rpc.subscribe_finalized_heads()
|
||||||
|
};
|
||||||
|
|
||||||
let mut subscription: Subscription<Header> = client.subscribe(&sub, None, &unsub).await?;
|
let mut subscription = heads_subscription().await?;
|
||||||
|
|
||||||
let client = Arc::new(client);
|
|
||||||
let (tx, mut rx) = mpsc::unbounded_channel::<StakingMinerError>();
|
let (tx, mut rx) = mpsc::unbounded_channel::<StakingMinerError>();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -97,8 +88,8 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
Some(Ok(r)) => r,
|
Some(Ok(r)) => r,
|
||||||
// Custom `jsonrpsee` message sent by the server if the subscription was closed on the server side.
|
// Custom `jsonrpsee` message sent by the server if the subscription was closed on the server side.
|
||||||
Some(Err(RpcError::SubscriptionClosed(reason))) => {
|
Some(Err(RpcError::SubscriptionClosed(reason))) => {
|
||||||
log::warn!(target: LOG_TARGET, "subscription to {} terminated: {:?}. Retrying..", sub, reason);
|
log::warn!(target: LOG_TARGET, "subscription to `subscribeNewHeads/subscribeFinalizedHeads` terminated: {:?}. Retrying..", reason);
|
||||||
subscription = client.subscribe(&sub, None, &unsub).await?;
|
subscription = heads_subscription().await?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
@@ -109,8 +100,8 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
// - the connection was closed.
|
// - the connection was closed.
|
||||||
// - the subscription could not keep up with the server.
|
// - the subscription could not keep up with the server.
|
||||||
None => {
|
None => {
|
||||||
log::warn!(target: LOG_TARGET, "subscription to {} terminated. Retrying..", sub);
|
log::warn!(target: LOG_TARGET, "subscription to `subscribeNewHeads/subscribeFinalizedHeads` terminated. Retrying..");
|
||||||
subscription = client.subscribe(&sub, None, &unsub).await?;
|
subscription = heads_subscription().await?;
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,17 +117,17 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
// Spawn task and non-recoverable errors are sent back to the main task
|
// Spawn task and non-recoverable errors are sent back to the main task
|
||||||
// such as if the connection has been closed.
|
// such as if the connection has been closed.
|
||||||
tokio::spawn(
|
tokio::spawn(
|
||||||
send_and_watch_extrinsic(client.clone(), tx.clone(), at, signer.clone(), shared.clone(), config.clone())
|
send_and_watch_extrinsic(rpc.clone(), tx.clone(), at, signer.clone(), config.clone())
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct extrinsic at given block and watch it.
|
/// Construct extrinsic at given block and watch it.
|
||||||
async fn send_and_watch_extrinsic(
|
async fn send_and_watch_extrinsic(
|
||||||
client: Arc<WsClient>,
|
rpc: SharedRpcClient,
|
||||||
tx: mpsc::UnboundedSender<StakingMinerError>,
|
tx: mpsc::UnboundedSender<StakingMinerError>,
|
||||||
at: Header,
|
at: Header,
|
||||||
signer: Signer,
|
signer: Signer,
|
||||||
shared: SharedConfig,
|
|
||||||
config: MonitorConfig,
|
config: MonitorConfig,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -144,20 +135,20 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
log::trace!(target: LOG_TARGET, "new event at #{:?} ({:?})", at.number, hash);
|
log::trace!(target: LOG_TARGET, "new event at #{:?} ({:?})", at.number, hash);
|
||||||
|
|
||||||
// if the runtime version has changed, terminate.
|
// if the runtime version has changed, terminate.
|
||||||
if let Err(err) = crate::check_versions::<Runtime>(&*client).await {
|
if let Err(err) = crate::check_versions::<Runtime>(&rpc).await {
|
||||||
let _ = tx.send(err.into());
|
let _ = tx.send(err.into());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we prefer doing this check before fetching anything into a remote-ext.
|
// we prefer doing this check before fetching anything into a remote-ext.
|
||||||
if ensure_signed_phase::<Runtime, Block>(&*client, hash).await.is_err() {
|
if ensure_signed_phase::<Runtime, Block>(&rpc, hash).await.is_err() {
|
||||||
log::debug!(target: LOG_TARGET, "phase closed, not interested in this block at all.");
|
log::debug!(target: LOG_TARGET, "phase closed, not interested in this block at all.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab an externalities without staking, just the election snapshot.
|
// grab an externalities without staking, just the election snapshot.
|
||||||
let mut ext = match crate::create_election_ext::<Runtime, Block>(
|
let mut ext = match crate::create_election_ext::<Runtime, Block>(
|
||||||
shared.uri.clone(),
|
rpc.clone(),
|
||||||
Some(hash),
|
Some(hash),
|
||||||
vec![],
|
vec![],
|
||||||
).await {
|
).await {
|
||||||
@@ -184,7 +175,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
|
|
||||||
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
|
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
|
||||||
|
|
||||||
let nonce = match crate::get_account_info::<Runtime>(&*client, &signer.account, Some(hash)).await {
|
let nonce = match crate::get_account_info::<Runtime>(&rpc, &signer.account, Some(hash)).await {
|
||||||
Ok(maybe_account) => {
|
Ok(maybe_account) => {
|
||||||
let acc = maybe_account.expect(crate::signer::SIGNER_ACCOUNT_WILL_EXIST);
|
let acc = maybe_account.expect(crate::signer::SIGNER_ACCOUNT_WILL_EXIST);
|
||||||
acc.nonce
|
acc.nonce
|
||||||
@@ -209,13 +200,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
let extrinsic = ext.execute_with(|| create_uxt(raw_solution, witness, signer.clone(), nonce, tip, era));
|
let extrinsic = ext.execute_with(|| create_uxt(raw_solution, witness, signer.clone(), nonce, tip, era));
|
||||||
let bytes = sp_core::Bytes(extrinsic.encode());
|
let bytes = sp_core::Bytes(extrinsic.encode());
|
||||||
|
|
||||||
let mut tx_subscription: Subscription<
|
let mut tx_subscription = match rpc.watch_extrinsic(&bytes).await {
|
||||||
TransactionStatus<<Block as BlockT>::Hash, <Block as BlockT>::Hash>
|
|
||||||
> = match client.subscribe(
|
|
||||||
"author_submitAndWatchExtrinsic",
|
|
||||||
rpc_params! { bytes },
|
|
||||||
"author_unwatchExtrinsic"
|
|
||||||
).await {
|
|
||||||
Ok(sub) => sub,
|
Ok(sub) => sub,
|
||||||
Err(RpcError::RestartNeeded(e)) => {
|
Err(RpcError::RestartNeeded(e)) => {
|
||||||
let _ = tx.send(RpcError::RestartNeeded(e).into());
|
let _ = tx.send(RpcError::RestartNeeded(e).into());
|
||||||
@@ -267,11 +252,10 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
let key = StorageKey(
|
let key = StorageKey(
|
||||||
frame_support::storage::storage_prefix(b"System", b"Events").to_vec(),
|
frame_support::storage::storage_prefix(b"System", b"Events").to_vec(),
|
||||||
);
|
);
|
||||||
let key2 = key.clone();
|
|
||||||
|
|
||||||
let events = match get_storage::<
|
let events = match rpc.get_storage_and_decode::<
|
||||||
Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>,
|
Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>,
|
||||||
>(&*client, rpc_params! { key, hash })
|
>(&key, Some(hash))
|
||||||
.await {
|
.await {
|
||||||
Ok(rp) => rp.unwrap_or_default(),
|
Ok(rp) => rp.unwrap_or_default(),
|
||||||
Err(RpcHelperError::JsonRpsee(RpcError::RestartNeeded(e))) => {
|
Err(RpcHelperError::JsonRpsee(RpcError::RestartNeeded(e))) => {
|
||||||
@@ -281,7 +265,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
// Decoding or other RPC error => just terminate the task.
|
// Decoding or other RPC error => just terminate the task.
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(target: LOG_TARGET, "get_storage [key: {:?}, hash: {:?}] failed: {:?}; skip block: {}",
|
log::warn!(target: LOG_TARGET, "get_storage [key: {:?}, hash: {:?}] failed: {:?}; skip block: {}",
|
||||||
key2, hash, e, at.number
|
key, hash, e, at.number
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ pub type Balance = core_primitives::Balance;
|
|||||||
pub type Index = core_primitives::AccountIndex;
|
pub type Index = core_primitives::AccountIndex;
|
||||||
/// The hash type. We re-export it here, but we can easily get it from block as well.
|
/// The hash type. We re-export it here, but we can easily get it from block as well.
|
||||||
pub type Hash = core_primitives::Hash;
|
pub type Hash = core_primitives::Hash;
|
||||||
|
/// The header type. We re-export it here, but we can easily get it from block as well.
|
||||||
|
pub type Header = core_primitives::Header;
|
||||||
|
|
||||||
pub use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
pub use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
/// Default URI to connect to.
|
/// Default URI to connect to.
|
||||||
pub const DEFAULT_URI: &str = "wss://rpc.polkadot.io";
|
pub const DEFAULT_URI: &str = "wss://rpc.polkadot.io:443";
|
||||||
/// The logging target.
|
/// The logging target.
|
||||||
pub const LOG_TARGET: &str = "staking-miner";
|
pub const LOG_TARGET: &str = "staking-miner";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Polkadot.
|
||||||
|
|
||||||
|
// Polkadot 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.
|
||||||
|
|
||||||
|
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! JSON-RPC related types and helpers.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use jsonrpsee::{
|
||||||
|
core::{Error as RpcError, RpcResult},
|
||||||
|
proc_macros::rpc,
|
||||||
|
};
|
||||||
|
use pallet_transaction_payment::RuntimeDispatchInfo;
|
||||||
|
use sc_transaction_pool_api::TransactionStatus;
|
||||||
|
use sp_core::{storage::StorageKey, Bytes};
|
||||||
|
use sp_version::RuntimeVersion;
|
||||||
|
use std::{future::Future, time::Duration};
|
||||||
|
|
||||||
|
const MAX_CONNECTION_DURATION: Duration = Duration::from_secs(20);
|
||||||
|
const MAX_REQUEST_DURATION: Duration = Duration::from_secs(60);
|
||||||
|
|
||||||
|
#[derive(frame_support::DebugNoBound, thiserror::Error)]
|
||||||
|
pub(crate) enum RpcHelperError {
|
||||||
|
JsonRpsee(#[from] jsonrpsee::core::Error),
|
||||||
|
Codec(#[from] codec::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for RpcHelperError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
<RpcHelperError as std::fmt::Debug>::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rpc(client)]
|
||||||
|
pub trait RpcApi {
|
||||||
|
/// Fetch system name.
|
||||||
|
#[method(name = "system_chain")]
|
||||||
|
async fn system_chain(&self) -> RpcResult<String>;
|
||||||
|
|
||||||
|
/// Fetch a storage key.
|
||||||
|
#[method(name = "state_getStorage")]
|
||||||
|
async fn storage(&self, key: &StorageKey, hash: Option<Hash>) -> RpcResult<Option<Bytes>>;
|
||||||
|
|
||||||
|
/// Fetch the runtime version.
|
||||||
|
#[method(name = "state_getRuntimeVersion")]
|
||||||
|
async fn runtime_version(&self, at: Option<Hash>) -> RpcResult<RuntimeVersion>;
|
||||||
|
|
||||||
|
/// Fetch the payment query info.
|
||||||
|
#[method(name = "payment_queryInfo")]
|
||||||
|
async fn payment_query_info(
|
||||||
|
&self,
|
||||||
|
encoded_xt: &Bytes,
|
||||||
|
at: Option<&Hash>,
|
||||||
|
) -> RpcResult<RuntimeDispatchInfo<Balance>>;
|
||||||
|
|
||||||
|
/// Dry run an extrinsic at a given block. Return SCALE encoded [`sp_runtine::ApplyExtrinsicResult`].
|
||||||
|
#[method(name = "system_dryRun")]
|
||||||
|
async fn dry_run(&self, extrinsic: &Bytes, at: Option<Hash>) -> RpcResult<Bytes>;
|
||||||
|
|
||||||
|
/// Submit an extrinsic to watch.
|
||||||
|
///
|
||||||
|
/// See [`TransactionStatus`](sc_transaction_pool_api::TransactionStatus) for details on
|
||||||
|
/// transaction life cycle.
|
||||||
|
//
|
||||||
|
// TODO: https://github.com/paritytech/jsonrpsee/issues/698.
|
||||||
|
#[subscription(
|
||||||
|
name = "author_submitAndWatchExtrinsic" => "author_extrinsicUpdate",
|
||||||
|
item = TransactionStatus<Hash, Hash>,
|
||||||
|
)]
|
||||||
|
fn watch_extrinsic(&self, bytes: &Bytes) -> RpcResult<()>;
|
||||||
|
|
||||||
|
/// New head subscription.
|
||||||
|
#[subscription(
|
||||||
|
name = "chain_subscribeNewHeads" => "newHead",
|
||||||
|
item = Header
|
||||||
|
)]
|
||||||
|
fn subscribe_new_heads(&self) -> RpcResult<()>;
|
||||||
|
|
||||||
|
/// Finalized head subscription.
|
||||||
|
#[subscription(
|
||||||
|
name = "chain_subscribeFinalizedHeads" => "chain_finalizedHead",
|
||||||
|
item = Header
|
||||||
|
)]
|
||||||
|
fn subscribe_finalized_heads(&self) -> RpcResult<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a shared web-socket JSON-RPC client that can be cloned.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct SharedRpcClient(Arc<WsClient>);
|
||||||
|
|
||||||
|
impl Deref for SharedRpcClient {
|
||||||
|
type Target = WsClient;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedRpcClient {
|
||||||
|
/// Consume and extract the inner client.
|
||||||
|
pub fn into_inner(self) -> Arc<WsClient> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new shared JSON-RPC web-socket client.
|
||||||
|
pub(crate) async fn new(uri: &str) -> Result<Self, RpcError> {
|
||||||
|
let client = WsClientBuilder::default()
|
||||||
|
.connection_timeout(MAX_CONNECTION_DURATION)
|
||||||
|
.max_request_body_size(u32::MAX)
|
||||||
|
.request_timeout(MAX_REQUEST_DURATION)
|
||||||
|
.build(uri)
|
||||||
|
.await?;
|
||||||
|
Ok(Self(Arc::new(client)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a storage item and decode it as `T`.
|
||||||
|
///
|
||||||
|
/// # Return value:
|
||||||
|
///
|
||||||
|
/// The function returns:
|
||||||
|
///
|
||||||
|
/// * `Ok(Some(val))` if successful.
|
||||||
|
/// * `Ok(None)` if the storage item was not found.
|
||||||
|
/// * `Err(e)` if the JSON-RPC call failed.
|
||||||
|
pub(crate) async fn get_storage_and_decode<'a, T: codec::Decode>(
|
||||||
|
&self,
|
||||||
|
key: &StorageKey,
|
||||||
|
hash: Option<Hash>,
|
||||||
|
) -> Result<Option<T>, RpcHelperError> {
|
||||||
|
if let Some(bytes) = self.storage(key, hash).await? {
|
||||||
|
let decoded = <T as codec::Decode>::decode(&mut &*bytes.0)
|
||||||
|
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||||
|
Ok(Some(decoded))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes a future that returns `Bytes` and tries to decode those bytes into the type `Dec`.
|
||||||
|
/// Warning: don't use for storage, it will fail for non-existent storage items.
|
||||||
|
///
|
||||||
|
/// # Return value:
|
||||||
|
///
|
||||||
|
/// The function returns:
|
||||||
|
///
|
||||||
|
/// * `Ok(val)` if successful.
|
||||||
|
/// * `Err(RpcHelperError::JsonRpsee)` if the JSON-RPC call failed.
|
||||||
|
/// * `Err(RpcHelperError::Codec)` if `Bytes` could not be decoded.
|
||||||
|
pub(crate) async fn await_request_and_decode<'a, Dec: codec::Decode>(
|
||||||
|
req: impl Future<Output = Result<Bytes, RpcError>>,
|
||||||
|
) -> Result<Dec, RpcHelperError> {
|
||||||
|
let bytes = req.await?;
|
||||||
|
Dec::decode(&mut &*bytes.0).map_err::<RpcHelperError, _>(Into::into)
|
||||||
|
}
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Polkadot.
|
|
||||||
|
|
||||||
// Polkadot 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.
|
|
||||||
|
|
||||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Helper method for RPC.
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use jsonrpsee::core::client::ClientT;
|
|
||||||
pub(crate) use jsonrpsee::types::ParamsSer;
|
|
||||||
|
|
||||||
#[derive(frame_support::DebugNoBound, thiserror::Error)]
|
|
||||||
pub(crate) enum RpcHelperError {
|
|
||||||
JsonRpsee(#[from] jsonrpsee::core::Error),
|
|
||||||
Codec(#[from] codec::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for RpcHelperError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
<RpcHelperError as std::fmt::Debug>::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make the rpc request, returning `Ret`.
|
|
||||||
pub(crate) async fn rpc<'a, Ret: serde::de::DeserializeOwned>(
|
|
||||||
client: &WsClient,
|
|
||||||
method: &'a str,
|
|
||||||
params: Option<ParamsSer<'a>>,
|
|
||||||
) -> Result<Ret, RpcHelperError> {
|
|
||||||
client
|
|
||||||
.request::<Ret>(method, params)
|
|
||||||
.await
|
|
||||||
.map_err::<RpcHelperError, _>(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make the rpc request, decode the outcome into `Dec`. Don't use for storage, it will fail for
|
|
||||||
/// non-existent storage items.
|
|
||||||
pub(crate) async fn rpc_decode<'a, Dec: codec::Decode>(
|
|
||||||
client: &WsClient,
|
|
||||||
method: &'a str,
|
|
||||||
params: Option<ParamsSer<'a>>,
|
|
||||||
) -> Result<Dec, RpcHelperError> {
|
|
||||||
let bytes = rpc::<sp_core::Bytes>(client, method, params)
|
|
||||||
.await
|
|
||||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
|
||||||
<Dec as codec::Decode>::decode(&mut &*bytes.0).map_err::<RpcHelperError, _>(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the storage item.
|
|
||||||
pub(crate) async fn get_storage<'a, T: codec::Decode>(
|
|
||||||
client: &WsClient,
|
|
||||||
params: Option<ParamsSer<'a>>,
|
|
||||||
) -> Result<Option<T>, RpcHelperError> {
|
|
||||||
let maybe_bytes = rpc::<Option<sp_core::Bytes>>(client, "state_getStorage", params)
|
|
||||||
.await
|
|
||||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
|
||||||
if let Some(bytes) = maybe_bytes {
|
|
||||||
let decoded = <T as codec::Decode>::decode(&mut &*bytes.0)
|
|
||||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
|
||||||
Ok(Some(decoded))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
//! Wrappers around creating a signer account.
|
//! Wrappers around creating a signer account.
|
||||||
|
|
||||||
use crate::{prelude::*, rpc_helpers, AccountId, Error, Index, Pair, WsClient, LOG_TARGET};
|
use crate::{prelude::*, rpc::SharedRpcClient, AccountId, Error, Index, Pair, LOG_TARGET};
|
||||||
use sp_core::crypto::Pair as _;
|
use frame_system::AccountInfo;
|
||||||
|
use sp_core::{crypto::Pair as _, storage::StorageKey};
|
||||||
|
|
||||||
pub(crate) const SIGNER_ACCOUNT_WILL_EXIST: &str =
|
pub(crate) const SIGNER_ACCOUNT_WILL_EXIST: &str =
|
||||||
"signer account is checked to exist upon startup; it can only die if it transfers funds out \
|
"signer account is checked to exist upon startup; it can only die if it transfers funds out \
|
||||||
@@ -34,17 +35,14 @@ pub(crate) struct Signer {
|
|||||||
pub(crate) pair: Pair,
|
pub(crate) pair: Pair,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_account_info<T: frame_system::Config + EPM::Config>(
|
pub(crate) async fn get_account_info<T: frame_system::Config<Hash = Hash> + EPM::Config>(
|
||||||
client: &WsClient,
|
rpc: &SharedRpcClient,
|
||||||
who: &T::AccountId,
|
who: &T::AccountId,
|
||||||
maybe_at: Option<T::Hash>,
|
maybe_at: Option<T::Hash>,
|
||||||
) -> Result<Option<frame_system::AccountInfo<Index, T::AccountData>>, Error<T>> {
|
) -> Result<Option<AccountInfo<Index, T::AccountData>>, Error<T>> {
|
||||||
rpc_helpers::get_storage::<frame_system::AccountInfo<Index, T::AccountData>>(
|
rpc.get_storage_and_decode::<AccountInfo<Index, T::AccountData>>(
|
||||||
client,
|
&StorageKey(<frame_system::Account<T>>::hashed_key_for(&who)),
|
||||||
jsonrpsee::rpc_params! {
|
maybe_at,
|
||||||
sp_core::storage::StorageKey(<frame_system::Account<T>>::hashed_key_for(&who)),
|
|
||||||
maybe_at
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
@@ -56,10 +54,11 @@ pub(crate) async fn signer_uri_from_string<
|
|||||||
AccountId = AccountId,
|
AccountId = AccountId,
|
||||||
Index = Index,
|
Index = Index,
|
||||||
AccountData = pallet_balances::AccountData<Balance>,
|
AccountData = pallet_balances::AccountData<Balance>,
|
||||||
|
Hash = Hash,
|
||||||
> + EPM::Config,
|
> + EPM::Config,
|
||||||
>(
|
>(
|
||||||
seed: &str,
|
seed: &str,
|
||||||
client: &WsClient,
|
client: &SharedRpcClient,
|
||||||
) -> Result<Signer, Error<T>> {
|
) -> Result<Signer, Error<T>> {
|
||||||
let seed = seed.trim();
|
let seed = seed.trim();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user