美文网首页
EOS智能合约开发及授权

EOS智能合约开发及授权

作者: eosspark | 来源:发表于2018-08-13 10:10 被阅读0次

    环境描述:

    阅读本文前,假定您已经能够启动单节点EOSIO node,如果还不能正确操作,请参考官方WIKI:https://developers.eos.io/eosio-nodeos/docs/autobuild-script

    操作系统:MAC OS 10.13.X,EOSIO版本号:V1.1.3

    自定义合约开发与测试,在单节点操作,流程更简单,效果相同,因此以下操作流程都是在没有部署eosio.system合约的环境中进行。

    操作步骤:

    1.启动EOS环境,创建两组key

    启动NODE:

    nodeos --data-dir tmpdata -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin--plugin eosio::history_api_plugin --max-transaction-time=1000(避免超时设置1000)

    创建KEY:

    cleos create key

    2.使用创建的public_key,创建eosio.token用户,创建部署合约账户cactus,转账账户from:

    create account eosio eosio.token EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8 EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8

    create account eosio cactus EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8 EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8

    create account eosio from EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8 EOS6JowfuTT7CZe4ResHqNvEWAnuYjCT68gw97KxsHY99sUk2t1j8

    2.1解锁钱包:

    cleos wallet unlock --password PW5JCM32pkoqwfNwfMnLih8Gh5s5edbQyys6vP3Ci9NxL2x6EKecq

    2.2导入私钥:

    导入用户private_key:

    cleos wallet import --private-key 5JC3dp6z2imXiAnq4M4JAQXetRntU23QLoFNZJxwBB1yxPVsSW3

    导入eosio的private_key:

    cleos wallet import --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

    3.发布eosio.token合约到eosio.token

    3.1cd到eosio目录/build/programs/cleos

    cleos set contract eosio.token ../../contracts/eosio.token

    3.2创建代币:

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

    3.3发行代币

    cleos push action eosio.token issue '["eosio","1000000000.0000 SYS","issue"]' -p eosio

    至此,基础工作完毕,可以先把node节点停掉,开始编写自定义转账合约。


    4.创建自定义转账合约cactus.token.cpp

    打开源码目录contracts,新建目录cactus.token,创建源码文件cactus.token.cpp,此合约使用了inline_action的方式调用eosio.token合约的transfer函数,inline action具体来说就是一个智能合约的代码调用另外一个智能合约的函数。action(xx).send(),具体参数的含义是:Action(permssion_level, other_contract_account_name, method, args)

    action(permission_level{from, N(active)}, 
                 N(eosio.token), N(transfer), 
                 std::make_tuple(from, to,quantity,std::string("cactus transfer"))).send();
    

    此处,合约调用eosio.token transfer方法从from的账户转账,因此必须获得用户from的active权限,否则不能操作,具体授权在8处详述。

    注意:目录名称与主文件名称相同,部署合约时使用目录名进行部署

    namespace cactus {
        class msig : public eosio::contract {
        public:
            using contract::contract;
            msig(account_name self)
                    : eosio::contract(self), mtranses(_self, _self), wits(_self, _self),cts(_self, _self) {}
            //@abi action
            void transfer(account_name from, account_name to, asset quantity) {
                auto quant_after_fee = quantity;
                eosio_assert(is_account(from), "to account does not exist");
                eosio_assert(quantity.is_valid(), "invalid quantity");
                eosio_assert(quantity.amount > 0, "must withdraw positive quantity");
                require_auth(from);
                action(
                        permission_level{from, N(active)},
                        N(eosio.token), N(transfer),
                        std::make_tuple(from, _self, quantity, std::string("cactus transfer"))
                ).send();
                cts.emplace(_self, [&](auto &a) {
                    a.id = cts.available_primary_key();
                    a.from = from;
                    a.to = to;
                    a.amount = quantity.amount;
                });
            }
    

    5.根据cactus.token.cpp生成cactus.token.wast及cactus.token.wasm,cactus.token.abi文件

    cd 到eosio主目录/contracts/cactus.token/

    生成cactus.token.wast、cactus.token.wasm文件,虚拟机加载使用

    eosiocpp -o cactus.token.wast cactus.token.cpp

    生成cactus.token.abi文件

    eosiocpp -g cactus.token.abi cactus.token.cpp

    执行此命令将文件夹cactus.token copy到build/contracts/

    cp -R ../cactus.token ../../build/contracts/

    6.重新启动node节点:

    nodeos --data-dir tmpdata -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin--plugin eosio::history_api_plugin --max-transaction-time=1000(避免超时设置1000)

    7.部署合约

    部署自定义合约到账户cactus,此时终端cd eosio主目录/build/contracts :

    cleos set contract cactus cactus.token

    可以看到输出内容如下图所示

    contracts.jpg

    8.授权
    8.1 eosio.code内部权限
    dawn4.0后新增的内部特殊权限eosio.code,用来加强inline action的安全性,当cactus.token智能合约代码通过action.send调用eosio.token智能合约时,cactus.token代码是拿不到任何私钥的,也就没法为声明的权限签名,即没办法证明该智能合约具备action声明的权限from@active。此时系统代码做安全性保障,因而系统提出了一个虚拟权限eosio.code。具体逻辑执行时,权限检验逻辑(controller.authorization_manager) ,cactus.transfer已经具备cactus@eosio.code权限。然后authorization_manager只需检验from@active是否授权给cactus@eosio.code即可。通过这种虚拟的权限证明解决了合约调用合约的权限检测问题。

    如图标红处,校验合约部署账户的eosio.code权限,以避免inline action调用时出现安全问题。

    contracts.jpg

    8.2合约账户授权

    智能合约cactus.token要调用eosio.token合约中transfer,将from的代币转出,必须得到from的授权,但是合约执行又需要使用合约部署账户的eosio.code权限才能操作,因此必须把from@active权限赋予cactus@eosio.code才能执行;

    cleos set account permission from active '{"threshold" : 1, "keys" : [{"key":"EOS5CoAP5TqEzvzVjdhCfDrhffZ7JdpN7dnxgEqjAoVd2n4vRa5Zb","weight":1}], "accounts" : [{"permission":{"actor":"cactus","permission":"eosio.code"},"weight":1}]}' owner -p from@owner

    执行结果:

    contracts.jpg

    8.3查看A的权限信息:

    cleos get account from

    执行结果如图所示

    contracts.jpg

    9.使用合约进行转账

    cleos push action cactus transfer '["from","cactus","10.0000 SYS"]' -p from

    操作结果:


    contracts.jpg

    至此,自定义合约转账的编码和授权操作结束。

    相关文章

      网友评论

          本文标题:EOS智能合约开发及授权

          本文链接:https://www.haomeiwen.com/subject/zjjybftx.html