关于扩容新主张的研究:SPV 能支持十亿数量级用户的比特币网络正常运行吗?
漫谈

关于扩容新主张的研究:SPV 能支持十亿数量级用户的比特币网络正常运行吗?

让我们通过计算分析深入探讨一下

2017-08-02 11:54:01


编者按:Jameson Lopp 是 BitGo 的软件工程师,也是 statoshi.info 和 bitcoinsig.com 的创始人。在他近日撰写的一篇文章中,Loop 阐述了通过使用“简单支付验证”(simplified payment verification,SPV)的方法来移除比特币区块大小的限制是安全的这一观点,并做了深入的分析和研究。

这是一个将会一直存在于比特币扩容争议之中的新主张

这个主张指出:通过“简单支付验证”(SPV)的方法,比特币的区块大小可以安全地移除上限限制,用以支撑十亿数量级的用户便捷地使用比特币进行交易而不用担心网络拥堵。据推测,由于 SPV 客户端的存储模式,用户电脑需要接受和发送的数据非常少,所以 SPV 是一种高效的解决扩容争议的方法。

现在,让我们来深入研究一下这个说法,并从多个角度出发来看待这个问题。

SPV的工作原理

1501643066(1)

中本聪在比特币白皮书中描述了 SPV 的高级设计原理,尽管直到两年后 Mike Hearn 创造出了 BitcoinJ 才使得这一设计得以投入应用。

早期的 SPV 应用设计非常简陋,这些 SPV 应用需要下载整个比特币的区块链,这使得使用 SPV 方式进行支付验证时需要的带宽并不比普通的维护节点更有效率。

通过去掉和 SPV 客户钱包无关的交易,可以节省出大量的磁盘空间。之前被提出的 BIP37 方案需要 18 个月才能发布,这个方案会发布布隆过滤器(Bloom filtering)的交易规范。Bloom filtering 的工作原理是通过快速判断出某检索值一定不存在于某个指定的集合,从而可以过滤掉大量无关数据,减少客户端不必要的下载量,大大减少了对带宽的需求,这就是中本聪在比特币白皮书里所描述的高级设计原理。

由于以往的比特币系统协议中缺少对 SPV 的支持,在原有的协议中,可以通过“getheaders”命令来获取 block headers,也可以通过“getdata”命令支持获取指定的 block, 但这种协议不支持通过 tx_hash 反向查找关键信息所在的 block。为了定位 block,客户端往往不得不下载整个区块链,而 Bloom filter 则可以很好地解决这一问题。

一旦客户端与比特币网络同步之后,如果它能保持连接到完整的节点,就可以只接受 Bloom filter 加载出来的只与 SPV 钱包相关的交易信息。

SPV客户端扩容

从客户端的角度来看,布隆过滤器是在完整区块链中检索相关交易信息的一种非常有效的方式,在确认支付验证的同时能保证客户端占用最少的 CPU 资源、带宽和磁盘空间。

无论未来交易量有多大,每个比特币 block header 的大小始终不变,只有 80 字节。按照每小时 6 个的出块速度,每年会产出 52560 个区块。当 SPV 客户端只保存 block header 时,每年新增的存储需求约为 4 兆字节,100 年后累计的存储需求仅为 400M,即使用户使用的是最低端的设备,在正常情况下也完全能够达到数据的负载要求。

用于证明确保收录与区块中所有交易真实性的 Merkle 树算法也非常好用。因为添加到树中的每一个新的“层”都可以用“叶子”总数翻倍来表示,所以并不需要特别“深”的树枝分层来证明一次交易中所包含的信息,即使这些信息位于一个具有数百万交易的区块链中。

1501643089(1)

Merkle 树的数据结构是非常高效的,它能够包含 1600 万次交易,使用 Merkle 树算法证明在如此数量庞大的交易仅需要占据 1K 以下的磁盘空间。

1501643110(1)

很明显,从 SPV 客户端的角度来看,即便比特币的区块大小扩大几个 GB 的规模,SPV 客户端仍能够使用非常少的带宽,CPU 和磁盘空间来处理这些数量巨大的交易数据,这使得普通的 3G 手机都可以安装 SPV 客户端。

但是,比特币网络扩容却并不简单。

SPV服务器扩容

虽然 SPV 对于客户端来说是非常有效的,但对于服务器来说却并非如此,即 SPV 客户端要求完整的节点,由于一些原因,在服务器方面,该方法的展示出的可扩展性在非常差。

比特币网络中的节点必须处理数量非常大的数据量才能证明一个交易,这样工作量巨大的过程还必须在每个区块产生的时候重复,因此,磁盘的输出输入速度的限制很快就是成为新区块生成的瓶颈。

