25#include <boost/signals2/connection.hpp>
26#include <boost/algorithm/string.hpp>
27#include <boost/lexical_cast.hpp>
28#include <boost/filesystem.hpp>
29#include <boost/filesystem/path.hpp>
43const fc::string deep_mind_logger_name(
"deep-mind");
59 osm <<
"irreversible";
66 const std::vector<std::string>& values,
70 using namespace boost::program_options;
73 validators::check_first_occurrence(v);
77 std::string
const&
s = validators::get_single_string(values);
79 if (
s ==
"speculative" ) {
81 }
else if (
s ==
"head" ) {
83 }
else if (
s ==
"read-only" ) {
85 }
else if (
s ==
"irreversible" ) {
88 throw validation_error(validation_error::invalid_option_value);
103 const std::vector<std::string>& values,
107 using namespace boost::program_options;
110 validators::check_first_occurrence(v);
114 std::string
const&
s = validators::get_single_string(values);
118 }
else if (
s ==
"light" ) {
121 throw validation_error(validation_error::invalid_option_value);
127using namespace sysio;
134using boost::signals2::scoped_connection;
212 std::string wasm_runtime_opt =
"Override default WASM runtime (";
213 std::string wasm_runtime_desc;
215#ifdef SYSIO_SYS_VM_JIT_RUNTIME_ENABLED
216 wasm_runtime_opt +=
" \"sys-vm-jit\"";
217 wasm_runtime_desc +=
"\"sys-vm-jit\" : A WebAssembly runtime that compiles WebAssembly code to native x86 code prior to execution.\n";
221#ifdef SYSIO_SYS_VM_RUNTIME_ENABLED
222 wasm_runtime_opt += delim +
"\"sys-vm\"";
223 wasm_runtime_desc +=
"\"sys-vm\" : A WebAssembly interpreter.\n";
227#ifdef SYSIO_SYS_VM_OC_DEVELOPER
228 wasm_runtime_opt += delim +
"\"sys-vm-oc\"";
229 wasm_runtime_desc +=
"\"sys-vm-oc\" : Unsupported. Instead, use one of the other runtimes along with the option enable-sys-vm-oc.\n";
231 wasm_runtime_opt +=
")\n" + wasm_runtime_desc;
236 (
"blocks-dir", bpo::value<bfs::path>()->default_value(
"blocks"),
237 "the location of the blocks directory (absolute path or relative to application data dir)")
238 (
"protocol-features-dir", bpo::value<bfs::path>()->default_value(
"protocol_features"),
239 "the location of the protocol_features directory (absolute path or relative to application config dir)")
240 (
"checkpoint", bpo::value<vector<string>>()->composing(),
"Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.")
241 (
"wasm-runtime", bpo::value<sysio::chain::wasm_interface::vm_type>()->value_name(
"runtime")->notifier([](
const auto& vm){
242#ifndef SYSIO_SYS_VM_OC_DEVELOPER
244 if(vm == wasm_interface::vm_type::eos_vm_oc) {
245 elog(
"SYS VM OC is a tier-up compiler and works in conjunction with the configured base WASM runtime. Enable SYS VM OC via 'sys-vm-oc-enable' option");
249 })->default_value(sysio::chain::config::default_wasm_runtime, default_wasm_runtime_str), wasm_runtime_opt.c_str()
251 (
"profile-account", boost::program_options::value<
vector<string>>()->composing(),
252 "The name of an account whose code will be profiled")
253 (
"abi-serializer-max-time-ms", bpo::value<uint32_t>()->default_value(config::default_abi_serializer_max_time_us / 1000),
254 "Override default maximum ABI serialization time allowed in ms")
255 (
"chain-state-db-size-mb", bpo::value<uint64_t>()->default_value(config::default_state_size / (1024 * 1024)),
"Maximum size (in MiB) of the chain state database")
256 (
"chain-state-db-guard-size-mb", bpo::value<uint64_t>()->default_value(config::default_state_guard_size / (1024 * 1024)),
"Safely shut down node when free space remaining in the chain state database drops below this size (in MiB).")
257 (
"signature-cpu-billable-pct", bpo::value<uint32_t>()->default_value(config::default_sig_cpu_bill_pct / config::percent_1),
258 "Percentage of actual signature recovery cpu to bill. Whole number percentages, e.g. 50 for 50%")
259 (
"chain-threads", bpo::value<uint16_t>()->default_value(config::default_controller_thread_pool_size),
260 "Number of worker threads in controller thread pool")
261 (
"contracts-console", bpo::bool_switch()->default_value(
false),
262 "print contract's output to console")
263 (
"deep-mind", bpo::bool_switch()->default_value(
false),
264 "print deeper information about chain operations")
265 (
"actor-whitelist", boost::program_options::value<
vector<string>>()->composing()->multitoken(),
266 "Account added to actor whitelist (may specify multiple times)")
267 (
"actor-blacklist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
268 "Account added to actor blacklist (may specify multiple times)")
269 (
"contract-whitelist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
270 "Contract account added to contract whitelist (may specify multiple times)")
271 (
"contract-blacklist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
272 "Contract account added to contract blacklist (may specify multiple times)")
273 (
"action-blacklist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
274 "Action (in the form code::action) added to action blacklist (may specify multiple times)")
275 (
"key-blacklist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
276 "Public key added to blacklist of keys that should not be included in authorities (may specify multiple times)")
277 (
"sender-bypass-whiteblacklist", boost::program_options::value<vector<string>>()->composing()->multitoken(),
278 "Deferred transactions sent by accounts in this list do not have any of the subjective whitelist/blacklist checks applied to them (may specify multiple times)")
280 "Database read mode (\"speculative\", \"head\", \"read-only\", \"irreversible\").\n"
281 "In \"speculative\" mode: database contains state changes by transactions in the blockchain up to the head block as well as some transactions not yet included in the blockchain.\n"
282 "In \"head\" mode: database contains state changes by only transactions in the blockchain up to the head block; transactions received by the node are relayed if valid.\n"
283 "In \"read-only\" mode: (DEPRECATED: see p2p-accept-transactions & api-accept-transactions) database contains state changes by only transactions in the blockchain up to the head block; transactions received via the P2P network are not relayed and transactions cannot be pushed via the chain API.\n"
284 "In \"irreversible\" mode: database contains state changes by only transactions in the blockchain up to the last irreversible block; transactions received via the P2P network are not relayed and transactions cannot be pushed via the chain API.\n"
286 (
"api-accept-transactions", bpo::value<bool>()->default_value(
true),
"Allow API transactions to be evaluated and relayed if valid.")
288 "Chain validation mode (\"full\" or \"light\").\n"
289 "In \"full\" mode all incoming blocks will be fully validated.\n"
290 "In \"light\" mode all incoming blocks headers will be fully validated; transactions in those validated blocks will be trusted \n")
291 (
"disable-ram-billing-notify-checks", bpo::bool_switch()->default_value(
false),
292 "Disable the check which subjectively fails a transaction if a contract bills more RAM to another account within the context of a notification handler (i.e. when the receiver is not the code of the action).")
293#ifdef SYSIO_DEVELOPER
294 (
"disable-all-subjective-mitigations", bpo::bool_switch()->default_value(
false),
295 "Disable all subjective mitigations checks in the entire codebase.")
297 (
"maximum-variable-signature-length", bpo::value<uint32_t>()->default_value(16384u),
298 "Subjectively limit the maximum length of variable components in a variable legnth signature to this size in bytes")
299 (
"trusted-producer", bpo::value<vector<string>>()->composing(),
"Indicate a producer whose blocks headers signed by it will be fully validated, but transactions in those validated blocks will be trusted.")
301 "Database map mode (\"mapped\", \"heap\", or \"locked\").\n"
302 "In \"mapped\" mode database is memory mapped as a file.\n"
304 "In \"heap\" mode database is preloaded in to swappable memory and will use huge pages if available.\n"
305 "In \"locked\" mode database is preloaded, locked in to memory, and will use huge pages if available.\n"
309#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
310 (
"sys-vm-oc-cache-size-mb", bpo::value<uint64_t>()->default_value(
eosvmoc::config().cache_size / (1024u*1024u)),
"Maximum size (in MiB) of the SYS VM OC code cache")
311 (
"sys-vm-oc-compile-threads", bpo::value<uint64_t>()->default_value(1u)->notifier([](
const auto t) {
313 elog(
"sys-vm-oc-compile-threads must be set to a non-zero value");
316 }),
"Number of threads to use for SYS VM OC tier-up")
317 (
"sys-vm-oc-enable", bpo::bool_switch(),
"Enable SYS VM OC tier-up runtime")
319 (
"enable-account-queries", bpo::value<bool>()->default_value(
false),
"enable queries to find accounts by various metadata.")
320 (
"max-nonprivileged-inline-action-size", bpo::value<uint32_t>()->default_value(config::default_max_nonprivileged_inline_action_size),
"maximum allowed size (in bytes) of an inline action for a nonprivileged account")
321 (
"transaction-retry-max-storage-size-gb", bpo::value<uint64_t>(),
322 "Maximum size (in GiB) allowed to be allocated for the Transaction Retry feature. Setting above 0 enables this feature.")
323 (
"transaction-retry-interval-sec", bpo::value<uint32_t>()->default_value(20),
324 "How often, in seconds, to resend an incoming transaction to network if not seen in a block.")
325 (
"transaction-retry-max-expiration-sec", bpo::value<uint32_t>()->default_value(120),
326 "Maximum allowed transaction expiration for retry transactions, will retry transactions up to this value.")
327 (
"transaction-finality-status-max-storage-size-gb", bpo::value<uint64_t>(),
328 "Maximum size (in GiB) allowed to be allocated for the Transaction Finality Status feature. Setting above 0 enables this feature.")
329 (
"transaction-finality-status-success-duration-sec", bpo::value<uint64_t>()->default_value(config::default_max_transaction_finality_status_success_duration_sec),
330 "Duration (in seconds) a successful transaction's Finality Status will remain available from being first identified.")
331 (
"transaction-finality-status-failure-duration-sec", bpo::value<uint64_t>()->default_value(config::default_max_transaction_finality_status_failure_duration_sec),
332 "Duration (in seconds) a failed transaction's Finality Status will remain available from being first identified.");
335 cfg.add_options()(
"block-log-retain-blocks", bpo::value<uint32_t>(),
"if set, periodically prune the block log to store only configured number of most recent blocks");
349 (
"genesis-json", bpo::value<bfs::path>(),
"File to read Genesis State from")
350 (
"genesis-timestamp", bpo::value<string>(),
"override the initial timestamp in the Genesis State file")
351 (
"print-genesis-json", bpo::bool_switch()->default_value(
false),
352 "extract genesis_state from blocks.log as JSON, print to console, and exit")
353 (
"extract-genesis-json", bpo::value<bfs::path>(),
354 "extract genesis_state from blocks.log as JSON, write into specified file, and exit")
355 (
"print-build-info", bpo::bool_switch()->default_value(
false),
356 "print build environment information to console as JSON and exit")
357 (
"extract-build-info", bpo::value<bfs::path>(),
358 "extract build environment information as JSON, write into specified file, and exit")
359 (
"force-all-checks", bpo::bool_switch()->default_value(
false),
360 "do not skip any validation checks while replaying blocks (useful for replaying blocks from untrusted source)")
361 (
"disable-replay-opts", bpo::bool_switch()->default_value(
false),
362 "disable optimizations that specifically target replay")
363 (
"replay-blockchain", bpo::bool_switch()->default_value(
false),
364 "clear chain state database and replay all blocks")
365 (
"hard-replay-blockchain", bpo::bool_switch()->default_value(
false),
366 "clear chain state database, recover as many blocks as possible from the block log, and then replay those blocks")
367 (
"delete-all-blocks", bpo::bool_switch()->default_value(
false),
368 "clear chain state database and block log")
369 (
"truncate-at-block", bpo::value<uint32_t>()->default_value(0),
370 "stop hard replay / block log recovery at this block number (if set to non-zero number)")
371 (
"terminate-at-block", bpo::value<uint32_t>()->default_value(0),
372 "terminate after reaching this block number (if set to a non-zero number)")
373 (
"snapshot", bpo::value<bfs::path>(),
"File to read Snapshot State from")
378#define LOAD_VALUE_SET(options, op_name, container) \
379if( options.count(op_name) ) { \
380 const std::vector<std::string>& ops = options[op_name].as<std::vector<std::string>>(); \
381 for( const auto& v : ops ) { \
382 container.emplace( sysio::chain::name( v ) ); \
388 if( strcasecmp (tstr.c_str(),
"now") == 0 ) {
395 auto diff_us = epoch_us % config::block_interval_us;
397 auto delay_us = (config::block_interval_us - diff_us);
399 dlog(
"pausing ${us} microseconds to the next interval",(
"us",delay_us));
402 ilog(
"Adjusting genesis timestamp to ${timestamp}", (
"timestamp", genesis_timestamp) );
403 return genesis_timestamp;
407 using boost::filesystem::directory_iterator;
429 wlog(
"problem encountered while reading '${path}':\n${details}",
432 dlog(
"unknown problem encountered while reading '${path}'",
433 (
"path",
p.generic_string()) );
439 using boost::filesystem::directory_iterator;
443 bool directory_exists =
true;
447 "Path to protocol-features is not a directory: ${path}",
448 (
"path",
p.generic_string())
451 if( populate_missing_builtins )
452 bfs::create_directories(
p );
454 directory_exists =
false;
458 if(
f.subjective_restrictions.enabled ) {
459 if(
f.subjective_restrictions.preactivation_required ) {
460 if(
f.subjective_restrictions.earliest_allowed_activation_time ==
time_point{} ) {
461 ilog(
"Support for builtin protocol feature '${codename}' (with digest of '${digest}') is enabled with preactivation required",
463 (
"digest", feature_digest)
466 ilog(
"Support for builtin protocol feature '${codename}' (with digest of '${digest}') is enabled with preactivation required and with an earliest allowed activation time of ${earliest_time}",
468 (
"digest", feature_digest)
469 (
"earliest_time",
f.subjective_restrictions.earliest_allowed_activation_time)
473 if(
f.subjective_restrictions.earliest_allowed_activation_time ==
time_point{} ) {
474 ilog(
"Support for builtin protocol feature '${codename}' (with digest of '${digest}') is enabled without activation restrictions",
476 (
"digest", feature_digest)
479 ilog(
"Support for builtin protocol feature '${codename}' (with digest of '${digest}') is enabled without preactivation required but with an earliest allowed activation time of ${earliest_time}",
481 (
"digest", feature_digest)
482 (
"earliest_time",
f.subjective_restrictions.earliest_allowed_activation_time)
487 ilog(
"Recognized builtin protocol feature '${codename}' (with digest of '${digest}') but support for it is not enabled",
489 (
"digest", feature_digest)
494 map<builtin_protocol_feature_t, fc::path> found_builtin_protocol_features;
495 map<digest_type, std::pair<builtin_protocol_feature, bool> > builtin_protocol_features_to_add;
497 map< builtin_protocol_feature_t, std::optional<digest_type> > visited_builtins;
500 if( directory_exists ) {
502 auto file_path = itr->path();
503 if( !
fc::is_regular_file( file_path ) || file_path.extension().generic_string().compare(
".json" ) != 0 )
510 auto res = found_builtin_protocol_features.emplace(
f->get_codename(), file_path );
513 "Builtin protocol feature '${codename}' was already included from a previous_file",
515 (
"current_file", file_path.generic_string())
516 (
"previous_file", res.first->second.generic_string())
519 const auto feature_digest =
f->digest();
521 builtin_protocol_features_to_add.emplace( std::piecewise_construct,
522 std::forward_as_tuple( feature_digest ),
523 std::forward_as_tuple( *
f,
false ) );
528 using itr_type = map<digest_type, std::pair<builtin_protocol_feature, bool>>::iterator;
529 std::function<void(
const itr_type&)> add_protocol_feature =
530 [&pfs, &builtin_protocol_features_to_add, &visited_builtins, &log_recognized_protocol_feature, &add_protocol_feature](
const itr_type& itr ) ->
void {
531 if( itr->second.second ) {
534 itr->second.second =
true;
535 visited_builtins.emplace( itr->second.first.get_codename(), itr->first );
538 for(
const auto&
d : itr->second.first.dependencies ) {
539 auto itr2 = builtin_protocol_features_to_add.find(
d );
540 if( itr2 != builtin_protocol_features_to_add.end() ) {
541 add_protocol_feature( itr2 );
547 log_recognized_protocol_feature( itr->second.first, itr->first );
550 for(
auto itr = builtin_protocol_features_to_add.begin(); itr != builtin_protocol_features_to_add.end(); ++itr ) {
551 add_protocol_feature( itr );
555 string filename(
"BUILTIN-" );
559 auto file_path =
p / filename;
562 "Could not save builtin protocol feature with codename '${codename}' because a file at the following path already exists: ${path}",
564 (
"path", file_path.generic_string())
568 ilog(
"Saved default specification for builtin protocol feature '${codename}' (with digest of '${digest}') to: ${path}",
570 (
"digest", feature_digest)
571 (
"path", file_path.generic_string())
574 elog(
"Error occurred while writing default specification for builtin protocol feature '${codename}' (with digest of '${digest}') to: ${path}",
576 (
"digest", feature_digest)
577 (
"path", file_path.generic_string())
583 [&pfs, &visited_builtins, &output_protocol_feature, &log_recognized_protocol_feature, &add_missing_builtins, populate_missing_builtins]
585 auto res = visited_builtins.emplace( codename, std::optional<digest_type>() );
587 SYS_ASSERT( res.first->second, protocol_feature_exception,
588 "invariant failure: cycle found in builtin protocol feature dependencies"
590 return *res.first->second;
595 return add_missing_builtins(
d );
598 if( !populate_missing_builtins )
599 f.subjective_restrictions.enabled =
false;
604 log_recognized_protocol_feature(
f, pf.feature_digest );
606 if( populate_missing_builtins )
607 output_protocol_feature(
f, pf.feature_digest );
609 return pf.feature_digest;
613 auto itr = found_builtin_protocol_features.find(
p.first );
614 if( itr != found_builtin_protocol_features.end() )
continue;
616 add_missing_builtins(
p.first );
626 bfs::path old_fork_db = my->
chain_config->state_dir / config::forkdb_filename;
627 bfs::path new_fork_db = my->
blocks_dir / config::reversible_blocks_dir_name / config::forkdb_filename;
628 if( bfs::exists( old_fork_db ) && bfs::is_regular_file( old_fork_db ) ) {
629 bool copy_file =
false;
630 if( bfs::exists( new_fork_db ) && bfs::is_regular_file( new_fork_db ) ) {
631 if( bfs::last_write_time( old_fork_db ) > bfs::last_write_time( new_fork_db ) ) {
636 bfs::create_directories( my->
blocks_dir / config::reversible_blocks_dir_name );
649 ilog(
"Hard replay requested: deleting state database" );
655 ilog(
"initializing chain plugin");
660 }
catch (
const std::exception& ) {
661 elog(
"SYSIO_ROOT_KEY ('${root_key}') is invalid. Recompile with a valid public key.",
668 if( options.at(
"print-build-info" ).as<
bool>() || options.count(
"extract-build-info") ) {
669 if( options.at(
"print-build-info" ).as<
bool>() ) {
672 if( options.count(
"extract-build-info") ) {
673 auto p = options.at(
"extract-build-info" ).as<bfs::path>();
675 if(
p.is_relative()) {
676 p = bfs::current_path() /
p;
680 "Error occurred while writing build info JSON to '${path}'",
681 (
"path",
p.generic_string())
684 ilog(
"Saved build info JSON to '${path}'", (
"path",
p.generic_string()) );
687 SYS_THROW( node_management_success,
"reported build environment information" );
698 if( options.count(
"action-blacklist" )) {
699 const std::vector<std::string>& acts = options[
"action-blacklist"].as<std::vector<std::string>>();
701 for(
const auto&
a : acts ) {
702 auto pos =
a.find(
"::" );
703 SYS_ASSERT( pos != std::string::npos, plugin_config_exception,
"Invalid entry in action-blacklist: '${a}'", (
"a",
a));
706 list.emplace( code, act );
710 if( options.count(
"key-blacklist" )) {
711 const std::vector<std::string>& keys = options[
"key-blacklist"].as<std::vector<std::string>>();
713 for(
const auto& key_str : keys ) {
714 list.emplace( key_str );
718 if( options.count(
"blocks-dir" )) {
719 auto bld = options.at(
"blocks-dir" ).as<bfs::path>();
720 if( bld.is_relative())
729 auto pfd = options.at(
"protocol-features-dir" ).as<bfs::path>();
730 if( pfd.is_relative())
733 protocol_features_dir = pfd;
738 if( options.count(
"checkpoint") ) {
741 for(
const auto& cp : cps ) {
746 plugin_config_exception,
747 "redefining existing checkpoint at block number ${num}: original: ${orig} new: ${new}",
748 (
"num", item.first)(
"orig", itr->second)(
"new", item.second)
756 if( options.count(
"wasm-runtime" ))
761 if(options.count(
"abi-serializer-max-time-ms"))
768 if (
auto resmon_plugin =
app().find_plugin<resource_monitor_plugin>()) {
769 resmon_plugin->monitor_directory(my->
chain_config->blocks_dir);
770 resmon_plugin->monitor_directory(my->
chain_config->state_dir);
773 if( options.count(
"chain-state-db-size-mb" ))
774 my->
chain_config->state_size = options.at(
"chain-state-db-size-mb" ).as<
uint64_t>() * 1024 * 1024;
776 if( options.count(
"chain-state-db-guard-size-mb" ))
777 my->
chain_config->state_guard_size = options.at(
"chain-state-db-guard-size-mb" ).as<
uint64_t>() * 1024 * 1024;
779 if( options.count(
"max-nonprivileged-inline-action-size" ))
780 my->
chain_config->max_nonprivileged_inline_action_size = options.at(
"max-nonprivileged-inline-action-size" ).as<
uint32_t>();
782 if( options.count(
"transaction-finality-status-max-storage-size-gb" )) {
783 const uint64_t max_storage_size = options.at(
"transaction-finality-status-max-storage-size-gb" ).as<
uint64_t>() * 1024 * 1024 * 1024;
784 if (max_storage_size > 0) {
792 if( options.count(
"chain-threads" )) {
795 "chain-threads ${num} must be greater than 0", (
"num", my->
chain_config->thread_pool_size) );
800 "signature-cpu-billable-pct must be 0 - 100, ${pct}", (
"pct", my->
chain_config->sig_cpu_bill_pct) );
801 my->
chain_config->sig_cpu_bill_pct *= config::percent_1;
806 my->
chain_config->force_all_checks = options.at(
"force-all-checks" ).as<
bool>();
807 my->
chain_config->disable_replay_opts = options.at(
"disable-replay-opts" ).as<
bool>();
808 my->
chain_config->contracts_console = options.at(
"contracts-console" ).as<
bool>();
809 my->
chain_config->allow_ram_billing_in_notify = options.at(
"disable-ram-billing-notify-checks" ).as<
bool>();
811#ifdef SYSIO_DEVELOPER
812 my->
chain_config->disable_all_subjective_mitigations = options.at(
"disable-all-subjective-mitigations" ).as<
bool>();
815 my->
chain_config->maximum_variable_signature_length = options.at(
"maximum-variable-signature-length" ).as<
uint32_t>();
817 if( options.count(
"terminate-at-block" ))
820 if( options.count(
"extract-genesis-json" ) || options.at(
"print-genesis-json" ).as<
bool>()) {
821 std::optional<genesis_state> gs;
826 plugin_config_exception,
827 "Block log at '${path}' does not contain a genesis state, it only has the chain-id.",
828 (
"path", (my->
blocks_dir /
"blocks.log").generic_string())
831 wlog(
"No blocks.log found at '${p}'. Using default genesis state.",
832 (
"p", (my->
blocks_dir /
"blocks.log").generic_string()));
836 if( options.at(
"print-genesis-json" ).as<
bool>()) {
840 if( options.count(
"extract-genesis-json" )) {
841 auto p = options.at(
"extract-genesis-json" ).as<bfs::path>();
843 if(
p.is_relative()) {
844 p = bfs::current_path() /
p;
849 "Error occurred while writing genesis JSON to '${path}'",
850 (
"path",
p.generic_string())
853 ilog(
"Saved genesis JSON to '${path}'", (
"path",
p.generic_string()) );
856 SYS_THROW( extract_genesis_state_exception,
"extracted genesis state from blocks.log" );
860 upgrade_from_reversible_to_fork_db( my.get() );
862 if(options.count(
"block-log-retain-blocks" )) {
864 my->
chain_config->prune_config->prune_blocks = options.at(
"block-log-retain-blocks" ).as<
uint32_t>();
865 SYS_ASSERT(my->
chain_config->prune_config->prune_blocks, plugin_config_exception,
"block-log-retain-blocks cannot be 0");
868 if( options.at(
"delete-all-blocks" ).as<
bool>()) {
869 ilog(
"Deleting state database and blocks" );
870 if( options.at(
"truncate-at-block" ).as<
uint32_t>() > 0 )
871 wlog(
"The --truncate-at-block option does not make sense when deleting all blocks." );
874 }
else if( options.at(
"hard-replay-blockchain" ).as<
bool>()) {
876 }
else if( options.at(
"replay-blockchain" ).as<
bool>()) {
877 ilog(
"Replay requested: deleting state database" );
878 if( options.at(
"truncate-at-block" ).as<
uint32_t>() > 0 )
879 wlog(
"The --truncate-at-block option does not work for a regular replay of the blockchain." );
881 }
else if( options.at(
"truncate-at-block" ).as<
uint32_t>() > 0 ) {
882 wlog(
"The --truncate-at-block option can only be used with --hard-replay-blockchain." );
885 std::optional<chain_id_type> chain_id;
886 if (options.count(
"snapshot" )) {
887 my->
snapshot_path = options.at(
"snapshot" ).as<bfs::path>();
889 "Cannot load snapshot, ${name} does not exist", (
"name", my->
snapshot_path->generic_string()) );
893 auto infile = std::ifstream(my->
snapshot_path->generic_string(), (std::ios::in | std::ios::binary));
899 SYS_ASSERT( options.count(
"genesis-timestamp" ) == 0,
900 plugin_config_exception,
901 "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information");
902 SYS_ASSERT( options.count(
"genesis-json" ) == 0,
903 plugin_config_exception,
904 "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information");
906 auto shared_mem_path = my->
chain_config->state_dir /
"shared_memory.bin";
908 plugin_config_exception,
909 "Snapshot can only be used to initialize an empty database." );
913 if( block_log_genesis ) {
914 const auto& block_log_chain_id = block_log_genesis->compute_chain_id();
916 plugin_config_exception,
917 "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID from the genesis state in the block log (${block_log_chain_id})",
918 (
"snapshot_chain_id", *chain_id)
919 (
"block_log_chain_id", block_log_chain_id)
924 plugin_config_exception,
925 "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID (${block_log_chain_id}) in the block log",
926 (
"snapshot_chain_id", *chain_id)
927 (
"block_log_chain_id", block_log_chain_id)
936 std::optional<genesis_state> block_log_genesis;
937 std::optional<chain_id_type> block_log_chain_id;
941 if( block_log_genesis ) {
942 block_log_chain_id = block_log_genesis->compute_chain_id();
948 SYS_ASSERT( *block_log_chain_id == *chain_id, block_log_exception,
949 "Chain ID in blocks.log (${block_log_chain_id}) does not match the existing "
950 " chain ID in state (${state_chain_id}).",
951 (
"block_log_chain_id", *block_log_chain_id)
952 (
"state_chain_id", *chain_id)
954 }
else if( block_log_genesis ) {
955 ilog(
"Starting fresh blockchain state using genesis state extracted from blocks.log." );
956 my->
genesis = block_log_genesis;
962 if( options.count(
"genesis-json" ) ) {
963 bfs::path genesis_file = options.at(
"genesis-json" ).as<bfs::path>();
964 if( genesis_file.is_relative()) {
965 genesis_file = bfs::current_path() / genesis_file;
969 plugin_config_exception,
970 "Specified genesis file '${genesis}' does not exist.",
971 (
"genesis", genesis_file.generic_string()));
975 if( options.count(
"genesis-timestamp" ) ) {
978 ilog(
"Using genesis state provided in '${genesis}' but with adjusted genesis timestamp",
979 (
"genesis", genesis_file.generic_string()) );
981 ilog(
"Using genesis state provided in '${genesis}'", (
"genesis", genesis_file.generic_string()));
984 if( block_log_genesis ) {
985 SYS_ASSERT( *block_log_genesis == provided_genesis, plugin_config_exception,
986 "Genesis state, provided via command line arguments, does not match the existing genesis state"
987 " in blocks.log. It is not necessary to provide genesis state arguments when a full blocks.log "
988 "file already exists."
991 const auto& provided_genesis_chain_id = provided_genesis.
compute_chain_id();
993 SYS_ASSERT( provided_genesis_chain_id == *chain_id, plugin_config_exception,
994 "Genesis state, provided via command line arguments, has a chain ID (${provided_genesis_chain_id}) "
995 "that does not match the existing chain ID in the database state (${state_chain_id}). "
996 "It is not necessary to provide genesis state arguments when an initialized database state already exists.",
997 (
"provided_genesis_chain_id", provided_genesis_chain_id)
998 (
"state_chain_id", *chain_id)
1001 if( block_log_chain_id ) {
1002 SYS_ASSERT( provided_genesis_chain_id == *block_log_chain_id, plugin_config_exception,
1003 "Genesis state, provided via command line arguments, has a chain ID (${provided_genesis_chain_id}) "
1004 "that does not match the existing chain ID in blocks.log (${block_log_chain_id}).",
1005 (
"provided_genesis_chain_id", provided_genesis_chain_id)
1006 (
"block_log_chain_id", *block_log_chain_id)
1010 chain_id = provided_genesis_chain_id;
1012 ilog(
"Starting fresh blockchain state using provided genesis state." );
1013 my->
genesis = std::move(provided_genesis);
1017 SYS_ASSERT( options.count(
"genesis-timestamp" ) == 0,
1018 plugin_config_exception,
1019 "--genesis-timestamp is only valid if also passed in with --genesis-json");
1025 chain_id = my->
genesis->compute_chain_id();
1029 SYS_ASSERT( !block_log_chain_id, plugin_config_exception,
1030 "Genesis state is necessary to initialize fresh blockchain state but genesis state could not be "
1031 "found in the blocks log. Please either load from snapshot or find a blocks log that starts "
1035 ilog(
"Starting fresh blockchain state using default genesis state." );
1037 chain_id = my->
genesis->compute_chain_id();
1042 if ( options.count(
"read-mode") ) {
1047 if( my->
chain_config->read_mode == db_read_mode::IRREVERSIBLE || my->
chain_config->read_mode == db_read_mode::READ_ONLY ) {
1048 if( my->
chain_config->read_mode == db_read_mode::READ_ONLY ) {
1049 wlog(
"read-mode = read-only is deprecated use p2p-accept-transactions = false, api-accept-transactions = false instead." );
1053 std::stringstream ss; ss << my->
chain_config->read_mode;
1054 wlog(
"api-accept-transactions set to false due to read-mode: ${m}", (
"m", ss.str()) );
1061 if ( options.count(
"validation-mode") ) {
1067#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
1068 if( options.count(
"sys-vm-oc-cache-size-mb") )
1069 my->
chain_config->eosvmoc_config.cache_size = options.at(
"sys-vm-oc-cache-size-mb" ).as<
uint64_t>() * 1024u * 1024u;
1070 if( options.count(
"sys-vm-oc-compile-threads") )
1071 my->
chain_config->eosvmoc_config.threads = options.at(
"sys-vm-oc-compile-threads").as<
uint64_t>();
1072 if( options[
"sys-vm-oc-enable"].as<bool>() )
1080 if( options.count(
"transaction-retry-max-storage-size-gb" )) {
1081 SYS_ASSERT( !options.count(
"producer-name"), plugin_config_exception,
1082 "Transaction retry not allowed on producer nodes." );
1083 const uint64_t max_storage_size = options.at(
"transaction-retry-max-storage-size-gb" ).as<
uint64_t>() * 1024 * 1024 * 1024;
1084 if( max_storage_size > 0 ) {
1085 const uint32_t p2p_dedup_time_s = options.at(
"p2p-dedup-cache-expire-time-sec" ).as<
uint32_t>();
1086 const uint32_t trx_retry_interval = options.at(
"transaction-retry-interval-sec" ).as<
uint32_t>();
1087 const uint32_t trx_retry_max_expire = options.at(
"transaction-retry-max-expiration-sec" ).as<
uint32_t>();
1088 SYS_ASSERT( trx_retry_interval >= 2 * p2p_dedup_time_s, plugin_config_exception,
1089 "transaction-retry-interval-sec ${ri} must be greater than 2 times p2p-dedup-cache-expire-time-sec ${dd}",
1090 (
"ri", trx_retry_interval)(
"dd", p2p_dedup_time_s) );
1091 SYS_ASSERT( trx_retry_max_expire > trx_retry_interval, plugin_config_exception,
1092 "transaction-retry-max-expiration-sec ${m} should be configured larger than transaction-retry-interval-sec ${i}",
1093 (
"m", trx_retry_max_expire)(
"i", trx_retry_interval) );
1101 if ( options.at(
"deep-mind" ).as<
bool>() ) {
1124 setbuf(stdout, NULL);
1127 SYS_ASSERT( options.at(
"api-accept-transactions").as<
bool>() ==
false, plugin_config_exception,
1128 "api-accept-transactions must be set to false in order to enable deep-mind logging.");
1130 SYS_ASSERT( options.at(
"p2p-accept-transactions").as<
bool>() ==
false, plugin_config_exception,
1131 "p2p-accept-transactions must be set to false in order to enable deep-mind logging.");
1139 return my->
chain->fetch_block_by_number( block_num );
1144 return my->
chain->fetch_block_by_id(
id );
1148 return my->
chain->head_block_id();
1153 return my->
chain->last_irreversible_block_num();
1160 auto id = blk->calculate_id();
1161 SYS_ASSERT( itr->second ==
id, checkpoint_exception,
1162 "Checkpoint does not match for block number ${num}: expected: ${expected} actual: ${actual}",
1163 (
"num", blk->block_num())(
"expected", itr->second)(
"actual",
id)
1209 [
this]( std::tuple<const transaction_trace_ptr&, const packed_transaction_ptr&> t ) {
1215 my->
_trx_retry_db->on_applied_transaction(std::get<0>(t), std::get<1>(t));
1236 my->
chain->add_indices();
1246 "read-mode = irreversible. transactions should not be enabled by enable_accept_transactions" );
1254 auto infile = std::ifstream(my->
snapshot_path->generic_string(), (std::ios::in | std::ios::binary));
1255 auto reader = std::make_shared<istream_snapshot_reader>(infile);
1263 }
catch (
const database_guard_exception& e) {
1264 log_guard_exception(e);
1271 ilog(
"starting chain in read/write mode");
1275 ilog(
"Blockchain started; head block is #${num}, genesis timestamp is ${ts}",
1276 (
"num", my->
chain->head_block_num())(
"ts", (std::string)my->
genesis->initial_timestamp));
1279 ilog(
"Blockchain started; head block is #${num}", (
"num", my->
chain->head_block_num()));
1303 if(
app().is_quiting())
1304 my->
chain->get_wasm_interface().indicate_shutting_down();
1314, trx_retry(trx_retry)
1316, api_accept_transactions(api_accept_transactions)
1321 SYS_ASSERT( api_accept_transactions, missing_chain_api_plugin_exception,
1322 "Not allowed, node has api-accept-transactions = false" );
1346 return my->
chain->get_chain_id();
1367 if (e.code() == chain::database_guard_exception::code_value) {
1368 elog(
"Database has reached an unsafe level of usage, shutting down to avoid corrupting the database. "
1369 "Please increase the value set for \"chain-state-db-size-mb\" and restart the process!");
1372 dlog(
"Details: ${details}", (
"details", e.to_detail_string()));
1376 log_guard_exception(e);
1378 elog(
"database chain::guard_exception, quitting...");
1384 elog(
"database memory exhausted: increase chain-state-db-size-mb");
1390 elog(
"std::bad_alloc - memory exhausted");
1403namespace chain_apis {
1405const string read_only::KEYi64 =
"i64";
1408std::string
itoh(I n,
size_t hlen =
sizeof(I)<<1) {
1409 static const char* digits =
"0123456789abcdef";
1410 std::string
r(hlen,
'0');
1411 for(
size_t i = 0,
j = (hlen - 1) * 4 ; i < hlen; ++i,
j -= 4)
1412 r[i] = digits[(n>>
j) & 0x0f];
1417 const auto& rm = db.get_resource_limits_manager();
1422 db.head_block_num(),
1423 db.last_irreversible_block_num(),
1424 db.last_irreversible_block_id(),
1426 db.head_block_time(),
1427 db.head_block_producer(),
1428 rm.get_virtual_block_cpu_limit(),
1429 rm.get_virtual_block_net_limit(),
1430 rm.get_block_cpu_limit(),
1431 rm.get_block_net_limit(),
1435 db.fork_db_pending_head_block_num(),
1436 db.fork_db_pending_head_block_id(),
1438 rm.get_total_cpu_weight(),
1439 rm.get_total_net_weight(),
1440 db.earliest_available_block_num(),
1441 db.last_irreversible_block_time()
1446 SYS_ASSERT(trx_finality_status_proc, unsupported_feature,
"Transaction Status Interface not enabled. To enable, configure nodeop with '--transaction-finality-status-max-storage-size-gb <size>'.");
1450 const auto trx_st = trx_finality_status_proc->get_trx_state(param.
id);
1455 trx_st ? trx_st->status :
"UNKNOWN",
1456 trx_block_valid ? std::optional<uint32_t>(chain::block_header::num_from_id(trx_st->block_id)) : std::optional<uint32_t>{},
1457 trx_block_valid ? std::optional<chain::block_id_type>(trx_st->block_id) : std::optional<chain::block_id_type>{},
1458 trx_block_valid ? std::optional<fc::time_point>(trx_st->block_timestamp) : std::optional<fc::time_point>{},
1459 trx_st ? std::optional<fc::time_point_sec>(trx_st->expiration) : std::optional<fc::time_point_sec>{},
1460 chain::block_header::num_from_id(ch_state.
head_id),
1463 chain::block_header::num_from_id(ch_state.
irr_id),
1474 const auto& pfm = db.get_protocol_feature_manager();
1476 uint32_t lower_bound_value = std::numeric_limits<uint32_t>::lowest();
1477 uint32_t upper_bound_value = std::numeric_limits<uint32_t>::max();
1479 if(
params.lower_bound ) {
1480 lower_bound_value = *
params.lower_bound;
1483 if(
params.upper_bound ) {
1484 upper_bound_value = *
params.upper_bound;
1487 if( upper_bound_value < lower_bound_value )
1490 auto walk_range = [&](
auto itr,
auto end_itr,
auto&& convert_iterator ) {
1492 mvo(
"activation_ordinal", 0 );
1493 mvo(
"activation_block_num", 0 );
1495 auto& activation_ordinal_value = mvo[
"activation_ordinal"];
1496 auto& activation_block_num_value = mvo[
"activation_block_num"];
1500 for(
unsigned int count = 0;
1501 cur_time <= end_time &&
count <
params.limit && itr != end_itr;
1504 const auto& conv_itr = convert_iterator( itr );
1505 activation_ordinal_value = conv_itr.activation_ordinal();
1506 activation_block_num_value = conv_itr.activation_block_num();
1508 result.activated_protocol_features.emplace_back( conv_itr->to_variant(
false, &mvo ) );
1511 if( itr != end_itr ) {
1512 result.more = convert_iterator( itr ).activation_ordinal() ;
1516 auto get_next_if_not_end = [&pfm](
auto&& itr ) {
1517 if( itr == pfm.cend() )
return itr;
1523 auto lower = (
params.search_by_block_num ? pfm.lower_bound( lower_bound_value )
1524 : pfm.at_activation_ordinal( lower_bound_value ) );
1526 auto upper = (
params.search_by_block_num ? pfm.upper_bound( upper_bound_value )
1527 : get_next_if_not_end( pfm.at_activation_ordinal( upper_bound_value ) ) );
1530 walk_range( std::make_reverse_iterator(upper), std::make_reverse_iterator(lower),
1531 [](
auto&& ritr ) {
return --(ritr.base()); } );
1533 walk_range( lower, upper, [](
auto&& itr ) {
return itr; } );
1540 using boost::algorithm::starts_with;
1542 const uint64_t table =
p.table.to_uint64_t();
1543 uint64_t index = table & 0xFFFFFFFFFFFFFFF0ULL;
1544 SYS_ASSERT( index == table, chain::contract_table_query_exception,
"Unsupported table name: ${n}", (
"n",
p.table) );
1548 if (
p.index_position.empty() ||
p.index_position ==
"first" ||
p.index_position ==
"primary" ||
p.index_position ==
"one") {
1550 }
else if (
starts_with(
p.index_position,
"sec") ||
p.index_position ==
"two") {
1551 }
else if (
starts_with(
p.index_position ,
"ter") || starts_with(
p.index_position,
"th")) {
1571 SYS_ASSERT(
false, chain::contract_table_query_exception,
"Invalid index_position: ${p}", (
"p",
p.index_position));
1580 index |= (pos & 0x000000000000000FULL);
1588 return boost::lexical_cast<uint64_t>(str.c_str(), str.size());
1592 auto trimmed_str = str;
1593 boost::trim(trimmed_str);
1594 name s(trimmed_str);
1595 return s.to_uint64_t();
1598 if (str.find(
',') != string::npos) {
1601 return symb.value();
1606 return ( sysio::chain::string_to_symbol( 0, str.c_str() ) >> 8 );
1609 "uint64_t, valid name, or valid symbol (with or without the precision)",
1610 (
"desc", desc)(
"str", str));
1619 }
FC_RETHROW_EXCEPTIONS(warn,
"Could not convert ${desc} string '${str}' to key type.", (
"desc", desc)(
"str",str) )
1621 SYS_ASSERT( !std::isnan(val), chain::contract_table_query_exception,
1622 "Converted ${desc} string '${str}' to NaN which is not a permitted value for the key type", (
"desc", desc)(
"str",str) );
1627template<
typename Type>
1637 if (
key_type == chain_apis::sha256 || (
key_type == chain_apis::i256 && encode_type == chain_apis::hex)) {
1639 fc::sha256 val(
reinterpret_cast<char *
>(byte_array.data()), byte_array.size());
1640 return std::string(val);
1641 }
else if (
key_type == chain_apis::i256) {
1643 fc::sha256 val(
reinterpret_cast<char *
>(byte_array.data()), byte_array.size());
1644 return std::string(
"0x") + std::string(val);
1645 }
else if (
key_type == chain_apis::ripemd160) {
1648 memcpy(val.
_hash, byte_array.data(), byte_array.size() );
1649 return std::string(val);
1665 const auto &
d = db.
db();
1667 SYS_ASSERT(code_accnt !=
nullptr, chain::account_query_exception,
"Fail to retrieve account for ${account}", (
"account", account) );
1669 abi_serializer::to_abi(code_accnt->abi, abi);
1674 for(
const auto& t : abi.tables ) {
1676 return t.index_type;
1679 SYS_ASSERT(
false, chain::contract_table_query_exception,
"Table ${table} is not specified in the ABI", (
"table",
table_name) );
1684 bool primary =
false;
1685 auto table_with_index = get_table_index_name(
p, primary );
1687 SYS_ASSERT(
p.table == table_with_index, chain::contract_table_query_exception,
"Invalid table name ${t}", (
"t",
p.table ));
1689 if( table_type == KEYi64 ||
p.key_type ==
"i64" ||
p.key_type ==
"name" ) {
1690 return get_table_rows_ex<key_value_index>(
p,abi);
1692 SYS_ASSERT(
false, chain::contract_table_query_exception,
"Invalid table type ${type}", (
"type",table_type)(
"abi",abi));
1694 SYS_ASSERT( !
p.key_type.empty(), chain::contract_table_query_exception,
"key type required for non-primary index" );
1696 if (
p.key_type == chain_apis::i64 ||
p.key_type ==
"name") {
1697 return get_table_rows_by_seckey<index64_index, uint64_t>(
p, abi, [](
uint64_t v)->
uint64_t {
1701 else if (
p.key_type == chain_apis::i128) {
1702 return get_table_rows_by_seckey<index128_index, uint128_t>(
p, abi, [](
uint128_t v)->
uint128_t {
1706 else if (
p.key_type == chain_apis::i256) {
1707 if (
p.encode_type == chain_apis::hex) {
1709 return get_table_rows_by_seckey<conv::index_type, conv::input_type>(
p, abi, conv::function());
1712 return get_table_rows_by_seckey<conv::index_type, conv::input_type>(
p, abi, conv::function());
1714 else if (
p.key_type == chain_apis::float64) {
1715 return get_table_rows_by_seckey<index_double_index, double>(
p, abi, [](
double v)->
float64_t {
1721 else if (
p.key_type == chain_apis::float128) {
1722 if (
p.encode_type == chain_apis::hex) {
1723 return get_table_rows_by_seckey<index_long_double_index, uint128_t>(
p, abi, [](
uint128_t v)->
float128_t{
1729 return get_table_rows_by_seckey<index_long_double_index, double>(
p, abi, [](
double v)->
float128_t{
1737 else if (
p.key_type == chain_apis::sha256) {
1739 return get_table_rows_by_seckey<conv::index_type, conv::input_type>(
p, abi, conv::function());
1741 else if(
p.key_type == chain_apis::ripemd160) {
1743 return get_table_rows_by_seckey<conv::index_type, conv::input_type>(
p, abi, conv::function());
1745 SYS_ASSERT(
false, chain::contract_table_query_exception,
"Unsupported secondary index type: ${t}", (
"t",
p.key_type));
1751 const auto&
d = db.db();
1754 auto lower_bound_lookup_tuple = std::make_tuple(
p.code,
name(std::numeric_limits<uint64_t>::lowest()),
p.table );
1755 auto upper_bound_lookup_tuple = std::make_tuple(
p.code,
name(std::numeric_limits<uint64_t>::max()),
1756 (
p.table.empty() ?
name(std::numeric_limits<uint64_t>::max()) :
p.table) );
1758 if(
p.lower_bound.
size() ) {
1759 uint64_t scope = convert_to_type<uint64_t>(
p.lower_bound,
"lower_bound scope");
1760 std::get<1>(lower_bound_lookup_tuple) =
name(scope);
1763 if(
p.upper_bound.
size() ) {
1764 uint64_t scope = convert_to_type<uint64_t>(
p.upper_bound,
"upper_bound scope");
1765 std::get<1>(upper_bound_lookup_tuple) =
name(scope);
1768 if( upper_bound_lookup_tuple < lower_bound_lookup_tuple )
1771 auto walk_table_range = [&](
auto itr,
auto end_itr ) {
1775 if(
p.table && itr->table !=
p.table )
continue;
1777 result.rows.push_back( {itr->code, itr->scope, itr->table, itr->payer, itr->count} );
1781 if( itr != end_itr ) {
1782 result.more = itr->scope.to_string();
1786 auto lower = idx.lower_bound( lower_bound_lookup_tuple );
1787 auto upper = idx.upper_bound( upper_bound_lookup_tuple );
1788 if(
p.reverse && *
p.reverse ) {
1789 walk_table_range( boost::make_reverse_iterator(upper), boost::make_reverse_iterator(lower) );
1791 walk_table_range( lower, upper );
1803 walk_key_value_table(
p.code,
p.account,
"accounts"_n, [&](
const key_value_object& obj){
1804 SYS_ASSERT( obj.value.size() >= sizeof(asset), chain::asset_type_exception,
"Invalid data on table");
1807 fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
1808 fc::raw::unpack(ds, cursor);
1810 SYS_ASSERT( cursor.get_symbol().valid(), chain::asset_type_exception,
"Invalid asset");
1812 if( !p.symbol || boost::iequals(cursor.symbol_name(), *p.symbol) ) {
1813 results.emplace_back(cursor);
1817 return !(
p.symbol && boost::iequals(cursor.symbol_name(), *
p.symbol));
1829 uint64_t scope = ( sysio::chain::string_to_symbol( 0, boost::algorithm::to_upper_copy(
p.symbol).c_str() ) >> 8 );
1841 results[result.supply.symbol_name()] = result;
1850 SYS_ASSERT(table_type ==
read_only::KEYi64, chain::contract_table_query_exception,
"Invalid table type ${type} for table global", (
"type",table_type));
1852 const auto*
const table_id = db.
find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple(config::system_account_name, config::system_account_name,
"global"_n));
1856 const auto it = kv_index.find(boost::make_tuple(
table_id->id,
"global"_n.to_uint64_t()));
1857 SYS_ASSERT(it != kv_index.end(), chain::contract_table_query_exception,
"Missing row in table global");
1868 SYS_ASSERT(table_type == KEYi64, chain::contract_table_query_exception,
"Invalid table type ${type} for table producers", (
"type",table_type));
1870 const auto&
d = db.db();
1871 const auto lower =
name{
p.lower_bound};
1873 static const uint8_t secondary_index_num = 0;
1875 boost::make_tuple(config::system_account_name, config::system_account_name,
"producers"_n));
1877 boost::make_tuple(config::system_account_name, config::system_account_name,
name(
"producers"_n.to_uint64_t() | secondary_index_num)));
1878 SYS_ASSERT(
table_id && secondary_table_id, chain::contract_table_query_exception,
"Missing producers table");
1882 const auto& secondary_index_by_primary =
secondary_index.get<by_primary>();
1890 if(lower.to_uint64_t() == 0)
1891 return secondary_index_by_secondary.lower_bound(
1892 boost::make_tuple(secondary_table_id->id,
to_softfloat64(std::numeric_limits<double>::lowest()), 0));
1895 secondary_index_by_primary.lower_bound(
1896 boost::make_tuple(secondary_table_id->id, lower.to_uint64_t())));
1899 for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) {
1904 copy_inline_row(*kv_index.find(boost::make_tuple(
table_id->id, it->primary_key)), data);
1916 for (
auto p : db.active_producers().producers) {
1918 (
"owner",
p.producer_name)
1919 (
"producer_authority",
p.authority)
1921 (
"total_votes", 0.0f);
1924 if (std::holds_alternative<block_signing_authority_v0>(
p.authority)) {
1925 const auto& auth = std::get<block_signing_authority_v0>(
p.authority);
1926 if (auth.keys.size() == 1 && auth.keys.back().weight == auth.threshold) {
1927 row(
"producer_key", auth.keys.back().key);
1931 result.rows.push_back(row);
1943 if(proposed && !proposed->producers.empty())
1951 return [&control, yield{std::move(yield)}](
const account_name &
name) -> std::optional<abi_serializer> {
1952 const auto* accnt = control.
db().template find<account_object, by_name>(
name);
1953 if (accnt !=
nullptr) {
1959 return std::optional<abi_serializer>();
1968read_only::get_scheduled_transactions_result
1970 const auto&
d = db.
db();
1974 if (!
p.lower_bound.empty()) {
1977 return idx_by_delay.lower_bound(boost::make_tuple(when));
1982 auto itr = by_txid.find( txid );
1983 if (itr == by_txid.end()) {
1990 return idx_by_delay.end();
1994 return idx_by_delay.begin();
2004 while (itr != idx_by_delay.end() && remaining > 0 && time_limit >
fc::time_point::now()) {
2006 (
"trx_id", itr->trx_id)
2007 (
"sender", itr->sender)
2008 (
"sender_id", itr->sender_id)
2009 (
"payer", itr->payer)
2010 (
"delay_until", itr->delay_until)
2011 (
"expiration", itr->expiration)
2012 (
"published", itr->published)
2023 row(
"transaction", pretty_transaction);
2029 result.transactions.emplace_back(std::move(row));
2034 if (itr != idx_by_delay.end()) {
2035 result.more =
string(itr->trx_id);
2043 std::optional<uint64_t> block_num;
2046 chain::block_id_type_exception,
2047 "Invalid Block number or ID, must be greater than 0 and less than 64 characters"
2059 }
SYS_RETHROW_EXCEPTIONS(chain::block_id_type_exception,
"Invalid block ID: ${block_num_or_id}", (
"block_num_or_id",
params.block_num_or_id))
2062 SYS_ASSERT( block, unknown_block_exception,
"Could not find block: ${block}", (
"block",
params.block_num_or_id));
2068 const auto block_id = block->calculate_id();
2069 uint32_t ref_block_prefix = block_id._hash[1];
2073 (
"block_num",block->block_num())
2074 (
"ref_block_prefix", ref_block_prefix);
2086 SYS_ASSERT( block, unknown_block_exception,
"Could not find block: ${block}", (
"block",
params.block_num));
2088 const auto id = block->calculate_id();
2089 const uint32_t ref_block_prefix =
id._hash[1];
2092 (
"block_num", block->block_num())
2093 (
"ref_block_num",
static_cast<uint16_t>(block->block_num()))
2095 (
"timestamp", block->timestamp)
2096 (
"producer", block->producer)
2097 (
"confirmed", block->confirmed)
2098 (
"previous", block->previous)
2099 (
"transaction_mroot", block->transaction_mroot)
2100 (
"action_mroot", block->action_mroot)
2101 (
"schedule_version", block->schedule_version)
2102 (
"producer_signature", block->producer_signature)
2103 (
"ref_block_prefix", ref_block_prefix);
2108 std::optional<uint64_t> block_num;
2109 std::exception_ptr e;
2119 }
SYS_RETHROW_EXCEPTIONS(chain::block_id_type_exception,
"Invalid block ID: ${block_num_or_id}", (
"block_num_or_id",
params.block_num_or_id))
2122 SYS_ASSERT( b, unknown_block_exception,
"Could not find reversible block: ${block}", (
"block",
params.block_num_or_id));
2132 }
catch ( boost::interprocess::bad_alloc& ) {
2134 }
catch (
const std::bad_alloc& ) {
2142 auto pretty_input = std::make_shared<packed_transaction>();
2149 [
this, next](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) ->
void {
2150 if (std::holds_alternative<fc::exception_ptr>(result)) {
2151 next(std::get<fc::exception_ptr>(result));
2153 auto trx_trace_ptr = std::get<transaction_trace_ptr>(result);
2162 for(
const auto& act_trace : output[
"action_traces"].get_array() ) {
2163 if (act_trace[
"receipt"].is_null() && act_trace[
"except"].is_null())
continue;
2164 auto closest_unnotified_ancestor_action_ordinal =
2166 auto global_sequence = act_trace[
"receipt"].is_null() ?
2167 std::numeric_limits<uint64_t>::max() :
2168 act_trace[
"receipt"][
"global_sequence"].as<
uint64_t>();
2169 act_traces_map.emplace( std::make_pair( closest_unnotified_ancestor_action_ordinal,
2171 act_trace.get_object() );
2174 std::function<vector<fc::variant>(
uint32_t)> convert_act_trace_to_tree_struct =
2175 [&](
uint32_t closest_unnotified_ancestor_action_ordinal) {
2177 auto it = act_traces_map.lower_bound(
2178 std::make_pair( closest_unnotified_ancestor_action_ordinal, 0)
2181 it != act_traces_map.end() && it->first.first == closest_unnotified_ancestor_action_ordinal; ++it )
2183 auto& act_trace_mvo = it->second;
2186 act_trace_mvo[
"inline_traces"] = convert_act_trace_to_tree_struct(action_ordinal);
2187 if (act_trace_mvo[
"receipt"].is_null()) {
2190 (
"act_digest",
digest_type::hash(trx_trace_ptr->action_traces[action_ordinal-1].act))
2191 (
"auth_sequence", flat_map<account_name,uint64_t>())
2192 (
"code_sequence", 0)
2193 (
"global_sequence", 0)
2194 (
"receiver", act_trace_mvo[
"receiver"])
2195 (
"recv_sequence", 0);
2197 restructured_act_traces.push_back( std::move(act_trace_mvo) );
2199 return restructured_act_traces;
2203 output_mvo[
"action_traces"] = convert_act_trace_to_tree_struct(0);
2205 output = output_mvo;
2206 }
catch( chain::abi_exception& ) {
2207 output = *trx_trace_ptr;
2215 }
catch ( boost::interprocess::bad_alloc& ) {
2217 }
catch (
const std::bad_alloc& ) {
2223 auto wrapped_next = [=](
const std::variant<fc::exception_ptr, read_write::push_transaction_results>& result) {
2224 if (std::holds_alternative<fc::exception_ptr>(result)) {
2225 const auto& e = std::get<fc::exception_ptr>(result);
2228 const auto&
r = std::get<read_write::push_transaction_results>(result);
2232 size_t next_index = index + 1;
2233 if (next_index < params->size()) {
2245 SYS_ASSERT(
params.size() <= 1000, too_many_tx_at_once,
"Attempt to push too many transactions at once" );
2246 auto params_copy = std::make_shared<read_write::push_transactions_params>(
params.begin(),
params.end());
2247 auto result = std::make_shared<read_write::push_transactions_results>();
2248 result->reserve(
params.size());
2250 push_recurse(
this, 0, params_copy, result, next);
2251 }
catch ( boost::interprocess::bad_alloc& ) {
2253 }
catch (
const std::bad_alloc& ) {
2261 auto pretty_input = std::make_shared<packed_transaction>();
2268 [
this, next](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) ->
void {
2269 if (std::holds_alternative<fc::exception_ptr>(result)) {
2270 next(std::get<fc::exception_ptr>(result));
2272 auto trx_trace_ptr = std::get<transaction_trace_ptr>(result);
2278 }
catch( chain::abi_exception& ) {
2279 output = *trx_trace_ptr;
2287 }
catch ( boost::interprocess::bad_alloc& ) {
2289 }
catch (
const std::bad_alloc& ) {
2296 auto ptrx = std::make_shared<packed_transaction>();
2302 bool retry =
params.retry_trx;
2303 std::optional<uint16_t> retry_num_blocks =
params.retry_trx_num_blocks;
2305 SYS_ASSERT( !retry || trx_retry.has_value(), unsupported_feature,
"Transaction retry not enabled on node" );
2306 SYS_ASSERT( !retry || (ptrx->expiration() <= trx_retry->get_max_expiration_time()), tx_exp_too_far_exception,
2307 "retry transaction expiration ${e} larger than allowed ${m}",
2308 (
"e", ptrx->expiration())(
"m", trx_retry->get_max_expiration_time()) );
2311 [
this, ptrx, next, retry, retry_num_blocks](
const std::variant<fc::exception_ptr, transaction_trace_ptr>& result) ->
void {
2312 if( std::holds_alternative<fc::exception_ptr>( result ) ) {
2313 next( std::get<fc::exception_ptr>( result ) );
2316 auto trx_trace_ptr = std::get<transaction_trace_ptr>( result );
2317 if( retry && trx_retry.has_value() && !trx_trace_ptr->except) {
2319 trx_retry->track_transaction( ptrx, retry_num_blocks,
2320 [ptrx, next](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result ) {
2321 if( std::holds_alternative<fc::exception_ptr>( result ) ) {
2322 next( std::get<fc::exception_ptr>( result ) );
2324 fc::variant& output = *std::get<std::unique_ptr<fc::variant>>( result );
2325 next( read_write::send_transaction_results{ptrx->id(), std::move( output )} );
2331 output = db.to_variant_with_abi( *trx_trace_ptr, abi_serializer::create_yield_function( abi_serializer_max_time ) );
2332 } catch( chain::abi_exception& ) {
2333 output = *trx_trace_ptr;
2335 const chain::transaction_id_type& id = trx_trace_ptr->id;
2336 next( read_write::send_transaction_results{id, std::move( output )} );
2341 }
catch ( boost::interprocess::bad_alloc& ) {
2343 }
catch (
const std::bad_alloc& ) {
2350 result.account_name =
params.account_name;
2351 const auto&
d = db.db();
2356 result.abi = std::move(abi);
2364 result.account_name =
params.account_name;
2365 const auto&
d = db.db();
2369 SYS_ASSERT(
params.code_as_wasm, unsupported_feature,
"Returning WAST from get_code is no longer supported" );
2371 if( accnt_metadata_obj.code_hash !=
digest_type() ) {
2372 const auto& code_obj =
d.get<
code_object, by_code_hash>(accnt_metadata_obj.code_hash);
2373 result.wasm =
string(code_obj.code.begin(), code_obj.code.end());
2374 result.code_hash = code_obj.code_hash;
2379 result.abi = std::move(abi);
2387 result.account_name =
params.account_name;
2388 const auto&
d = db.db();
2392 result.code_hash = accnt.code_hash;
2399 result.account_name =
params.account_name;
2401 const auto&
d = db.db();
2404 if( accnt_metadata_obj.code_hash !=
digest_type() ) {
2405 const auto& code_obj =
d.get<
code_object, by_code_hash>(accnt_metadata_obj.code_hash);
2406 result.wasm =
blob{{code_obj.code.begin(), code_obj.code.end()}};
2408 result.abi =
blob{{accnt_obj.abi.begin(), accnt_obj.abi.end()}};
2415 result.account_name =
params.account_name;
2417 const auto&
d = db.db();
2420 result.abi_hash =
fc::sha256::hash( accnt_obj.abi.data(), accnt_obj.abi.size() );
2421 if( accnt_metadata_obj.code_hash !=
digest_type() )
2422 result.code_hash = accnt_metadata_obj.code_hash;
2423 if( !
params.abi_hash || *
params.abi_hash != result.abi_hash )
2424 result.abi =
blob{{accnt_obj.abi.begin(), accnt_obj.abi.end()}};
2431 result.account_name =
params.account_name;
2433 const auto&
d = db.db();
2434 const auto& rm = db.get_resource_limits_manager();
2436 result.head_block_num = db.head_block_num();
2437 result.head_block_time = db.head_block_time();
2439 rm.get_account_limits( result.account_name, result.ram_quota, result.net_weight, result.cpu_weight );
2441 const auto& accnt_obj = db.get_account( result.account_name );
2444 result.privileged = accnt_metadata_obj.is_privileged();
2445 result.last_code_update = accnt_metadata_obj.last_code_update;
2446 result.created = accnt_obj.creation_date;
2448 uint32_t greylist_limit = db.is_resource_greylisted(result.account_name) ? 1 : config::maximum_elastic_resource_multiplier;
2449 result.net_limit = rm.get_account_net_limit_ex( result.account_name, greylist_limit).first;
2450 result.cpu_limit = rm.get_account_cpu_limit_ex( result.account_name, greylist_limit).first;
2451 result.ram_usage = rm.get_account_ram_usage( result.account_name );
2453 if ( producer_plug ) {
2455 subjective_cpu_bill_limit.
used = producer_plug->get_subjective_bill( result.account_name,
fc::time_point::now() );
2456 result.subjective_cpu_bill_limit = subjective_cpu_bill_limit;
2459 const auto linked_action_map = ([&](){
2461 auto iter = links.lower_bound( boost::make_tuple(
params.account_name ) );
2463 std::multimap<name, linked_action> result;
2464 while (iter != links.end() && iter->account ==
params.account_name ) {
2465 auto action = iter->message_type.empty() ? std::optional<name>() : std::optional<name>(iter->message_type);
2466 result.emplace(std::make_pair(iter->required_permission,
linked_action{iter->code, std::move(action)}));
2473 auto get_linked_actions = [&](
chain::name perm_name) {
2474 auto link_bounds = linked_action_map.equal_range(perm_name);
2475 auto linked_actions = std::vector<linked_action>();
2476 linked_actions.reserve(linked_action_map.count(perm_name));
2477 for (
auto link = link_bounds.first; link != link_bounds.second; ++link) {
2478 linked_actions.push_back(link->second);
2480 return linked_actions;
2484 auto perm = permissions.lower_bound( boost::make_tuple(
params.account_name ) );
2485 while( perm != permissions.end() && perm->owner ==
params.account_name ) {
2490 if( perm->parent._id ) {
2493 SYS_ASSERT(perm->owner ==
p->owner, invalid_parent_permission,
"Invalid parent permission");
2498 auto linked_actions = get_linked_actions(perm->name);
2500 result.permissions.push_back(
permission{ perm->name, parent, perm->auth.to_authority(), std::move(linked_actions)} );
2505 result.sysio_any_linked_actions = get_linked_actions(chain::config::sysio_any_name);
2507 const auto& code_account = db.db().get<
account_object,by_name>( config::system_account_name );
2513 const auto token_code =
"sysio.token"_n;
2515 auto core_symbol = extract_core_symbol();
2517 if (
params.expected_core_symbol)
2518 core_symbol = *(
params.expected_core_symbol);
2520 const auto* t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( token_code,
params.account_name,
"accounts"_n ));
2521 if( t_id !=
nullptr ) {
2523 auto it = idx.find(boost::make_tuple( t_id->id, core_symbol.to_symbol_code() ));
2524 if( it != idx.end() && it->value.size() >=
sizeof(
asset) ) {
2530 result.core_liquid_balance = bal;
2535 t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( config::system_account_name,
params.account_name,
"userres"_n ));
2536 if (t_id !=
nullptr) {
2538 auto it = idx.find(boost::make_tuple( t_id->id,
params.account_name.to_uint64_t() ));
2539 if ( it != idx.end() ) {
2541 copy_inline_row(*it, data);
2546 t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( config::system_account_name,
params.account_name,
"delband"_n ));
2547 if (t_id !=
nullptr) {
2549 auto it = idx.find(boost::make_tuple( t_id->id,
params.account_name.to_uint64_t() ));
2550 if ( it != idx.end() ) {
2552 copy_inline_row(*it, data);
2557 t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( config::system_account_name,
params.account_name,
"refunds"_n ));
2558 if (t_id !=
nullptr) {
2560 auto it = idx.find(boost::make_tuple( t_id->id,
params.account_name.to_uint64_t() ));
2561 if ( it != idx.end() ) {
2563 copy_inline_row(*it, data);
2568 t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( config::system_account_name, config::system_account_name,
"voters"_n ));
2569 if (t_id !=
nullptr) {
2571 auto it = idx.find(boost::make_tuple( t_id->id,
params.account_name.to_uint64_t() ));
2572 if ( it != idx.end() ) {
2574 copy_inline_row(*it, data);
2579 t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( config::system_account_name, config::system_account_name,
"rexbal"_n ));
2580 if (t_id !=
nullptr) {
2582 auto it = idx.find(boost::make_tuple( t_id->id,
params.account_name.to_uint64_t() ));
2583 if( it != idx.end() ) {
2585 copy_inline_row(*it, data);
2595 auto it = std::find_if(abi.structs.begin(), abi.structs.end(), [&](
auto& x){return x.name == action_type;});
2596 if( it != abi.structs.end() )
2604 SYS_ASSERT(code_account !=
nullptr, contract_query_exception,
"Contract can't be found ${contract}", (
"contract",
params.code));
2614 "'${args}' is invalid args for action '${action}' code '${code}'. expected '${proto}'",
2617 SYS_ASSERT(
false, abi_not_found_exception,
"No ABI found for ${contract}", (
"contract",
params.code));
2624 abi_bin_to_json_result result;
2625 const auto& code_account = db.db().get<account_object,by_name>(
params.code );
2628 abi_serializer abis( abi, abi_serializer::create_yield_function( abi_serializer_max_time ) );
2629 result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs, abi_serializer::create_yield_function( abi_serializer_max_time ), shorten_abi_errors );
2631 SYS_ASSERT(false, abi_not_found_exception,
"No ABI found for ${contract}", (
"contract", params.code));
2636read_only::get_required_keys_result read_only::get_required_keys(
const get_required_keys_params&
params )
const {
2643 auto required_keys_set = db.get_authorization_manager().get_required_keys( pretty_input,
params.available_keys,
fc::seconds( pretty_input.delay_sec ));
2644 get_required_keys_result result;
2645 result.required_keys = required_keys_set;
2651 auto pretty_input = std::make_shared<packed_transaction>();
2657 app().get_method<incoming::methods::transaction_async>()(pretty_input, false, true, true,
2659 if (std::holds_alternative<fc::exception_ptr>(result)) {
2660 next(std::get<fc::exception_ptr>(result));
2662 auto trx_trace_ptr = std::get<transaction_trace_ptr>(result);
2668 }
catch( chain::abi_exception& ) {
2669 output = *trx_trace_ptr;
2673 next(compute_transaction_results{
id, output});
2677 }
catch ( boost::interprocess::bad_alloc& ) {
2679 }
catch (
const std::bad_alloc& ) {
2683read_only::get_transaction_id_result read_only::get_transaction_id(
const read_only::get_transaction_id_params&
params)
const {
2688account_query_db::get_accounts_by_authorizers_result read_only::get_accounts_by_authorizers(
const account_query_db::get_accounts_by_authorizers_params& args)
const
2690 SYS_ASSERT(aqdb.has_value(), plugin_config_exception,
"Account Queries being accessed when not enabled");
2691 return aqdb->get_accounts_by_authorizers(args);
2695 struct ram_market_exchange_state_t {
2708 const auto&
d = db.db();
2709 const auto* t_id =
d.find<
chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple(
"sysio"_n,
"sysio"_n,
"rammarket"_n ));
2710 if( t_id !=
nullptr ) {
2712 auto it = idx.find(boost::make_tuple( t_id->id, sysio::chain::string_to_symbol_c(4,
"RAMCORE") ));
2713 if( it != idx.end() ) {
2714 detail::ram_market_exchange_state_t ram_market_exchange_state;
2724 if( ram_market_exchange_state.core_symbol.get_symbol().valid() ) {
2725 core_symbol = ram_market_exchange_state.core_symbol.get_symbol();
2742 pretty_output = trx_trace;
2744 return pretty_output;
2754 pretty_output = trx;
2756 return pretty_output;
2760FC_REFLECT( sysio::chain_apis::detail::ram_market_exchange_state_t, (ignore1)(ignore2)(ignore3)(core_symbol)(ignore4) )
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
#define SYS_RETHROW_EXCEPTIONS(exception_type, FORMAT,...)
#define CATCH_AND_CALL(NEXT)
FC_REFLECT_ENUM(chainbase::environment::os_t,(OS_LINUX)(OS_MACOS)(OS_WINDOWS)(OS_OTHER)) FC_REFLECT_ENUM(chainbase sysio::chain::deep_mind_handler _deep_mind_log
#define LOAD_VALUE_SET(options, op_name, container)
abstract_plugin * find_plugin(const string &name) const
bfs::path data_dir() const
Get data directory.
string version_string() const
Get version string; generated from git describe if available.
auto get_method() -> std::enable_if_t< is_method_decl< MethodDecl >::value, typename MethodDecl::method_type & >
bfs::path config_dir() const
Get config directory.
void register_config_type()
string full_version_string() const
Get full version string; same as version_string() unless set differently.
void publish(int priority, const Data &data)
virtual void shutdown() override
const generic_index< MultiIndexType > & get_index() const
const ObjectType * find(CompatibleKey &&key) const
const char * data() const
static bool supports_hole_punching()
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_file(const fc::path &p, const parse_type ptype=parse_type::legacy_parser, const uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
static bool save_to_file(const T &v, const fc::path &fi, const bool pretty=true, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
static string to_pretty_string(const variant &v, const yield_function_t &yield, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
static variant from_string(const string &utf8_str, const parse_type ptype=parse_type::legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
constexpr int64_t count() const
An order-preserving dictionary of variants.
wraps boost::filesystem::path to provide platform independent path manipulation.
static sha256 hash(const char *d, uint32_t dlen)
constexpr const microseconds & time_since_epoch() const
static time_point from_iso_string(const fc::string &s)
An order-preserving dictionary of variants.
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
variant_object & get_object()
static std::optional< genesis_state > extract_genesis_state(const fc::path &data_dir)
static fc::path repair_log(const fc::path &data_dir, uint32_t truncate_at_block=0, const char *reversible_block_dir_name="")
static chain_id_type extract_chain_id(const fc::path &data_dir)
block_state_ptr fetch_block_state_by_number(uint32_t block_num) const
const chainbase::database & db() const
signed_block_ptr fetch_block_by_number(uint32_t block_num) const
static std::optional< chain_id_type > extract_chain_id_from_db(const path &state_dir)
static chain_id_type extract_chain_id(snapshot_reader &snapshot)
std::optional< producer_authority_schedule > proposed_producers() const
const producer_authority_schedule & pending_producers() const
signed_block_ptr fetch_block_by_id(block_id_type id) const
block_state_ptr fetch_block_state_by_id(block_id_type id) const
const producer_authority_schedule & active_producers() const
fc::variant to_variant_with_abi(const T &obj, const abi_serializer::yield_function_t &yield) const
void update_logger(const std::string &logger_name)
void validate() const override
static builtin_protocol_feature make_default_builtin_protocol_feature(builtin_protocol_feature_t codename, const std::function< digest_type(builtin_protocol_feature_t dependency)> &handle_dependency)
const protocol_feature & add_feature(const builtin_protocol_feature &f)
static symbol from_string(const string &from)
The table_id_object class tracks the mapping of (scope, code, table) to an opaque identifier.
static std::string vm_type_string(vm_type vmtype)
void walk_key_value_table(const name &code, const name &scope, const name &table, Function f) const
static void copy_inline_row(const chain::key_value_object &obj, vector< char > &data)
static const string KEYi64
fc::variant get_block_info(const get_block_info_params ¶ms) const
fc::variant get_block(const get_block_params ¶ms) const
fc::variant get_currency_stats(const get_currency_stats_params ¶ms) const
get_producers_result get_producers(const get_producers_params ¶ms) const
get_scheduled_transactions_result get_scheduled_transactions(const get_scheduled_transactions_params ¶ms) const
fc::variant get_block_header_state(const get_block_header_state_params ¶ms) const
get_producer_schedule_result get_producer_schedule(const get_producer_schedule_params ¶ms) const
void push_block(push_block_params &¶ms, chain::plugin_interface::next_function< push_block_results > next)
void push_transactions(const push_transactions_params ¶ms, chain::plugin_interface::next_function< push_transactions_results > next)
void send_transaction(const send_transaction_params ¶ms, chain::plugin_interface::next_function< send_transaction_results > next)
read_write(controller &db, std::optional< trx_retry_db > &trx_retry, const fc::microseconds &abi_serializer_max_time, bool api_accept_transactions)
void send_transaction2(const send_transaction2_params ¶ms, chain::plugin_interface::next_function< send_transaction_results > next)
void push_transaction(const push_transaction_params ¶ms, chain::plugin_interface::next_function< push_transaction_results > next)
std::optional< controller > chain
fc::microseconds abi_serializer_max_time_us
std::optional< vm_type > wasm_runtime
bool api_accept_transactions
methods::get_last_irreversible_block_number::method_type::handle get_last_irreversible_block_number_provider
methods::get_head_block_id::method_type::handle get_head_block_id_provider
std::optional< scoped_connection > accepted_block_header_connection
methods::get_block_by_id::method_type::handle get_block_by_id_provider
std::optional< genesis_state > genesis
std::optional< scoped_connection > accepted_transaction_connection
channels::pre_accepted_block::channel_type & pre_accepted_block_channel
channels::irreversible_block::channel_type & irreversible_block_channel
incoming::methods::block_sync::method_type & incoming_block_sync_method
std::optional< scoped_connection > block_start_connection
const producer_plugin * producer_plug
std::optional< scoped_connection > accepted_block_connection
chain_apis::trx_finality_status_processing_ptr _trx_finality_status_processing
flat_map< uint32_t, block_id_type > loaded_checkpoints
std::optional< scoped_connection > pre_accepted_block_connection
channels::accepted_block_header::channel_type & accepted_block_header_channel
methods::get_block_by_number::method_type::handle get_block_by_number_provider
bool account_queries_enabled
channels::accepted_transaction::channel_type & accepted_transaction_channel
std::optional< scoped_connection > applied_transaction_connection
incoming::methods::transaction_async::method_type & incoming_transaction_async_method
std::optional< chain_apis::account_query_db > _account_query_db
std::optional< scoped_connection > irreversible_block_connection
channels::applied_transaction::channel_type & applied_transaction_channel
channels::accepted_block::channel_type & accepted_block_channel
std::optional< chain_apis::trx_retry_db > _trx_retry_db
std::optional< controller::config > chain_config
std::optional< bfs::path > snapshot_path
void plugin_initialize(const variables_map &options)
static void handle_db_exhaustion()
bool accept_block(const chain::signed_block_ptr &block, const chain::block_id_type &id, const chain::block_state_ptr &bsp)
bool api_accept_transactions() const
fc::microseconds get_abi_serializer_max_time() const
chain_apis::read_write get_read_write_api()
void enable_accept_transactions()
bool account_queries_enabled() const
void do_hard_replay(const variables_map &options)
chain_apis::read_only get_read_only_api() const
static void handle_guard_exception(const chain::guard_exception &e)
bool transaction_finality_status_enabled() const
chain::chain_id_type get_chain_id() const
static void handle_bad_alloc()
virtual void set_program_options(options_description &cli, options_description &cfg) override
void accept_transaction(const chain::packed_transaction_ptr &trx, chain::plugin_interface::next_function< chain::transaction_trace_ptr > next)
fc::variant get_log_trx_trace(const chain::transaction_trace_ptr &trx_trace) const
bool accept_transactions() const
fc::variant get_log_trx(const transaction &trx) const
void handle_sighup() override
std::array< uint8_t, Size > extract_as_byte_array() const
bool starts_with(std::string const &str, std::string const &pref)
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_LOG_AND_RETHROW()
#define FC_LOG_AND_DROP(...)
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
static const Segment ds(Segment::ds)
void unpack(Stream &s, std::deque< T > &value)
void rename(const path &from, const path &to)
bool remove(const path &p)
std::shared_ptr< exception > exception_ptr
bool exists(const path &p)
void remove_all(const path &p)
void uint128_to_float128(const sysio::chain::uint128_t &u, float128_t &f)
bool is_regular_file(const path &p)
void double_to_float64(const double &d, float64_t &f)
constexpr microseconds seconds(int64_t s)
bool is_directory(const path &p)
uint64_t to_uint64(const fc::string &)
datastream< ST > & operator<<(datastream< ST > &s, const sysio::chain::may_not_exist< T > &v)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
std::function< void(const std::variant< fc::exception_ptr, T > &)> next_function
string convert_to_string(const Type &source, const string &key_type, const string &encode_type, const string &desc)
string get_table_type(const abi_def &abi, const name &table_name)
auto make_resolver(const controller &control, abi_serializer::yield_function_t yield)
abi_def get_abi(const controller &db, const name &account)
std::function< void(const std::variant< fc::exception_ptr, T > &)> next_function
std::string itoh(I n, size_t hlen=sizeof(I)<< 1)
uint64_t convert_to_type(const string &str, const string &desc)
fc::variant get_global_row(const database &db, const abi_def &abi, const abi_serializer &abis, const fc::microseconds &abi_serializer_max_time_us, bool shorten_abi_errors)
std::unique_ptr< trx_finality_status_processing > trx_finality_status_processing_ptr
const std::unordered_map< builtin_protocol_feature_t, builtin_protocol_feature_spec, enum_hash< builtin_protocol_feature_t > > builtin_protocol_feature_codenames
chainbase::shared_multi_index_container< permission_link_object, indexed_by< ordered_unique< tag< by_id >, >, ordered_unique< tag< by_action_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, code), > >, ordered_unique< tag< by_permission_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, permission_name, required_permission), > > > > permission_link_index
checksum_type digest_type
builtin_protocol_feature_t
std::array< uint128_t, 2 > key256_t
chainbase::shared_multi_index_container< permission_object, indexed_by< ordered_unique< tag< by_id >, member< permission_object, permission_object::id_type, &permission_object::id > >, ordered_unique< tag< by_parent >, composite_key< permission_object, member< permission_object, permission_object::id_type, &permission_object::parent >, member< permission_object, permission_object::id_type, &permission_object::id > > >, ordered_unique< tag< by_owner >, composite_key< permission_object, member< permission_object, account_name, &permission_object::owner >, member< permission_object, permission_name, &permission_object::name > > >, ordered_unique< tag< by_name >, composite_key< permission_object, member< permission_object, permission_name, &permission_object::name >, member< permission_object, permission_object::id_type, &permission_object::id > > > > > permission_index
std::shared_ptr< transaction_trace > transaction_trace_ptr
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 transaction_exception
secondary_index< float64_t, index_double_object_type, soft_double_less >::index_index index_double_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
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 action_validate_exception
sysio::chain::action_name action_name
chain type exception chain_type_exception
const char * builtin_protocol_feature_codename(builtin_protocol_feature_t)
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
bool validate(const Authority &auth)
checksum_type transaction_id_type
chainbase::shared_multi_index_container< key_value_object, indexed_by< ordered_unique< tag< by_id >, member< key_value_object, key_value_object::id_type, &key_value_object::id > >, ordered_unique< tag< by_scope_primary >, composite_key< key_value_object, member< key_value_object, table_id, &key_value_object::t_id >, member< key_value_object, uint64_t, &key_value_object::primary_key > >, composite_key_compare< std::less< table_id >, std::less< uint64_t > > > > > key_value_index
chainbase::shared_multi_index_container< table_id_object, indexed_by< ordered_unique< tag< by_id >, member< table_id_object, table_id_object::id_type, &table_id_object::id > >, ordered_unique< tag< by_code_scope_table >, composite_key< table_id_object, member< table_id_object, account_name, &table_id_object::code >, member< table_id_object, scope_name, &table_id_object::scope >, member< table_id_object, table_name, &table_id_object::table > > > > > table_id_multi_index
std::shared_ptr< block_state > block_state_ptr
std::shared_ptr< transaction_metadata > transaction_metadata_ptr
fc::time_point calculate_genesis_timestamp(string tstr)
protocol_feature_set initialize_protocol_features(const fc::path &p, bool populate_missing_builtins=true)
std::optional< builtin_protocol_feature > read_builtin_protocol_feature(const fc::path &p)
void clear_chainbase_files(const fc::path &p)
void clear_directory_contents(const fc::path &p)
uint32_t next(octet_iterator &it, octet_iterator end)
const CharType(& source)[N]
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
const fc::microseconds abi_serializer_max_time
#define FC_REFLECT(TYPE, MEMBERS)
Specializes fc::reflector for TYPE.
#define FC_REFLECT_ENUM(ENUM, FIELDS)
float64_t f128_to_f64(float128_t a)
void f64_to_f128M(float64_t a, float128_t *zPtr)
float64_t to_softfloat64(double d)
unsigned __int64 uint64_t
static constexpr int medium
static constexpr int high
static yield_function_t create_yield_function(const fc::microseconds &max_serialization_time)
type_name get_table_type(name action) const
static void to_log_variant(const T &o, fc::variant &vo, Resolver resolver, const yield_function_t &yield)
static bool to_abi(const Vec &abi_vec, abi_def &abi)
bytes variant_to_binary(const std::string_view &type, const fc::variant &var, const fc::microseconds &max_serialization_time, bool short_path=false) const
type_name get_action_type(name action) const
static void to_variant(const T &o, fc::variant &vo, Resolver resolver, const yield_function_t &yield)
namespace sysio::chain::impl
fc::variant binary_to_variant(const std::string_view &type, const bytes &binary, const yield_function_t &yield, bool short_path=false) const
static void from_variant(const fc::variant &v, T &o, Resolver resolver, const yield_function_t &yield)
const symbol & get_symbol() const
static const string sysio_root_key
time_point initial_timestamp
chain_id_type compute_chain_id() const
Immutable except for fc::from_variant.
std::string to_string() const
vector< producer_authority > producers
digest_type feature_digest
int64_t used
quantity used in current window
chain::transaction_id_type id
static auto make(const controller &control, abi_serializer::yield_function_t yield)
chain::block_id_type earliest_tracked_block_id
chain::block_timestamp_type irr_block_timestamp
chain::block_id_type head_id
chain::block_timestamp_type head_block_timestamp
chain::block_id_type irr_id
account_query_db::get_accounts_by_authorizers_result results
account_query_db::get_accounts_by_authorizers_params params
memcpy((char *) pInfo->slotDescription, s, l)