def add_transaction(transaction)
      raise AssertError, "head candiate cannot be nil" unless @head_candidate

      hc = @head_candidate
      logger.debug "add tx", num_txs: transaction_count, tx: transaction, on: hc

      if @head_candidate.include_transaction?(transaction.full_hash)
        logger.debug "known tx"
        return
      end

      old_state_root = hc.state_root
      # revert finalization
      hc.state_root = @pre_finalize_state_root
      begin
        success, output = hc.apply_transaction(transaction)
      rescue InvalidTransaction => e
        # if unsuccessful the prerequisites were not fullfilled and the tx is
        # invalid, state must not have changed
        logger.debug "invalid tx", error: e
        hc.state_root = old_state_root
        return false
      end
      logger.debug "valid tx"

      # we might have a new head_candidate (due to ctx switches in up layer)
      if @head_candidate != hc
        logger.debug "head_candidate changed during validation, trying again"
        return add_transaction(transaction)
      end

      @pre_finalize_state_root = hc.state_root
      hc.finalize
      logger.debug "tx applied", result: output

      raise AssertError, "state root unchanged!" unless old_state_root != hc.state_root
      true
    end
def add_transaction(transaction)
      raise AssertError, "head candiate cannot be nil" unless @head_candidate

      hc = @head_candidate
      logger.debug "add tx", num_txs: transaction_count, tx: transaction, on: hc

      if @head_candidate.include_transaction?(transaction.full_hash)
        logger.debug "known tx"
        return
      end

      old_state_root = hc.state_root
      # revert finalization
      hc.state_root = @pre_finalize_state_root
      begin
        success, output = hc.apply_transaction(transaction)
      rescue InvalidTransaction => e
        # if unsuccessful the prerequisites were not fullfilled and the tx is
        # invalid, state must not have changed
        logger.debug "invalid tx", error: e
        hc.state_root = old_state_root
        return false
      end
      logger.debug "valid tx"

      # we might have a new head_candidate (due to ctx switches in up layer)
      if @head_candidate != hc
        logger.debug "head_candidate changed during validation, trying again"
        return add_transaction(transaction)
      end

      @pre_finalize_state_root = hc.state_root
      hc.finalize
      logger.debug "tx applied", result: output

      raise AssertError, "state root unchanged!" unless old_state_root != hc.state_root
      true
    end
Add a transaction to the `head_candidate` block.

 If the transaction is invalid, the block will not be changed.

 @return [Bool,NilClass] `true` is the transaction was successfully added or
   `false` if the transaction was invalid, `nil` if it's already included