# NerveDEX设计文档

# 模块运行环境

  • jdk: 11
  • ide: IntelliJ IDEA 2020.3.3 (Community Edition)
  • maven: 3.3.9

# 模块配置说明

配置文件路径:module.ncf

配置项 说明
sysFeeAddress 订单成交后,系统收取手续费的地址
sysFeeScale 系统收取手续费比例(sysFeeScale=3,表示3/10000)
createTradingAmount 用户创建资产交易对手续费用

# 模块协议说明

创建交易对协议(CoinTrading)

说明:

  1. scaleBaseDecimal:交易资产允许最小交易小数位。用比特币来举例,比特币的小数为8位,即 1BTC = 10^8聪。而在实际交易的时候,我们并不需要支持这么小的单位来做交易,例如我们只想支持小数位到6位,在创建交易对的时候scaleBaseDecimal填写为6即可。scaleQuoteDecimal字段含义一样。注:scaleBaseDecimal填写数值不能大于资产本身的小数位。
  2. **minBaseAmount:交易资产最小交易单位。**最小交易单位,受最小交易小数位制约。例如,BTC我们只支持小数为到6位,那最小交易单位填写数值就必须>=100聪。
Length Fields Type Remark
23 address byte[] 交易对创建人
4 baseAssetChainId uint 交易币种的链Id
4 baseAssetId uint 交易币种的资产Id
1 scaleBaseDecimal byte 交易币种允许最小交易小数位
8 minBaseAmount bigInteger 交易币种最小交易单位
4 quoteAssetChainId uint 计价币种的链Id
4 quoteAssetId uint 计价币种的资产Id
1 scaleQuoteDecimal byte 计价币种允许最小交易小数位
8 minQuoteAmount bigInteger 计价币种最小交易单位

修改资产交易对交易协议(EditCoinTrading)

说明:

  1. 修改资产交易对交易只允许资产交易对创建人发起。
  2. 只允许修改最小支持交易小数位和最小交易单位。
Length Fields Type Remark
32 tradingHash byte[] 资产交易对hash
1 scaleBaseDecimal byte 交易币种允许最小交易小数位
1 scaleQuoteDecimal byte 计价币种允许最小交易小数位
8 minBaseAmount bigInteger 交易币种最小交易单位
8 minQuoteAmount bigInteger 计价币种最小交易单位

资产交易对交易委托挂单协议(TradingOrder)

说明:

  1. feeAddress:收取服务费地址。用户在去中心化交易所服务节点发起委托挂单的时候,节点可配置一个NVT地址作为服务费收取地址。当用户委托单成交后,该地址会收取成交额一定比例作为服务手续费。若节点未配置地址,则视为不收取服务费。
  2. **feeScale:收取服务费比例。**feeScale和feeAddress配套使用。当feeAddress为空时,feeScale取值必须为0;当feeAddress不为空时,feeScale取值1-5,表示收取成交额的1/10000~5/10000作为服务费。
Length Fields Type Remark
32 tradingHash byte[] 资产交易对hash
23 address byte[] 委托挂单账户地址
1 type byte 1:买单,2:卖单
8 amount bigInteger 委托挂单数量(交易币种数量)
8 price bigInteger 委托挂单价格
feeAddress byte[] 收取服务费地址(可为空)
1 feeScale byte 收取服务费比例,取值0-5

撤销委托挂单协议(TradingOrderCancel)

说明:

  1. 用户发送撤销挂单时,不能指定撤销部分委托。例如:委托够买10个BTC,不能撤销部分委托只购买5个BTC,只能是订单全部撤销。
  2. 用户发送撤销挂单后,最后撤销数量由节点打包时做最后确认。(详细说明见:NerveDEX说明文档)
Length Fields Type Remark
32 orderHash byte[] 挂单交易hash

成交协议(TradingDeal)

说明:

  1. 用户支付的手续费 = 系统收取手续费(固定为成交额的3/10000) + 交易所服务节点手续费(成交额的0 ~ 5/10000)
Length Fields Type Remark
32 tradingHash byte[] 资产交易对hash
32 buyHash byte[] 委托买单交易hash
8 buyNonce byte[] 委托买单nonce值
32 sellHash byte[] 委托卖单交易hash
8 sellNonce byte[] 委托卖单nonce值
8 quoteAmount bigInteger 成交总额
8 baseAmount bigInteger 成交总量
8 buyFee bigInteger 买家支付手续费
8 sellFee bigInteger 卖家支付手续费
8 price bigInteger 成交价
1 taker byte 主动成交方: 1 买单主动吃单,2 卖单主动吃单
1 type byte 成交状态: 1 买单已完全成交,2 卖单已完全成交,3 买卖双方都完全成交

取消委托确认协议(CancelDeal)

说明:

  1. status:撤销确认结果。共识节点在打包区块时,若先于打包用户的撤销交易前,打包了一个新的委托挂单交易,恰好委托挂单能和匹配撮合。这时需先处理撮合成交交易。撮合完成后,若挂单已完全成交,则此次撤销则为失败。反之,若订单只有部分金额撮合成功,或未匹配撮合,则此次撤销成功。
  2. 无论最终的撤销确认是否成功,用户发送的原始撤销挂单交易都会被打包到区块中,作为凭证。
