写在前面
system合约是EOS区块链最核心的智能合约,分析其源码可以一窥EOS的精妙之处。
文件结构
native 基础的数据结构和功能
delegate_bandwidth 带宽抵押与内存买卖
exchange_state 内存市场数据结构与bancor算法
eosio.system 关键数据结构
producer_pay和voting DPOS相关
接口
// *** native.hpp ***
newaccount
updateauth
deleteauth
linkauth
unlinkauth
canceldelay
onerror
// 更新区块链参数到链上
// require_auth(eosio)
void setparams(const blockchain_parameters& params);
// 设置用户特权级
// ispriv为bool值
void setpriv(account_name account, uint8_t ispriv);
数据结构
/* 区块链全局状态 */
struct eosio_global_state : public blockchain_parameters
{
uint64_t max_ram_size = 64 * 1024 * 1024 * 1024; // 64GB
uint64_t total_ram_bytes_reserved;
int64_t total_ram_stake;
block_timestamp last_porducer_schedule_update;
uint64_t last_pervote_bucket_fill;
int64_t pervote_bucket;
int64_t perblock_bucket;
uint32_t total_unpaid_blocks;
int64_t total_activated_stake_time;
uint64_t thresh_activated_stake_time;
uint16_t last_producer_schedule_size;
double total_producer_vote_weight;
block_timestamp last_name_close;
}
// 区块链参数
struct blockchain_parameters
{
uint64_t max_block_net_usage;
uint32_t target_block_net_usage_pct;
uint32_t max_transaction_net_usage;
uint32_t base_per_transaction_net_usage;
uint32_t net_usage_leeway;
uint32_t context_free_discount_net_usage_num;
uint32_t context_free_discount_net_usage_den;
uint32_t max_block_cpu_usage;
uint32_t target_block_cpu_usage_pct;
uint32_t max_transaction_cpu_usage;
uint32_t min_transaction_cpu_usage;
uint64_t context_free_discount_cpu_usage_num;
uint64_t context_free_discount_cpu_usage_den;
uint32_t max_transaction_lifetime;
uint32_t deferred_trx_expiration_window;
uint32_t max_transaction_delay;
uint32_t max_inline_action_size;
uint16_t max_inline_action_depth;
uint16_t max_authority_depth;
};
核心算法
SYSTEM合约的构造与析构
有一定EOS智能合约开发经验的朋友可以知道,在每次调用合约对外接口时,智能合约对应的类的构造函数和析构函数都是会被调用一遍的,如此使得合约类的构造析构函数会发挥特殊的作用。
构造
1.获取当前区块链参数
2.开启内存市场
析构
更新区块链参数
单例singleton
system合约类定义了两个特殊的成员变量,_gstate和_global。
_global为eosio::singleton<N(global), eosio_global_state>类型,_gstate为eosio_global_state类型。
这里涉及到eos内置的singleton,通过观察其定义,可以知道是通过eosio::multi_index存储实例的模板类单例。
eosio::singleton的用法通常会与EOS合约的构造析构函数结合起来,一个是singleton,一个是临时变量。在构造函数中,把singleton的值传到临时变量,其他接口都是通过操作临时变量来完成实现,最后在析构函数中把最新的值更新到singleton中。
带宽抵押
// N(userres) user_resources_table
user_resources {
account_name owner // primary key
asset net_weight
asset cpu_weight
int64_t ram_bytes
}
// N(delband) del_bandwidth_table
delegated_bandwidth {
account_name from
account_name to // primary key
asset net_weight
asset cpu_weight
}
// N(refunds) refunds_request
refund_request {
account_name owner // primary key
time request_time
asset net_amount
asset cpu_amount
}
+ void delegatebw(account_name from,
account_name receiver,
asset stake_net_quantity,
asset stake_cpu_quantity,
bool transfer);