术语表 /节点与软件
Assumeutxo
- Assumeutxo 是什么?
- Assumeutxo 使 Bitcoin Core 节点能够从硬编码高度上的未花费输出集快照启动,然后在后台验证被跳过的历史记录。
该快照列出了某一区块高度上所有可花费的币,其哈希值是编译进软件的,而不是随软件一同下载的。Bitcoin Core 28.0为高度840,000加入了主网参数,这是在真实网络上第一个可以加载快照的高度。您的钱包在完整历史被核验之前很久就能使用,而节点则在后台悄悄验证被跳过的区块。
运作方式
Assumeutxo 把一个节点拆分为两个链状态(chainstate),并让它们同时运行。
您把快照文件交给 loadtxoutset RPC。Bitcoin Core 会创建第二个链状态来加载它,并在读取和检查内容期间保持原链状态处于活动状态。快照链状态加载并验证完成后,它成为活动链状态,数据目录中会出现一个名为 chainstate_snapshot 的目录,节点开始从快照的基准区块向网络最新区块同步。该目录内有一个名为 base_blockhash 的小文件,记录快照是在哪个区块处生成的,因此这一安排在重启后依然有效。
哈希值就是全部的信任基础。Core 自己的文档指出,快照没有权威来源,您下载的任何快照都会与源代码中硬编码的值进行核对。因此,您信任的不是托管该文件的人,而是您已经选择运行的同一个版本,哈希值与编译值不符的文件在成为您的链状态之前就会被拒绝。
与此同时,原链状态继续从创世区块起逐步推进,并应用全部规则。当它到达快照的基准区块时,会对自己的未花费输出集计算哈希,并将结果与编译进去的参数比较。缓存会分配给更需要它的那条链:快照链在冲向最新区块时优先,之后后台链获得更大份额。getchainstates RPC 会显示这两者。
清理在下一次重启时进行,而不是立即进行。Core 把 chainstate_snapshot 重命名为 chainstate,删除后台数据,此后这个节点与以传统方式建立的节点没有区别。base_blockhash 文件会保留下来,作为其起点的记录。
购买比特币时为何重要
Assumeutxo 针对的是让大多数买家无法自行验证其持有的币的那个缺点。
本站评测的41款钱包中,Bitcoin Core 是唯一自行下载并检查整条区块链的钱包,因此本站评测给它评分4.7,同时仍把首次同步需要下载并验证整条链、耗费数小时和大量磁盘空间列为它的第一个缺点。这句话正是大多数人从不尝试的原因。快照并没有让这一成本消失,而是把它挪了位置:那几个小时依然存在,只是发生在钱包已经可以使用之后,而不是之前。
这一做法的价值在提币时体现出来。您在本站收录的63家交易所之一购买比特币,把币转到您掌控的密钥,然后想确认币已到账。没有自己的节点,您能询问的只有两方:刚刚发出这些币的交易所,以及现在已经知道您地址的公共区块浏览器。有了自己的节点,答案则来自您自己的机器完成的运算。
它还改变了启动一套严谨配置的成本。本站对 Sparrow 的评测同样评分4.7,其中描述了直接连接 Bitcoin Core 作为后端,而这种搭配过去意味着要先等完整同步结束,Sparrow 才有可连接的对象。快照把耗时一整天的配置压缩为一个可用的晚上,而您推迟的验证会在您睡觉时自行完成。
实例:用 dumptxoutset 生成快照
生成 assumeutxo 快照是在您已经信任的节点上进行的有意操作,而不是去获取的一个文件。
dumptxoutset RPC 负责生成快照,可以使用类型 "latest" 在当前最新区块处生成,也可以使用类型 "rollback" 在较近的某个高度处生成。在运行的大部分时间里,节点处于一种不反映实际情况的临时状态,会把它明知有效的区块标记为无效,并且由于这种状态,网络活动被关闭,所有对等节点都被断开连接。Core 的文档建议使用 -rpcclienttimeout=0,因为无论硬件如何、选择哪种类型,转储都需要一段时间,并且不建议在此期间对节点做任何其他操作。
有两个细节常让人踩坑。快照只有在其高度已在链参数中列有哈希值时才可使用,因此选择任何其他高度都意味着要修改该代码并重新编译,而 "rollback" 类型也可用来核对硬编码的哈希值:重新生成快照并进行比较。此外,Bitcoin Core 28.0更改了序列化方式:旧格式的转储已不再受支持,必须在28.0或更高版本的节点上重新创建,loadtxoutset 才会接受。
Bitcoin Core 29.0加入了一个相关工具 contrib/utxo-tools/utxo_to_sqlite.py,可把紧凑序列化的快照转换为 SQLite3 数据库。这与节点同步毫无关系,却与快照的本质息息相关:它是某一高度上谁拥有什么的完整、自成一体的画面,而这恰好很适合用来查询。
Assumeutxo vs 初始区块下载
Assumeutxo 并不取代初始区块下载,它改变的是工作发生的先后顺序。
加载了快照的节点,仍会在其后台链状态中从创世区块起执行完整的初始区块下载,该链状态负责对快照所假定的那一段链进行完整验证。没有任何内容被永久跳过。快照带来的好处是钱包在等待期间不再毫无用处,因为活动链状态已经知道您关心的每个地址的当前状态。创世区块与快照高度之间的区间被记录为假定有效,而不是悄悄算作已验证,这正是 Core 使用两个链状态而不是在单个链状态上加一个标志的原因。加载了快照却从未完成后台同步的节点,处于一种真实且有名称的状态,而不是隐藏的状态。
Assumeutxo vs 修剪节点
Assumeutxo 和修剪都减轻了节点需要应对的负担,但它们减轻的是相反的东西。
修剪针对的是验证之后的磁盘占用:修剪节点会检查每个区块,然后删除不再需要的原始文件。Assumeutxo 针对的是验证之前的时间:它推迟的检查仍会在之后完成。两者可以结合使用,Core 为此放宽了自己的一条规则。-prune 的通常下限是550 MiB,而加载快照的节点会忽略这一最低值,改为至少使用1100 MiB。空间并不是唯一的开销项:在后台同步运行期间,会暂时存在两个链状态目录,每个都有数 GB,并且很可能增长到超过您下载的快照的大小。
两者分歧最大的是索引。索引无法从快照中获益,因为索引总是从创世区块开始构建,并且只能按顺序应用区块,所以只有当后台验证把节点推进到快照区块之后,索引才会追上最新区块。修剪使这一点更加突出:凡是支持修剪的索引,都只允许节点删除已经建立索引的区块,因此旧的快照会在磁盘上留下一大堆已下载、未建立索引且无法删除的区块,直到索引追上进度。