首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >铂链第4课 如何在BOTTOS实现最简智能合约"Hello World"?

铂链第4课 如何在BOTTOS实现最简智能合约"Hello World"?

作者头像
辉哥
发布2019-02-22 15:05:43
5590
发布2019-02-22 15:05:43
举报
文章被收录于专栏:区块链入门区块链入门

1,摘要

本文假设你已经完成了铂链本地节点部署和账户创建,没有完成的话,参考《铂链第3课 BOTTOS账户体系(密钥对/账号/钱包)的创建和管理》完成相关准备工作。 本文的主要内容包括: (1)用C++创建"Hello World"合约 (2)编译wasm和ABI文件 (3)部署和运行合约

2,内容

2.1 前置条件-本地节点启动和账户创建

1)启动本地节点

参考《铂链第2课 如何部署节点并加入BOTTOS测试网络?》 完成本地节点部署。 启动本地节点

./bottos --delegate=bottos --enable-wallet

2)创建账户,质押BTO

请参考《铂链第3课 BOTTOS账户体系(密钥对/账号/钱包)的创建和管理》 完成用户账号的创建,从系统账号转账一定的BTO并质押200个BTO。

账户信息: 账号名称: wangdenghui 密钥对: public_key: 049b98b5f5eea7fd5145842d08f8cd25052f69e731f9f550ac8a2e37792e165cf13fbc52ad7dad32eaa192799601b4cc35eab1923e007048f9d47c80aa4bf9cb8d private_key: 1d2533b83d5c811b53b7503aad9488310631b705e9df12bbce8c03149be559fd 账户余额:800BTO 质押情况:100 BTO for time; 100 BTO for space;

2.2 创建合约

C++和C语言的语法,辉哥就不展开分析了。假设我们创建了相关的文件。

1) testHelloWorld.cpp

三个函数,打印“hello world...”出来。

#include "contractcomm.hpp"

extern "C" {
    int start();
    int add();
    int del();
}

int start() 
{
    myprints("hello world in start");
    
    return 0;
}

int add() 
{
    myprints("hello world in add");
    
    return 0;
}

int del() 
{
    myprints("hello world in del");
    
    return 0;
}
2) testHelloWorld.h

头文件定义

//@abi action start
struct NullStruct {
};

2.3 编译产生wasm和ABI文件

(1)制定合约工作目录和下载编译版本

假设我们创建/home/duncanwang/go/work目录作为BOTOS工作目录。 在工作目录下,下载编译工具:

git clone https://github.com/bottos-project/contract-tool-cpp.git

【成功执行结果】

duncanwang@ubuntu64bit-server:~/go/work$ git clone https://github.com/bottos-project/contract-tool-cpp.git
Cloning into 'contract-tool-cpp'...
remote: Enumerating objects: 31, done.
remote: Counting objects: 100% (31/31), done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 237 (delta 16), reused 23 (delta 10), pack-reused 206
Receiving objects: 100% (237/237), 26.89 MiB | 2.02 MiB/s, done.
Resolving deltas: 100% (128/128), done.
Checking out files: 100% (41/41), done.
(2) 编译合约产生WASM文件

上面合约代码其实铂链的编译工具已经自带了,辉哥就不重复上传了。只是提示下,如果发生Access Denied的问题,记得chmod 777修改文件读写属性即可。 进入合约目录testHelloWorld,然后运行下面命令编译合约

python ../gentool.py --type wasm --file testHelloWorld.cpp

运行后,新的testHelloWorld.wasm和testHelloWorld.wast已经产生了。

【成功结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ python ../gentool.py --type wasm --file testHelloWorld.cpp
../bin/clang -emit-llvm -O3 --std=c++14 --target=wasm32 -ffreestanding -nostdlib -fno-threadsafe-statics -fno-rtti -fno-exceptions -I ../lib -I . -c testHelloWorld.cpp -o ./tmpdir/build/testHelloWorld.cpp
In file included from testHelloWorld.cpp:1:
../lib/contractcomm.hpp:181:22: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
            myprints("ERROR: Get my contract name failed.");
                     ^
