RFC: Regulation Compliance Extension

Regulation Compliance Extension

Regulation Compliance Extension (RCE) is an xUDT extension that enhance UDT with regulation compliance capabilities. It provides the following features:

  • Transfer Whitelist
  • Transfer Blacklist
  • Emergency Halt
  • PKI Style Regulation Agency Support

While the RCE script itself implements only the above features, an accompanying Administrator Lock script provides following additional features:

  • Multiple Administrators

It is up to the regulators to decide if the accompanying RCE-lock script shall be used.

Regulation Compliance Extension (RCE) script

A RCE script has the following structure:

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

A RCE script, as shown above, only contains the type ID args used by a special RCE Cell. The RCE Cell holds a molecule serialized RCData structure described below in its cell data part:

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,
}

Each RCRule structure can either represents a blacklist SMT tree, or a whitelist SMT tree. If flags & 0x2 == 1, it means smt_root is used as a whitelist, otherwise it is used as a blacklist.

If flags & 0x1 == 0x1, the current RCRule is put in Emergency Halt mode.

From this we can see, the cell data of a RCE cell, can be any of the following formats:

  • A normal RCRule structure. When executing, the RCE script would load data from the RCE cell denoted by type ID args, and enforce the following checking:
    • If current RCRule uses whitelist, all the lock script hashes of xUDT cells in current transaction, must be present in the whitelist SMT tree. The details on how SMT works, will be explained below.
    • If current RCRule uses blacklist, none of the lock script hashes of xUDT cells in current transaction, can be present in the blacklist SMT tree.
    • Current RCRule must not be in Emergency Halt mode.
  • A RCCellVec structure works in slightly different rules:
    • First, a nested RCCellVec structure is flattened as a plain array containing only RCRule structure. For simplicity, we will add a limitation, so that any RCE cell can contain at most 8192 RCRule structures. Any more RCRule structures will result in an immediate failure.
    • None of the lock script hash used by current xUDT cells in current transaction, can be found in any of the SMT trees in RCRule structures using blacklists.
    • As long as any of the RCRule structure uses whitelists, all the lock script hashes used by current xUDT cells in current transaction, must be found in the SMT tree of at least one RCRule structure using whitelists, which is not in Emergency Halt mode.

SMT

RCE scripts leverage optimized sparse merkle tree(SMT) extensively to reduce storage costs. For each sparse merkle tree used here, the key will be lock script hash, values are either 0 or 1: 0 represents the corresponding lock hash is missing in the sparse merkle tree, whereas 1 means the lock hash is included in the sparse merkle tree.

Generators will need to attach proofs of SMT for certain keys in transaction’s witness, so as to prove the following properties:

  • A lock hash is included in the whitelist SMT
  • A lock hash is not included in the blacklist SMT

See the next sections for real examples.

Operations

Transfer

Here is an example of a transfer operation with RCE whitelist enabled:

CellDeps:
    <vec> RCE cell
Inputs:
    <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 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>
           <...>

The proof of an SMT given certain keys, is just a series of raw bytes generated by the SMT library. See here for some examples.

Update Whitelist SMT in RCE cell

Inputs:
    <vec> RCE Cell
        Data:
            RCRule:
              <old smt root>
              <flags>
        Type:
            <type id type script>
        Lock:
            <user defined lock>
    <...>
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>
           <...>

The SMT validation flow works like following:

  • Using the given proof, we first test the updated keys and provided old values are correct given the old SMT root hash.
  • Now we use the given proof, we test that using the updated keys and updated values, the new SMT root hash could be calculated.

An example for this flow can be found here. Notice this workflow has already been tested and used in the v1 version of polyjuice, as well as current version of godwoken.

8 Likes

[翻译] 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