每个 SPV 客户端必须与从上一次与网络的联系中同步整个区块链,如果它在同步过程中发现其中错过了一些交易,SPV 客户端就必须从创建日起重新扫描整个区块链的数据。在最坏的情况下,写入磁盘时,大约要占 150G 的大小。作为完整的节点,磁盘必须加载完整区块链中的每一个区块,将相关的信息过滤到客户端并得出结果。

由于区块链是一个带有附加属性的分布式账本,新区块会一直产生,所以节点磁盘要加载的数据只会越来越多。如果广泛的协议不做出相应的更改,区块扩容与 BIP 37 方案就不兼容—-该方案希望所有区块在完整节点上都可用来通知 NODE_BLOOM。

BIP37 SPV 客户端会被冗长的数据欺骗。为了解决这个问题,SPV 客户端会连接到多个节点(通常为四个),这将使得整个节点的网络负载增加四倍。但这样做也不能保证这个问题被完全解决,因为恶意性的主动攻击可以将 SPV 客户端和主网络隔开。

对于每个连接到主网络并和区块链末端同步的 SPV 客户端来说,每个区块中传入的交易数据都必须被单独过滤。这涉及到不可忽略的 CPU 处理数据的时间量问题,该工作必须为每个连接到网络的 SPV 客户端单独完成。

精细的数据分析

在数据写入磁盘时,大约有 8300 个完整的节点在运行以接受传入的连接,这应该能够满足 SPV 客户端的服务需求。但是,目前能够监听完整节点合理支持的 SPV 客户端的数目有多少呢?

需要做些什么才能比特币网络可以支持十亿日常用户的需求,并能防止大量交易阻塞网络呢?

1501643130(1)

Bitcoin Core 默认最多传入连接的最大值为 117,这将在网络创建最大值为 936000 的可用套接字上限,这些套接字中的大部分会被消耗。

默认情况下,每个完整的节点会连接到其他 8 个完整的节点。Bitcoin Core 的开发人员 Luke-Jr 粗略地估计出在写入数据时约有 100000 个节点,其中有 92000 个节点不能为 SPV 客户端提供套接字,这样就会为完整的节点消耗 800000 个可用的套接字,只剩下 136000 个适用于 SPV 客户端的套接字。

这使我得出这样一个结论:大约有 85%的套接字会被完整的节点网络消耗(值得注意的是,Luke-Jr 的估计方法不能确定非监听节点在线花费了多少时间;至少可以确定的是这些节点中的一部分会与网络断开并定期重新连接)。

我的节点平均为 statoshi.info 的 100 个完整节点和 25 个 SPV 客户端提供运行动力,其中 80%的可用套接字都被完整节点所消耗。

1501643147(1)

如果我们想要建立一个十亿用户数量的 SPV 客户端能够运行的比特币系统,则需要足够的完整节点资源来为网络套接字、CPU 周期、磁盘写入和输出等提供服务,那么,使用数学的方法能够解决这个问题吗?

为了说明 SPV 扩容主张的优点,我将做出一些保守性的假设,这十亿用户中的每一个都会:

  • 每天发送和接受一笔交易
  • 每天都会将他们的钱包和区块链末端同步一次
  • 在同步时会查询四个不同的节点,以减少被遗漏的可能性

如果将每天 10 亿次的交易平均分配到每个区块中(实际上这根本不可能),每个区块大约会包含 700 万次交易。由于 Merkle 树算法具有极强的扩展性,它只需要 23 个哈希值来证明交易被包含在某个区块中,每个区块的大小为 736 个字节的数据加上一个平均为 500 字节大小的交易。

每天添加 12KB 大小的区块头文件,SPV 客户端每天只需要载入大约 20KB 的数据就能完成工作。

然而,如果每天有 10 亿次的交易,那么完整的节点每天将需要存储和处理 500GB 大小的新区块数据。每当 SPV 客户端连接到节点并要求在过去一天的数据中找到与其钱包相关的任何交易数据时,四个完整的节点就必须读取 500GB 大小的数据并从中过滤出相关的信息。

现在我们回想一下,在拥有 8000 个 SPV 服务的完整节点的网络中,一般大约有 136000 个套接字可用于 SPV 客户端。如果每个 SPV 客户端使用四个套接字,那么只有 34000 个客户端可以在任何给定的时间内与整个网络同步。但如果在网络上的客户端数量超出了这个范围,那么其他打开钱包尝试与网络同步的用户就会遇到连接错误的情况。

