以太坊源码之RPC服务

搭建过以太坊私链的同学或许都通过console或者Postman第三方工具去查询以太坊主链的相关信息,如通过区块高度查询区块信息。在以太坊的底层,这些都是通过RPC的调用去实现的,今天就来看看以太坊底层RPC启动方面的源码,了解一下RPC的启动过程。
RPC在以太坊源码中的启动步骤如下:

----- geth
-------- startNode
----------- utils.StartNode
-------------- Node.Start()
----------------- Node.startRPC
上述是RPC在以太坊启动过程中的调用路径,下面先来介绍一下与RPC相关的几个重要的数据结构:

type API struct {
	Namespace string      
	Version   string   
	Service   interface{} 
	Public    bool      
}
Namespace:命令空间,对模块进行命名,eg:eth,net,web3
Version   :模块的版本信息
Service   :执行模块的服务函数
Public    :模式是否运行外部调用

type Server struct {
    services serviceRegistry
    run      int32
    codecsMu sync.Mutex
    codecs   *set.Set
}
 run:该服务是否运行的状态
 codecsMu :sync的互斥锁
 codecs   :
 services :是一个map,key是Namespace,value是一个service实例。定义:type serviceRegistry map[string]*service
 
 下面看看server的定义:
 type service struct {
    name          string        
    typ           reflect.Type 
    callbacks     callbacks     
    subscriptions subscriptions 
}
name :模块名称
typ:接收的类型
callbacks     : 是一个map,key是Namespace,value是一个callback 实例。定义: type callbacks map[string]*callback 
subscriptions : 是一个map,key是Namespace,value是一个callback 实例。定义: type subscriptions map[string]*callback

下面看看callback的定义:
type callback struct {
    rcvr        reflect.Value  // receiver of method
    method      reflect.Method // callback
    argTypes    []reflect.Type // input argument types
    hasCtx      bool           // method's first argument is a context (not included in argTypes)
    errPos      int            // err return idx, of -1 when method cannot return error
    isSubscribe bool           // indication if the callback is a subscription
}
rcvr:方法的接收者,这是一个反射值类型,其实就是指向了之前的NewPublicEthereumAPI
method:对应rcvr中的函数
argTypes:函数参数的类型列表
hasCtx:标识函数的第一个参数是否是context.Context类型
errPos:错误代码数值
isSubscribe:是否是subscription类型

接下来我们一起看看RPC启动的源码:

源码路径:go-ethereum\node\node.go
func (n *Node) startRPC(services map[reflect.Type]Service) error {
	//创建apis
	apis := n.apis()
	for _, service := range services {
		apis = append(apis, service.APIs()...)
	}
	//基于apis启动服务
	if err := n.startInProc(apis); err != nil {
		return err
	}
	if err := n.startIPC(apis); err != nil {
		n.stopInProc()
		return err
	}
	if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors, n.config.HTTPVirtualHosts); err != nil {
		n.stopIPC()
		n.stopInProc()
		return err
	}
	if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins, n.config.WSExposeAll); err != nil {
		n.stopHTTP()
		n.stopIPC()
		n.stopInProc()
		return err
	}
	// All API endpoints started successfully
	n.rpcAPIs = apis
	return nil
}

startInProc:内部调用,没有启动相关Server服务
startIPC:启动IPC服务
startHTTP:启动http服务
startWS:启动WebSocket服务
如上述服务有一项启动失败,整体RPC服务启动失败,报错并退出!下面重点介绍一下httpRPC的启动过程,源码如下:

func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string) error {
	// http的IP和端口,默认localhost:8545
	if endpoint == "" {
		return nil
	}
	listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts)
	if err != nil {
		return err
	}
	n.log.Info("HTTP en
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值