RFC: Regulation Compliance Extension

[翻译] RFC:监管合规性扩展

监管合规性扩展(RCE)xUDT 的一个扩展,它增强了 UDT 的监管合规性能力,具有以下功能:

  • 调用白名单
  • 调用黑名单
  • 紧急停止
  • PKI Style 监管机构支持

虽然 RCE 脚本本身只实现了上述功能,但附带的管理员锁定脚本提供了以下附加功能:

  • Multiple Administrators

由监管机构决定是否使用附带的 RCE 锁定脚本。

监管合规性扩展(RCE)脚本

RCE 脚本的结构如下:

Code hash: RCE script code hash
Hash type: RCE script hash type
Args: <type ID args for RCE cell>

如上所示,一个 RCE 脚本只包含一个特殊的 RCE Cell 使用的类型 ID 参数。RCE Cell 在它的 cell 数据部分保存着如下所示的分子序列化 RCData 结构:

array Byte32 [byte; 32];
array Uint128 [byte; 16];

struct RCRule { // RC stands for Regulation Compliance
  smt_root: Byte32,
  flags: byte,
}

vector RCCellVec <Byte32>;

union RCData {
  RCRule,
  RCCellVec,
}

每个 RCRule 结构可以代表一个黑名单 SMT 树,也可以代表一个白名单 SMT 树。如果 flags & 0x2 == 1 ,则表示 smt_root 被作为白名单使用,否则作为黑名单使用。

如果 flags & 0x1 == 0x1 ,则当前 RCRule 被置于紧急停止模式。

由此我们可以看出,一个 RCE cell 的 cell 数据可以是以下任意一种格式:

  • 一个正常的 RCRule 结构。当执行时,RCE 脚本将从类型 ID args 表示的 RCE cell 中加载数据,并强制执行以下检查:
    • 如果当前 RCRule 使用白名单,则当前交易中 xUDT cell 的所有锁脚本哈希必须出现在白名单 SMT 树中。关于 SMT 的工作原理细节将在下面解释。
    • 如果当前 RCRule 使用黑名单,则当前交易中的 xUDT cell 的锁脚本哈希都不能出现在黑名单 SMT 树中。
    • 当前 RCRule 不能处于紧急停止模式。
  • RCCellVec 结构的工作原理稍有不同:
    • 首先,嵌套的 RCCellVec 结构被简化为一个只包含 RCRule 结构的普通数组。为了简单起见,我们将添加一个限制,以便任何 RCE cell 最多可以包含 8192 个 RCRule 结构。任何更多的 RCRule 结构都将导致立即失败。
    • 当前交易中当前 xUDT cell 所使用的锁脚本哈希,都不能在任何使用黑名单的 RCRule 结构的 SMT 树中找到。
    • 只要有任何 RCRule 结构使用了白名单,那么当前交易中所有 xUDT cell 所使用的锁脚本哈希值,都必须在至少一个使用白名单的 RCRule 结构的 SMT 树中找到,且该结构不处于紧急停止模式。

SMT

RCE 脚本广泛利用优化的 Sparse Merkle Tree(SMT)来降低存储成本。对于这里使用的每一棵 SMT,其关键是锁脚本哈希,若值为 0 或 1: 0,则表示 SMT 中缺少相应的锁定哈希,若值为 1,则表示 SMT 中包含了锁定哈希。

生成器将需要为交易见证中的某些密钥附加 SMT 证明,以证明以下属性:

  • 锁定哈希包含在白名单 SMT 中
  • 锁定哈希不包含在黑名单 SMT 中

以下为实际示例。

操作

调用

下面是一个启用 RCE 白名单的操作调用示例:

        Type:
            code_hash: extensible_udt type script
            args: <owner lock script hash> <xudt args for RCE script>
        Lock:
            <user defined lock 1>
    <...>
Outputs:
    <vec> xUDT_Cell
        Data:
            <amount: uint128> <xudt data>
        Type:
            code_hash: extensible_udt type script
            args: <owner lock script hash> <xudt args for RCE script>
        Lock:
            <user defined lock 2>
    <...>
Witnesses:
    WitnessArgs structure:
      Lock: <user defined>
      Input Type:
           <vec> Bytes structure:
               <proof length>
               <proof that lock 1 & 2 are both mapped to 1 in SMT>
           <...>

给定某些密钥的 SMT 证明,只是一系列由 SMT 库生成的原生字节。这里有一些示例。

更新 RCE cell 中的白名单 SMT

    <...>
Outputs:
    <vec> RCE Cell
        Data:
            RCRule:
              <new smt root>
              <flags>
        Type:
            <type id type script>
        Lock:
            <user defined lock>
    <...>
Witnesses:
    WitnessArgs structure:
      Lock: <user defined>
      Input Type:
           <vec> Bytes structure:
               <number of updated keys>
               <updated key 1> <updated value 1> <old value 1>
               <updated key 2> <updated value 2> <old value 2>
               <...>
               <proof length>
               <proof for the updated keys in the old SMT>
           <...>

SMT 验证工作流如下:

  • 利用给定的证明,在给定的旧 SMT 根哈希值时,我们首先测试更新的密钥和提供的旧值是否正确。
  • 现在我们使用给定的证明,测试使用更新的密钥和更新的值,可以计算出新的 SMT 根哈希。

这个流程的示例可以在这里找到。注意,这个工作流已经在 Polyjuice 的 v1 版本和 Godwoken 的当前版本中进行了测试和使用。

1 Like