严格来说,Orphan Block 是指某个节点尚不知道其直接前驱的区块。这个词有时也被宽泛地用于 Stale Block,即活跃链之外的区块。任何一种标签都不能单独说明欺诈或区块有问题;首先要知道节点掌握哪些数据,以及对方使用的是哪一种含义。
前一个区块有时被称为父区块。对于真正的 Orphan Block,Jana 的节点不认识父区块,因此无法完成衔接关系的验证。Stale Block 则可能有已知的父区块,而且本身完全有效;只是节点把另一条分支作为当前历史。Bitcoin Developer Guide 明确区分了这些含义。因此,Jana 在区块浏览器里看到 orphan 时,首先要问:是缺少前驱,还是这个区块只是没有留在主链上? [1]
在Bitcoin Core中也能看到这个区别。这是一款运行节点的软件,用来按照Bitcoin的规则检查区块和交易。在 Bitcoin Core 29 中,AcceptBlockHeader 通过 hashPrevBlock 查找前驱,这个字段引用的是前驱的身份指纹。索引中没有记录时,返回 prev-blk-not-found;如果已知父区块被标记为无效,则返回 bad-prevblk。前者表示“我缺少上下文”,后者表示“你建立在无效区块之上”。补齐前驱可以让后续检查继续,但本身还不能保证整个区块会被接受。 [2]
区块由区块头和包含交易的主体组成。区块头是一组用于识别身份和连接前驱的简短信息。Bitcoin Core 0.10.0 引入了 headers-first 同步:先获取并检查区块头,然后可以并行下载区块。因此,Jana 的节点可能已经知道前驱的区块头,却还没有把整个区块存到磁盘。缺少区块主体,不等于前驱未知。混淆两者,会让普通的数据下载看起来像难以解释的故障。 [3]
Bitcoin Core 29 的 getchaintips 命令可以告诉 Jana,节点知道哪些分支的末端。active 表示活跃链;valid-fork 表示已完整验证的非活跃分支。valid-headers 表示区块数据齐全但尚未完成全部验证;headers-only 表示仍缺少部分区块。invalid 则表示分支中含有无效区块。所以,这不是一张问题程度相同的结果清单。帮助文字中的 orphaned branches 也没有抹去这些区别。 [4]
设想两个不同的区块 A 和 B,都处在高度 900000。这是我们自拟的例子,不是在描述某次实际事件。高度是区块在链中的位置,竞争区块可以拥有同一高度。Jana 用 hash,即区块的身份指纹,以及 previousblockhash,即前驱引用,区分它们。在有效分支之间做选择,依据的是累计工作量,不只是高度。用于向程序发出命令的 RPC 接口把它称为 chainwork:与各区块难度对应的预期工作量之和。 [1] [5]
Jana 用 getblock 查询主链之外的区块时,Bitcoin Core 29 可能给出 confirmations = -1。这是特殊状态标记,不是普通的确认次数。它既不是倒计时,也不是负的链重组深度,同样不能证明前驱缺失。Jana 要结合区块身份和分支状态理解它;她的节点也未必拥有其他参与者曾经见过的所有区块。 [5]
区块奖励由一笔特殊的首笔交易 coinbase 创建,与同名交易所无关。交易输出记录一笔比特币金额,以及花费这笔金额时必须满足的条件。 在 Bitcoin Core 29 中,COINBASE_MATURITY 为 100:高度 H 创建的输出,最早可以在高度 H+100 的有效区块中花费。这里看的是高度差,不是经过的分钟数。但等待条件不能代替进入活跃链。只要奖励所在区块仍处在非活跃分支,其输出就不在活跃 UTXO 集,即尚未花费输出的记录中。其他地方新增区块,并不会自动把这笔钱恢复回来。 [6] [7] [1] [8]
Jana 保存区块的 hash、前驱、分支状态和软件版本,还保存 getchaintips、getblock 的回复及取得回复的时间。这个观察时间要与区块头中的 time 字段分开:区块自带的时间戳,不是她的计算机观察到它的时刻。这样的记录有助于比较后续观察,却不能单独证明攻击、某个具体网络故障或全球 orphan 区块比例。它首先描述的是某个节点在某个时刻的状态。 [4] [5]
要获得更完整的理解,请将本词条与以下词条结合阅读: Stale Block, Reorg, Block Propagation, Proof of Work, Bitcoin. 反向关联还来自: Stale Block.