14. 面向资产互换的原子性保障应用使用指南

14.1. 概述

14.1.1. 跨链原子性协议概述

本应用支持基于哈希时间锁合约HTLC、哈希时间锁优化合约Lilac实现具有事务原子性保障的跨链资产互换。应用用户客户端实现了提案筛选、事件监听、自动取款、自动退款等操作。

了解跨链原子性协议设计方案,请看该链接: 跨链原子性协议设计方案

14.2. 部署流程

14.2.1. 源码下载

  • 下载源码到本地

git clone https://git.chainmaker.org.cn/ibpc/atomic_assets_swap.git

14.3. 应用代码整体目录结构

.
├── bin # 区块链必要的可执行文件
├── chainclient # 链SDK接口
├── chainmaker_contract_test.sh # 长安链合约测试脚本
├── chainmaker_restart.sh # 长安链重启脚本
├── client # 用户客户端接口
├── client_test.md # 用户客户端测试示例文档
├── commod.md # 用户客户端测试命令文档
├── config # 链用户私钥、证书接口
├── config_files # 链配置文件、测试用户私钥、证书
├── contracts # 链上合约
├── deploy # 合约部署脚本
├── fabric_restart.sh # Fabric重启脚本
├── go.mod
├── go.sum
├── install-deploy-contract.sh # 启动合约部署脚本
├── keystore 
├── main.go # 用户连接客户端
├── Makefile
├── presentation # 性能测试
├── projectinterface # 链接入的标准接口
├── README.md
├── restart.sh # 系统重启脚本
├── scripts # 其它脚本
├── stop.sh # 关闭链脚本
├── test # Fabric合约测试
├── test.sh # 覆盖率测试脚本
├── ut_cover.sh # ut测试脚本
├── utils
├── 设计方案.md
└── 部署和使用文档.md

14.3.1. 部署本地链环境,安装并启动区块链

  • 进入应用文件夹,部署链环境

cd atomic-assets-swap/
make && ./restart.sh

14.3.2. 安装必要的合约

  • 执行install-deploy-contract.sh脚本,编译并安装合约

bash install-deploy-contract.sh

14.3.3. 启动客户端

  • 在应用根目录下, 打开两个terminal,模拟用户1用户2

  • 用户1终端执行

go run main.go client1
  • 用户2终端执行

go run main.go client2
  • 在两个终端会看到类似的输出

tips: [当前工作空间:  /home/.../atomic-assets-swap]
info: [chain1_user1 address:  99fecbbd54840df106f652f571c05384b4bafba8]
info: [chain2_user1 address:  e70f6e47003083409c43392665c72a37115dc07f]
info: [配置文件: ./config_files/fabric/user.yaml]
info: [call assets getAddress]
info: [call assets reset]
info: [fabric_user1 address:  63642b1ad5a7f5dcb03372bee094b0851bef668dc5a04e8033388d4184b1f424]
Please input command line :info: [订阅lilac的withdraw]
info: [订阅lilac的newProposal]
info: [订阅htlc的newProposal]
info: [订阅htlc的withdraw]
  • 通过输入对应的命令执行对应的操作

  • 输入exit或者break退出客户端

14.4. 使用方法

  • 通过在控制台输入相应的交互命令执行对应的操作

  • 当输入命令错误的时候会提示命令

