# 前言
节点之间要组成一个P2P网络,又没有中心化节点,这些节点之间在P2P网络中进行信息传播,涉及到节点之间的连接管理、
地址管理、Peer节点的管理和Peer之间同步区块的协议等,参考比特币区块链的网络设计:
* btcd/peer:实现了P2P网络中Peer之间维持连接及收发wire协议消息的机制。
* btcd/wire:实现Bitcoin网络协议,定义理论Peers之间的协议消息,消息格式及包的封装和解析等。
* btcd/connmgr:管理Peer节点之间的TCP连接,包括监听本地端口等待其他节点连接和主动连接Peer节点等。
* btcd/addrmgr:收集、存储Bitcoin网络上的节点的地址,随机从地址集中选择路由可达的地址建立Peer连接,这些地址包括IPv4,IPv6及洋葱地址(onion address)等。
* netsync:同步管理器,用于统一处理各个节点发送和接收到的数据,以便同步区块链和同步交易。
* btcd/server.go:btcd节点启动后执行的主要入口,定义了server及serverPeer类型,负责初始化和启动connmgr,addrmgr,以及响应Peer的协议消息等。
与比特币区块链不同,我们不使用洋葱网络协议,而是使用libp2p作为网络协议。另外,本项目会先基于libp2p进行基本功能实现,并考虑DDOS攻击和钓鱼攻击的风险规避。
暂时不考虑实现SPV节点,而假定每一个节点都是全节点,关注点在三个区块链网络核心功能上:
1. 发现节点;
2. 同步区块;
2. 发布交易;
3. 挖矿(交易上链)
# 发现节点
比特币通过dns seed帮助节点发现其它节点,dns seed数据是硬编码到项目中的。
为了能够加入到比特币网络,区块链客户端会做一下几件事情:
a、节点会记住它最近成功连接的网络节点,当重新启动后它可以迅速与先前的对等节点网络重新建立连接。
b、节点会在失去已有连接时尝试发现新节点。
c、当建立一个或多个连接后,节点将一条包含自身IP地址消息发送给其相邻节点。相邻节点再将此消息依次转发给它们各自的相邻节点,从而保证节点信息被多个节点所接收、保证连接更稳定。
d、新接入的节点可以向它的相邻节点发送获取地址getaddr消息,要求它们返回其已知对等节点的IP地址列表。节点可以找到需连接到的对等节点。
e、在节点启动时,可以给节点指定一个正活跃节点IP, 如果没有,客户端也维持一个列表,列出了那些长期稳定运行的节点。这样的节点也被称为种子节点(其实和BT下载的种子文件道理是一样的),就可以通过种子节点来快速发现网络中的其他节点。
1、新节点自举,连接到区块链网络
区块链的核心部分维护一个在启动时可以连接的对等节点列表,并被硬编码到项目中。当一个新的节点第一次启动时,它必须被自举(bootstrapped)到网络。使用选项-dnsseed定义这种自举行为,默认的设置是1。**dns**请求命令返回一个可连接的IP地址列表。任何一个节点均可从那里可以连接到整个区块链网络。
自举过程完成后,节点向其对等节点发送一个包含其自身IP地址的**addr**消息。其对等的每个节点向它们自己的对等节点转发这个信息,以便进一步扩大连接池。
通过**getpeerinfo**命令可以查看某个节点所连接的对等节点及相关的数据。
小结:
这里涉及到3个命令需要实现:
(1)dns -dnsseed,默认值为1
(2)addr
(3)getpeerinfo -address 节点地址
# 连接到对等节点
节点通过发送version消息连接到一个对等节点。消息version 包含了节点的版本信息、块信息和距离远程节点的时间。一旦这个消息被对等节点收到,它必须回复一个verack。如果它愿意建立对等关系,它将发送自己的version消息。
一旦建立对等关系,节点可以向远程节点发送getaddr和addr消息来获得其它的对等节点信息。为了维持与对等节点的连接,节点默认情况下每30分钟内会给对等节点至少发送一次信息。如果超过90分钟没有收到回复,节点会认为连接已经断开。
这里需要实现1个新命令:
(1)version
# 块广播
在与对等节点建立连接后,双方互发包含最新块哈希值的getblocks消息。如果某个节点坚信其拥有最新的块信息或者有更长的链,它将发送一个inv消息,其中包含至多500个最新块的哈希值,以此来表明它的链更长。收到的节点使用getdata来请求块的详细信息,而远程的节点通过命令block来发送这些信息。在500个块的信息被处理完之后,节点可以通过getblocks请求更多的块信息。这些块在被接收节点认证之后得到确认。
新块的确认也可通过矿工挖到并发布的块来发现。其扩散过程和上述类似。通过之前的连接,新块以inv消息发布出去,而接收节点可以通过getdata请求这些块的详细信息。
需要实现的新命令:
(1)getblocks
(2)block
(3)inv
(4)getdata
# 交易的广播
和对等节点的交易通过inv消息来实现。如果收到了getdata信息,那么交易通过发送tx实现。对等节点收到有效的交易的信息后会通过类似的方式将其扩散。如果交易的信息在一段时间内没有被放进块中,那么交易将被从内存池中清除,而原节点将重新发送交易信息。
需要实现的新命令1个:
(1)tx
# 处罚行为不端的节点
对于所有的广播,那些行为不端的节点(占用带宽和通过发布错误信息来浪费计算资源)将收到惩罚。如果一个节点惩罚分数超过门限值-banscore=,它将被禁止加入网络若干秒。这个时间由参数-bantime=定义,默认值是86400秒,即24小时。(暂不实现)
# 警告
为了应对可能出现的bug和攻击,提供了比特币警告服务RSS。比特币用户通过命令getinfo可以查看针对其特定客户端版本的错误信息。这些信息通过allert消息尽可能多扩散出去给每一个连接的对等节点。错误信息采用特定的ECDSA私有密钥签名,只被极少数的开发者控制。(暂不实现)
# 四个类
## peer
实现P2P网络中Peer之间维持连接及收发wire协议消息的机制。
## wire
实现libp2p网络协议,定义理论Peers之间的协议消息,消息格式及包的封装和解析等。
## connmgr
管理Peer节点之间的TCP连接,包括监听本地端口等待其他节点连接和主动连接Peer节点等。
## addrmgr
收集、存储Bitcoin网络上的节点的地址,随机从地址集中选择路由可达的地址建立Peer连接,这些地址包括IPv4,IPv6及libp2p地址等。
## server
节点启动后执行的主要入口,定义了server及serverPeer类型,负责初始化和启动connmgr,addrmgr,以及响应Peer的协议消息等。
模块之间通信关系如下:
![](https://img.kancloud.cn/7f/ce/7fce39bf3eedb55684f2e72b9cef50c3_445x238.png)
- 重要更新说明
- linechain发布
- linechain新版设计
- 引言一
- 引言二
- 引言三
- vs-code设置及开发环境设置
- BoltDB数据库应用
- 关于Go语言、VS-code的一些Tips
- 区块链的架构
- 网络通信与区块链
- 单元测试
- 比特币脚本语言
- 关于区块链的一些概念
- 区块链组件
- 区块链第一版:基本原型
- 区块链第二版:增加工作量证明
- 区块链第三版:持久化
- 区块链第四版:交易
- 区块链第五版:实现钱包
- 区块链第六版:实现UTXO集
- 区块链第七版:网络
- 阶段小结
- 区块链第八版:P2P
- P2P网络架构
- 区块链网络层
- P2P区块链最简体验
- libp2p建立P2P网络的关键概念
- 区块链结构层设计与实现
- 用户交互层设计与实现
- 网络层设计与实现
- 建立节点发现机制
- 向区块链网络请求区块信息
- 向区块链网络发布消息
- 运行区块链
- LineChain
- 系统运行流程
- Multihash
- 区块链网络的节点发现机制深入探讨
- DHT
- Bootstrap
- 连接到所有引导节点
- Advertise
- 搜索其它peers
- 连接到搜到的其它peers
- 区块链网络的消息订发布-订阅机制深入探讨
- LineChain:适用于智能合约编程的脚本语言支持
- LineChain:解决分叉问题
- LineChain:多重签名
- libp2p升级到v0.22版本
- 以太坊基础
- 重温以太坊的树结构
- 世界状态树
- (智能合约)账户存储树
- 交易树
- 交易收据树
- 小结
- 以太坊的存储结构
- 以太坊状态数据库
- MPT
- 以太坊POW共识算法
- 智能合约存储
- Polygon Edge
- block结构
- transaction数据结构
- 数据结构小结
- 关于本区块链的一些说明
- UML工具-PlantUML
- libp2p介绍
- JSON-RPC
- docker制作:启动多个应用系统
- Dockerfile
- docker-entrypoint.sh
- supervisord.conf
- docker run
- nginx.conf
- docker基础操作整理
- jupyter计算交互环境
- git技巧一
- git技巧二
- 使用github项目的最佳实践
- windows下package管理工具