What is an EOSIO account
The account is the basis for accessing EOSIO, which is equivalent to the user name account in the general system. Its account is established according to the following rules
static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";
The EOSIO account is a string that can be freely combined in strict accordance with the above letters, the maximum length is 13, and the two ends cannot be "." characters. There are several
default accounts in EOSIO, which are used by the system.
const static name system_account_name {
"eosio"_n };
const static name null_account_name {
"eosio.null"_n };
const static name producers_account_name {
"eosio.prods"_n };
Notice:
- Among them, eosio is a system super account, which is equivalent to an administrator. It is created on the founding node with the node startup. The public and private keys used for creation are also the public and private keys of the founding node.
- For accounts created starting with eosio., the creator must be eosio, which is a private rule reserved by the system
- The specific implementation logic can be seen in the name class
The role of ESOIO account
After understanding what is an EOSIO account, what role does it play in the entire system? Looking at the various functions of the entire system, the account can be summed up as follows:
- Authentication of transaction authority
- Authorization authentication of internal chain Action
- Smart contract, the carrier of ABI
- producer name
Data structure of account permissions
// 最基础的账户表,记录账户名,创建时间,还有ABI数据块
class account_object : public chainbase::object<account_object_type, account_object> {
OBJECT_CTOR(account_object,(abi))
id_type id;
account_name name; //< name should not be changed within a chainbase modifier lambda
block_timestamp_type creation_date;
shared_blob abi;
};
// 账户元数据表,记录关于账号易变信息,或者一些统计信息
class account_metadata_object : public chainbase::object<account_metadata_object_type, account_metadata_object>
{
OBJECT_CTOR(account_metadata_object);
enum class flags_fields : uint32_t {
privileged = 1
};
id_type id;
account_name name; //< name should not be changed within a chainbase modifier lambda
uint64_t recv_sequence = 0;
uint64_t auth_sequence = 0;
uint64_t code_sequence = 0;
uint64_t abi_sequence = 0;
digest_type code_hash;
time_point last_code_update;
uint32_t flags = 0;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
};
// 合约数据表,保存用户的部署的合约
class code_object : public chainbase::object<code_object_type, code_object> {
OBJECT_CTOR(code_object, (code))
id_type id;
digest_type code_hash; //< code_hash should not be changed within a chainbase modifier lambda
shared_blob code;
uint64_t code_ref_count;
uint32_t first_block_used;
uint8_t vm_type = 0; //< vm_type should not be changed within a chainbase modifier lambda
uint8_t vm_version = 0; //< vm_version should not be changed within a chainbase modifier lambda
};
// 权限基础表
class permission_object : public chainbase::object<permission_object_type, permission_object> {
OBJECT_CTOR(permission_object, (auth) )
id_type id;
permission_usage_object::id_type usage_id;
id_type parent; ///< parent permission
account_name owner; ///< the account this permission belongs to (should not be changed within a chainbase modifier lambda)
permission_name name; ///< human-readable name for the permission (should not be changed within a chainbase modifier lambda)
time_point last_updated; ///< the last time this authority was updated
shared_authority auth; ///< authority required to execute this permission
};
// 权限链接表,记录和action进行绑定关系
class permission_link_object : public chainbase::object<permission_link_object_type, permission_link_object> {
OBJECT_CTOR(permission_link_object)
id_type id;
/// The account which is defining its permission requirements
account_name account;
/// The contract which account requires @ref required_permission to invoke
account_name code; /// TODO: rename to scope
/// The message type which account requires @ref required_permission to invoke
/// May be empty; if so, it sets a default @ref required_permission for all messages to @ref code
action_name message_type;
/// The permission level which @ref account requires for the specified message types
/// all of the above fields should not be changed within a chainbase modifier lambda
permission_name required_permission;
};
/****************************************************************************
在EOSIO中,账户的权限是作为整个数据块进行存储的
在authority结构中,主要记录了一下核心数据
threshold:阈值,所有权限之权重值之和, 最后的比较值
keys:记录公钥与权重数值
accounts:记录管理账户与权重值,新创建的账户一般没有这个数值
waits:延迟执行相关权限
****************************************************************************/
struct permission_level {
account_name actor;
permission_name permission;
};
struct permission_level_weight {
permission_level permission;
weight_type weight;
};
struct key_weight {
public_key_type key;
weight_type weight;
};
struct authority {
authority( public_key_type k, uint32_t delay_sec = 0 )
:threshold(1),keys({
{
k,1}})
{
if( delay_sec > 0 ) {
threshold = 2;
waits.push_back(wait_weight{
delay_sec, 1});
}
}
authority( permission_level p, uint32_t delay_sec = 0 )
:threshold(1),accounts({
{
p,1}})
{
if( delay_sec > 0 ) {
threshold = 2;
waits.push_back(wait_weight{
delay_sec, 1});
}
}
authority( uint32_t t, vector<key_weight> k, vector<permission_level_weight> p = {
}, vector<wait_weight> w = {
} )
:threshold(t),keys(move(k)),accounts(move(p)),waits(move(w)){
}
authority(){
}
uint32_t threshold = 0;
vector<key_weight> keys;
vector<permission_level_weight> accounts;
vector<wait_weight> waits;
};
From the above code structure, the following conclusions can be drawn directly
- The account table value records the core account name
- Accounts and permissions are deeply bound, and the entire permission data is stored as an overall data block
- The same permission can correspond to multiple key_weight, permission_level_weight, wait_weight, which can make the permission more flexible and expandable
- The authority directly acts on a single account, and the control is more detailed
- The authority data block exists together, and the access is fast, but at the same time it also brings troubles in operation and inconvenient query
- code and abi are stored separately, because the query frequency of abi is much higher than that of code, which will be described in detail later
Operation of account authority
In EOSIO, the operation of account permissions is done in the system contract eosio_contract. The eosio_contract contract is built-in and deployed on the eosio account. It is the most basic and important contract in eosio. It is directly compiled and deployed in the node and cannot be updated.
The action list of eosio_contract is as follows
-
newaccount: Create an account. When creating an account, the owner and active permissions are created by default.
The parameters attached to the action are as follows:struct newaccount { account_name creator; account_name name; authority owner; authority active; };
-
updateauth: authorization update
struct updateauth { account_name account; permission_name permission; permission_name parent; authority auth; };
-
deleteauth: delete account permissions
struct deleteauth { account_name account; permission_name permission; };
-
linkauth: Binding of permissions and contract actions
struct linkauth { account_name account; account_name code; action_name type; permission_name requirement; };
-
unlinkauth: Contact the binding relationship between the contract and the action
struct unlinkauth { account_name account; account_name code; action_name type; };
-
setcode: deploy contract
struct setcode { account_name account; uint8_t vmtype = 0; uint8_t vmversion = 0; bytes code; };
-
setabi: Department ABI
struct setabi { account_name account; bytes abi; };
-
canceldelay: cancel delay
struct canceldelay { permission_level canceling_auth; transaction_id_type trx_id; };
About the command line of the permission account in cleos
We said earlier that the interfaces provided by eosio for external access are all http interfaces, and cleos is just an encapsulation of these interfaces. Generally, in our projects, http interfaces are directly used, but in the initial stage of system deployment, we still inevitably meet Use the cleos command line, of course, you develop a command line yourself. In addition, in the author's project, we have developed a java version of the command line tool, as well as a wallet. This is mainly for background and Android use, which is very convenient. .
For specific command usage rules, you can refer to here, EOSIO Command Line Encyclopedia
Summarize
Relatively speaking, in EOSIO, the code about permissions is relatively unified and centralized, and its functions are relatively independent. It can encapsulate independent modules, or create an independent service that is only responsible for CA-related business logic.
However, at the same time, we also observed that in the public chain, the design of permissions is very different from the permissions in general systems. Then we will ask
- What are the benefits of such designed permissions? Is it easy to operate and access? If not, what aspects can be optimized?
- In the permission data structure, what is the relationship between account and key? Is it a one-to-one relationship?
- In the transaction, how is the authority identified, and how is it identified in the contract by extension?
- We observed that the definition of permission-related tables inherits chainbase::object, and how is it stored?
postscript
The account authority is a relatively independent but difficult to understand functional module in EOSIO, especially some concepts it introduces, such as threshold, weight, multi-signature, link binding, and code authority must be kept in mind before it can Understand the process and principle of its authority verification.
Therefore, by understanding the relevant data structure of account permissions, we can better understand its authentication process.