這篇文章早早就寫好了,但是最近工作特別忙锨阿,一直沒有潤色宵睦,所以就沒更新。而且墅诡,EOS Dawn 4.0 也發(fā)布了壳嚎,感覺研究不過來了。末早。烟馅。。
合約開發(fā)一些小思考
熟悉合約的開發(fā)之后然磷,其實可以發(fā)現(xiàn)郑趁,合約的編寫本身比較“簡單”;因為合約開發(fā)講究實現(xiàn)功能:邏輯實現(xiàn)簡單姿搜、復雜合約盡量拆分寡润、抱著安全。
習慣各種復雜業(yè)務邏輯的開發(fā)者舅柜,肯定感覺合約寫起來很簡單梭纹。但是,這也是另一種“復雜”致份;因為你要在一個有限功能变抽、有限存儲、節(jié)約資源的框架下,實現(xiàn)你想實現(xiàn)的功能绍载,想想其實挺有挑戰(zhàn)的O(∩_∩)O
稍微說了點想法太伊,還是快點開始正題吧!
智能合約之間的調用
這個之前在以太坊一些小問題中說過逛钻,為了讓智能合約能夠更新僚焦,最好是邏輯、數(shù)據(jù)業(yè)務分開在不懂合約中曙痘,然后用邏輯合約調用數(shù)據(jù)合約芳悲;雖然EOS的智能合約沒有這方面問題,但是边坤,合約間調用還是少不了的名扛。EOS中合約的調用,主要的實現(xiàn)就是靠函數(shù):
//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();
}
從入?yún)⒓胙鳎湍艽篌w看出如何使用了:
- code:合約名稱肮韧;
- act:action的名稱;
- perms:授權信息旺订,格式如下:
permission_level( account_name a, permission_name p )
比如level{tester, N(active)}
弄企; - args:action的入?yún)ⅲY構使用的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,這章中乞而,我們實現(xiàn)了一個簡單的用戶上傳博客的功能送悔,然后審核員能夠審核用戶的文章是否有敏感信息;
比較符合區(qū)塊鏈開發(fā)思路的方式晦闰,既然用戶上傳知識放祟、審核員審核文章鳍怨,這都是工作量呻右,那就要給用戶和審核員一些利益,好讓用戶多過來上傳文章鞋喇,壯大我們的區(qū)塊鏈合約声滥;我們就可以在審核員審核通過后,自動的使用合約給用戶和審核員發(fā)送token獎勵;
也就是在approved函數(shù)中落塑,添加獎勵功能纽疟;
首先假設,使用eosio.token合約憾赁,發(fā)布了token “BLOG幣”污朽,并使用issue發(fā)行給合約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,這語句是合約中最最簡單的調用方式晦款,參數(shù)詳解:
- eosio::token(N(eosio.token)) 前面是eosio.token頭文件中定義的結構炎功,然后傳入的參數(shù),是該合約上傳的賬戶缓溅;
- transfer 即需要調用的方法蛇损;
- {_self,N(active)} 本次交易,需要的權限坛怪;
- 后面的參數(shù)淤齐,就是本次action需要的所有參數(shù);
當然袜匿,實現(xiàn)的內部調用的方法床玻,還是很多種形式,比如action().send()沉帮、dispatch_inline()锈死、INLINE_ACTION_SENDER等等,其實最根本的穆壕,還是action.send()待牵,其他所有方法都是對該方法的封裝。
PS:合約間調用喇勋,還有一個比較嚴重的問題缨该,就是目前合約調用的權限簽名,只支持調用合約的簽名川背。比如合約A贰拿,調用合約B的action,假設為transfer熄云,transfer需要驗證發(fā)送者權限膨更,則只能驗證合約A的權限。假如缴允,用戶h荚守,調用A合約,A合約調用B合約的transfer,則只能有合約B矗漾,本身發(fā)出轉賬锈候,用h用戶的賬戶發(fā)出轉賬是不行的。。。挺繞的尖飞。
比如上面的例子杉编,只能是_self本身發(fā)出轉賬,任何其他賬戶都不行。
期望在4.0改進吧,不然限制太大。