feat: initialize Kurdistan SDK - independent fork of Polkadot SDK
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
[package]
|
||||
name = "sc-rpc-api"
|
||||
version = "0.33.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Substrate RPC interfaces."
|
||||
readme = "README.md"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { workspace = true, default-features = true }
|
||||
jsonrpsee = { features = [
|
||||
"client-core",
|
||||
"macros",
|
||||
"server-core",
|
||||
], workspace = true }
|
||||
sc-chain-spec = { workspace = true, default-features = true }
|
||||
sc-mixnet = { workspace = true, default-features = true }
|
||||
sc-transaction-pool-api = { workspace = true, default-features = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
serde = { features = ["derive"], workspace = true, default-features = true }
|
||||
serde_json = { workspace = true, default-features = true }
|
||||
sp-core = { workspace = true, default-features = true }
|
||||
sp-rpc = { workspace = true, default-features = true }
|
||||
sp-runtime = { workspace = true, default-features = true }
|
||||
sp-version = { workspace = true, default-features = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"sc-chain-spec/runtime-benchmarks",
|
||||
"sc-mixnet/runtime-benchmarks",
|
||||
"sc-transaction-pool-api/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
"sp-version/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
Substrate RPC interfaces.
|
||||
|
||||
A collection of RPC methods and subscriptions supported by all Substrate clients.
|
||||
|
||||
License: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
@@ -0,0 +1,186 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Authoring RPC module errors.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
use sp_runtime::transaction_validity::InvalidTransaction;
|
||||
|
||||
/// Author RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Author RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Client error.
|
||||
#[error("Client error: {}", .0)]
|
||||
Client(Box<dyn std::error::Error + Send + Sync>),
|
||||
/// Transaction pool error,
|
||||
#[error("Transaction pool error: {}", .0)]
|
||||
Pool(#[from] sc_transaction_pool_api::error::Error),
|
||||
/// Verification error
|
||||
#[error("Extrinsic verification error: {}", .0)]
|
||||
Verification(Box<dyn std::error::Error + Send + Sync>),
|
||||
/// Incorrect extrinsic format.
|
||||
#[error("Invalid extrinsic format: {}", .0)]
|
||||
BadFormat(#[from] codec::Error),
|
||||
/// Key type ID has an unknown format.
|
||||
#[error("Invalid key type ID format (should be of length four)")]
|
||||
BadKeyType,
|
||||
/// Some random issue with the key store. Shouldn't happen.
|
||||
#[error("The key store is unavailable")]
|
||||
KeystoreUnavailable,
|
||||
/// Invalid session keys encoding.
|
||||
#[error("Session keys are not encoded correctly")]
|
||||
InvalidSessionKeys,
|
||||
/// Call to an unsafe RPC was denied.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
}
|
||||
|
||||
/// Base code for all authorship errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::AUTHOR;
|
||||
/// Extrinsic has an invalid format.
|
||||
const BAD_FORMAT: i32 = BASE_ERROR + 1;
|
||||
/// Error during transaction verification in runtime.
|
||||
const VERIFICATION_ERROR: i32 = BASE_ERROR + 2;
|
||||
|
||||
/// Pool rejected the transaction as invalid
|
||||
const POOL_INVALID_TX: i32 = BASE_ERROR + 10;
|
||||
/// Cannot determine transaction validity.
|
||||
const POOL_UNKNOWN_VALIDITY: i32 = POOL_INVALID_TX + 1;
|
||||
/// The transaction is temporarily banned.
|
||||
const POOL_TEMPORARILY_BANNED: i32 = POOL_INVALID_TX + 2;
|
||||
/// The transaction is already in the pool
|
||||
const POOL_ALREADY_IMPORTED: i32 = POOL_INVALID_TX + 3;
|
||||
/// Transaction has too low priority to replace existing one in the pool.
|
||||
const POOL_TOO_LOW_PRIORITY: i32 = POOL_INVALID_TX + 4;
|
||||
/// Including this transaction would cause a dependency cycle.
|
||||
const POOL_CYCLE_DETECTED: i32 = POOL_INVALID_TX + 5;
|
||||
/// The transaction was not included to the pool because of the limits.
|
||||
const POOL_IMMEDIATELY_DROPPED: i32 = POOL_INVALID_TX + 6;
|
||||
/// The transaction was not included to the pool since it is unactionable,
|
||||
/// it is not propagable and the local node does not author blocks.
|
||||
const POOL_UNACTIONABLE: i32 = POOL_INVALID_TX + 8;
|
||||
/// Transaction does not provide any tags, so the pool can't identify it.
|
||||
const POOL_NO_TAGS: i32 = POOL_INVALID_TX + 9;
|
||||
/// Invalid block ID.
|
||||
const POOL_INVALID_BLOCK_ID: i32 = POOL_INVALID_TX + 10;
|
||||
/// The pool is not accepting future transactions.
|
||||
const POOL_FUTURE_TX: i32 = POOL_INVALID_TX + 11;
|
||||
/// Other error.
|
||||
const OTHER_ERR: i32 = BASE_ERROR + 40;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> ErrorObjectOwned {
|
||||
use sc_transaction_pool_api::error::Error as PoolError;
|
||||
|
||||
match e {
|
||||
Error::BadFormat(e) => ErrorObject::owned(
|
||||
BAD_FORMAT,
|
||||
format!("Extrinsic has invalid format: {}", e),
|
||||
None::<()>,
|
||||
),
|
||||
Error::Verification(e) => ErrorObject::owned(
|
||||
VERIFICATION_ERROR,
|
||||
format!("Verification Error: {}", e),
|
||||
Some(format!("{:?}", e)),
|
||||
),
|
||||
Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => {
|
||||
ErrorObject::owned(
|
||||
POOL_INVALID_TX,
|
||||
"Invalid Transaction",
|
||||
Some(format!("Custom error: {}", e)),
|
||||
)
|
||||
},
|
||||
Error::Pool(PoolError::InvalidTransaction(e)) => {
|
||||
let msg: &str = e.into();
|
||||
ErrorObject::owned(
|
||||
POOL_INVALID_TX,
|
||||
"Invalid Transaction",
|
||||
Some(msg),
|
||||
)
|
||||
},
|
||||
Error::Pool(PoolError::UnknownTransaction(e)) => {
|
||||
ErrorObject::owned(
|
||||
POOL_UNKNOWN_VALIDITY,
|
||||
"Unknown Transaction Validity",
|
||||
Some(format!("{:?}", e)),
|
||||
)
|
||||
},
|
||||
Error::Pool(PoolError::TemporarilyBanned) =>
|
||||
ErrorObject::owned(
|
||||
POOL_TEMPORARILY_BANNED,
|
||||
"Transaction is temporarily banned",
|
||||
None::<()>,
|
||||
),
|
||||
Error::Pool(PoolError::AlreadyImported(hash)) =>
|
||||
ErrorObject::owned(
|
||||
POOL_ALREADY_IMPORTED,
|
||||
"Transaction Already Imported",
|
||||
Some(format!("{:?}", hash)),
|
||||
),
|
||||
Error::Pool(PoolError::TooLowPriority { old, new }) => ErrorObject::owned(
|
||||
POOL_TOO_LOW_PRIORITY,
|
||||
format!("Priority is too low: ({} vs {})", old, new),
|
||||
Some("The transaction has too low priority to replace another transaction already in the pool.")
|
||||
),
|
||||
Error::Pool(PoolError::CycleDetected) =>
|
||||
ErrorObject::owned(
|
||||
POOL_CYCLE_DETECTED,
|
||||
"Cycle Detected",
|
||||
None::<()>
|
||||
),
|
||||
Error::Pool(PoolError::ImmediatelyDropped) => ErrorObject::owned(
|
||||
POOL_IMMEDIATELY_DROPPED,
|
||||
"Immediately Dropped",
|
||||
Some("The transaction couldn't enter the pool because of the limit"),
|
||||
),
|
||||
Error::Pool(PoolError::Unactionable) => ErrorObject::owned(
|
||||
POOL_UNACTIONABLE,
|
||||
"Unactionable",
|
||||
Some("The transaction is unactionable since it is not propagable and \
|
||||
the local node does not author blocks")
|
||||
),
|
||||
Error::Pool(PoolError::NoTagsProvided) => ErrorObject::owned(
|
||||
POOL_NO_TAGS,
|
||||
"No tags provided",
|
||||
Some("Transaction does not provide any tags, so the pool can't identify it")
|
||||
),
|
||||
Error::Pool(PoolError::InvalidBlockId(_)) =>
|
||||
ErrorObject::owned(
|
||||
POOL_INVALID_BLOCK_ID,
|
||||
"The provided block ID is not valid",
|
||||
None::<()>
|
||||
),
|
||||
Error::Pool(PoolError::RejectedFutureTransaction) => {
|
||||
ErrorObject::owned(
|
||||
POOL_FUTURE_TX,
|
||||
"The pool is not accepting future transactions",
|
||||
None::<()>,
|
||||
)
|
||||
},
|
||||
Error::UnsafeRpcCalled(e) => e.into(),
|
||||
other => ErrorObject::owned(
|
||||
OTHER_ERR,
|
||||
other.to_string(),
|
||||
None::<()>,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Extrinsic helpers for author RPC module.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::Bytes;
|
||||
|
||||
/// RPC Extrinsic or hash
|
||||
///
|
||||
/// Allows to refer to extrinsic either by its raw representation or its hash.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ExtrinsicOrHash<Hash> {
|
||||
/// The hash of the extrinsic.
|
||||
Hash(Hash),
|
||||
/// Raw extrinsic bytes.
|
||||
Extrinsic(Bytes),
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate block-author/full-node API.
|
||||
|
||||
pub mod error;
|
||||
pub mod hash;
|
||||
|
||||
use error::Error;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sc_transaction_pool_api::TransactionStatus;
|
||||
use sp_core::Bytes;
|
||||
|
||||
/// Substrate authoring RPC API
|
||||
#[rpc(client, server)]
|
||||
pub trait AuthorApi<Hash, BlockHash> {
|
||||
/// Submit hex-encoded extrinsic for inclusion in block.
|
||||
#[method(name = "author_submitExtrinsic")]
|
||||
async fn submit_extrinsic(&self, extrinsic: Bytes) -> Result<Hash, Error>;
|
||||
|
||||
/// Insert a key into the keystore.
|
||||
#[method(name = "author_insertKey", with_extensions)]
|
||||
fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> Result<(), Error>;
|
||||
|
||||
/// Generate new session keys and returns the corresponding public keys.
|
||||
#[method(name = "author_rotateKeys", with_extensions)]
|
||||
fn rotate_keys(&self) -> Result<Bytes, Error>;
|
||||
|
||||
/// Checks if the keystore has private keys for the given session public keys.
|
||||
///
|
||||
/// `session_keys` is the SCALE encoded session keys object from the runtime.
|
||||
///
|
||||
/// Returns `true` iff all private keys could be found.
|
||||
#[method(name = "author_hasSessionKeys", with_extensions)]
|
||||
fn has_session_keys(&self, session_keys: Bytes) -> Result<bool, Error>;
|
||||
|
||||
/// Checks if the keystore has private keys for the given public key and key type.
|
||||
///
|
||||
/// Returns `true` if a private key could be found.
|
||||
#[method(name = "author_hasKey", with_extensions)]
|
||||
fn has_key(&self, public_key: Bytes, key_type: String) -> Result<bool, Error>;
|
||||
|
||||
/// Returns all pending extrinsics, potentially grouped by sender.
|
||||
#[method(name = "author_pendingExtrinsics")]
|
||||
fn pending_extrinsics(&self) -> Result<Vec<Bytes>, Error>;
|
||||
|
||||
/// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting.
|
||||
#[method(name = "author_removeExtrinsic", with_extensions)]
|
||||
async fn remove_extrinsic(
|
||||
&self,
|
||||
bytes_or_hash: Vec<hash::ExtrinsicOrHash<Hash>>,
|
||||
) -> Result<Vec<Hash>, Error>;
|
||||
|
||||
/// Submit an extrinsic to watch.
|
||||
///
|
||||
/// See [`TransactionStatus`](sc_transaction_pool_api::TransactionStatus) for details on
|
||||
/// transaction life cycle.
|
||||
#[subscription(
|
||||
name = "author_submitAndWatchExtrinsic" => "author_extrinsicUpdate",
|
||||
unsubscribe = "author_unwatchExtrinsic",
|
||||
item = TransactionStatus<Hash, BlockHash>,
|
||||
)]
|
||||
fn watch_extrinsic(&self, bytes: Bytes);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Error helpers for Chain RPC module.
|
||||
|
||||
use jsonrpsee::types::{error::ErrorObject, ErrorObjectOwned};
|
||||
/// Chain RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Chain RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Client error.
|
||||
#[error("Client error: {}", .0)]
|
||||
Client(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
/// Other error type.
|
||||
#[error("{0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
/// Base error code for all chain errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::CHAIN;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> ErrorObjectOwned {
|
||||
match e {
|
||||
Error::Other(message) => ErrorObject::owned(BASE_ERROR + 1, message, None::<()>),
|
||||
e => ErrorObject::owned(BASE_ERROR + 2, e.to_string(), None::<()>),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate blockchain API.
|
||||
|
||||
pub mod error;
|
||||
|
||||
use error::Error;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sp_rpc::{list::ListOrValue, number::NumberOrHex};
|
||||
|
||||
#[rpc(client, server)]
|
||||
pub trait ChainApi<Number, Hash, Header, SignedBlock> {
|
||||
/// Get header.
|
||||
#[method(name = "chain_getHeader", blocking)]
|
||||
fn header(&self, hash: Option<Hash>) -> Result<Option<Header>, Error>;
|
||||
|
||||
/// Get header and body of a block.
|
||||
#[method(name = "chain_getBlock", blocking)]
|
||||
fn block(&self, hash: Option<Hash>) -> Result<Option<SignedBlock>, Error>;
|
||||
|
||||
/// Get hash of the n-th block in the canon chain.
|
||||
///
|
||||
/// By default returns latest block hash.
|
||||
#[method(name = "chain_getBlockHash", aliases = ["chain_getHead"], blocking)]
|
||||
fn block_hash(
|
||||
&self,
|
||||
hash: Option<ListOrValue<NumberOrHex>>,
|
||||
) -> Result<ListOrValue<Option<Hash>>, Error>;
|
||||
|
||||
/// Get hash of the last finalized block in the canon chain.
|
||||
#[method(name = "chain_getFinalizedHead", aliases = ["chain_getFinalisedHead"], blocking)]
|
||||
fn finalized_head(&self) -> Result<Hash, Error>;
|
||||
|
||||
/// All head subscription.
|
||||
#[subscription(
|
||||
name = "chain_subscribeAllHeads" => "chain_allHead",
|
||||
unsubscribe = "chain_unsubscribeAllHeads",
|
||||
item = Header
|
||||
)]
|
||||
fn subscribe_all_heads(&self);
|
||||
|
||||
/// New head subscription.
|
||||
#[subscription(
|
||||
name = "chain_subscribeNewHeads" => "chain_newHead",
|
||||
aliases = ["subscribe_newHead", "chain_subscribeNewHead"],
|
||||
unsubscribe = "chain_unsubscribeNewHeads",
|
||||
unsubscribe_aliases = ["unsubscribe_newHead", "chain_unsubscribeNewHead"],
|
||||
item = Header
|
||||
)]
|
||||
fn subscribe_new_heads(&self);
|
||||
|
||||
/// Finalized head subscription.
|
||||
#[subscription(
|
||||
name = "chain_subscribeFinalizedHeads" => "chain_finalizedHead",
|
||||
aliases = ["chain_subscribeFinalisedHeads"],
|
||||
unsubscribe = "chain_unsubscribeFinalizedHeads",
|
||||
unsubscribe_aliases = ["chain_unsubscribeFinalisedHeads"],
|
||||
item = Header
|
||||
)]
|
||||
fn subscribe_finalized_heads(&self);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate child state API
|
||||
use crate::state::{Error, ReadProof};
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sp_core::storage::{PrefixedStorageKey, StorageData, StorageKey};
|
||||
|
||||
/// Substrate child state API
|
||||
///
|
||||
/// Note that all `PrefixedStorageKey` are deserialized
|
||||
/// from json and not guaranteed valid.
|
||||
#[rpc(client, server)]
|
||||
pub trait ChildStateApi<Hash> {
|
||||
/// Returns the keys with prefix from a child storage, leave empty to get all the keys
|
||||
#[method(name = "childstate_getKeys", blocking)]
|
||||
#[deprecated(since = "2.0.0", note = "Please use `getKeysPaged` with proper paging support")]
|
||||
fn storage_keys(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
prefix: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<StorageKey>, Error>;
|
||||
|
||||
/// Returns the keys with prefix from a child storage with pagination support.
|
||||
/// Up to `count` keys will be returned.
|
||||
/// If `start_key` is passed, return next keys in storage in lexicographic order.
|
||||
#[method(name = "childstate_getKeysPaged", aliases = ["childstate_getKeysPagedAt"], blocking)]
|
||||
fn storage_keys_paged(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
prefix: Option<StorageKey>,
|
||||
count: u32,
|
||||
start_key: Option<StorageKey>,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<StorageKey>, Error>;
|
||||
|
||||
/// Returns a child storage entry at a specific block's state.
|
||||
#[method(name = "childstate_getStorage", blocking)]
|
||||
fn storage(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
key: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Option<StorageData>, Error>;
|
||||
|
||||
/// Returns child storage entries for multiple keys at a specific block's state.
|
||||
#[method(name = "childstate_getStorageEntries", blocking)]
|
||||
fn storage_entries(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
keys: Vec<StorageKey>,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<Option<StorageData>>, Error>;
|
||||
|
||||
/// Returns the hash of a child storage entry at a block's state.
|
||||
#[method(name = "childstate_getStorageHash", blocking)]
|
||||
fn storage_hash(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
key: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Option<Hash>, Error>;
|
||||
|
||||
/// Returns the size of a child storage entry at a block's state.
|
||||
#[method(name = "childstate_getStorageSize", blocking)]
|
||||
fn storage_size(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
key: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Option<u64>, Error>;
|
||||
|
||||
/// Returns proof of storage for child key entries at a specific block's state.
|
||||
#[method(name = "state_getChildReadProof", blocking)]
|
||||
fn read_child_proof(
|
||||
&self,
|
||||
child_storage_key: PrefixedStorageKey,
|
||||
keys: Vec<StorageKey>,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<ReadProof<Hash>, Error>;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Error helpers for Dev RPC module.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
|
||||
/// Dev RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Dev RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Failed to query specified block or its parent: Probably an invalid hash.
|
||||
#[error("Error while querying block: {0}")]
|
||||
BlockQueryError(Box<dyn std::error::Error + Send>),
|
||||
/// The re-execution of the specified block failed.
|
||||
#[error("Failed to re-execute the specified block")]
|
||||
BlockExecutionFailed,
|
||||
/// Failed to extract the proof.
|
||||
#[error("Failed to extract the proof")]
|
||||
ProofExtractionFailed,
|
||||
/// The witness compaction failed.
|
||||
#[error("Failed to create to compact the witness")]
|
||||
WitnessCompactionFailed,
|
||||
/// The method is marked as unsafe but unsafe flag wasn't supplied on the CLI.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
}
|
||||
|
||||
/// Base error code for all dev errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::DEV;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> Self {
|
||||
let msg = e.to_string();
|
||||
|
||||
match e {
|
||||
Error::BlockQueryError(_) => ErrorObject::owned(BASE_ERROR + 1, msg, None::<()>),
|
||||
Error::BlockExecutionFailed => ErrorObject::owned(BASE_ERROR + 3, msg, None::<()>),
|
||||
Error::WitnessCompactionFailed => ErrorObject::owned(BASE_ERROR + 4, msg, None::<()>),
|
||||
Error::ProofExtractionFailed => ErrorObject::owned(BASE_ERROR + 5, msg, None::<()>),
|
||||
Error::UnsafeRpcCalled(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate dev API containing RPCs that are mainly meant for debugging and stats collection for
|
||||
//! developers. The endpoints in this RPC module are not meant to be available to non-local users
|
||||
//! and are all marked `unsafe`.
|
||||
|
||||
pub mod error;
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use error::Error;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use scale_info::TypeInfo;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Statistics of a block returned by the `dev_getBlockStats` RPC.
|
||||
#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BlockStats {
|
||||
/// The length in bytes of the storage proof produced by executing the block.
|
||||
pub witness_len: u64,
|
||||
/// The length in bytes of the storage proof after compaction.
|
||||
pub witness_compact_len: u64,
|
||||
/// Length of the block in bytes.
|
||||
///
|
||||
/// This information can also be acquired by downloading the whole block. This merely
|
||||
/// saves some complexity on the client side.
|
||||
pub block_len: u64,
|
||||
/// Number of extrinsics in the block.
|
||||
///
|
||||
/// This information can also be acquired by downloading the whole block. This merely
|
||||
/// saves some complexity on the client side.
|
||||
pub num_extrinsics: u64,
|
||||
}
|
||||
|
||||
/// Substrate dev API.
|
||||
///
|
||||
/// This API contains unstable and unsafe methods only meant for development nodes. They
|
||||
/// are all flagged as unsafe for this reason.
|
||||
#[rpc(client, server)]
|
||||
pub trait DevApi<Hash> {
|
||||
/// Reexecute the specified `block_hash` and gather statistics while doing so.
|
||||
///
|
||||
/// This function requires the specified block and its parent to be available
|
||||
/// at the queried node. If either the specified block or the parent is pruned,
|
||||
/// this function will return `None`.
|
||||
#[method(name = "dev_getBlockStats", with_extensions)]
|
||||
fn block_stats(&self, block_hash: Hash) -> Result<Option<BlockStats>, Error>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// Base error code for RPC modules.
|
||||
pub mod base {
|
||||
pub const AUTHOR: i32 = 1000;
|
||||
pub const SYSTEM: i32 = 2000;
|
||||
pub const CHAIN: i32 = 3000;
|
||||
pub const STATE: i32 = 4000;
|
||||
pub const OFFCHAIN: i32 = 5000;
|
||||
pub const DEV: i32 = 6000;
|
||||
pub const STATEMENT: i32 = 7000;
|
||||
pub const MIXNET: i32 = 8000;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate RPC interfaces.
|
||||
//!
|
||||
//! A collection of RPC methods and subscriptions supported by all substrate clients.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod error;
|
||||
mod policy;
|
||||
|
||||
pub use policy::{check_if_safe, DenyUnsafe, UnsafeRpcError};
|
||||
|
||||
pub mod author;
|
||||
pub mod chain;
|
||||
pub mod child_state;
|
||||
pub mod dev;
|
||||
pub mod mixnet;
|
||||
pub mod offchain;
|
||||
pub mod state;
|
||||
pub mod statement;
|
||||
pub mod system;
|
||||
@@ -0,0 +1,48 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Mixnet RPC module errors.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
use sc_mixnet::{PostErr, RemoteErr, TopologyErr};
|
||||
|
||||
/// Mixnet RPC error type.
|
||||
pub struct Error(pub sc_mixnet::Error);
|
||||
|
||||
/// Base code for all mixnet errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::MIXNET;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(err: Error) -> Self {
|
||||
let code = match err.0 {
|
||||
sc_mixnet::Error::ServiceUnavailable => BASE_ERROR + 1,
|
||||
sc_mixnet::Error::NoReply => BASE_ERROR + 2,
|
||||
sc_mixnet::Error::BadReply => BASE_ERROR + 3,
|
||||
sc_mixnet::Error::Post(PostErr::TooManyFragments) => BASE_ERROR + 101,
|
||||
sc_mixnet::Error::Post(PostErr::SessionMixnodesNotKnown(_)) => BASE_ERROR + 102,
|
||||
sc_mixnet::Error::Post(PostErr::SessionDisabled(_)) => BASE_ERROR + 103,
|
||||
sc_mixnet::Error::Post(PostErr::Topology(TopologyErr::NoConnectedGatewayMixnodes)) =>
|
||||
BASE_ERROR + 151,
|
||||
sc_mixnet::Error::Post(PostErr::Topology(_)) => BASE_ERROR + 150,
|
||||
sc_mixnet::Error::Post(_) => BASE_ERROR + 100,
|
||||
sc_mixnet::Error::Remote(RemoteErr::Other(_)) => BASE_ERROR + 200,
|
||||
sc_mixnet::Error::Remote(RemoteErr::Decode(_)) => BASE_ERROR + 201,
|
||||
};
|
||||
ErrorObject::owned(code, err.0.to_string(), None::<()>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate mixnet API.
|
||||
|
||||
pub mod error;
|
||||
|
||||
use error::Error;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sp_core::Bytes;
|
||||
|
||||
#[rpc(client, server)]
|
||||
pub trait MixnetApi {
|
||||
/// Submit encoded extrinsic over the mixnet for inclusion in block.
|
||||
#[method(name = "mixnet_submitExtrinsic")]
|
||||
async fn submit_extrinsic(&self, extrinsic: Bytes) -> Result<(), Error>;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Offchain RPC errors.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
|
||||
/// Offchain RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Offchain RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Unavailable storage kind error.
|
||||
#[error("This storage kind is not available yet.")]
|
||||
UnavailableStorageKind,
|
||||
/// Call to an unsafe RPC was denied.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
}
|
||||
|
||||
/// Base error code for all offchain errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::OFFCHAIN;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> Self {
|
||||
match e {
|
||||
Error::UnavailableStorageKind => ErrorObject::owned(
|
||||
BASE_ERROR + 1,
|
||||
"This storage kind is not available yet",
|
||||
None::<()>,
|
||||
),
|
||||
Error::UnsafeRpcCalled(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate offchain API.
|
||||
|
||||
pub mod error;
|
||||
|
||||
use error::Error;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sp_core::{offchain::StorageKind, Bytes};
|
||||
|
||||
/// Substrate offchain RPC API
|
||||
#[rpc(client, server)]
|
||||
pub trait OffchainApi {
|
||||
/// Set offchain local storage under given key and prefix.
|
||||
#[method(name = "offchain_localStorageSet", with_extensions)]
|
||||
fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> Result<(), Error>;
|
||||
|
||||
/// Clear offchain local storage under given key and prefix.
|
||||
#[method(name = "offchain_localStorageClear", with_extensions)]
|
||||
fn clear_local_storage(&self, kind: StorageKind, key: Bytes) -> Result<(), Error>;
|
||||
|
||||
/// Get offchain local storage under given key and prefix.
|
||||
#[method(name = "offchain_localStorageGet", with_extensions)]
|
||||
fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> Result<Option<Bytes>, Error>;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Policy-related types.
|
||||
//!
|
||||
//! Contains a `DenyUnsafe` type that can be used to deny potentially unsafe
|
||||
//! RPC when accessed externally.
|
||||
|
||||
use jsonrpsee::types::{error::ErrorCode, ErrorObject, ErrorObjectOwned};
|
||||
|
||||
/// Checks if the RPC call is safe to be called externally.
|
||||
pub fn check_if_safe(ext: &jsonrpsee::Extensions) -> Result<(), UnsafeRpcError> {
|
||||
match ext.get::<DenyUnsafe>().map(|deny_unsafe| deny_unsafe.check_if_safe()) {
|
||||
Some(Ok(())) => Ok(()),
|
||||
Some(Err(e)) => Err(e),
|
||||
None => unreachable!("DenyUnsafe extension is always set by the substrate rpc server; qed"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Signifies whether a potentially unsafe RPC should be denied.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum DenyUnsafe {
|
||||
/// Denies only potentially unsafe RPCs.
|
||||
Yes,
|
||||
/// Allows calling every RPCs.
|
||||
No,
|
||||
}
|
||||
|
||||
impl DenyUnsafe {
|
||||
/// Returns `Ok(())` if the RPCs considered unsafe are safe to call,
|
||||
/// otherwise returns `Err(UnsafeRpcError)`.
|
||||
pub fn check_if_safe(self) -> Result<(), UnsafeRpcError> {
|
||||
match self {
|
||||
DenyUnsafe::Yes => Err(UnsafeRpcError),
|
||||
DenyUnsafe::No => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Signifies whether an RPC considered unsafe is denied to be called externally.
|
||||
#[derive(Debug)]
|
||||
pub struct UnsafeRpcError;
|
||||
|
||||
impl std::fmt::Display for UnsafeRpcError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "RPC call is unsafe to be called externally")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for UnsafeRpcError {}
|
||||
|
||||
impl From<UnsafeRpcError> for ErrorObjectOwned {
|
||||
fn from(e: UnsafeRpcError) -> ErrorObjectOwned {
|
||||
ErrorObject::owned(ErrorCode::MethodNotFound.code(), e.to_string(), None::<()>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! State RPC errors.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
|
||||
/// State RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// State RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Client error.
|
||||
#[error("Client error: {}", .0)]
|
||||
Client(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
/// Provided block range couldn't be resolved to a list of blocks.
|
||||
#[error("Cannot resolve a block range ['{:?}' ... '{:?}]. {}", .from, .to, .details)]
|
||||
InvalidBlockRange {
|
||||
/// Beginning of the block range.
|
||||
from: String,
|
||||
/// End of the block range.
|
||||
to: String,
|
||||
/// Details of the error message.
|
||||
details: String,
|
||||
},
|
||||
/// Provided count exceeds maximum value.
|
||||
#[error("count exceeds maximum value. value: {}, max: {}", .value, .max)]
|
||||
InvalidCount {
|
||||
/// Provided value
|
||||
value: u32,
|
||||
/// Maximum allowed value
|
||||
max: u32,
|
||||
},
|
||||
/// Call to an unsafe RPC was denied.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
}
|
||||
|
||||
/// Base code for all state errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::STATE;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> ErrorObjectOwned {
|
||||
match e {
|
||||
Error::InvalidBlockRange { .. } =>
|
||||
ErrorObject::owned(BASE_ERROR + 1, e.to_string(), None::<()>),
|
||||
Error::InvalidCount { .. } =>
|
||||
ErrorObject::owned(BASE_ERROR + 2, e.to_string(), None::<()>),
|
||||
e => ErrorObject::owned(BASE_ERROR + 3, e.to_string(), None::<()>),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate state API helpers.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::Bytes;
|
||||
|
||||
/// ReadProof struct returned by the RPC
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReadProof<Hash> {
|
||||
/// Block hash used to generate the proof
|
||||
pub at: Hash,
|
||||
/// A proof used to prove that storage entries are included in the storage trie
|
||||
pub proof: Vec<Bytes>,
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate state API.
|
||||
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use sp_core::{
|
||||
storage::{StorageChangeSet, StorageData, StorageKey},
|
||||
Bytes,
|
||||
};
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
pub mod error;
|
||||
pub mod helpers;
|
||||
|
||||
pub use self::helpers::ReadProof;
|
||||
pub use error::Error;
|
||||
|
||||
/// Substrate state API
|
||||
#[rpc(client, server)]
|
||||
pub trait StateApi<Hash> {
|
||||
/// Call a method from the runtime API at a block's state.
|
||||
#[method(name = "state_call", aliases = ["state_callAt"], blocking)]
|
||||
fn call(&self, name: String, bytes: Bytes, hash: Option<Hash>) -> Result<Bytes, Error>;
|
||||
|
||||
/// Returns the keys with prefix, leave empty to get all the keys.
|
||||
#[method(name = "state_getKeys", blocking)]
|
||||
#[deprecated(since = "2.0.0", note = "Please use `getKeysPaged` with proper paging support")]
|
||||
fn storage_keys(
|
||||
&self,
|
||||
prefix: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<StorageKey>, Error>;
|
||||
|
||||
/// Returns the keys with prefix, leave empty to get all the keys
|
||||
#[method(name = "state_getPairs", blocking, with_extensions)]
|
||||
fn storage_pairs(
|
||||
&self,
|
||||
prefix: StorageKey,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<(StorageKey, StorageData)>, Error>;
|
||||
|
||||
/// Returns the keys with prefix with pagination support.
|
||||
/// Up to `count` keys will be returned.
|
||||
/// If `start_key` is passed, return next keys in storage in lexicographic order.
|
||||
#[method(name = "state_getKeysPaged", aliases = ["state_getKeysPagedAt"], blocking)]
|
||||
fn storage_keys_paged(
|
||||
&self,
|
||||
prefix: Option<StorageKey>,
|
||||
count: u32,
|
||||
start_key: Option<StorageKey>,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<StorageKey>, Error>;
|
||||
|
||||
/// Returns a storage entry at a specific block's state.
|
||||
#[method(name = "state_getStorage", aliases = ["state_getStorageAt"], blocking)]
|
||||
fn storage(&self, key: StorageKey, hash: Option<Hash>) -> Result<Option<StorageData>, Error>;
|
||||
|
||||
/// Returns the hash of a storage entry at a block's state.
|
||||
#[method(name = "state_getStorageHash", aliases = ["state_getStorageHashAt"], blocking)]
|
||||
fn storage_hash(&self, key: StorageKey, hash: Option<Hash>) -> Result<Option<Hash>, Error>;
|
||||
|
||||
/// Returns the size of a storage entry at a block's state.
|
||||
#[method(name = "state_getStorageSize", aliases = ["state_getStorageSizeAt"], with_extensions)]
|
||||
async fn storage_size(&self, key: StorageKey, hash: Option<Hash>)
|
||||
-> Result<Option<u64>, Error>;
|
||||
|
||||
/// Returns the runtime metadata as an opaque blob.
|
||||
#[method(name = "state_getMetadata", blocking)]
|
||||
fn metadata(&self, hash: Option<Hash>) -> Result<Bytes, Error>;
|
||||
|
||||
/// Get the runtime version.
|
||||
#[method(name = "state_getRuntimeVersion", aliases = ["chain_getRuntimeVersion"], blocking)]
|
||||
fn runtime_version(&self, hash: Option<Hash>) -> Result<RuntimeVersion, Error>;
|
||||
|
||||
/// Query historical storage entries (by key) starting from a block given as the second
|
||||
/// parameter.
|
||||
///
|
||||
/// NOTE: The first returned result contains the initial state of storage for all keys.
|
||||
/// Subsequent values in the vector represent changes to the previous state (diffs).
|
||||
/// WARNING: The time complexity of this query is O(|keys|*dist(block, hash)), and the
|
||||
/// memory complexity is O(dist(block, hash)) -- use with caution.
|
||||
#[method(name = "state_queryStorage", blocking, with_extensions)]
|
||||
fn query_storage(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
block: Hash,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Vec<StorageChangeSet<Hash>>, Error>;
|
||||
|
||||
/// Query storage entries (by key) at a block hash given as the second parameter.
|
||||
/// NOTE: Each StorageChangeSet in the result corresponds to exactly one element --
|
||||
/// the storage value under an input key at the input block hash.
|
||||
#[method(name = "state_queryStorageAt", blocking)]
|
||||
fn query_storage_at(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
at: Option<Hash>,
|
||||
) -> Result<Vec<StorageChangeSet<Hash>>, Error>;
|
||||
|
||||
/// Returns proof of storage entries at a specific block's state.
|
||||
#[method(name = "state_getReadProof", blocking)]
|
||||
fn read_proof(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<ReadProof<Hash>, Error>;
|
||||
|
||||
/// New runtime version subscription
|
||||
#[subscription(
|
||||
name = "state_subscribeRuntimeVersion" => "state_runtimeVersion",
|
||||
unsubscribe = "state_unsubscribeRuntimeVersion",
|
||||
aliases = ["chain_subscribeRuntimeVersion"],
|
||||
unsubscribe_aliases = ["chain_unsubscribeRuntimeVersion"],
|
||||
item = RuntimeVersion,
|
||||
)]
|
||||
fn subscribe_runtime_version(&self);
|
||||
|
||||
/// New storage subscription
|
||||
#[subscription(
|
||||
name = "state_subscribeStorage" => "state_storage",
|
||||
unsubscribe = "state_unsubscribeStorage",
|
||||
item = StorageChangeSet<Hash>,
|
||||
with_extensions,
|
||||
)]
|
||||
fn subscribe_storage(&self, keys: Option<Vec<StorageKey>>);
|
||||
|
||||
/// The `traceBlock` RPC provides a way to trace the re-execution of a single
|
||||
/// block, collecting Spans and Events from both the client and the relevant WASM runtime.
|
||||
/// The Spans and Events are conceptually equivalent to those from the [Tracing][1] crate.
|
||||
///
|
||||
/// The structure of the traces follows that of the block execution pipeline, so meaningful
|
||||
/// interpretation of the traces requires an understanding of the Substrate chain's block
|
||||
/// execution.
|
||||
///
|
||||
/// [Link to conceptual map of trace structure for Pezkuwi and Kusama block execution.][2]
|
||||
///
|
||||
/// [1]: https://crates.io/crates/tracing
|
||||
/// [2]: https://docs.google.com/drawings/d/1vZoJo9jaXlz0LmrdTOgHck9_1LsfuQPRmTr-5g1tOis/edit?usp=sharing
|
||||
///
|
||||
/// ## Node requirements
|
||||
///
|
||||
/// - Fully synced archive node (i.e. a node that is not actively doing a "major" sync).
|
||||
/// - [Tracing enabled WASM runtimes](#creating-tracing-enabled-wasm-runtimes) for all runtime
|
||||
/// versions
|
||||
/// for which tracing is desired.
|
||||
///
|
||||
/// ## Node recommendations
|
||||
///
|
||||
/// - Use fast SSD disk storage.
|
||||
/// - Run node flags to increase DB read speed (i.e. `--state-cache-size`, `--db-cache`).
|
||||
///
|
||||
/// ## Creating tracing enabled WASM runtimes
|
||||
///
|
||||
/// - Checkout commit of chain version to compile with WASM traces
|
||||
/// - [diener][1] can help to peg commit of substrate to what the chain expects.
|
||||
/// - Navigate to the `runtime` folder/package of the chain
|
||||
/// - Add feature `with-tracing = ["frame-executive/with-tracing", "sp-io/with-tracing"]`
|
||||
/// under `[features]` to the `runtime` packages' `Cargo.toml`.
|
||||
/// - Compile the runtime with `cargo build --release --features with-tracing`
|
||||
/// - Tracing-enabled WASM runtime should be found in
|
||||
/// `./target/release/wbuild/{{chain}}-runtime`
|
||||
/// and be called something like `{{your_chain}}_runtime.compact.wasm`. This can be
|
||||
/// renamed/modified however you like, as long as it retains the `.wasm` extension.
|
||||
/// - Run the node with the wasm blob overrides by placing them in a folder with all your
|
||||
/// runtimes,
|
||||
/// and passing the path of this folder to your chain, e.g.:
|
||||
/// - `./target/release/pezkuwi --wasm-runtime-overrides /home/user/my-custom-wasm-runtimes`
|
||||
///
|
||||
/// You can also find some pre-built tracing enabled wasm runtimes in [substrate-archive][2]
|
||||
///
|
||||
/// [Source.][3]
|
||||
///
|
||||
/// [1]: https://crates.io/crates/diener
|
||||
/// [2]: https://github.com/paritytech/substrate-archive/tree/master/wasm-tracing
|
||||
/// [3]: https://github.com/paritytech/substrate-archive/wiki
|
||||
///
|
||||
/// ## RPC Usage
|
||||
///
|
||||
/// The RPC allows for two filtering mechanisms: tracing targets and storage key prefixes.
|
||||
/// The filtering of spans and events takes place after they are all collected; so while filters
|
||||
/// do not reduce time for actual block re-execution, they reduce the response payload size.
|
||||
///
|
||||
/// Note: storage events primarily come from _primitives/state-machine/src/ext.rs_.
|
||||
/// The default filters can be overridden, see the [params section](#params) for details.
|
||||
///
|
||||
/// ### `curl` example
|
||||
///
|
||||
/// - Get tracing spans and events
|
||||
/// ```text
|
||||
/// curl \
|
||||
/// -H "Content-Type: application/json" \
|
||||
/// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
|
||||
/// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "pallet,frame,state", "", ""]}' \
|
||||
/// http://localhost:9933/
|
||||
/// ```
|
||||
///
|
||||
/// - Get tracing events with all `storage_keys`
|
||||
/// ```text
|
||||
/// curl \
|
||||
/// -H "Content-Type: application/json" \
|
||||
/// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
|
||||
/// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "", ""]}' \
|
||||
/// http://localhost:9933/
|
||||
/// ```
|
||||
///
|
||||
/// - Get tracing events with `storage_keys` ('f0c365c3cf59d671eb72da0e7a4113c4')
|
||||
/// ```text
|
||||
/// curl \
|
||||
/// -H "Content-Type: application/json" \
|
||||
/// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
|
||||
/// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "f0c365c3cf59d671eb72da0e7a4113c4", ""]}' \
|
||||
/// http://localhost:9933/
|
||||
/// ```
|
||||
///
|
||||
/// - Get tracing events with `storage_keys` ('f0c365c3cf59d671eb72da0e7a4113c4') and method
|
||||
/// ('Put')
|
||||
/// ```text
|
||||
/// curl \
|
||||
/// -H "Content-Type: application/json" \
|
||||
/// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
|
||||
/// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "f0c365c3cf59d671eb72da0e7a4113c4", "Put"]}' \
|
||||
/// http://localhost:9933/
|
||||
/// ```
|
||||
///
|
||||
/// - Get tracing events with all `storage_keys` and method ('Put')
|
||||
/// ```text
|
||||
/// curl \
|
||||
/// -H "Content-Type: application/json" \
|
||||
/// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
|
||||
/// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "", "Put"]}' \
|
||||
/// http://localhost:9933/
|
||||
/// ```
|
||||
///
|
||||
/// ### Params
|
||||
///
|
||||
/// - `block` (param index 0): Hash of the block to trace.
|
||||
/// - `targets` (param index 1): String of comma separated (no spaces) targets. Specified
|
||||
/// targets match with trace targets by prefix (i.e if a target is in the beginning
|
||||
/// of a trace target it is considered a match). If an empty string is specified no
|
||||
/// targets will be filtered out. The majority of targets correspond to Rust module names,
|
||||
/// and the ones that do not are typically "hardcoded" into span or event location
|
||||
/// somewhere in the Substrate source code. ("Non-hardcoded" targets typically come from frame
|
||||
/// support macros.)
|
||||
/// - `storage_keys` (param index 2): String of comma separated (no spaces) hex encoded
|
||||
/// (no `0x` prefix) storage keys. If an empty string is specified no events will
|
||||
/// be filtered out. If anything other than an empty string is specified, events
|
||||
/// will be filtered by storage key (so non-storage events will **not** show up).
|
||||
/// You can specify any length of a storage key prefix (i.e. if a specified storage
|
||||
/// key is in the beginning of an events storage key it is considered a match).
|
||||
/// Example: for balance tracking on Pezkuwi & Kusama you would likely want
|
||||
/// to track changes to account balances with the frame_system::Account storage item,
|
||||
/// which is a map from `AccountId` to `AccountInfo`. The key filter for this would be
|
||||
/// the storage prefix for the map:
|
||||
/// `26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9`
|
||||
/// - `methods` (param index 3): String of comma separated (no spaces) tracing event method.
|
||||
/// If an empty string is specified no events will be filtered out. If anything other than
|
||||
/// an empty string is specified, events will be filtered by method (so non-method events will
|
||||
/// **not** show up).
|
||||
///
|
||||
/// Additionally you would want to track the extrinsic index, which is under the
|
||||
/// `:extrinsic_index` key. The key for this would be the aforementioned string as bytes
|
||||
/// in hex: `3a65787472696e7369635f696e646578`.
|
||||
/// The following are some resources to learn more about storage keys in substrate:
|
||||
/// [substrate storage][1], [transparent keys in substrate][2],
|
||||
/// [querying substrate storage via rpc][3].
|
||||
///
|
||||
/// [1]: https://docs.pezkuwichain.io/main-docs/fundamentals/state-transitions-and-storage/
|
||||
/// [2]: https://www.shawntabrizi.com/blog/substrate/transparent-keys-in-substrate/
|
||||
/// [3]: https://www.shawntabrizi.com/blog/substrate/querying-substrate-storage-via-rpc/
|
||||
///
|
||||
/// ### Maximum payload size
|
||||
///
|
||||
/// The maximum payload size allowed is 15mb. Payloads over this size will return a
|
||||
/// object with a simple error message. If you run into issues with payload size you can
|
||||
/// narrow down the traces using a smaller set of targets and/or storage keys.
|
||||
///
|
||||
/// If you are having issues with maximum payload size you can use the flag
|
||||
/// `-ltracing=trace` to get some logging during tracing.
|
||||
#[method(name = "state_traceBlock", blocking, with_extensions)]
|
||||
fn trace_block(
|
||||
&self,
|
||||
block: Hash,
|
||||
targets: Option<String>,
|
||||
storage_keys: Option<String>,
|
||||
methods: Option<String>,
|
||||
) -> Result<sp_rpc::tracing::TraceBlockResponse, Error>;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Statement RPC errors.
|
||||
|
||||
use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned};
|
||||
|
||||
/// Statement RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Statement RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Statement store internal error.
|
||||
#[error("Statement store error")]
|
||||
StatementStore(String),
|
||||
/// Call to an unsafe RPC was denied.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
}
|
||||
|
||||
/// Base error code for all statement errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::STATEMENT;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> Self {
|
||||
match e {
|
||||
Error::StatementStore(message) => ErrorObject::owned(
|
||||
BASE_ERROR + 1,
|
||||
format!("Statement store error: {message}"),
|
||||
None::<()>,
|
||||
),
|
||||
Error::UnsafeRpcCalled(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate Statement Store RPC API.
|
||||
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
|
||||
use sp_core::Bytes;
|
||||
|
||||
pub mod error;
|
||||
|
||||
/// Substrate statement RPC API
|
||||
#[rpc(client, server)]
|
||||
pub trait StatementApi {
|
||||
/// Return all statements, SCALE-encoded.
|
||||
#[method(name = "statement_dump", with_extensions)]
|
||||
fn dump(&self) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return the data of all known statements which include all topics and have no `DecryptionKey`
|
||||
/// field.
|
||||
///
|
||||
/// To get the statement, and not just the data, use `statement_broadcastsStatement`.
|
||||
#[method(name = "statement_broadcasts")]
|
||||
fn broadcasts(&self, match_all_topics: Vec<[u8; 32]>) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return the data of all known statements whose decryption key is identified as `dest` (this
|
||||
/// will generally be the public key or a hash thereof for symmetric ciphers, or a hash of the
|
||||
/// private key for symmetric ciphers).
|
||||
///
|
||||
/// To get the statement, and not just the data, use `statement_postedStatement`.
|
||||
#[method(name = "statement_posted")]
|
||||
fn posted(&self, match_all_topics: Vec<[u8; 32]>, dest: [u8; 32]) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return the decrypted data of all known statements whose decryption key is identified as
|
||||
/// `dest`. The key must be available to the client.
|
||||
///
|
||||
/// To get the statement, and not just the data, use `statement_postedClearStatement`.
|
||||
#[method(name = "statement_postedClear")]
|
||||
fn posted_clear(
|
||||
&self,
|
||||
match_all_topics: Vec<[u8; 32]>,
|
||||
dest: [u8; 32],
|
||||
) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return all known statements which include all topics and have no `DecryptionKey`
|
||||
/// field.
|
||||
///
|
||||
/// This returns the SCALE-encoded statements not just the data as in rpc
|
||||
/// `statement_broadcasts`.
|
||||
#[method(name = "statement_broadcastsStatement")]
|
||||
fn broadcasts_stmt(&self, match_all_topics: Vec<[u8; 32]>) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return all known statements whose decryption key is identified as `dest` (this
|
||||
/// will generally be the public key or a hash thereof for symmetric ciphers, or a hash of the
|
||||
/// private key for symmetric ciphers).
|
||||
///
|
||||
/// This returns the SCALE-encoded statements not just the data as in rpc `statement_posted`.
|
||||
#[method(name = "statement_postedStatement")]
|
||||
fn posted_stmt(&self, match_all_topics: Vec<[u8; 32]>, dest: [u8; 32])
|
||||
-> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Return the statement and the decrypted data of all known statements whose decryption key is
|
||||
/// identified as `dest`. The key must be available to the client.
|
||||
///
|
||||
/// This returns for each statement: the SCALE-encoded statement concatenated to the decrypted
|
||||
/// data. Not just the data as in rpc `statement_postedClear`.
|
||||
#[method(name = "statement_postedClearStatement")]
|
||||
fn posted_clear_stmt(
|
||||
&self,
|
||||
match_all_topics: Vec<[u8; 32]>,
|
||||
dest: [u8; 32],
|
||||
) -> RpcResult<Vec<Bytes>>;
|
||||
|
||||
/// Submit a pre-encoded statement.
|
||||
#[method(name = "statement_submit")]
|
||||
fn submit(&self, encoded: Bytes) -> RpcResult<()>;
|
||||
|
||||
/// Remove a statement from the store.
|
||||
#[method(name = "statement_remove")]
|
||||
fn remove(&self, statement_hash: [u8; 32]) -> RpcResult<()>;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! System RPC module errors.
|
||||
|
||||
use crate::system::helpers::Health;
|
||||
use jsonrpsee::types::{
|
||||
error::{ErrorCode, ErrorObject},
|
||||
ErrorObjectOwned,
|
||||
};
|
||||
|
||||
/// System RPC Result type.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// System RPC errors.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Provided block range couldn't be resolved to a list of blocks.
|
||||
#[error("Node is not fully functional: {}", .0)]
|
||||
NotHealthy(Health),
|
||||
/// Peer argument is malformatted.
|
||||
#[error("{0}")]
|
||||
MalformattedPeerArg(String),
|
||||
/// Call to an unsafe RPC was denied.
|
||||
#[error(transparent)]
|
||||
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
|
||||
/// Internal error.
|
||||
#[error("{0}")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
// Base code for all system errors.
|
||||
const BASE_ERROR: i32 = crate::error::base::SYSTEM;
|
||||
// Provided block range couldn't be resolved to a list of blocks.
|
||||
const NOT_HEALTHY_ERROR: i32 = BASE_ERROR + 1;
|
||||
// Peer argument is malformatted.
|
||||
const MALFORMATTED_PEER_ARG_ERROR: i32 = BASE_ERROR + 2;
|
||||
|
||||
impl From<Error> for ErrorObjectOwned {
|
||||
fn from(e: Error) -> ErrorObjectOwned {
|
||||
match e {
|
||||
Error::NotHealthy(ref h) =>
|
||||
ErrorObject::owned(NOT_HEALTHY_ERROR, e.to_string(), Some(h)),
|
||||
Error::MalformattedPeerArg(e) =>
|
||||
ErrorObject::owned(MALFORMATTED_PEER_ARG_ERROR, e, None::<()>),
|
||||
Error::UnsafeRpcCalled(e) => e.into(),
|
||||
Error::Internal(e) =>
|
||||
ErrorObjectOwned::owned(ErrorCode::InternalError.code(), e, None::<()>),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate system API helpers.
|
||||
|
||||
use sc_chain_spec::{ChainType, Properties};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// Running node's static details.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SystemInfo {
|
||||
/// Implementation name.
|
||||
pub impl_name: String,
|
||||
/// Implementation version.
|
||||
pub impl_version: String,
|
||||
/// Chain name.
|
||||
pub chain_name: String,
|
||||
/// A custom set of properties defined in the chain spec.
|
||||
pub properties: Properties,
|
||||
/// The type of this chain.
|
||||
pub chain_type: ChainType,
|
||||
}
|
||||
|
||||
/// Health struct returned by the RPC
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Health {
|
||||
/// Number of connected peers
|
||||
pub peers: usize,
|
||||
/// Is the node syncing
|
||||
pub is_syncing: bool,
|
||||
/// Should this node have any peers
|
||||
///
|
||||
/// Might be false for local chains or when running without discovery.
|
||||
pub should_have_peers: bool,
|
||||
}
|
||||
|
||||
impl fmt::Display for Health {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { "syncing" } else { "idle" })
|
||||
}
|
||||
}
|
||||
|
||||
/// Network Peer information
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PeerInfo<Hash, Number> {
|
||||
/// Peer ID
|
||||
pub peer_id: String,
|
||||
/// Roles
|
||||
pub roles: String,
|
||||
/// Peer best block hash
|
||||
pub best_hash: Hash,
|
||||
/// Peer best block number
|
||||
pub best_number: Number,
|
||||
}
|
||||
|
||||
/// The role the node is running as
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum NodeRole {
|
||||
/// The node is a full node
|
||||
Full,
|
||||
/// The node is an authority
|
||||
Authority,
|
||||
}
|
||||
|
||||
/// The state of the syncing of the node.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SyncState<Number> {
|
||||
/// Height of the block at which syncing started.
|
||||
pub starting_block: Number,
|
||||
/// Height of the current best block of the node.
|
||||
pub current_block: Number,
|
||||
/// Height of the highest block in the network.
|
||||
pub highest_block: Number,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_serialize_health() {
|
||||
assert_eq!(
|
||||
::serde_json::to_string(&Health {
|
||||
peers: 1,
|
||||
is_syncing: false,
|
||||
should_have_peers: true,
|
||||
})
|
||||
.unwrap(),
|
||||
r#"{"peers":1,"isSyncing":false,"shouldHavePeers":true}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize_peer_info() {
|
||||
assert_eq!(
|
||||
::serde_json::to_string(&PeerInfo {
|
||||
peer_id: "2".into(),
|
||||
roles: "a".into(),
|
||||
best_hash: 5u32,
|
||||
best_number: 6u32,
|
||||
})
|
||||
.unwrap(),
|
||||
r#"{"peerId":"2","roles":"a","bestHash":5,"bestNumber":6}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize_sync_state() {
|
||||
assert_eq!(
|
||||
::serde_json::to_string(&SyncState {
|
||||
starting_block: 12u32,
|
||||
current_block: 50u32,
|
||||
highest_block: 128u32,
|
||||
})
|
||||
.unwrap(),
|
||||
r#"{"startingBlock":12,"currentBlock":50,"highestBlock":128}"#,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
::serde_json::to_string(&SyncState {
|
||||
starting_block: 12u32,
|
||||
current_block: 50u32,
|
||||
highest_block: 50u32,
|
||||
})
|
||||
.unwrap(),
|
||||
r#"{"startingBlock":12,"currentBlock":50,"highestBlock":50}"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate system API.
|
||||
|
||||
pub mod error;
|
||||
pub mod helpers;
|
||||
|
||||
use jsonrpsee::{core::JsonValue, proc_macros::rpc};
|
||||
|
||||
pub use self::helpers::{Health, NodeRole, PeerInfo, SyncState, SystemInfo};
|
||||
pub use error::Error;
|
||||
|
||||
/// Substrate system RPC API
|
||||
#[rpc(client, server)]
|
||||
pub trait SystemApi<Hash, Number> {
|
||||
/// Get the node's implementation name. Plain old string.
|
||||
#[method(name = "system_name")]
|
||||
fn system_name(&self) -> Result<String, Error>;
|
||||
|
||||
/// Get the node implementation's version. Should be a semver string.
|
||||
#[method(name = "system_version")]
|
||||
fn system_version(&self) -> Result<String, Error>;
|
||||
|
||||
/// Get the chain's name. Given as a string identifier.
|
||||
#[method(name = "system_chain")]
|
||||
fn system_chain(&self) -> Result<String, Error>;
|
||||
|
||||
/// Get the chain's type.
|
||||
#[method(name = "system_chainType")]
|
||||
fn system_type(&self) -> Result<sc_chain_spec::ChainType, Error>;
|
||||
|
||||
/// Get a custom set of properties as a JSON object, defined in the chain spec.
|
||||
#[method(name = "system_properties")]
|
||||
fn system_properties(&self) -> Result<sc_chain_spec::Properties, Error>;
|
||||
|
||||
/// Return health status of the node.
|
||||
///
|
||||
/// Node is considered healthy if it is:
|
||||
/// - connected to some peers (unless running in dev mode)
|
||||
/// - not performing a major sync
|
||||
#[method(name = "system_health")]
|
||||
async fn system_health(&self) -> Result<Health, Error>;
|
||||
|
||||
/// Returns the base58-encoded PeerId of the node.
|
||||
#[method(name = "system_localPeerId")]
|
||||
async fn system_local_peer_id(&self) -> Result<String, Error>;
|
||||
|
||||
/// Returns the multi-addresses that the local node is listening on
|
||||
///
|
||||
/// The addresses include a trailing `/p2p/` with the local PeerId, and are thus suitable to
|
||||
/// be passed to `addReservedPeer` or as a bootnode address for example.
|
||||
#[method(name = "system_localListenAddresses")]
|
||||
async fn system_local_listen_addresses(&self) -> Result<Vec<String>, Error>;
|
||||
|
||||
/// Returns currently connected peers
|
||||
#[method(name = "system_peers", with_extensions)]
|
||||
async fn system_peers(&self) -> Result<Vec<PeerInfo<Hash, Number>>, Error>;
|
||||
|
||||
/// Returns current state of the network.
|
||||
///
|
||||
/// **Warning**: This API is not stable. Please do not programmatically interpret its output,
|
||||
/// as its format might change at any time.
|
||||
// TODO: the future of this call is uncertain: https://github.com/paritytech/substrate/issues/1890
|
||||
// https://github.com/paritytech/substrate/issues/5541
|
||||
#[method(name = "system_unstable_networkState", with_extensions)]
|
||||
async fn system_network_state(&self) -> Result<JsonValue, Error>;
|
||||
|
||||
/// Adds a reserved peer. Returns the empty string or an error. The string
|
||||
/// parameter should encode a `p2p` multiaddr.
|
||||
///
|
||||
/// `/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV`
|
||||
/// is an example of a valid, passing multiaddr with PeerId attached.
|
||||
#[method(name = "system_addReservedPeer", with_extensions)]
|
||||
async fn system_add_reserved_peer(&self, peer: String) -> Result<(), Error>;
|
||||
|
||||
/// Remove a reserved peer. Returns the empty string or an error. The string
|
||||
/// should encode only the PeerId e.g. `QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV`.
|
||||
#[method(name = "system_removeReservedPeer", with_extensions)]
|
||||
async fn system_remove_reserved_peer(&self, peer_id: String) -> Result<(), Error>;
|
||||
|
||||
/// Returns the list of reserved peers
|
||||
#[method(name = "system_reservedPeers")]
|
||||
async fn system_reserved_peers(&self) -> Result<Vec<String>, Error>;
|
||||
|
||||
/// Returns the roles the node is running as.
|
||||
#[method(name = "system_nodeRoles")]
|
||||
async fn system_node_roles(&self) -> Result<Vec<NodeRole>, Error>;
|
||||
|
||||
/// Returns the state of the syncing of the node: starting block, current best block, highest
|
||||
/// known block.
|
||||
#[method(name = "system_syncState")]
|
||||
async fn system_sync_state(&self) -> Result<SyncState<Number>, Error>;
|
||||
|
||||
/// Adds the supplied directives to the current log filter
|
||||
///
|
||||
/// The syntax is identical to the CLI `<target>=<level>`:
|
||||
///
|
||||
/// `sync=debug,state=trace`
|
||||
#[method(name = "system_addLogFilter", with_extensions)]
|
||||
fn system_add_log_filter(&self, directives: String) -> Result<(), Error>;
|
||||
|
||||
/// Resets the log filter to Substrate defaults
|
||||
#[method(name = "system_resetLogFilter", with_extensions)]
|
||||
fn system_reset_log_filter(&self) -> Result<(), Error>;
|
||||
}
|
||||
Reference in New Issue
Block a user