BTC 学习笔记连载(12)——比特币网络

欢迎交流:twitter.com/songoku_web3

转载请注明出处~

Bitcoin:A Peer-to-Peer Electronic Cash System
(比特币:一种点对点的电子现金系统)

这是中本聪发布比特币白皮书的标题,这个“点对点”简单明了地点出了比特币网络的特点,比特币运行在应用层,它的底层基于一个P2P网络。

P2P、种子节点、邻居节点

Peer-to-Peer就是我们平常说的P2P,指位于同一网络中的每台计算机都彼此对等,节点之间互惠互利共同提供网络服务,不存在任何“特殊”节点,也因此具有可靠性、去中心化及开放的特性,著名的BitTorrent下载就是基于P2P的。

某些P2P网络是存在超级节点 (Super node) 的,超级节点比一般的节点行使更多的职责,但在比特币网络协议中节点是完全对等的,不存在任何服务器端、中心化服务及网络层级结构,也没有超级节点,整个网络节点以扁平的拓扑结构相连,任何节点都没有特权,节点之间协同互助:

我们熟知的Web2中 C/S 网络架构,任何客户端请求服务器端即可获取数据及服务,对等的P2P网络节点之间可不是这样的,比如节点A(比特币客户端)启动试图加入比特币网络时,是无从知晓任何其它活跃节点的。

为了新节点能够找到其它节点的IP地址,比特币系统把一些Dns Seed地址硬编码到比特币源码中,这个DNS种子我们通常称为种子节点(Seed node),种子节点会告诉节点A其它节点的信息:

Dns Seed由比特币社区维护,分为动态和静态两种,动态dns seed服务通过扫描网络自动获取活跃的节点IP地址,静态一般需要手动添加。

A节点通过种子节点就可以跟其它节点建立联系,节点启动时只需要连接一个对等节点,然后由这个节点再扩展其它节点,这个过程又会进一步持续,这些最终跟A节点连接的节点就是A的邻居节点

比特币网络并不需要所有节点都两两相连,每个节点只需要连接有限数量的节点即可,一个节点连接大量的邻居节点会对网络资源造成巨大浪费,而且也没有必要,比特币协议为了降低节点之间的过度消耗,规定任意节点的邻居节点最多125个

比特币网络里的交易(Transaction)及区块(Block)就是通过邻居节点广播出去的。

一个节点至少需要连接到几个不同的对等节点,以便建立进入比特币网络的不同路径。任何人/组织都可以作为节点随时加入比特币网络,也可以在任何时候离开!节点需要在失去旧连接时继续发现新节点,并在给予其他新节点帮助。当一个节点离开网络的时候不用通知其它节点,连接它的节点一段时间检测不到就会将它剔除,而当它重新回来的时候又可以再次连接。

除了节点之间完全对等之外,比特币网络的灵魂就是加入、离开这个网络时的自由性!

没有人为设置的准入门槛!

这就是去中心化!

这才是公链!

任何诚实节点的加入都将提升整个比特币系统的去中心化程度及安全性,任何个人/组织想作恶都将被其它节点排斥,这可能是天底下最公平的事。

什么?那个叫什么lana、什么SC的“公链”还有准入条件!

任何打着公链口号行联盟之事的都是耍流氓!

公链会Down机、停服、回滚么?

注意:上面说的没有准入门槛是指没有任何中心化的机构对节点加入设限。但是基本的软硬件还是需要达标的,比如磁盘空间、网络带宽等… 作为一个全节点至少要能无压力运行比特币核心软件吧,而且目前整个比特币账本数据量至少大几百个G了,存储空间及带宽需要保障吧。而这一点又实实在在会影响公链的参与门槛、去中心化程度及公链自身的安全性,整个账本数据量、区块大小、网络传输、甚至出块时长都是公链设计的核心问题。

比特币网络、全节点 & 轻节点

我们通常所说的比特币网络就是运行比特币点对点协议的一系列节点的集合,前面讲到这些节点是完全对等的,那为什么又常常会听到有全节点、轻节点之分呢?(以太坊还专门有存档节点)

这里的完全对等是指任何个人、组织都有行使对等节点的权利!

