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

"Dapp"你们走的太快了,请等等你们的"EOS"

80天80亿流水, EOS DApp生态大爆发,CPU价格水涨船高,这是一个很正常的市场行为,需求大了,价格自然上涨。但是如果你仔细看看数据就会发现,目前EOS TPS平均只有50,理论上CPU肯定是空闲的。既然是空闲的,CPU没有涨价的理由啊。所以这里就存在一个问题,要么是CPU价格虚高,要么就是目前系统配置下,EOS TPS极限就是50左右。


为了一探究竟,就必须先分析分析CPU价格的计算机制。

CPU资源价格计算机制

CPU的价格是指1个EOS可以使用多长时间的CPU,所以CPU价格自然受两个指标影响:一个是CPU资源总量,一个是CPU需求量。

由于EOS投票必须抵押,因而系统中抵押的EOS有很多只是用来投票而不是用来使用CPU的,自然没法判断当前CPU的真实需求量,自然没法计算出CPU的价格。于是EOS提出了虚拟CPU资源的概念,CPU的价格=虚拟CPU资源总量/系统总的EOS抵押量。这个虚拟CPU资源总量是动态调整的,是根据过去1分钟CPU真实使用量动态调整的,当CPU真实使用量大于某个阈值(目前是CPU总量的20%)时,认为CPU处于繁忙了,会调低虚拟CPU总量即提高CPU价格以降低需求量,如果CPU使用量还是没下来(交易量还是没减少),虚拟CPU总量会继续降低,直到很多用户因为CPU不够或超支没法发起交易,然后CPU使用量自然就下降了。反之CPU闲时,CPU价格会降低,用户能够发起的交易增多,自然交易量就大了,CPU使用量就会上升。因此,这个机制还是非常市场化和实时的。这个虚拟CPU量最大为真实CPU量的1000倍,这其实间接认为,抵押的EOS中用来兑换为CPU的那部分占比最少为1/1000。这个虚拟CPU总量没有下限,下限是根据CPU使用量来调整的。下限是直到CPU的使用量低于真实CPU总量的20%才开始不降低或回升。

由于这个CPU价格实时动态调整机制,在一个活跃的市场内,CPU的使用量应该会在阈值(20%)这个量上下波动。事实上数据显示也如此

同时CPU价格应该也有忙闲之分

从上可以看出,凌晨2点开始变闲,凌晨4点到6点最闲,从一定角度可以看出,EOS中国及东南亚国家玩家多。

更长时间的CPU价格图也表明几乎每天都是4点到6点最闲。


上面分析提到CPU的最大使用量就在阈值附近。所以在CPU真实总量确定的情况下,这个阈值是EOS最大TPS的唯一影响因素。那这个阈值又是如何确定的呢?这个阈值就是前一段时间广泛报道的TARGET_BLOCK_CPU_USAGE_PCT。

10月18号EOS通过决议将TARGET_BLOCK_CPU_USAGE_PCT

的值从10%提升到20%,所以TPS在10.18号后得到提升,还是继续看数据。

从上面可以看出,10.18后的2天,社区立马做出了恰当的反应,TPS在短短2天内快速从20左右提升到50的极限TPS并一直保持。
再看看看这个变动后,CPU的真实使用量变化

从上可以看出CPU的使用量也从10%缓慢上升到了20%极限附近。

TPS极限

EOS通过区块CPU总量来调节TPS的极限值。
区块CPU总量=MAX_BLOCK_CPU_USAGETARGET_BLOCK_CPU_USAGE_PCT=2000.2
0.5s产生一个区块,也就是1s中可用2000.22=80ms的CPU

我们以EOS转账为例来说明一个transaction的CPU消耗,目前一个转账交易需要消耗1ms CPU,所以如果EOS中都是EOS转账交易,那么目前EOS TPS理论最高值是80, 但是由于目前很多交易是game类的Dapp,一个交易可能有很多inline action,所以一个交易的耗时是EOS转账交易的2倍左右,从而TPS下降到50左右,和上面的数据分析结果吻合。

TPS如何提升

1)提高TARGET_BLOCK_CPU_USAGE_PCT,这个参数是一个配置,自然可以通过BP提议修改以提高TPS上限,并降低目前CPU价格
2)TARGET_BLOCK_CPU_USAGE_PCT的提升是有限的,最多提升到100%,也就是目前TPS的5倍,所以TPS上线最多达到50*5=250
3) 目前MAX_BLOCK_CPU_USAGE设置为200ms, 1s两个区块,所以1s限定使用400ms, 只占了总时间的40%,这个参数不配置为100%是因为BP节点的CPU除了处理交易,还需要处理网络请求等其他业务,比如交易接收广播,系统软件自身CPU损耗。但是这个40%比例偏低,有提升的可能。
4)EOS系统优化,目前EOS是单线程,BP的超级多核(128核)使不上力,如果并行优化加入,应该可以提升不少。