因此,为了使当前的网络能够满足 10 亿用户每天同步一次的规模需求,每个用户就必须在不到 3 秒的时间内同步前一天的数据。

1404333K6-0

这就带来了一个棘手的问题,因为这将要求每个完整的节点能够持续写入和过滤每个 SPV 客户端 167G 的数据,并且整个过程要在 1 秒中内完成。在有 20 个 PSV 客户端的节点,每秒需要处理的数据大小会是 3333GB。目前,不存在任何能够达到这种处理速度的单个存储设备,即使创建出一个巨大 RAID 0 阵列的高端固态磁盘,其能达到的最大处理速度也只有 600M/S。

这是需要 5555 个驱动器同时工作才能完成的吞吐量。理论上,如此规模庞大连接在一起的磁盘只能够存储两天里产生的新区块数据,那么用在数据写入时的成本花费为 400 美元。因此,你必须每隔两天就添加一个这样规模的磁盘列阵,每年花费在写入和存储数据上的金额将超过 4 亿美元。

当然,我们也可以在假设中调整各项数据以便找到节点花费更节省的方法。

让我们来试试吧:

如果我们有 10 万个完整的节点都可以使用更便宜且容量更大的磁盘,且假设这些节点都接受 SPV 客户端的连接请求,这样会出现什么情况呢?如果我们能设法修改完整节点的软件来支持 1000 个 SPV 客户端又会怎么样呢?

这将为我们提供 10 亿可用于 SPV 客户端的套接字以支持 2500 个在网络上同步的 SPV 客户端。因此,每个 SPV 客户端每天将会有 2160 秒的时间与网络同步。为了达到这一要求,必须保持每个完整节点能维持 231MB/S 的读取速度,如果有 1000 个连接到网络的客户端,则需要保证读取速度为 231GB/S。

一个转速为 7200 的硬盘其读取速度约为 220MB/S,所以需要一个超过 1000 个硬盘的 RAID 0 阵列实现这种读取吞吐量。

在写入数据时,你可以购买 400 美元容量为 10TB 的驱动器,因此,如果花费 40 万美元建立一个 RAID 阵列,它将能够存储 20 天的新区块生成数据,这意味着一年花费 720 万美元就能满足磁盘读取吞肚量的要求。

shutterstock_456083404你每天都必须增加 2 个这样的设备

值得注意的是,由于单个驱动器发生故障会导致整个磁盘阵列的损坏,所以不会有人愿意使用如此多的单个驱动器来组成这么大的磁盘阵列,而拥有容错率功能的磁盘阵列性能不佳且价格更贵。

另外同样值得注意的是,以上这些保守的估计假设了 SPV 客户端会以某种方式协调运作,以便在一天中均匀地分配其同步时间。实际上,网络上会有以一天和一周为周期的周期性的高峰和低谷,所以网络系统需要比估计中更大的容量才能适应高峰期的需求。

否则,许多 SPV 客户端在网络高峰期时将无法完成网络同步。

有趣的是,事实证明,更改每个节点的套接字数量不会影响到给定的完整节点的总体负载,每个完整的节点仍需要处理海量的数据。在这个方程中真正重要的是完整节点和 SPV 客户端的比例,当然,区块链中的区块大小同样重要。

所以,这个最终得出的结论似乎是不可避免的:要运行并维持能够满足 10 亿用户 SPV 客户端交易的完整节点的成本会是一个天文数字。

寻找一些折中的位置

到目前为止,上面计算出的情况在资金方面是无法实现的。

但是,如果我们翻转这个计算过程,尝试找到一个公式,通过增加区块链上的交易吞吐量来确定网络增加负载的成本,又会得出什么样的结果呢?

为了让比特币网络能够支持目标数量的每秒交易数(每日新增用户为 86400 个),我们可以计算出每个节点的磁盘吞吐量要求:

1234

上面的公式为我们提供了完整节点满足 SPV 客户端需求的每秒磁盘读取吞吐量的最小值。利用现有的网络特征和技术,我们可以通过使用磁盘吞吐量作为假设中的瓶颈来推断满足要求的完整节点的运行成本。需要注意的是,在运行节点的过程中肯定存在其他增加运行成本的因素,但我们暂时不考虑这些。

对于要进行的计算,我预先做出了一些假设:

  • 基于 info. 的平均交易大小为 500 字节
  • SPV 用户每天交易一次
  • SPV 客户端消耗的套接字数量为 4
  • 每个完整节点上可用于 SPV 客户端的套接字数量为 20
  • 网络中可用于 SPV 客户端的套接字的总数量为 136000
  • RAID 0 配置中的硬盘陈本 400 美元,其容量为 10TB,转速为 7200/S