这句话怎么理解呢?(请自行思考一下……)

严格地讲节点之间还是有差异的,不同的节点支持不同的功能、行使不同的职责,任意一个节点都是由以下4个功能组成的一组集合:

  • Wallet (钱包)
    由字母W表示

  • Miner (挖矿)
    由字母M表示

  • Full Blockchain database (数据)
    由字母B或Full Blockchain来表示

  • Network routing (路由)
    由字母N表示

需要强调的是所有节点都包含路由功能,所有全节点都会验证并传播交易(Transaction)及区块(Block),所有节点都要发现并维护和其它对等节点的连接,并承担节点该行使的职责。

Bitcoin core

  • 比特币核心(Bitcoin Core)是比特币开源客户端
    最初由中本聪以“Bitcoin”命名,后改为“Bitcoin Core”

  • 包含所有4组功能

  • 拥有所有历史区块数据,可以自主验证交易及区块

  • 比特币发展初期的节点都是全节点,基本都是Bitcoin Core
    后来出现了 Bitcoin Classic, Bitcoin Unlimited, BitcoinJ, Libbitcoin, btcd, and bcoin等运行着各类比特币点对点协议的其他实现

Full Block Chain Node

  • 包含全部历史区块数据

  • 不具备挖矿及钱包功能

  • 可以构建边缘路由器(edge routers)搭建一系列服务
    eg:交易所、钱包、区块浏览器、商家支付处理(merchant payment processing)等

独立矿工

  • 运行矿机通过POW竞争挖矿的节点

  • 挖矿节点基本等同于全节点,存储区块链的完整历史数据

  • 这里的独立旷工跟后面的特殊矿机挖矿是有本质区别的
    比如Stratum protocol node、Mining protoclo node

轻量钱包

  • 不包含B/Full Blockchain,只存储Block header数据
    这样每个区块的存储数据相当于全节点的1/1000

  • 基于简单支付验证(Simplified payment verification)来验证交易
    需要向全节点请求数据才能验证交易

  • 随着比特币的普及越来越多的钱包应用流行起来,这些钱包都属于轻节点

除了比特币的P2P协议外,还有一些其它的网络协议,比如Stratum协议:

  • 在比特币发展的早期,矿工需要运行全节点才能与比特币协议连接及交互

  • 为规范矿工和比特币协议之间的通信,开源的getwork协议成为了矿工单机挖矿的快捷解决方案。

  • getwork协议基于HTTP,对多节点协同开采比特币来说太低效

  • 到了2012年挖矿算力呈指数倍增长,getwork协议的低效已经是无法忍受的问题了,而且它还要求相当大的网络带宽,矿池要满足所有矿工的带宽增长并不现实。

在2012年,Marek "Slush" Palatinus在getwork协议的基础上推出了阶层Stratum协议:

Stratum服务器通过Stratum协议,将一些特殊挖矿节点连接到比特币主网络,比特币主网络运行的是比特币P2P协议,我们使用“扩展比特币网络”来表示包含P2P协议、Stratum协议、矿池协议及连接比特币系统组件的其它任何协议的整个扩展网络。

如图Mining Nodes包括Stratum protocl node、Pool mining protocol node,这是和Solo Miners有本质区别的,这2类节点通过Pool Protocl Servers连接到比特币主网,一些小矿工可以只需要提供算力接入矿池,由矿池行使全节点的职责。

运行P2P协议的比特币主网络节点大约有10000+,其中绝大部分是运行着不同版本Bitcoin Core的监听节点,有几百个是运行着各类比特币P2P协议的应用的节点,比如BitcoinJ、Libbitcoin、btcd… 比特币P2P网络中绝大部分都是轻节点,一小部分是挖矿节点,它们验证交易、打包区块、抢夺记账权:

这个图演示了整个比特币网络的主要节点类型及关系,是不是有点复杂。

把它简化一下,本质上节点大类划分就是:全节点、轻节点

包含Full Blockchain database功能的节点就可以等同于全节点,同时又可以有挖矿、钱包的能力;只有部分数据而需要SPV辅助验证交易的都是轻节点,轻节点也可以参与挖矿;

