3. 创建合约

超级链支持丰富的智能合约开发语言,比如go,Solitidy,C++,Java等。 阅读本节前,请先确保完成 XuperChain环境部署

3.1. 编写合约

可以根据合约示例代码,编写自己的合约

c++ counter 合约, go counter 合约, java counter 合约

3.2. 部署 wasm合约

  1. 编译合约

    对于C++合约,已提供编译脚本,位于 contractsdk/cpp/build.sh。

    需要注意的是,脚本依赖从hub.baidubce.com拉取的docker镜像,请在编译前确认docker相关环境是可用的

  2. 部署合约

    部署合约的操作需要由合约账号完成,部署操作同样需要支付手续费,操作前需要确保合约账号下有足够的余额

    1. $ ./xchain-cli wasm deploy --account XC1111111111111111@xuper --cname counter ../core/contractsdk/cpp/build/counter.wasm

    运行时会提示手续费的数目,使用 –fee 参数传入即可

  1. 合约调用

    1. $./xchain-cli wasm invoke --method increase -a '{"key":"test"}' counter --fee 100
    2. The gas you cousume is: 93
    3. The fee you pay is: 100
    4. Tx id: 141e4c1fb99566ce4b6ba32fa92af73c0e9857189debf773cf5753d64e1416a7
    5. $./xchain-cli native query --method get -a '{"key":"test"}' counter
    6. contract response: 1

3.3. 部署native合约

如果本地搭建超级链环境,在部署、调用 native 合约之前,请先查看`conf/xchain.yaml` 中native一节,确保native合约功能开启。

  1. # 管理native合约的配置
  2. native:
  3. enable: true
  4. # docker相关配置
  5. docker:
  6. enable:false
  7. # 合约运行的镜像名字
  8. imageName: "docker.io/centos:7.5.1804"
  9. # cpu核数限制,可以为小数
  10. cpus: 1
  11. # 内存大小限制
  12. memory: "1G"
  13. # 停止合约的等待秒数,超时强制杀死
  14. stopTimeout: 3
  1. 编译合约 - Golang

    编译native合约时,只要保持环境和编译XuperChain源码时一致即可,我们以 contractsdk/go/example 中的 counter 合约为例

    1. cd contractsdk/go/example/counter
    2. go build
  2. 编译合约 - Java

    我们以contractsdk/java/example中的counter合约为例

    1. $ cd contractsdk/java/example/counter
    2. $ mvn package
  3. 部署合约

    部署native合约。针对不同语言实现的合约,主要通过 --runtime 字段进行区分

    1. # 部署golang native合约
    2. $./xchain-cli native deploy --account XC1111111111111111@xuper --fee 15587517 --runtime go --cname golangcounter ../core/contractsdk/go/example/counter/main
    3. contract response: ok
    4. The gas you cousume is: 14311874
    5. The fee you pay is: 15587517
    6. Tx id: af0d46f6df2edba4d9d9d07e1db457e5267274b1c9fe0611bb994c0aa7931933
    7. # 部署java native合约
    8. $./xchain-cli native deploy --account XC1111111111111111@xuper --fee 15587517 --runtime java --cname javacounter ../core/contractsdk/java/example/counter/target/counter-0.1.0-jar-with-dependencies.jar
    9. The gas you cousume is: 14311876
    10. The fee you pay is: 15587517
    11. Tx id: 875d2c9129973a1c64811d7a5a55ca80743102abc30d19f012656fa52ee0f4f7
  4. 合约调用

    针对不同语言实现的 native合约,调用方式相同。通过合约名直接发起合约调用和查询

    1. # 调用golang native合约,Increase方法,golangcounter为合约名
    2. $ ./xchain-cli native invoke --method Increase -a '{"key":"test"}' golangcounter
    3. # 调用golang native合约,Get方法,golangcounter为合约名
    4. $ ./xchain-cli native query --method Get -a '{"key":"test"}' golangcounter
    5. contract response: 1
    6. # 调用java native合约,increase方法,javacounter为合约名
    7. $ ./xchain-cli native invoke --method increase -a '{"key":"test"}' javacounter --fee 10
    8. # 调用java native合约,get方法,javacounter为合约名
    9. $ ./xchain-cli native query --method get -a '{"key":"test"}' javacounter
    10. contract response: 1

3.4. 部署solidity合约

