EOS智能合约 -- 合约交互

这篇文章早早就写好了,但是最近工作特别忙,一直没有润色,所以就没更新。而且,EOS Dawn 4.0 也发布了,感觉研究不过来了。。。。

合约开发一些小思考

熟悉合约的开发之后,其实可以发现,合约的编写本身比较“简单”;因为合约开发讲究实现功能:逻辑实现简单、复杂合约尽量拆分、抱着安全。

习惯各种复杂业务逻辑的开发者,肯定感觉合约写起来很简单。但是,这也是另一种“复杂”;因为你要在一个有限功能、有限存储、节约资源的框架下,实现你想实现的功能,想想其实挺有挑战的O(∩_∩)O

稍微说了点想法,还是快点开始正题吧!

智能合约之间的调用

这个之前在以太坊一些小问题中说过,为了让智能合约能够更新,最好是逻辑、数据业务分开在不懂合约中,然后用逻辑合约调用数据合约;虽然EOS的智能合约没有这方面问题,但是,合约间调用还是少不了的。EOS中合约的调用,主要的实现就是靠函数:

//file: contracts/eosiolib/action.h

template<typename... Args>
   void dispatch_inline( account_name code, action_name act,
                         vector<permission_level> perms,
                         std::tuple<Args...> args ) {
      action( perms, code, act, std::move(args) ).send();
   }

从入参,就能大体看出如何使用了:

  • code:合约名称;
  • act:action的名称;
  • perms:授权信息,格式如下:
    permission_level( account_name a, permission_name p )
    比如 level{tester, N(active)}
  • args:action的入参,结构使用的C++的tuple;

这是,比如麻烦的调用,程序也提供了比较方面的使用方式,如下的宏定义:

#define INLINE_ACTION_SENDER3( CONTRACT_CLASS, FUNCTION_NAME, ACTION_NAME  )\
::eosio::inline_dispatcher<decltype(&CONTRACT_CLASS::FUNCTION_NAME), ACTION_NAME>::call

#define INLINE_ACTION_SENDER2( CONTRACT_CLASS, NAME )\
INLINE_ACTION_SENDER3( CONTRACT_CLASS, NAME, ::eosio::string_to_name(#NAME) )

#define INLINE_ACTION_SENDER(...) BOOST_PP_OVERLOAD(INLINE_ACTION_SENDER,__VA_ARGS__)(__VA_ARGS__)

#define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\
INLINE_ACTION_SENDER(std::decay_t<decltype(CONTRACT)>, NAME)( (CONTRACT).get_self(),\
BOOST_PP_TUPLE_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)) );

至于,如何使用呢,我们接下来用个例子。

调用例子

我们就用前面一章中的例子来展示如何调用,blog_view,这章中,我们实现了一个简单的用户上传博客的功能,然后审核员能够审核用户的文章是否有敏感信息
比较符合区块链开发思路的方式,既然用户上传知识、审核员审核文章,这都是工作量,那就要给用户和审核员一些利益,好让用户多过来上传文章,壮大我们的区块链合约;我们就可以在审核员审核通过后,自动的使用合约给用户和审核员发送token奖励;

也就是在approved函数中,添加奖励功能;
首先假设,使用eosio.token合约,发布了token “BLOG币”,并使用issue发行给合约blog.view一定量的币;

///注意要include eosio.token的头文件
/// @abi action
        void approved(const uint64_t ID) {

            auto itrid = idlists.find(ID);
            eosio_assert(itrid != idlists.end(), "this blog doesn't exists!\n");
            blog_index approve_blogs(_self, itrid->producer);

            auto itr = approve_blogs.find( ID );
            eosio_assert(itr != approve_blogs.end(), "this blog doesn't exists!\n");
            eosio_assert(itr->status == Status::s_reviewing, "this blog is reviewed!\n");
            require_auth(itr->reviewer);
            
            approve_blogs.modify(itr, itrid->producer, [&](auto& g){
                g.status = Status::s_approved;
                g.approve_status = std::string("approved");
            });
            //审核通过后,给予奖励
            SEND_INLINE_ACTION( eosio::token(N(eosio.token)), transfer, {_self,N(active)}, { _self, producer, itrid->producer, "reward"} );
        }

可以看到,最后一个语句就是调用的其他合约 eosio.token,这语句是合约中最最简单的调用方式,参数详解:

  • eosio::token(N(eosio.token)) 前面是eosio.token头文件中定义的结构,然后传入的参数,是该合约上传的账户;
  • transfer 即需要调用的方法;
  • {_self,N(active)} 本次交易,需要的权限;
  • 后面的参数,就是本次action需要的所有参数;

当然,实现的内部调用的方法,还是很多种形式,比如action().send()、dispatch_inline()、INLINE_ACTION_SENDER等等,其实最根本的,还是action.send(),其他所有方法都是对该方法的封装。

PS:合约间调用,还有一个比较严重的问题,就是目前合约调用的权限签名,只支持调用合约的签名。比如合约A,调用合约B的action,假设为transfer,transfer需要验证发送者权限,则只能验证合约A的权限。假如,用户h,调用A合约,A合约调用B合约的transfer,则只能有合约B,本身发出转账,用h用户的账户发出转账是不行的。。。挺绕的。
比如上面的例子,只能是_self本身发出转账,任何其他账户都不行。
期望在4.0改进吧,不然限制太大。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容