Flooding、Gossip & Kademlia

比特币的设计原则是:

Simple, robust, but not efficient!

区块链是解决去中心化问题的,不是解决效率问题的!不是所有Web2干过的事情都适合搬到Web3来再干一遍,所有需要强调效率的场景都不太适合直接用区块链来解决!

Anyway,拉回来!比特币网络中每个节点都要维护一个邻居节点的集合,消息在节点之间传播基于Flooding算法。

什么是Flooding?

简单地讲就是一个节点收到一条消息后,就将其广播给邻居节点,收到交易的节点重复这个过程,直到传播给整个网络。

之前有同事分享讲到交易会在节点之间来回传播N多次,是这样吗?

  • 当D收到一笔交易Tx 1001验证合法后,广播给自己的邻居节点B、C

  • C很快验证完就将交易Tx 1001广播给A

  • B随后验证完也将交易Tx 1001广播给自己的邻居节点

  • 当B广播完成之后,A也将交易Tx 1001广播给B

当B收到相同的一笔交易Tx 1001时怎么处理?继续广播吗?

显然不是!Flooding算法考虑到了P2P网络节点的负担,B节点收到重复的消息就不会再次广播了!Transaction和Block都是这样,而且如果验证不合法会直接丢弃。

但就算是这样,依然有引发广播风暴的风险。

什么是广播风暴?

广播风暴就是网络上数据被大量转发导致带宽下降甚至瘫痪的情况。

我们之前讲到比特币网络节点最多可以由125个邻居节点,给这么多节点不停地广播Transaction、Block当然有风险造成广播风暴。

比特币网络当然要解决这个问题,基于Flooding改进的Gossip算法就能缓解这个问题。Gossip算法不会广播给所有的邻居节点,而是随机选择1个或多个邻居节点进行广播,每个节点都这么干同样能很快将消息同步给全网。

还记得我们前面讲过比特币节点是完全对等的吗?这种对等性就是连地理位置信息都没有的,上面那张图中的C可能在东京,B可能在巴西,他们都是A的邻居节点。他们之间的网络传输效率可能不一样,但他们在比特币网络拓扑结构来看就像在你隔壁一样。

这将对等、自由、随机及去中心化体现得淋漓尽致。

但是需要这么对等、这么随机么?

权衡效率和安全性及应用场景等一系列问题,其实也不一定要那么严格!

以太坊采取的方式跟比特币不同,是一个叫Kademlia的算法,属于DHT(分布式哈希表)。这种方式下每个节点都会存储一张该系统的部分网络拓扑图,这个图以哈希表形式存储,这个表可以分散地更新。即使自己的表中不存在某一节点,也可以通过XOR距离找到和该节点距离较近的节点。在做数据分发的时候,由于拓扑结构明确,可以大大的优化网络传输的数据量,BT、电驴等都是用的这种算法。

Forking 问题

我们前面文章也讲到过,比特币是一个开放的分布式系统,这个系统:

  • 没有裁判(中心化权威机构)

  • 但有规则

这些规则包括:区块大小不超过1M、区块挖矿难度、基于UTXO的交易合法性、私钥签名交易公钥验证…… 这些规则就形成我们所谓的共识协议,遍布全世界的所有比特币节点都共同遵守并维护这些规则,任何不遵循这些规则的行为都不会被全网的诚实节点所接受,这对持有比特币的用户来讲都是至关重要的。

对于比特币网络来讲,有2条规则要再次强调一下:

  1. 所有诚实节点都会接受先收到的合法交易(Transaction)及区块(Block)

  2. 所有诚实节点都遵循最长合法链原则

第1点怎么理解?

结合上图我们做个假设:

  • Alice有1.5个BTC

  • Alice签名了2笔交易并进行广播
    Tx 1001:Alice → Bob 1BTC
    Tx 1002:Alice → Cooper 0.8BTC
    显然这2笔交易单独看都是OK的,但合在一起就涉嫌双花

  • 节点1先收到Tx 1001,通过自己的UTXO验证这是一笔合法交易
    于是接收这笔交易至Transaction Pool里,然后继续广播这笔交易,如图节点2也收到了Tx 1001

  • 节点3先收到Tx 1002,通过自己的UTXO验证这是一笔合法交易
    同样将这笔交易广播给节点4

