本文详细介绍了eosio.system智能合约中的选举、投票、系统设置,适用于EOS智能合约的初级开发者,了解如何进行选举、投票以及系统设置。
01
概述
“eosio.system”智能合约是eos的系统命令合约。这个合约几乎实现了eos全部的系统命令,包括创建账户、资源质押、超级节点投票、域名竞拍等功能,它定义了区块链核心功能所需的结构和操作。
下文将介绍eosio.system是如何实现选举、投票以及系统设置的。
02
环境准备
(一)一条正在运行且可访问的区块链
中移链(基于EOS)测试环境搭建:
https://mp.weixin.qq.com/s/NBNFk9Xk9FCukMVgl0tfHA
(二)确保本地钱包已打开并解锁
如何创建钱包:
https://developers.eos.io/manuals/eos/latest/cleos/how-to-guides/how-to-create-a-wallet
(三)已完成eosio.contracts的构建和部署
如何构建eosio.contracts:
https://developers.eos.io/manuals/eosio.contracts/latest/build-and-deploy
(四)已完成token的创建、发行和转移
如何创建、发行和转移token:
https://developers.eos.io/manuals/eosio.contracts/latest/guides/how-to-create-issue-and-transfer-a-token
03
选举
(一)节点的注册、取消
eos的超级节点选举是围绕账户进行的。账户注册为超级节点候选账户,其他账户才可以为其投票。
注册为超级节点候选账户,需要提供公钥,此公钥用于当选超级节点后,产块时验证签名。
命令基础结构:
注册节点示例:
取消节点:
取消节点后,其他账号不能再为其投票,但是之前投的票会被保留,下次创建节点仍会出现。
04
投票
(一)投票流程
1、注册节点
运行以下指令注册节点(详见前文):
2、抵押与取消抵押
抵押:
抵押给自己:
抵押成功返回值
抵押前转给ost 1000.0000 SYS token,查看抵押后的账户:
查看抵押信息:
抵押给别人:
查看抵押信息:
查询ost的balance为:890.0000 SYS
取消抵押:
取消抵押命令基础结构如下:
此时再次查看ost的balance,显示仍为890.0000 SYS,没有将取消抵押的返回,原因是取消抵押有3天延迟,3天后再查看即可得到正常反馈。
3、投票与取消投票
投票前准备:
创建节点:
抵押:
ost→ost 5.0000 SYS,ost→imtube 5.0000 SYS
imtube→imtube
查看imtube抵押信息:
imtube→bob
节点给其他节点投票
投票成功返回值:
executed transaction: e21875311a7445bb9714b83fde2442a09839c246868e80cd5eef58212f83c8d5 120 bytes 300 us
# eosio <= eosio::voteproducer {"voter":"imtube","proxy":"","producers":["ost"]}
warning: transaction executed locally, but may not be confirmed by the network yet ]
获取投票者信息:
查看imtube抵押信息:
节点给自己投票
投票成功返回值:
账号给节点投票:
bob抵押:
bob给ost投票:
投票数量计算公式:votingNum=(stake_net_quantity+stake_cpu_quantity)*10000;
投票给多个节点
将alice设置为节点
cleos system voteproducer prods为直接给超级节点投票的命令,可以指定投票账户,可以一次性投给多个超级节点候选账户,账户名需要按字母从小到大排序,最多不超过30个账户。
4、 投票失败
以下情况会导致投票失败:
未创建的节点;
创建后又取消的节点;
一次投30个以上的节点,只有前30可以成功;
多个节点投票,没有按顺序;
5、 节点奖励
如需发放节点奖励,必须保证per_block_payments大于0;
否则会导致报错
出块奖励只向21个超级节点发放,其中涉及到一个出块奖励池的概念,由于每个节点领取时都会增发部分EOS,所以所有未领取的出块奖励都会放在出块奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的出块奖励数量计算公式如下:单个节点可领取的数量=出块奖励池里的EOS数量*该BP未领取奖励的出块数量/所有未领取奖励的区块数量
得票率奖励向超级节点和备用节点发放,同出块奖励相似,所有未领取的得票率奖励都会放在得票奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的得票率奖励数量计算公式如下:单个节点可领取的数量=得票率奖励池里的EOS数量*该BP的得票权重/所有BP的总得票权重
领取(claim)条件节点领取奖励需满足三个条件:超级节点和备用节点才可领取;同一节点两次claim间隔时间不能少于24小时;备用节点无出块奖励,只有得票率奖励且需要在100个EOS以上,否则不算备用节点,无法领取奖励。
(二)代理投票流程
1、注册节点
2 、建立代理与取消代理
建立代理:
代理成功返回值:
取消代理:
取消代理成功返回值:
3、代理投票
建立代理:
抵押:
委托代理:
委托成功返回值:
代理投票:
通过代理进行投票,即先投票给代理,再由代理投票给生产者。
代理的作用就是替别人做出选择投票,本身不需要抵押。
在投票的时候,要先抵押,投票有两种选择,只能选择一种,两种不能同时存在。
若选择自己投票,则直接操作;若选择代理投票,则将票抵押给代理,由代理选择要投票的节点。
已经作为代理的账号,不能再设置代理投票。
05
系统设置
(一)setalimits设置账号资源限制
源码:
参数详解:
cpu_weight:账户CPU总抵押权重;与net_weight同理。
setalimits()方法调用set_resource_limits函数用来对一个用户的ram,net,cpu资源最大使用进行设置,该函数主要是在eosio.system系统合约中买卖内存,只允许合约账户本身调用,只能为已在用户资源表中的账户进行资源限制设置。
资源介绍:
EOS的资源可以分为两类:
一类是可以借给别人使用的资源:CPU,NET,有称为可转让资源;
另一类是只能够自己使用,无法借出给他人的资源:RAM,又称为不可转让资源。
注:CPU和NET在使用后可以恢复,而RAM则不同,RAM是固定资源,用完了需要重新购买。
为什么要使用setalimits()设置账号资源限制 ?
1. EOS网络中的资源总是有限的,而交易处理又是资源敏感的,因此,为避免资源滥用,保障网络的正常运行,必须对资源使用权限作出限制和管理。
2. 资源使用中需要实现一些基础的数据限制,如单笔交易最大CPU限制150ms、单个区块最大带宽限制1M等,通过写死的源码常量、或者set接口调用、或者每次交易时传参来确定;
(二)setacctram设置内存限制
源码:
参数详解:
由于RAM资源有限,在具体实现时,需要设置RAM资源限制:单个账户限制、单笔交易限制和单个区块限制三部分,此处setacctram()方法设置单个账户限制,该方法只允许合约账户本身调用。
为什么要设置RAM限制?
RAM对开发者来说十分宝贵,因为开发DApp需要占用RAM空间。此外EOS中没有地址的概念,用户如果想使用EOS,必须在EOS上创建一个账户。创建EOS账户需要消耗内存,即RAM。RAM被用来进行一些特殊的EOS链上的操作,比如:生成新的账户、竞价EOS账户名拍卖等。数据库记录需要消耗RAM,RAM是一项宝贵的资源。所以需要设置账户使用ram的大小。
(三)setram设置提供的内存大小
源码:
参数详解:
max_ram_size初始默认为64G,setram()方法实现了对RAM的一次性扩容,该方法只允许合约账户本身调用。
应用场景:
某个基于EOS开发的链,提供了免费的账户注册接口,执行调用后,账户免费为其抵押CPU、NET和购买RAM。由于接口没有做严格有效的防刷处理,导致账户注册严重超过预期,导致链内系统资源浪费严重,以及空投部分系统代币占用过多。
解决方法:
通过setram()方法一次性扩增RAM容量
通过setramrate()方法设置为每块持续新增。
(四)setramrate设置每个块内存增长速率
源码:
参数详解:
setramrate()方法实现了每个块内存增长速率的设置,该方法只允许合约账户本身调用。
注意:
以字节/块为单位设置ram的增加速率,其上限为uint16。
每年的最高速率为3TB,如果update_ram_supply没有被最新的块覆盖。
在切换速率之前,将以旧速率分配新的ram直到当前块。
(五)setpriv设置特权开关
源码:
参数详解:
setpriv()方法只允许合约账户本身调用,实现了特权开关的设置,调用成功后,该账户成为特权帐户,可以跳过标准授权检查执行交易。
(六)setparams设置系统参数
1、setparams()方法详解
源码:
参数详解:
setparams()是公共函数,该函数设置了链参数eosio::blockchain_parameter,只允许合约账户本身调用。
应用场景:
cpu资源分配的算法是动态,全网cpu的利用率分忙时和闲时,当利用率超过一定阈值,即为忙时。这个阈值将会使用setparams()方法修改,修改参数为target_block_cpu_usage_pct。目前,eos主网的值为3000,即cpu利用率为30%。
setparams()方法修改链配置。可配置的参数如下:
2、blockchain_parameters默认配置及参数详解
数据结构:
核心参数详解:

(七)setinflation设置通胀率
源码:
参数详解:
相关数据结构:
setinflation()方法通过更改核心代币供应的年通货膨胀率,并根据以下结构指定新发行代币的分配 方式实现了通胀率的设置:
例如,对于5%的年通货膨胀率=>annual_rate=default_inflation_pay_factor*5%=500,对于1.5%的年通货膨胀率=>annual_rate=default_inflation_pay_factor* 1.5%=150
设置通胀系数后会增发一部分代币,其中20%会用于奖励生产者(会根据指定生产者所占总量的占比来分配奖励),剩余80%存储在eosio.saving(用作WPS工作提案奖励用)。
设置投票系数后剩余的奖励将根据收到的选票按比例分配。例如,其中有25%的量按生产者的产块量奖励;75%的量按生产者所收获的票数奖励。
为什么要设置年通货膨胀率?
产块奖励与代币增发的实现是通过年通货膨胀系数的设置的。
产块奖励与代币增发:
在每个新的区块中,区块生产者会生成第一个交易,该交易就是onblock,用于标记未付款的区块数(unpaid block)和更新账户竞标的信息。其发放奖励的接口claimrewards由外部调用触发。EOSIO也并非每年只增发一次,一次性增发全年所有的EOS,而是采用连续增发方式,即任何节点领取(claim)时都会触发系统的增发动作,这也就意味着,增发是根据流动时间长度不定期发生的。
增发代币数量计算公式:
增发代币数量=年通货膨胀系数(0.04879=4.879%)×当前代币发行总量×上一次增发代币到现在的时长/一年的微秒数
-END-
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70012206/viewspace-2962295/ ,如需转载,请注明出处,否则将追究法律责任。