2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

_code と _self の違い

Posted at

EOS のスマートコントラクトを開発する時、_code_self について把握できてなかったので、この辺の内容を調べてみました。

変数 英語 日本語(意訳)
_code The name of this contract このコントラクトの名前
_self The code name of the action this contract is processing. この契約が処理しているアクションのコード名

出典:https://eosio.github.io/eosio.cdt/group__contract.html#variable-self

先に結論

  • _self は、どのケースでも関数が所属しているコントラクトになる
  • _codeは、
    • require_recipient の通知を受け取る場合だけ、通知元のコントラクトになる
    • それ以外は、_selfと同じ

require_recipient 以外、プリントアウトしてみる

  • hello コントラクト関数内
  • hello コントラクトが inline action で呼び出した message コントラクトの関数内
  • hello コントラクトが deferred action で呼び出した message コントラクトの関数内

hello.cpp

#include <eosiolib/eosio.hpp>
#include <eosiolib/transaction.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public eosio::contract {
  public:
    hello(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds){}

    [[eosio::action]]
    void hi(name from) {
      print("_code : ", name{_code}, ", _self : ", name{_self}, ", get_code: ", name{get_code()}, ", get_self : ", name{get_self()});

      action(
        permission_level{from, "active"_n},
        "message"_n,
        "callme"_n,
        std::make_tuple()
      ).send();

      transaction txn{};
      const uint128_t sender_id = 100; // 遅延呼び出しに付ける任意の id

      txn.actions.emplace_back(
        action(
          permission_level{from, "active"_n},
          "message"_n,
          "callme"_n,
          std::make_tuple()
        )
      );

      txn.delay_sec = 1; // 遅延する秒数
      txn.send(sender_id, from);
    }
};

EOSIO_DISPATCH(hello, (hi))

message.cpp

#include <eosiolib/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] message : public eosio::contract
{

  public:
    message(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds){}

    [[eosio::action]] 
    void callme()
    {
      print("_code : ", name{_code}, ", _self : ", name{_self}, ", get_code: ", name{get_code()}, ", get_self : ", name{get_self()});
    }
};

EOSIO_DISPATCH(message, (callme))

実験

上記2つコントラクトをコンパイルしてデプロイしておいてから、実行してみると

cleos push action hello hi '["bob"]' -p bob
executed transaction: 84f5772661416e48c86cea7cc087bd23188de33afe5564cb455a24d2f69c29d4  144 bytes  6513 us
#         hello <= hello::hi                    {"from":"bob"}
>> _code : hello, _self : hello, get_code: hello, get_self : hello
#       message <= message::callme              ""
>> _code : message, _self : message, get_code: message, get_self : message
warning: transaction executed locally, but may not be confirmed by the network yet         ]

nodes 側のログで確認すると、

2018-12-10T20:43:50.169427100Z debug 2018-12-10T20:43:50.167 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T20:43:50.169460900Z [(hello,hi)->hello]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T20:43:50.169480500Z _code : hello, _self : hello, get_code: hello, get_self : hello
2018-12-10T20:43:50.169502300Z [(hello,hi)->hello]: CONSOLE OUTPUT END   =====================
2018-12-10T20:43:50.169551700Z debug 2018-12-10T20:43:50.167 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T20:43:50.169573200Z [(message,callme)->message]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T20:43:50.169593800Z _code : message, _self : message, get_code: message, get_self : message
2018-12-10T20:43:50.169625700Z [(message,callme)->message]: CONSOLE OUTPUT END   =====================
2018-12-10T20:43:50.506156600Z info  2018-12-10T20:43:50.502 thread-0  producer_plugin.cpp:1490      produce_block        ] Produced block 001432f1eb282355... #1323761 @ 2018-12-10T20:43:50.500 signed b
y eosio [trxs: 1, lib: 1323760, confirmed: 0]
2018-12-10T20:43:51.010081600Z info  2018-12-10T20:43:51.001 thread-0  producer_plugin.cpp:1490      produce_block        ] Produced block 001432f2192708e3... #1323762 @ 2018-12-10T20:43:51.000 signed b
y eosio [trxs: 0, lib: 1323761, confirmed: 0]
2018-12-10T20:43:51.011983000Z debug 2018-12-10T20:43:51.011 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T20:43:51.012076700Z [(message,callme)->message]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T20:43:51.012197000Z _code : message, _self : message, get_code: message, get_self : message
2018-12-10T20:43:51.012250300Z [(message,callme)->message]: CONSOLE OUTPUT END   =====================

結論

_code_self は、どのケースでも同じ値でした

require_recipient で通知された場合

hello.cpp

hi 関数の処理に require_recipient("message"_n); を追記し、message アカウントに通知する

#include <eosiolib/eosio.hpp>
#include <eosiolib/transaction.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public eosio::contract {
  public:
    hello(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds){}

    [[eosio::action]]
    void hi(name from) {
      print("_code : ", name{_code}, ", _self : ", name{_self}, ", get_code: ", name{get_code()}, ", get_self : ", name{get_self()});

      require_recipient("message"_n);

      action(
        permission_level{from, "active"_n},
        "message"_n,
        "callme"_n,
        std::make_tuple()
      ).send();

      transaction txn{};
      const uint128_t sender_id = 100; // 遅延呼び出しに付ける任意の id

      txn.actions.emplace_back(
        action(
          permission_level{from, "active"_n},
          "message"_n,
          "callme"_n,
          std::make_tuple()
        )
      );

      txn.delay_sec = 1; // 遅延する秒数
      txn.send(sender_id, from);
    }
};