节点1、节点2随着时间推移也必将收到了Tx 1002,一验证就知道Alice之前1.5个BTC的UTXO已经“用过了”,剩余已不足0.8个BTC了,于是就会将Tx 1002视为一笔非法交易抛弃掉。节点3、节点4对待Tx 1001也是同理。

这样就会导致不同的节点之间接受的交易有所差异,UNconfirm Transaction Pool里的交易必然会有不同,打包的区块也必将有差异,在比特币的共识协议下这些都是合法的,但到底哪笔交易最终上链取决于哪个节点获得了记账权。

区块(Block)同理!

第2点的最长合法连原则是什么?

这个在上一篇《BTC 学习笔记连载(11)——比特币的实现 & UTXO》中有讲到过,所有合法的节点都会跟随自己验证的最长合法链进行挖矿。

结合前面讲的2条规则会导致什么问题?

我们同样做个假设:

  • 节点1/2和节点3/4非邻居节点,而且在物理连接上相去甚远
    广播传输到彼此需要比较长的时间

  • 节点1、节点3几乎相同时间挖出相同高度的区块
    如图分别是Block # 10001和Block # 10001’

  • 节点2很快接收到了Block # 10001
    经过验证接受这是一个合法的最新区块
    于是重新打包区块紧随该区块进行挖矿

  • 同理节点3紧随Block # 10001’进行挖矿

  • 当节点1/2随后接收到Block # 10001’时,一般不会切换算力
    节点3/4同理

一个开放的分布式网络是一定会有异步问题的,全网不同节点无时无刻不在产生并广播交易(Transaction)及区块(Block),这必然导致不同的节点接收到交易(Transaction)及区块(Block)的先后顺序不同。

在相同高度下不同节点跟随不同的区块(Block)挖矿(Mining),而随后接收到的相同高度的其它区块只是暂时保留,而不会切换算力,这在比特币共识协议下是合法且必然会发生的事:

这就是我们通常说的分叉(Forking),这种分叉是比特币网络基于其共识协议下的正常现象,而且理论上可能会出现3个甚至更多的分叉,这跟恶意的分叉攻击(Forking attack)是有本质区别的。

区别在哪里?可以自行思考一下!

这种由比特币网络及其共识协议带来的分叉本质上导致了算力分散,算力如果过度分散对一个公链来讲安全性会打折扣,这个我们在POW挖矿一篇再详细讲。

再附加一个思考问题,如果一个节点先后收到2个相同高度的合法区块,应该怎么更新自己的UTXO?

慢与贵之困

同样是上一篇《BTC 学习笔记连载(11)——比特币的实现 & UTXO》中有讲到过比特币最多支撑每秒7笔交易(transaction),这显然无法满足我们现实生活中的支付场景,要知道微信支付、支付宝交易峰值可是数十万笔每秒。

比特币为什么只能7笔?

因为比特币共识协议决定其一个区块(Block)的大小只有1M,1个区块满打满算最多支撑4000笔交易,而比特币系统期望出块时长为10分钟。

4000 /(6*10)≈ 7

注意,这是理论值,实际上旷工一般不会打包3000-4000笔交易,可以看下历史上很多区块都只有几百笔交易,所以绝大多数时候还远远不到每秒7笔交易。

旷工为什么不把区块利用满?

更多的交易不就能赚到更多fee吗?

这就是网络问题,如果一个区块(Block)过大一定会影响其广播至全网的速度,前面讲过诚实节点都会接受先收到的合法区块,然后跟随其后进行挖矿,这是旷工之间争分夺秒抢夺算力的战争,挖出的区块需要最快时间达到全网尽可能多的节点,对旷工来讲网络延迟与利润率直接相关。

要注意区块数据不仅仅是在节点之间传播,广播之前节点还需要对区块进行验证:

  • 挖矿难度是否符合要求?

  • 交易是否合法?

  • 区块大小是否符合要求?

那干脆1个交易都别打包,行不行?

