18#include <boost/asio.hpp>
19#include <boost/date_time/posix_time/posix_time.hpp>
23#include <boost/algorithm/string.hpp>
24#include <boost/range/adaptor/map.hpp>
25#include <boost/function_output_iterator.hpp>
26#include <boost/multi_index_container.hpp>
27#include <boost/multi_index/member.hpp>
28#include <boost/multi_index/hashed_index.hpp>
29#include <boost/multi_index/ordered_index.hpp>
30#include <boost/signals2/connection.hpp>
32namespace bmi = boost::multi_index;
34using bmi::ordered_non_unique;
37using bmi::hashed_unique;
39using boost::multi_index_container;
44using boost::signals2::scoped_connection;
47#define LOG_AND_DROP() \
48 catch ( const guard_exception& e ) { \
49 chain_plugin::handle_guard_exception(e); \
50 } catch ( const std::bad_alloc& ) { \
51 chain_plugin::handle_bad_alloc(); \
52 } catch ( boost::interprocess::bad_alloc& ) { \
53 chain_plugin::handle_db_exhaustion(); \
54 } catch( fc::exception& er ) { \
55 wlog( "${details}", ("details",er.to_detail_string()) ); \
56 } catch( const std::exception& e ) { \
58 FC_LOG_MESSAGE( warn, "std::exception: ${what}: ",("what",e.what()) ), \
59 fc::std_exception_code,\
60 BOOST_CORE_TYPEID(e).name(), \
62 wlog( "${details}", ("details",fce.to_detail_string()) ); \
64 fc::unhandled_exception e( \
65 FC_LOG_MESSAGE( warn, "unknown: ", ), \
66 std::current_exception() ); \
67 wlog( "${details}", ("details",e.to_detail_string()) ); \
98 return (code == block_cpu_usage_exceeded::code_value) ||
99 (code == block_net_usage_exceeded::code_value) ||
100 (code == deadline_exception::code_value);
151 auto in_chain = (bool)block_ptr;
152 boost::system::error_code ec;
156 SYS_THROW(snapshot_finalization_exception,
157 "Snapshotted block was forked out of the chain. ID: ${block_id}",
162 SYS_ASSERT(!ec, snapshot_finalization_exception,
163 "Unable to finalize valid snapshot of block number ${bn}: [code: ${ec}] ${message}",
166 (
"message", ec.message()));
193class account_failures {
202 void set_max_failures_per_account(
uint32_t max_failures ) {
203 max_failures_per_account = max_failures;
207 auto& fa = failed_accounts[n];
214 auto fitr = failed_accounts.find( n );
216 if( !is_whitelisted && fitr != failed_accounts.end() && fitr->second.num_failures >= max_failures_per_account ) {
217 ++fitr->second.num_failures;
223 void report()
const {
226 for(
const auto& e : failed_accounts ) {
228 if( e.second.is_deadline() ) reason +=
"deadline";
229 if( e.second.is_tx_cpu_usage() ) {
230 if( !reason.empty() ) reason +=
", ";
231 reason +=
"tx_cpu_usage";
233 if( e.second.is_sysio_assert() ) {
234 if( !reason.empty() ) reason +=
", ";
237 if( e.second.is_other() ) {
238 if( !reason.empty() ) reason +=
", ";
241 fc_dlog(
_log,
"Failed ${n} trxs, account: ${a}, sub bill: ${b}us, reason: ${r}",
243 (
"a", e.first)(
"r", reason) );
249 failed_accounts.clear();
253 struct account_failure {
254 enum class ex_fields :
uint8_t {
255 ex_deadline_exception = 1,
256 ex_tx_cpu_usage_exceeded = 2,
257 ex_sysio_assert_exception = 4,
258 ex_other_exception = 8
263 ex_flags = set_field( ex_flags, ex_fields::ex_tx_cpu_usage_exceeded );
265 ex_flags = set_field( ex_flags, ex_fields::ex_deadline_exception );
266 }
else if(
exception_code == sysio_assert_message_exception::code_value ||
268 ex_flags = set_field( ex_flags, ex_fields::ex_sysio_assert_exception );
270 ex_flags = set_field( ex_flags, ex_fields::ex_other_exception );
271 fc_dlog(
_log,
"Failed trx, account: ${a}, reason: ${r}",
276 bool is_deadline()
const {
return has_field( ex_flags, ex_fields::ex_deadline_exception ); }
277 bool is_tx_cpu_usage()
const {
return has_field( ex_flags, ex_fields::ex_tx_cpu_usage_exceeded ); }
278 bool is_sysio_assert()
const {
return has_field( ex_flags, ex_fields::ex_sysio_assert_exception ); }
279 bool is_other()
const {
return has_field( ex_flags, ex_fields::ex_other_exception ); }
285 std::map<account_name, account_failure> failed_accounts;
286 uint32_t max_failures_per_account = 3;
380 itr->second.first = std::max( itr->second.first, block_num );
381 itr->second.second = std::max( itr->second.second, timestamp );
382 }
else if(
_producers.count( producer ) > 0 ) {
399 fc_dlog(
_log,
"Removed applied transactions before: ${before}, after: ${after}",
413 uint32_t lib_height = lib->block_num();
415 while (!snapshots_by_height.empty() && snapshots_by_height.begin()->get_height() <= lib_height) {
416 const auto& pending = snapshots_by_height.begin();
417 auto next = pending->next;
420 next(pending->finalize(chain));
423 snapshots_by_height.erase(snapshots_by_height.begin());
437 fc_wlog(
_log,
"dropped incoming block #${num} id: ${id}",
438 (
"num", block->block_num())(
"id", block_id ? (*block_id).str() :
"UNKNOWN") );
447 const auto&
id = block_id ? *block_id : block->calculate_id();
448 auto blk_num = block->block_num();
450 fc_dlog(
_log,
"received incoming block ${n} ${id}", (
"n", blk_num)(
"id",
id));
453 "received a block from the future, ignoring it: ${id}", (
"id",
id) );
456 auto existing = chain.fetch_block_by_id(
id );
457 if( existing ) {
return false; }
460 std::future<block_state_ptr>
bsf;
462 bsf = chain.create_block_state_future(
id, block );
469 auto handle_error = [&](
const auto& e)
471 elog((e.to_detail_string()));
478 chain.push_block( bspr, [
this](
const branch_type& forked_branch ) {
486 }
catch (
const std::bad_alloc& ) {
488 }
catch ( boost::interprocess::bad_alloc& ) {
491 elog(
"Cannot recover from ${e}. Shutting down.", (
"e", e.to_detail_string()));
495 }
catch (
const std::exception& e) {
499 const auto& hbs = chain.head_block_state();
505 ilog(
"Received block ${id}... #${n} @ ${t} signed by ${p} [trxs: ${count}, lib: ${lib}, conf: ${confs}, latency: ${latency} ms]",
506 (
"p",block->producer)(
"id",
id.str().substr(8,16))(
"n",blk_num)(
"t",block->timestamp)
507 (
"count",block->transactions.size())(
"lib",chain.last_irreversible_block_num())
508 (
"confs", block->confirmed)(
"latency", (
fc::time_point::now() - block->timestamp).count()/1000 ) );
509 if( chain.get_read_mode() != db_read_mode::IRREVERSIBLE && hbs->id !=
id && hbs->block !=
nullptr ) {
510 ilog(
"Block not applied to head ${id}... #${n} @ ${t} signed by ${p} [trxs: ${count}, dpos: ${dpos}, conf: ${confs}, latency: ${latency} ms]",
511 (
"p",hbs->block->producer)(
"id",hbs->id.str().substr(8,16))(
"n",hbs->block_num)(
"t",hbs->block->timestamp)
512 (
"count",hbs->block->transactions.size())(
"dpos", hbs->dpos_irreversible_blocknum)
513 (
"confs", hbs->block->confirmed)(
"latency", (
fc::time_point::now() - hbs->block->timestamp).count()/1000 ) );
529 bool persist_until_expired,
531 bool return_failure_traces,
539 read_only ? transaction_metadata::trx_type::read_only : transaction_metadata::trx_type::input,
542 boost::asio::post(
_thread_pool->get_executor(), [
self =
this, future{std::move(future)}, persist_until_expired, return_failure_traces,
543 next{std::move(next)}, trx]()
mutable {
544 if( future.valid() ) {
546 app().post( priority::low, [self, future{std::move(future)}, persist_until_expired, next{std::move( next )}, trx{std::move(trx)}, return_failure_traces]() mutable {
547 auto exception_handler = [self, &next, trx{std::move(trx)}](fc::exception_ptr ex) {
548 fc_dlog(_trx_failed_trace_log,
"[TRX_TRACE] Speculative execution is REJECTING tx: ${txid}, auth: ${a} : ${why} ",
549 (
"txid", trx->id())(
"a",trx->get_transaction().first_authorizer())(
"why",ex->what()));
552 fc_dlog(_trx_trace_failure_log,
"[TRX_TRACE] Speculative execution is REJECTING tx: ${entire_trx}",
553 (
"entire_trx", self->chain_plug->get_log_trx(trx->get_transaction())));
554 fc_dlog(_trx_log,
"[TRX_TRACE] Speculative execution is REJECTING tx: ${trx}",
555 (
"trx", self->chain_plug->get_log_trx(trx->get_transaction())));
558 auto result = future.get();
559 if( !self->process_incoming_transaction_async( result, persist_until_expired, return_failure_traces, next) ) {
560 if( self->_pending_block_mode == pending_block_mode::producing ) {
561 self->schedule_maybe_produce_block( true );
563 self->restart_speculative_block();
566 } CATCH_AND_CALL(exception_handler);
573 bool persist_until_expired,
574 bool return_failure_traces,
576 bool exhausted =
false;
579 auto send_response = [
this, &trx, &chain, &next](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& response) {
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)};
586 return chain_plug->get_log_trx_trace( std::get<transaction_trace_ptr>(response) );
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();
598 if (!trx->read_only) {
599 _transaction_ack_channel.publish(
priority::low, std::pair<fc::exception_ptr, packed_transaction_ptr>(except_ptr, trx->packed_trx()));
606 (
"prod", get_pending_block_producer())
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}",
611 (
"block_num", chain.
head_block_num() + 1)(
"prod", get_pending_block_producer())
612 (
"trx", chain_plug->get_log_trx(trx->packed_trx()->get_transaction())));
614 (
"block_num", chain.
head_block_num() + 1)(
"prod", get_pending_block_producer())
615 (
"entire_trace", get_trace(response)));
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} ",
622 (
"trx", chain_plug->get_log_trx(trx->packed_trx()->get_transaction())));
624 (
"entire_trace", get_trace(response)));
630 (
"prod", get_pending_block_producer())
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}",
635 (
"block_num", chain.
head_block_num() + 1)(
"prod", get_pending_block_producer())
636 (
"trx", chain_plug->get_log_trx(trx->packed_trx()->get_transaction())));
638 (
"block_num", chain.
head_block_num() + 1)(
"prod", get_pending_block_producer())
639 (
"entire_trace", get_trace(response)));
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}",
648 (
"trx", chain_plug->get_log_trx(trx->packed_trx()->get_transaction())));
654 const auto&
id = trx->id();
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 )))));
667 send_response( std::static_pointer_cast<fc::exception>( std::make_shared<tx_duplicate>(
668 FC_LOG_MESSAGE( error,
"duplicate transaction ${id}", (
"id",
id)))) );
673 _unapplied_transactions.add_incoming( trx, persist_until_expired, return_failure_traces, next );
677 auto first_auth = trx->packed_trx()->get_transaction().first_authorizer();
678 if( _account_fails.failure_limit( first_auth ) ) {
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) ) ) ) );
691 || ( persist_until_expired && _disable_subjective_api_billing )
692 || ( !persist_until_expired && _disable_subjective_p2p_billing )
696 if( !disable_subjective_billing )
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 ) ) {
704 _unapplied_transactions.add_incoming( trx, persist_until_expired, return_failure_traces, next );
708 (
"prod", get_pending_block_producer())
709 (
"txid", trx->id()));
712 (
"txid", trx->id()));
714 exhausted = block_is_exhausted();
716 if (!disable_subjective_billing)
717 _subjective_billing.subjective_bill_failure( first_auth, trace->elapsed,
fc::time_point::now() );
720 auto failure_code = trace->except->code();
721 if( failure_code != tx_duplicate::code_value ) {
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 )
726 _account_fails.add( first_auth, failure_code );
729 if( return_failure_traces ) {
730 send_response( trace );
732 auto e_ptr = trace->except->dynamic_copy_exception();
733 send_response( e_ptr );
737 if( persist_until_expired && !_disable_persist_until_expired ) {
741 _unapplied_transactions.add_persisted( trx );
744 if (!disable_subjective_billing)
745 _subjective_billing.subjective_bill( trx->id(), expire, first_auth, trace->elapsed,
748 send_response( trace );
753 }
catch ( boost::interprocess::bad_alloc& ) {
755 }
catch ( std::bad_alloc& ) {
765 if (now < _irreversible_block_time) {
768 return now - _irreversible_block_time;
773 auto& chain = chain_plug->chain();
774 if (chain.is_building_block()) {
775 return chain.pending_block_producer();
782 return !_production_enabled || _pause_production || (_max_irreversible_block_age_us.count() >= 0 && get_irreversible_block_age() >= _max_irreversible_block_age_us);
789 waiting_for_production,
793 inline bool should_interrupt_start_block(
const fc::time_point& deadline )
const;
794 start_block_result start_block();
798 void schedule_delayed_production_loop(
const std::weak_ptr<producer_plugin_impl>& weak_this, std::optional<fc::time_point> wake_up_time);
799 std::optional<fc::time_point> calculate_producer_wake_up_time(
const block_timestamp_type& ref_block_time )
const;
806 "*******************************\n"
808 "* ------ NEW CHAIN ------ *\n"
809 "* - Welcome to SYSIO! - *\n"
810 "* ----------------------- *\n"
812 "*******************************\n"
817 std::cerr <<
"Your genesis seems to have an old timestamp\n"
818 "Please consider using the --genesis-timestamp option to give your genesis a recent timestamp\n"
825producer_plugin::producer_plugin()
832 boost::program_options::options_description& command_line_options,
833 boost::program_options::options_description& config_file_options)
836 auto private_key_default = std::make_pair(default_priv_key.get_public_key(), default_priv_key );
838 boost::program_options::options_description producer_options;
840 producer_options.add_options()
841 (
"enable-stale-production,e", boost::program_options::bool_switch()->notifier([
this](
bool e){my->_production_enabled = e;}),
"Enable block production, even if the chain is stale.")
842 (
"pause-on-startup,x", boost::program_options::bool_switch()->notifier([
this](
bool p){my->_pause_production =
p;}),
"Start this node in a state where production is paused")
843 (
"max-transaction-time", bpo::value<int32_t>()->default_value(30),
844 "Limits the maximum time (in milliseconds) that is allowed a pushed transaction's code to execute before being considered invalid")
845 (
"max-irreversible-block-age", bpo::value<int32_t>()->default_value( -1 ),
846 "Limits the maximum age (in seconds) of the DPOS Irreversible Block for a chain this node will produce blocks on (use negative value to indicate unlimited)")
847 (
"producer-name,p", boost::program_options::value<vector<string>>()->composing()->multitoken(),
848 "ID of producer controlled by this node (e.g. inita; may specify multiple times)")
849 (
"private-key", boost::program_options::value<vector<string>>()->composing()->multitoken(),
850 "(DEPRECATED - Use signature-provider instead) Tuple of [public key, WIF private key] (may specify multiple times)")
851 (
"signature-provider", boost::program_options::value<vector<string>>()->composing()->multitoken()->default_value(
852 {default_priv_key.get_public_key().to_string() +
"=KEY:" + default_priv_key.to_string()},
853 default_priv_key.get_public_key().
to_string() +
"=KEY:" + default_priv_key.to_string()),
854 "Key=Value pairs in the form <public-key>=<provider-spec>\n"
856 " <public-key> \tis a string form of a vaild SYSIO public key\n\n"
857 " <provider-spec> \tis a string in the form <provider-type>:<data>\n\n"
858 " <provider-type> \tis KEY, or KSYSD\n\n"
859 " KEY:<data> \tis a string form of a valid SYSIO private key which maps to the provided public key\n\n"
860 " KSYSD:<data> \tis the URL where kiod is available and the approptiate wallet(s) are unlocked")
861 (
"kiod-provider-timeout", boost::program_options::value<int32_t>()->default_value(5),
862 "Limits the maximum time (in milliseconds) that is allowed for sending blocks to a kiod provider for signing")
863 (
"greylist-account", boost::program_options::value<
vector<string>>()->composing()->multitoken(),
864 "account that can not access to extended CPU/NET virtual resources")
865 (
"greylist-limit", boost::program_options::value<uint32_t>()->default_value(1000),
866 "Limit (between 1 and 1000) on the multiple that CPU/NET virtual resources can extend during low usage (only enforced subjectively; use 1000 to not enforce any limit)")
867 (
"produce-time-offset-us", boost::program_options::value<int32_t>()->default_value(0),
868 "Offset of non last block producing time in microseconds. Valid range 0 .. -block_time_interval.")
869 (
"last-block-time-offset-us", boost::program_options::value<int32_t>()->default_value(-200000),
870 "Offset of last block producing time in microseconds. Valid range 0 .. -block_time_interval.")
871 (
"cpu-effort-percent", bpo::value<uint32_t>()->default_value(config::default_block_cpu_effort_pct / config::percent_1),
872 "Percentage of cpu block production time used to produce block. Whole number percentages, e.g. 80 for 80%")
873 (
"last-block-cpu-effort-percent", bpo::value<uint32_t>()->default_value(config::default_block_cpu_effort_pct / config::percent_1),
874 "Percentage of cpu block production time used to produce last block. Whole number percentages, e.g. 80 for 80%")
875 (
"max-block-cpu-usage-threshold-us", bpo::value<uint32_t>()->default_value( 5000 ),
876 "Threshold of CPU block production to consider block full; when within threshold of max-block-cpu-usage block can be produced immediately")
877 (
"max-block-net-usage-threshold-bytes", bpo::value<uint32_t>()->default_value( 1024 ),
878 "Threshold of NET block production to consider block full; when within threshold of max-block-net-usage block can be produced immediately")
879 (
"max-scheduled-transaction-time-per-block-ms", boost::program_options::value<int32_t>()->default_value(100),
880 "Maximum wall-clock time, in milliseconds, spent retiring scheduled transactions in any block before returning to normal transaction processing.")
881 (
"subjective-cpu-leeway-us", boost::program_options::value<int32_t>()->default_value( config::default_subjective_cpu_leeway_us ),
882 "Time in microseconds allowed for a transaction that starts with insufficient CPU quota to complete and cover its CPU usage.")
883 (
"subjective-account-max-failures", boost::program_options::value<uint32_t>()->default_value(3),
884 "Sets the maximum amount of failures that are allowed for a given account per block.")
885 (
"subjective-account-decay-time-minutes", bpo::value<uint32_t>()->default_value( config::account_cpu_usage_average_window_ms / 1000 / 60 ),
886 "Sets the time to return full subjective cpu for accounts")
887 (
"incoming-defer-ratio", bpo::value<double>()->default_value(1.0),
888 "ratio between incoming transactions and deferred transactions when both are queued for execution")
889 (
"incoming-transaction-queue-size-mb", bpo::value<uint16_t>()->default_value( 1024 ),
890 "Maximum size (in MiB) of the incoming transaction queue. Exceeding this value will subjectively drop transaction with resource exhaustion.")
891 (
"disable-api-persisted-trx", bpo::bool_switch()->default_value(
false),
892 "Disable the re-apply of API transactions.")
893 (
"disable-subjective-billing", bpo::value<bool>()->default_value(
true),
894 "Disable subjective CPU billing for API/P2P transactions")
895 (
"disable-subjective-account-billing", boost::program_options::value<
vector<string>>()->composing()->multitoken(),
896 "Account which is excluded from subjective CPU billing")
897 (
"disable-subjective-p2p-billing", bpo::value<bool>()->default_value(
true),
898 "Disable subjective CPU billing for P2P transactions")
899 (
"disable-subjective-api-billing", bpo::value<bool>()->default_value(
true),
900 "Disable subjective CPU billing for API transactions")
901 (
"producer-threads", bpo::value<uint16_t>()->default_value(config::default_controller_thread_pool_size),
902 "Number of worker threads in producer thread pool")
903 (
"snapshots-dir", bpo::value<bfs::path>()->default_value(
"snapshots"),
904 "the location of the snapshots directory (absolute path or relative to application data dir)")
906 config_file_options.add(producer_options);
911 auto private_key_itr = my->_signature_providers.find(key);
912 if(private_key_itr != my->_signature_providers.end())
919 return my->_subjective_billing.get_subjective_bill( first_auth, now );
925 auto private_key_itr = my->_signature_providers.find(key);
926 SYS_ASSERT(private_key_itr != my->_signature_providers.end(), producer_priv_key_not_found,
"Local producer has no private key in config.ini corresponding to public key ${key}", (
"key", key));
928 return private_key_itr->second(
digest);
940#define LOAD_VALUE_SET(options, op_name, container) \
941if( options.count(op_name) ) { \
942 const std::vector<std::string>& ops = options[op_name].as<std::vector<std::string>>(); \
943 for( const auto& v : ops ) { \
944 container.emplace( sysio::chain::name( v ) ); \
956make_kiod_signature_provider(
const std::shared_ptr<producer_plugin_impl>& impl,
const string& url_str,
const public_key_type pubkey) {
958 if(boost::algorithm::starts_with(url_str,
"unix://"))
964 std::weak_ptr<producer_plugin_impl> weak_impl = impl;
967 auto impl = weak_impl.lock();
982 SYS_ASSERT( my->chain_plug, plugin_config_exception,
"chain_plugin not found" );
983 my->_options = &options;
988 if( options.count(
"private-key") )
990 const std::vector<std::string> key_id_to_wif_pair_strings = options[
"private-key"].as<std::vector<std::string>>();
991 for (
const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
995 my->_signature_providers[key_id_to_wif_pair.first] = make_key_signature_provider(key_id_to_wif_pair.second);
996 auto blanked_privkey = std::string(key_id_to_wif_pair.second.to_string().size(),
'*' );
997 wlog(
"\"private-key\" is DEPRECATED, use \"signature-provider=${pub}=KEY:${priv}\"", (
"pub",key_id_to_wif_pair.first)(
"priv", blanked_privkey));
998 }
catch (
const std::exception& e ) {
999 elog(
"Malformed private key pair");
1004 if( options.count(
"signature-provider") ) {
1005 const std::vector<std::string> key_spec_pairs = options[
"signature-provider"].as<std::vector<std::string>>();
1006 for (
const auto& key_spec_pair : key_spec_pairs) {
1008 auto delim = key_spec_pair.find(
"=");
1009 SYS_ASSERT(delim != std::string::npos, plugin_config_exception,
"Missing \"=\" in the key spec pair");
1010 auto pub_key_str = key_spec_pair.substr(0, delim);
1011 auto spec_str = key_spec_pair.substr(delim + 1);
1013 auto spec_delim = spec_str.find(
":");
1014 SYS_ASSERT(spec_delim != std::string::npos, plugin_config_exception,
"Missing \":\" in the key spec pair");
1015 auto spec_type_str = spec_str.substr(0, spec_delim);
1016 auto spec_data = spec_str.substr(spec_delim + 1);
1020 if (spec_type_str ==
"KEY") {
1022 }
else if (spec_type_str ==
"KSYSD") {
1023 my->_signature_providers[
pubkey] = make_kiod_signature_provider(my, spec_data,
pubkey);
1027 elog(
"Malformed signature provider: \"${val}\", ignoring!", (
"val", key_spec_pair));
1034 my->_account_fails.set_max_failures_per_account( options.at(
"subjective-account-max-failures").as<
uint32_t>() );
1036 my->_produce_time_offset_us = options.at(
"produce-time-offset-us").as<
int32_t>();
1037 SYS_ASSERT( my->_produce_time_offset_us <= 0 && my->_produce_time_offset_us >= -config::block_interval_us, plugin_config_exception,
1038 "produce-time-offset-us ${o} must be 0 .. -${bi}", (
"bi", config::block_interval_us)(
"o", my->_produce_time_offset_us) );
1040 my->_last_block_time_offset_us = options.at(
"last-block-time-offset-us").as<
int32_t>();
1041 SYS_ASSERT( my->_last_block_time_offset_us <= 0 && my->_last_block_time_offset_us >= -config::block_interval_us, plugin_config_exception,
1042 "last-block-time-offset-us ${o} must be 0 .. -${bi}", (
"bi", config::block_interval_us)(
"o", my->_last_block_time_offset_us) );
1045 SYS_ASSERT( cpu_effort_pct >= 0 && cpu_effort_pct <= 100, plugin_config_exception,
1046 "cpu-effort-percent ${pct} must be 0 - 100", (
"pct", cpu_effort_pct) );
1047 cpu_effort_pct *= config::percent_1;
1048 int32_t cpu_effort_offset_us =
1049 -
SYS_PERCENT( config::block_interval_us, chain::config::percent_100 - cpu_effort_pct );
1051 uint32_t last_block_cpu_effort_pct = options.at(
"last-block-cpu-effort-percent").as<
uint32_t>();
1052 SYS_ASSERT( last_block_cpu_effort_pct >= 0 && last_block_cpu_effort_pct <= 100, plugin_config_exception,
1053 "last-block-cpu-effort-percent ${pct} must be 0 - 100", (
"pct", last_block_cpu_effort_pct) );
1054 last_block_cpu_effort_pct *= config::percent_1;
1055 int32_t last_block_cpu_effort_offset_us =
1056 -
SYS_PERCENT( config::block_interval_us, chain::config::percent_100 - last_block_cpu_effort_pct );
1058 my->_produce_time_offset_us = std::min( my->_produce_time_offset_us, cpu_effort_offset_us );
1059 my->_last_block_time_offset_us = std::min( my->_last_block_time_offset_us, last_block_cpu_effort_offset_us );
1061 my->_max_block_cpu_usage_threshold_us = options.at(
"max-block-cpu-usage-threshold-us" ).as<
uint32_t>();
1062 SYS_ASSERT( my->_max_block_cpu_usage_threshold_us < config::block_interval_us, plugin_config_exception,
1063 "max-block-cpu-usage-threshold-us ${t} must be 0 .. ${bi}", (
"bi", config::block_interval_us)(
"t", my->_max_block_cpu_usage_threshold_us) );
1065 my->_max_block_net_usage_threshold_bytes = options.at(
"max-block-net-usage-threshold-bytes" ).as<
uint32_t>();
1067 my->_max_scheduled_transaction_time_per_block_ms = options.at(
"max-scheduled-transaction-time-per-block-ms").as<
int32_t>();
1069 if( options.at(
"subjective-cpu-leeway-us" ).as<
int32_t>() != config::default_subjective_cpu_leeway_us ) {
1074 SYS_ASSERT( subjective_account_decay_time.
count() > 0, plugin_config_exception,
1075 "subjective-account-decay-time-minutes ${dt} must be greater than 0", (
"dt", subjective_account_decay_time.
to_seconds() / 60));
1076 my->_subjective_billing.set_expired_accumulator_average_window( subjective_account_decay_time );
1078 my->_max_transaction_time_ms = options.at(
"max-transaction-time").as<
int32_t>();
1080 my->_max_irreversible_block_age_us =
fc::seconds(options.at(
"max-irreversible-block-age").as<
int32_t>());
1082 auto max_incoming_transaction_queue_size = options.at(
"incoming-transaction-queue-size-mb").as<
uint16_t>() * 1024*1024;
1084 SYS_ASSERT( max_incoming_transaction_queue_size > 0, plugin_config_exception,
1085 "incoming-transaction-queue-size-mb ${mb} must be greater than 0", (
"mb", max_incoming_transaction_queue_size) );
1087 my->_unapplied_transactions.set_max_transaction_queue_size( max_incoming_transaction_queue_size );
1089 my->_incoming_defer_ratio = options.at(
"incoming-defer-ratio").as<
double>();
1091 my->_disable_persist_until_expired = options.at(
"disable-api-persisted-trx").as<
bool>();
1092 bool disable_subjective_billing = options.at(
"disable-subjective-billing").as<
bool>();
1093 my->_disable_subjective_p2p_billing = options.at(
"disable-subjective-p2p-billing").as<
bool>();
1094 my->_disable_subjective_api_billing = options.at(
"disable-subjective-api-billing").as<
bool>();
1095 dlog(
"disable-subjective-billing: ${s}, disable-subjective-p2p-billing: ${p2p}, disable-subjective-api-billing: ${api}",
1096 (
"s", disable_subjective_billing)(
"p2p", my->_disable_subjective_p2p_billing)(
"api", my->_disable_subjective_api_billing) );
1097 if( !disable_subjective_billing ) {
1098 my->_disable_subjective_p2p_billing = my->_disable_subjective_api_billing =
false;
1099 }
else if( !my->_disable_subjective_p2p_billing || !my->_disable_subjective_api_billing ) {
1100 disable_subjective_billing =
false;
1102 if( disable_subjective_billing ) {
1103 my->_subjective_billing.disable();
1104 ilog(
"Subjective CPU billing disabled" );
1105 }
else if( !my->_disable_subjective_p2p_billing && !my->_disable_subjective_api_billing ) {
1106 ilog(
"Subjective CPU billing enabled" );
1108 if( my->_disable_subjective_p2p_billing )
ilog(
"Subjective CPU billing of P2P trxs disabled " );
1109 if( my->_disable_subjective_api_billing )
ilog(
"Subjective CPU billing of API trxs disabled " );
1112 auto thread_pool_size = options.at(
"producer-threads" ).as<
uint16_t>();
1113 SYS_ASSERT( thread_pool_size > 0, plugin_config_exception,
1114 "producer-threads ${num} must be greater than 0", (
"num", thread_pool_size));
1115 my->_thread_pool.emplace(
"prod", thread_pool_size );
1117 if( options.count(
"snapshots-dir" )) {
1118 auto sd = options.at(
"snapshots-dir" ).as<bfs::path>();
1119 if( sd.is_relative()) {
1125 my->_snapshots_dir = sd;
1129 "No such directory '${dir}'", (
"dir", my->_snapshots_dir.generic_string()) );
1131 if (
auto resmon_plugin =
app().find_plugin<resource_monitor_plugin>()) {
1132 resmon_plugin->monitor_directory(my->_snapshots_dir);
1138 return my->on_incoming_block(block, block_id, bsp);
1143 return my->on_incoming_transaction_async(trx, persist_until_expired,
read_only, return_failure_traces, next );
1146 if (options.count(
"greylist-account")) {
1147 std::vector<std::string> greylist = options[
"greylist-account"].as<std::vector<std::string>>();
1149 for (
auto &
a : greylist) {
1160 if( options.count(
"disable-subjective-account-billing") ) {
1161 std::vector<std::string> accounts = options[
"disable-subjective-account-billing"].as<std::vector<std::string>>();
1162 for(
const auto&
a : accounts ) {
1174 ilog(
"producer plugin: plugin_startup() begin");
1178 "node cannot have any producer-name configured because block production is impossible when read_mode is not \"speculative\"" );
1181 "node cannot have any producer-name configured because block production is not safe when validation_mode is not \"full\"" );
1183 SYS_ASSERT( my->_producers.empty() || my->chain_plug->accept_transactions(), plugin_config_exception,
1184 "node cannot have any producer-name configured because no block production is possible with no [api|p2p]-accepted-transactions" );
1186 my->_accepted_block_connection.emplace(chain.
accepted_block.connect( [
this](
const auto& bsp ){ my->on_block( bsp ); } ));
1187 my->_accepted_block_header_connection.emplace(chain.
accepted_block_header.connect( [
this](
const auto& bsp ){ my->on_block_header( bsp ); } ));
1188 my->_irreversible_block_connection.emplace(chain.
irreversible_block.connect( [
this](
const auto& bsp ){ my->on_irreversible_block( bsp->block ); } ));
1193 my->on_irreversible_block(lib);
1198 if (!my->_producers.empty()) {
1199 ilog(
"Launching block production for ${n} producers at ${time}.", (
"n", my->_producers.size())(
"time",
fc::time_point::now()));
1201 if (my->_production_enabled) {
1208 my->schedule_production_loop();
1210 ilog(
"producer plugin: plugin_startup() end");
1220 my->_timer.cancel();
1221 }
catch (
const std::bad_alloc& ) {
1223 }
catch (
const boost::interprocess::bad_alloc& ) {
1227 }
catch(
const std::exception& e) {
1231 if( my->_thread_pool ) {
1232 my->_thread_pool->stop();
1235 app().
post( 0, [me = my](){} );
1250 my->_pause_production =
true;
1254 my->_pause_production =
false;
1260 fc_ilog(
_log,
"Producer resumed. Scheduling production.");
1261 my->schedule_production_loop();
1268 return my->_pause_production;
1273 bool check_speculating =
false;
1275 if (options.max_transaction_time) {
1276 my->_max_transaction_time_ms = *options.max_transaction_time;
1279 if (options.max_irreversible_block_age) {
1280 my->_max_irreversible_block_age_us =
fc::seconds(*options.max_irreversible_block_age);
1281 check_speculating =
true;
1284 if (options.produce_time_offset_us) {
1285 my->_produce_time_offset_us = *options.produce_time_offset_us;
1288 if (options.last_block_time_offset_us) {
1289 my->_last_block_time_offset_us = *options.last_block_time_offset_us;
1292 if (options.max_scheduled_transaction_time_per_block_ms) {
1293 my->_max_scheduled_transaction_time_per_block_ms = *options.max_scheduled_transaction_time_per_block_ms;
1296 if (options.incoming_defer_ratio) {
1297 my->_incoming_defer_ratio = *options.incoming_defer_ratio;
1302 my->schedule_production_loop();
1305 if (options.subjective_cpu_leeway_us) {
1309 if (options.greylist_limit) {
1316 my->_max_transaction_time_ms,
1317 my->_max_irreversible_block_age_us.count() < 0 ? -1 : my->_max_irreversible_block_age_us.count() / 1'000'000,
1318 my->_produce_time_offset_us,
1319 my->_last_block_time_offset_us,
1320 my->_max_scheduled_transaction_time_per_block_ms,
1321 my->chain_plug->chain().get_subjective_cpu_leeway() ?
1322 my->chain_plug->chain().get_subjective_cpu_leeway()->count() :
1323 std::optional<int32_t>(),
1324 my->_incoming_defer_ratio,
1325 my->chain_plug->chain().get_greylist_limit()
1351 result.accounts.reserve(list.size());
1352 for (
auto &acc: list) {
1353 result.accounts.push_back(acc);
1372 chain::invalid_http_request,
1373 "At least one of actor_whitelist, actor_blacklist, contract_whitelist, contract_blacklist, action_blacklist, and key_blacklist is required"
1389 my->schedule_production_loop();
1396 reschedule.cancel();
1413 auto ex = snapshot_exists_exception(
FC_LOG_MESSAGE( error,
"snapshot named ${name} already exists", (
"name", snapshot_path.generic_string()) ) );
1414 next(ex.dynamic_copy_exception());
1418 auto write_snapshot = [&](
const bfs::path&
p ) ->
void {
1420 my->schedule_production_loop();
1427 reschedule.cancel();
1430 bfs::create_directory(
p.parent_path() );
1433 auto snap_out = std::ofstream(
p.generic_string(), (std::ios::out | std::ios::binary));
1434 auto writer = std::make_shared<ostream_snapshot_writer>(snap_out);
1444 write_snapshot( temp_path );
1446 boost::system::error_code ec;
1447 bfs::rename(temp_path, snapshot_path, ec);
1448 SYS_ASSERT(!ec, snapshot_finalization_exception,
1449 "Unable to finalize valid snapshot of block number ${bn}: [code: ${ec}] ${message}",
1450 (
"bn", head_block_num)
1452 (
"message", ec.message()));
1462 auto& pending_by_id = my->_pending_snapshot_index.get<by_id>();
1463 auto existing = pending_by_id.find(head_id);
1464 if( existing != pending_by_id.end() ) {
1466 pending_by_id.modify(existing, [&next](
auto& entry ){
1467 entry.next = [prev = entry.next, next](
const std::variant<fc::exception_ptr, producer_plugin::snapshot_information>& res){
1476 write_snapshot( temp_path );
1478 boost::system::error_code ec;
1479 bfs::rename(temp_path, pending_path, ec);
1480 SYS_ASSERT(!ec, snapshot_finalization_exception,
1481 "Unable to promote temp snapshot to pending for block number ${bn}: [code: ${ec}] ${message}",
1482 (
"bn", head_block_num)
1484 (
"message", ec.message()));
1486 my->_pending_snapshot_index.emplace(head_id, next, pending_path.generic_string(), snapshot_path.generic_string());
1493 return {my->_protocol_features_to_activate};
1498 std::set<digest_type> set_of_features_to_activate( schedule.protocol_features_to_activate.begin(),
1499 schedule.protocol_features_to_activate.end() );
1500 SYS_ASSERT( set_of_features_to_activate.size() == schedule.protocol_features_to_activate.size(),
1501 invalid_protocol_features_to_activate,
"duplicate digests" );
1504 for (
auto &feature_digest : set_of_features_to_activate) {
1505 const auto& pf = pfs.get_protocol_feature(feature_digest);
1506 SYS_ASSERT( !pf.preactivation_required, protocol_feature_exception,
1507 "protocol feature requires preactivation: ${digest}",
1508 (
"digest", feature_digest));
1510 my->_protocol_features_to_activate = schedule.protocol_features_to_activate;
1511 my->_protocol_features_signaled =
false;
1520 flat_map<digest_type, bool> visited_protocol_features;
1521 visited_protocol_features.reserve( pfs.size() );
1524 [&
results, &pfs, &
params, next_block_time, &visited_protocol_features, &add_feature]
1526 if( (
params.exclude_disabled ||
params.exclude_unactivatable ) && !pf.enabled )
return false;
1527 if(
params.exclude_unactivatable && ( next_block_time < pf.earliest_allowed_activation_time ) )
return false;
1529 auto res = visited_protocol_features.emplace( pf.feature_digest,
false );
1530 if( !res.second )
return res.first->second;
1532 const auto original_size =
results.size();
1533 for(
const auto& dependency : pf.dependencies ) {
1534 if( !add_feature( pfs.get_protocol_feature( dependency ) ) ) {
1535 results.resize( original_size );
1540 res.first->second =
true;
1541 results.emplace_back( pf.to_variant(
true) );
1545 for(
const auto& pf : pfs ) {
1555 const auto& db = my->chain_plug->chain().db();
1558 account_name lower_bound_value{ std::numeric_limits<uint64_t>::lowest() };
1559 account_name upper_bound_value{ std::numeric_limits<uint64_t>::max() };
1561 if(
params.lower_bound ) {
1562 lower_bound_value = *
params.lower_bound;
1565 if(
params.upper_bound ) {
1566 upper_bound_value = *
params.upper_bound;
1569 if( upper_bound_value < lower_bound_value )
1572 auto walk_range = [&](
auto itr,
auto end_itr ) {
1573 for(
unsigned int count = 0;
1580 if( itr != end_itr ) {
1581 result.more = itr->name;
1585 auto lower = idx.lower_bound( lower_bound_value );
1586 auto upper = idx.upper_bound( upper_bound_value );
1588 walk_range( boost::make_reverse_iterator(upper), boost::make_reverse_iterator(lower) );
1590 walk_range( lower, upper );
1599 const auto& active_schedule = hbs->active_schedule.producers;
1602 auto itr = std::find_if(active_schedule.begin(), active_schedule.end(), [&](
const auto& asp){ return asp.producer_name == producer_name; });
1603 if (itr == active_schedule.end()) {
1605 return std::optional<fc::time_point>();
1608 size_t producer_index = itr - active_schedule.begin();
1617 if (current_watermark) {
1618 const auto watermark = *current_watermark;
1623 if (watermark.first > block_num) {
1625 minimum_offset = watermark.first - block_num + 1;
1627 if (watermark.second > current_block_time) {
1629 minimum_offset = std::max(minimum_offset, watermark.second.slot - current_block_time.
slot + 1);
1634 uint32_t minimum_slot = current_block_time.
slot + minimum_offset;
1635 size_t minimum_slot_producer_index = (minimum_slot % (active_schedule.size() * config::producer_repetitions)) / config::producer_repetitions;
1636 if ( producer_index == minimum_slot_producer_index ) {
1641 size_t producer_distance = producer_index - minimum_slot_producer_index;
1643 if (producer_distance > producer_index) {
1644 producer_distance += active_schedule.size();
1648 uint32_t first_minimum_producer_slot = minimum_slot - (minimum_slot % config::producer_repetitions);
1651 uint32_t next_block_slot = first_minimum_producer_slot + (producer_distance * config::producer_repetitions);
1660 const int64_t min_time_to_next_block = (config::block_interval_us) - (base.time_since_epoch().count() % (config::block_interval_us) );
1667 bool last_block = ((
block_timestamp_type( block_time ).
slot % config::producer_repetitions) == config::producer_repetitions - 1);
1704 const auto& scheduled_producer = hbs->get_scheduled_producer(block_time);
1706 const auto current_watermark =
get_watermark(scheduled_producer.producer_name);
1708 size_t num_relevant_signatures = 0;
1712 num_relevant_signatures++;
1723 }
else if (num_relevant_signatures == 0) {
1724 elog(
"Not producing block because I don't have any private keys relevant to authority: ${authority}", (
"authority", scheduled_producer.authority));
1727 elog(
"Not producing block because production is explicitly paused");
1730 elog(
"Not producing block because the irreversible block is too old [age:${age}s, max:${max}s]", (
"age", irreversible_block_age.count() / 1'000'000)(
"max",
_max_irreversible_block_age_us.
count() / 1'000'000 ));
1736 if (current_watermark) {
1738 if (current_watermark->first > hbs->block_num) {
1739 elog(
"Not producing block because \"${producer}\" signed a block at a higher block number (${watermark}) than the current fork's head (${head_block_num})",
1740 (
"producer", scheduled_producer.producer_name)
1741 (
"watermark", current_watermark->first)
1742 (
"head_block_num", hbs->block_num));
1745 elog(
"Not producing block because \"${producer}\" signed a block at the next block time or later (${watermark}) than the pending block time (${block_timestamp})",
1746 (
"producer", scheduled_producer.producer_name)
1747 (
"watermark", current_watermark->second)
1761 const auto start_block_time = block_time -
fc::microseconds( config::block_interval_us );
1762 if( now < start_block_time ) {
1763 fc_dlog(
_log,
"Not producing block waiting for production window ${n} ${bt}", (
"n", hbs->block_num + 1)(
"bt", block_time) );
1770 const auto start_block_time = block_time -
fc::microseconds( config::block_interval_us );
1771 fc_dlog(
_log,
"Not starting speculative block until ${bt}", (
"bt", start_block_time) );
1776 fc_dlog(
_log,
"Starting block #${n} at ${time} producer ${p}",
1777 (
"n", hbs->block_num + 1)(
"time", now)(
"p", scheduled_producer.producer_name));
1789 if (current_watermark) {
1790 auto watermark_bn = current_watermark->first;
1791 if (watermark_bn < hbs->block_num) {
1792 blocks_to_confirm = (
uint16_t)(std::min<uint32_t>(std::numeric_limits<uint16_t>::max(), (
uint32_t)(hbs->block_num - watermark_bn)));
1797 blocks_to_confirm = (
uint16_t)(std::min<uint32_t>(blocks_to_confirm, (
uint32_t)(hbs->block_num - hbs->dpos_irreversible_blocknum)));
1804 bool drop_features_to_activate =
false;
1807 }
catch (
const std::bad_alloc& ) {
1809 }
catch (
const boost::interprocess::bad_alloc& ) {
1812 wlog(
"protocol features to activate are no longer all valid: ${details}",
1814 drop_features_to_activate =
true;
1815 }
catch(
const std::exception& e ) {
1816 wlog(
"protocol features to activate are no longer all valid: ${details}",
1818 drop_features_to_activate =
true;
1821 if( drop_features_to_activate ) {
1825 if( features_to_activate.size() > 0 ) {
1826 protocol_features_to_activate.reserve( protocol_features_to_activate.size()
1827 + features_to_activate.size() );
1828 std::set<digest_type> set_of_features_to_activate( protocol_features_to_activate.begin(),
1829 protocol_features_to_activate.end() );
1830 for(
const auto&
f : features_to_activate ) {
1831 auto res = set_of_features_to_activate.insert(
f );
1833 protocol_features_to_activate.push_back(
f );
1836 features_to_activate.clear();
1838 std::swap( features_to_activate, protocol_features_to_activate );
1840 ilog(
"signaling activation of the following protocol features in block ${num}: ${features_to_activate}",
1841 (
"num", hbs->block_num + 1)(
"features_to_activate", features_to_activate) );
1845 chain.
start_block( block_time, blocks_to_confirm, features_to_activate, preprocess_deadline );
1852 elog(
"Unexpected block signing authority, reverting to speculative mode! [expected: \"${expected}\", actual: \"${actual\"", (
"expected", scheduled_producer.authority)(
"actual", pending_block_signing_authority));
1864 [&](){ return should_interrupt_start_block( preprocess_deadline ); } ) ) {
1875 auto scheduled_trx_deadline = preprocess_deadline;
1877 scheduled_trx_deadline = std::min<fc::time_point>(
1878 scheduled_trx_deadline,
1886 if(
app().is_quiting() )
1899 }
catch ( std::bad_alloc& ) {
1901 }
catch ( boost::interprocess::bad_alloc& ) {
1916 size_t num_expired_persistent = 0;
1917 size_t num_expired_other = 0;
1922 if( trx_type == trx_enum_type::persisted ) {
1925 "[TRX_TRACE] Block ${block_num} for producer ${prod} is EXPIRING PERSISTED tx: ${txid}",
1926 (
"block_num", chain.
head_block_num() + 1)(
"txid", packed_trx_ptr->id())
1928 fc_dlog(
_trx_log,
"[TRX_TRACE] Block ${block_num} for producer ${prod} is EXPIRING PERSISTED tx: ${trx}",
1940 fc_dlog(
_trx_log,
"[TRX_TRACE] Speculative execution is EXPIRING PERSISTED tx: ${trx}",
1945 ++num_expired_persistent;
1947 if (has_producers) {
1949 "[TRX_TRACE] Node with producers configured is dropping an EXPIRED transaction that was PREVIOUSLY ACCEPTED : ${txid}",
1950 (
"txid", packed_trx_ptr->id()));
1952 fc_dlog(
_trx_log,
"[TRX_TRACE] Node with producers configured is dropping an EXPIRED transaction that was PREVIOUSLY ACCEPTED: ${trx}",
1954 fc_dlog(
_trx_trace_failure_log,
"[TRX_TRACE] Node with producers configured is dropping an EXPIRED transaction that was PREVIOUSLY ACCEPTED: ${entire_trx}",
1957 ++num_expired_other;
1962 fc_wlog(
_log,
"Unable to process all expired transactions in unapplied queue before deadline, "
1963 "Persistent expired ${persistent_expired}, Other expired ${other_expired}",
1964 (
"persistent_expired", num_expired_persistent)(
"other_expired", num_expired_other) );
1966 fc_dlog(
_log,
"Processed ${m} expired transactions of the ${n} transactions in the unapplied queue, "
1967 "Persistent expired ${persistent_expired}, Other expired ${other_expired}",
1968 (
"m", num_expired_persistent+num_expired_other)(
"n", orig_count)
1969 (
"persistent_expired", num_expired_persistent)(
"other_expired", num_expired_other) );
1979 if(!blacklist_by_expiry.empty()) {
1983 int num_expired = 0;
1986 while (!blacklist_by_expiry.empty() && blacklist_by_expiry.begin()->expiry <= lib_time) {
1991 blacklist_by_expiry.erase(blacklist_by_expiry.begin());
1995 fc_dlog(
_log,
"Processed ${n} blacklisted transactions, Expired ${expired}",
1996 (
"n", orig_count)(
"expired", num_expired));
2007 int num_applied = 0, num_failed = 0, num_processed = 0;
2014 while( itr != end_itr ) {
2025 auto first_auth = trx->packed_trx()->get_transaction().first_authorizer();
2029 itr->next( std::make_shared<tx_cpu_usage_exceeded>(
2030 FC_LOG_MESSAGE( error,
"transaction ${id} exceeded failure limit for account ${a}",
2031 (
"id", trx->id())(
"a", first_auth) ) ) );
2040 auto prev_billed_cpu_time_us = trx->billed_cpu_time_us;
2042 uint64_t prev_billed_plus100_us = prev_billed_cpu_time_us +
SYS_PERCENT( prev_billed_cpu_time_us, 100 * config::percent_1 );
2043 if( prev_billed_plus100_us < max_trx_time.
count() ) max_trx_time =
fc::microseconds( prev_billed_plus100_us );
2053 auto trace = chain.
push_transaction( trx, deadline, max_trx_time, prev_billed_cpu_time_us,
false, sub_bill );
2054 fc_dlog(
_trx_failed_trace_log,
"Subjective unapplied bill for ${a}: ${b} prev ${t}us", (
"a",first_auth)(
"b",prev_billed_cpu_time_us)(
"t",trace->elapsed));
2055 if( trace->except ) {
2056 if( exception_is_exhausted( *trace->except ) ) {
2063 fc_dlog(
_trx_failed_trace_log,
"Subjective unapplied bill for failed ${a}: ${b} prev ${t}us", (
"a",first_auth)(
"b",prev_billed_cpu_time_us)(
"t",trace->elapsed));
2064 auto failure_code = trace->except->code();
2065 if( failure_code != tx_duplicate::code_value ) {
2067 fc_dlog(
_log,
"Failed ${c} trx, prev billed: ${p}us, ran: ${r}us, id: ${id}",
2068 (
"c", trace->except->code())(
"p", prev_billed_cpu_time_us)
2071 if (!disable_subjective_billing)
2076 itr->next( trace->except->dynamic_copy_exception() );
2082 fc_dlog(
_trx_successful_trace_log,
"Subjective unapplied bill for success ${a}: ${b} prev ${t}us", (
"a",first_auth)(
"b",prev_billed_cpu_time_us)(
"t",trace->elapsed));
2084 if (!disable_subjective_billing)
2088 if( itr->trx_type != trx_enum_type::persisted ) {
2089 if( itr->next ) itr->next( trace );
2098 fc_dlog(
_log,
"Processed ${m} of ${n} previously applied transactions, Applied ${applied}, Failed/Dropped ${failed}",
2099 (
"m", num_processed)(
"n", unapplied_trxs_size )(
"applied", num_applied)(
"failed", num_failed) );
2107 int num_applied = 0;
2109 int num_processed = 0;
2111 double incoming_trx_weight = 0.0;
2115 time_point pending_block_time = chain.pending_block_time();
2119 const auto scheduled_trxs_size = sch_idx.size();
2120 auto sch_itr = sch_idx.begin();
2121 while( sch_itr != sch_idx.end() ) {
2122 if( sch_itr->delay_until > pending_block_time)
break;
2127 if( sch_itr->published >= pending_block_time ) {
2132 if (blacklist_by_id.find(sch_itr->trx_id) != blacklist_by_id.end()) {
2138 const auto sch_expiration = sch_itr->expiration;
2139 auto sch_itr_next = sch_itr;
2141 const auto next_delay_until = sch_itr_next != sch_idx.end() ? sch_itr_next->delay_until : sch_itr->delay_until;
2142 const auto next_id = sch_itr_next != sch_idx.end() ? sch_itr_next->id : sch_itr->id;
2147 while (incoming_trx_weight >= 1.0 && pending_incoming_process_limit && itr != end ) {
2153 --pending_incoming_process_limit;
2154 incoming_trx_weight -= 1.0;
2156 auto trx_meta = itr->trx_meta;
2157 auto next = itr->next;
2158 bool persist_until_expired = itr->trx_type == trx_enum_type::incoming_persisted;
2159 bool return_failure_trace = itr->return_failure_trace;
2176 auto trace = chain.push_scheduled_transaction(trx_id, deadline, max_trx_time, 0,
false);
2177 if (trace->except) {
2178 if (exception_is_exhausted(*trace->except)) {
2194 if (!pending_incoming_process_limit) incoming_trx_weight = 0.0;
2196 if( sch_itr_next == sch_idx.end() )
break;
2197 sch_itr = sch_idx.lower_bound( boost::make_tuple( next_delay_until, next_id ) );
2200 if( scheduled_trxs_size > 0 ) {
2202 "Processed ${m} of ${n} scheduled transactions, Applied ${applied}, Failed/Dropped ${failed}",
2203 (
"m", num_processed )(
"n", scheduled_trxs_size )(
"applied", num_applied )(
"failed", num_failed ) );
2210 if( pending_incoming_process_limit ) {
2211 size_t processed = 0;
2212 fc_dlog(
_log,
"Processing ${n} pending transactions", (
"n", pending_incoming_process_limit) );
2215 while( pending_incoming_process_limit && itr != end ) {
2220 --pending_incoming_process_limit;
2222 auto trx_meta = itr->trx_meta;
2223 auto next = itr->next;
2224 bool persist_until_expired = itr->trx_type == trx_enum_type::incoming_persisted;
2225 bool return_failure_trace = itr->return_failure_trace;
2244 const uint64_t net_limit = rl.get_block_net_limit();
2262 elog(
"Failed to start a pending block, will try again later");
2263 _timer.expires_from_now( boost::posix_time::microseconds( config::block_interval_us / 10 ));
2267 [weak_this = weak_from_this(), cid = ++
_timer_corelation_id](
const boost::system::error_code& ec ) {
2268 auto self = weak_this.lock();
2269 if(
self && ec != boost::asio::error::operation_aborted && cid ==
self->_timer_corelation_id ) {
2270 self->schedule_production_loop();
2275 fc_dlog(
_log,
"Waiting till another block is received and scheduling Speculative/Production Change");
2278 fc_dlog(
_log,
"Waiting till another block is received");
2290 fc_dlog(
_log,
"Speculative Block Created; Scheduling Speculative/Production Change");
2302 static const boost::posix_time::ptime epoch( boost::gregorian::date( 1970, 1, 1 ) );
2308 "producing without pending_block_state, start_block succeeded" );
2309 _timer.expires_at( epoch + boost::posix_time::microseconds( deadline.time_since_epoch().count() ) );
2310 fc_dlog(
_log,
"Scheduling Block Production on Normal Block #${num} for ${time}",
2314 _timer.expires_from_now( boost::posix_time::microseconds( 0 ) );
2315 fc_dlog(
_log,
"Scheduling Block Production on ${desc} Block #${num} immediately",
2320 [&chain, weak_this = weak_from_this(), cid=++
_timer_corelation_id](
const boost::system::error_code& ec) {
2321 auto self = weak_this.lock();
2322 if(
self && ec != boost::asio::error::operation_aborted && cid ==
self->_timer_corelation_id ) {
2326 auto res =
self->maybe_produce_block();
2327 fc_dlog(
_log,
"Producing Block #${num} returned: ${res}", (
"num", block_num)(
"res", res ) );
2334 std::optional<fc::time_point> wake_up_time;
2337 if (next_producer_block_time) {
2338 auto producer_wake_up_time = *next_producer_block_time -
fc::microseconds(config::block_interval_us);
2341 if( producer_wake_up_time < *wake_up_time ) {
2342 wake_up_time = producer_wake_up_time;
2345 wake_up_time = producer_wake_up_time;
2349 if( !wake_up_time ) {
2350 fc_dlog(
_log,
"Not Scheduling Speculative/Production, no local producers had valid wake up times");
2353 return wake_up_time;
2358 fc_dlog(
_log,
"Scheduling Speculative/Production Change at ${time}", (
"time", wake_up_time));
2359 static const boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
2360 _timer.expires_at(epoch + boost::posix_time::microseconds(wake_up_time->time_since_epoch().count()));
2363 auto self = weak_this.lock();
2364 if(
self && ec != boost::asio::error::operation_aborted && cid ==
self->_timer_corelation_id ) {
2365 self->schedule_production_loop();
2382 fc_dlog(
_log,
"Aborting block due to produce_block error");
2387static auto make_debug_time_logger() {
2394static auto maybe_make_debug_time_logger() -> std::optional<
decltype(make_debug_time_logger())> {
2396 return make_debug_time_logger();
2406 SYS_ASSERT(chain.
is_building_block(), missing_pending_block_state,
"pending_block_state does not exist but it should, another plugin may have corrupted it");
2409 std::vector<std::reference_wrapper<const signature_provider_type>> relevant_providers;
2416 relevant_providers.emplace_back(iter->second);
2420 SYS_ASSERT(relevant_providers.size() > 0, producer_priv_key_not_found,
"Attempting to produce a block for which we don't have any relevant private keys");
2435 if (!relevant_s_transactions.empty()) {
2436 ilog(
"Relevant S-Transactions found: ${count}", (
"count", relevant_s_transactions.size()));
2439 checksum256_type s_root = sub_chain_plug.calculate_s_root(relevant_s_transactions);
2440 ilog(
"s_root calculated: ${root}", (
"root", s_root.
str()));
2445 ilog(
"curr_s_id calculated: ${curr_s_id}", (
"curr_s_id", curr_s_id.
str()));
2448 sub_chain_plug.get_contract_name(),
2449 sub_chain_plug.get_prev_s_id(),
2460 sub_chain_plug.update_prev_s_id(curr_s_id);
2465 auto debug_logger = maybe_make_debug_time_logger();
2467 sigs.reserve(relevant_providers.size());
2470 for (
const auto&
p : relevant_providers) {
2471 sigs.emplace_back(
p.get()(
d));
2483 ilog(
"Produced block ${id}... #${n} @ ${t} signed by ${p} [trxs: ${count}, lib: ${lib}, confirmed: ${confs}]",
2484 (
"p",new_bs->header.producer)(
"id",new_bs->id.str().substr(8,16))
2485 (
"n",new_bs->block_num)(
"t",new_bs->header.timestamp)
2491 my->_received_block =
true;
2496 (
"txid", trx_id)(
"why", reason));
2497 fc_dlog(
_trx_log,
"[TRX_TRACE] Speculative execution is REJECTING tx: ${trx}",
2498 (
"entire_trx", packed_trx_ptr ? my->chain_plug->get_log_trx(packed_trx_ptr->get_transaction()) :
fc::variant{trx_id}));
2500 (
"entire_trx", packed_trx_ptr ? my->chain_plug->get_log_trx(packed_trx_ptr->get_transaction()) :
fc::variant{trx_id}));
constexpr uint64_t SYS_PERCENT(uint64_t value, uint32_t percentage)
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
#define CATCH_AND_CALL(NEXT)
#define LOAD_VALUE_SET(options, op_name, container)
abstract_plugin * find_plugin(const string &name) const
abstract_plugin & get_plugin(const string &name) const
bfs::path data_dir() const
Get data directory.
auto post(int priority, Func &&func)
auto get_method() -> std::enable_if_t< is_method_decl< MethodDecl >::value, typename MethodDecl::method_type & >
auto get_channel() -> std::enable_if_t< is_channel_decl< ChannelDecl >::value, typename ChannelDecl::channel_type & >
static private_key regenerate(const typename KeyType::data_type &data)
Used to generate a useful error report when an exception is thrown.
std::string to_detail_string(log_level ll=log_level::all) const
static variant from_string(const string &utf8_str, const parse_type ptype=parse_type::legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
static void update(const fc::string &name, logger &log)
bool is_enabled(log_level e) const
constexpr int64_t to_seconds() const
constexpr int64_t count() const
static constexpr microseconds maximum()
An order-preserving dictionary of variants.
static sha256 hash(const char *d, uint32_t dlen)
static std_exception_wrapper from_current_exception(const std::exception &e)
static constexpr time_point maximum()
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
fc::time_point to_time_point() const
void set_greylist_limit(uint32_t limit)
void set_actor_whitelist(const flat_set< account_name > &)
const flat_set< account_name > & get_actor_blacklist() const
signal< void(const block_state_ptr &)> accepted_block_header
validation_mode get_validation_mode() const
signed_block_ptr fetch_block_by_number(uint32_t block_num) const
void set_actor_blacklist(const flat_set< account_name > &)
signal< void(const block_state_ptr &)> accepted_block
signal< void(const block_state_ptr &)> irreversible_block
bool is_building_block() const
db_read_mode get_read_mode() const
vector< transaction_metadata_ptr > abort_block()
transaction_trace_ptr push_transaction(const transaction_metadata_ptr &trx, fc::time_point deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time, int64_t subjective_cpu_bill_us)
uint32_t head_block_num() const
block_id_type head_block_id() const
block_state_ptr head_block_state() const
void write_snapshot(const snapshot_writer_ptr &snapshot)
uint32_t last_irreversible_block_num() const
void set_key_blacklist(const flat_set< public_key_type > &)
void set_s_header(const s_header &)
const protocol_feature_manager & get_protocol_feature_manager() const
uint32_t configured_subjective_signature_length_limit() const
const flat_set< account_name > & get_contract_whitelist() const
account_name pending_block_producer() const
const block_signing_authority & pending_block_signing_authority() const
signed_block_ptr fetch_block_by_id(block_id_type id) const
time_point last_irreversible_block_time() const
const flat_set< pair< account_name, action_name > > & get_action_blacklist() const
uint32_t get_terminate_at_block() const
void set_contract_blacklist(const flat_set< account_name > &)
block_state_ptr finalize_block(const signer_callback_type &signer_callback)
const flat_set< account_name > & get_contract_blacklist() const
void remove_resource_greylist(const account_name &name)
chain_id_type get_chain_id() const
const flat_set< public_key_type > & get_key_blacklist() const
const flat_set< account_name > & get_resource_greylist() const
void set_contract_whitelist(const flat_set< account_name > &)
time_point pending_block_time() const
void validate_protocol_features(const vector< digest_type > &features_to_activate) const
vector< digest_type > get_preactivated_protocol_features() const
void set_subjective_cpu_leeway(fc::microseconds leeway)
void add_resource_greylist(const account_name &name)
bool is_known_unexpired_transaction(const transaction_id_type &id) const
sha256 calculate_integrity_hash()
const flat_set< account_name > & get_actor_whitelist() const
time_point head_block_time() const
const resource_limits_manager & get_resource_limits_manager() const
controller_impl
void set_action_blacklist(const flat_set< pair< account_name, action_name > > &)
void start_block(block_timestamp_type time=block_timestamp_type(), uint16_t confirm_block_count=0)
const protocol_feature_set & get_protocol_feature_set() const
uint64_t get_block_cpu_limit() const
bool clear_expired(const time_point &pending_block_time, Yield &&yield, Callback &&callback)
size_t incoming_size() const
iterator incoming_begin()
iterator unapplied_begin()
void add_forked(const branch_type &forked_branch)
iterator erase(iterator itr)
caller's responsibility to call next() if applicable
void add_aborted(std::vector< transaction_metadata_ptr > aborted_trxs)
iterator persisted_begin()
void clear_applied(const block_state_ptr &bs)
transaction_metadata_ptr get_trx(const transaction_id_type &id) const
static void handle_db_exhaustion()
static void handle_guard_exception(const chain::guard_exception &e)
static void handle_bad_alloc()
bool accept_transactions() const
fc::variant get_log_trx(const transaction &trx) const
producer_plugin::next_function< producer_plugin::snapshot_information > next_t
static bfs::path get_pending_path(const block_id_type &block_id, const bfs::path &snapshots_dir)
uint32_t get_height() const
static bfs::path get_temp_path(const block_id_type &block_id, const bfs::path &snapshots_dir)
pending_snapshot(const block_id_type &block_id, next_t &next, std::string pending_path, std::string final_path)
producer_plugin::snapshot_information finalize(const chain::controller &chain) const
static bfs::path get_final_path(const block_id_type &block_id, const bfs::path &snapshots_dir)
fc::microseconds get_irreversible_block_age()
bool remove_expired_trxs(const fc::time_point &deadline)
void on_block_header(const block_state_ptr &bsp)
bool should_interrupt_start_block(const fc::time_point &deadline) const
void on_block(const block_state_ptr &bsp)
bool _disable_persist_until_expired
void schedule_delayed_production_loop(const std::weak_ptr< producer_plugin_impl > &weak_this, std::optional< fc::time_point > wake_up_time)
transaction_id_with_expiry_index _blacklisted_transactions
uint32_t _timer_corelation_id
void on_incoming_transaction_async(const packed_transaction_ptr &trx, bool persist_until_expired, bool read_only, bool return_failure_traces, next_function< transaction_trace_ptr > next)
bool maybe_produce_block()
bool process_incoming_transaction_async(const transaction_metadata_ptr &trx, bool persist_until_expired, bool return_failure_traces, next_function< transaction_trace_ptr > next)
fc::microseconds _kiod_provider_timeout_us
std::optional< scoped_connection > _irreversible_block_connection
std::optional< scoped_connection > _accepted_block_connection
bool _disable_subjective_p2p_billing
bool _protocol_features_signaled
incoming::methods::transaction_async::method_type::handle _incoming_transaction_async_provider
void schedule_maybe_produce_block(bool exhausted)
std::map< chain::account_name, producer_watermark > _producer_watermarks
bool remove_expired_blacklisted_trxs(const fc::time_point &deadline)
incoming::methods::block_sync::method_type::handle _incoming_block_sync_provider
void on_irreversible_block(const signed_block_ptr &lib)
std::optional< fc::time_point > calculate_producer_wake_up_time(const block_timestamp_type &ref_block_time) const
double _incoming_defer_ratio
fc::time_point _irreversible_block_time
compat::channels::transaction_ack::channel_type & _transaction_ack_channel
bool process_incoming_trxs(const fc::time_point &deadline, size_t &pending_incoming_process_limit)
std::optional< scoped_connection > _accepted_block_header_connection
bool production_disabled_by_policy()
producer_plugin_impl(boost::asio::io_service &io)
start_block_result start_block()
bool process_unapplied_trxs(const fc::time_point &deadline)
int32_t _produce_time_offset_us
std::optional< producer_watermark > get_watermark(account_name producer) const
fc::time_point calculate_block_deadline(const fc::time_point &) const
std::optional< fc::time_point > calculate_next_block_time(const account_name &producer_name, const block_timestamp_type ¤t_block_time) const
bool on_incoming_block(const signed_block_ptr &block, const std::optional< block_id_type > &block_id, const block_state_ptr &bsp)
int32_t _last_block_time_offset_us
std::atomic< bool > _received_block
boost::asio::deadline_timer _timer
bool block_is_exhausted() const
int32_t _max_scheduled_transaction_time_per_block_ms
boost::program_options::variables_map _options
void restart_speculative_block()
std::vector< chain::digest_type > _protocol_features_to_activate
unapplied_transaction_queue _unapplied_transactions
std::atomic< int32_t > _max_transaction_time_ms
std::optional< named_thread_pool > _thread_pool
pending_snapshot_index _pending_snapshot_index
uint32_t _max_block_cpu_usage_threshold_us
uint32_t _max_block_net_usage_threshold_bytes
std::function< chain::signature_type(chain::digest_type)> signature_provider_type
subjective_billing _subjective_billing
chain_plugin * chain_plug
void schedule_production_loop()
std::map< chain::public_key_type, signature_provider_type > _signature_providers
void consider_new_watermark(account_name producer, uint32_t block_num, block_timestamp_type timestamp)
fc::microseconds _max_irreversible_block_age_us
bool _disable_subjective_api_billing
pending_block_mode _pending_block_mode
std::pair< uint32_t, block_timestamp_type > producer_watermark
std::set< chain::account_name > _producers
void process_scheduled_and_incoming_trxs(const fc::time_point &deadline, size_t &pending_incoming_process_limit)
fc::time_point calculate_pending_block_time() const
account_failures _account_fails
account_name get_pending_block_producer()
virtual void plugin_initialize(const boost::program_options::variables_map &options)
greylist_params get_greylist() const
virtual void set_program_options(boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options) override
chain::signature_type sign_compact(const chain::public_key_type &key, const fc::sha256 &digest) const
virtual void plugin_shutdown()
void create_snapshot(next_function< snapshot_information > next)
void remove_greylist_accounts(const greylist_params ¶ms)
runtime_options get_runtime_options() const
bool is_producer_key(const chain::public_key_type &key) const
void add_greylist_accounts(const greylist_params ¶ms)
void handle_sighup() override
fc::variants get_supported_protocol_features(const get_supported_protocol_features_params ¶ms) const
std::function< void(const std::variant< fc::exception_ptr, T > &)> next_function
virtual ~producer_plugin()
whitelist_blacklist get_whitelist_blacklist() const
void schedule_protocol_feature_activations(const scheduled_protocol_feature_activations &schedule)
void set_whitelist_blacklist(const whitelist_blacklist ¶ms)
void log_failed_transaction(const transaction_id_type &trx_id, const chain::packed_transaction_ptr &packed_trx_ptr, const char *reason) const
virtual void plugin_startup()
int64_t get_subjective_bill(const account_name &first_auth, const fc::time_point &now) const
get_account_ram_corrections_result get_account_ram_corrections(const get_account_ram_corrections_params ¶ms) const
void update_runtime_options(const runtime_options &options)
scheduled_protocol_feature_activations get_scheduled_protocol_feature_activations() const
integrity_hash_information get_integrity_hash() const
std::vector< sysio::chain::transaction > find_relevant_transactions(sysio::chain::controller &curr_chain)
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)
bool remove_expired(fc::logger &log, const fc::time_point &pending_block_time, const fc::time_point &now, Yield &&yield)
bool is_account_disabled(const account_name &a) const
void on_block(fc::logger &log, const block_state_ptr &bsp, const fc::time_point &now)
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_LOG_AND_RETHROW()
#define FC_LOG_MESSAGE(LOG_LEVEL, FORMAT,...)
A helper method for generating log messages.
#define fc_ilog(LOGGER, FORMAT,...)
#define fc_wlog(LOGGER, FORMAT,...)
#define fc_dlog(LOGGER, FORMAT,...)
fc::sha256 digest(const T &value)
std::shared_ptr< exception > exception_ptr
std::optional< fc::string > ostring
scoped_exit< Callback > make_scoped_exit(Callback &&c)
sysio::chain_apis::account_query_db::get_accounts_by_authorizers_params params
bool exists(const path &p)
fc::string to_string(double)
bool is_regular_file(const path &p)
constexpr microseconds milliseconds(int64_t s)
void create_directories(const path &p)
std::vector< fc::variant > variants
constexpr microseconds seconds(int64_t s)
std::optional< fc::variant_object > ovariant_object
constexpr microseconds minutes(int64_t m)
bool is_directory(const path &p)
fc::string format_string(const fc::string &, const variant_object &, bool minimize=false)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
void swap(picojson::value &x, picojson::value &y)
std::function< void(const std::variant< fc::exception_ptr, T > &)> next_function
fc::crypto::public_key public_key_type
block_timestamp< config::block_interval_ms, config::block_timestamp_epoch > block_timestamp_type
deque< block_state_ptr > branch_type
chainbase::shared_multi_index_container< account_ram_correction_object, indexed_by< ordered_unique< tag< by_id >, member< account_ram_correction_object, account_ram_correction_object::id_type, &account_ram_correction_object::id > >, ordered_unique< tag< by_name >, member< account_ram_correction_object, account_name, &account_ram_correction_object::name > > > > account_ram_correction_index
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit Account name already exists sysio_assert_message assertion failure Action can not be found Attempt to use unaccessible API Inline Action exceeds maximum size limit sysio_assert_code assertion failure uses restricted error code value action return value size too big Permission Query Exception Contract Table Query Exception Database is an unknown or unsupported version guard_exception
std::shared_ptr< const packed_transaction > packed_transaction_ptr
chainbase::shared_multi_index_container< generated_transaction_object, indexed_by< ordered_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, generated_transaction_object::id_type, id)>, ordered_unique< tag< by_trx_id >, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, transaction_id_type, trx_id)>, ordered_unique< tag< by_expiration >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, time_point, expiration), > >, ordered_unique< tag< by_delay >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, time_point, delay_until), > >, ordered_unique< tag< by_sender_id >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, account_name, sender), > > > > generated_transaction_multi_index
std::shared_ptr< signed_block > signed_block_ptr
std::shared_ptr< block_state > block_state_ptr
fc::crypto::private_key private_key_type
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type fork_database_exception
std::shared_ptr< transaction_metadata > transaction_metadata_ptr
fc::crypto::signature signature_type
multi_index_container< pending_snapshot, indexed_by< hashed_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(pending_snapshot, block_id_type, block_id)>, ordered_non_unique< tag< by_height >, BOOST_MULTI_INDEX_CONST_MEM_FUN(pending_snapshot, uint32_t, get_height)> > > pending_snapshot_index
multi_index_container< transaction_id_with_expiry, indexed_by< hashed_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(transaction_id_with_expiry, transaction_id_type, trx_id)>, ordered_non_unique< tag< by_expiry >, BOOST_MULTI_INDEX_MEMBER(transaction_id_with_expiry, fc::time_point, expiry)> > > transaction_id_with_expiry_index
T dejsonify(const string &s)
@ self
the connection is to itself
const fc::string logger_name("net_plugin_impl")
void new_chain_banner(const sysio::chain::controller &db)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
const std::string trx_trace_failure_logger_name("transaction_trace_failure")
const std::string trx_failed_trace_logger_name("transaction_failure_tracing")
fc::logger _trx_trace_success_log
fc::logger _trx_trace_failure_log
const std::string trx_successful_trace_logger_name("transaction_success_tracing")
const std::string trx_trace_success_logger_name("transaction_trace_success")
const std::string logger_name("producer_plugin")
fc::logger _trx_failed_trace_log
fc::logger _trx_successful_trace_log
const std::string trx_logger_name("transaction")
producer_name(block_signing_key)) FC_REFLECT(producer_set_def
unsigned __int64 uint64_t
static constexpr int medium
static constexpr int high
Immutable except for fc::from_variant.
static void for_each_key(const block_signing_authority &authority, Op &&op)
std::vector< permission_level > accounts
transaction_id_type trx_id
account_query_db::get_accounts_by_authorizers_result results
account_query_db::get_accounts_by_authorizers_params params
void bsf(const Reg ®, const Operand &op)
void bt(const Operand &op, const Reg ®)