575 {
578
579 auto send_response = [
this, &trx, &chain, &
next](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& response) {
581
582 auto get_trace = [&](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& response) ->
fc::variant {
583 if (std::holds_alternative<fc::exception_ptr>(response)) {
584 return fc::variant{std::get<fc::exception_ptr>(response)};
585 } else {
587 }
588
589 };
590
592 if (std::holds_alternative<fc::exception_ptr>(response)) {
593 except_ptr = std::get<fc::exception_ptr>(response);
594 } else if (std::get<transaction_trace_ptr>(response)->except) {
595 except_ptr = std::get<transaction_trace_ptr>(response)->except->dynamic_copy_exception();
596 }
597
598 if (!trx->read_only) {
600 }
601
602 if (except_ptr) {
605 ("block_num", chain.head_block_num() + 1)
607 ("txid", trx->id())
608 ("a", trx->packed_trx()->get_transaction().first_authorizer())
609 ("why", except_ptr->what()));
610 fc_dlog(
_trx_log,
"[TRX_TRACE] Block ${block_num} for producer ${prod} is REJECTING tx: ${trx}",
615 ("entire_trace", get_trace(response)));
616 } else {
618 ("txid", trx->id())
619 ("a", trx->packed_trx()->get_transaction().first_authorizer())
620 ("why", except_ptr->what()));
621 fc_dlog(
_trx_log,
"[TRX_TRACE] Speculative execution is REJECTING tx: ${trx} ",
624 ("entire_trace", get_trace(response)));
625 }
626 } else {
629 ("block_num", chain.head_block_num() + 1)
631 ("txid", trx->id())
632 ("a", trx->packed_trx()->get_transaction().first_authorizer())
633 ("cpu", trx->billed_cpu_time_us));
634 fc_dlog(
_trx_log,
"[TRX_TRACE] Block ${block_num} for producer ${prod} is ACCEPTING tx: ${trx}",
639 ("entire_trace", get_trace(response)));
640 } else {
642 ("txid", trx->id())
643 ("a", trx->packed_trx()->get_transaction().first_authorizer())
644 ("cpu", trx->billed_cpu_time_us));
646 ("entire_trace", get_trace(response)));
647 fc_dlog(
_trx_log,
"[TRX_TRACE] Speculative execution is ACCEPTING tx: ${trx}",
649 }
650 }
651 };
652
653 try {
654 const auto& id = trx->id();
655
656 fc::time_point bt = chain.is_building_block() ? chain.pending_block_time() : chain.head_block_time();
659 send_response( std::static_pointer_cast<fc::exception>(
660 std::make_shared<expired_tx_exception>(
661 FC_LOG_MESSAGE( error,
"expired transaction ${id}, expiration ${e}, block time ${bt}",
662 (
"id",
id)(
"e", expire)(
"bt",
bt )))));
663 return true;
664 }
665
666 if( chain.is_known_unexpired_transaction( id )) {
667 send_response( std::static_pointer_cast<fc::exception>( std::make_shared<tx_duplicate>(
668 FC_LOG_MESSAGE( error,
"duplicate transaction ${id}", (
"id",
id)))) );
669 return true;
670 }
671
672 if( !chain.is_building_block()) {
674 return true;
675 }
676
677 auto first_auth = trx->packed_trx()->get_transaction().first_authorizer();
679 send_response( std::static_pointer_cast<fc::exception>( std::make_shared<tx_cpu_usage_exceeded>(
680 FC_LOG_MESSAGE( error,
"transaction ${id} exceeded failure limit for account ${a}",
681 ("id", trx->id())("a", first_auth) ) ) ) );
682 return true;
683 }
684
689
693 || trx->read_only;
694
696 if( !disable_subjective_billing )
698
699 auto prev_billed_cpu_time_us = trx->billed_cpu_time_us;
700 auto trace = chain.push_transaction( trx, block_deadline, max_trx_time, prev_billed_cpu_time_us, false, sub_bill );
702 if( trace->except ) {
703 if( exception_is_exhausted( *trace->except ) ) {
707 ("block_num", chain.head_block_num() + 1)
709 ("txid", trx->id()));
710 } else {
712 ("txid", trx->id()));
713 }
715 } else {
716 if (!disable_subjective_billing)
718
720 auto failure_code = trace->except->code();
721 if( failure_code != tx_duplicate::code_value ) {
722
723 fc_dlog(
_log,
"Failed ${c} trx, prev billed: ${p}us, ran: ${r}us, id: ${id}",
724 ("c", trace->except->code())( "p", prev_billed_cpu_time_us )
727 }
728 }
729 if( return_failure_traces ) {
730 send_response( trace );
731 } else {
732 auto e_ptr = trace->except->dynamic_copy_exception();
733 send_response( e_ptr );
734 }
735 }
736 } else {
738
739
740
742 } else {
743
744 if (!disable_subjective_billing)
747 }
748 send_response( trace );
749 }
750
753 } catch ( boost::interprocess::bad_alloc& ) {
755 } catch ( std::bad_alloc& ) {
758
760 }
void publish(int priority, const Data &data)
constexpr int64_t count() const
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
void add_incoming(const transaction_metadata_ptr &trx, bool persist_until_expired, bool return_failure_trace, next_func_t next)
void add_persisted(const transaction_metadata_ptr &trx)
fc::variant get_log_trx_trace(const chain::transaction_trace_ptr &trx_trace) const
fc::variant get_log_trx(const transaction &trx) const
bool _disable_persist_until_expired
bool _disable_subjective_p2p_billing
fc::time_point calculate_block_deadline(const fc::time_point &) const
bool block_is_exhausted() const
bool _disable_subjective_api_billing
account_failures _account_fails
account_name get_pending_block_producer()
int64_t get_subjective_bill(const account_name &first_auth, const fc::time_point &now) const
void subjective_bill(const transaction_id_type &id, const fc::time_point &expire, const account_name &first_auth, const fc::microseconds &elapsed, bool in_pending_block)
void subjective_bill_failure(const account_name &first_auth, const fc::microseconds &elapsed, const fc::time_point &now)
#define FC_LOG_MESSAGE(LOG_LEVEL, FORMAT,...)
A helper method for generating log messages.
std::shared_ptr< exception > exception_ptr
fc::logger _trx_trace_success_log
fc::logger _trx_trace_failure_log
fc::logger _trx_failed_trace_log
fc::logger _trx_successful_trace_log
void bt(const Operand &op, const Reg ®)