Exy.PW:在Nervos上构建一个高效去中心化交易所

今年DeFi(去中心化金融)行业明星项目lendf被黑客攻击盗走1亿多人民币资产,黑天鹅事件频发警醒我们,请重新思考以下几个问题:

暴力无处不在,如何更好抵御暴力?

金融资产交易,用户最担心什么?

答:资产安全。面对中心化交易所,我们最担心的是交易所卷款跑路、黑客攻击资产被盗、资产冻结、限制提现的风险。

去中心化的目的是什么?

答:打破中心垄断,恢复用户的真正控制权,避免遭受中心化的单点风险所带来的资产损失。

为什么使用DeFi?

答:安全:资产自己保管,避免中心风险造成损失。自由:无限制,随时进出,多服务商可选择。开放:无需注册kyc,无需许可准入,无地域界限。

​ DeFi行业蓬勃发展且瞬息万变,我相信一千个观众眼中会有一千个哈姆雷特,我很期待你也能同我一样在这里分享你的看法。作为DeFi爱好者跟Nervos社区的编程初学者,我一直很惊讶于Jan神的可怕预见性,如你感兴趣不妨阅读以下几篇来自社区Jan参与的讨论。

《PoW vs. PoS》

《需要预言机的智能合约是不是笨蛋合约?》

《DeFi 智能合约风险与 Nervos DAO 对策》

​ 在有幸上完CKB第一期编程体验课程后,我尝试通过设计一个基于Nervos的高效去中心化交易所,展现作为最贴近(bitcoin)加密编程本质的Cell模型,它能给我们带来怎样不同的Defi安全范式。先申明这是一篇初稿拙作,但希望通过它你可以尝试对比以太坊的DEX,看看有何不同。

你需要提前了解的知识:

1)Cell模型

  • 空间大小:Capacity (CKB)
  • 所有者权限:Lock script
  • 验证规则:Type script
  • 存储数据:Data
  1. UDT代币 (等同于以太坊上erc20代币):通过Type script实现。

  2. Crypto 体系:公钥加密,私钥解密;私钥签名,公钥验证。

Exy.PW的定义:安全高效去中心化交易所

有中介方

  • 提供高效可靠服务:传递报价签名信息,验证撮合交易

资产托管去中心化

  • 用户自己保管,即使Exy交易所服务不可抗力因素中断停止,用户仍然掌握着资产的所有权和控制权。

免授权

  • 无需授权中介方操作你的任何资产

Exy.PW力求在nervos上建立一个高效安全的去中心化交易所,他本身并没有去中介化,Exy就是一个中介存在,我们尝试利用Nervos Cell编程模型的优势:

作为中介方,我们不保管用户的任何资产及隐私信息,也不需要用户提供任何授权,用户资产均由自己保管。

我们只做:传递您签名的报价信息,协助撮合您的交易,确保交易不违背你的真实意愿,保证交易公平性。

我们希望为用户提供一个更安全、更放心、更高效的交易服务。

用户体验

Maker方:挂单

  • 报价灵活

    • 即时出价
    • 即时撤回

Maker将需要卖或用于买的资产cells的所有者权限更新成Exy_Maker_Lock,并通过提供一条报价签名信息(Maker_Witness)挂单,通过更新Maker_Witness可随时撤单重新挂单。

Taker方:吃单

  • 快速安全

    • 无需换锁
    • 一步成交

Taker通过Exy的UI检索得到挂单状态的Maker_cells,并获取Maker的有效报价信息后,根据持有的资产就可以直接构造交易并签名,将该笔交易信息推送给Exy.PW

撮合方:Exy.PW

  • 信息转发,撮合验证

Exy.PW需要将Taker发起的交易经Exy.PW签名后广播上链,这是为了确保Maker的报价信息为最新报价(Maker撤单或更新报价),另一方面也确保最先发起交易的Taker者的交易优先权。

产品

产品分为链内和链外,可以通俗地理解链内为后端,利用CKB网络的高度可靠性和安全性,负责用户资产端的结清算和交易。链外则为前端,负责高效处理并准确传递信息。