Length Fields Type Remark
32 cancelHash byte[] 用户发起的撤销委托交易hash
32 orderHash byte[] 原始委托挂单交易hash
1 status byte 撤销确认结果: 0 撤销失败 1撤销成功
8 cancelAmount bigInteger 最终确认撤销金额

# 功能描述

# DEX模块功能需求说明

目标:实现一个去中心化的资产交易对交易系统。

需实现功能:

  • 其他链的加密资产能够转入NerveDEX模块,且支持资产在链内的流通,转账数据能够上链。
  • 能够创建资产交易对,且资产交易对的信息能够上链。
  • 用户能够委托挂单,也能够委托撤销挂单。挂单和撤单数据能够上链。
  • 委托挂单能够撮合成交,且有严格公平的撮合机制。且最终的撮合数据能够上链,接受全网监督。
  • 有可视化的交易界面,提供交易对查询、交易对最新价格展示、交易对K线图展示、交易对盘口展示、最新成交记录展示。
  • 有可视化的交易界面,用户可直接挂单买入或者卖出、查看当前委托单信息、撤销委托单、查看用户历史委托记录和成交记录。

实现方式:

  • 他链的加密资产转入到Nerve链来,这个通过NULS生态的跨链模块已实现。NULS链本身就支持生态内的跨链转账,且独有的异构跨链网络,也已实现将其他公链的加密资产转入NULS生态内(目前暂支持ETH和ERC20)。相信资料详见NULS跨链模块文档。

  • 在区块链底层添加交易所运行流程必需的交易协议(交易对创建、用户委托订单、用户撤销委托单、委托单撮合成交);

  • 添加各个协议的验证器。验证器严格规范了交易数据验证流程,只有验证通过的交易协议才允许上链;

  • 数据的维护与处理。数据的维护与处理包括三块:

    1. 区块打包:共识节点打包区块时,需要将盘口维护的已有挂单与新打包的挂单做撮合匹配生成成交协议,撮合匹配这一步严格意义上来说也包括协议验证,因为每个节点打包生成的成交协议,也会被其他节点验证。若验证失败,区块被拒收。
    2. 区块存储:区块存储实际是将已被链上确认的交易数据持久化到本地。DEX模块在存储交易信息时,会先更新维护的盘口数据,再将更新后的数据做持久化存储。
  • 提供可视化界面,方便用户挂单进行买卖操作等功能由附属模块NerveDEX-API模块提供。(详见DEX-API功能文档)。

# 整体功能流程图

# 模块内部功能

# 模块的启动与初始化(DexBootstrap)

加载配置文件

加载模块依赖关系

初始化DEX模块持久化表结构

启动模块定时任务(模块会定期调用账本模块接口查询当前Nerve链已有的他链币信息)

加载DEX模块已有数据(包括资产交易对信息、用户挂单委托信息),通过这些数据创建资产交易对盘口,并将委托单数据放入盘口维护资产交易对交易验证与存储

# 创建资产交易对CoinTrading

用户发起并广播创建资产交易对交易

节点收到并验证交易信息,见CoinTradingProcessor.validate()

打包交易到区块

区块验证通过后,存储资产交易对交易,见CoinTradingProcessor.coinTradingCommit()

  • 持久化资产交易对信息
  • 创建资产交易对盘口

# 资产交易对信息修改EditCoinTrading

用户发起并广播修改资产交易对交易

节点收到并验证交易信息,见EditCoinTradingProcessor.validate()

打包交易到区块

区块验证通过后,存储资产交易对交易,见EditCoinTradingProcessor.editCoinTradingCommit()

  • 持久化资产交易对修改信息
  • 修改资产交易对盘口信息

# 用户委托挂单TradingOrder

用户发起并广播委托挂单交易

节点收到并验证交易信息,见TradingOrderProcessor.validate()

打包交易到区块

区块验证通过后,存储委托单交易,见TradingOrderProcessor.coinTradingCommit()

  • 持久化委托单数据
  • 将委托单数据放入盘口维护,并按照规则排序,见TradingContainer.addTradingOrder()

# 用户撤销委托TradingOrderCancel

用户发起并广播撤销委托挂单交易

节点收到并验证交易信息,见OrderCancelProcessor.validate()

打包交易到区块

区块验证通过后,存储撤销委托单交易

# 共识节点打包DEX-API模块交易(DEX-APITxPackageProcessor.packProduce())

共识节点打包DEX-API模块交易时,会依次将区块内的委托单交易和当前盘口内已维护的挂单交易,尝试匹配撮合生成成交交易。若有用户申请撤销委托,打包时也会根据交易顺序,最终确定用户委托单是否可以撤销,以及可撤销挂单的具体数量。最终将此次打包的所有用户撤销委托申请,汇总生成一条撤销确认交易。生成的成交交易和撤销确认交易会一并打包到区块里。目前一次区块打包最多可确认200个成交交易。如果有新的挂单一次性吃掉盘口的挂单超过200个,则超出的部分会再下次区块出块时优先确认成交。

# 区块确认

节点在接收到新的区块时,首先要对区块内的所有交易进行验证,验证通过后才能持久化存储。DEX-API模块的交易确认和其他模块不同,在批量验证交易时,会根据顺序依次验证委托挂单和撤销委托单。再像打包区块时一样,将新的委托单和盘口已有挂单进行匹配,生成成交交易。最后将生成的成交交易和区块打包的成交交易一一比对,必须要交易数量和成交金额完全一致才能最终确认区块的合法性,并进行持久化存储和更新盘口。