Introduction

Our previous guide (a prerequisite for this guide) covered the basics of RPC nodes and their role in blockchain networks. RPC (remote procedure call) nodes process JSON-RPC requests and provide access to blockchain data and operations. Unlike full nodes, which store the entire blockchain and participate in consensus, RPC nodes act as intermediaries between users and the blockchain network.

RPC nodes have a complex internal architecture comprising various components that work together to enable its intricate functionalities. Understanding how these components are structured and interact is crucial for anyone building decentralized applications using RPC nodes.

This post will examine the internal architecture of a typical RPC node. We will discuss the key components, including the client handler, core engine, router, decoders, and encoders. We will explore each component's responsibilities and how they fit into the workflow.

We will also examine how these components communicate with each other to handle RPC requests and responses. A case study of a real-world RPC node implementation will help demonstrate how the architecture works in practice. We’ll also examine the security architecture of RPC nodes. This knowledge can inform decisions ranging from selecting RPC nodes to developing improvements.

Components of an RPC Node

An RPC node consists of several key components, each serving a specific function. These components handle client requests, execute commands, and return responses. These components include:

  1. Client Handler.

  2. Core Engine.

  3. Router.

  4. Request Decoder.

  5. Response Encoder.

Client Handler

Overview

The client handler manages all client interactions. It receives incoming requests and parses them to validate the format. The client handler also queues valid requests, sends them to the core engine for processing, and receives the response afterward. Once the core engine executes the command and generates the response, it formats it according to the requested encoding format and sends it back to the client. The client handler also handles network connections and disconnections.

Functions

The client handler is one of the most important architecture components of an RPC node. Its primary responsibilities include.

  1. Receiving requests from clients.

  2. Routing requests to other components.

  3. Returning responses to clients.

  4. Managing client connections.

They act as the interface between the node and external clients looking to make RPC calls. The client handler listens on the configured ports for incoming TCP/IP connections and HTTP requests. When a new request comes in, the client handler accepts the connection and begins processing the request.

Operation

First, it parses the raw request to extract essential information, such as the RPC method being called and the parameters being passed. Next, it packages the request into an internal message format with all the details needed to process it further. It then routes this message to the appropriate internal component based on the requested RPC method.

Once the request has been processed, the client handler will receive the response message from the internal components. It takes this internal response and encodes it into the expected format for the external client, usually JSON. Finally, it sends this formatted response to the originating client over the established TCP/IP or HTTP connection.

In addition to request-response processing, the client handler manages persistent connections from long-running clients. It utilizes connection pooling and keep-alive messages to maximize performance across multiple requests. The client handler must be optimized for concurrency to handle high volumes of simultaneous client connections.

Core Engine

Overview

The Core Engine of an RPC node serves as the heart of the node's operation. It executes the commands specified in RPC requests, interacting directly with the blockchain's ledger, database, or state. These requests include validating transactions, updating the ledger, and retrieving data in response to queries. The Core Engine ensures that every operation adheres to the blockchain's protocols and consensus rules.

Functions

The Core Engine's primary responsibilities encompass:

  1. Processing Transactions.

  2. Maintaining State.

  3. Generating Blocks (for block-producing nodes).

  4. Executing Smart Contracts (In blockchains supporting smart contracts).

  5. Retrieving Data.

Operation

The Core Engine receives packaged requests from the Client Handler. These requests can range from transaction submissions to data queries. Upon receiving the request, the Cor Engine validates the request's authenticity and syntax. This involves verifying digital signatures and checking the transaction's format for transaction requests.

Depending on the request type, the Core Engine then executes the operation. For transactions, this means applying the transaction's effects to the current state. It involves retrieving the requested data from the blockchain's database for queries. While in nodes responsible for producing blocks, this involves participating in the blockchain's consensus mechanism to agree on the next block.

After successfully executing transactions, the Core Engine updates the blockchain's state, which might involve modifying account balances, smart contract states, or other relevant data. Once the operation is complete, the Core Engine packages the result into an internal message. This could be a confirmation of a transaction's inclusion, the output of a smart contract execution, or the requested data.

After packaging the response, the core engine sends it back to the client handler, who then formats it according to the client's requirements and sends it over the network.

