这篇文章上次修改于 731 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

1 Cell

pub struct CellOutput {
    pub capacity: Capacity,    
    pub data: Vec<u8>,         
    pub lock: Script,          
    pub type_: Option<Script>, 
}
  • capacity 定义 cell 容量大小,同时也是 nervos 的原生资产 ckb。cell 中的所有四个字段加起来不超过 capacity
  • data 存储数据和脚本,数据可能是某个应用的状态,也可能是 sUDT
  • lock 验证 cell 的所有权,只有提供正确签名的人才能使用 transaction.inputs 中的 cell
  • type_ 同时验证 transaction 的输入和输出是否满足某些规则,相当于是合约。

示例:

{
  "capacity": "0x19995d0ccf",
  "lock": {
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259",
    "hash_type": "type"
  },
  "type": null
}

其中,lock 结构为 Script

pub struct Script {
    code_hash: Byte32,
    hash_type: Byte,
    args: Bytes,
}
  • code_hash: 编写 lock script 后,编译生成 RISC-V bin。code_hash 即为 bin 的 hash,后面可通过该 hash 定位到 bin,进而加载并运行。
  • args 为 lock script 所需的参数。
  • hash_type 取值为 typedata。如果是 data,应该取 code_hash 等于 transaction.cell_deps 中 blake2b_hash(cell.data) 的 cell;否则,code_hash 应该取等于 transaction.cell_deps 中 hash(cell.type) 的 cell。

2 transaction

pub struct TransactionBuilder {
    pub(crate) version: packed::Uint32,
    pub(crate) cell_deps: Vec<packed::CellDep>,
    pub(crate) header_deps: Vec<packed::Byte32>,
    pub(crate) inputs: Vec<packed::CellInput>,
    pub(crate) outputs: Vec<packed::CellOutput>,
    pub(crate) witnesses: Vec<packed::Bytes>,
    pub(crate) outputs_data: Vec<packed::Bytes>,
}
  • 消耗 inputs 中的 cell,生成 outputs 中的 cell。
  • cell_deps 和 inputs 都是输入,不同的是,cell_deps 中的 cell 不会被消耗,而 inputs 中的 cell 会被消耗,从而不能再出现在别的 transaction 的 inputs 中。
  • header_deps 指向所依赖的区块头。
  • witnesses 一般存放签名,lock script 会校验该签名是否正确
  • outputs_data 和 outputs 的长度相同。

CellDep:

pub struct CellDep {
    out_point: OutPoint,
    dep_type: Byte,
}
  • out_point 指向的 cell 中可能包含需要运行的代码,也可能是需要加载的数据
  • dep_type 取值为 codedep_group,前者表示 out_point 指向的 cell 直接包含在 transaction 中;后者表示首先加载 out_point 指向的 cell,然后根据该 cell 进行二次定位

CellInput:

pub struct CellInput {
    previous_output: OutPoint,
    since: Uint64
}
  • previous_output 指向之前 transaction 的 outputs

OutPoint:

pub struct OutPoint {
    tx_hash: Byte32,
    index: Uint32
}
  • tx_hash 为当前 cell 所属的 transaction
  • index 表示 transaction.outputs 中的下标

示例

{
  "version": "0x0",
  "cell_deps": [
    {
      "out_point": {
        "tx_hash": "0xbd864a269201d7052d4eb3f753f49f7c68b8edc386afc8bb6ef3e15a05facca2",
        "index": "0x0"
      },
      "dep_type": "dep_group"
    }
  ],
  "header_deps": [
    "0xaa1124da6a230435298d83a12dd6c13f7d58caf7853f39cea8aad992ef88a422"
  ],
  "inputs": [
    {
      "previous_output": {
        "tx_hash": "0x8389eba3ae414fb6a3019aa47583e9be36d096c55ab2e00ec49bdb012c24844d",
        "index": "0x1"
      },
      "since": "0x0"
    }
  ],
  "outputs": [
    {
      "capacity": "0x746a528800",
      "lock": {
        "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
        "args": "0x56008385085341a6ed68decfabb3ba1f3eea7b68",
        "hash_type": "type"
      },
      "type": null
    },
    {
      "capacity": "0x1561d9307e88",
      "lock": {
        "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
        "args": "0x886d23a7858f12ebf924baaacd774a5e2cf81132",
        "hash_type": "type"
      },
      "type": null
    }
  ],
  "outputs_data": [
    "0x",
    "0x"
  ],
  "witnesses":[ "0x55000000100000005500000055000000410000004a975e08ff99fa000142ff3b86a836b43884b5b46f91b149f7cc5300e8607e633b7a29c94dc01c6616a12f62e74a1415f57fcc5a00e41ac2d7034e90edf4fdf800"
  ]
}

参考

Data Structures of Nervos CKB
CKB 结构介绍