远程过程调用 RPC

RPC 是 Remote Procedure Call 的缩写,即远程过程调用,它是一种计算机通信协议,用于在计算机网络中的不同系统之间进行通信和调用远程服务。它允许一个程序调用另一个计算机上的程序,并且就像调用本地程序一样,使得远程服务的使用者无需了解底层的网络细节。

在区块链领域,RPC 是一种常见的通信协议,用于与区块链节点进行交互和调用节点上的方法或功能。

Solana RPC 就是 Solana 区块链提供的一种远程过程调用协议,允许开发者通过 RPC 接口与 Solana 主网或测试网的节点进行通信,并执行一系列操作,如获取区块信息、查询交易状态、部署智能合约等。它是用户界面和区块链之间的桥梁,是开发者构建 Solana DApps  的重要工具之一。

通过 Solana RPC,开发者可以使用各种编程语言(如 JavaScript、Python、Go 等)编写应用程序或脚本,与 Solana 区块链进行交互并访问其功能。例如,开发者可以使用 Solana RPC 获取最新的区块高度、查询某个地址的余额、发送交易等操作,从而构建各种类型的去中心化应用或工具。

Solana 提供的 RPC 分为:主动请求的 HTTP 接口 消息推送的 Websocket 接口

单次查询一般使用 HTTP 接口,如发送交易,查询用户余额,而对于链上数据的监控则通过 Websocket 接口,如监控合约执行的日志。

HTTP 接口

HTTP 接口是通过 JSON RPC 的格式对外提供服务。

JSON RPC 是一种以 JSON 作为序列化工具,HTTP 作为传输协议的 RPC  模,当前使用的是 v2 版本。

请求格式为:

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getBalance",
    "params": [
       "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"
    ]
}

数据结构中的 Key 是固定的,其中:

  • jsonrpc 表示协议办法本号;
  • id 表示序号;
  • method 表示 RPC 的函数方法名;
  • params 表示该函数的参数。

对应的请求结果为:

{
    "jsonrpc": "2.0",
    "result": {

            },
    "id": 1
}

这里的 Key 也是固定的,其中:

  • result 表示请求的结果;
  • id 与请求里面的 id 对应,表示的是哪个请求的结果。

在请求查询的时候,对查询的结果有三种状态选择:

  • 'finalized' - 节点将查询由超过集群中超多数确认为达到最大封锁期的最新区块,表示集群已将此区块确认为已完成。
  • 'confirmed' - 节点将查询由集群的超多数投票的最新区块。
  • 'processed' - 节点将查询最新的区块。注意,该区块可能被集群跳过。

状态参数可以在 "params" 数组的最后,以字典的形式带入进去。

同时 Solana 也对常用的结果做了人为可读的优化。

当传递 "encoding":"jsonParsed" 会讲结果尽量以 JSON 的方式返回。

encoding 和上面的状态放在同一个位置。

例如:

{
   "commitment":"processed",
   "encoding":"jsonParsed"
}

Websocket 接口

WebsocketHTTP 为了补充长链接,而增加一个特性,概括来说就可以认为这个是一条 TCP 长连接。Solana 通过这条连接来给客户端推送消息。

只是这里的消息的内容也是采用了 JSONRPC 的格式,如:

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "accountSubscribe",
    "params": [
       "CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12",
       {
          "encoding": "jsonParsed",
          "commitment": "finalized"
        }
    ]
}

这样的消息订阅了 Account("CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12") 的变化消息。

当有变化时,也是将结果打包成一个 JSONRPC 的格式推送给客户端:

{
  "jsonrpc": "2.0",
  "method": "accountNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5199307
      },
      "value": {
        "data": {
          "program": "nonce",
          "parsed": {
            "type": "initialized",
            "info": {
              "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX",
              "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k",
              "feeCalculator": {
                "lamportsPerSignature": 5000
              }
            }
          }
        },
        "executable": false,
        "lamports": 33594,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 635,
        "space": 80
      }
    },
    "subscription": 23784
  }
}

每个 Subscribe 方法,都对应的有一个 Unsubscribe 方法,当发送改方法时,服务器后续不再推送消息。