LoginSignup
2
0

More than 5 years have passed since last update.

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

Posted at

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 アクションが実行される流れになっています
  • ネイティブ実装とコントラクトの実装両方あるので、どう切り分けるべきかの設計は難しいところです
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