Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

cleos create account を実行する時の流れを調べてみました

More than 1 year has passed since last update.

account 情報の保存場所を調べてみました で newaccount の例をあげましたが、実際 cleos create account を実行する時に、どうやって newaccount 関数まで辿ったのかは把握出来なかったので、もう少し調べてみました。

処理ハンドラー登録

事前にシステム側で用意している処理をハンドラーに登録しています。

// libraries/chain/controller.cpp
// 下記のように、`eosio`の`newaccount`アクションの呼び出しを、`apply_eosio_newaccount`の `apply_handler` に指すように設定しています
#define SET_APP_HANDLER( receiver, contract, action) \
   set_apply_handler( #receiver, #contract, #action, &BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) )

   SET_APP_HANDLER( eosio, eosio, newaccount );
   SET_APP_HANDLER( eosio, eosio, setcode );
   SET_APP_HANDLER( eosio, eosio, setabi );
   SET_APP_HANDLER( eosio, eosio, updateauth );
   SET_APP_HANDLER( eosio, eosio, deleteauth );
   SET_APP_HANDLER( eosio, eosio, linkauth );
   SET_APP_HANDLER( eosio, eosio, unlinkauth );
/*
   SET_APP_HANDLER( eosio, eosio, postrecovery );
   SET_APP_HANDLER( eosio, eosio, passrecovery );
   SET_APP_HANDLER( eosio, eosio, vetorecovery );
*/

   SET_APP_HANDLER( eosio, eosio, canceldelay );

実行時の切り分け

アクションが実行される時は、まず find_apply_handlerで検索し、ネイティブ処理ハンドラーが登録されている場合は、それを実行してから、アカウントにコントラクトがデプロイされていればそのコントラクトのアクションも実行するようになっています。

// libraries/chain/apply_context.cpp の apply_context::exec_one
...
auto native = control.find_apply_handler( receiver, act.account, act.name );
if( native ) {
  ...
  (*native)( *this );
}
if( a.code.size() > 0 ... {
  ...
  try {
      control.get_wasm_interface().apply( a.code_version, a.code, *this );
  } catch( const wasm_exit& ) {}
}

cleos の動き

cleos create accountcleos system newaccountによってパラメータが異なる部分がありますが、結果的にはeosio に対してアクションが送信されることが同じです。

// programs/cleos/main.cpp
create_account_subcommand(CLI::App* actionRoot, bool s) : simple(s) {
  auto createAccount = actionRoot->add_subcommand(
                          (simple ? "account" : "newaccount"),
                          (simple ? localized("Create a new account on the blockchain (assumes system contract does not restrict RAM usage)")
                                  : localized("Create a new account on the blockchain with initial resources") )
  );
  createAccount->add_option("creator", creator, localized("The name of the account creating the new account"))->required();
  createAccount->add_option("name", account_name, localized("The name of the new account"))->required();
  createAccount->add_option("OwnerKey", owner_key_str, localized("The owner public key for the new account"))->required();
  createAccount->add_option("ActiveKey", active_key_str, localized("The active public key for the new account"));

  ...

  createAccount->set_callback([this] {
        ...
        auto create = create_newaccount(creator, account_name, owner_key, active_key);
        if (!simple) {
            ...
            if ( net.get_amount() != 0 || cpu.get_amount() != 0 ) {
              action delegate = create_delegate( creator, account_name, net, cpu, transfer);
              send_actions( { create, buyram, delegate } );
            } else {
              send_actions( { create, buyram } );
            }
        } else {
            send_actions( { create } );
        }
  });
}

まとめ

  • cleos create account を実行すると、アクションが送信され、libraries/chain/eosio_contract.cppapply_eosio_newaccount 関数が実行されてから、eosio.system.cppnative::newaccount アクションが実行される流れになっています
  • ネイティブ実装とコントラクトの実装両方あるので、どう切り分けるべきかの設計は難しいところです
blueplanet
ブロックチェーンエンジニア
https://chainbow.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away