[EOS源码分析]6.EOS特殊智能合约eosio

article/2025/9/12 22:30:38

    这里说的eosio智能合约不是泛指eos的智能合约,它是一个特殊的具体的合约。它本事可大了,我们一起来看看它有哪些功能

负责智能合约部署

    大家有注意到如下红色字体的log吗

$ cleos set contract hello.code ../eos-contract/hello -p hello.code

Publishing contract...

executed transaction: daabe65267af4b9a11e5ff90a165bbaac68469630f499bcea1ef0eb7da6d970c  1792 bytes  2558 us

#         eosio <= eosio::setcode               {"account":"hello.code","vmtype":0,"vmversion":0,"code":"0061736d01000000013b0c60027f7e006000017e600...

#         eosio <= eosio::setabi                {"account":"hello.code","abi":"00010c6163636f756e745f6e616d65046e616d6501026869000104757365720c61636...

 

这段log很明显的说明了

$ cleos set contract eosio build/contracts/eosio.bios -p eosio

    等价于调用eosio智能合约的setcode和setabi函数

$ cleos push action eosio setcode '[eosio.bios.wasm]' -p eosio

$ cleos push action eosio setabi eosio '[eosio.bios.abi] -p eosio

    也就说合约部署是通过调用eosio合约来实现的

    对应的源码:

        set contract会产生setcode和setabi两个action

   add_standard_transaction_options(contractSubcommand, "account@active");

   add_standard_transaction_options(codeSubcommand, "account@active");

   add_standard_transaction_options(abiSubcommand, "account@active");

   contractSubcommand->set_callback([&] {

      shouldSend = false;

      set_code_callback();

      set_abi_callback();

      std::cout << localized("Publishing contract...") << std::endl;

      send_actions(std::move(actions), 10000, packed_transaction::zlib);

   });

chain::action create_setcode(const name& account, const bytes& code) {

   return action {

      tx_permission.empty() ? vector<chain::permission_level>{{account,config::active_name}} : get_account_permissions(tx_permission),

      setcode{

         .account   = account,

         .vmtype    = 0,

         .vmversion = 0,

         .code      = code

      }

   };

}

struct setcode {

   account_name                     account;

   uint8_t                          vmtype = 0;

   uint8_t                          vmversion = 0;

   bytes                            code;

 

   static account_name get_account() {

      return config::system_account_name;

   }

   static action_name get_name() {

      return N(setcode);

   }

};

const static uint64_t system_account_name    = N(eosio);

    set_code和set_abi都是通过调用system_account_name即eosio智能合约来执行的


负责账号创建

    同样我们看看create account,其实就是调用eosio合约的newaccount函数

$ cleos create account eosio hello.code EOS7KBTMkUq4VPakqsZUnZfBbMbS2U7cn9qSa3q6G5ZzEeUeNSVgv EOS7KBTMkUq4VPakqsZUnZfBbMbS2U7cn9qSa3q6G5ZzEeUeNSVgv

executed transaction: 01aff4356a6277eec777494fc6aeaf97164c53997c46fe853247ed7e100f4987  200 bytes  911 us

#         eosio <= eosio::newaccount            {"creator":"eosio","name":"hello.code","owner":{"threshold":1,"keys":[{"key":"EOS7KBTMkUq4VPakqsZUnZ...

    


负责权限管理

    这次是调用eosio的updateauth函数

$ cleos set account permission testaccount active '{"threshold" : 1, "keys" : [], "accounts" : [{"permission":{"actor":"bob","permission":"active"},"weight":1}, {"permission":{"actor":"stacy","permission":"active"},"weight":1}]}’ owner

executed transaction: b1bc9680a9ba615a6de8c3f7c692d7d28ff97edae245bb40f948692b14ea6c15  160 bytes  189 us

#         eosio <= eosio::updateauth            {"account":"testaccount","permission":"active","parent":"owner","auth":{"threshold":1,"keys":[],"acc...

warning: transaction executed locally, but may not be confirmed by the network yet

 

