以太坊我爱编程

以太坊启动流程分析

2018-02-25  本文已影响490人  shi_qinfeng

pyethapp启动过程

pyethapp的启动实际上就是启动各个服务的过程。pyethapp提供的服务包括:

# 注意: 顺序代表服务启动的顺序, 后面的服务依赖于前面服务的启动
services = [
    DBService, 
    AccountsService, 
    NodeDiscovery, 
    PeerManager, 
    ChainService,
    PoWService, 
    JSONRPCServer, 
    IPCRPCServer, 
    Console]

所有服务都注册在ethApp的实例上:

image

主流程启动

image
  1. main入口在app.py, 只有一个函数调用: app(), 该函数主要功能是根据输入参数以及默认配置生成一个config词典,便于后面各个服务获取相关的配置.
  2. 执行子命令run(...)
image
  1. 配置p2p的默认监听端口=29873
  2. 创建一个app实例: app=EthApp(BaseApp) , 其中BaseApp是pydevp2p组件提供的, 主要用于服务的注册( register_service ) , 并负责启动服务( service.start()) .
  3. 实例化一个AccountsService服务, 并注册到EthApp
  4. 注册AccountsService服务后,就可以处理账户相关的操作了。
  5. 启动参数中指定unlock的账户, 对该账户进行解锁,;
  6. 检查coinbase是否已经配置,没有配置的话设置为默认的accounts[0];
  7. 如果配置需要启动console, 记录启动标识符: app.start_console = console
  8. 检查是否有用户自定义的服务。
用户可以自定义服务, 将py文件放在pyethapp/contrib下, module的名字就是文件名

1\. 获取该module下继承BaseService的类;
1\. 获取on_block和on_start函数,生产成一个 `_OnBlockCallbackService`  服务,该服务下start函数和cb函数对应为on_block和on_start函数, 该服务作为用户自定义服务;

  1. 实例化并注册上面services 中的所有服务;
  2. 启动app: app.start() , 实际上就是启动所有服务: service.start()

各个服务的主要初始化和启动

在上面注册和实例化服务过程中,实际上是初始化和启动服务的过程。下面分析下各个服务的初始化流程。

DBService(levelDB/LmDB/CodernityDB/EphemDB Service)服务

顾名思义该服务和数据库相关,主要动作是根据配置实例化一个数据库, 默认 db_service = levelDB; 该数据库用来持久化所有区块链相关的数据

AccountsService服务

该服务除了处理unlock参数之外,还要:

  1. 解析keystore文件夹中的账户文件, 并保存公钥私钥到accounts数组中;
  2. 配置coinbase地址:默认是accounts[0],如果配置了pow.coinbase_hex, coinbase就是pow.coinbase_hex;

NodeDiscovery服务

该服务提供节点发现功能,是p2p的底层协议。p2p节点发现的默认监听地址是: 0.0.0.0:30303

  1. 首先实例化一个发现协议: DiscoveryProtocol(app=self.app, transport=self)

  2. 然后start(): 启动过一个udp服务,监听报文, 报文处理函数是 _handle_packet:

    self.server = DatagramServer((ip, port), handle=self._handle_packet)

  3. 配置bootstrap...

WiredService服务: p2p网络的线上服务. 提供2个接口。

on_wire_protocol_start(proto) 
on_wire_protocol_stop(proto)

继承该类的服务可以自定义接口的实现, 系统中有2个服务基层了该服务:

PeerManager继承自该服务. 初始化如下:

  1. 每个node都有一个私钥,根据私钥配置nodeid, 配置监听的 host : port

  2. 在p2p的监听地址上创建一个TCP服务端, 接受新连接并为每个连接创建一个协程,协程函数是用户提供的: _on_new_connection

  self.server = StreamServer(self.listen_addr, 
  handle=self._on_new_connection)
  1. 配置线上协议 wire_protocol = P2PProtocol 。这个线上协议实现的就是协议层的功能。

  2. start(): 启动上面创建的tcp服务端, 延时0.001秒后启动一个线程连接bootstrap_nodes: _bootstrap(bootstrap_nodes)
    5.1 从bootstrap_nodes的uri中获取对端的ip, port, pubkey
    5.2 建立socket连接, 连接成功, 创建一个Peer实例,并维护长连接 _start_peer(),详见p2p服务章节.

  3. start(): 延时1s,启动任务 _discovery_loop 每隔0.5秒就检查节点, 从节点发现协议kademlia中获取节点信息,并连接。

ChainService继承自该服务。初始化如下:

  1. 配置线上协议 wire_protocol = ETHProtocol 。这个线上协议实现的就是协议层的功能;

  2. 实例化一个Chain数据结构, 配置包括db,创世块数据,矿工地址,及new_head_cb的处理函数;

  3. 新建一个block同步器Synchronizer, 新建一个block队列block_queue, 新建一个交易池TransactionQueue和广播过滤器DuplicatesFilter;

  4. 启动一个处理time_queue的定时任务, 周期5s, time_queue用来保存时间戳混乱的block;

PoWService

  1. 启动一个进程 powworker_process
  2. 注册chain的一个回调处理函数:on_new_head_cbs=mine_head_candidate

console服务

提供控制台操作入口

RPCServer

rpc 命令包括 Web3, Personal, Net, Compilers, DB, Chain, Miner, FilterManager

rpc相关的详细描述见: https://www.notion.so/RPC-9eda75aaa51a4277a2aeb4cd9ae3693a

初始化阶段启用下面2个服务:

  1. JSONRPCServer 继承自该服务. 初始化如下:
    1.1. 注册上面的rpc子命令到dispatcher
    1.2. 启动wsgi服务和jsonrpc服务
    transport =WsgiServerTransport( queue_class=gevent.queue.Queue, allow_origin=self.config['jsonrpc']['corsdomain'])
    self.wsgi_server = gevent.wsgi.WSGIServer(listener, transport.handle, log=WSGIServerLogger) self.rpc_server = RPCServerGreenlets( transport, JSONRPCProtocol(), self.dispatcher )
    1.3. 启动wsgi服务和jsonrpc服务
    self.wsgi_thread = gevent.spawn(self.wsgi_server.serve_forever) self.rpc_server.serve_forever()

  2. IPCRPCServer继承自该服务. 初始化如下:
    2.1 默认ipcpath='/tmp/pyethapp.ipc'
    2.2 实例化一个分发器: LoggingDispatcher(RPCDispatcher)
    2.3 启动1个rpc-server
    self.transport = IPCDomainSocketTransport( queue_class=gevent.queue.Queue, sockpath=self.ipcpath, )
    self.rpc_server = RPCServerGreenlets( self.transport, JSONRPCProtocol(), self.dispatcher )
    2.4. 启动socket服务和rpc服务

    self.socket_server = gevent.spawn(serve, self.transport.socket, handler=self.transport.handle) self.rpc_server.serve_forever()

validator Service

和casper混合挖矿有关, 目前版本还在开发中。

上一篇 下一篇

猜你喜欢

热点阅读