美文网首页EOS学习大本营
EOS之智能合约授权限制和数据存储

EOS之智能合约授权限制和数据存储

作者: P叔 | 来源:发表于2018-06-01 17:22 被阅读91次

    EOS智能合约授权限制和数据存储

    123.png

    在EOS合约中,调用合约需要来自账户的授权,同时还要指定需要调用的动作。当然,有的合约并不是所有账户都可以调用的,这就需要用到授权限制。接下来我们就来看看如何限制合约的授权账户。

    合约案例

    为了更好的演示,写了一个下课和吃饭的智能合约小例子。这个合约有两个动作,下课和吃饭。教师账户可以调用下课动作,学生账户可以调用吃饭动作。教师调用下课动作后,学生才能调用吃饭动作。接下来我们来看代码:

    teacher.hpp

    头文件teacher.hpp定义了两个动作,over是class over 下课动作,eat是吃饭动作。

    #include <eosiolib/eosio.hpp>
    #include <eosiolib/print.hpp>
    
    using namespace eosio;
    
    class teacher_stu : public eosio::contract{
    
        using contract::contract;
      public:
        teacher_stu( account_name self ) :
            contract( self ) {}
    
        void over(account_name teacher);
    
        void eat(account_name student);
    
      private:
        static uint64_t id;
    
        // @abi table
        struct mshare {
          uint64_t id;
          uint64_t start = 0;
    
          uint64_t primary_key() const { return id; }
        };
    
        typedef multi_index<N(mshare), mshare> mshares;
    
    };
    
    EOSIO_ABI( teacher_stu, (over)(eat))
    

    teacher.cpp

    teacher.cpp中主要是over和eat动作的实现。

    #include "teacher.hpp"
    
    uint64_t teacher_stu::id = 1;
    uint64_t start = 0;
    
    void teacher_stu::over(account_name teacher) {
      require_auth(teacher);
      print("teache:Class over!");
    
      mshares mshare_table(_self, _self);
    
      start = 1;//存储动作调用状态
      mshare_table.emplace( teacher, [&]( auto& mshare ) {
        mshare.id = id;
        mshare.start = start;
      });
    }
    
    void teacher_stu::eat(account_name student) {
      require_auth(student);
      mshares mshare_table(_self, _self);
      auto it = mshare_table.find( id );
      if (it->start == 1) {
        print("student:Class over, go to eat!");
        mshare_table.erase( it );
      }
      else
        print("teacher:Class time, you can't eat");
    }
    

    仔细观察这段代码就会发现,over和eat动作中都有个"require_auth()"语句。在over动作中,"requir_auth(teacher)"的作用是限制只有"teacher"账户才可以调用over动作。在eat动作中则是限制只有"student"账户才可调用eat动作。

    合约数据存储

    此合约设计为下课后才可以吃饭,所以当教师账户调用合约的over动作后,需要存储一个合约调用状态值。EOS合约的数据存储需要用数据库,把数据存到一张表中,这是令人很难受的。

    teacher.hpp

    在teacher.hpp中创建一个结构体。下段代码中的"//@abi table"注释非常重要,必须要写的,如果不写数据将无法存储。

        static uint64_t id;
    
        // @abi table
        struct mshare {
          uint64_t id;
          uint64_t start = 0;
    
          uint64_t primary_key() const { return id; }
        };
    
        typedef multi_index<N(mshare), mshare> mshares;
    

    DAWN 3.0 使用eosio::multi_index作为容器,我们可以使用emplace来插入数据,使用modify来修改数据,使用erase删除数据。

    teacher.cpp

      mshares mshare_table(_self, _self);
    
      start = 1;
      mshare_table.emplace( teacher, [&]( auto& mshare ) {
        mshare.id = id;
        mshare.start = start;
      });
    

    在over动作中创建数据,学生调用eat动作后再修改或删除数据即可

      mshares mshare_table(_self, _self);
      auto it = mshare_table.find( id );
      if (it->start == 1) {
        print("student:Class over, go to eat!");
        mshare_table.erase( it );
      }
    

    合约调用效果展示

    • 授权限制
    $ cleos push action class over '{"teacher":"teacher","student":"student"}' -p student
    Error 3030001: 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 authority using -p option.
    Error Details:
    missing authority of teacher
    
    • 学生没下课就吃饭
    $ cleos push action class eat '{"teacher":"teacher","student":"student"}' -p student
    executed transaction: 02918b223230cb9ea1fd383e0499ea22d22ced8f2108db3233bdfd51c06f3b37  232 bytes  102400 cycles
    #         class <= class::eat                   {"student":"student"}
    >> teacher:Class time, you can't eat
    
    • 正常下课吃饭
    $ cleos push action class over '{"teacher":"teacher","student":"student"}' -p teacher
    executed transaction: a96520fa28c8412e0998080126734337507811638ecf6b939e904818a4892e35  232 bytes  103424 cycles
    #         class <= class::over                  {"teacher":"teacher"}
    >> teache:Class over!
    $ cleos push action class eat '{"teacher":"teacher","student":"student"}' -p student
    executed transaction: 2955a693b626c539d20da9d4f5d41a6b53bb8ca2b2651b63cf4a67012fb3dd7e  232 bytes  103424 cycles
    #         class <= class::eat                   {"student":"student"}
    >> student:Class over, go to eat!
    
    • 查看表中数据
    $ cleos get table class class mshare
    {
      "rows": [{
          "id": 1,
          "start": 1
        }
      ],
      "more": false
    }
    
    

    整个合约写下来调通也是费了我很多脑细胞,数据存储也比较坑爹啊。现在把我的一点经验分享出来,希望大家在学习EOS的路上少踩一些坑。

    知识星球二维码380.png

    相关文章

      网友评论

        本文标题:EOS之智能合约授权限制和数据存储

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