蛋生鸡,鸡生蛋问题

    既然eosio是一个智能合约,而它又负责合约部署,那它自己是谁部署的呢?我们先来看下这个结构图

    eosio contract负责系统服务,比如部署合约,创建账号。infra contracts层比如eosio.token和eosio.msig类似库作用的合约,比如多签名,发行代币,方便dapp层使用。Dapp才是用户直接接触的,每个开发人员编写程序然后部署,这些程序都是DApp。

    eosio contract由3个部分构成

  1. nativeaction

      nativeactions就是前面提到的setcode, setabi, newaccount功能的函数集。这部分代码是hardcode在EOS系统代码里的,也就说不需要部署这一步骤,所以就解决了蛋生鸡,鸡生蛋问题。

   2.  eosio.bios, eosio.system

        eosio.bios是一个智能合约的代码,是通过智能合约部署方式绑定到eosio contract上的。那你可能会说,eosio.bios部署后,nativeactions部分是不是就失效了啊。确实可以这样实现,由于setcode这些action需要永久生效,这就需要eosio.bios包含nativeactions这些函数,这样就出现了相同一份代码分散在两个模块,独立性和维护不够好。所以,目前的实现是通过特殊处理让nativeactions的函数有最高优先级,永不覆盖,哪怕eosio.bios实现了同样的函数(比如set_code, set_abi)。但是eosio.system和eosio.bios是一个级别的,都是contract,  是水火不相容的,一旦将eosio.system绑定到eosio这个账号,eosio.bios就失效了,所以eosio.bios的函数要么是临时用途的,要么就需要bios.system重新实现,比如setalimits会失效,而setpriv会在eosio.system重新实现。这个和cpu启动一样,一开始bios(bootloader)代码运行,然后引导system代码,当system加载后,bios(bootloader)代码失效。所以从这个设计和名字可以看出,EOS确实是在按照操作系统的逻辑设计

eosio.bios的接口

EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) )

eosio.sytem的接口

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)

//this file

(setpriv)

)

 

nativeaction解读

nativeaction注册

    nativeaction是通过SET_APP_HANDLER注册的