tips: [###### usage ######]
newHtlcProposal chainName userName toAddr amount Preimage hashlock timelock chain2 amount
newLilacProposal chainName userName toAddr amount Preimage hashlock timelock chain2 amount
refund chainName userName contractName proposalID
withdraw chainName userName contractName proposalID preimage
getProposal chainName userName proposalType proposalID
getBalance chainName userName
getAddress chainName userName
break
exit
tips: [###### end ######]

14.4.1. 退出

  • 在终端输入命令进行退出

exit/break
# 输出如下:
info: [login out client.]

14.4.2. 获取用户的地址

  • 获取链chainName上用户userName的地址

  • 比如在链chain1上获取用户user1的地址

# getAddress chainName userName
getAddress chain1 user1
# 输出如下:
info: [address:18bea55343220196ce02038b147c149e275b38cc]

14.4.3. 获取用户余额

  • 获取链chainName上用户userName的余额

  • 比如在链chain1上获取用户user2的余额

# getBalance chainName userName
getBalance chain1 user2
# 输出如下:
info: [chain1 user2 balance:  1000]

14.4.4. 发起一个新的htlc proposal

  • 发起一个新的htlc proposal,是从chainName的用户userName,发送给目的地址toAddr4d8bae757deae72905c6cbc6bc688dc74f634c77的用户amount个token,并以preimage为原像,锁定timelock秒的时间,兑换chain2amount个token

  • 如果preimage设置不为nil则会自动计算哈希锁hashlock,此时hashlock的输入没有作用

  • 如果preimage字段设置为nil,则将会使用hashlock字段作为哈希锁

  • 比如链chain1上的用户user1,发起一个htlc proposal, 发给链chain14d8bae757deae72905c6cbc6bc688dc74f634c77地址用户10个币,并从链chain2获得1个币,设置原像为preimage, 时间锁timelock设置为600秒, 命令为

# newHtlcProposal chainName userName toAddr amount Preimage hashlock timelock chain2 amount
newHtlcProposal chain1 user1 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 preimage nil 600 chain2 1
# 输出如下:
info: [preimage preimage]
info: [hashlock 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f]
info: [timelock 600]
tips: [发起时的hashlock 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f]
info: [newProposal:705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4]
tips: [proposal加入完成 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4]
info: [{18bea55343220196ce02038b147c149e275b38cc 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 1682062662 600 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f preimage false false false 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4 chain1 user1 htlc htlc chain2 1}]
  • 同时在客户端2看到输出

info: [===== chain1 监听到proposal ===== 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4]
info: [{18bea55343220196ce02038b147c149e275b38cc 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 1682062661 600 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f null true false false 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4 chain1 user2 htlc htlc  0}]
  • 表示客户端2收到一个关于自己用户的proposal

  • 客户端2上的链2用户2发起一个对应的proposal, 发给链chain2上的用户user1地址 d9053ab1c1088feaab4f727eeeac69aa327eb28c 1个token,并以同样的哈希锁 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f ,设置时间锁hashlock300秒, 期望获得链chain110个token

newHtlcProposal chain2 user2 d9053ab1c1088feaab4f727eeeac69aa327eb28c 1 nil 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f 300 chain1 10
# 输出如下:
info: [preimage ]
info: [hashlock 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f]
info: [timelock 300]
tips: [发起时的hashlock 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f]
info: [newProposal:8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863]
tips: [proposal加入完成 8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863]
info: [{e525a7ff7b740539b9bb36c3fd081acb3a0d20c2 d9053ab1c1088feaab4f727eeeac69aa327eb28c 1 1682062882 300 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f  false false false 8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863 chain2 user2 htlc htlc chain1 10}]
  • 同时会在客户端1看到输出, 表示进入了自动取款程序

info: [===== chain2 监听到proposal ===== 8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863]
info: [{e525a7ff7b740539b9bb36c3fd081acb3a0d20c2 d9053ab1c1088feaab4f727eeeac69aa327eb28c 1 1682062881 300 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f null true false false 8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863 chain2 user1 htlc htlc  0}]
tips: [等待1秒]
info: [===== new proposal切换到对端链取钱 =====]
info: [{"sender":"e525a7ff7b740539b9bb36c3fd081acb3a0d20c2","receiver":"d9053ab1c1088feaab4f727eeeac69aa327eb28c","amount":0,"posaltime":1682062881,"timelock":300,"hashlock":"107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f","preimage":"preimage","locked":false,"unlocked":true,"rolledback":false}]
info: [====== 取钱成功 ======: 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4]
info: [======= chain1 =======]
info: [自己的proposal被取钱了]
info: [{18bea55343220196ce02038b147c149e275b38cc 4d8bae757deae72905c6cbc6bc688dc74f634c77 0 1682062661 600 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f preimage false true false 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4 chain1 user1 htlc htlc  0}]
warning: [监听到属于自己的Propsal, 但是没在本地找到匹配的proposal异常]
  • 随后在客户端2看到输出, 表示看到了

info: [======= chain2 =======]
info: [自己的proposal被取钱了]
info: [{e525a7ff7b740539b9bb36c3fd081acb3a0d20c2 d9053ab1c1088feaab4f727eeeac69aa327eb28c 0 1682062881 300 107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f preimage false true false 8caefc5171998eafd5ff7d19116c795be5435c50ffce9e57517a8f1d24d80863 chain2 user2 htlc htlc  0}]
info: [withdraw切换到对端链取钱]
info: [{"sender":"18bea55343220196ce02038b147c149e275b38cc","receiver":"4d8bae757deae72905c6cbc6bc688dc74f634c77","amount":0,"posaltime":1682062661,"timelock":600,"hashlock":"107661134f21fc7c02223d50ab9eb3600bc3ffc3712423a1e47bb1f9a9dbf55f","preimage":"preimage","locked":false,"unlocked":true,"rolledback":false}]
  • 链1用户1和链2用户1查看余额

getBalance chain1 user1
getBalance chain2 user1
# 输出如下:
info: [chain1 user1 balance:  990]
info: [chain2 user1 balance:  1001]
  • 客户端2同理

14.4.5. 发起一个新的lilac proposal

  • htlc proposal一样,唯一的不同是preimage字段需要写入多个原像,并以,隔开

  • 发起一个新的lilac proposal,是从chainName的用户userName,发送给目的地址toAddr4d8bae757deae72905c6cbc6bc688dc74f634c77的用户 amount个token,并以preimage1preimage2为原像,锁定timelock秒的时间,兑换chain2amount个token,其中preimage字段有多个用户,以英文逗号,分割

  • 如果preimage设置不为nil则会自动计算哈希锁hashlock,此时hashlock的输入没有作用

  • 如果preimage字段设置为nil,则将会使用hashlock字段作为哈希锁

  • 比如链chain1上的用户user1,发起一个lilac proposal, 发给链chain14d8bae757deae72905c6cbc6bc688dc74f634c77 地址用户10个币,并期望从链chain2兑换1个币,设置原像为 preimage1,preimage2, 时间锁hashlock设置为10, 等待10秒会自动退款, 命令为

# newLilacProposal chainName userName toAddr amount Preimage hashlock timelock chain2 amount
newLilacProposal chain1 user1 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 preimage1,preimage2 nil 10 chain2 1
  • 有如下输出, 其中 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854proposal id

info: [vPreimage: [preimage1 preimage2]]
info: [vHashlock: [5144f34d1b8edc707120dc254bf56e00bd9f5a6f5e6892f72103408f43ee9ded 7a869987c84cbd23568dab928f0229581c2658e61a1ee37214c83ea16ba9cba7]]
info: [timelock 10]
tips: [发起时的hashlock [5144f34d1b8edc707120dc254bf56e00bd9f5a6f5e6892f72103408f43ee9ded 7a869987c84cbd23568dab928f0229581c2658e61a1ee37214c83ea16ba9cba7]]
info: [newProposal:04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854]
tips: [proposal加入完成 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854]
info: [{18bea55343220196ce02038b147c149e275b38cc 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 1682063920 10 [5144f34d1b8edc707120dc254bf56e00bd9f5a6f5e6892f72103408f43ee9ded 7a869987c84cbd23568dab928f0229581c2658e61a1ee37214c83ea16ba9cba7] [preimage1 preimage2] false false false 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854 chain1 user1 lilac lilac chain2 1}]
  • 等待10秒会自动退款,有如下输出

info: [proposa超时,进入退款程序:{18bea55343220196ce02038b147c149e275b38cc 4d8bae757deae72905c6cbc6bc688dc74f634c77 10 1682063920 10 [5144f34d1b8edc707120dc254bf56e00bd9f5a6f5e6892f72103408f43ee9ded 7a869987c84cbd23568dab928f0229581c2658e61a1ee37214c83ea16ba9cba7] [preimage1 preimage2] false false false 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854 chain1 user1 lilac lilac chain2 1}]
info: [{"sender":"18bea55343220196ce02038b147c149e275b38cc","receiver":"4d8bae757deae72905c6cbc6bc688dc74f634c77","amount":0,"posaltime":1682063920,"timelock":10,"hashlock":["5144f34d1b8edc707120dc254bf56e00bd9f5a6f5e6892f72103408f43ee9ded","7a869987c84cbd23568dab928f0229581c2658e61a1ee37214c83ea16ba9cba7"],"preimage":[],"locked":false,"unlocked":true,"rolledback":true}]

14.4.6. 手动退款

  • 用户userName在链chainName上发起一个contractName的退款请求

  • 比如用户user1对在链chain1proposalid04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854lilac proposal退款,命令如下

# refund chainName userName contractName proposalID
refund chain1 user1 lilac 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854
  • 由于这个proposal id已经被取款了,所以会失败, 报锁定状态错误

info: [run commond:  [refund chain1 user1 lilac 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854]]
funcName->run commond error->funcName->c.refund error->c.Refund error: funcName->contractinvoke.RefundLilac error->=== IncokeContract ===
resp.Message->
resp.ContractsResult->code:1 result:"proposal \"locked\" state error" message:"Fail" gas_used:11625 
error->=== client.InvokeContract ===
resp.Message->
resp.ContractsResult->code:1 result:"proposal \"locked\" state error" message:"Fail" gas_used:11625 
  • 比如用户user1对在链chain1proposalid04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854htlc proposal退款,命令如下

# refund chainName userName contractName proposalID
refund chain1 user1 htlc 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854

14.4.7. 对某个proposal id取款

  • 用户userName在链chainName上对id为propsalIDcontractName类型的proposal取款withdraw, 同时提供原像preimage

  • 比如链chain1用户user1,对proposal id04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854lilac类型proposal取款,使用withdraw命令,需要提前知道preimage,命令如下

# withdraw chainName userName contractName proposalID preimage
withdraw chain1 user1 lilac 04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854 preimage1,preimage2
  • 取款htlc类型的proposal,和lilac一样,示例命令如下

  • 比如链chain1用户user1,对proposal id04dac20d774781d9a0814cbbb84a8634e24b684d100f32203068d9228700a854htlc类型proposal取款,使用withdraw命令,需要提前知道preimage,命令如下

# withdraw chainName userName contractName proposalID preimage
withdraw chain1 user1 htlc 705b7fb6cd2c28ad848a00abda4708856d6f20706ba93021a5fc4d44c8eb45a4 preimage