Here is an example walkthrough for the eth_call RPC Method:

Source: Moralis.

Router

Overview

The Router is a critical component within an RPC node, serving as the intermediary that directs incoming and outgoing network traffic between the Client Handler and the Core Engine. Its role is to determine the destination of each incoming request and ensure that the corresponding responses are steered back to the correct client. Unlike the Client Handler, which directly manages client communication, the Router focuses more on the internal flow of messages within the node.

Functions

The Router primarily deals with:

  1. Directing Incoming Requests.

  2. Traffic Optimization.

  3. Response Dispatching.

The Router constantly evaluates the optimal paths for data to travel through the node, making real-time decisions to increase efficiency.

Operation

When a packaged request arrives at the Router from the Client Handler, the Router first inspects the request to understand its nature, including the type of operation requested and the specific internal component it needs to be directed to, such as the Core Engine for executing transactions or a data retrieval component for fetching information.

Based on predefined rules and the system's current status, including considerations of load and priority, the Router then determines the most efficient path for the request to travel to its destination. This process could involve queueing the request if the target component is busy or immediate handling if sufficient resources are available.

The Router retrieves the resulting response after the Core Engine or another component processes the request. It identifies the origin of the initial request through sophisticated tracking mechanisms, ensuring that the response is accurately routed back to the Client Handler that generated the initial connection. This careful management ensures the client's reply is correctly directed.

Furthermore, throughout this process, the Router actively monitors network traffic and system performance, adjusting routing configurations and paths to optimize efficiency and maintain robust system operation even under varying loads.

Here is a diagram illustrating the lifecycle of a transaction submitted to a network and processed by an authoring node.

Source: Substrate’s Docs.

Request Decoder

Overview

The Request Decoder is a critical component in an RPC node dedicated to analyzing and interpreting incoming requests. Its primary function is to dissect network requests into understandable, actionable components for further processing within the RPC node infrastructure. The Request Decoder ensures that requests are in the correct format and conform to expected protocols before they’re handed off for processing.

It supports decoding at serialization formats like JSON, XML, and protocol buffers. For example, if a client sends a JSON-RPC request, the request decoder validates the request format and parses the JSON payload into a request object consumable by the core engine.

Functions

The Request Decoder fulfills several vital functions, including:

  1. Decoding and validation.

  2. Extraction of RPC Method and Parameters.

  3. Request Standardization.

These functions make the Request Decoder a gateway for translating external communication into internally usable instructions.

Operation

Upon receipt of a new request by the Client Handler, the Request Decoder takes over to parse and decode the request. The decoder starts by parsing the raw request data to confirm it adheres to the expected request structure, such as JSON-RPC 2.0 specifications. This initial step involves validating the syntax and semantics against the supported protocols.

Afterward, The Request Decoder identifies the specific RPC method being invoked and the parameters supplied, separating each discrete piece of information. Following identification, the decoder standardizes the request, converting it into a uniform internal message format. This standardization ensures consistency in how the Core Engine or other specialized components process the request.

If a request cannot be parsed or fails validation, the decoder generates an error response detailing the issue. This response is formatted per the protocol specifications and sent back to the client through the Client Handler. Once a request is decoded and validated, it is packaged into an internal data structure, often along with metadata such as the request identifier or client context, and ready for routing.

Finally, once the request is validated and packaged with the necessary metadata, the Request Decoder signals that the Router or the next intended component is ready for further handling. Thus, the process is streamlined to ensure that the RPC nodes can handle the request quickly and accurately, bridging the client's input with the node's internal logic.

Response Encoder

Overview

The Response Encoder within an RPC node translates the processing results from the node's internal components into a format the client can understand and utilize. After the core engine or relevant processing component has executed the request and produced a response, the Response Encoder works to serialize this output into a standardized communication format, most commonly JSON or XML, depending on the client's specification.

Functions

The core functions of the Response Encoder are as follows:

  1. Serialization (internal to a suitable transmission format).

  2. Formatting.

  3. Compression & Optimization.

  4. Error Encoding.

Operation

