您正在查看: EOS-优秀转载 分类下的文章

EOS的增发机制设定

今天去重新整理了下关于EOS的资料,特别了解了下EOS的增发机制,希望有助于大家更深入的了解EOS

1.EOS介绍

EOS的全称为Enterprise Operation System,即为商用分布式应用设计的一款区块链操作系统。EOS的设计目的在于解决现有的区块链应用性能低、安全性差、开发难度高以及交易手续费高的问题。EOS交易无需手续费。任何团队都可以在EOS上以比较快的速度开发出所需要的Dapp(基于区块链的分布式应用),EOS框架内发生的经济活动用EOS代币完成交易。EOS是区块链3.0的代表。

2.EOS代币发行

EOS代币的初始发行总量共10亿枚,它的发行机制很有趣,1亿留给创始团队,作为开发者的回报。其余9亿对外公募开放,公募阶段分为两个阶段,第一阶段向市场投放2亿枚EOS代币,这个在2017年7月1日完成。前期的2亿枚EOS代币投放,用于激活市场,向投资者介绍EOS的功能和它所具备的价值。第二阶段,2017年7月2日开始每天200万个公开众筹,持续336天,一共7亿个,后期以稳定的增发量逐步释放剩余的7亿枚EOS代币。这个设计很有趣,在这个时间的段,每天都可以参与众筹,同时二级市场也可以买入EOS,这边每天有200万产出,市场还可以消化,也可以搬砖套利,最主要的是,这个价格就完全由市场价格决定了这些新出来的价格。

3.EOS的增发体系及节点奖励分配

针对记账节点所设计的经济激励机制是区块链项目不可缺少的重要组成部分,EOS则是通过增发的方式来给予节点奖励,支付其工资。讲解EOS的增发体系,以及节点奖励分配规则。
主要结论:
1.EOS采用领取时触发的连续增发方式,最高年通胀率近似为5%。
2.增发的EOS主要用于节点奖励和提案基金两方面,其中节点奖励占五分之一,即1%的年通胀率,剩下的即提案基金,约4%。
3.节点(包括超级节点和备用节点)奖励的四分之一,即0.25%的年通胀率为超级节点的出块奖励,剩下的0.75%为所有节点的得票率奖励。
4.备用节点无出块奖励,只有得票率奖励且要求在100个EOS以上,否则便不算备用节点,无法领取奖励。接下来进行详细说明,可以分为增发方式和节点奖励计算及领取(claim)规则两部分进行:

3.1增发方式

1.增发频率

EOSIO并非每年只增发一次,一次性增发完全年所有的EOS,而是采用连续增发方式,即任何节点领取(claim)时都会触发系统的增发动作,这也就意味着,增发是根据流动时间长度不定期发生的。

2.增发数量

每次触发增发时,系统增发的数量按如下公式计算:每次增发数量=年通胀系数(4.879%) 当前EOS总量 上一次增发到本次增发的时间间隔(微秒)/ 每年总时间(5272436001000000微秒)·年通胀系数为什么不是5%?简单来说,5%是每年只增发一次的年通胀率,但EOS采用的是无限次数增发的方式,因此,在这种增发方式下求出来的年通胀系数为4.879%,可使得EOS的年通胀率近似为5%。·设所有BP全年领取的总次数(即增发次数)n为无穷大,单次通胀率为x。那么在EOS初始总量为10亿,一年增发后数量为10.5亿的情况下,可得等式10乘以(1+x)的n次方等于10.5,求极限可得年通胀系数x乘以n等于ln1.05,即4.879%。

3.增发用途

EOS每年增发将近5%,主要用于节点奖励和提案基金两方面:

  • BP奖励:增发数量的五分之一,即1%的年通胀率,又分为两部分
  • 出块奖励:BP奖励的四分之一,即0.25%的年通胀率
  • 得票率奖励:BP奖励减去出块奖励,即0.75%的年通胀率
  • 提案基金:增发数量减去BP奖励,即4%的年通胀率