CPU资源生态优化方向

富人的无成本“倒奶行为“

只提升TPS对改善CPU生态是治标不治本的行为。因为TPS一提升,在达到TPS阈值之前,CPU的价格就会很便宜,由于CPU是免费的,自然会有人发起廉价的交易消耗掉掉这个提升的TPS。上面提到的TARGET_BLOCK_CPU_USAGE_PCT从10%到20%将TPS提升1倍,两天就被吃掉就是一个实例。

CPU资源有价格,但是却是免费的,是CPU资源生态乱像的根源。cpu不够的时候,会出现两个极端。穷人没有CPU,富人一大堆,且有一天有效期,很有可能低效使用甚至乱用。

免费从来就不是资源的最佳分配方式,因而我个人觉得适当的收费是CPU资源生态的一个可能方向。

CPU资源适当收费方向(租赁模式)

CPU资源已经设计成免费模式了,直接在代码中更改为收费不太合理,改动量也大。因而从经济学生态角度来实现CPU适当收费是一个相对安全软改动的方向。具体就是大力发展CPU租赁业务,用户大部分交易通过低价但非免费的租赁方式购买CPU资源。

目前CPU租赁生态已经很红火了,几乎所有钱包(TP, Hoo, MeetOne, 麦子钱包)都支持法币租赁CPU,各大超级节点比如EOS42, Laomao也搭建了租赁平台。但是目前的CPU租赁业务没法承载CPU资源适当收费功能,因为目前租赁生态里的可用EOS太少了,会导致CPU租赁价格过高。租赁生态可用EOS太少原因如下:

EOS所有权目前有3类:资源使用权,投票权,糖果权,由于糖果权属于不确定性资产(需要其他人给你空投),这里只考虑资源使用权和投票权。同时,用户在投票前必须先抵押EOS,而CPU资源的“租客"是一个动态积累撮合的过程, 用户投票前,很难立马找到"租客"出租抵押EOS,但为了投票,它只好给自己抵押,哪怕他并不需要使用CPU,所以投票的那些EOS很难流入租赁市场。你可能会说,用户可以先抵押给自己然后投票,等有租客了取消抵押,然后再租给租客。但是要想将已经抵押的EOS重新抵押给其他人,需要先取消抵押,而取消抵押有3天的回收期,租客是等不了的,同时3天的无票期也是用户不能接受的。所以事实上目前EOS这个投票权是一个不太自由的权利,它依赖抵押这一行为。那为啥EOS要这样设计呢?这是因为投票后,你相应的EOS需要冻结,要不你投票后立马转账,计票模块还需要更新投票信息,相当于需要监控转账等其他行为,于是通过先抵押这一统一的操作先冻结相应的EOS。所以,为了发展健康的CPU租赁市场,必须切割投票权和资源使用权(抵押行为)。具体怎么做呢?就是用户不用抵押即可投票,EOS仍需冻结,但是这些投票冻结的EOS可以继续抵押给自己或者抵押给别人(出租),这样分割后,那些投票大户自己就可以开设CPU租赁平台赚钱,或者无心打理的可以交给第三方专业的CPU租赁公司。其实REX就在往这方面尝试,购买REX的EOS可以投票就是一种不抵押投票行为,REX本身又是一个CPU租赁平台,所以投票用户通过购买REX完成了投票和出租EOS两个操作,可见REX从一定角度上是能完善CPU生态的。REX对目前”民营“租赁平台的影响后续我可能会单独写一篇文章,大家可以关注。

完善后的CPU生态可用房市来类比,租售并举,租是一种普世的保障措施。

总结

目前的CPU价格是真实的市场反馈,目前的50TPS是极限TPS,TPS长时间保持满负荷运行,说明需求旺盛。
EOS价格有忙闲之分,凌晨4-6点最闲,CPU紧张的可以试试这个时段。

在TPS极限没有提升之前(TARGET_BLOCK_CPU_USAGE_PCT),Dapp的推广者不要花全部精力在拉交易量上了,因为TPS总量是定的,市场总交易量几乎是固定的了,整个系统是交易存量市场,零和游戏,一个Dapp多了交易,其他Dapp就会少一些交易,大家可以尝试优化优化下智能合约,尽量少耗一些CPU吧。

目前这个状态,用户经常不能操作,新用户的体验肯定是谈不上爽的,所以在引入新用户的时候,适当给与关怀和指引。
EOS社区需要多花点心思在EOS性能优化和TPS上了,REX也请快点发布吧。
”Dapp“你们走的太快了,请等等你们的“EOS"。

附录

EOS进化“臆想"图

