2.1 Hello World!
在之前创建的contracts
目录创建一个新目录命名为hello
.或者通过系统GUI或cli创建一个名为hello
的目录并按下enter.
cd /Users/zhong/coding/CLion/contracts
mkdir hello
cd hello
创建一个新文件:hello.cpp
,并用你最喜欢的编辑器打开它.
touch hello.cpp
将需要的依赖包含进去:
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
为了让合约的内容更简洁, 请使用命名空间eosio
.
using namespace eosio;
eosiolib/eosio.hpp
加载了EOSIO C 和C++ API到你的合约上下文,这是你的新warchest.
创建一个标准的C++11类.这个合约需要继承eosio:contract
.
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;
class hello : public contract {};
一个空的合约不需要做什么事情.添加一个public
权限修饰符和using
声明 .using
声明会让我们编写的代码更简洁.
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;
class hello : public contract {
public:
using contract::contract;
};
这个合约需要做些什么.基于hello world的精神,写一个action接收一个"name"参数.然后将这个参数打印出来.
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;
class hello : public contract {
public:
using contract::contract;
[[eosio::action]]
void hi( name user ) {
print( "Hello, ", user);
}
};
上面这个action可以接受一个类型为name
命名为user
的参数.EOSIO提供了一些类型定义,name
会是你最常遇到的之一.使用之前引入的eosio:print
library,连接字符串并将user
参数打印出来
这样,eosio.cdt
的abi generator在没有参数的情况下不会知道hi()
这一action.添加一个C++11的样式属性到action上,这能让abi generator创建更可靠的输出.
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;
class hello : public contract {
public:
using contract::contract;
[[eosio::action]]
void hi( name user ) {
print( "Hello, ", user);
}
};
EOSIO_DISPATCH( hello, (hi))
最后,添加EOSIO_ABI
宏来处理hello
合约对actions的分发.
EOSIO_DISPATCH( hello, (hi))
所有事都完成了,这是完整的hello world合约:
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;
class hello : public contract {
public:
using contract::contract;
[[eosio::action]]
void hi( name user ) {
print( "Hello, ", user);
}
};
EOSIO_DISPATCH( hello, (hi))
eosio.cdt的ABI Generator支持一些不同的参数样式,查看ABI使用指南 here
你能编译你的合约为 web assembly(.wasm):
eosio-cpp -o hello.wasm hello.cpp --abigen
当合约部署好了,它会被部署到一个账户,这个账户成为这个合约的接口.在这些教程的前面提到过,对所有的账户都使用相同的公钥以求简单.
cleos wallet keys
使用下面的命令创建一个账户 cleos create account:
cleos create account eosio hello EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV -p eosio@active
出现了error?
任何和链上的交互都需要将钱包解锁,或者你没有在教程的
1.3
部分设置alias(别称)
使用cleos set contract将编译好的wasm
广播到区块链.
cleos set contract hello /Users/zhong/coding/CLion/contracts/hello -p hello@active
set contract
是发布合约的命令,hello
是发布合约的账户,/Users/zhong/coding/CLion/contracts/hello
是包含WAST或WASM的文件,-p hello@active
是授权账户和权限级别,如account@permission
(默认为account@active
)
很好!现在合约设置好了,push一个action给它.
cleos push action hello hi '["bob"]' -p bob@active
结果:
zhongdeMacBook-Pro:hello zhong$ cleos push action hello hi '["bob"]' -p bob@active
executed transaction: 151987c8763a5f008229cf9fbcec1c07034717e533585c9fe33658bddc87db04 104 bytes 418 us
# hello <= hello::hi {"user":"bob"}
>> Hello, bob
warning: transaction executed locally, but may not be confirmed by the network yet ]
如我们所写的代码,合约允许任何账号对任何人 say hi
cleos push action hello hi '["bob"]' -p alice@active
executed transaction: 28d92256c8ffd8b0255be324e4596b7c745f50f85722d0c4400471bc184b9a16 244 bytes 1000 cycles
# hello.code <= hello.code::hi {"user":"bob"}
>> Hello, bob
就和我们预想的一样,控制台输出了"Hello, bob".
当前,"alice"是给其授权的人,user
只是一个参数. 修改合约让它需要权限.在当前的例子应该是"alice", 必须是同样的参数传入才能让合约相应hi
这一action.使用require_auth
函数.该函数会校验当前执行action的account是否拥有它所对应的权限.
[[eosio::action]]
void hi( name user ) {
require_auth( user );
print( "Hello, ", user);
}
重新编译合约:
eosio-cpp -o hello.wasm hello.cpp --abigen
然后更新它:
cleos set contract hello /Users/zhong/coding/CLion/contracts/hello -p hello@active
现在再尝试执行action,但这次会说权限不匹配.
cleos push action hello hi '["bob"]' -p alice@active
就像预期的一样,require_auth
停止了交易并抛出了一个错误:
Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the [relevant](**http://google.com**) authority using -p option.
通过我们对合约的修改,验证提供的account_name user
和我们授权用户一样.这次,在参数中传入"alice".
cleos push action hello hi '["alice"]' -p alice@active
结果:
executed transaction: 31d2e756527e8afa6c8733cbb32ec85fd654f1a856f94168b8176b865e447b57 104 bytes 248 us
# hello <= hello::hi {"user":"alice"}
>> Hello, alice
warning: transaction executed locally, but may not be confirmed by the network yet ]