After the RPC node’s internal components complete the request processing, the Response Encoder initiates its operation. Firstly, The Encoder fetches the internal representation of the response, which includes the execution's outcome and any data produced.

It then serializes the internal response into a widely accepted format, such as JSON, ensuring compatibility with various clients and adhering to the necessary communication protocols. Suppose the client has specified a particular encoding format, such as a specific version of JSON or a customized XML schema. In that case, the Response Encoder formats the serialized response to match this specification.

Before the response is sent over the network, applicable compression techniques reduce the response payload's size, improving the data transmission efficiency. If the internal components signal an error, the Response Encoder is also responsible for creating a structured error message that gives the client sufficient detail to understand and possibly rectify the issue.

Finally, after ensuring the response data is correctly encoded, compressed, and error-free, the Response Encoder returns the response to the Client Handler. The Client Handler sends this response to the client over the previously established network connection, be it TCP/IP or HTTP/S.

Component Interactions

The various components within an RPC node architecture need to communicate seamlessly to enable overall functionality. Understanding these interactions provides insight into the inner workings of an RPC node.

  1. The client handler sits at the edge of the node, providing the interface for external applications to connect and make RPC calls. When a request comes in, the client handler authenticates the client and passes the request to the request decoder.

  2. The request decoder parses the request, extracts vital information like the method name and parameters, and constructs an internal request object. This request object is then passed to the router.

  3. The router examines the internal request to determine which core engine method should handle it. The router passes the request object to the appropriate core engine component.

  4. The core engine contains the business logic and methods for executing RPC commands. Once it processes the request, it generates a response object and returns this to the router.

  5. The router sends the response object back to the response encoder, which encodes it into the expected format, usually JSON.

  6. Finally, the response is returned to the external client through the client handler. Once the response is delivered, the client handler also closes the connection.

Here is a diagram showing request flow through RPC node components:

The key interfaces are the client handler and router, which decouple the external world from the internal node processing, providing stability and separation of concerns.

Security Architecture of RPC Nodes

The security architecture of RPC Nodes is paramount in ensuring that communication between clients and servers is both private and authenticated. Given the increasing sophistication of cyber threats, robust security mechanisms are integral to maintaining the integrity and confidentiality of data transmitted across networks.

Encryption and Security Protocols

RPC nodes often employ encryption methods and security protocols to secure their communication. The primary protocol in use is SSL/TLS (Secure Sockets Layer/Transport Layer Security), which ensures that data exchanged between the client and server is encrypted, making it incomprehensible to unauthorized parties.

SSL/TLS establishes an encrypted connection with two key components: a handshake and data transfer phases. During the handshake phase, the client and server agree on the protocol version to use, select cryptographic algorithms, and authenticate each other using digital certificates. Once the handshake is completed, the data transfer phase begins, where all transmitted data is encrypted using the agreed-upon cryptographic algorithms.

For instance, Ethereum’s Infura, one of the popular blockchain node providers, uses TLS to secure its RPC communication.

However, while SSL/TLS provides a robust security framework, it’s not impervious to vulnerabilities. For example, weaknesses in the protocol, such as the infamous Heartbleed bug in OpenSSL or poor implementation, can lead to security breaches. Furthermore, SSL stripping attacks can downgrade a connection to non-encrypted HTTP. RPC nodes must use up-to-date software libraries to mitigate these risks and enforce strict checks, such as Certificate Pinning and HSTS (HTTP Strict Transport Security).

Access Control and Authentication Mechanisms

Access control and authentication are other critical aspects of RPC node security. They ensure that only authorized entities can access the RPC endpoints.

Access Control Lists (ACLs) and Role-Based Access Control (RBAC) are two common mechanisms for managing access. ACLs specify which clients (identified by their IP addresses or other identifiers) can access the RPC node. On the other hand, role-based access control assigns roles to clients and determines access permissions based on these roles.

Authentication, on the other hand, verifies the identity of the clients. Common methods include using session tokens, representing the user's session with a unique identifier that must be passed with each request, or JSON Web Tokens (JWT), compact and self-contained tokens that carry JSON data. For example, Alchemy, another popular blockchain node provider, uses API keys (token-based authentication) to authenticate requests to RPC endpoints.