3.2节点奖励计算及领取规则

  1. 出块奖励出块奖励只向21个超级节点发放,其中涉及到一个出块奖励池的概念,由于每个节点领取时都会增发部分EOS,所以所有未领取的出块奖励都会放在出块奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的出块奖励数量计算公式如下:单个节点可领取的数量=出块奖励池里的EOS数量 * 该BP未领取奖励的出块数量 / 所有未领取奖励的区块数量
  2. 得票率奖励得票率奖励向超级节点和备用节点发放,其中涉及到一个得票奖励池的概念,由于每个节点领取时都会增发部分EOS,所以所有未领取的得票率奖励都会放在得票奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的得票率奖励数量计算公式如下:单个节点可领取的数量=得票率奖励池里的EOS数量 * 该BP的得票权重 / 所有BP的总得票权重
  3. 领取(claim)条件节点领取奖励需满足以下条件:
  • 只有超级节点和备用节点才能领取奖励
  • 同一个节点两次claim间隔时间不能少于24小时
  • 备用节点无出块奖励,只有得票率奖励且需要在100个EOS以上,否则便不算备用节点,无法领取奖励

转载自:https://www.jianshu.com/p/14e78b0f5a71

EOSPark 杂谈 | 投票

投票的分数是怎么计算的

score_of_vote=stake_of_EOS∗2^{current_year−2000}
举个例子,比如现在是2018年7月1号0点,我抵押了100个eos,那么我给超级节点A投了一票的分值就是:100 * 2^{18.5} = 37072760
过了半年,到了2019年1月1号0点,还是抵押了100个eos,那么我再次给超级节点A投了一票,那么节点A的总得分会先减去我前一票的分值37072760,然后再加上我当前的分值:100 * 2^{19}=52428800,详情可参见源码
当减少或者增加自己抵押的eos时,以前的投票的分数也会被即时更新,被投的节点总得分也会相应减少或增加。所以就是为什么你明明已经给某节点投过票,他们还在催你继续给他投的原因了,因为可能尽管你抵押的EOS数量没变,但你不同时刻的每一票的的分数是不一样的,它是随着时间递增的。

投票账户数是什么意思

投票账户数是从另一个维度来描述节点的支持率。表示有这么多个EOS用户来给他们喜欢的节点投票。不过,节点的排名并不是根据投票账户数来的,而是看上面讲的投票的总得分数来排序的。
所以你会经常发现有些节点的投票账户数很少,但是他们的得分却很高,原因就是有很多EOS大户给他们投票了,一个大户的一张票含金量非常高了。
前段时间发现一个很有意思的帐户 bpvoter.one,这个帐户下面创建了600多个小号,然后随便点进一个小号大概率都可以发现他们都抵押了2000到5000不等的EOS,这些小号基本上除了投票之外啥也不干,为啥不直接用一个帐号投呢。嘿嘿,人多热闹嘛,你懂的~

待申领奖励是怎么来的

节点们辛辛苦苦给我们出块、记账,活可不是白干的(每年的服务器成本还是很高的)。再加上EOS通过一些比如竞拍、买卖RAM过程中的手续费等操作会白白烧掉EOS,没有增发的话也会导致通货紧缩,所以有了每年增发不超过5%的EOS。那么这些增发的EOS是怎么分配的呢?
首先,增发的这部分EOS中的80%会打到一个叫 eosio.saving的账户里,可以看到现在为止已经有9百多万个EOS了,据说这账户里的EOS会用于社区建设。
然后,剩下的20%就是奖励给节点的了。这部分奖励又分两部分,其中的25%是作为出块奖励,剩下的75%就是我们这篇文章要介绍的投票奖励了。
那么这每年增发的5%里的20%里的75%的EOS是按什么规则分配给这么多节点的呢?

合约版本1.3.0之前的投票奖励分配规则

之前的分配规则比较简单粗暴,各自按照其得票的分数占比来瓜分这些奖励。以此刻的排名第一的eoshuobipool为例子,此时它的得分占比为2.596%,那么假如从现在开始它保持这个得票比率坚持一百年不动摇,那么它的得票奖励一年获得的奖励大致就是:
1000000000*0.05*0.2*0.75*0.02596 = 194700
每天的得票奖励大约为194700/365=533。不过这并不是一个节点的全部奖励,别忘了上面说过的还有出块奖励的哈。

合约版本1.3.0之后的投票奖励分配规则