#define SET_APP_HANDLER( receiver, contract, action) \

   set_apply_handler( #receiver, #contract, #action, &BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) )

 

   SET_APP_HANDLER( eosio, eosio, newaccount );

   SET_APP_HANDLER( eosio, eosio, setcode );

   SET_APP_HANDLER( eosio, eosio, setabi );

   SET_APP_HANDLER( eosio, eosio, updateauth );

   SET_APP_HANDLER( eosio, eosio, deleteauth );

   SET_APP_HANDLER( eosio, eosio, linkauth );

   SET_APP_HANDLER( eosio, eosio, unlinkauth );

/*

   SET_APP_HANDLER( eosio, eosio, postrecovery );

   SET_APP_HANDLER( eosio, eosio, passrecovery );

   SET_APP_HANDLER( eosio, eosio, vetorecovery );

*/

 

   SET_APP_HANDLER( eosio, eosio, canceldelay );

   void set_apply_handler( account_name receiver, account_name contract, action_name action, apply_handler v ) {

      apply_handlers[receiver][make_pair(contract,action)] = v;

   }

    

对应的函数名是apply_eosio_xxx,比如apply_eosio_setcode,apply_eosio_newaccount

nativeaction函数调用

    系统会先检测action的名字是否注册在native handler里,如果在则直接调用,不在的话,执行合约代码,并跳转到相应的action函数

 

class apply_context { 

    { 

    public:

      apply_context(controller& con, transaction_context& trx_ctx, const action& a, uint32_t depth=0)

      :control(con)

      ,db(con.db())

      ,trx_context(trx_ctx)

      ,act(a)

      //合约的账号

      ,receiver(act.account)

      ,used_authorizations(act.authorization.size(), false)

}

 

action_trace apply_context::exec_one()

{

   auto start = fc::time_point::now();

 

   const auto& cfg = control.get_global_properties().configuration;

   try {

      //获取智能合约对象

      const auto &a = control.get_account(receiver);

      privileged = a.privileged;

      //检测该action是否是native action,如果是则调用native handler

      auto native = control.find_apply_handler(receiver, act.account, act.name);

      if (native) {

         //hative handler(action)存在,则调用

         (*native)(*this);

      }

      //只要不是setcode调用,允许nativehandler和contract部署的代码都执行

      if( a.code.size() > 0

          && !(act.account == config::system_account_name && act.name == N(setcode) && receiver == config::system_account_name) ) {

         try {

            control.get_wasm_interface().apply(a.code_version, a.code, *this);

         } catch ( const wasm_exit& ){}

      }

     ….

 

   } FC_CAPTURE_AND_RETHROW((_pending_console_output.str()));

}

 

/********************************

* 本文来自CSDN博主"爱踢门"

* 转载请标明出处:http://blog.csdn.net/itleaks

******************************************/

如果你对EOS,ETH技术及开发感兴趣,请入QQ群讨论: 829789117


如需实时查看最新文章,请关注公众号"区块链斜杠青年",一起探索区块链未来


http://chatgpt.dhexx.cn/article/uSHWafcQ.shtml

相关文章

EOS智能合约开发(一)

一、 智能合约功能二、 通讯模式 2.1 运行机制2.2 内联通信2.3 延迟通信2.4 交易和动作2.5 交易确认2.6 动作处理程序和动作的apply上下文2.7 交易限制 三、文件结构 3.1 创建框架3.2 apply处理程序3.3 EOSIO_ABI 宏 四、多索引数据库API 4.1 EOSIO多索引API4.2 EOSIO多索引迭代…

EOS系列 - WASM智能合约 - 特性

构造函数 addressbook(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds) {}#单例表&#xff08;code和scope都用receiver的表&#xff09;也可在初始化列表中实例化 singleton_example( name receiver, name code, datastream<c…

EOS智能合约开发(十五)EOS 状态机架构解析

好久没有写文章了&#xff0c;最近公司事情比较忙。非常感谢上次杭州团队一位负责EOS状态机的同事精彩分享。今天查阅很多资料后&#xff0c;整理这篇文章&#xff0c;希望对大家有所帮助。 EOS状态机是什么&#xff1f; 简单讲就是数据库&#xff0c;是EOS记录智能合约执行结…

接口测试时,输入所有参数的参数值后,接口返回“参数错误:所有参数都不能为空”

问题原因&#xff1a; 参数名称输入有误&#xff0c;前台&#xff08;pwd&#xff09;和后台&#xff08;password&#xff09;的参数名称不一致 &#xff0c;保持一致后即可

matlab 错误使用 connector.internal.autostart.run输入参数的数目不足。

matlab打开后提示&#xff1a; 错误使用 connector.internal.autostart.run输入参数的数目不足 原因&#xff1a;自己写的一个函数和matlab自带的函数重名了 参考&#xff1a;警告: 在 matlabrc 中初始化 Java 首选项失败 – MATLAB中文论坛MATLAB中文论坛MATLAB 基础讨论板块…

Matlab 自带遗传算法函数 ga() 运行报错:“ fitnessfcn() 输入参数的数目不足。”

原始程序 %主程序 m [1 2]; R [1.5 1]; epsilon [2^R(1)-1 2^R(2) - 1]; A [-1 epsilon(1); 0 -1]; b [0 0]; Aeq [1 1]; Beq 1;%matlab自带函数包 [x_optimal, fval] ga(fitnessfcn, 2, A, b, Aeq, Beq, [0;0], [1;1], []); ---------------------------------…

matlab函数参数不足,调用函数显示输入参数不足

问题描述.png (29.7 KB, 下载次数: 1) 2015-1-27 09:34 上传 %Gauss-Newton算法实现如下 function[x,minf] = GN(f,x0,var,eps)formatlong; ifnargin == 3 %如果没有设置eps,则eps=1.0e-6eps = 1.0e-6; end m = 0; S =transpose(f)*f; %trnspose是转…

matlab 函数不定参数,matlab function定义一个函数,但一直出来说输入参数数目不足。我用的是2014版本,不知道数目原因啊?...

www.mh456.com防采集。 h 5;g 1; % g取源0有问题% 被积函数2113可以化5261简成f 4102(a,b,r)(r*h-r^16532*cos(a-b))/(h^2r^2g^2-2*h*r*cos(a-b))^1.5;% 求积分quadv((r)quadv((b)quadv((a)f(a,b,r), 0, 2*pi), 0, 2*pi), 0, h) 错误在于&#xff0c;调用函数f( x )缺一个…

matlab plot输入参数太多,输入参数太多问题

版本&#xff1a;R2016a 利用SCE-UA调用新安江模型进行率定时&#xff0c;显示参数太多&#xff0c;求大神指导。 clear; clc; spathcd P0(textread([spath,\matlabxingshanjiangyu.txt])); PP0(2,:);%降水量(mm) EI0(textread([spath,\matlabxingshanzhengfa.txt])); EIEI0(2,…

参数输入太多

参数输入太多 在向platEMO平台添加新的算法时&#xff0c;可能会出现参数输入太多的错误提示 可能是由于输入的参数内包含逗号&#xff0c;比如 a[1,2],b[3,4] 从而造成”输入参数太多“的错误提示。

MATLAB S-function(教程分享) 报错 flag = 3(output), at time 0.0. 输入参数的数目不足。

前言 从上周开始用S-function做仿真&#xff0c;之前已经学过的&#xff0c;我觉得很好的教程网址是 【0基础直接带你上手matlab simulink仿真&#xff08;不是标题党&#xff0c;讲解超级细致用心&#xff09;&#xff08;非线性系统自适应控制器的搭建&#xff09;】 https…

matlab报错“输入参数的数目不足”

图片源自下方链接 原文链接MATLAB中出现参数数目不足的错误提示 - 爱上对方过后就哭了忆 - 博客园 (cnblogs.com)

错误使用 max 输入参数的数目不足。

相比大多数人熟悉的在调用自己编写的函数时出现的 “输入参数的数目不足” 问题&#xff0c;该情况下&#xff08;即在同一脚本或同一函数中&#xff09;也会出现matlab内部函数调用问题&#xff08;如max、min等&#xff09;&#xff0c;在编程时应注意此点&#xff01;

Matlab运行自定义函数显示“输入参数的数目不足”

问题描述 很多初学者在刚开始学习使用Matlab自定义函数时&#xff0c;可能遇到程序上没有问题&#xff0c;但一运行就显示输入参数的数目不足这个问题。 比如自定义一个函数&#xff1a;查找最小的m&#xff0c;使得m满足12…m > k&#xff08;k为任意一个整数&#xff09;…

浏览器播放视频倍速方法

1.右击播放页面 2.选择检查 4.选择console&#xff0c;如图&#xff1a; 5.在下面输入 &#xff1a;videojs.getPlayers("video-player").html5player.tech_.setPlaybackRate(1.5)&#xff0c;括号里的数字就是要加倍的倍速。

浏览器播放RTSP

浏览器播放RTSP 由于现在浏览器不直接支持RTSP&#xff0c;然后很多监控厂商如海康大华等又不提供RTMP的情况下&#xff0c;项目需要实现HTML中播放监控视频。之前做过转流的方案&#xff0c;在服务器中把RTSP转成RTMP&#xff0c;这种方案开发量大而且转码不稳定&#xff0c;…

0516---win10 chrome 浏览器播放视频没有声音的解决办法

win10 chrome 浏览器播放视频没有声音的解决办法 近期我的Win10 主机在使用 Chrome 浏览器播放搜狐视频的时候没有声音&#xff0c;而用 Edge浏览器播放同一视频就一切正常&#xff0c;初步判断是浏览器的设置引起的。通过以下操作步骤得以解决。 启动 chrome 浏览器&#xf…

html5播放mp4不见画面,浏览器播放mp4格式视频时只有声音看不到画面的原因及解决方法(精)...

做HTML5网页&#xff0c;要播放视频&#xff0c;视频格式为mp4&#xff0c;结果浏览器只能听到声音&#xff0c;看不到画面。 反复测试&#xff0c;多个浏览器均出现此问题。刚开始以为视频的格式不对&#xff0c;我是从MOV转的MP4格式&#xff0c;反复确认嵌入的视频确实是mp4…

360浏览器html5无法播放,win7系统360浏览器播放不了视频的解决方法

今天和大家分享一下win7系统360浏览器播放不了视频问题的解决方法&#xff0c;在使用win7系统的过程中经常不知道如何去解决win7系统360浏览器播放不了视频的问题&#xff0c;有什么好的办法去解决win7系统360浏览器播放不了视频呢&#xff1f;小编教你只需要 1、视频无法正常…