链内:Exy_Maker_Lock合约

Exy_Maker_Lock的功能,是使Maker用户需要交易的资产在保持依然由自己保管控制的同时,即资产所有权不变的情况下,允许有taker方在满足自己报价条件,并经由Exy.PW第三方签名确认后,该资产在链上移交给taker方,同时收取taker方提供的资产。

  • Maker挂单: 交易资产进入挂单状态,同时向交易市场提供报价信息

    • 1、将交易资产保管锁换为Exy_Maker_Lock
    • 2、向Exy服务器提交报价签名信息(Maker_Witness)
  • UnLock解锁方式:

    • 1、用户私钥secp256k1签名 :解除挂单状态或者直接进行转账交易。
    • 2、有Taker成交挂单
      • 1.用户的有效报价签名(Maker_Witness)
      • 2.Taker根据报价构造符合要求的payment交易并签名(Taker_Witness)
      • 3.撮合方Exy的有效签名(Exy_witness)
  • 数据结构

    • Exy_Maker_Lock_cell结构

      //Lock_args为空时,无需Exy签名由Taker直接广播该笔撮合交易。
      Lock script: 
        {code_hash:Exy_Maker合约代码hash ,type ,args:Exy公钥 }
      Type script:
       { 为空或者udt_type_hash}
      DATA:
       {uint128,用户Maker公钥}
      
    • 解锁Witness

      • 1.Maker_Witness

        作为Lock验证入参,Maker_Witness签名信息包含2个内容,报价信息Message以及使用用户私钥对报价信息签名Signature,确保报价来自Maker用户且不可篡改。

        Message:[
        maker_cell_out_point,        //防止过往签名再利用攻击
        ask_udt2_amount,                // price:maker_udt/taker_udt
        asset_type:usdt,              //ask_udt_type_script_hash;补齐0为ckb
        ],
        Signature: sig(Maker_Privatekey,Message)
        
      • 2.Taker_Witness

        Taker用户私钥签名解锁Taker_Cell
        
      • 3.Exy_witness

        对整个TX进行签名验证
        
  • Lock验证规则

上图漏了最后的Exy_witness验证环节:

​ 如果Lock_script_args为空,无需提供Exy_witness,以上验证通过则解锁;

​ 否则提取Exy_witness的签名人并与Lock_script_args比对正确解锁。

  • 安全风险

    • 合约升级

      Exy_Maker_Lock合约升级采用Type ID的方法,升级本身存在必要性,因为考虑代码效率及未来支持OpenTX方案及手续费方案。但引入合约升级会导致存在用户Maker交易资产被盗攻击路径:作恶方Exy或私钥泄露导致合约所有权被盗窃。关于如何避免此安全风险其实也很简单:合约所有权分散化管理

      至于所有权如何分散化管理除了多签方案之外,CKB的编程范式也使得我们可以有更多更好的选择,此处就不展开叙述了。

链外

作为技术小白,对链外前端服务架构设计这块不太熟悉,但是几个原则需要遵守:用户安全第一,轻客户端且高效,可嵌入多方钱包中。【?用户匿名性,不收集用户信息如IP地址等。】

  • 前端的用户UI:

    • 提供基础的挂单订单簿及K线功能
    • 提供Maker挂单报价签名功能,且可即时出价撤单
    • 提供报价及挂单cells信息,帮助Taker构造有效交易。
  • 后端Server:

    • 报价签名DB

      • 报价签名信息转发

      • 报价信息时效验证,确保Maker报价为最新及有效性

      • 提供市场订单簿报价信息

    • 交易队列管理

      • 确保最先push交易的Taker优先,避免无效上链交易的发生。
    • Exy撮合签名私钥管理

    • TX撮合签名广播

    • Exy_Maker_Lock_cells检索收集更新

  • 安全风险

    • Exy作恶:

      • 私自保留用户旧报价签名信息,在市场价格涨时以旧报价签名成交套利

      • 链外报价签名DB及交易队列管理使得Exy自身具备最优先成交权。

        如何避免?

    • 不可抗因素被攻击导致服务中断,不抗审查

    • 可禁止指定用户资产交易【避免不干净资产流入造成用户损失其实也是优势】

