EOS中的事務(wù)(transaction)中的動作(action)執(zhí)行分2種红淡,1)一般的事務(wù)里面的動作立即執(zhí)行 2)延遲事務(wù)里面的動作在將來某個時刻執(zhí)行顽腾,第二類事務(wù)成為延遲事務(wù)(deferred transaction)
延遲事務(wù)相關(guān)的表
在generated_transaction_object.hpp中定義了延遲事務(wù)相關(guān)的表跟數(shù)據(jù)結(jié)構(gòu)弧烤,generated_transaction_multi_index表中保存的記錄結(jié)構(gòu)如下:
class generated_transaction_object : public chainbase::object<generated_transaction_object_type, generated_transaction_object>
{
OBJECT_CTOR(generated_transaction_object, (packed_trx) )
id_type id;
transaction_id_type trx_id; // packed_trx id
account_name sender; // 發(fā)送該trx的inline action合約名稱 如果不是inline action產(chǎn)生 則為空
uint128_t sender_id = 0; // 由sender給出的唯一標(biāo)號(inline action)
account_name payer; // 該結(jié)構(gòu)的占用的ram由誰支付
time_point delay_until; // 事務(wù)開始執(zhí)行的時間
time_point expiration; // 事務(wù)過期時間
time_point published; // 產(chǎn)生該延遲事務(wù)的時間
shared_string packed_trx; // packed_trx
uint32_t set( const transaction& trx ) {
auto trxsize = fc::raw::pack_size( trx );
packed_trx.resize( trxsize );
fc::datastream<char*> ds( packed_trx.data(), trxsize );
fc::raw::pack( ds, trx );
return trxsize;
}
};
延遲事務(wù)的產(chǎn)生
- 事務(wù)本身是延遲的
transaction中有一個字段delay_sec否彩,如果該字段非0則表示延遲delay_sec秒后執(zhí)行該事務(wù),在transaction_context::exec() 函數(shù)中會判斷
void transaction_context::exec() {
EOS_ASSERT( is_initialized, transaction_exception, "must first initialize" );
if( apply_context_free ) {
for( const auto& act : trx.context_free_actions ) {
trace->action_traces.emplace_back();
dispatch_action( trace->action_traces.back(), act, true );
}
}
if( delay == fc::microseconds() ) {
for( const auto& act : trx.actions ) {
trace->action_traces.emplace_back();
dispatch_action( trace->action_traces.back(), act );
}
// 如果delay 為非空托享,則是延遲事務(wù)
} else {
schedule_transaction();
}
}
schedule_transaction函數(shù)在generated_transaction_multi_index插入一條延遲事務(wù)記錄
- 合約中發(fā)出的事務(wù)
合約 ===》send_deferred ===》apply_context::schedule_deferred_transaction
在執(zhí)行合約中合約不僅能發(fā)出inline action還能發(fā)出延遲事務(wù)其兴,事實上合約發(fā)出的事務(wù)都是延遲的顶瞒,因為能發(fā)出事務(wù)的wasm接口目前只有一個
/**
* 發(fā)送一個延遲事務(wù).
*
* @brief Sends a deferred transaction.
* @param sender_id - ID of sender
* @param payer - Account paying for RAM
* @param serialized_transaction - Pointer of serialized transaction to be deferred
* @param size - Size to reserve
* @param replace_existing - f this is `0` then if the provided sender_id is already in use by an in-flight transaction from this contract, which will be a failing assert. If `1` then transaction will atomically cancel/replace the inflight transaction
*/
void send_deferred(const uint128_t& sender_id, capi_name payer, const char *serialized_transaction, size_t size, uint32_t replace_existing = 0);
schedule_deferred_transaction函數(shù)主要是先做權(quán)限檢查然后在generated_transaction_multi_index插入一條延遲事務(wù)記錄
延遲事務(wù)的執(zhí)行
start_block===>push_scheduled_transaction
延遲事務(wù)的執(zhí)行發(fā)生在producer_plugin.cpp中的start_block中,通過get_scheduled_transactions函數(shù)獲取可以執(zhí)行的延遲事務(wù)然后調(diào)用push_scheduled_transaction執(zhí)行該延遲事務(wù)