eosio.system合约分析部署合约:

eos有个核心理念,EOS代币的所有者给予用户按比例的网络带宽、存储空间、运算能力。好处是用户拥有1%的EOS代币,无论网络其余部分的负载如何,他将始终可以访问1%的网络带宽。恶意攻击者只能消耗根据其EOS代币占比拥有的相应比例的网络资源。不会影响整个eos网络。

本文目的是分析eos这一核心理念是如何实现的?

根据eos官网找到了代码实现的范围 https://github.com/EOSIO/eos/tree/master/contracts/eosio.system

eosio.system是EOS的智能合约,eos三个核心功能: 1,用户抵押token,可以投票给区块生成者(block producer),就是目前竞争火热的21个超级节点,还有获得社区提案(worker proposal)的权利。 2,设置代理,把投票权移交给其他用户。 3,抵押token,获得相应的网络带宽,存储空间,运算能力。

部署合约:

首先需要创建个钱包,才可以做其它操作

创建默认钱包
./cleos wallet create
设置基础配置智能合约:eosio.bios
./cleos set contract eosio ../../contracts/eosio.bios -p eosio -j
设置系统智能合约:eosio.system 部署了该智能合约
cleos set contract eosio ../../contracts/eosio.system -p eosio

然后才可以有账户发行EOS token,才可以执行,注册producer,投票者下注,投票等操作。

创建eos token
./cleos push action eosio issue '{"to":"eosio","quantity":"1000000000.0000 EOS"}' --permission eosio@active -j
创建账户 bp.a
./cleos create account eosio bp.a EOS8dtXWZQWqSv4mk3WPrpMKGywA5pBY1MWxbpSGSLVvV4k98kvxs EOS7fhfs1j5BBQC9bsM5c8c2WZy6NPG6mbAGMuuYJCnKNHfb3vrND
vo.a 押token
./cleos push action eosio delegatebw '{"from":"vo.a","receiver":"vo.a","stake_net":"100.0000 EOS","stake_cpu":"100.0000 EOS","stake_storage":"0.0000 EOS"}' --permission vo.a@active
vo.a给 bp.a 投票
./cleos push action eosio voteproducer '{"voter":"vo.a","proxy":"","producers":["bp.a"]}' --permission vo.a@active

eosio.system合约源码

1,eosio.system合约的主要代码在eosio.system.hpp、eosio.system.cpp两个文件中; 2,eosio.system合约有很多Action,eosio.system.cpp中的EOSIO_ABI宏定义如下:

EOSIO_ABI( eosiosystem::system_contract,
 (setram)
 // delegate_bandwith.cpp
 (delegatebw)(undelegatebw)(refund)
 (buyram)(buyrambytes)(sellram)
 // voting.cpp
 // producer_pay.cpp
 (regproxy)(regproducer)(unregprod)(voteproducer)
 (claimrewards)
 // native.hpp
 (onblock)
 (newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(postrecovery)(passrecovery)(vetorecovery)(onerror)(canceldelay)
)

3,可以看到,具体的Action实现代码分散到了delegate_bandwith.cpp、voting.cpp、producer_pay.cpp、native.cpp中,下面会进行分析。

4、eosio.system.hpp中定义了合约类eosiosystem::system_contract,和一些结构体:

eosio_global_state(全局状态) producer_info(生产者信息) voter_info(投票人信息)

5,system_contract类继承自native.hpp中定义的eosiosystem::native类,native类又继承自eosio::contract基类;

6,system_contract类中定义了system合约的Action,

以下Action在producer_pay.cpp中实现:

计算生产者节点收益的相关代码:

//计算一些遗漏的区块,更新指定生产者的区块信息
void onblock( uint32_t timestamp_slot, account_name producer );

//(生产者)获取回报
void claimrewards( const account_name& owner );



//计算根据生产者生产的区块数量,计算每个块的收益    
eosio::asset system_contract::payment_per_block( double rate, const eosio::asset& token_supply,  uint32_t num_blocks ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(num_blocks)) / double(blocks_per_year) );
return eosio::asset( payment, token_supply.symbol );
}

//计算根据生产者的生产时间,计算每秒收益    
eosio::asset system_contract::supply_growth( double rate, const eosio::asset& token_supply, time seconds ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(seconds)) / double(seconds_per_year) );
return eosio::asset( payment, token_supply.symbol );
}

//计算生产者从每次投票中获得的收益(代码部分省略)
eosio::asset system_contract::payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& pervote_bucket ) {
eosio::asset payment(0, S(4,EOS));
//如果每日收益少于100EOS,则没有收益
const int64_t min_daily_amount = 100 * 10000;
if ( pervote_bucket.amount < min_daily_amount ) {
     return payment;
}
//省略...
return payment;
}

以下Action在delegate_bandwidth.cpp中实现:

  //抵押token,获取网络和CPU资源
  //from是抵押者,receiver是token接收者
  //transfer如果设置为true,接收者可以取消抵押,否则抵押者可以随时取消抵押
    void delegatebw(account_name from, 
            account_name receiver,
            asset stake_net_quantity, 
            asset stake_cpu_quantity, 
            bool transfer);

//取消抵押,释放网络和CPU资源
//from取消抵押后,会失去投票权
void undelegatebw(  account_name from, 
                account_name receiver,
                asset unstake_net_quantity, 
                asset unstake_cpu_quantity );

//购买指定价值内存,buyer是购买者,receiver是内存接收者
void buyram( account_name buyer, account_name receiver, asset tokens );