时不时被冻结的资产头脑风暴

普通用户可能只会抵押少量EOS,但是CPU价格的波动导致用户CPU不足或者超支,进而用户没法执行任何交易,用自己的EOS给自己抵押CPU的交易也执行不了了,账号处于冷冻状态。这就存在一个问题,我明明有EOS余额的,但是我没法抵押CPU。我的资产已经不由我做主了。针对这种状态,已经有“民间”商业活动解决了,法币租赁CPU,用租赁的CPU解冻,然后就可以用自己的余额抵押更多的CPU。但是本来是可以设计成用自己余额给自己抵押CPU的,为啥要多出这个花钱租赁操作呢?所以在EOS系统层面增加CPU不足时允许用余额抵押CPU这一功能是有必要的。如果系统层面不能做出改动,那民间是可以想办法的。我这里就有一个想法:

当一个账号CPU不够时,肯定是需要第三方来抵押CPU激活的。作者很早以前就做过免费互助抵押,但是目前这CPU价格,免费业务做不下去了,需要太多EOS了,没法及时补充。所以我想到另外一个思路,被救账号(A)先用scatter等工具发起一个离线交易签名(不需要CPU),比如A签署一个A转给B 10 EOS的离线交易T1,并将这个数据发给B。有了这个离线交易T1,B就给A抵押10EOS, A就有了足够的CPU.然后B发起离线交易T1, T1执行后就返回了10EOS给B,这样B的EOS池的容量保持不变,可以继续这个免费业务。这个过程可以这样类比,借方A在银行有1万元钱,取钱需要手续费100元,但是A身无分文,取不出来。A就向B借100元钱,B知道A有1万元钱,但是B担心A借了钱不还,所以B需要A写一个“A欠B100元钱"的借条,有了借条,B就无后顾之忧了,于是借给A100元, A拿着100元就可以取钱了,B凭借借条也可以拿回100元。上面1万元就是A用户的EOS余额,借条就是离线交易签名。当然这个方案有一些小问题,需要大家更加完善,比如同步问题。

CPU计算逻辑源码

转载自区块链斜杠青年

EOS 资源汇总

EOS 资源汇总

A curated list of EOS Ecosystem by SuperONE.



EOS 资源汇总。提交 PR 参考 contributing,提交 issue 点击 此处

中文 | English

EOS 主网

超级节点

GitHub

主网启动相关

主网启动状态

映射查询

区块浏览器

主网投票状态

主网投票

DevOps

文档

开发

安全

资源

社区

资讯

博客

空投

导航

下载

视频

工具

账号相关工具

浏览器插件

其他工具

EOS 钱包

硬件钱包

移动端

Web 钱包

浏览器插件钱包

开源钱包

交易所

中心化交易所

  • 畅思,专注 EOS 生态的区块链资产精品交易平台
  • 鲸交所,全球首个基于 EOS 主链开发、支持跨链的高流动性去中心化交易所
  • BigONE,BigONE 是一家数字资产交易及托管平台,帮助用户寻找全球优质区块链资产,提供便捷的交易服务,以顶尖的技术和安全控制流程保障用户数字资产安全,帮助用户进行资产管理。BigONE 团队汇集了来自世界各地的区块链专家、极客和爱好者
  • HADEX,火币自主数字资产交易所
  • EOSFINEX,全球首个高性能去中心化交易所
  • ZBG,Pos+Pow 交易挖矿,社区化自治的交易平台

去中心化交易所

  • Newdex,全球首家基于 EOS 的去中心化交易所,支持 SimpleWallet 协议
  • SouthEX,基于 EOS 的去中心化交易所
  • DEXEOS,全球首家基于 EOS 的去中心化交易所

Dapp

Dapp 展示