Here are the explanations, brief context, and reference links for each component:

Real-World Examples of RPC Node Components Across Blockchain Networks

Client Handler

  • Ethereum's Web3.js / web3.py (Java/Python Script library): These are Ethereum library collections for JavaScript and Python, respectively, used to interact with Ethereum nodes. They include functionality to handle client requests to the Ethereum blockchain.

  • Bitcoin - bitcoin-cli: A command-line client that interfaces with the bitcoind daemon to send RPC commands to a Bitcoin node. GitHub.

  • Polkadot Polkadot JS API (JavaScript library) is a JavaScript library that provides developers with the necessary tools to connect with and interact with the Polkadot blockchain efficiently.

  • Ripple - RippleAPI (ripple-lib): A JavaScript API for interacting with the XRP Ledger in Node.js and the browser. GitHub.

Core Engine

  • Ethereum - Ethereum Virtual Machine (EVM): is the runtime environment for smart contracts on the Ethereum blockchain.

  • Bitcoin - Bitcoin Script Engine: Executes the scripting language used for transactions on the Bitcoin blockchain.

  • Solana - Solana Runtime (Rust library): is the core engine for executing programs on the Solana blockchain.

  • Hyperledger—Chaincode (Hyperledger Fabric): This is the 'smart contract' layer where the business logic of Hyperledger Fabric blockchains is implemented, forming the core processing engine of the ledger.

Router

  • Cosmos - IBC protocol: This router component facilitates communication between blockchains in the Cosmos network. GitHub.

  • Polkadot, etc - Substrate's Message Queue: Substrate, the blockchain-building framework used by Polkadot, includes message queue systems for sending information between the runtime and the various off-chain workers.

  • IPFS, Ethereum 2.0, etc.—Libp2p is a modular network stack that can route various peer-to-peer connections and data exchanges.

Request Decoder

  • Ethereum - JSON-RPC Servers: It functions as a request decoder by interpreting JSON requests sent by clients and translating them into commands that the Ethereum node can execute.

  • Bitcoin - JSON-RPC Server (Bitcoin Core): This server decodes JSON-RPC requests and translates them into commands that the Bitcoin node can process.

  • NEAR - JSON RPC API: This API handles and decodes incoming JSON RPC requests for the NEAR blockchain, providing an interface to the chain's data and functionality.

  • Cardano - Cardano Serialization Library (Haskell library): is used to decode and validate data on the Cardano blockchain (GitHub).

Response Encoder

  • Bitcoin Core's JSON-RPC interface: Encodes responses from the Bitcoin node into JSON for client software to easily interpret.

  • Ethereum JSON-RPC API Responses: When an Ethereum node processes a call, the response is encoded back into a JSON object for the requesting client.

  • Avalanche API: The API for interacting with an Avalanche node encodes its responses in JSON format, which includes information like transaction details, blocks, and other blockchain-related data.

Case Study: Analyzing the Architecture of Geth

For in-depth details about the architecture of Geth, please check our previous guide.

Conclusion

The architecture of RPC nodes plays a crucial role in their performance and capabilities. This article has explored the critical components of an RPC node and how they work together to handle requests and return responses.

To recap, the main components of an RPC are:

  • Client Handler - receives requests and sends back responses.

  • Core Engine - processes requests and coordinates other components.

  • Router - routes requests to appropriate internal services.

  • Request Decoder - decodes requests into a readable format.

  • Response Encoder - encodes responses into the required format.

These components must seamlessly interact for efficient request-response workflows. The client handler acts as the interface, while the core engine handles the logic and computation. The router intelligently directs requests, and the decoders/encoders translate between external and internal formats.

The architecture must evolve as RPC nodes are adopted for more complex blockchain systems. We may see designs optimized for particular use cases like IoT networks or decentralized finance (DeFi). Machine learning could improve request routing and resource allocation within nodes. More advanced security mechanisms can be built into the architecture, too. The possibilities for innovating on RPC node architecture to power the decentralized future. are endless.

The architecture ultimately determines the capabilities of an RPC node. A sound, scalable design is crucial for performance as blockchain networks grow. Understanding these architectural foundations will be essential for developers building the next generation of RPC nodes.