eeee

通过上图,我们可以看到,在每秒处理的交易数量不超过 100 的情况下,系统对于磁盘吞吐量的要求非常合理。此时,只需要购买多个磁盘组成磁盘阵列就能达到相应的性能要求。

但随着每秒交易数的持续增加,磁盘的吞吐量需求以及运行完整节点的成本会成二次方式的增加,因此,对应的成本很快又变成了无法实现的天文数字。

作为参考,Visa 系统每秒大约处理 2000 笔交易,这在比特币系统中需要花费将近 20 万美元的成本才能跟上 SPV 客户端的需求。值得注意的一点是,在这些图表中,整个系统中节点的总数保持在 8000 这个恒定值上,实际上,节点的数量会随着成本的增加而减少,这会导致剩下的节点必须提高吞吐量,并拥有更快的处理速度。

这似乎是节点集中化复合力量的体现。

34556

正如我在“如何避免比特币节点集中化”中得出的结论所述,在比特币扩容之争中的一个根本性问题是节点运行和维护的成本。上述的计算让我们看到了计算节点操作成本的复杂性,因为这个过程中涉及到了非常多的变量,所以在计算中我假定了大多数变量保持不变,只关注磁盘吞吐量对于节点操作成本的影响。

一年前,一份(不科学的)的民意调查显示,98%的节点运营成本每月不会超过 100 美元,我敢打赌,增加比特币的在线交易量会导致大部分的完整节点运营成本的增加,如果交易数量增加两个数量级,会导致至少 90%的节点产生巨大亏损。

我相信,没有人愿意构建成本高昂的磁盘阵列来运行完整的节点。在这种情况下,声称交易量的增长对一般用户有利是一种毫无依据的说法,因为网络中将不会有足够的节点和符合要求的磁盘吞量为 SPV 客户端提供其需求的套接字。

SPV的其他缺陷

SPV 对于不需要完全验证节点安全性和隐私性的终端用户再好不过了。然而,忽略其可扩展行,基于 SPV 的比特币网络中仍然存在很多需要认真考虑的因素。

SPV 假设的条件使其安全性和隐私性都比运行完整节点要差的多:

  1. SPV 客户端信任矿工会正确验证和执行比特币规则;他们认为具有最大累积工作量证明的区块链也是有效的。关于这些,你可以在 这篇文章 中了解 SPV 与完整节点安全模式之前的区别。
  2. SPV 客户端假设完整节点不会因为遗漏对其欺诈。一个完整的节点不能捏造出一个不存在区块中的交易,但是节点仍旧可以声称在节点中的交易未发生来进行欺诈行为。
  3. 由于 SPV 客户端追求的是效率,所以它们只需要跟自己交易相关的数据信息,这将导致隐私性信息的大量丢失。

有趣的是,BIP 37 方案的合作者 Matt Corallo 为此还向外界道了歉,称后悔创造了它:

今天我发现了系统中存在巨大的用户隐私泄露问题,这就是 BIP 37 方案中的布隆过滤器设计存在的缺陷,很抱歉,是我写了这个程序的代码。

使用 BIP 37 方案中布隆过滤器的 SPV 客户端的用户几乎没有隐私,Jonas Nick(Blockstream 的安全工程师)发现,只要给定一个公钥,他就可以确定属于给定钱包地址 70%的相关信息。

虽然用户可以通过分配布隆过滤器在不同的节点上来解决隐私泄露的问题,但这大大增加了网络节点中的负载,也使得 SPV 的扩展性大大降低。

182342i9vg3rt596rr96rn

同时,BIP 37 方案也容易遭受微小琐碎的拒绝服务性攻击。 这里 提供的演示代码,可以通过特殊构造的过滤器进行大量快速库存请求,这将导致连续的磁盘搜索和较高的 CPU 使用率,从而使得整个节点瘫痪。

攻击概念验证的作者,Core 的开发人员 Peter Todd 解释道:

根本问题是,你可以使用非常低的网络带宽来消耗不成比例的磁盘吞吐量。

即使到今天,中本聪在比特币白皮书中描述的欺诈情况仍旧没有被真正实施过。事实上,关于这方面的研究表明,一些轻量级的欺诈警报可能都无法实施。

例如,欺诈警报只有在实际获得证明欺诈所需数据的情况下才会起作用,如果没有矿工提供该项数据,则无法实施欺诈警报,因此,SPV 客户端并没有中本聪预想中的那么不安全。