终于来到本篇文章的重点了,该版本发布说明在 这里。新的分配规则在New producer pay algorithm章节里有说明,反正我是读不太懂,只能去源码里读全球通用语言了。
首先介绍一下大背景,新版本引入了一个叫做votepay share的概念,通过阅读代码我理解为这个新出的概念是一个类似于 得票分数随着时间成正比增长的股份 ,后面就是依据这个得票股份占比来分配投票奖励。这个得票股份的计算大致如下:
得票股份=得票分数*时间差
这个时间差就是任何两个 涉及到更新得票分数 的操作之间的时间差,比如:投票给某节点、增加/减少抵押的EOS、节点的申领奖励的操作等等。
如果仅仅是这样的话,其实跟旧规则差别不大,只是换个壳而已,但是其中有一个特别的限制:当节点有超过三天没有做claimrewards操作的时候,它就申领不到任何奖励,这些奖励会变相地被别的勤快的节点领走。
那么这个特别的限制会带来什么影响呢?你也许会说,现在的节点基本上都是天天领奖励,有些节点甚至都写了个脚本天天定时领,很少会有超过三天没领的。嗯,对于前21个出块节点来说是这样的,但是备选节点呢?我们知道通常备选节点没有机会出块,所以只有得票奖励,而得票奖励不满100EOS是无法领取的,所以就极有可能会造成三天没有claimrewards操作的尴尬情况。如果这次新版本的目的就是过滤掉垃圾备选节点的话,那我可以悄悄地告诉你一声,这个版本的系统合约是有bug的。
解释这个bug前,得先了解下新版本的逻辑,从两个action来阐述吧,一个是给节点投票的voteproducer,另一个就是节点的申领操作claimrewards。便于后面示例的解释,先给出一个宏定义:

公式的编号 公式的具体内容
A 节点得票股份+=节点得票分数*时间差
B 全网得票股份+=全网得票股份变化率*时间差
C 全网得票股份变化率+=节点得票分数
D 全网得票股份-=节点的得票股份
E 全网得票股份变化率-=节点得票分数
F 节点得票股份=0
G 节点奖励=(节点得分/全网总得分)*增发的得票EOS
H 节点奖励=(节点得票股份/全网得票股份)*增发的得票EOS
I 节点奖励=0

Voteproducer

示例编号 操作编号 节点的得票股份变化 全网的得票股份变化
0 vote0 A BC
1 vote1 F BDE
2 vote2 F B
3 vote3 A BC

Claimrewards
因为部署了新版本的系统合约后,还需要节点手动做一次updtrevision才开始走新版本的得票奖励结算逻辑,之后可以手动用regproducer重新更新一次节点,或者在下一次claimrewards的时候自动更新一次。
当updtrevision与regproducer/claimrewards之间无涉及到更新得票分数的操作时

示例编号 操作编号 节点获得的奖励 全网得票股份的变化
4 claim0 FG BC
5 claim1 ABHF D
6 claim2 I BADF

示例编号 操作编号 节点获得的奖励 全网得票股份的变化
7 claim1 I BDCF

当updtrevision与regproducer/claimrewards之间有涉及到更新得票分数的操作时

示例编号 操作编号 节点获得的奖励 全网得票股份的变化
8 vote0+claim0 ABHF D
9 vote0+claim0 AABHF D

示例总结

  • 通过示例1、2、6、7可以知道节点超过3天不claimrewards的话,得票奖励会被清0,损失的奖励继续在得票奖励池子里。等于变相的增加了其他节点的奖励。
  • 通过示例8、9可以知道节点在做完updtrevision操作后,要尽快执行一次regproducer或者claimrewards操作,否则会丢失这期间的可能的来自用户投票的奖励。这也是原文里最后一句话说可能遗失某些奖励的原因。

关于bug

现在再来解释前面提到的bug,这个bug存在于判断本次claimrewards离上次claimrewards是否已经超过3天。
相关源码如下:

if( producer_per_vote_pay < min_pervote_daily_pay ) {
         producer_per_vote_pay = 0;
}

......

_producers.modify( prod, 0, [&](auto& p) {
   p.last_claim_time = ct;
   p.unpaid_blocks   = 0;
});

