EOS延迟事务(deferred transaction)

EOS中的事务(transaction)中的动作(action)执行分2种,1)一般的事务里面的动作立即执行 2)延迟事务里面的动作在将来某个时刻执行,第二类事务成为延迟事务(deferred transaction)

延迟事务相关的表

在generated_transaction_object.hpp中定义了延迟事务相关的表跟数据结构,generated_transaction_multi_index表中保存的记录结构如下:

class generated_transaction_object : public chainbase::object
   {
         OBJECT_CTOR(generated_transaction_object, (packed_trx) )

         id_type                       id;
         transaction_id_type           trx_id;        // packed_trx id
         account_name                  sender;       // 发送该trx的inline action合约名称  如果不是inline action产生 则为空
         uint128_t                     sender_id = 0; // 由sender给出的唯一标号(inline action)
         account_name                  payer;      // 该结构的占用的ram由谁支付
         time_point                    delay_until;   // 事务开始执行的时间
         time_point                    expiration;   // 事务过期时间
         time_point                    published;   // 产生该延迟事务的时间
         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 ds( packed_trx.data(), trxsize );
            fc::raw::pack( ds, trx );
            return trxsize;
         }
   };

延迟事务的产生

  • 事务本身是延迟的
    transaction中有一个字段delay_sec,如果该字段非0则表示延迟delay_sec秒后执行该事务,在transaction_context::exec() 函数中会判断
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 为非空,则是延迟事务
      } else {
         schedule_transaction();
      }
   }

schedule_transaction函数在generated_transaction_multi_index插入一条延迟事务记录

  • 合约中发出的事务

合约 ===》send_deferred ===》apply_context::schedule_deferred_transaction

在执行合约中合约不仅能发出inline action还能发出延迟事务,事实上合约发出的事务都是延迟的,因为能发出事务的wasm接口目前只有一个

    /**
     *  发送一个延迟事务.
     *
     *  @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函数主要是先做权限检查然后在generated_transaction_multi_index插入一条延迟事务记录

延迟事务的执行

start_block===>push_scheduled_transaction

延迟事务的执行发生在producer_plugin.cpp中的start_block中,通过get_scheduled_transactions函数获取可以执行的延迟事务然后调用push_scheduled_transaction执行该延迟事务

你可能感兴趣的:(EOS延迟事务(deferred transaction))