反正当前出块收益绝大多数都来至Coinbase铸币交易,fee占比非常小。

理论上可以但并非最优策略,指不定谁能挖出区块来,那些fee可观的交易你不打包其它节点也会打包,而且不打包交易也不一定比打包几百笔交易快多少,这是一个平衡问题,我也不知道多少笔是收益最大化,但从历史账本来看打包几百笔还是有必要的。

所以比特币系统慢是一定的!

协议就限制了吞吐量!

那咱们改协议行不行?

  1. 把区块从1M改到4M、甚至改到10M行不行?

    其实并不一定非要1M,可能1.2M也行,中本聪当时设计比特币共识协议的时候可能也并没有经过多么严密的计算,也没法进行大规模的数据验证,我们现在知道1M并非是不可动摇的,只是完好的Run了14年的共识没必要去破坏它。

    改到4M就不一样了,这对网络的负担及存储的压力会淘汰掉一些节点,从而伤害到整个比特币网络的去中心化程度及安全性。有人这么干过,BCH现在不知道可好?

  2. 把出块期望时间改到5分钟、甚至改到1分钟行不行?

    其实也并不一定非要10分钟,可能8分钟也是可以的,但1分钟就绝对不行了。

    为什么?

    比特币全网不停地在广播交易(Transaction)及区块(Block),一笔交易/区块要被全网绝大多数节点接收并验证至少100-200s就过去了,如果1分钟就出块,那必将导致大量的分叉,大量的分叉必将导致算力分散,这对比特币网络的安全性及去中心化程度是不好的。

有的人可能会说一笔交易广播到主要的节点其实就几秒钟,这可能是基于比特币传输网络来讲的,比特币传输网络是一种尝试最小化矿工之间区块传输延迟的网络。最初的比特币传输网络Bitcoin Relay Network 是由核心开发人员Matt Corallo在2015年创建的,目的是在极低延迟的矿工之间实现区块的快速同步。该网络由几个专门的节点组成,这些节点托管在世界各地的Amazon Web Services基础设施上,用于连接大多数矿工和采矿池。2016年被FIBRE(Fast Internet Bitcoin Relay Engine)取代。

传输网络不是替代比特币的点对点网络,是在具有特殊需求的节点之间提供额外的连接,就像高速公路和乡村小路的关系,而任何终端节点之间连接最后还是要走小路。

另外还需要强调的是,有些节点可能不会进行广播,甚至可能会广播错误的消息,这导致任何一笔交易或区块都可能无法传播到全网所有节点,有些节点可能永远都收不到某些合法交易。

从上面分析可以看出随意改动共识协议是不合适的!

那拥堵就是不可避免的!

就算现在比特币区块是4M,一样会拥堵。

拥堵就必然导致大量交易排队,那些等不急的交易只能提高fee,从而让旷工更快打包自己的交易,这必然导致贵,贵又会引发一系列问题。

慢和贵是比特币甚至公链无法从根本上解决的问题:

Simple, robust, but not efficient!

区块链是解决去中心化问题的,不是解决效率问题的,所有依赖效率的场景都不适合区块链直接搭建服务。那些号称每秒支持上万笔交易的公链,你想想一笔交易广播至全网需要多少时间,这不搞笑么?

如果非要用到区块链,那就绕不开扩容方案,这个我们在比特币闪电网络一篇再来讨论。

Bitcoin并不慢、也并不贵

慢和贵都是比较级,看怎么来比。一个在美国打工的非洲小伙给家里寄点钱需要几天?需要给多少手续费?

比特币一个小时就解决了,前面我们讲过比特币P2P网络是没有地理位置属性的,一个美国的节点和一个非洲的节点可能直接就互为邻居节点,全世界任何一个角落之间的转账看起来就像在你身边一样,这是比特币网络无与伦比的优势。

所有从这样的场景来讲,比特币又很快很便宜,只是在小额支付场景上显得太笨重了。

这篇文章写完的时候是1月3号,刚好比特币创世区块发布14周年,以此祝Bitcoin14周岁生日快乐,也感谢比特币及区块链之父中本聪

Subscribe to All in Web3
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.