[翻译] 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 的当前版本中进行了测试和使用。