EOS
の Account
は結局どこで保存しているかを知りたいので、調べてみました。
結論
さきに結論を言いますと
- EOS ネイティブの実装で、
shared_multi_index_container
に下記のマルチインデックステーブルに保持しています- account_object 情報
- account_sequence_object 情報
- permission 情報
アカウント作成処理
アカウント作成するとき newaccount
を実行していますが、
contracts/eosio.system/eosio.system.cpp#native::newaccount
には、リソースの処理しかありません。
libraries/chain/eosio_contract.cpp#apply_eosio_newaccount
に実際のアカウント作成を処理しています。
処理の流れとしては、
- 入力データの検証処理
- account_object データを作成する
- account_sequence_object データを作成する
- permission_object データを作成する(
owner
とactive
2つのレコード)- permission_object のshared_authority は構造体であり、認証用の情報を保持している
データ構成は下記になっています。
account_object
class account_object : public chainbase::object<account_object_type, account_object> {
...
id_type id;
account_name name;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
bool privileged = false;
time_point last_code_update;
digest_type code_version;
block_timestamp_type creation_date;
shared_blob code;
shared_blob abi;
...
using account_index = chainbase::shared_multi_index_container<
account_object,
indexed_by<
ordered_unique<tag<by_id>, member<account_object, account_object::id_type, &account_object::id>>,
ordered_unique<tag<by_name>, member<account_object, account_name, &account_object::name>>
>
>;
...
}
class account_sequence_object : public chainbase::object<account_sequence_object_type, account_sequence_object>
{
OBJECT_CTOR(account_sequence_object);
id_type id;
account_name name;
uint64_t recv_sequence = 0;
uint64_t auth_sequence = 0;
uint64_t code_sequence = 0;
uint64_t abi_sequence = 0;
};
struct by_name;
using account_sequence_index = chainbase::shared_multi_index_container<
account_sequence_object,
indexed_by<
ordered_unique<tag<by_id>, member<account_sequence_object, account_sequence_object::id_type, &account_sequence_object::id>>,
ordered_unique<tag<by_name>, member<account_sequence_object, account_name, &account_sequence_object::name>>
>
>;
permission_object
class permission_object : public chainbase::object<permission_object_type, permission_object> {
...
id_type id;
permission_usage_object::id_type usage_id;
id_type parent; ///< parent permission
account_name owner; ///< the account this permission belongs to
permission_name name; ///< human-readable name for the permission
time_point last_updated; ///< the last time this authority was updated
shared_authority
...
}
using permission_index = chainbase::shared_multi_index_container<
permission_object,
indexed_by<
ordered_unique<tag<by_id>, member<permission_object, permission_object::id_type, &permission_object::id>>,
ordered_unique<tag<by_parent>,
composite_key<permission_object,
member<permission_object, permission_object::id_type, &permission_object::parent>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>,
ordered_unique<tag<by_owner>,
composite_key<permission_object,
member<permission_object, account_name, &permission_object::owner>,
member<permission_object, permission_name, &permission_object::name>
>
>,
ordered_unique<tag<by_name>,
composite_key<permission_object,
member<permission_object, permission_name, &permission_object::name>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>
>
>;
shared_authority
struct shared_authority {
...
uint32_t threshold = 0;
shared_vector<key_weight> keys;
shared_vector<permission_level_weight> accounts;
shared_vector<wait_weight> waits;
...
まとめ
EOS
アカウント周りは、仕組み的には普通のスマートコントラクトと同じくマルチインデックスを使ってますが、実際の処理とアクセス制限いろいろあるので、ネイティブ実装になっていることを分かりました。