前两天一直在写一个帮助用户从交易所提现完成注册账户的智能合约,理论上EOS中的inline action
是可以调用所有的智能合约的,当然也应该包括EOS的系统合约。newaccount
作为系统中用来完成账户创建的合约,怎么调用它在我们的合约中是无法绕过的一个问题。但是当我找到eosio.system.cpp
中的代码的时候,他是长这个样子的:
void native::newaccount( account_name creator,
account_name newact
/* no need to parse authorites
const authority& owner,
const authority& active*/ ) {
跟我们用cleos
命令行工具的时候传入的根本对不上,authority
直接被注释了也不知道是什么意思。急着把合约开发出来,没时间跟他纠结。立马转向去研究cleos
命令行工具的代码,这次看到的还算是像个样子:
chain::action create_newaccount(const name& creator, const name& newaccount, public_key_type owner, public_key_type active) {
return action {
tx_permission.empty() ? vector<chain::permission_level>{{creator,config::active_name}} : get_account_permissions(tx_permission),
eosio::chain::newaccount{
.creator = creator,
.name = newaccount,
.owner = eosio::chain::authority{1, {{owner, 1}}, {}},
.active = eosio::chain::authority{1, {{active, 1}}, {}}
}
};
}
心想这下简单了,直接套用就是了。结果编译的时候就开始了无止境的报错:
'float.h' file not found when I include <eosio/chain/types.hpp>
最后给官方提了个issue,官方给了解答
You shouldn't include any eosio/chain/* inside your smart contract, it won't be supported. The right types.hpp for a smart contract is #include <eosio/types.hpp> which is the file inside contracts/eosiolib/types.hpp
大概明白了chain中的头文件虽然会安装到本地,但并不是给合约用的。然而他们给的这个eosio/types.hpp
当中并没有我最需要的authority
结构体。最后只好放弃用官方的头文件,开始自己把newaccount所需要的结构体撸了一遍,总算成功调用。
signupeoseos这个合约中另一个浪费时间比较多的地方就是EOS公钥的解码了,因为系统合约中大部分用到公钥的地方都是直接用的eosio::public_key
这个结构体。
namespace eosio {
struct public_key {
unsigned_int type;
std::array<char,33> data;
}
}
所以如果通过memo来传输公钥地址的话,就必须先把公钥地址解码成eosio::public_key
,否则无法完成其他系统合约的调用。好在EOS公钥的格式设计还是相对比较简单的,前面三个字符是 EOS
前缀,去掉之后剩下的50个字符是经过base58编码的一个字符串,直接解出来去掉最后的4字节的rim160
检验位,剩下的33字节就是public_key
中的data
部分。至于base58解码函数,本来想用EOS中的代码,后来因为跟上面一样的原因失败了,所以直接拷贝了比特币的代码过来解决之。