技术 › 网络

交易结构

门罗币交易的字节里有什么:前缀、RingCT 签名与可修剪部分

简而言之

一笔交易 = 前缀(版本、输入、输出、extra)+ RingCT 基础部分(类型、手续费、加密金额、输出承诺)+ 可修剪部分(Bulletproofs+、CLSAG、伪输出)。交易哈希由这三部分的哈希构成,因此旧节点可以丢弃可修剪部分(修剪,pruning),而交易依然可以验证。

前缀

version        = 2
unlock_time    = 0                       // 遗留字段,现在始终为 0
vin[]:                                   // 输入
  txin_to_key:
    amount       = 0                     // 金额隐藏在 RingCT 中
    key_offsets  = [g₀, Δ₁, …, Δ₁₅]      // 16 个全局索引,以相对偏移存储
    k_image      = I                     // key image,32 字节
vout[]:                                  // 输出
  amount = 0
  target: txout_to_tagged_key
    key      = P                         // 一次性公钥,32 字节
    view_tag = 1 byte
extra          = [0x01 ‖ R, …]           // 交易公钥及其他内容

key_offsets 以差值形式存储:第一个是该输出的绝对索引,其余是与前一个的距离。数字越小,用 varint 编码时占用的字节越少。

RingCT 基础部分

type       = 6                           // RCTTypeBulletproofPlus
txnFee     = fee in atomic units (varint)
ecdhInfo[] = encrypted amount, 8 bytes per output
outPk[]    = commitment C, 32 bytes per output

可修剪部分

bulletproofs_plus[] = one aggregated proof
CLSAGs[]            = { s[16], c1, D } per input
pseudoOuts[]        = C̃, 32 bytes per input

交易哈希

txid = Keccak( H(prefix) ‖ H(RingCT base) ‖ H(prunable) )

这种“三个哈希组成的树”让修剪节点可以丢弃旧交易中体积庞大的证明(只保留哈希),同时仍能计算出 txid。

手续费

手续费取决于交易的权重(≈ 字节大小,并针对 Bulletproofs+ 做了调整,使多输出交易不会便宜得不成比例)以及优先级。每字节的基础费率会根据区块大小中位数自动调整——参见动态区块大小。

FCMP++ 带来的变化

  • 取代 key_offsets 的是对某个区块的引用,证明基于该区块时的树状态构建。
  • 取代 CLSAG 的是成员证明和 SA+L;key image 保留。
  • 输出格式改为 Carrot(3 字节 view tag、Janus 锚点)。