在判断完得票奖励不足100EOS时,没有做任何处理,代码会径直走到p.last_claim_time = ct;这一行,个人觉得这应该是个bug,因为备选几点可以写个定时脚本天天做一次claimrewards操作,尽管他们可能并不能申领到任何奖励,但是依旧能成功刷新他们的last_claim_time时间。这样的话,新版本的关于超过3天未做claimrewards的判断就不可能成功了。

原文地址:https://articles.eospark.com/?p=74

EOS 新型攻击手法之 hard_fail 状态攻击

前言

昨日(2019 年 3 月 10 日)凌晨,EOS 游戏 Vegas Town (合约帐号 eosvegasgame)遭受攻击,损失数千 EOS。慢雾安全团队及时捕获这笔攻击,并同步给相关的交易所及项目方。本次攻击手法之前没有相同的案例,但可以归为假充值类别中的一种。对此慢雾安全团队进行了深入的分析。

攻击回顾

根据慢雾安全团队的持续分析,本次的攻击帐号为 fortherest12,通过 eosq 查询该帐号,发现首页存在大量的错误执行交易:

查看其中任意一笔交易,可以发现其中的失败类型均为 hard_fail:

这立即就让我想起了不久前的写过的一篇关于 EOS 黑名单攻击手法的分析,不同的是实现攻击的手法,但是原理是类似的,就是没有对下注交易的状态进行分析。

攻击分析

本次攻击的一个最主要的点有两个,一个是 hard_fail,第二个是上图中的延迟。可以看到的是上图中的延迟竟达到了 2 个小时之久。接下来我们将对每一个要点进行分析。

(1)hard_faild:

参考官方开发文档(https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state-with-state-history-plugin

可以得知 fail 有两种类型,分别是 soft_fail 和 hard_fail,soft_fail 我们遇见的比较多,我们一般自己遇到合约内执行 eosio_assert 的时候就会触发 soft_fail,回看官方对 soft_fail 的描述:客观的错误并且错误处理器正确执行,怎么说呢?拿合约内 eosio_assert 的例子来说

{
    //do something
    eosio_assert(0,"This is assert by myself");
    //do others
}

这种用户自己的错误属于客观错误,并且当发生错误之后,错误处理器正确执行,后面提示的内容 This is assert by myself 就是错误处理器打印出来的消息。

那么 hard_fail 是什么呢?回看官方对 hard_fail 的描述:客观的错误并且错误处理器没有正确执行。那又是什么意思呢?简单来说就是出现错误但是没有使用错误处理器(error handler)处理错误,比方说使用 onerror 捕获处理,如果说没有 onerror 捕获,就会 hard_fail。

OK,到这里,我们已经明白了 hard_fail 和 soft_fail 的区别,接下来是怎么执行的问题,传统的错误抛出都是使用 eosio_assert 进行抛出的,自然遇到 hard_fail 机会不多,那怎么抛出一个 hard_fail 错误呢?我们继续关注下一个点—延迟时间。

(2)延迟时间:

很多人可能会疑惑,为什么会有延迟时间,我们通过观察可以知道 fortherest12 是一个普通帐号,我们惯常知道的延时交易都是通过合约发出的,其实通过 cleos 中的一个参数设置就可以对交易进行延迟,即使是非合约帐号也可以执行延迟交易,但是这种交易不同于我们合约发出的 eosio_assert,没有错误处理,根据官方文档的描述,自然会变成 hard_fail。而且最关键的一个点是,hard_fail 会在链上出现记录。

攻击细节分析

根据 jerry@EOSLive 钱包的讲解,本次的攻击发生和 EOS 的机制相关,当交易的延迟时间不为 0 的时候,不会立马校验是否执行成功,对延迟交易的处理是 push_schedule_transaction,而交易的延迟时间等于 0 的时候,会直接 push_transaction。这两个的处理机制是存在区别的。

攻击成因

本次攻击是因为项目方没有对 trx 的 status 状态进行校验,只是对 trx 是否存在作出了判断。从而导致了本次攻击的发生。

防御手法

项目方在进行线下开奖的时候,要注意下注订单的执行状态,不要只是判断交易是否存在,还要判断下注订单是否成功执行。如下图

相关参考

引起 object fail 的错误类型参考:

https://eos.live/detail/16715
官方对交易执行状态的描述:

https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state-with-state-history-plugin

by yudan@慢雾安全团队