//购买指定大小的内存,支付的EOS会以当前市场价格计算
void buyrambytes( account_name buyer, account_name receiver, uint32_t bytes   );

//出售内存
void sellram( account_name receiver, uint64_t bytes );

//取回token,有3天等待期
void refund( account_name owner );

实现的主要是和资源分配有关的Action:

//抵押token,获取网络和CPU资源
//from是抵押者,receiver是token接收者
//transfer如果设置为true,接收者可以取消抵押,否则抵押者可以随时取消抵押
void delegatebw(account_name from, 
            account_name receiver,
            asset stake_net_quantity, 
            asset stake_cpu_quantity, 
            bool transfer);

//取消抵押,释放网络和CPU资源
//from取消抵押后,会失去投票权
void undelegatebw(  account_name from, 
                account_name receiver,
                asset unstake_net_quantity, 
                asset unstake_cpu_quantity );

//购买指定价值内存,buyer是购买者,receiver是内存接收者
void buyram( account_name buyer, account_name receiver, asset tokens );

//购买指定大小的内存,支付的EOS会以当前市场价格计算
void buyrambytes( account_name buyer, account_name receiver, uint32_t bytes );

//出售内存
void sellram( account_name receiver, uint64_t bytes );

//取回token,有3天等待期
void refund( account_name owner );

以下Action在voting.cpp中实现

//注册生产者,会为生产者创建或更新producer_info对象
  void regproducer( const account_name producer, const public_key& producer_key, const std::string& url );

//取消注册
  void unregprod( const account_name producer );

//投票,可以投给多个生产者
void voteproducer( const account_name voter, const account_name proxy, const std::vector<account_name>& producers );

//注册成为投票代理
//已经使用了代理的投票者,不能注册为投票代理
void regproxy( const account_name proxy, bool isproxy );

voting.cpp中包含了投票相关的Action,比较重要的有:

//根据投票数由高到低,选出21个区块生产者,并更新数据
void system_contract::update_elected_producers( block_timestamp block_time ) {
//...    
}

//用户投票选出生产者
//参数voter_name表示投票人,proxy表示该账户的代理人
//参数producers是一个生产者数组
void system_contract::voteproducer( const account_name voter_name, const account_name proxy, const std::vector<account_name>& producers ) {

//如果已有代理人,表示该账户已经把投票权委托出去了,就不能再投票
if ( proxy ) {
    eosio_assert( producers.size() == 0, "cannot vote for producers and proxy at same time" );
    //不能委托给自己
    eosio_assert( voter_name != proxy, "cannot proxy to self" );
    require_recipient( proxy );
} else {
    //一次不能投超过30个生产者
    eosio_assert( producers.size() <= 30, "attempt to vote for too many producers" );
    //检测账户投的生产者列表中的节点是否是唯一且排好序的
    for( size_t i = 1; i < producers.size(); ++i ) {
        eosio_assert( producers[i-1] < producers[i], "producer votes must be unique and sorted" );
    }
}

auto voter = _voters.find(voter_name);
//需要抵押token才能投票
eosio_assert( voter != _voters.end(), "user must stake before they can vote" ); 
//已注册为代理人的账户,不能再委托别人进行投票
eosio_assert( !proxy || !voter->is_proxy, "account registered as a proxy is not allowed to use a proxy" );

//省略...
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

FacexWorm通过Facebook Messenger和Chrome扩展传播

Facebook和Chrome用户要注意了,最近有一款名叫FacexWorm的病毒,可以窃取密码,窃取加密货币,或者向Facebook用户发送垃圾邮件。

862
来自专栏区块链大本营

Vitalik Buterin:Casper 权益证明与分片技术最新进展

1696
来自专栏FreeBuf

加密钱包再爆严重漏洞,看我怎么“榨干”你的钱包

SaleemRashid 是一名来自英国的十五岁少年,而这位年少有为的同学成功地在Ledger公司所生产的加密货币硬件钱包Ledger Nano S中发现了一个...

1274
来自专栏申龙斌的程序人生

体验小矿工:门罗币挖矿指南

国家在2017年9月全面禁止了ICO,但比特币挖矿仍是合法的。挖矿行业涉及到场地、矿机、电力等诸多因素,前期投入比较大,现在基本上都是专业机构在参与。如果你想体...

8779
来自专栏华仔的技术笔记

什么是Photon?

Photon就是以前SmartMesh生态的SmartRaiden,Photon network是Spectrum的链下扩展解决方案,能够实现即时、低费用和可扩...

1191
来自专栏区块链大本营

如何摧毁黑客梦想, 提升EOS游戏体验? 本营小仙女: 比他们更努力!

对于制造伪 EOS 以次充好,其实只需要检查发行方是否为 eosio,或者调用相关合约查看代币信息,但是检查代币操作依然不够严谨的情况下又会产生更多的变体漏洞,...

1221
来自专栏FreeBuf

去中心化应用安全威胁Top10榜单

NCC Group 发起了一个名为 2018 年去中心化应用安全 Top10(Decentralized Application Security Projec...

1102
来自专栏Netkiller

以太坊·代币开发详解

本文节选自《Netkiller Blockchain 手札》

62811
来自专栏区块链大本营

【技术贴】从拜占庭问题,谈区块链技术实现及政务应用

39510
来自专栏区块链入门

第1课 EOS开发从入门到精通学习导航

1)EOS.io 2)EOS Blog 3)BlockONE 4)Reddit

1444

扫码关注云+社区