CKB 交易验证生命周期

交易是 CKB 操作的核心。在与 CKB 交互时,人们将通过交易提交新的状态。本文档中,CKB 开发者 DingWei Zhang 将向大家解释 CKB 交易验证的生命周期,欢迎查看。

%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6%20(1)

RPC

首先,发送方会构造一笔交易,通过 RPC 提交。交易由提交到的 outputs_validator(从 0.27.0 版本引入)进行验证。

默认的验证逻辑包括检查各种东西:

transaction.outputs.all{ |output|
    let script = output.script
    (script.code_hash == secp256k1_blake160_sighash_all && script.hash_type == "type" && script.args.size == 20) ||
    (script.code_hash == secp256k1_blake160_multisig_all && script.hash_type == "type" && (script.args.size == 20 || (script.args.size == 28 && script.args[20..28].is_valid_since_format))
}
transaction.outputs.all{ |output|
    let script = output.type
    script.is_null || script.code_hash == dao && script.hash_type == "type"
    || (script.has_lock_period() && since.is_absolute())
}

此验证旨在防止格式不正确的交易,例如在 Common Gotchas 中提到的交易。

此外,可以将其配置为 passthrough 以跳过此验证。

交易提交到本地节点后,节点还会输出交易 id,您可以使用该 id 跟踪交易的状态。

Verification验证

在广播交易并进入 mempool 之前,交易将在本地验证和执行。

步骤 1——Resolve

本质上,交易 input 只是指针,如下所示:

struct OutPoint {
    tx_hash:        Byte32,
    index:          Uint32,
}

我们在交易执行之前通过指针收集引用的数据,这个过程称为「解析交易」。我们还需要检查这个交易的所有输入都是有效的(没有重复或双花)。

步骤 2——验证

验证步骤需要检查如下要素:

  1. 版本(目前必须是 0)
  2. serialized_size 必须小于如下限制:
    1. pub fn serialized_size(&self) -> usize {
      // the offset in TransactionVec header is u32
      self.as_slice().len() + molecule::NUMBER_SIZE
      // molecule::NUMBER_SIZE = size_of::<u32>() 4
      }
  3. inputs 不是空的
    1. inputs().is_empty() || outputs().is_empty()
  4. inputs 是成熟的
    1. 对于每个 input 和 dep,如果引用的 output 交易是 cellbase,那么它必须至少经过 4 个 epoch 确认
  5. capacity
    1. input capacity 的和必须大于或等于 output capacity
  6. duplicate_deps
    1. deps 不能重复
  7. outputs_data_verifier
    1. 「output data」字段的数量必须等于 outputs 的数量
  8. since
    1. since 值必须遵循 RFC:Transaction valid since

CKB VM 将执行交易脚本,并输出所消耗的 cycles 个数

向网络广播

如果验证成功,当前节点将交易(带有 cycles 值)广播给它的所有对等节点(它所连接的节点)。

在验证失败的情况下,将不再广播交易。交易流经各个「完整节点」,这些节点重复前面步骤中描述的验证过程,并检查 cycle 值是否与验证交易时使用的实际 cycle 相匹配。

Tx-pool

CKB 使用 two-step 进行交易确认。交易将在 tx-pool 中划分为不同的状态(pending 状态和 proposed 状态)。当一个块上链时,交易的状态将改变。当最新的块更改时,将重新扫描 tx-pool 中的所有交易,以确保它们仍然有效。

BlockAssembler 将从 pending 池和 proposed 池中为块模板获取 proposal 和交易,详细可参考:Two-Step Transaction Confirmation.

7 Likes

大于或等于?

是的,原文已改,谢谢纠正啦~