【精】EOS智能合约:system系统合约源码分析 (2)

定义在libraries\eosiolib\producer_schedule.hpp。该结构体定义了有效生产者集合的出块顺序、账户名以及签名密钥。

struct producer_schedule { // 时间计划的版本号,按顺序递增。 uint32_t version; // 此计划的生产者列表,包括其签名密钥 std::vector<producer_key> producers; };

陌生的部分是producer_key,该结构体定义在libraries\eosiolib\privileged.hpp,是用来映射生产者及其签名密钥,用于生产者计划。

struct producer_key { name producer_name; // 此生产者使用的区块签名密钥 public_key block_signing_key; // 重载运算符小于号,producer_key的两个对象进行小于号比较时,返回的是其name类型的生产者账户的比较。 friend constexpr bool operator < ( const producer_key& a, const producer_key& b ) { return a.producer_name < b.producer_name; } EOSLIB_SERIALIZE( producer_key, (producer_name)(block_signing_key) ) };

一个问题:name类型是EOS中账户类型,那么它的对象是如何比较的?请转到第二大节。

abihash

native.hpp除了声明以上必要结构体以外,还协助eosio.system合约定义了一个状态表abihash。该状态表只有两个字段,一个是账户名,另一个是hash,该hash是当前账户的abi。在EOS中,一个账户除了通过命令

cleos get account xxxxxxxxxxxx

获得自身属性之外,还可以通过分别通过命令get code和get abi获得该账户部署的合约的abi hash以及code hash,这两个hash是用来校验其部署的智能合约的内容是否发生改变。其中abi hash就是存储在native.hpp定义的状态表中。下面是源码内容:

struct [[eosio::table("abihash"), eosio::contract("eosio.system")]] abi_hash { name owner; capi_checksum256 hash; uint64_t primary_key()const { return owner.value; } // 以账户的值作为该表的主键。 EOSLIB_SERIALIZE( abi_hash, (owner)(hash) ) };

注意:通过[[eosio::table("abihash"), eosio::contract("eosio.system")]]的方式可以为合约定义一个状态表,而不再需要原始的typedef multi_index的方式了。这种方式适用于只有主键的情况,如果有多级索引,仍旧需要multi_index。

native合约类

先展示位于native.hpp文件中的native合约类以及位于eosio.system.hpp文件中的system_contract的区别。

class [[eosio::contract("eosio.system")]] native : public eosio::contract

class [[eosio::contract("eosio.system")]] system_contract : public native

eosio::contract是EOS中所有智能合约的基类,native合约类继承于它,然后system_contract合约类继承于native,而他们二者共同组成了eosio.system智能合约。这种方式让原本单一的智能合约架构变得丰富。作为基类的native,它都声明了eosio.system的哪些属性呢?下面仔细观瞧。

[[eosio::action]] newaccount

我们常用的system newaccount功能就是在native中声明的。该action在创建新帐户后调用,此代码强制实施新帐户的资源限制规则以及新帐户命名约定。规则包含两个:

帐户不能包含'.' 强制所有帐户的符号长度为12个字符而没有“.” 直到实施未来的帐户拍卖流程。

新帐户必须包含最少数量的token(如系统参数中所设置),因此,此方法将为新用户执行内联buyram购买内存,其金额等于当前新帐户的创建费用。

[[eosio::action]] void newaccount( name creator, name name, ignore<authority> owner, ignore<authority> active);

陌生的部分是ignore,该结构位于libraries\eosiolib\ignore.hpp。

ignore

告诉数据流忽略此类型,但允许abi生成器添加正确的类型。当前非忽略类型不能在方法定义中成功忽略类型,即允许

void foo(float,ignore

但不允许

void foo(float,ignore

因为int已经被声明为忽略类型,所以后面不能再作为非忽略类型出现了。ignore结构体源码如下:

template <typename T> struct [[eosio::ignore]] ignore {}; 其他[[eosio::action]] 动作 返回值 参数 解释
updateauth   void   ignore   更新账户的某项权限内容  
deleteauth   void   ignore   删除账户的某项权限内容  
linkauth   void   ignore   连接其他账户  
unlinkauth   void   ignore   解除某账户的连接  
canceldelay   void   ignore<permission_level> canceling_auth
ignore<capi_checksum256> trx_id
  取消某个延迟交易  
onerror   void   ignore<uint128_t> sender_id
ignore<std::vector
  处理错误  
setabi   void   name account
const std::vector
  设置账户的abi内容  
setcode   void   name account
uint8_t vmtype
uint8_t vmversion
const std::vector
  设置账户的code内容  
二、name.hpp

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsspgz.html