大家好,以太坊源码分析–p2p节点发现相信很多的网友都不是很明白,包括如何识别以太坊全节点也是一样,不过没有关系,接下来就来为大家分享关于以太坊源码分析–p2p节点发现和如何识别以太坊全节点的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!
本文目录
以太坊源码分析–p2p节点发现
节点发现功能主要涉及 Server \ Table \ udp这几个数据结构,它们有独自的事件响应循环,节点发现功能便是它们互相协作完成的。其中,每个以太坊客户端启动后都会在本地运行一个 Server,并将网络拓扑中相邻的节点视为 Node,而 Table是 Node的容器, udp则是负责维持底层的连接。下面重点描述它们中重要的字段和事件循环处理的关键部分。
PrivateKey-本节点的私钥,用于与其他节点建立时的握手协商
Protocols-支持的所有上层协议
StaticNodes-预设的静态 Peer,节点启动时会首先去向它们发起连接,建立邻居关系
newTransport-下层传输层实现,定义握手过程中的数据加密解密方式,默认的传输层实现是用 newRLPX()创建的 rlpx,这不是本文的重点
ntab-典型实现是 Table,所有 peer以 Node的形式存放在 Table
ourHandshake-与其他节点建立连接时的握手信息,包含本地节点的版本号以及支持的上层协议
addpeer-连接握手完成后,连接过程通过这个通道通知 Server
Server的监听循环,启动底层监听socket,当收到连接请求时,Accept后调用 setupConn()开始连接建立过程
Server的主要事件处理和功能实现循环
Node唯一表示网络上的一个节点
IP- IP地址
UDP/TCP-连接使用的UDP/TCP端口号
ID-以太坊网络中唯一标识一个节点,本质上是一个椭圆曲线公钥(PublicKey),与 Server的 PrivateKey对应。一个节点的IP地址不一定是固定的,但ID是唯一的。
sha-用于节点间的距离计算
Table主要用来管理与本节点与其他节点的连接的建立\更新\删除
bucket-所有 peer按与本节点的距离远近放在不同的桶(bucket)中,详见之后的节点维护
refreshReq-更新 Table请求通道
Table的主要事件循环,主要负责控制 refresh和 revalidate过程。
refresh.C-定时(30s)启动Peer刷新过程的定时器
refreshReq-接收其他线程投递到 Table的刷新Peer连接的通知,当收到该通知时启动更新,详见之后的更新邻居关系
revalidate.C-定时重新检查以连接节点的有效性的定时器,详见之后的探活检测
udp负责节点间通信的底层消息控制,是 Table运行的 Kademlia协议的底层组件
conn-底层监听端口的连接
addpending- udp用来接收 pending的channel。使用场景为:当我们向其他节点发送数据包后(packet)后可能会期待收到它的回复,pending用来记录一次这种还没有到来的回复。举个例子,当我们发送ping包时,总是期待对方回复pong包。这时就可以将构造一个pending结构,其中包含期待接收的pong包的信息以及对应的callback函数,将这个pengding投递到udp的这个channel。 udp在收到匹配的pong后,执行预设的callback。
gotreply- udp用来接收其他节点回复的通道,配合上面的addpending,收到回复后,遍历已有的pending链表,看是否有匹配的pending。
Table-和 Server中的ntab是同一个 Table
udp的处理循环,负责控制消息的向上递交和收发控制
udp的底层接受数据包循环,负责接收其他节点的 packet
以太坊使用 Kademlia分布式路由存储协议来进行网络拓扑维护,了解该协议建议先阅读易懂分布式。更权威的资料可以查看 wiki。总的来说该协议:
源码中由 Table结构保存所有 bucket, bucket结构如下
节点可以在 entries和 replacements互相转化,一个 entries节点如果 Validate失败,那么它会被原本将一个原本在 replacements数组的节点替换。
有效性检测就是利用 ping消息进行探活操作。 Table.loop()启动了一个定时器(0~10s),定期随机选择一个bucket,向其 entries中末尾的节点发送 ping消息,如果对方回应了 pong,则探活成功。
Table.loop()会定期(定时器超时)或不定期(收到refreshReq)地进行更新邻居关系(发现新邻居),两者都调用 doRefresh()方法,该方法对在网络上查找离自身和三个随机节点最近的若干个节点。
Table的 lookup()方法用来实现节点查找目标节点,它的实现就是 Kademlia协议,通过节点间的接力,一步一步接近目标。
当一个节点启动后,它会首先向配置的静态节点发起连接,发起连接的过程称为 Dial,源码中通过创建 dialTask跟踪这个过程
dialTask表示一次向其他节点主动发起连接的任务
在 Server启动时,会调用 newDialState()根据预配置的 StaticNodes初始化一批 dialTask,并在 Server.run()方法中,启动这些这些任务。
Dial过程需要知道目标节点( dest)的IP地址,如果不知道的话,就要先使用 recolve()解析出目标的IP地址,怎么解析?就是先要用借助 Kademlia协议在网络中查找目标节点。
当得到目标节点的IP后,下一步便是建立连接,这是通过 dialTask.dial()建立连接
连接建立的握手过程分为两个阶段,在在 SetupConn()中实现
第一阶段为 ECDH密钥建立:
第二阶段为协议握手,互相交换支持的上层协议
如果两次握手都通过,dialTask将向 Server的 addpeer通道发送 peer的信息
以太坊多节点私有链部署
假设两台电脑A和B
要求:
1、两台电脑要在一个网络中,能ping通
2、两个节点使用相同的创世区块文件
3、禁用ipc;同时使用参数–nodiscover
4、networkid要相同,端口号可以不同
1.4搭建私有链
1.4.1创建目录和genesis.json文件
创建私有链根目录./testnet
创建数据存储目录./testnet/data0
创建创世区块配置文件./testnet/genesis.json
1.4.2初始化操作
cd./eth_test
geth–datadir data0 init genesis.json
1.4.3启动私有节点
1.4.4创建账号
personal.newAccount()
1.4.5查看账号
eth.accounts
1.4.6查看账号余额
eth.getBalance(eth.accounts[0])
1.4.7启动&停止挖矿
启动挖矿:
miner.start(1)
其中 start的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG文件,这个过程有点慢,等进度达到 100%后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
停止挖矿,在 console中输入:
miner.stop()
挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做 coinbase,默认情况下 coinbase是本地账户中的第一个账户,可以通过 miner.setEtherbase()将其他账户设置成 coinbase。
1.4.8转账
目前,账户 0已经挖到了 3个块的奖励,账户 1的余额还是0:
我们要从账户 0向账户 1转账,所以要先解锁账户 0,才能发起交易:
发送交易,账户 0->账户 1:
需要输入密码 123456
此时如果没有挖矿,用 txpool.status命令可以看到本地交易池中有一个待确认的交易,可以使用 eth.getBlock(“pending”, true).transactions查看当前待确认交易。
使用 miner.start()命令开始挖矿:
miner.start(1);admin.sleepBlocks(1);miner.stop();
新区块挖出后,挖矿结束,查看账户 1的余额,已经收到了账户 0的以太币:
web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
用同样的genesis.json初始化操作
cd./eth_test
geth–datadir data1 init genesis.json
启动私有节点一,修改 rpcport和port
可以通过 admin.addPeer()方法连接到其他节点,两个节点要要指定相同的 chainID。
假设有两个节点:节点一和节点二,chainID都是 1024,通过下面的步骤就可以从节点二连接到节点一。
首先要知道节点一的 enode信息,在节点一的 JavaScript console中执行下面的命令查看 enode信息:
admin.nodeInfo.enode
” enode://d465bcbd5c34da7f4b8e00cbf9dd18e7e2c38fbd6642b7435f340c7d5168947ff2b822146e1dc1b07e02f7c15d5ca09249a92f1d0caa34587c9b2743172259ee@[::]:30303″
然后在节点二的 JavaScript console中执行 admin.addPeer(),就可以连接到节点一:
addPeer()的参数就是节点一的 enode信息,注意要把 enode中的 [::]替换成节点一的 IP地址。连接成功后,节点一就会开始同步节点二的区块,同步完成后,任意一个节点开始挖矿,另一个节点会自动同步区块,向任意一个节点发送交易,另一个节点也会收到该笔交易。
通过 admin.peers可以查看连接到的其他节点信息,通过 net.peerCount可以查看已连接到的节点数量。
除了上面的方法,也可以在启动节点的时候指定–bootnodes选项连接到其他节点。 bootnode是一个轻量级的引导节点,方便联盟链的搭建下一节讲通过 bootnode自动找到节点
参考:
以太坊如何处理网络中节点的异常情况
以太坊如何处理网络中节点的异常情况?
以太坊是目前最流行的基于区块链技术的智能合约平台之一。在以太坊网络中,节点的健康状态对整个网络的运行非常重要。因此,以太坊开发人员开发了一些机制来处理网络中节点的异常情况。
一种常见的节点故障是节点丢失同步。这种情况发生在节点与其他节点之间的数据同步出现问题时。以太坊通过使用“GHOST”协议来处理这种情况。GHOST协议将在网络中被放弃的区块也考虑在内,从而在网络中创造一个更加完整的区块链。这有助于提高网络中节点的同步率和可靠性,从而减少丢失同步的情况。
另一种可能发生的节点故障是“链分裂”(chainsplitting)。这种情况发生在网络中有太多的分叉,导致不同的节点看到不同的区块链。以太坊使用一种称为“最长链规则”的协议来处理这种情况。该规则简单地指示以最长链为准,即大多数节点看到的链是正常的链。
还有一种节点故障是节点崩溃。这种情况发生在节点由于硬件或软件故障而导致无法正常运行。以太坊处理这种故障的方式是使用“分散式存储”。分散式存储的概念是将节点的信息存储在网络的多个节点和服务器中,而不是单一的节点。这样即使一个节点崩溃,数据仍然可以从其他节点恢复,使整个系统保持运行状态。
总的来说,以太坊已经做出了相当多的努力来处理网络中节点的异常情况。这种措施有助于保持网络的健康运行,并增强了整个以太坊平台的强大性能。
文章分享结束,以太坊源码分析–p2p节点发现和如何识别以太坊全节点的答案你都知道了吗?欢迎再次光临本站哦!
原创文章,作者:,如若转载,请注明出处:https://www.peipei.net/77622.html