這篇文章早早就寫好了,但是最近工作特別忙,一直沒有潤色,所以就沒更新。而且,EOS Dawn 4.0 也發(fā)布了,感覺研究不過來了。。。。
合約開發(fā)一些小思考
熟悉合約的開發(fā)之后,其實可以發(fā)現(xiàn),合約的編寫本身比較“簡單”;因為合約開發(fā)講究實現(xiàn)功能:邏輯實現(xiàn)簡單、復(fù)雜合約盡量拆分、抱著安全。
習(xí)慣各種復(fù)雜業(yè)務(wù)邏輯的開發(fā)者,肯定感覺合約寫起來很簡單。但是,這也是另一種“復(fù)雜”;因為你要在一個有限功能、有限存儲、節(jié)約資源的框架下,實現(xiàn)你想實現(xiàn)的功能,想想其實挺有挑戰(zhàn)的O(∩_∩)O
稍微說了點想法,還是快點開始正題吧!
智能合約之間的調(diào)用
這個之前在以太坊一些小問題中說過,為了讓智能合約能夠更新,最好是邏輯、數(shù)據(jù)業(yè)務(wù)分開在不懂合約中,然后用邏輯合約調(diào)用數(shù)據(jù)合約;雖然EOS的智能合約沒有這方面問題,但是,合約間調(diào)用還是少不了的。EOS中合約的調(diào)用,主要的實現(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:授權(quán)信息,格式如下:
permission_level( account_name a, permission_name p )
比如level{tester, N(active)}; - args:action的入?yún)ⅲY(jié)構(gòu)使用的C++的tuple;
這是,比如麻煩的調(diào)用,程序也提供了比較方面的使用方式,如下的宏定義:
#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__)) );
至于,如何使用呢,我們接下來用個例子。
調(diào)用例子
我們就用前面一章中的例子來展示如何調(diào)用,blog_view,這章中,我們實現(xiàn)了一個簡單的用戶上傳博客的功能,然后審核員能夠?qū)徍擞脩舻奈恼率欠裼?strong>敏感信息;
比較符合區(qū)塊鏈開發(fā)思路的方式,既然用戶上傳知識、審核員審核文章,這都是工作量,那就要給用戶和審核員一些利益,好讓用戶多過來上傳文章,壯大我們的區(qū)塊鏈合約;我們就可以在審核員審核通過后,自動的使用合約給用戶和審核員發(fā)送token獎勵;
也就是在approved函數(shù)中,添加獎勵功能;
首先假設(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"} );
}
可以看到,最后一個語句就是調(diào)用的其他合約 eosio.token,這語句是合約中最最簡單的調(diào)用方式,參數(shù)詳解:
- eosio::token(N(eosio.token)) 前面是eosio.token頭文件中定義的結(jié)構(gòu),然后傳入的參數(shù),是該合約上傳的賬戶;
- transfer 即需要調(diào)用的方法;
- {_self,N(active)} 本次交易,需要的權(quán)限;
- 后面的參數(shù),就是本次action需要的所有參數(shù);
當(dāng)然,實現(xiàn)的內(nèi)部調(diào)用的方法,還是很多種形式,比如action().send()、dispatch_inline()、INLINE_ACTION_SENDER等等,其實最根本的,還是action.send(),其他所有方法都是對該方法的封裝。
PS:合約間調(diào)用,還有一個比較嚴重的問題,就是目前合約調(diào)用的權(quán)限簽名,只支持調(diào)用合約的簽名。比如合約A,調(diào)用合約B的action,假設(shè)為transfer,transfer需要驗證發(fā)送者權(quán)限,則只能驗證合約A的權(quán)限。假如,用戶h,調(diào)用A合約,A合約調(diào)用B合約的transfer,則只能有合約B,本身發(fā)出轉(zhuǎn)賬,用h用戶的賬戶發(fā)出轉(zhuǎn)賬是不行的。。。挺繞的。
比如上面的例子,只能是_self本身發(fā)出轉(zhuǎn)賬,任何其他賬戶都不行。
期望在4.0改進吧,不然限制太大。