美文网首页
EOS延迟事务(deferred transaction)

EOS延迟事务(deferred transaction)

作者: vergil6 | 来源:发表于2018-12-03 15:53 被阅读291次

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

    延迟事务相关的表

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

    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;       // 发送该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<char*> 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)

          本文链接:https://www.haomeiwen.com/subject/idyycqtx.html