EOSIO_DISPATCH(hello, (hi))

message.cpp

  • EOSIO_DISPATCH_EX を定義し、通知受け取った時の処理を変更して、hello からの通知を受け取るようにします。
  • hi メソッドも定義して、プリントアウトしています。
#include <eosiolib/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] message : public eosio::contract
{

  public:
    message(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds){}

    [[eosio::action]] 
    void callme()
    {
      print("_code : ", name{_code}, ", _self : ", name{_self}, ", get_code: ", name{get_code()}, ", get_self : ", name{get_self()});
    }

    [[eosio::action]] 
    void hi()
    {
      print("_code : ", name{_code}, ", _self : ", name{_self}, ", get_code: ", name{get_code()}, ", get_self : ", name{get_self()});
    }
};

#define EOSIO_DISPATCH_EX(TYPE, MEMBERS)                                       \
  extern "C"                                                                   \
  {                                                                            \
    void apply(uint64_t receiver, uint64_t code, uint64_t action)              \
    {                                                                          \
      print("receiver : ", name{receiver}, ", code : ", name{code});           \
      if (code == receiver || code == "hello"_n.value)                               \
      {                                                                        \
        switch (action)                                                        \
        {                                                                      \
          EOSIO_DISPATCH_HELPER(TYPE, MEMBERS)                                 \
        }                                                                      \
        /* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
      }                                                                        \
    }                                                                          \
  }

EOSIO_DISPATCH_EX(message, (callme)(hi))

実行すると、

cleos push action hello hi '["bob"]' -p bob
executed transaction: 03ff84d534bf1c7f84ab6296ef78d91673df944035ea6b8a145bde481f5f33f5  144 bytes  6008 us
#         hello <= hello::hi                    {"from":"bob"}
>> _code : hello, _self : hello, get_code: hello, get_self : hello
#       message <= hello::hi                    {"from":"bob"}
>> receiver : message, code : hello_code : hello, _self : message, get_code: hello, get_self : message
#       message <= message::callme              ""
>> receiver : message, code : message_code : message, _self : message, get_code: message, get_self : message
warning: transaction executed locally, but may not be confirmed by the network yet         ]

nodes側のログは、下記のようになっています

2018-12-10T21:16:14.414101400Z debug 2018-12-10T21:16:14.411 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T21:16:14.414181300Z [(hello,hi)->hello]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T21:16:14.414208800Z _code : hello, _self : hello, get_code: hello, get_self : hello
2018-12-10T21:16:14.414260700Z [(hello,hi)->hello]: CONSOLE OUTPUT END   =====================
2018-12-10T21:16:14.414308700Z debug 2018-12-10T21:16:14.412 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T21:16:14.414331600Z [(hello,hi)->message]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T21:16:14.414360900Z receiver : message, code : hello_code : hello, _self : message, get_code: hello, get_self : message
2018-12-10T21:16:14.414388000Z [(hello,hi)->message]: CONSOLE OUTPUT END   =====================
2018-12-10T21:16:14.414424300Z debug 2018-12-10T21:16:14.412 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T21:16:14.414446100Z [(message,callme)->message]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T21:16:14.414465500Z receiver : message, code : message_code : message, _self : message, get_code: message, get_self : message
2018-12-10T21:16:14.414489100Z [(message,callme)->message]: CONSOLE OUTPUT END   =====================
2018-12-10T21:16:14.508502900Z info  2018-12-10T21:16:14.505 thread-0  producer_plugin.cpp:1490      produce_block        ] Produced block 0014421cffd84734... #1327644 @ 2018-12-10T21:16:14.500 signed b
y eosio [trxs: 1, lib: 1327643, confirmed: 0]
2018-12-10T21:16:15.012995300Z info  2018-12-10T21:16:15.002 thread-0  producer_plugin.cpp:1490      produce_block        ] Produced block 0014421ddfdb1fdc... #1327645 @ 2018-12-10T21:16:15.000 signed b
y eosio [trxs: 0, lib: 1327644, confirmed: 0]
2018-12-10T21:16:15.013123600Z debug 2018-12-10T21:16:15.006 thread-0  apply_context.cpp:28          print_debug          ]
2018-12-10T21:16:15.013195500Z [(message,callme)->message]: CONSOLE OUTPUT BEGIN =====================
2018-12-10T21:16:15.013343400Z receiver : message, code : message_code : message, _self : message, get_code: message, get_self : message
2018-12-10T21:16:15.013416400Z [(message,callme)->message]: CONSOLE OUTPUT END   =====================

ポイントは、(hello,hi)->message の処理の時、_codehelloになっているところです。

receiver : message, code : hello_code : hello, _self : message, get_code: hello, get_self : message

まとめ

  • 処理の中では、関数が所属しているコントラクト名を使いたい場合は、_selfを使う
  • 通知を受け取る時は、_code で通知元を判定できる
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?