从高层次的角度来看,一个主要由 SPV 节点组成的系统会使共识发生变化,例如改变比特币数量上限,使得编辑分类账目更加容易。更少的完全验证节点意味着更集中地执行通过一致协商的规则,从而减少变化的因素对共识的抵制。有人认为这将会是 SPV 节点系统的特色,但另一些人却认为这根本就是一个缺陷。

潜在的改进

理论上,SPV 的安全性和扩展性都可以通过欺诈证明、欺诈提示、输入证明和花费证明等多种方式得以改善,但据我所知,目前这些方法都还处于概念性阶段,人们对于实际应用方面并没有做多少充足的准备。

布隆过滤器承诺能够通过改进来改变隐私泄露的状况,但是在过滤器大小和错报率之间存在一种有效性的参数:粗率的过滤使得错报率会非常高,而过于精细的过滤使得过滤器变得非常巨大,普通用户的 SPV 客户端根本无法运行。虽然它会减少完整节点磁盘吞吐量的负担,但由于整个区块必须通过网络传输,SPV 客户端和完整节点将会增加交易所需的带宽。

最近提出的紧凑型客户端过滤消除了隐私问题,但如果与过滤器匹配,它仍旧需要下载完整的区块链。

UTXO 承诺可以使 SPV 客户端同步其当前的 UTXO 集,即便不扫描整个区块链也能知道电子钱包的实时余额,当然,这种方式必须向 SPV 客户端提供现有的 UTXO 证明。

通过要求 SPV 客户端提交工作量证明或基于通道的微支付可以提防布隆过滤器受到 DoS 攻击,但是这两者都没有提出直截了当的解决方案。

完整节点的磁盘读取量需求可能会通过改进数据索引 SPV 客户端对所有请求的批量处理等多种方式来减少。

Ryan X Charles 指出,使用 BIP 70 方案的付款协议直接告诉某人你要发送的付款人的 UTXO ID,这样他们可以直接从完整的节点请求相关的数据信息,消除他们使用布隆过滤器的需求,如果你愿意接受泄露隐私的风险,这种方法将是非常有效的。

可以说,目前的方案有很多的改进余地,但这需要克服许多挑战才能正在改善在线网络的可扩展性。

1493971194275011506

合适的扩容方案

如果我们忽略大量的其他问题,例如区块传播延迟、UTXO 集缩放、初始区块同步时间、安全性和隐私权衡,将区块扩大,则可以从技术上将比特币系统扩大成日用户数十亿级别的交易系统,前提是有人愿意投入大量的资金和资源来开发并改进维持这个系统运行的基础设施和软件。

但是,比特币似乎不可能以这样的方式发展,因为现实中存在更加有效的扩容方式。其中最有效并且已经实施了的扩容方案是:集中并整合 API 供应商。在选取扩容方案时,人们倾向于那些可信任且隐私性高的方案,但是许多此类方案中的交互涉及到一些能够淡化某些危险的合同协议。

在以不可完全信任的方式扩容方面,例如闪电网络之类的第二层协议则提供了更为有效的扩容方案,因为大量的交易可以在主链之外进行。你可以将其视为广播带以太网通信层与路由 IP 层之间的区别—-互联网无法在无路由的情况下扩展,价值互联网也是如此。

虽然这种扩容方法在技术层面上比传统的集中式扩展更为复杂,并且还要克服一些独特的挑战,但是用于研究和开发这些路由协议的前期投资将会为系统带来巨大的长期收益,因为这些方案能够减少整个网络负载的数量级。

除了以上介绍的之外,还有其他一些方案可以进行探索:

  • 利用 Chaum 代币采用具有完美隐私性的中心化管理方案,例如 HashCash
  • 中心化非监禁零知识证明系统,例如 TumbleBit
  • 联合(非完全信任的多重签名)侧链
  • 矿工担保安全(非完全信任)的驱动链

我相信,从长远来看,比特币区块链需要更大的区块。

但是我们仍旧需要尽可能有效地进行系统扩容,与此同时必须保证系统的安全性和隐私性,对此我们必须有耐心并且要以睿智长远的眼光来考虑问题。

如果从一般用户的角度来看,Paypal 的实用性当然更高,但是它并不能像比特币系统一样让用户享受完整的财务主权。

 

 

 

 

 

 

 

 

 

 

扫码关注粹客网微信公众号,每日推送更多精彩资讯,随时随地关注业界最新动态
这个人很懒,什么都没留下

热门评论

Copyright © 2015-2016 粹客网 | 广州市彼利熊网络科技有限公司 (粤ICP备15096117号)