feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit 286de54384
6841 changed files with 1848356 additions and 0 deletions
+44
View File
@@ -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",
]
+5
View File
@@ -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::<()>),
}
}
}
+77
View File
@@ -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>;
}
+61
View File
@@ -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(),
}
}
}
+64
View File
@@ -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>;
}
+29
View File
@@ -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;
}
+38
View File
@@ -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>;
}
+71
View File
@@ -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>,
}
+303
View File
@@ -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}"#,
);
}
}
+121
View File
@@ -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>;
}