第一種:建立系統帳號eosio的方式。app
直接調用create_native_account 方法直接進行建立。並將資源設置成無限。less
void create_native_account( account_name name, const authority& owner, const authority& active, bool is_privileged = false ) { //create account 直接建立帳號,不會作任何資源判斷,由於建立的是系統帳號 db.create<account_object>([&](auto& a) { a.name = name; a.creation_date = conf.genesis.initial_timestamp; a.privileged = is_privileged; if( name == config::system_account_name ) { a.set_abi(eosio_contract_abi(abi_def())); } }); db.create<account_sequence_object>([&](auto & a) { a.name = name; }); const auto& owner_permission = authorization.create_permission(name, config::owner_name, 0, owner, conf.genesis.initial_timestamp ); const auto& active_permission = authorization.create_permission(name, config::active_name, owner_permission.id, active, conf.genesis.initial_timestamp ); //初始化帳號資源,可是初始化賦值只賦了resource_limits_object的owner值,其餘cpu,ram,net等資源默認是-1,也就是unlimit。 resource_limits.initialize_account(name); int64_t ram_delta = config::overhead_per_account_ram_bytes; ram_delta += 2*config::billable_size_v<permission_object>; ram_delta += owner_permission.auth.get_billable_size(); ram_delta += active_permission.auth.get_billable_size(); resource_limits.add_pending_ram_usage(name, ram_delta); resource_limits.verify_account_ram_usage(name); } void resource_limits_manager::initialize_account(const account_name& account) { _db.create<resource_limits_object>([&]( resource_limits_object& bl ) { bl.owner = account; }); _db.create<resource_usage_object>([&]( resource_usage_object& bu ) { bu.owner = account; }); } /** * Every account that authorizes a transaction is billed for the full size of that transaction. This object * tracks the average usage of that account. */ struct resource_limits_object : public chainbase::object<resource_limits_object_type, resource_limits_object> { OBJECT_CTOR(resource_limits_object) id_type id; account_name owner; bool pending = false; int64_t net_weight = -1; int64_t cpu_weight = -1; int64_t ram_bytes = -1; };
第二種:cleos create account 方式建立帳號,調用的是eosio的默認合約,但該方式在eosio 部署了eosio.system後不可用。 由於默認合約被替換掉。eosio的默認合約是來自源碼提早定義好的。ui
具體的abi信息在:libraries/chain/eosio_contract_abi.cpp,libraries/chain/eosio_contract.cpp。this
跟第一種同樣,一樣是將資源的使用權設置爲無限。 下一次再介紹eosio默認合約的造成原理,以及調用流程。code
/** * This method is called assuming precondition_system_newaccount succeeds a */ void apply_eosio_newaccount(apply_context& context) { auto create = context.act.data_as<newaccount>(); try { context.require_authorization(create.creator); // context.require_write_lock( config::eosio_auth_scope ); auto& authorization = context.control.get_mutable_authorization_manager(); //判斷公鑰是否合法。 EOS_ASSERT( validate(create.owner), action_validate_exception, "Invalid owner authority"); EOS_ASSERT( validate(create.active), action_validate_exception, "Invalid active authority"); auto& db = context.db; auto name_str = name(create.name).to_string(); //判斷account name的合法性 EOS_ASSERT( !create.name.empty(), action_validate_exception, "account name cannot be empty" ); EOS_ASSERT( name_str.size() <= 12, action_validate_exception, "account names can only be 12 chars long" ); // Check if the creator is privileged //只有eosio才能建立eosio.爲前綴的帳號。 const auto &creator = db.get<account_object, by_name>(create.creator); if( !creator.privileged ) { EOS_ASSERT( name_str.find( "eosio." ) != 0, action_validate_exception, "only privileged accounts can have names that start with 'eosio.'" ); } //判斷用戶名是否存在。 auto existing_account = db.find<account_object, by_name>(create.name); EOS_ASSERT(existing_account == nullptr, account_name_exists_exception, "Cannot create account named ${name}, as that name is already taken", ("name", create.name)); const auto& new_account = db.create<account_object>([&](auto& a) { a.name = create.name; a.creation_date = context.control.pending_block_time(); }); db.create<account_sequence_object>([&](auto& a) { a.name = create.name; }); for( const auto& auth : { create.owner, create.active } ){ validate_authority_precondition( context, auth ); } const auto& owner_permission = authorization.create_permission( create.name, config::owner_name, 0, std::move(create.owner) ); const auto& active_permission = authorization.create_permission( create.name, config::active_name, owner_permission.id, std::move(create.active) ); context.control.get_mutable_resource_limits_manager().initialize_account(create.name); int64_t ram_delta = config::overhead_per_account_ram_bytes; ram_delta += 2*config::billable_size_v<permission_object>; ram_delta += owner_permission.auth.get_billable_size(); ram_delta += active_permission.auth.get_billable_size(); context.trx_context.add_ram_usage(create.name, ram_delta); } FC_CAPTURE_AND_RETHROW( (create) ) }
跟第一種同樣,一樣是將資源的使用權設置爲無限。 下一次再介紹當沒有部署eosio.system合約時,eosio默認合約的造成原理。資源
第三種:當部署eosio.system合約時,建立帳號都必須使用該合約的newaccount的action。 值得一提的是用第三種方式建立時,第二種方式的apply_eosio_newaccount也會執行。部署
void native::newaccount( account_name creator, account_name newact /* no need to parse authorities const authority& owner, const authority& active*/ ) { //當creator 不是eosio時,須要判斷建立者的資源以及低於12個字符的名字是否經過拍賣。 if( creator != _self ) { auto tmp = newact >> 4; bool has_dot = false; for( uint32_t i = 0; i < 12; ++i ) { has_dot |= !(tmp & 0x1f); tmp >>= 5; } if( has_dot ) { // or is less than 12 characters auto suffix = eosio::name_suffix(newact); if( suffix == newact ) { name_bid_table bids(_self,_self); auto current = bids.find( newact ); eosio_assert( current != bids.end(), "no active bid for name" ); eosio_assert( current->high_bidder == creator, "only highest bidder can claim" ); eosio_assert( current->high_bid < 0, "auction for name is not closed yet" ); bids.erase( current ); } else { eosio_assert( creator == suffix, "only suffix may create this account" ); } } } user_resources_table userres( _self, newact); userres.emplace( newact, [&]( auto& res ) { res.owner = newact; }); //將帳號資源初始化爲0,不購買資源沒法進行相關動做 set_resource_limits( newact, 0, 0, 0 ); }