如果本地搭建超级链环境,在部署、调用solidity合约之前,请先查看`conf/xchain.yaml` 中evm一节,确保evm合约功能开启。

  1. # evm合约配置
  2. evm:
  3. driver: "evm"
  4. enable: true
  1. 编译合约 - Solidity

    使用 solc 编译solidity合约。安装 solc 编译器,请参见**https://solidity-cn.readthedocs.io/zh/latest/installing-solidity.html\*\*。

    1. solc --version
    2. // solc, the solidity compiler commandline interface
    3. // Version: 0.5.9+commit.c68bc34e.Darwin.appleclang

    我们以contractsdk/evm/example中的counter合约为例

    1. cd core/contractsdk/evm/example/counter
    2. // 通过solc编译合约源码
    3. solc --bin --abi Counter.sol -o .
    4. // 合约二进制文件和abi文件分别存放在当前目录下,Counter.bin和Counter.abi。
  2. 部署合约

    部署solidity合约。

    1. ./xchain-cli evm deploy --account XC1111111111111111@xuper --cname counterevm --fee 5200000 ../core/contractsdk/evm/example/counter/Counter.bin --abi ../core/contractsdk/evm/example/counter/Counter.abi
    2. contract response: ok
    3. The gas you cousume is: 1789
    4. The fee you pay is: 22787517
    5. Tx id: 78469246d86a92ad47e5c15991a55978075902809346e48533e09a8eb0e3a7e4
    • --abi Counter.abi :表示部署需要使用的abi文件,用于合约方法参数编解码

    • ``-a ``:如果合约需要构造函数,通过-a进行指定。与c++、golang等合约的部署和调用方式相同。

  3. 合约调用

    调用solidity合约。通过合约名直接发起合约调用和查询。

    1. # 调用solidity合约,increase方法,counterevm为合约名
    2. $ ./xchain-cli evm invoke --method increase -a '{"key":"test"}' counterevm --fee 22787517
    3. # 调用solidity合约,get方法,counterevm为合约名
    4. $ ./xchain-cli evm query --method get -a '{"key":"test"}' counterevm
    5. # 调用结果,其中0表示返回值的次序,1为返回值
    6. # key,value: 0 1
  4. 超级链账户与EVM账户地址转换

    超级链有普通地址、合约账户以及合约名,这三类账户在EVM运行时需要转换为以太坊的地址类型(16进制编码字符串,形如0x1234567890abcdef1234567890abcdef12345678格式)。超级链提供了上述三个地址与EVM地址类型转换工具。

    1. # xchain合约账户地址转evm地址,contract-account表示超级链合约账户
    2. ./xchain-cli evm addr-trans -t x2e -f XC1111111111111113@xuper
    3. result, 3131313231313131313131313131313131313133 contract-account
    4. # evm地址转xchain合约账户,contract-account表示超级链合约账户
    5. ./xchain-cli evm addr-trans -t e2x -f 3131313231313131313131313131313131313133
    6. result, XC1111111111111113@xuper contract-account
    7. # xchain普通账户地址转evm地址,xchain表示超级链普通账户
    8. ./xchain-cli evm addr-trans -t e2x -f 93F86A462A3174C7AD1281BCF400A9F18D244E06
    9. result, dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN xchain
    10. # xchain普通账户地址转evm地址,xchain表示超级链普通账户
    11. ./xchain-cli evm addr-trans -t x2e -f dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN
    12. result, 93F86A462A3174C7AD1281BCF400A9F18D244E06 xchain
    13. # xchain合约名地址转evm地址,contract-name表示超级链合约名
    14. ./xchain-cli evm addr-trans -t x2e -f storagedata11
    15. result, 313131312D2D2D73746F72616765646174613131 contract-name
    16. # evm地址转xchain合约名,contract-name表示超级链合约名
    17. ./xchain-cli evm addr-trans -t e2x -f 313131312D2D2D73746F72616765646174613131
    18. result, storagedata11 contract-name
    • x2e :表示超级链地址转换为EVM地址

    • e2x :表示EVM地址转换为超级链地址。

3.5. 设置合约方法的ACL

  1. 准备desc文件setMethodACL.desc

    1. {
    2. "module_name": "xkernel",
    3. "method_name": "SetMethodAcl",
    4. "args" : {
    5. "contract_name": "counter",
    6. "method_name": "increase",
    7. "acl": "{\"pm\": {\"rule\": 1,\"acceptValue\": 1.0},\"aksWeight\": {\"UU4kyZcQinAMsBSPRLUA34ebXrfZtB4Z8\": 1}}"
    8. }
    9. }

    参数说明:

    • module_name: 模块名称,用固定值xkernel

    • method_name :方法名称,用固定值SetMethodAcl

    • contract_name:合约名称

    • method_name:合约方法名称

    • acl:合约方法的acl

  2. 设置合约方法ACL

    设置合约方法ACL的操作,需符合合约账号的ACL,在3.2节,使用 XC1111111111111111@xuper 部署的counter合约,合约账号ACL里 只有1个AK,所以在data/acl/addrs中添加1行,如果合约账号ACL里有多个AK,则填写多行。

    1. echo "XC1111111111111111@xuper/dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN" > data/acl/addrs

    执行如下命令,设置ACL:

    1. ./xchain-cli multisig gen --desc ./setMethodACL.desc --fee 1 -H 127.0.0.1:37101
    2. ./xchain-cli multisig sign --output sign.out
    3. ./xchain-cli multisig send sign.out sign.out -H 127.0.0.1:37101
  3. 查看合约方法ACL

    1. [work@]$ deploy-env -> ./xchain-cli acl query --contract counter --method increase -H :37101
    2. # 执行结果
    3. # {
    4. # "pm": {
    5. # "rule": 1,
    6. # "acceptValue": 1
    7. # },
    8. # "aksWeight": {
    9. # "UU4kyZcQinAMsBSPRLUA34ebXrfZtB4Z8": 1
    10. # }
    11. # }