CoTA 支持归集地址的提案

需求背景

考虑中心化交易所,会为每一个用户提供一个唯一地址,用户可以把自己的资产发送到该地址,而该地址由中心化交易所控制,进行去中心化收款、中心化记账。

一个平庸的解决方案是,交易所真的为每一个用户创建一个 secp256k1 地址,并让用户转账 CoTA token。带来的问题是,交易所需要为每一个地址创建一个永久占用 145 ckb 的 CoTA Cell。

解决方案一:代收地址注册(不建议该方案)

方案描述

  1. 中心化交易所(下称中心方)在 registry-cell 注册 secp256k1 代收地址,其特点为
    1. 必须是 secp256k1 地址
    2. 必须在 k-v 中指明 v 为另一个地址的 lockhash(默认的注册行为是指明 v = 0xFFFF…)
    3. 无需提供 cota cell 作为 tx output
    4. 必须提供 secp256k1 地址对应的数字签名作为交易签名(默认的注册行为不需要交易签名)
  2. 当用户充值时,会 withdraw CoTA token 到该 secp256k1 地址
  3. 交易所归集 token 时,提供如下 proof
    1. 历史 registry-cell 在 block head 的证明
    2. secp256k1 代收地址 在 registry-cell 的 smt 中的证明
    3. 另一个地址的 lockhash 与当前 claim 的目标地址的匹配证明
    4. 常规的 claim 证明

方案缺点

  • 交易所需要频繁操作 registry cell
  • 证明复杂,需要多层证明
  • 一次只能 claim 一个 token

解决方案二:子地址

方案思路

如果我们要求用户在转账的时候附带一个充值附言,比如 uid,那么用户可以都充值到同一个地址,这样交易所根据 uid 进行入账即可。但缺点有两个1)用户如果忘记填写了,会带来很大的客服压力;2)需要协调应用方增加附言界面,这里难度太大。

那么如果我们把 uid 作为地址的一部分,比如 secp256k1 地址的 args 末尾,这样每个用户收到的地址是不一样的,不存在上面出现的两个问题,同时在 sk 持有人解锁 lock 的时候,script 依然按照前 20byte args 验证即可。

方案描述

名词解释

  • secp256k1-sub lock:支持 args 超过 20 字节的 secp256k1 lock
  • 主地址:secp256k1-sub lock 地址,记其 args 为 master-arg
  • 子地址:args 超过 20 字节的 secp256k1-sub lock 地址
  • ext-arg:子地址中,args 超过 20 字节的部分

子地址

  • 交易所生成主地址
  • 交易所为每个用户生成子地址,子地址args 为 master-arg 加扩展字节(ext-arg
    • ext-arg 的长度、含义由交易所自行指定,默认为 UIN32 uid
    • lock hash ⇒ secp256k1 script(修改版本,因原版限制 20 字节arg)
    • args ⇒ master-arg | uint32-uid

secp256k1-sub lock 合约描述

考虑到该地址可能不光 CoTA 会作为虚拟地址使用,也可能有真实的 cell 以它为地址保存,例如交易所提供该子地址给用户充值 ckb,那么该合约需要完成符合预期的功能

  • 交易 witness 与原 secp256k1 要求一致
  • 不限制 20 bytes args

Registry 合约修改

  • secp256k1-sub lock 地址只允许主地址注册,不允许子地址注册,即如果注册地址的 lock hash 是 secp256k1-sub,则 args 只能是 20byte

CoTA 合约修改

  • withdraw 到交易所子地址(无修改)
    • 无特殊要求,和提现到其他地址无区别,提现记录忠实写入完整子地址(带 ext-arg
  • claim 转账到子地址的资产
    • 要求 claim 地址必须是对应的 secp256k1-sub lock 主地址,跳过子地址检查(不修改的话,需要匹配子地址,修改的话只需要匹配主地址)

方案优点

  • 改动小,兼容性强
4 Likes