eos 开发一个记录转账信息的智能合约

 

 “EOS to the ground!”昨天老板看了我的文章,上来就劈头盖脸说,“什么to the moon,心情差,招你来是炒币的?!我们是一个最落地的DApp开发团队,打造牛逼的产品,然后跟社区分享技术心得! %@¥#@%¥!%@*……(此处打码数千字)。”老板还说,创业团队的人要脚踏实地,还要有老板的心态。其实我觉得我就很踏实啊,还特了解我们的老板,就是凡事都要梭哈,才能有最大收获(1美金扫货eos的主不懂18美金吃进的苦......),好了好了,我们要去火星落地,今天我们会学会eos的系统初始化、转发EOS代币、智能合约开发、EOS智能合约消息通知机制、数据持久化存储。。。内容有点多,请同学们系好安全带,发!车!咯!

EOS系统初始化

上篇我们详细介绍了如何在虚拟机编译eos。编译安装完eos之后,我们就可以运行nodeos了:

 $ nodeos-e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin--plugin eosio::history_api_plugin

可以看到nodeos加载wallet_api_plguin, chain_api_plugin, 和history_api_plugin这三个插件, 这个三个插件的功能简单罗列如下:

Wallet:提供操作钱包的命令,比如创建新钱包,导入私钥,解锁钱包等等。

Chain:获取链上信息,以及提交交易等

History:获取指定账号的交易历史记录

 

Nodeos启动后,系统默认有个初始账号,叫eosio,可以认为这是一个root账号。EOS系统的账号必须由系统内已有的账号创建,这是EOS有别于其他区块链的一个地方。

要创建账号,我们需要指定账号owner和active权限的公钥,我们可以使用系统提供的 cleos create key来创建一对公私钥:

$ cleos create key

Private key:5Jmsawgsp1tQ3GD6JyGCwy1dcvqKZgX6ugMVMdjirx85iv5VyPR

Public key: EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

 

接下来我们创建钱包:

$ cleos wallet create

Creating wallet: default

Save password to use in the future tounlock this wallet.

Without password imported keys will not beretrievable.

"PW5K5gvNHJ48n6fVh2nG7Hdqmf115DzQy4D2ZtTEQmic6whZGbVDT"

创建钱包时,会提示用户保存钱包的密码,这个密码很重要,钱包过一段时间会自动上锁,需要使用这个密码解锁,才能使用里面的私钥对发起的交易消息进行签名。

钱包创建好之后,我们导入刚才创建的私钥:

$ cleos wallet import5Jmsawgsp1tQ3GD6JyGCwy1dcvqKZgX6ugMVMdjirx85iv5VyPR

imported private key for: EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

这样,钱包里就保存了公钥对应的私钥了。接下来,我们初始化系统,用eosio账号加载esoio.bios合约;创建eosio.token账号,加载eosio.token合约。依次执行如下命令:

# 部署eosio.bios合约

$ cleos set contract eosio~/eos/build/contracts/eosio.bios -p eosio

# 创建eosio.token账号

$ cleos create account eosio eosio.token EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4   EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

# 部署eosio.token合约

$ cleos set contract eosio.token~/eos/build/contracts/eosio.token -p eosio.token

接下来创建EOS系统中的EOS代币,我们创建10亿个EOS,代币的发行者是eosio账号。

$ cleos push action eosio.token create '["eosio", "1000000000.0000 EOS", 0, 0, 0]' -p eosio.token

EOS的一个合约必须与一个账号关联,而且,一个账号只能部署一个合约。此外,EOS系统的合约能够升级,假如修改了合约,可以通过cleos set contract命令重新部署。

创建charity合约账号和测试账号

完成了系统初始化,创建charity合约账号和使用合约的账号alice和bob备用。为了简化起见,我们新创建的账号owner权限和active权限都使用刚才产生的公钥。

# 创建charity账号

$ cleos create account eosio charityEOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

# 创建alice账号

$ cleos create account eosio aliceEOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

# 创建bob账号

$ cleos create account eosio bobEOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4

 

然后由eosio给alice和bob分别发行1万个EOS:

$ cleos push action eosio.token issue '["alice", "10000.0000 EOS", "" ]' -p eosio

$ cleos push action eosio.token issue '["bob", "10000.0000 EOS", "" ]' -p eosio

开发charity智能合约

新建一个测试目录,在该目录下使用eosiocpp产生智能合约的初始文件:

$ eosiocpp -n charity

可以看见,命令新建了一个目录charity,在chairty目录自动生成了charity.abi、charity.hpp和charity.cpp这三个文件,其中abi文件是描述智能合约的接口。打开这个三个文件,发现自动生成的合约实现了一个接口hi,但是abi描述不对。

修改charity.abi文件:

{

 "types": [{

     "new_type_name": "account_name",

     "type": "name"

    }

  ],

 "structs": [{

     "name": "hi",

     "base": "",

     "fields": [

       {"name":"user","type":"account_name"}

     ]

    }

  ],

 "actions": [{

     "name": "hi",

     "type": "hi",

     "ricardian_contract": ""

    }

  ],

 "tables": [

  ],

 "ricardian_clauses": []

}

 

然后在charity的目录中执行部署合约的命令:

$ cleos set contract charity .   charity.wast charity.abi -p charity

合约部署成功之后,我们可以看见合约的hash值:

$ cleos get code charity

code hash:1d0070ffc528f1268ad1f6c5ba998245811318bdcfd8827432d56e24c69a476c

若没有部署合约,code hash是全为0.

现在调用charity的hi接口,我们看看合约会输出什么:

$ cleos push action charity hi '["alice"]'-p alice

executed transaction:4e0c500d27fdd4d2a093b5f0c60e5023c9f1d0addc185db0e1bac37a2f                                                                                                                                 643fcd  104 bytes 1242 us

#      charity <= charity::hi                  {"user":"alice"}

>> Hello, alice

 

我们可以看到,合约简单的把hi接口传入的字符串输出,完成合约的调用。考察命令输出提示信息:

#      charity <= charity::hi                  {"user":"alice"}

其中<= 指向左边的charity是receiver,就是接受调用的合约账号。<=右边的charity::hi指的是调用charity合约的hi接口。聪明如你一定会问了,难道<=左右两边receiver和contract还会不一样?你说对了,合约中有消息通知机制,可以把一条合约的调用发给另一个合约receiver。我们下一步给charity转账就会发现了:

$ cleos push action eosio.token transfer '{"from":"alice","to":"charity","quantity":"10.0000EOS","memo":""}' -p alice

executed transaction:ba422c8f8f2efb540a9e3a91e6d615235dcf90d0d6f750c41ac8b0b0c93bf1cc  128 bytes 989 us

#  eosio.token <= eosio.token::transfer        {"from":"alice","to":"charity","quantity":"10.0000EOS","memo":""}

>> transfer from alice to charity10.0000 EOS

#        alice <= eosio.token::transfer       {"from":"alice","to":"charity","quantity":"10.0000EOS","memo":""}

#      charity <= eosio.token::transfer       {"from":"alice","to":"charity","quantity":"10.0000EOS","memo":""}

 

从上面我们可以看到,调用eosio.token的账号的transfer接口转账,会有消息通知发送方和接收方。聪明的你可能又想到了,在charity合约中把接收到消息内容记录下来不就OK了?

说干就干,模仿eosio.token合约的transfer接口,给charity也实现一个,现在仅仅是简单的输出信息:

eos 开发一个记录转账信息的智能合约_第1张图片

编译、部署、再给charity账号转账,可是没有我们期望的输出。哪里出了问题?查看EOS源代码下contracts/eosiolib/dispather.hpp中的EOSIO_ABI的宏定义:

eos 开发一个记录转账信息的智能合约_第2张图片

展开是个C语言的apply调用,其中receiver和code就是合约名称转成的Uint64的数值,加上action,刚看看到的<= 输出其实是:

        receiver    <= code::action

考察代码,发现只有receiver等于code才能继续调用合约接口。哈哈,问题找到了,稍作修改,重新定义一下宏,命名为EOSIO_ABI_EX:

eos 开发一个记录转账信息的智能合约_第3张图片

其中增加判断条件若是由eosio.token合约转发过来的消息,也可以继续处理。

修改好之后,编译、部署,然后再给charity账号转账,查看结果:

果然,在最后一句输出transfer的跟踪消息。

调用问题解决了之后,我们要把和charity交易的消息记录在EOS的table之中。首先在头文件定义table记录的数据结构:

eos 开发一个记录转账信息的智能合约_第4张图片

这个数据结构包括transfer接口传进的参数,还加了一个自增id作为主键。还需在charity.abi文件中对这个table进行描述:

增加一个record结构描述,此结构作为table的type。

eos 开发一个记录转账信息的智能合约_第5张图片

然后再增加table的描述,这样,我们的table在abi文件中就定义完整了。

eos 开发一个记录转账信息的智能合约_第6张图片

接下来,我们在charity::transfer中添加代码保存每次转账时候的记录:

eos 开发一个记录转账信息的智能合约_第7张图片

编译、部署,我们再通过eosio.token合约给charity转账:

重复执行一次,然后使用cleos get table查查看record表中的数据:

eos 开发一个记录转账信息的智能合约_第8张图片

哈哈,查出来,两笔alice转账的记录!至此,我们初步实现了一个合约接收转账消息,并把它记录在表格中的功能。

代码已经上传至github,https://github.com/ofo/charity,any commentsare welcome!

转自:https://www.jianshu.com/p/d8d03562b3d5

你可能感兴趣的:(Eos)