主页 > imtoken最新安卓下载 > 3.5 比特币网络
3.5 比特币网络
至此,我们讨论了参与者可以发布交易,并将交易放入区块链,这一切看起来很神奇。 事实上,上述整个过程都是通过比特币网络完成的。 比特币网络是一个点对点网络,它遵循许多现有点对点网络的概念。 在比特币网络中,所有节点都是平等的。 没有等级,也没有特殊节点或所谓的主节点。 它在具有随机拓扑结构的 TCP 网络上运行,其中每个节点都连接到其他随机节点。 新节点也可以随时加入。 您现在可以尝试下载比特币节点软件,将您的个人电脑注册为节点。 该节点的权限与比特币网络中的所有其他节点相同。
由于随时有新节点进入和旧节点离开,比特币网络实际上是在不断变化的。 对于节点何时离开网络没有强制性规定。 一个节点只要3小时没有消息,就会逐渐被其他节点遗忘。 通过这种方式,网络非常温和地处理节点离线。
如上所述,每个节点都连接到其他随机节点,网络中没有确定的地理拓扑结构。 那么节点如何加入网络呢? 当您启动一个新节点时,首先要向您认识的节点发送一条简单的消息。 这个节点就是你的种子节点,当然有很多不同的方法可以找到种子节点。 然后你会问你的种子节点认识其他节点吗? 连接到新节点后,可以多次重复这个过程,最后可以选择连接到哪些节点。 这时候,你就成为了比特币网络中一个完全合格的节点。 这些步骤中有很多随机性,理想情况下,您将能够连接到一些随机节点集。 为了作为网络节点加入网络,您只需要首先知道如何连接其中一个节点。
那么加入网络有什么好处呢? 当然是为了维护区块链。 当我们发起交易时,我们希望整个网络都知道。 这是通过“泛洪”算法(有时我们称之为“八卦”协议)完成的。 如果 Alice 想给 Bob 转账,她的客户端发起一个交易,然后将这笔交易通知所有连接到她的客户端节点的其他节点,这些节点会进行一系列的检查来决定是否接受和广播这笔交易。 交易。 如果验证通过,这些节点会将交易信息传播到与其连接的其他节点。 当节点收到交易消息后,会将交易放入交易池中,但需要注意的是,交易池中的交易还没有被打包到区块链中。 如果节点收到的交易已经存在于交易池中,则不会再次传播。 这样就保证了泛洪协议会自动终止,而不是让一个交易在网络中反复传播,永不停止。 由于每笔交易都有唯一的哈希值,节点可以方便地查询某笔交易是否在自己的交易池中。
当一个节点收到一个新的交易信息时,如何验证呢? 这里有四个检查点:第一个也是最重要的一个是交易验证,即验证交易在当前区块链中是否有效,节点会对之前每笔交易的输出运行验证脚本,以确保脚本is valid 返回值都为真; 第二,检查是否存在重复支付; 第三,如上所述,节点会检查节点是否已经接收到交易信息; 第四,节点只会接收和发送列表中的标准脚本。
以上所有的检查都是合理的检查,所有的节点都很好地执行这些检查以使网络健康稳定,但实际上并没有规则强制节点执行这些检查。 即便如此,还是有必要让每个节点都去检查——因为比特币网络是一个点对点的网络,任何人都可以随时加入,总会有一些节点会发出双重支付,或者与非标准脚本,甚至完全是非法交易。
由于网络传输的延迟,不同的节点可能有不同的交易池。 当出现双花攻击时,这种现象就变得非常有趣。 假设爱丽丝要向鲍勃和查理支付相同的比特币,那么爱丽丝几乎同时发送了两笔交易。 有些节点先听到 Alice→Bob 交易,有些节点先听到 Alice→Charlie 交易。 当一个节点收到这两个交易中的任何一个时,它会将收到的交易放入交易池中,稍后,它听到另一笔交易,看起来像是双重支付交易,该节点会将其丢弃,不再向外传播。 结果是许多节点将不同意将哪笔交易包含在区块链中。 这种情况称为竞争条件[1](race condition)。
幸运的是,对于比特币来说,这根本不是问题:打包下一个区块的矿工将打破僵局,他将决定最终将哪笔交易包含在这个区块中。 如果 Alice → Bob 交易进入区块,那些听到 Alice → Charlie 的节点会将 Alice → Charlie 交易从交易池中移除,因为它是双重支付; 而那些听到 Alice → Bob Bob 节点的节点也会移除这个交易,因为这个交易已经包含在区块链中了。 因此,一旦区块被传播,就不再有上述的任何分歧。
由于每个节点默认保留最早收到的交易,因此节点在网络上的位置很重要。 如果在网络上的两个不同地方发起了两个相互矛盾的交易或区块,它们将同时广播到全网,节点先接收到哪个交易取决于其在网络中的位置。
当然,这是基于一个假设:无论收到什么信息,每个节点都保留最早收到的交易。 但比特币网络是一个点对点网络,并不要求节点这样做。 任何节点都有权按照其他逻辑行事,并根据选择的逻辑决定保留哪些交易和转播哪些交易。 第 5 章的矿工奖励部分讨论了这个问题。
零验证交易和替换费用(按费用替换)
在第 2 章中,我们讨论了零验证交易,其中接收方在交易在网络上广播后立即接受交易。 零验证交易并不是为了防止双重支付,而是由于矿工的默认行为是先将收到的交易放入交易池,因此零验证交易很难实现双重支付。 同时,由于零验证交易非常方便,因而越来越受欢迎。
从2013年开始,矿工的默认行为变成了“手续费替代策略”比特币可随时加入或退出,即当节点遇到冲突交易时,会将交易手续费较高的交易放入自己的交易池,将手续费较低的交易放入自己的交易池中更换。 从矿工的角度来看,这也是一个理性的选择,因为回报更高——至少在短期内是这样。 但这种费用替代策略使得多次支付攻击变得更加容易。
因此,费用替代策略受到了很大的争议。 这些争论一方面从技术角度讨论费用替代策略是否真的可以避免多次支付; 另一方面,他们从哲学的角度讨论比特币是否应该尽可能支持零验证。 或者干脆放弃成本替代策略。 这些争论已久的争议我们在此不再赘述,但近期比特币核心代码采用了“opt-in”的手续费替代策略,即交易可以标注是否符合手续费替代条件。 战略。
以上是关于交易的传播。 至于区块的传播,就是矿工挖一个矿(打包一个区块),然后把这个区块加入到区块链中。 这个过程类似于新交易的传播过程,也受到相同的竞争条件。 如果同时挖出两个有效区块(即两个矿工同时获得记账权),只有其中一个区块可以进入长期共识链,最终哪个区块被纳入长期共识链。术语共识链取决于其他节点选择在哪个区块上扩展区块链,未包括的将被丢弃。
验证区块比验证交易复杂得多。 除了确认区块头和确认里面的哈希值在可接受的范围之外,节点还必须确认区块中的每一笔交易。 最后,节点传播的区块必须是最长区块链上新添加的区块(当然,“最长区块链”取决于节点对区块链当前状态的了解)。 这是防止区块链分叉的唯一方法。 但就像在传播交易时一样,节点也可以执行自己的逻辑:它可以选择传递无效块,也可以选择传递共识链中较早添加的块而不是最新添加的块。 这会导致分叉,但这种情况是协议可以接受的。
泛洪算法的延迟如何? 让我们看一下图 3.9,它显示了网络中不同数量的节点接收到一个块所花费的时间(以秒为单位)。 三条线分别代表该块被网络中 25%、50% 和 75% 的节点接收所需的时间。 可以看到,由于网络带宽的限制,比较大的区块传播到大部分节点需要30秒左右。 所以这个协议不是很有效。 30秒在互联网上算是比较长的时间了。 在比特币的设计中,简单性是第一位的(简单的网络,节点可以随时加入或退出),效率是第二位的,所以在比特币网络中,一个区块可能需要经过很多节点才能到达最远节点。 如果网络是自上而下设计的,那么我们需要使任意两个节点之间的距离非常短。
网络规模
比特币网络规模很难衡量,因为它一直在变化,而且没有中央权威。 有人通过研究给出了一些估计:在高层次上,每个月可能有 100 万个 IP 地址成为比特币网络的节点(或临时成为节点)。 在低层次上,只有大约 5,000~10,000 个节点始终在线并处理交易。 这个数字出人意料地小,但是截至本书撰写之时,没有证据表明永远在线节点的数量在增加或减少。
图 3.9 区块传播时间
注意:显示一个块被网络中不同数量(百分比)的节点接受所花费的时间。
资料来源:Yonatan Sompolinsky 和 Aviv Zohar,加速比特币的交易处理(2014 年)。 可从以下 URL 获得。经 Yonatan Sompolinsky 和 Aviv Zohar 许可使用的数据
存储空间要求
完全有效的节点必须永久在线才能接收所有交易数据。 节点离线的时间越长,重新连接到网络时更新所有交易所需的时间就越长。 这些节点还需要存储完整的共识区块链,还需要有良好的网络连接,以保证所有的交易都能被接收并广播到其他节点。 目前的存储空间大约是几十GB(见图3.10),一台台式机就可以满足要求。
最后,完全有效的节点必须维护交易中生成的未消费比特币的完整列表(交易的输出)。 该列表最好存储在内存中而不是硬盘中。 此时节点可以快速查看并运行脚本,验证签名是否有效,然后将交易放入交易池。 到 2014 年年中,区块链中已包含大约 4400 万笔交易,其中 1200 万笔交易产生了未花费的比特币。 幸运的是,这个数据并不大,1G内存可以轻松装下。
图 3.10 区块链的大小
注意:全节点必须维护整个区块链。 2015年底,区块链大小在50GB以上。
轻量节点
除了完全有效的节点,还有一种轻量级节点(nightweight nodes),或者轻客户端,也被称为简单支付验证(SPV)客户端。 事实上,比特币系统中的大多数节点都是轻量级节点。 这些节点不存储整个比特币区块链,它们只存储它们关心的需要验证的交易部分。 如果你使用钱包软件,里面会有一个SPV节点,这个节点只会下载支付到你账户的交易和区块头。
SPV 节点的安全级别远不如全节点。 它可以验证难以挖掘的区块——因为它有区块头数据,但它无法验证一个区块中所有交易记录的有效性——因为它没有所有的交易历史记录,也没有那些没有的比特币的列表被花费了。 SPV 节点只验证那些与其相关的交易,因此它们必须依赖那些全节点来验证网络上的所有其他交易。 虽然这是一种安全上的妥协,但这并不是一个坏主意:轻节点依靠全节点来处理那些更困难的工作,但是当一个区块由于某种原因没有被矿工挖出时(挖矿成本巨大)比特币可随时加入或退出,这些轻量级节点节点也会做一些验证,确保这个区块不会被拒绝。
成为SPV节点可以节省大量资源。 区块头的大小仅为整个区块链的千分之一。 因此,一个轻量级的节点不需要几十G的存储空间,只需要几十MB。 甚至智能手机也可以成为比特币网络的轻量级节点。
比特币是一种开源协议,比特币网络必须通过不同实现方式的软件系统进行无缝交互。 这样,即使某些软件系统出现缺陷,也不会导致整个比特币网络瘫痪。 好消息是人们一直在用不同的语言重新实现协议,有些是用 C++,有些是用 Go,还有很多其他语言。 不好的是大部分节点会调用官方的比特币客户端资源库(bitcoind library),这是比特币核心代码开发者用C++开发的库,部分节点使用过时版本。 因此,即使在同一时间,每个人都在运行略有不同的客户端。
[1] race condition也可以理解为无序的情况。 ——译者注