../lib/contractcomm.hpp:196:18: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
        myprints("getBinValue failed!");
                 ^
testHelloWorld.cpp:11:14: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
    myprints("hello world in start");
             ^
testHelloWorld.cpp:18:14: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
    myprints("hello world in add");
             ^
testHelloWorld.cpp:25:14: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
    myprints("hello world in del");
             ^
5 warnings generated.
../bin/llvm-link -o ./tmpdir/linked.bc ./tmpdir/build/*
../bin/llc --asm-verbose=false -o ./tmpdir/assembly.s ./tmpdir/linked.bc
../bin/s2wasm -o testHelloWorld.wast -s 16384 ./tmpdir/assembly.s
常见问题及解决方案
1)【失败结果】- python未安装
duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp$ python

Command 'python' not found, but can be installed with:

sudo apt install python3       
sudo apt install python        
sudo apt install python-minimal

You also have python3 installed, you can run 'python3' instead.

【安装出错】

duncanwang@ubuntu64bit-server:~/go/work$ sudo apt install python   
[sudo] password for duncanwang: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python-minimal python2.7 python2.7-minimal
Suggested packages:
  python-doc python-tk python2.7-doc binutils binfmt-support
The following NEW packages will be installed:
  libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python2.7 python2.7-minimal
0 upgraded, 7 newly installed, 0 to remove and 75 not upgraded.
Need to get 3,949 kB of archives.
After this operation, 16.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 python-minimal amd64 2.7.15~rc1-1 [28.1 kB]
Get:4 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpython2.7-stdlib amd64 2.7.15~rc1-1 [1,910 kB]
Get:7 http://archive.ubuntu.com/ubuntu bionic/main amd64 python amd64 2.7.15~rc1-1 [140 kB]                                              
Err:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpython2.7-minimal amd64 2.7.15~rc1-1                                                                                              
  502  Bad Gateway [IP: 117.143.109.143 80]
Err:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 python2.7-minimal amd64 2.7.15~rc1-1                                                                                                 
  502  Bad Gateway [IP: 117.143.109.142 80]
Get:5 http://archive.ubuntu.com/ubuntu bionic/main amd64 python2.7 amd64 2.7.15~rc1-1 [238 kB]                                                                                                
Get:6 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpython-stdlib amd64 2.7.15~rc1-1 [7,620 B]                                                                                        
Fetched 2,324 kB in 17s (136 kB/s)                                                                                                                                                            
E: Failed to fetch http://117.143.109.143/cache/archive.ubuntu.com/ubuntu/pool/main/p/python2.7/libpython2.7-minimal_2.7.15~rc1-1_amd64.deb?ich_args2=144-13213206052547_3259d609842731f004706c767b1bb39a_10001002_9c89602ed6c2f4d8903c518939a83798_5a2e3e24305ad5ad963c61d5902f3d1f  502  Bad Gateway [IP: 117.143.109.143 80]
E: Failed to fetch http://117.143.109.142/cache/archive.ubuntu.com/ubuntu/pool/main/p/python2.7/python2.7-minimal_2.7.15~rc1-1_amd64.deb?ich_args2=144-13213210052808_ca0ba91cda916deada222929a3eb7ae4_10001002_9c89602ed6c2f4d8903c518939a83798_6d64072715e5c504a601fe11b7a54dbe  502  Bad Gateway [IP: 117.143.109.142 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

【访问外国网站-安装成功有输出】

duncanwang@ubuntu64bit-server:~/go/work$ sudo apt install python
[sudo] password for duncanwang: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python-minimal python2.7 python2.7-minimal
Suggested packages:
  python-doc python-tk python2.7-doc binutils binfmt-support
The following NEW packages will be installed:
  libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python2.7 python2.7-minimal
0 upgraded, 7 newly installed, 0 to remove and 75 not upgraded.
Need to get 334 kB/3,949 kB of archives.
After this operation, 16.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpython2.7-minimal amd64 2.7.15~rc1-1 [334 kB]
Fetched 334 kB in 3s (124 kB/s)                
Selecting previously unselected package libpython2.7-minimal:amd64.
(Reading database ... 102201 files and directories currently installed.)
Preparing to unpack .../0-libpython2.7-minimal_2.7.15~rc1-1_amd64.deb ...
Unpacking libpython2.7-minimal:amd64 (2.7.15~rc1-1) .......................................................................................................................................] 
Selecting previously unselected package python2.7-minimal..................................................................................................................................] 
...
Processing triggers for mime-support (3.60ubuntu1) ...##########################################################################################...........................................] 
Processing triggers for man-db (2.8.3-2) ...
Setting up libpython2.7-stdlib:amd64 (2.7.15~rc1-1) ...
Setting up python2.7 (2.7.15~rc1-1) ...###################################################################################################################.................................] 
Setting up libpython-stdlib:amd64 (2.7.15~rc1-1) ...###############################################################################################################........................] 
Setting up python (2.7.15~rc1-1) ...########################################################################################################################################...............] 
2)文件目录不正确

【错误输出】

duncanwang@ubuntu64bit-server:~/go/work/RegUser$ python ~/go/work/contract-tool-cpp/gentool.py wasm testRegUser.cpp
Error! Please keep these files [clang | llc | llvm-link | s2wasm] under current directory.

【解决方法】 工作目录要建立在~/go/work/contract-tool-cpp下,不要建立在其他地方。

(3) 编译合约产生ABI文件

运行以下命令产生ABI文件。

python ../gentool.py --file testHelloWorld.hpp

【成功结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ python ../gentool.py --file testHelloWorld.hpp

[ testHelloWorld.abi ] is generated. Please have a check.

下载已产生的ABI,可以看到testHelloWorld.abi内容如下:

{
    "types": [],
    "structs": [
              {
                "name": "NullStruct",
                "base": "",
                "fields": {
                    }
                }
       ],
    "actions": [
              {
                "action_name": "start",
                "type": "NullStruct"
              }
       ],
    "tables": [
       ]
}

简单介绍一下abi文件的组成:

structs :扫描出来的结构体的定义描述,这儿是"NullStruct",供后面使用; actions:合约提供的方法描述,其中action_name 是方法名,例如 "start"函数, type 是调用合约所要的参数; tables :合约持久化数据访问接口描述,即合约保存的数据描述,其中table_name 是表名,index_type 是索引的类型, key_names 和key_types 分别是键值的名称和类型,type 是保存的数据的结构定义。

abi文件是通过扫描hpp文件生成, 在hpp文件里通过注释来告诉扫描器具体的定义:

"//@abi action start": ​ 本合约定义了两个方法,其中start 对应的入参定义为NullStruct;

”//@abi table testTableName:index_type:string, key_names:keyName, key_types:string “ ​ 定义了一个表, 表内容的结构体定义为testTableName 。本案例不存在。

2.3 部署和运行合约

(1)部署智能合约与ABI文件

部署合约d的命令如下,该命令成功后将返回BCLI成功发送的Transaction信息。

./bcli contract deploy

参数描述如下: --contract 合约名 --code 合约文件(.WASM)所在路径 --filetype 合约文件类型:wasm/js --abi 合约文件(.abi) --account 部署合约的账户

在操作前,需要把bcli 命令从BOTTOS安装环境复制过来。

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ cp /home/duncanwang/go/src/github.com/bottos/bcli .

然后,把wangdenghui账号unlock,把部署的合约取名为babycry,样例命令如下:

./bcli contract deploy --contract babycry --account wangdenghui --code testHelloWorld.wasm --abi testHelloWorld.abi

【成功交易结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli contract deploy --contract babycry --account wangdenghui --code testHelloWorld.wasm --abi testHelloWorld.abi

TrxHash: fc5527e0600b353c0c38c87b64ec29c8b8856fc36ec83575f916b1cc556def7f

This transaction is sent. Please check its result by command : bcli transaction get --trxhash  <hash>

【查询交易结果】

./bcli transaction get --trxhash fc5527e0600b353c0c38c87b64ec29c8b8856fc36ec83575f916b1cc556def7f

【结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli transaction get --trxhash  fc5527e0600b353c0c38c87b64ec29c8b8856fc36ec83575f916b1cc556def7f
{
    "ResourceReceipt": {
        "account_name": "wangdenghui",
        "space_token_cost": 2138,
        "time_token_cost": 100
    },
    "Transaction": {
        "contract": "bottos",
        "cursor_label": 1543494136,
        "cursor_num": 5304,
        "lifetime": 1546681090,
        "method": "deploycontract",
        "param": {
            "contract": "babycry",
            "contract_abi": "7b0a09227479706573223a205b5d2c0a092273747275637473223a205b0a20202020202020202020202020207b0a202020202020202020202020202009226e616d65223a20224e756c6c537472756374222c0a2020202020202020202020202020092262617365223a2022222c0a202020202020202020202020202009226669656c6473223a207b0a20202020202020202020202020202020202020207d0a2020202020202020202020202020097d0a202020202020205d2c0a0922616374696f6e73223a205b0a20202020202020202020202020207b0a20202020202020202020202020200922616374696f6e5f6e616d65223a20227374617274222c0a2020202020202020202020202020092274797065223a20224e756c6c537472756374220a20202020202020202020202020207d0a202020202020205d2c0a09227461626c6573223a205b0a202020202020205d0a7d0a",
            "contract_code": "0061736d01000000010d0360027f7f006000006000017f020e0103656e76067072696e74730000030504010202020404017000000503010001074205066d656d6f7279020005737461727400020361646400030364656c0004215f474c4f42414c5f5f7375625f495f7465737448656c6c6f576f726c642e63707000010a9c0304f202004100420037028c4041004200370294404100420037029c40410042003702a440410042003702ac40410041003602b440410041003602b840410041003602bc40410041003602c040410041003602c440410041003602c840410041003602cc40410041003602d040410041003602d440410041003602d840410041003602dc40410041003602e040410041003602e440410041003602e840410041003602ec40410041003602f040410041003602f440410041003602f840410041003602fc404100410036028041410041003602844141004100360288414100410036028c414100410036029041410041003602944141004100360298414100410036029c41410041003602a041410041003602a441410041003602a841410041003602ac41410041003602b041410041003602b441410041003602b841410041003602bc41410041003602c041410041003602c441410041003602c841410041003602cc41410041003602d041410041003602d4410b0c004180c5004114100041000b0c0041a0c5004112100041000b0c0041c0c5004112100041000b0b5a040041040b04e0620000004180c5000b1568656c6c6f20776f726c6420696e207374617274000041a0c5000b1368656c6c6f20776f726c6420696e20616464000041c0c5000b1368656c6c6f20776f726c6420696e2064656c00",
            "vm_type": 1,
            "vm_version": 1
        },
        "sender": "wangdenghui",
        "sig_alg": 1,
        "signature": "65b8fe0a75949e3250ae1074234989fc3850af7179ef184d233e0c15d7e5a3025e7c343b557756af3e516b16cdda126c7f9728a65788a73ed6e8f4ba49890a9c",
        "version": 65536
    },
    "TrxHash": "fc5527e0600b353c0c38c87b64ec29c8b8856fc36ec83575f916b1cc556def7f"
}

<<<Transaction Status>>> : commited

【提醒】 如果已把bcli复制到系统bin文件夹,则直接执行bcli ...,如果是复制到工作目录,则需要输入./bcli ...格式。

复制bcli命令到本地工程目录,命令调用格式:./bcli ...

cp /home/duncanwang/go/src/github.com/bottos/bcli .

复制到可执行文件夹,命令调用格式:bcli ...

cp /home/duncanwang/go/src/github.com/bottos/bcli /usr/bin/.

【常见错误提示】
duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli contract deploy --contract babyContract --account wangdenghui --code testHelloWorld.wasm --abi testHelloWorld.abi
Error: Please input the correct contract's name, [a-z,0-9], 3-10 character, begin with a-z

【分析说明】 合约名称不超过10个字符,只能是小写字母和数字a-z,0-9,这个太戏剧了,10个字符能表达一个好的合约名字吗?建议铂链采用不超过32个字符的名字均可。

(2)运行合约

运行合约的命令如下,该命令成功后将返回指定Trxhash对应的Transaction信息。

./bcli transaction push

参数说明: --sender 签名发起者(缺省为内置bottos用户) --contract 合约名,格式为合约名@部署账户 --method 合约方法名 --param 参数键值对 --sign 用户自定义公钥(缺省为内置缺省值)

【运行合约样例】

./bcli transaction push --sender wangdenghui --method start --contract babycry@wangdenghui

【执行成功结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli transaction push --sender wangdenghui --method start --contract babycry@wangdenghui

TrxHash: 50226dc38a102b4dd848ecebbf3cb3668886f7b0f10158acd435e315efcb930a

This transaction is sent. Please check its result by command : bcli transaction get --trxhash  <hash>

【查看合约是否部署成功】

./bcli  transaction  get --trxhash  "50226dc38a102b4dd848ecebbf3cb3668886f7b0f10158acd435e315efcb930a"

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli  transaction  get --trxhash  "50226dc38a102b4dd848ecebbf3cb3668886f7b0f10158acd435e315efcb930a"

<<<Transaction Status>>> : commited


./bcli  gettable --account wangdenghui --table testTableName --key testKeyName

./bcli  transaction  get --trxhash  "c0780dd99c1d38b613cc3c644309a897b022dfbcf45c029ee7e1b701aa6385db"
【重大疑问】-输出并没有"hello world"的打印

BOTTOS的命令行输出没有Info打印信息,所有信息都在~/go/src/github.com/bottos/datadir/log的bottos.log文件显示。 但是默认情况下不显示info信息,需要执行命令改变。

修改LOG输出等级的命令:

./bcli log setconfigitem

参数说明: --key 日志参数,选其一设置:minlevel maxlevel --value 按日志参数,填写对应项值 例如: ./bcli log setconfigitem --key minlevel --value debug

【调整LOG等级输出结果】

duncanwang@ubuntu64bit-server:~/go/work/contract-tool-cpp/testHelloWorld$ ./bcli log  setconfigitem --key minlevel --value debug
{
    "errcode": 0
}
setconfigitem successfully.

再执行合约。 然后再执行./bcli transaction push命令,就可以在bottos.log文件搜索"hello world in start"关键字可以看到对应的"hello world ..."打印。 如下:

2019-01-05 10:39:21.173 [INF] res-processor.go:444 GetUserFreeTimeLimit(): RESOURCE:GetUserFreeTime account:wangdenghui, limit:{Available:202 Used:198 Max:400}
2019-01-05 10:39:21.173 [INF] res-processor.go:420 GetUserTimeLimit(): RESOURCE:GetUserTimeLimit account:wangdenghui, limit:{Available:28799999709 Used:291 Max:28800000000}
2019-01-05 10:39:21.174 [INF] env_func.go:442 prints(): VM prints value hello world in start

至此,BOTTOS最简合约的编写及运行讲解完毕。

3,参考

1) 铂链官网 http://www.bottos.org/ 2)铂链开发手册 https://docs.botfans.org/en/ 3)铂链GITHUB https://github.com/bottos-project 4)研发帮助文档 https://github.com/bottos-project/Documentation/tree/master/resource_cn 5)BCLI使用说明 https://github.com/bottos-project/Documentation/blob/master/resource_cn/BCLI%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md

本篇文章得到铂链技术专家张伟的指导,谨表感谢。


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.01.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1,摘要
  • 2,内容
    • 2.1 前置条件-本地节点启动和账户创建
      • 2.2 创建合约
        • 2.3 编译产生wasm和ABI文件
          • 2.3 部署和运行合约
          • 3,参考
          相关产品与服务
          区块链
          云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档