eosio.system智能合约介绍 (三) 选举、投票、系统设置

本文详细介绍了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的超级节点选举是围绕账户进行的。账户注册为超级节点候选账户,其他账户才可以为其投票。

注册为超级节点候选账户,需要提供公钥,此公钥用于当选超级节点后,产块时验证签名。

命令基础结构:

cleos system regproducer [OPTIONS] account producer_key [url] [location]

注册节点示例:

cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

取消节点:

cleos system unregprod alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

取消节点后,其他账号不能再为其投票,但是之前投的票会被保留,下次创建节点仍会出现。

04

投票

(一)投票流程

1、注册节点

运行以下指令注册节点(详见前文):

cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

2、抵押与取消抵押

抵押:

抵押给自己:

cleos system delegatebw ost ost "5 SYS" "5 SYS" 

抵押成功返回值

executed transaction: 403f264c483947d3a5b2cd3508632d2993789467674ff458fac1b413d2f2b4ea  144 bytes  318 us
#         eosio <= eosio::delegatebw            {"from":"ost","receiver":"ost","stake_net_quantity":"51.0000 SYS","stake_cpu_quantity":"49.0000 SYS"...
#   eosio.token <= eosio.token::transfer        {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
#           ost <= eosio.token::transfer        {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
#   eosio.stake <= eosio.token::transfer        {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]

抵押前转给ost 1000.0000 SYS token,查看抵押后的账户:

cleos get table eosio.token ost accounts
{
  "rows": [{
      "balance": "900.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

查看抵押信息:

cleos get table eosio ost delband
{
  "rows": [{
      "from": "ost",
      "to": "ost",
      "net_weight": "153.0000 SYS",
      "cpu_weight": "147.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

抵押给别人:

cleos system delegatebw ost imtube "5.0000 SYS" "5.0000 SYS"

查看抵押信息:

cleos get table eosio ost delband{
{
  "rows": [{
      "from": "ost",
      "to": "imtube",
      "net_weight": "5.0000 SYS",
      "cpu_weight": "5.0000 SYS"
    },{
      "from": "ost",
      "to": "ost",
      "net_weight": "153.0000 SYS",
      "cpu_weight": "147.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

查询ost的balance为:890.0000 SYS

取消抵押:

取消抵押命令基础结构如下:

cleos system undelegatebw [OPTIONS] from receiver unstake_net_quantity unstake_cpu_quantity

此时再次查看ost的balance,显示仍为890.0000 SYS,没有将取消抵押的返回,原因是取消抵押有3天延迟,3天后再查看即可得到正常反馈。

cleos get table eosio.token ost accounts
{
  "rows": [{
      "balance": "890.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

3、投票与取消投票

投票前准备:

创建节点:

cleos system regproducer ost EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

cleos system regproducer imtube EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

抵押:

ost→ost 5.0000 SYS,ost→imtube 5.0000 SYS

cleos get table eosio ost delband
{
  "rows": [{
      "balance": "880.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}
root@5dca586566d1:~# cleos get table eosio ost delband
{
  "rows": [{
      "from": "ost",
      "to": "imtube",
      "net_weight": "5.0000 SYS",
      "cpu_weight": "5.0000 SYS"
    },{
      "from": "ost",
      "to": "ost",
      "net_weight": "158.0000 SYS",
      "cpu_weight": "152.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

imtube→imtube

cleos system delegatebw imtube imtube "2 SYS" "2 SYS"

查看imtube抵押信息:

cleos get table eosio imtube delband
{
  "rows": [{
      "from": "imtube",
      "to": "imtube",
      "net_weight": "2.0000 SYS",
      "cpu_weight": "2.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

imtube→bob

cleos system delegatebw imtube bob "3 SYS" "3 SYS"

节点给其他节点投票

cleos system voteproducer prods imtube ost

投票成功返回值:

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    ]       
获取投票者信息:
cleos get table eosio eosio voters
{
  "rows": [{
      "owner": "eosio",
      "proxy": "",
      "producers": [],
      "staked": 800840,
      "last_vote_weight": "0.00000000000000000",
      "proxied_vote_weight": "0.00000000000000000",
      "is_proxy": 0,
      "flags1": 0,
      "reserved2": 0,
      "reserved3": "0 "
    },{
      "owner": "imtube",
      "proxy": "",
      "producers": [
        "ost"
      ],
      "staked": 100000,
      "last_vote_weight": "1080641469324.71191406250000000",
      "proxied_vote_weight": "0.00000000000000000",
      "is_proxy": 0,
      "flags1": 0,
      "reserved2": 0,
      "reserved3": "0 "
    },{
      "owner": "jiscfgtizds5",
      "proxy": "",
      "producers": [],
      "staked": 2000000,
      "last_vote_weight": "0.00000000000000000",
      "proxied_vote_weight": "0.00000000000000000",
      "is_proxy": 0,
      "flags1": 0,
      "reserved2": 0,
      "reserved3": "0 "
    },{
      "owner": "ost",
      "proxy": "",
      "producers": [],
      "staked": 3200000,
      "last_vote_weight": "0.00000000000000000",
      "proxied_vote_weight": "0.00000000000000000",
      "is_proxy": 0,
      "flags1": 0,
      "reserved2": 0,
      "reserved3": "0 "
    },{
      "owner": "pagbbj4afmu5",
      "proxy": "",
      "producers": [],
      "staked": 2000000,
      "last_vote_weight": "0.00000000000000000",
      "proxied_vote_weight": "0.00000000000000000",
      "is_proxy": 0,
      "flags1": 0,
      "reserved2": 0,
      "reserved3": "0 "
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

查看imtube抵押信息:

cleos get table eosio imtube delband
{
  "rows": [{
      "from": "imtube",
      "to": "bob",
      "net_weight": "3.0000 SYS",
      "cpu_weight": "3.0000 SYS"
    },{
      "from": "imtube",
      "to": "imtube",
      "net_weight": "2.0000 SYS",
      "cpu_weight": "2.0000 SYS"
    }
  ],
  "more": false,
  "next_key": "",
  "next_key_bytes": ""
}

节点给自己投票

cleos system voteproducer prods imtube imtube

投票成功返回值:

executed transaction: 65cc7f09e0b5d0bc3e263f3b770b520838c44583be1da2f6c151d57275a0b951  120 bytes  306 us
#         eosio <= eosio::voteproducer          {"voter":"imtube","proxy":"","producers":["imtube"]}
warning: transaction executed locally, but may not be confirmed by the network yet   ] 

账号给节点投票:

bob抵押:

cleos system delegatebw bob bob "11 SYS" "11 SYS"

bob给ost投票:

cleos system voteproducer prods bob ost

投票数量计算公式:votingNum=(stake_net_quantity+stake_cpu_quantity)*10000;

投票给多个节点

将alice设置为节点

cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

cleos system voteproducer prods为直接给超级节点投票的命令,可以指定投票账户,可以一次性投给多个超级节点候选账户,账户名需要按字母从小到大排序,最多不超过30个账户。

cleos system voteproducer prods [OPTIONS] voter producers...

4、 投票失败

以下情况会导致投票失败:

  • 未创建的节点;

  • 创建后又取消的节点;

  • 一次投30个以上的节点,只有前30可以成功;

  • 多个节点投票,没有按顺序;

5、 节点奖励

cleos system voteproducer prods [OPTIONS] voter producers...

如需发放节点奖励,必须保证per_block_payments大于0;

否则会导致报错

Error 3050003: eosio_assert_message assertion failure
Error Details:
assertion failure with message: cannot claim rewards until the chain is activated (at least 15% of all tokens participate in voting)
pending console output:
  • 出块奖励只向21个超级节点发放,其中涉及到一个出块奖励池的概念,由于每个节点领取时都会增发部分EOS,所以所有未领取的出块奖励都会放在出块奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的出块奖励数量计算公式如下:单个节点可领取的数量=出块奖励池里的EOS数量*该BP未领取奖励的出块数量/所有未领取奖励的区块数量

  • 得票率奖励向超级节点和备用节点发放,同出块奖励相似,所有未领取的得票率奖励都会放在得票奖励池中等待节点领取。每次单个节点领取(claim)时,能领取到的得票率奖励数量计算公式如下:单个节点可领取的数量=得票率奖励池里的EOS数量*该BP的得票权重/所有BP的总得票权重

  • 领取(claim)条件节点领取奖励需满足三个条件:超级节点和备用节点才可领取;同一节点两次claim间隔时间不能少于24小时;备用节点无出块奖励,只有得票率奖励且需要在100个EOS以上,否则不算备用节点,无法领取奖励。

(二)代理投票流程

1、注册节点

cleos system regproducer ost EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1

2 、建立代理与取消代理

建立代理:

cleos system regproxy imtube

代理成功返回值:

executed transaction: 06616d46400deef7191c869cb3d96f1d35b4fec1f98adb41b32b4754e00afa77  104 bytes  243 us
#         eosio <= eosio::regproxy              {"proxy":"imtube","isproxy":1}
warning: transaction executed locally, but may not be confirmed by the network yet   ]
 
 

取消代理:

cleos system unregproxy imtube

取消代理成功返回值:​​​​​​​

executed transaction: 07a59f11b4f076dd57bc9356c65d9621bdbd40a4d5a48077cc7e48f650925c9a  104 bytes  268 us
#         eosio <= eosio::regproxy              {"proxy":"imtube","isproxy":0}
warning: transaction executed locally, but may not be confirmed by the network yet   ]

3、代理投票

建立代理:

cleos system regproxy alice

抵押:

cleos system delegatebw imtube imtube "11.0000 SYS" "11.0000SYS"

委托代理:

cleos system voteproducer proxy imtube alice

委托成功返回值:​​​​​​​

executed transaction: 667ffb20e7ec556d1760495f3f6ecfe1c315405d9ac31c2133f1523854dd8672  112 bytes  285 us
#         eosio <= eosio::voteproducer          {"voter":"imtube","proxy":"alice","producers":[]}
warning: transaction executed locally, but may not be confirmed by the network yet   ]      ]

代理投票:

cleos system voteproducer prods alice ost
  • 通过代理进行投票,即先投票给代理,再由代理投票给生产者。

  • 代理的作用就是替别人做出选择投票,本身不需要抵押。

  • 在投票的时候,要先抵押,投票有两种选择,只能选择一种,两种不能同时存在。

  • 若选择自己投票,则直接操作;若选择代理投票,则将票抵押给代理,由代理选择要投票的节点。

  • 已经作为代理的账号,不能再设置代理投票。

05

系统设置

(一)setalimits设置账号资源限制

源码:

void system_contract::setalimits( const name& account, int64_t ram, int64_t net, int64_t cpu ) {
      require_auth( get_self() );

      user_resources_table userres( get_self(), account.value );
      auto ritr = userres.find( account.value );
      check( ritr == userres.end(), "only supports unlimited accounts" );

      auto vitr = _voters.find( account.value );
      if( vitr != _voters.end() ) {
         bool ram_managed = has_field( vitr->flags1, voter_info::flags1_fields::ram_managed );
         bool net_managed = has_field( vitr->flags1, voter_info::flags1_fields::net_managed );
         bool cpu_managed = has_field( vitr->flags1, voter_info::flags1_fields::cpu_managed );
         check( !(ram_managed || net_managed || cpu_managed), "cannot use setalimits on an account with managed resources" );
      }

      set_resource_limits( account, ram, net, cpu );
   }

参数详解:​​​​​​​

account: 要设置其资源限制的帐户的名称

ram_bytes: 账户内存总购买量(以绝对字节为单位)

net_weight: 账户带宽总抵押权重;账户带宽总抵押权重/全网总抵押权重=账户实际可使用率;对账户总抵押权重的修改也会反应到全网总抵押权重上。

cpu_weight: 账户CPU总抵押权重;与net_weight同理。

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设置内存限制

源码:

void setacctram( const name& account, const std::optional<int64_t>& ram_bytes );

参数详解:​​​​​​​

account:账户

ram_bytes:内存限制

由于RAM资源有限,在具体实现时,需要设置RAM资源限制:单个账户限制、单笔交易限制和单个区块限制三部分,此处setacctram()方法设置单个账户限制,该方法只允许合约账户本身调用。

为什么要设置RAM限制?

RAM对开发者来说十分宝贵,因为开发DApp需要占用RAM空间。此外EOS中没有地址的概念,用户如果想使用EOS,必须在EOS上创建一个账户。创建EOS账户需要消耗内存,即RAM。RAM被用来进行一些特殊的EOS链上的操作,比如:生成新的账户、竞价EOS账户名拍卖等。数据库记录需要消耗RAM,RAM是一项宝贵的资源。所以需要设置账户使用ram的大小。

(三)setram设置提供的内存大小

源码:

void system_contract::setram( uint64_t max_ram_size ) {
      require_auth( get_self() );

      check( _gstate.max_ram_size < max_ram_size, "ram may only be increased" ); /// decreasing ram might result market maker issues
      check( max_ram_size < 1024ll*1024*1024*1024*1024, "ram size is unrealistic" );
      check( max_ram_size > _gstate.total_ram_bytes_reserved, "attempt to set max below reserved" );

      auto delta = int64_t(max_ram_size) - int64_t(_gstate.max_ram_size);
      auto itr = _rammarket.find(ramcore_symbol.raw());

      /**
       *  Increase the amount of ram for sale based upon the change in max ram size.
       */
      _rammarket.modify( itr, same_payer, [&]( auto& m ) {
         m.base.balance.amount += delta;
      });

      _gstate.max_ram_size = max_ram_size;
   }

参数详解:

max_ram_size: 内存大小

max_ram_size初始默认为64G,setram()方法实现了对RAM的一次性扩容,该方法只允许合约账户本身调用。

应用场景:

某个基于EOS开发的链,提供了免费的账户注册接口,执行调用后,账户免费为其抵押CPU、NET和购买RAM。由于接口没有做严格有效的防刷处理,导致账户注册严重超过预期,导致链内系统资源浪费严重,以及空投部分系统代币占用过多。

解决方法:

  • 通过setram()方法一次性扩增RAM容量

  • 通过setramrate()方法设置为每块持续新增。

(四)setramrate设置每个块内存增长速率

源码:

void system_contract::setramrate( uint16_t bytes_per_block ) {
      require_auth( get_self() );

      update_ram_supply();
      _gstate2.new_ram_per_block = bytes_per_block;
   }

参数详解:

bytes_per_block: 每个块的内存大小

setramrate()方法实现了每个块内存增长速率的设置,该方法只允许合约账户本身调用。

注意:

  • 以字节/块为单位设置ram的增加速率,其上限为uint16。

  • 每年的最高速率为3TB,如果update_ram_supply没有被最新的块覆盖。

  • 在切换速率之前,将以旧速率分配新的ram直到当前块。

(五)setpriv设置特权开关

源码:​​​​​​​

void system_contract::setpriv( const name& account, uint8_t ispriv ) {
      require_auth( get_self() );
      set_privileged( account, ispriv );
   }

参数详解:​​​​​​​

account: 账户

is_priv: 是否开启特权( 0不开,>0开启 )

setpriv()方法只允许合约账户本身调用,实现了特权开关的设置,调用成功后,该账户成为特权帐户,可以跳过标准授权检查执行交易。

(六)setparams设置系统参数

1、setparams()方法详解

源码:

void system_contract::setparams( const eosio::blockchain_parameters& params ) {
      require_auth( get_self() );
      (eosio::blockchain_parameters&)(_gstate) = params;
      check( 3 <= _gstate.max_authority_depth, "max_authority_depth should be at least 3" );
      set_blockchain_parameters( params );
   }

参数详解:

params: 参数

setparams()是公共函数,该函数设置了链参数eosio::blockchain_parameter,只允许合约账户本身调用。

应用场景:

  • cpu资源分配的算法是动态,全网cpu的利用率分忙时和闲时,当利用率超过一定阈值,即为忙时。这个阈值将会使用setparams()方法修改,修改参数为target_block_cpu_usage_pct。目前,eos主网的值为3000,即cpu利用率为30%。

setparams()方法修改链配置。可配置的参数如下:​​​​​​​

{ "params":
  {
    "max_block_net_usage": 1048577,
    "target_block_net_usage_pct": 1000,
    "max_transaction_net_usage": 524288,
    "base_per_transaction_net_usage": 12,
    "net_usage_leeway": 500,
    "context_free_discount_net_usage_num": 20,
    "context_free_discount_net_usage_den": 100,
    "max_block_cpu_usage": 200000,
    "target_block_cpu_usage_pct": 1000,
    "max_transaction_cpu_usage": 150000,
    "min_transaction_cpu_usage": 100,
    "max_transaction_lifetime": 3600,
    "deferred_trx_expiration_window": 600,
    "max_transaction_delay": 3888000,
    "max_inline_action_size": 4096,
    "max_inline_action_depth": 4,
    "max_authority_depth": 6
  }
}

2、blockchain_parameters默认配置及参数详解

数据结构:

/* 区块链全局状态 */
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;
};

核心参数详解:

名字 注释
max_ram_size 最大内存,默认大小为 64GB
total_ram_bytes_reserved 可用内存大小,默认配置为0
total_ram_stake 总内存抵押大小,默认配置为0
last_producer_schedule_update 最后一个块生成时间
last_pervote_bucket_fill 最后一次投入桶时间
pervote_bucket
perblock_bucket
total_unpaid_blocks 总未支付的块
total_activated_stake 总活跃的块
thresh_activated_stake_time
last_producer_schedule_size 上一个生产者调度任务大小
total_producer_vote_weight 生产者的投票资产
last_name_close

(七)setinflation设置通胀率

源码:

void system_contract::setinflation( int64_t annual_rate, int64_t inflation_pay_factor, int64_t votepay_factor ) {
      require_auth(get_self());
      check(annual_rate >= 0, "annual_rate can't be negative");
      if ( inflation_pay_factor < pay_factor_precision ) {
         check( false, "inflation_pay_factor must not be less than " + std::to_string(pay_factor_precision) );
      }
      if ( votepay_factor < pay_factor_precision ) {
         check( false, "votepay_factor must not be less than " + std::to_string(pay_factor_precision) );
      }
      _gstate4.continuous_rate      = get_continuous_rate(annual_rate);
      _gstate4.inflation_pay_factor = inflation_pay_factor;
      _gstate4.votepay_factor       = votepay_factor;
      _global4.set( _gstate4, get_self() );
   }

参数详解:

annual_rate: 年率(核心代币供应的年通货膨胀率)

inflation_pay_factor: 通胀系数(用于奖励区块生产者的通货膨胀分数的倒数)

votepay_factor: 投票系数(区块生产者奖励的分数与所产生的区块成比例的倒数)

相关数据结构:​​​​​​​

static constexpr int64_t  default_inflation_pay_factor  = 50000;
static constexpr int64_t  default_votepay_factor = 40000;

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-

猜你喜欢

转载自blog.csdn.net/BSN_yanxishe/article/details/131533505