DApp 生态

  • EOS LIVE,EOS 社区首个产品与资讯聚合平台
  • AWOO!,允许用户合作完成共建更好的社会,目标是带来和平,繁荣和丰富
  • AZARUS,一个公平,可靠,透明的平台,用于玩令牌和下注。专门针对视频游戏行业而构建。
  • Billionaire Token,致力于成为首个在 EOS 区块链网络上运行的博彩娱乐场。代币通缩机制,通过分布式抽奖和智能合约每周销毁 XBL 代币。
  • Cards & Tokens.,可收藏的数字卡平台,用户可以上传内容并赚钱
  • Carmel.io,开源教育平台,可帮助有抱负和经验丰富的软件开发人员通过 token 化同行挑战来增长他们的技能并跟踪他们的成长
  • Chaince,专注 EOS 生态的区块链资产精品交易平台,支持糖果空投,主打严选项目,不收上币费
  • Chintai,Chintai 是一个由 EOS 节点候选者 EOS42 团队推出的 EOS 代币租赁平台,EOS 持币者就像是那些持有商业房产的投资客,而开发者是需要租用场地办公定期付租金的公司,双方各取所需,盘活了整个地产市场,而 Chintai 则是不收中介费的链家,这是一门相当有前景的生意
  • DEOS Games,赌场的边缘,赌场的平台
  • emanate,艺术家之间合作的音乐技术平台。 凭借智能合约,emanate 允许艺术家通过合作获利
  • EOS Bet,赌博系统,投资者可以支持房屋并获得股息
  • EOXCommerceA,分散的电子商务平台,允许使用基于 EOS 的加密货币和加密资产
  • EOSfinex,著名的交易所 Bitfinex 开发一个高性能、去中心化的交易所
  • EOS Gems,EOS 区块链上的收藏宝石游戏
  • Everipedia,一个众包的 wiki 平台,在线百科全书和知识库
  • HorusPay,分散的全球薪资门户网站,允许公司与国际薪资供应商交换私密的加密数据
  • HireVibes,一个众包型的去中心化求职招聘平台,解决中心化招聘平台收费高匹配度低的痛点
  • Insights Network,基于 EOS 的数据交易市场,用户可以直接出售他们的数据而不需要通过第三方
  • Karma,KARMA 旨在激励用户在世界上做得很好,并接受 KARMA 帮助人类
  • IRYO,去中心化的医疗数据,病人可以控制谁可以使用它并可以随身携带
  • Lab Ledger, A social media, crowdfunding website for scientists.
  • Onepay,帮助商家接收加密货币的支付钱包,传统的支付系统依靠中央银行和信贷机构,ONEPAY 的去中心化 POS 系统运行在 EOS 区块链上,只需付出一小部分成本即可闪电般交易
  • Oracle Chain,让世界与区块链互联
  • ONO,一个年轻人泛社交 App,定义了注意力价值,鼓励自由表达。目前社区已经初步形成
  • Plactal,Plactal 瞄准的是电子游戏市场。它通过收集每个玩家的信息做出分析,然后提供给游戏公司精准的广告投放信息
  • Scatter,用于保存身份和密钥安全的钱包。 项目的区块链部分是用于在应用程序和用户中建立信任
  • Sense,是一个 P2P 聊天机器人平台,便于任何两个用户通过各种不同的聊天工具实时对话,Sensay 利用人工智能匹配算法找出互相配对的用户
  • Seyara,一个开放的协议,以建立真正分散的点对点市场
  • SFEOS,玩家可以自己创建的,高沉浸式的体验游戏
  • Starteos,智能数字钱包,支持 EOS
  • Tokena,首个基于 EOS 的去中心化交易所
  • Trade Stuf,一个建立在 EOS 区块链上的高效,去中心化教育生态系统
  • TXT,支付观众的去中心化广告经济。 旨在激励观众观看所有人都获利的广告
  • Uncloak,将自己描述为世界上第一个基于区块链技术的网络威胁解决方案,通过一个完全自动化的区块链系统来解决网络威胁的弱点
  • Unico,去中心化数字收藏
  • Zimbra X,下一代 Zimbra 电子邮件和协作平台
  • EOS 超级矿工,EOS Asia 孵化的一款游戏:EOS 超级旷工,不发币,直接使用 EOS,奖池的 90% 左右的 EOS 全部返还给玩家,排行榜动态设计,保证后来的玩家的公平,总之我玩了几天感觉上手容易,既公平,也有趣味性,很快就上线,预约地址 http://eosminer.vip

参考:EOS dApp Ecosystem.

License

CC0

This list is released into the public domain.

SuperONE, robin

转载自 :https://github.com/superoneio/awesome-eos

eos系统合约介绍 — 提案合约eosio.msig (下)

简介

本篇将为大家介绍eosio.msig的源码实现,合约代码库详见:eosio.msig。eosio.msig主要有propose、approve、unapprove、cancel、exec、invalidate这几种方法,下面会详细逐一介绍每种方法的功能和实现细节。

主要合约方法

eosio.msig合约,在eosio.msig.hpp头文件中,主要定义了以下六个合约方法:

  • propose:提出提案
  • approve:通过提案
  • unapprove:不通过提案
  • cancel:取消提案
  • exec:执行提案
  • invalidate:撤回对之前所有该账户通过、但未被最终执行的提案的通过授权

eosio.msig合约头文件

namespace eosio {

   class multisig : public contract {
      public:
         multisig( account_name self ):contract(self){}

         void propose();
         void approve( account_name proposer, name proposal_name, permission_level level );
         void unapprove( account_name proposer, name proposal_name, permission_level level );
         void cancel( account_name proposer, name proposal_name, account_name canceler );
         void exec( account_name proposer, name proposal_name, account_name executer );
         void invalidate( account_name account );

propose方法

propose方法主要功能是提出提案,对应上篇提到的 cleos multisig propose 命令,传参如下:

  • proposer:提案账户
  • proposal_name:提案名
  • requested:提案通过所需权限
  • trx:提案具体执行的交易内容

为了节省资源开销,propose方法并不会根据 cleos multisig propose 传入的参数一一做解析,而是直接解析input data

/*
propose function manually parses input data (instead of taking parsed arguments from dispatcher)
because parsing data in the dispatcher uses too much CPU in case if proposed transaction is big

If we use dispatcher the function signature should be:

void multisig::propose( account_name proposer,
                        name proposal_name,
                        vector<permission_level> requested,
                        transaction  trx)
*/

void multisig::propose() {
   constexpr size_t max_stack_buffer_size = 512;
   size_t size = action_data_size();
   char* buffer = (char*)( max_stack_buffer_size < size ? malloc(size) : alloca(size) );
   read_action_data( buffer, size );

之后,会做一系列前置检验工作:proposer提案账户授权是否正确、交易是否超时、propose_name是否存在、提案通过所需权限是否正确等

require_auth( proposer );
   eosio_assert( trx_header.expiration >= eosio::time_point_sec(current_time_point()), "transaction expired" );
   //eosio_assert( trx_header.actions.size() > 0, "transaction must have at least one action" );

   proposals proptable( _self, proposer );
   eosio_assert( proptable.find( proposal_name ) == proptable.end(), "proposal with the same name exists" );

   bytes packed_requested = pack(requested);
   auto res = ::check_transaction_authorization( buffer+trx_pos, size-trx_pos,
                                                 (const char*)0, 0,
                                                 packed_requested.data(), packed_requested.size()
                                               );
   eosio_assert( res > 0, "transaction authorization failed" );

之后,将提案和提案合约的内容存表,将提案通过所需的权限存入requested_approvals表中,我们上篇文章所提到 cleos get table eosio.msig <proposer account> approvals 命令查询的就是这张表

proptable.emplace( proposer, [&]( auto& prop ) {
      prop.proposal_name       = proposal_name;
      prop.packed_transaction  = bytes( buffer+trx_pos, buffer+size );
   });

   approvals apptable(  _self, proposer );
   apptable.emplace( proposer, [&]( auto& a ) {
      a.proposal_name       = proposal_name;
      a.requested_approvals.reserve( requested.size() );
      for ( auto& level : requested ) {
         a.requested_approvals.push_back( approval{ level, time_point{ microseconds{0} } } );
      }
   });

approve方法

approve方法的主要功能是通过提案,对应上篇提到的 cleos multisig approve 命令,传参如下

  • proposer:提案人
  • proposal_name:提案名
  • permissions:使用哪个权限批准这个提案

首先,系统会查找提案合约内容,查找 requested_approvals 表中需要通过的权限中,是否有和传入permission匹配项。若有匹配项,将此权限加入 provided_approvals 表,即表示该权限通过此提案,并从 requested_approvals 表中移除该权限。

void multisig::approve( account_name proposer, name proposal_name, permission_level level ) {
   require_auth( level );

   approvals apptable(  _self, proposer );
   auto apps_it = apptable.find( proposal_name );
   if ( apps_it != apptable.end() ) {
      auto itr = std::find_if( apps_it->requested_approvals.begin(), apps_it->requested_approvals.end(), [&](const approval& a) { return a.level == level; } );
      eosio_assert( itr != apps_it->requested_approvals.end(), "approval is not on the list of requested approvals" );

      apptable.modify( apps_it, proposer, [&]( auto& a ) {
            a.provided_approvals.push_back( approval{ level, current_time_point() } );
            a.requested_approvals.erase( itr );
         });
   } else {
      old_approvals old_apptable(  _self, proposer );
      auto& apps = old_apptable.get( proposal_name, "proposal not found" );

      auto itr = std::find( apps.requested_approvals.begin(), apps.requested_approvals.end(), level );
      eosio_assert( itr != apps.requested_approvals.end(), "approval is not on the list of requested approvals" );

      old_apptable.modify( apps, proposer, [&]( auto& a ) {
            a.provided_approvals.push_back( level );
            a.requested_approvals.erase( itr );
         });
   }
}

unapprove方法

unapprove方法的主要功能是不通过提案,对应上篇提到的 cleos multisig unapprove 命令,传参如下:

  • proposer:提案人
  • proposal_name:提案名
  • permissions:使用哪个权限拒绝这个提案

首先,系统会查找提案合约内容,查找 provided_approvals 表中通过的权限中,是否有和传入permission匹配项。若有匹配项,将此权限加入requested_approvals 表,即表示该权限还没通过此提案,并从 provided_approvals 表中移除该权限。

void multisig::unapprove( account_name proposer, name proposal_name, permission_level level ) {
   require_auth( level );

   approvals apptable(  _self, proposer );
   auto apps_it = apptable.find( proposal_name );
   if ( apps_it != apptable.end() ) {
      auto itr = std::find_if( apps_it->provided_approvals.begin(), apps_it->provided_approvals.end(), [&](const approval& a) { return a.level == level; } );
      eosio_assert( itr != apps_it->provided_approvals.end(), "no approval previously granted" );
      apptable.modify( apps_it, proposer, [&]( auto& a ) {
            a.requested_approvals.push_back( approval{ level, current_time_point() } );
            a.provided_approvals.erase( itr );
         });
   } else {
      old_approvals old_apptable(  _self, proposer );
      auto& apps = old_apptable.get( proposal_name, "proposal not found" );
      auto itr = std::find( apps.provided_approvals.begin(), apps.provided_approvals.end(), level );
      eosio_assert( itr != apps.provided_approvals.end(), "no approval previously granted" );
      old_apptable.modify( apps, proposer, [&]( auto& a ) {
            a.requested_approvals.push_back( level );
            a.provided_approvals.erase( itr );
         });
   }
}

cancel方法

cancel方法的主要功能是取消提案,对应上篇提到的 cleos multisig cancel 命令,传参如下:

  • proposer:提案账户
  • proposal_name:提案名
  • canceler:取消账户

首先,先查找表获取提案内容。如果canceler账户和提案账户不同,则在提案交易过期之前,canceler都不能取消提案。若能取消,将提案从表中移除。

void multisig::cancel( account_name proposer, name proposal_name, account_name canceler ) {
   require_auth( canceler );

   proposals proptable( _self, proposer );
   auto& prop = proptable.get( proposal_name, "proposal not found" );

   if( canceler != proposer ) {
      eosio_assert( unpack<transaction_header>( prop.packed_transaction ).expiration < eosio::time_point_sec(current_time_point()), "cannot cancel until expiration" );
   }
   proptable.erase(prop);

   //remove from new table
   approvals apptable(  _self, proposer );
   auto apps_it = apptable.find( proposal_name );
   if ( apps_it != apptable.end() ) {
      apptable.erase(apps_it);
   } else {
      old_approvals old_apptable(  _self, proposer );
      auto apps_it = old_apptable.find( proposal_name );
      eosio_assert( apps_it != old_apptable.end(), "proposal not found" );
      old_apptable.erase(apps_it);
   }
}

exec方法

exec方法的主要功能是执行提案,对应上篇提到的 cleos multisig exec 命令,传参如下:

  • proposer:提案账户
  • proposal_name:提案名
  • executer:执行账户
void multisig::exec( account_name proposer, name proposal_name, account_name executer ) {
   require_auth( executer );

   proposals proptable( _self, proposer );
   auto& prop = proptable.get( proposal_name, "proposal not found" );
   transaction_header trx_header;
   datastream<const char*> ds( prop.packed_transaction.data(), prop.packed_transaction.size() );
   ds >> trx_header;
   //首先,需要做前置检查,检查交易是否过期
   eosio_assert( trx_header.expiration >= eosio::time_point_sec(current_time_point()), "transaction expired" );

   approvals apptable(  _self, proposer );
   auto apps_it = apptable.find( proposal_name );
   vector<permission_level> approvals;
   //然后,查 provided_approvals 表获取通过提案交易的权限们,对比 inv_table 表,如果权限不在 inv_table 表中或者 last_invalidation_time 
   //已经小于当前时间,代表权限有效,放入approvals表中。inv_table 表的用途在下一个invalidate方法中介绍
   invalidations inv_table( _self, _self );
   if ( apps_it != apptable.end() ) {
      approvals.reserve( apps_it->provided_approvals.size() );
      for ( auto& p : apps_it->provided_approvals ) {
         auto it = inv_table.find( p.level.actor );
         if ( it == inv_table.end() || it->last_invalidation_time < p.time ) {
            approvals.push_back(p.level);
         }
      }
      apptable.erase(apps_it);
   } else {
      old_approvals old_apptable(  _self, proposer );
      auto& apps = old_apptable.get( proposal_name, "proposal not found" );
      for ( auto& level : apps.provided_approvals ) {
         auto it = inv_table.find( level.actor );
         if ( it == inv_table.end() ) {
            approvals.push_back( level );
         }
      }
      old_apptable.erase(apps);
   }
   //最后,执行提案。如果交易执行权限检验无误,会发起一个defer延迟合约,去执行提案交易。如果执行成功,
   //`cleos get actions <executer account>` 会产生两条actions,一条是exec的交易,一条是提案执行的交易。
   bytes packed_provided_approvals = pack(approvals);
   auto res = ::check_transaction_authorization( prop.packed_transaction.data(), prop.packed_transaction.size(),
                                                 (const char*)0, 0,
                                                 packed_provided_approvals.data(), packed_provided_approvals.size()
                                                 );
   eosio_assert( res > 0, "transaction authorization failed" );

   send_deferred( (uint128_t(proposer) << 64) | proposal_name, executer, prop.packed_transaction.data(), prop.packed_transaction.size() );

   proptable.erase(prop);
}

invalidate方法

invalidate方法的主要功能是:如果account之前通过的提案还未执行,就可以使用该方法将提案一键设置为无效。这个方法主要是解决:账户权限变更时,之前通过但未执行的提案一旦执行会盗取账户权限的问题,详见issue。该方法传参如下:

  • account:提案的批准账户

该功能的实现非常简单,首先,inv_table 是用来存放权限的,它的两个字段 account 和last_invalidation_time 分别是账户名和账户权限最近失效时间。last_invalidation_time 时间之前,account的提案批准权限都不可用,在该时间之后account的提案批准权限才能生效。

因此,如果想使account之前审批通过的所有提案都失效的话,就将 last_invalidation_time 设置为当前时间即可。exec方法在执行之前会检查 inv_table,则包含在 inv_table 中的account,即便批准了该提案,该批准也会作废

void multisig::invalidate( account_name account ) {
   require_auth( account );
   invalidations inv_table( _self, _self );
   auto it = inv_table.find( account );
   if ( it == inv_table.end() ) {
      inv_table.emplace( account, [&](auto& i) {
            i.account = account;
            i.last_invalidation_time = current_time_point();
         });
   } else {
      inv_table.modify( it, account, [&](auto& i) {
            i.last_invalidation_time = current_time_point();
         });
   }
}

转载自简书

EOSIO cleos命令汇总

version返回版本信息

返回EOS客户端版本信息

$cleos version client
Build version: cc9decff

create在区块链上和区域外创建数据

create key 创建密钥

命令格式:$ cleos create key
为了创建一个帐户,你需要两个新的密钥:所有者和激活密钥。你可以要求cleos为你创建一些钥匙:
这将是你的Owner Key,

$ cleos create key --to-console
Private key: 5HtimtY36YN8mB5MRKh2FDkdtUg98dZ5HrnC9hhCkf5KsZvXR11
Public key: EOS86qf6z2CuNfYDADMMysy2Gfs6p3GVK5k71BbGovmtmkBwvMxPq

再次执行,生成active key

$ cleos create key --to-console
Private key: 5K4SVxGkSrUWJVSsxtyJx7nqwVoNwgEZ77KxwVXaB2yzCf2ri3q
Public key: EOS5aC4xP3rf1sJVfNudJaa4CikUpmAYqXuiCxfL8nQT3tFDys9X1

注意:cleos不会把生成的私钥自动导入钱包,需手动导入cleos wallet import

create account 创建账号

命令格式:$ cleos create account ${control_account} ${account_name} ${owner_public_key} ${active_public_key}

Usage: ./cleos create account [OPTIONS] creator name OwnerKey ActiveKey

Positionals:
  creator TEXT                创建新帐户的帐户的名称
  name TEXT                   新帐户的名称
  OwnerKey TEXT               新帐户的所有者公钥
  ActiveKey TEXT              新帐户的激活公钥

Options:
  -x,--expiration             在交易到期之前以秒为单位设置时间,默认值为30s。
  -f,--force-unique           强制使交易独一无二,这将消耗额外的带宽,并消除对多次发布同一交易的任何保护。
  -s,--skip-sign              指定未锁定钱包密钥是否用于签署交易。即跳过签署直接交易。
  -d,--dont-broadcast         不要向网络广播交易(只需打印到stdout)。
  -p,--permission TEXT ...    授权的帐户和权限级别,如“帐户@权限”(默认值'creator@active')

待续

怎么给超级节点发工资:EOS的奖励分配规则

最近几篇文章,持续在聊EOS的资源分配模型。今天节后上班第一天,我们来聊个五块钱的天,看看EOS节点的收入问题:收益有多少,是怎么计算出的。

当下一次有人问你,EOS的通胀比率是多少,节点的奖励比例是多少,怎么分配的时候,也许这篇文章可以帮你回答这些问题。

主要用到的网站:

超级节点/备用节点/BP是什么?

在许多文章里面你会看到BP这一缩写。这是Block Producer的简称,即出块节点。

实际上,超级节点,这是中文里面才会有的称呼,似乎不加上超级,就显得不够霸气似的。英文语境里面,只是称呼EOS的节点为BP(Block Producer)。

节点分为两类:出块节点,跟备用节点(Block Producer Candidate)。在EOS主网之中,现在是设定为前21个节点为出块节点,其他的节点为备用节点。

备用节点也有另外的名称,叫做候选节点,两个名字都是说的同一回事。

你如果愿意,也可以调用EOS的命令,将自己启动的节点注册为节点,只是,未必有收益罢了。

节点收益知多少?

通过https://eos.host/mainnet这一网络,可以非常直观的查看各个节点的收益情况。

上图列出了前30个节点的得票率占比,橙色为出块节点,灰色为备用节点。

21个出块节点的收益


通过第二张图,可以看到,有一栏是列出来了节点的预估收益。

我们再仔细看一下。排名第一的佳能节点(恭喜佳能!),总计出块34895,预估得到收益为: 1,248.86 EOS

备用节点的收益


除了出块节点之外,也有部分备用节点是有收益的。从图中可以看出来,排名59的备选节点hexlantttttt,预计也能够得到100多的EOS作为回报。

你可能会好奇:出块节点的收益跟备用节点的收益是怎么算的呢?我们从EOS的增发开始说起。

算算节点的收益分配

分配的流程
每次有节点发起指令要领取奖励的时候,系统会计算:

  • 新增发的EOS总数有多少;
  • 按照比例,将新增发的EOS分配到不同的奖励池之中(下文会详述);
  • 按照节点的实际情况,计算节点应该得到的收益,并分配这部分收益给节点;
  • 对于备用节点来说,如果领取的奖励不足100个EOS,则无法领取奖励。
    简单概括就是,先计算各部分奖励池应该分配多少EOS,即新注入多少EOS;然后,根据规则,分配这部分新增的奖励,分配给对应的人节点。

EOS通胀率为5%

EOS是温和通胀设计的系统,每年增发的EOS比率为5%左右,按照总供应量10亿来计算,就是五千万EOS。
而节点得到的奖励,只是通胀的一小部分,只是总EOS数量的1%。

新增EOS的用途

实际上,EOS的增发,是持续进行的,而并非是每年一次性新增加EOS。每次EOS的节点发起领取奖励的命令,就会计算新增EOS的量。

通胀的EOS,有两个用途:

  • 通胀EOS的20%, 用于给节点的奖励,即,如果新增了五千万EOS,那么会有1千万EOS分配给节点作为奖励,包括给出块节点和备用节点;
  • 通胀EOS的80%, 用于EOS基金池,这部分会在未来用于Worker Proposal的奖励发放。所谓的Worker Proposal,是指的社区福利应用或者对EOS系统有所帮助的项目。

Worker Proposal这部分的奖励,现在已经开始累积,但是没有发放。

后续会部署新的智能合约到系统之中,经过持票人投票选出来认为对社区有益的DAPP,来获得这部分奖金。

可以看得出来,EOS设计之中对于生态的重视,Worker Proposal(可以称为:工作提案?)这部分每年足足有四千万左右的EOS奖励。(此处进行了简化,实际上随着EOS通胀,奖励的EOS数量会越来越多,比率为总流通量的4%)

如果你觉得自己的创意够牛逼,对于推动社区进步有贡献,那后续,光凭藉Worker Proposal的这部分奖励,应该就足够你赚到钱的了。

出块节点和备用节点的收益

具体的节点奖励的这1%,分为两部分:出块奖励(0.25%)和得票奖励(0.75%)。

出块奖励只是分配给出块的前21个节点,而得票奖励呢,则是用作所有节点(包括出块节点和备用节点)的奖励。

  • 出块奖励占据EOS总量的0.25%,这部分前21个节点平分。
    假设总量是10亿,那么,出块奖励部分,则是两百五十万 EOS,这部分21个节点平分。
  • 得票奖励, 占0.75%,这部分由所有节点按照投票权重占比来分配的。

例如,在某个时刻,如果未分配的得票奖励部分是一万2千个EOS,那么,假设 EOS Cannon节点的投票权重比例为10%,则佳能可以分得10%的奖励,即两千五百个EOS。

另外,佳能作为出块节点,还可以因为出块得到奖励。
假设未分配的出块奖励为两千一百个EOS,那么,佳能得到的奖励就是一百个,因为出块奖励是21个节点平分的。

总结

  • 如果某个节点是前21个节点之一,那么,其奖励分为:出块奖励部分 + 得票奖励部分;
  • 如果某个节点是备用节点,那么,它可能得到的收益属于得票奖励之中的一部分,比如总共投票权重为100,该节点所得到的投票权重为5,则可以分到得票奖励的5%。
  • 如果某个备用节点的得票奖励不足100个EOS,则无法得到奖励。

转载自:https://www.jianshu.com/p/8fb3531d055c