#
pezkuwi_sdk_docs/reference_docs/
custom_runtime_api_rpc.rs

    1//! # Custom RPC do's and don'ts
    2//!
    3//! **TLDR:** Don't create new custom RPCs. Instead, rely on custom Runtime APIs, combined with
    4//! `state_call`.
    5//!
    6//! ## Background
    7//!
    8//! Pezkuwi-SDK offers the ability to query and subscribe storages directly. However what it does
    9//! not have is [view functions](https://github.com/pezkuwichain/pezkuwi-sdk/issues/101). This is an
    10//! essential feature to avoid duplicated logic between runtime and the client SDK. Custom RPC was
    11//! used as a solution. It allow the RPC node to expose new RPCs that clients can be used to query
    12//! computed properties.
    13//!
    14//! ## Problems with Custom RPC
    15//!
    16//! Unfortunately, custom RPC comes with many problems. To list a few:
    17//!
    18//! - It is offchain logic executed by the RPC node and therefore the client has to trust the RPC
    19//!   node.
    20//! - To upgrade or add a new RPC logic, the RPC node has to be upgraded. This can cause significant
    21//!   trouble when the RPC infrastructure is decentralized as we will need to coordinate multiple
    22//!   parties to upgrade the RPC nodes.
    23//! - A lot of boilerplate code is required to add custom RPC.
    24//! - It prevents dApps from using a light client or an alternative client.
    25//! - It makes ecosystem tooling integration much more complicated. For example, dApps will not
    26//!   be able to use [Chopsticks](https://github.com/AcalaNetwork/chopsticks) for testing as
    27//!   Chopsticks will not have the custom RPC implementation.
    28//! - Poorly implemented custom RPC can be a DoS vector.
    29//!
    30//! Hence, we should avoid custom RPC.
    31//!
    32//! ## Alternatives
    33//!
    34//! Generally, [`sc_rpc::state::StateBackend::call`] aka. `state_call` should be used instead of
    35//! custom RPC.
    36//!
    37//! Usually, each custom RPC comes with a corresponding runtime API which implements the business
    38//! logic. So instead of invoke the custom RPC, we can use `state_call` to invoke the runtime API
    39//! directly. This is a trivial change on the dApp and no change on the runtime side. We may remove
    40//! the custom RPC from the node side if wanted.
    41//!
    42//! There are some other cases that a simple runtime API is not enough. For example, implementation
    43//! of Ethereum RPC requires an additional offchain database to index transactions. In this
    44//! particular case, we can have the RPC implemented on another client.
    45//!
    46//! For example, the Acala EVM+ RPC are implemented by
    47//! [eth-rpc-adapter](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-rpc-adapter).
    48//! Alternatively, the [Frontier](https://github.com/pezkuwi-evm/frontier) project  also provided
    49//! Ethereum RPC compatibility directly in the node-side software.
    50//!
    51//! ## Create a new Runtime API
    52//!
    53//! For example, let's take a look at the process through which the account nonce can be queried
    54//! through an RPC. First, a new runtime-api needs to be declared:
    55#![doc = docify::embed!("../../substrate/frame/system/rpc/runtime-api/src/lib.rs", AccountNonceApi)]
    56//!
    57//! This API is implemented at the runtime level, always inside [`sp_api::impl_runtime_apis!`].
    58//!
    59//! As noted, this is already enough to make this API usable via `state_call`.
    60//!
    61//! ## Create a new custom RPC (Legacy)
    62//!
    63//! Should you wish to implement the legacy approach of exposing this runtime-api as a custom
    64//! RPC-api, then a custom RPC server has to be defined.
    65#![doc = docify::embed!("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)]
    66//!
    67//! ## Add a new RPC to the node (Legacy)
    68//!
    69//! Finally, this custom RPC needs to be integrated into the node side. This is usually done in a
    70//! `rpc.rs` in a typical template, as follows:
    71#![doc = docify::embed!("../../templates/minimal/node/src/rpc.rs", create_full)]
    72//!
    73//! ## Future
    74//!
    75//! - [XCQ](https://forum.network.pezkuwichain.io/t/cross-consensus-query-language-xcq/7583) will be a good
    76//! solution for most of the query needs.
    77//! - [New JSON-RPC Specification](https://github.com/paritytech/json-rpc-interface-spec)