以太坊RPC源码分析

本文深入剖析以太坊的RPC流程,包括API的注册和调用。首先介绍了API注册,从Service的构造到API的收集、命名空间管理,再到HTTP服务器的启动。接着详细阐述API调用流程,从接收到的数据解析,到反射调用API,最后形成响应并返回。通过源码分析,清晰揭示了以太坊RPC的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇过了一下以太坊的启动流程,这篇详细分析一下RPC的完整流程。

以太坊遵循JSON RPC规范,API列表参见以下链接:

https://github.com/ethereum/wiki/wiki/JSON-RPC

本文主要分析一下API注册和API调用的主要流程。

1. API注册流程

先看一张图,理清各组件之间的关系:

上篇提到,Node启动时会调用各Service的构造函数创建Service实例。Service是一个接口,要对外暴露RPC API的模块都需要实现该接口,比如Ethereum, Whisper, Swarm等等,在图中统一用<module>表示。

在Node的startRPC()函数中,首先会调用每个Service的APIs()函数,把所有RPC API收集到一个数组中:

    // Gather all the possible APIs to surface
    apis := n.apis()
    for _, service := range services {
        apis = append(apis, service.APIs()...)
    }

我们看一下API结构的定义,代码位于rpc/types.go:

type API struct {
    Namespace string      // namespace under which the rpc methods of Service are exposed
    Version   string      // api version for DApp's
    Service   interface{} // receiver instance which holds the methods
    Public    bool        // indication if the methods must be considered safe for public use
}

这里有一个Namespace的概念,可以理解为API的类别分组,方便管理。用过geth客户端的同学可能有印象,我们会在命令行指定类似下面的参数:

geth --rpc --rpcapi “eth,net,web3”

这里的eth,net,web3就是Namespace,指定了需要对外暴露哪些类型的RPC API。

除了Namespace,还有一个Service字段,注意它的类型是interface{},而不是我们之前提到的Service接口,所以个人感觉这个命名不太好,改成receiver可能就不容易引起混淆了。

那么这个Service指向哪里呢?我们以eth模块为例,看一下返回的API数组里到底存的是什么内容,代码位于eth/backend.go:

func (s *Ethereum) APIs() []rpc.API {
    ……

    // Append all the local APIs and return
    return append(apis, []rpc.API{
        {
            Namespace: "eth",
            Version:   "1.0",
            Service:   NewPublicEthereumAPI(s),
            Public:    true,
        }, {
            Namespace: "eth",
            Version:   "1.0",
            Service:   NewPublicMinerAPI(s),
            Public:    true,
        },
        ……)
}

其他先不看,我们先看下NewPublicEthereumAPI是个什么东西,代码位于eth.api.go:

func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI {
    return &PublicEthereumAPI{e}
}

type PublicEthereumAPI struct {
    e *Ethereum
}

可以看到就,就是一个普通的struct,内部有一个指针指向模块本身,其实就是一个wrapper。现在再回过头来看上面那张图的黄色部分,是不是就很清楚了?

获得所有RPC API的集合后,就开始启动RPC server了。上一篇提到RPC有4种方式:InProc、IPC、HTTP、WS,在Node中对应的字段都用不同颜色标识了。流程都是类似的,这里以HTTP为例进行分析。

HTTP相关的有3个字段:

 

  • httpEndpoint:这是一个字符串,表示IP和端口号,默认是localhost:8545
  • httpListener:这是一个接口,调用net.Listen()时返回,包含了Accept()/Close()/Addr()这3个函数,可以用来接受和关闭连接
  • httpHandler:这是一个需要重点分析的结构,定义位于rpc/types.go:
type Server struct {
    services serviceRegistry

    run      int32
    codecsMu sync
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值