交易类型

1.单/多Maker单Taker且全部成交

  • 已实现设计,参见Exy_Maker_Lock合约验证规则

2.单Maker单Taker部分成交/单Maker多Takers全部成交

  • 未实现设计,当前设计部分成交会导致Maker需要多次签名(出现1udt成交攻击使挂单状态失效),初步考虑须结合open_tx方案来实现,多Takers全部成交上链
  • 或者自定义设定最小成交数量限制,但都将增加用户操作使用成本

3.多Makers多Takers全部成交

  • 未实现设计,通过type id升级Exy_Maker_Lock合约,采用open_tx方案,更高效

可增加特性

HTLC挂单状态时间锁

待解决的疑问及一些局限性

  • Exy_Maker_Lock作为保障Maker交易资产所有权的合约,是否也应该链内验证taker的资产所有权(capacity)。
  • 考虑成交率,做市商需要将大额UDT挂单拆分成多个小额UDT进行挂单,方便更快成交。

总结:

  1. 利用Nervos的特性:链上验证,链外计算及构造交易;
  2. 通过Lock脚本验证中新增设定交易规则,满足规则条件即确认可交易成功,实现Maker用户资产自持且无需交予第三方就可被动成交。
  3. 通过witness写入临时参数(有效报价),受之前nervos社区技术群里关于如何链上引入Coinbase Oracle的喂价讨论启发:由用户自己提供一个链上可验证的喂价不就是一个报价。
  4. 避免旧报价信息再利用攻击:
    • 报价信息的生命周期通过Maker_cell live状态的outpoint限定;
    • 最终交易确认需要Exy.PW签名确认。
  5. 如果项目逻辑可行,我很希望Exy.PW能成为一个由社区参与开发的开源项目,欢迎有兴趣的小伙伴加入!

最后文章行文仓促,虽说Exy.PW的想法构思已有段时间,但奈何水平有限,其中难免存在错误遗漏及不足之处,所以欢迎大家拍砖及进一步探讨。

8 Likes

很不错的设计!

这里的问题能详细描述一下吗?感觉通过 lock script 是可以实现的。

Maker挂单一个含有100USD_udt_cell,报价换100DCKB,如果允许部分成交:存在相同挂单的竞争者可以拿1DCKB去跟100USD_udt_cell换1USD_udt,直接上链成交的话,这个剩99USD_udt_cell状态发生改变(现在设计是只要发生交换,锁就变成默认锁,但哪怕锁还是维持exy_maker_lock不变),Maker之前的报价签名也跟着失活了(捆绑了outpoint),就需要maker重新提交新的报价签名。

另外我记得好像cell的新状态是需要几个区块确认后才能再次使用?

cellbase 的要 4 个 epoch 后才成熟可以使用,其他的应该没啥要求吧

想到一件事
上币这个环节,会像uniswap 一样,直接透过 createExchange 可以直接上币
还是会像 IDEX, KyberSwap, Bancor, EtherDelta 这些 Dex 需要进行注册和人工审核?

udt标准还没出,如果udt_cell中不包含有udt_name,那就需要一个udt_name跟type_script_hash的key-value映射写入链外DB。这点链外完全可以设计成直接上币,但注册跟人工审核会更安全些。
另外,Exy_Maker_Lock的设计是用户可自行更换中介方验证公钥的。也就是说你还可以自由选择其他的中介方,硬核用户甚至可以不需要中介方帮你再做一次验证,通过微信或者其他通讯工具都可以做直接做交易。

1 Like

你有没有考虑过把一些信息从 witness/message 转移放到 maker lock args 里面?

一是增加了变更为Maker_Cell的储存成本,二是也不够灵活,同时每次更改价格上链也需要付矿工费。

确实这是 lock 灵活的地方,可让用户选择中介的使用,也可以自己构造交易
目前sUDT 的形态要辨识 udt 是认 type script 了 ,还没有 name 和 symbol 这种选项

是不是你要說的其實是“定位”?

对的。

1 Like