30#include <sysio/vm/allocator.hpp>
38namespace sysio {
namespace chain {
40using resource_limits::resource_limits_manager;
71 :_session(move(other._session))
98 _session.emplace(move(*mv._session));
108 std::optional<database::session> _session;
114 uint16_t num_prev_blocks_to_confirm,
150 uint16_t num_prev_blocks_to_confirm,
163 if( std::holds_alternative<building_block>(
_block_stage) )
164 return std::get<building_block>(
_block_stage)._pending_block_header_state;
166 return std::get<assembled_block>(
_block_stage)._pending_block_header_state;
170 if( std::holds_alternative<building_block>(
_block_stage) )
171 return std::get<building_block>(
_block_stage)._pending_trx_receipts;
173 if( std::holds_alternative<assembled_block>(
_block_stage) )
174 return std::get<assembled_block>(
_block_stage)._unsigned_block->transactions;
176 return std::get<completed_block>(
_block_stage)._block_state->block->transactions;
180 if( std::holds_alternative<building_block>(
_block_stage) )
181 return std::move( std::get<building_block>(
_block_stage)._pending_trx_metas );
183 if( std::holds_alternative<assembled_block>(
_block_stage) )
184 return std::move( std::get<assembled_block>(
_block_stage)._trx_metas );
186 return std::get<completed_block>(
_block_stage)._block_state->extract_trxs_metas();
190 if( std::holds_alternative<building_block>(
_block_stage) ) {
192 const auto& activated_features = bb._pending_block_header_state.prev_activated_protocol_features->protocol_features;
194 if( activated_features.find( feature_digest ) != activated_features.end() )
return true;
196 if( bb._num_new_protocol_features_that_have_activated == 0 )
return false;
198 auto end = bb._new_protocol_feature_activations.begin() + bb._num_new_protocol_features_that_have_activated;
199 return (std::find( bb._new_protocol_feature_activations.begin(), end, feature_digest ) != end);
202 if( std::holds_alternative<assembled_block>(
_block_stage) ) {
207 "checking if protocol feature is activated in the assembled_block stage is not yet supported" );
211 const auto& activated_features = std::get<completed_block>(
_block_stage)._block_state->activated_protocol_features->protocol_features;
212 return (activated_features.find( feature_digest ) != activated_features.end());
251#if defined(SYSIO_SYS_VM_RUNTIME_ENABLED) || defined(SYSIO_SYS_VM_JIT_RUNTIME_ENABLED)
278 template<builtin_protocol_feature_t F>
281 template<builtin_protocol_feature_t F>
284 SYS_ASSERT( res.second, misc_exception,
"attempting to set activation handler twice" );
290 (itr->second)( *
this );
302 cfg.state_size, false, cfg.db_map_mode ),
303 blog( cfg.blocks_dir, cfg.prune_config ),
304 fork_db( cfg.blocks_dir /
config::reversible_blocks_dir_name ),
305 wasmif( cfg.wasm_runtime, cfg.eosvmoc_tierup,
db, cfg.state_dir, cfg.eosvmoc_config, !cfg.profile_accounts.empty() ),
315 const flat_set<digest_type>& cur_features,
338#define SET_APP_HANDLER( receiver, contract, action) \
339 set_apply_handler( account_name(#receiver), account_name(#contract), action_name(#action), \
340 &BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) )
367 template<
typename Signal,
typename Arg>
370 s( std::forward<Arg>(
a ));
371 }
catch (std::bad_alloc& e) {
372 wlog(
"std::bad_alloc: ${w}", (
"w", e.what()) );
374 }
catch (boost::interprocess::bad_alloc& e) {
375 wlog(
"boost::interprocess::bad alloc: ${w}", (
"w", e.what()) );
377 }
catch ( controller_emit_signal_exception& e ) {
378 wlog(
"controller_emit_signal_exception: ${details}", (
"details", e.to_detail_string()) );
381 wlog(
"fc::exception: ${details}", (
"details", e.to_detail_string()) );
382 }
catch ( std::exception& e ) {
383 wlog(
"std::exception: ${details}", (
"details", e.what()) );
385 wlog(
"signal handler threw exception" );
408 "empty block log expects the first appended block to build off a block that is not the fork database root. root block number: ${block_num}, lib: ${lib_num}", (
"block_num",
fork_db.
root()->block_num) (
"lib_num", lib_num) );
413 if( fork_head->dpos_irreversible_blocknum <= lib_num )
416 const auto branch =
fork_db.
fetch_branch( fork_head->id, fork_head->dpos_irreversible_blocknum );
419 for(
auto bitr = branch.rbegin(); bitr != branch.rend(); ++bitr ) {
433 root_id = (*bitr)->id;
435 }
catch( std::exception& ) {
453 wlog(
"Initializing new blockchain with genesis state" );
467 head = std::make_shared<block_state>();
470 head->block = std::make_shared<signed_block>(genheader.
header);
475 void replay(std::function<
bool()> check_shutdown) {
483 auto start_block_num =
head->block_num + 1;
486 std::exception_ptr except_ptr;
488 if( blog_head && start_block_num <= blog_head->block_num() ) {
489 ilog(
"existing block log, attempting to replay from ${s} to ${n} blocks",
490 (
"s", start_block_num)(
"n", blog_head->block_num()) );
494 if( check_shutdown() )
break;
495 if( next->block_num() % 500 == 0 ) {
496 ilog(
"${n} of ${head}", (
"n", next->block_num())(
"head", blog_head->block_num()) );
499 }
catch(
const database_guard_exception& e ) {
500 except_ptr = std::current_exception();
502 ilog(
"${n} irreversible blocks replayed", (
"n", 1 +
head->block_num - start_block_num) );
506 ilog(
"fork database head ${h}, root ${r}", (
"h", pending_head->block_num)(
"r",
fork_db.
root()->block_num ) );
507 if( pending_head->block_num <
head->block_num ||
head->block_num <
fork_db.
root()->block_num ) {
508 ilog(
"resetting fork database with new last irreversible block as the new root: ${id}", (
"id",
head->id) );
513 "unexpected error: could not find new LIB in fork database" );
514 ilog(
"advancing fork database root to new last irreversible block within existing fork database: ${id}",
515 (
"id", new_root->id) );
526 ilog(
"no irreversible blocks need to be replayed" );
529 if( !except_ptr && !check_shutdown() &&
fork_db.
head() ) {
530 auto head_block_num =
head->block_num;
533 for(
auto i = branch.rbegin(); i != branch.rend(); ++i ) {
534 if( check_shutdown() )
break;
535 if( (*i)->block_num <= head_block_num )
continue;
539 ilog(
"${n} reversible blocks replayed", (
"n",rev) );
547 ilog(
"replayed ${n} blocks in ${duration} seconds, ${mspb} ms/block",
548 (
"n",
head->block_num + 1 - start_block_num)(
"duration", (end-start).count()/1000000)
549 (
"mspb", ((end-start).count()/1000.0)/(
head->block_num-start_block_num)) );
553 std::rethrow_exception( except_ptr );
558 SYS_ASSERT( snapshot, snapshot_exception,
"No snapshot reader provided" );
560 ilog(
"Starting initialization from snapshot, this may take a significant amount of time" );
562 snapshot->validate();
569 "Snapshot indicates controller head at block number 0, but that is not allowed. "
570 "Snapshot is invalid." );
574 ilog(
"database initialized with hash: ${hash}", (
"hash", hash) );
576 init(check_shutdown);
577 ilog(
"Finished initialization from snapshot" );
578 }
catch (boost::interprocess::bad_alloc& e) {
579 elog(
"Failed initialization from snapshot - db storage not configured to have enough storage for the provided snapshot, please increase and retry snapshot" );
587 const auto& genesis_chain_id = genesis.compute_chain_id();
589 "genesis state provided to startup corresponds to a chain ID (${genesis_chain_id}) that does not match the chain ID that controller was constructed with (${controller_chain_id})",
590 (
"genesis_chain_id", genesis_chain_id)(
"controller_chain_id",
chain_id)
598 wlog(
"No existing chain state. Initializing fresh blockchain state." );
600 wlog(
"No existing chain state or fork database. Initializing fresh blockchain state and resetting fork database.");
610 "block log does not start with genesis block"
615 init(check_shutdown);
628 "block log (ranging from ${block_log_first_num} to ${block_log_last_num}) does not contain the last irreversible block (${fork_db_lib})",
629 (
"block_log_first_num", first_block_num)
630 (
"block_log_last_num",
blog.
head()->block_num())
631 (
"fork_db_lib", lib_num)
635 if( first_block_num != (lib_num + 1) ) {
645 init(check_shutdown);
653 SYS_ASSERT(header_idx.begin() != header_idx.end(), bad_database_version_exception,
654 "state database version pre-dates versioning, please restore from a compatible snapshot or replay!");
656 auto header_itr = header_idx.begin();
657 header_itr->validate();
662 void init(std::function<
bool()> check_shutdown) {
668 "chain ID in state (${state_chain_id}) does not match the chain ID that controller was constructed with (${controller_chain_id})",
669 (
"state_chain_id", state_chain_id)(
"controller_chain_id",
chain_id)
674 if (header_itr->version != database_header_object::current_version) {
675 db.
modify(*header_itr, [](
auto& header) {
676 header.version = database_header_object::current_version;
682 "fork database head (${head}) is inconsistent with state (${db})",
686 wlog(
"database revision (${db}) is greater than head block number (${head}), "
687 "attempting to undo pending changes",
697 dm_logger->on_startup(
db,
head->block_num);
702 if( check_shutdown() )
return;
712 wlog(
"read_mode has changed from irreversible: applying best branch from fork database" );
718 wlog(
"applying branch from fork database ending with block: ${id}", (
"id", pending_head->id) );
730 controller_index_set::add_indices(
db);
731 contract_database_index_set::add_indices(
db);
748 snapshot->write_section(
"contract_tables", [
this](
auto& section ) {
751 section.add_row(table_row,
db);
754 contract_database_index_set::walk_indices([
this, §ion, &table_row](
auto utils ) {
755 using utils_t =
decltype(utils);
756 using value_t =
typename decltype(utils)::index_t::value_type;
759 auto tid_key = boost::make_tuple(table_row.id);
762 unsigned_int size = utils_t::template size_range<by_table_id>(
db, tid_key, next_tid_key);
763 section.add_row(size,
db);
765 utils_t::template walk_range<by_table_id>(
db, tid_key, next_tid_key, [
this, §ion](
const auto &row ) {
766 section.add_row(row,
db);
774 snapshot->read_section(
"contract_tables", [
this](
auto& section ) {
775 bool more = !section.empty();
780 section.read_row(row,
db);
785 contract_database_index_set::walk_indices([
this, §ion, &t_id, &more](
auto utils) {
786 using utils_t =
decltype(utils);
789 more = section.read_row(size,
db);
791 for (
size_t idx = 0; idx < size.
value; idx++) {
792 utils_t::create(
db, [
this, §ion, &more, &t_id](
auto& row) {
794 more = section.read_row(row,
db);
810 snapshot->write_section<
block_state>([
this](
auto §ion ){
811 section.template add_row<block_header_state>(*
head,
db);
814 controller_index_set::walk_indices([
this, &snapshot](
auto utils ){
815 using value_t =
typename decltype(utils)::index_t::value_type;
818 if (std::is_same<value_t, table_id_object>::value) {
823 if (std::is_same<value_t, database_header_object>::value) {
827 snapshot->write_section<value_t>([
this](
auto& section ){
828 decltype(utils)::walk(
db, [
this, §ion](
const auto &row ) {
829 section.add_row(row,
db);
841 std::optional<genesis_state> genesis;
844 if (std::clamp(version, v2::minimum_version, v2::maximum_version) == version ) {
846 snapshot.read_section<
genesis_state>([&genesis=*genesis](
auto §ion ){
847 section.read_row(genesis);
856 section.read_row(header,
db);
864 if (std::clamp(header.
version, v2::minimum_version, v2::maximum_version) == header.
version ) {
865 snapshot->read_section<
block_state>([
this, &head_header_state](
auto §ion ) {
867 section.read_row(legacy_header_state,
db);
871 snapshot->read_section<
block_state>([
this,&head_header_state](
auto §ion ){
872 section.read_row(head_header_state,
db);
879 "Block log is provided with snapshot but does not contain the head block from the snapshot nor a block right after it",
881 (
"block_log_first_num", blog_start)
882 (
"block_log_last_num", blog_end)
885 head = std::make_shared<block_state>();
889 controller_index_set::walk_indices([
this, &snapshot, &header](
auto utils ){
890 using value_t =
typename decltype(utils)::index_t::value_type;
893 if (std::is_same<value_t, table_id_object>::value) {
898 if (std::is_same<value_t, database_header_object>::value) {
903 if (std::is_same<value_t, global_property_object>::value) {
908 if (std::clamp(header.
version, v2::minimum_version, v2::maximum_version) == header.
version ) {
911 "Snapshot indicates chain_snapshot_header version 2, but does not contain a genesis_state. "
912 "It must be corrupted.");
914 v2 legacy_global_properties;
915 section.read_row(legacy_global_properties,
db);
925 if (std::clamp(header.
version, v3::minimum_version, v3::maximum_version) == header.
version ) {
927 v3 legacy_global_properties;
928 section.read_row(legacy_global_properties,
db);
938 if (std::clamp(header.
version, v4::minimum_version, v4::maximum_version) == header.
version) {
940 v4 legacy_global_properties;
941 section.read_row(legacy_global_properties,
db);
944 gpo.initalize_from(legacy_global_properties);
951 snapshot->read_section<value_t>([
this](
auto& section ) {
952 bool more = !section.empty();
954 decltype(utils)::create(
db, [
this, §ion, &more](
auto &row ) {
955 more = section.read_row(row,
db);
973 "chain ID in snapshot (${snapshot_chain_id}) does not match the chain ID that controller was constructed with (${controller_chain_id})",
974 (
"snapshot_chain_id", gpo.chain_id)(
"controller_chain_id",
chain_id)
980 auto hash_writer = std::make_shared<integrity_hash_snapshot_writer>(enc);
982 hash_writer->finalize();
990 a.creation_date = initial_timestamp;
992 if(
name == config::system_account_name ) {
1000 a.set_privileged( is_privileged );
1004 owner, initial_timestamp );
1006 active, initial_timestamp );
1010 int64_t ram_delta = config::overhead_per_account_ram_bytes;
1012 ram_delta += owner_permission.auth.get_billable_size();
1013 ram_delta += active_permission.auth.get_billable_size();
1016 dm_logger->on_ram_trace(
RAM_EVENT_ID(
"${name}", (
"name",
name)),
"account",
"add",
"newaccount");
1030 for (
int i = 0; i < 0x10000; i++)
1034 db.
modify( tapos_block_summary, [&](
auto& bs ) {
1035 bs.block_id =
head->id;
1038 genesis.initial_configuration.validate();
1040 gpo.configuration = genesis.initial_configuration;
1047 pso.num_supported_key_types = config::genesis_num_supported_key_types;
1058 authority system_auth(genesis.initial_key);
1059 create_native_account( genesis.initial_timestamp, config::system_account_name, system_auth, system_auth,
true );
1061 auto empty_authority =
authority(1, {}, {});
1062 auto active_producers_authority =
authority(1, {}, {});
1063 active_producers_authority.
accounts.push_back({{config::system_account_name, config::active_name}, 1});
1065 create_native_account( genesis.initial_timestamp, config::null_account_name, empty_authority, empty_authority );
1066 create_native_account( genesis.initial_timestamp, config::producers_account_name, empty_authority, active_producers_authority );
1069 config::majority_producers_permission_name,
1070 active_permission.id,
1071 active_producers_authority,
1072 genesis.initial_timestamp );
1074 config::minority_producers_permission_name,
1075 majority_permission.id,
1076 active_producers_authority,
1077 genesis.initial_timestamp );
1083 auto& bb = std::get<building_block>(
pending->_block_stage);
1084 auto orig_block_transactions_size = bb._pending_trx_receipts.size();
1085 auto orig_state_transactions_size = bb._pending_trx_metas.size();
1086 auto orig_action_receipt_digests_size = bb._action_receipt_digests.size();
1088 std::function<void()> callback = [
this,
1089 orig_block_transactions_size,
1090 orig_state_transactions_size,
1091 orig_action_receipt_digests_size]()
1093 auto& bb = std::get<building_block>(
pending->_block_stage);
1094 bb._pending_trx_receipts.resize(orig_block_transactions_size);
1095 bb._pending_trx_metas.resize(orig_state_transactions_size);
1096 bb._action_receipt_digests.resize(orig_action_receipt_digests_size);
1108 bool explicit_billed_cpu_time =
false,
1109 bool enforce_whiteblacklist =
true
1126 dm_logger->on_onerror(etrx);
1134 trx_context.max_transaction_time_subjective = max_transaction_time;
1140 auto handle_exception = [&](
const auto& e)
1145 trace->except_ptr = std::current_exception();
1163 }
catch(
const disallowed_transaction_extensions_bad_block_exception& ) {
1165 }
catch(
const protocol_feature_bad_block_exception& ) {
1167 }
catch (
const std::bad_alloc& ) {
1169 }
catch (
const boost::interprocess::bad_alloc& ) {
1172 handle_exception(e);
1173 }
catch (
const std::exception& e ) {
1175 handle_exception(wrapper);
1182 dm_logger->on_ram_trace(
RAM_EVENT_ID(
"${id}", (
"id", gto.id)),
"deferred_trx",
"remove",
"deferred_trx_removed");
1194 auto code = e.
code();
1195 return (code == subjective_block_production_exception::code_value)
1196 || (code == block_net_usage_exceeded::code_value)
1197 || (code == greylist_net_usage_exceeded::code_value)
1198 || (code == block_cpu_usage_exceeded::code_value)
1199 || (code == greylist_cpu_usage_exceeded::code_value)
1200 || (code == deadline_exception::code_value)
1201 || (code == leeway_deadline_exception::code_value)
1202 || (code == actor_whitelist_exception::code_value)
1203 || (code == actor_blacklist_exception::code_value)
1204 || (code == contract_whitelist_exception::code_value)
1205 || (code == contract_blacklist_exception::code_value)
1206 || (code == action_blacklist_exception::code_value)
1207 || (code == key_blacklist_exception::code_value)
1208 || (code == sig_variable_size_limit_exception::code_value)
1209 || (code == inline_action_too_big_nonprivileged::code_value);
1213 auto code = e.
code();
1214 return (code == tx_cpu_usage_exceeded::code_value)
1220 uint32_t billed_cpu_time_us,
bool explicit_billed_cpu_time =
false )
1223 auto itr = idx.find( trxid );
1224 SYS_ASSERT( itr != idx.end(), unknown_transaction_exception,
"unknown transaction" );
1225 return push_scheduled_transaction( *itr, block_deadline, max_transaction_time, billed_cpu_time_us, explicit_billed_cpu_time );
1230 uint32_t billed_cpu_time_us,
bool explicit_billed_cpu_time =
false )
1260 trx->accepted =
true;
1264 trace = std::make_shared<transaction_trace>();
1265 trace->id = gtrx.trx_id;
1269 trace->scheduled =
true;
1271 trace->account_ram_delta =
account_delta( gtrx.payer, trx_removal_ram_delta );
1284 uint32_t cpu_time_to_bill_us = billed_cpu_time_us;
1290 trx_context.max_transaction_time_subjective = max_transaction_time;
1294 trace = trx_context.
trace;
1296 auto handle_exception = [&](
const auto& e)
1301 trace->except_ptr = std::current_exception();
1305 dm_logger->on_fail_deferred();
1313 flat_set<account_name> actors;
1314 for(
const auto& act : trx->packed_trx()->get_transaction().actions ) {
1315 for(
const auto& auth : act.authorization ) {
1316 actors.insert( auth.actor );
1335 trace->account_ram_delta =
account_delta( gtrx.payer, trx_removal_ram_delta );
1347 }
catch(
const disallowed_transaction_extensions_bad_block_exception& ) {
1349 }
catch(
const protocol_feature_bad_block_exception& ) {
1351 }
catch (
const std::bad_alloc& ) {
1353 }
catch (
const boost::interprocess::bad_alloc& ) {
1356 handle_exception(e);
1357 }
catch (
const std::exception& e) {
1359 handle_exception(wrapper);
1369 auto error_trace =
apply_onerror( gtrx, block_deadline, max_transaction_time, trx_context.pseudo_start,
1370 cpu_time_to_bill_us, billed_cpu_time_us, explicit_billed_cpu_time,
1372 error_trace->failed_dtrx_trace = trace;
1373 trace = error_trace;
1374 if( !trace->except_ptr ) {
1375 trace->account_ram_delta =
account_delta( gtrx.payer, trx_removal_ram_delta );
1388 bool subjective =
false;
1395 if ( !subjective ) {
1401 int64_t account_cpu_limit = 0;
1405 std::min(
static_cast<int64_t>(cpu_time_to_bill_us), account_cpu_limit ),
1406 trx_context.initial_objective_duration_limit.
count() ) );
1407 SYS_ASSERT( !explicit_billed_cpu_time || (cpu_time_to_bill_us == limited_cpu_time_to_bill_us),
1408 transaction_exception,
"cpu to bill ${cpu} != limited ${limit}", (
"cpu", cpu_time_to_bill_us)(
"limit", limited_cpu_time_to_bill_us) );
1409 cpu_time_to_bill_us = limited_cpu_time_to_bill_us;
1416 trace->account_ram_delta =
account_delta( gtrx.payer, trx_removal_ram_delta );
1436 template<
typename T>
1439 uint64_t net_usage_words = net_usage / 8;
1441 auto& receipts = std::get<building_block>(
pending->_block_stage)._pending_trx_receipts;
1442 receipts.emplace_back( trx );
1444 r.cpu_usage_us = cpu_usage_us;
1445 r.net_usage_words = net_usage_words;
1459 bool explicit_billed_cpu_time,
1460 int64_t subjective_cpu_bill_us )
1470 if( !explicit_billed_cpu_time ) {
1473 if( start.time_since_epoch() < already_consumed_time ) {
1476 start -= already_consumed_time;
1487 trx_context.max_transaction_time_subjective = max_transaction_time;
1491 trace = trx_context.
trace;
1493 auto handle_exception =[&](
const auto& e)
1497 trace->except_ptr = std::current_exception();
1502 if( trx->implicit ) {
1507 trx->packed_trx()->get_prunable_size() );
1515 trx->recovered_keys(),
1518 [&trx_context](){ trx_context.checktime(); },
1528 if (!trx->implicit) {
1534 std::get<building_block>(
pending->_block_stage)._pending_trx_metas.emplace_back(trx);
1539 r.net_usage_words = trace->net_usage / 8;
1547 if (!trx->read_only) {
1548 if (!trx->accepted) {
1549 trx->accepted =
true;
1567 }
catch(
const disallowed_transaction_extensions_bad_block_exception& ) {
1569 }
catch(
const protocol_feature_bad_block_exception& ) {
1571 }
catch (
const std::bad_alloc& ) {
1573 }
catch (
const boost::interprocess::bad_alloc& ) {
1576 handle_exception(e);
1577 }
catch (
const std::exception& e) {
1579 handle_exception(wrapper);
1582 if (!trx->read_only) {
1596 const std::optional<block_id_type>& producer_block_id,
1605 dm_logger->on_start_block(
head->block_num + 1);
1609 protocol_features.popped_blocks_to( head_block_num );
1615 (
"db.revision()",
db.
revision())(
"controller_head_block",
head->block_num)(
"fork_db_head_block",
fork_db.
head()->block_num) );
1623 pending->_producer_block_id = producer_block_id;
1625 auto& bb = std::get<building_block>(
pending->_block_stage);
1626 const auto& pbhs = bb._pending_block_header_state;
1634 bool handled_all_preactivated_features = (num_preactivated_protocol_features == 0);
1636 if( new_protocol_feature_activations.size() > 0 ) {
1637 flat_map<digest_type, bool> activated_protocol_features;
1638 activated_protocol_features.reserve( std::max( num_preactivated_protocol_features,
1639 new_protocol_feature_activations.size() ) );
1640 for(
const auto& feature_digest : pso.preactivated_protocol_features ) {
1641 activated_protocol_features.emplace( feature_digest,
false );
1644 size_t num_preactivated_features_that_have_activated = 0;
1647 for(
const auto& feature_digest : new_protocol_feature_activations ) {
1648 const auto&
f = pfs.get_protocol_feature( feature_digest );
1650 auto res = activated_protocol_features.emplace( feature_digest,
true );
1653 SYS_ASSERT( !
f.preactivation_required, protocol_feature_exception,
1654 "attempted to activate protocol feature without prior required preactivation: ${digest}",
1655 (
"digest", feature_digest)
1659 "attempted duplicate activation within a single block: ${digest}",
1660 (
"digest", feature_digest)
1663 res.first->second =
true;
1664 ++num_preactivated_features_that_have_activated;
1667 if(
f.builtin_feature ) {
1673 ++bb._num_new_protocol_features_that_have_activated;
1676 if( num_preactivated_features_that_have_activated == num_preactivated_protocol_features ) {
1677 handled_all_preactivated_features =
true;
1682 "There are pre-activated protocol features that were not activated at the start of this block"
1685 if( new_protocol_feature_activations.size() > 0 ) {
1687 ps.preactivated_protocol_features.clear();
1689 ps.activated_protocol_features.reserve( ps.activated_protocol_features.size()
1690 + new_protocol_feature_activations.size() );
1691 for(
const auto& feature_digest : new_protocol_feature_activations ) {
1692 ps.activated_protocol_features.emplace_back( feature_digest, pbhs.block_num );
1699 if( gpo.proposed_schedule_block_num &&
1700 ( *gpo.proposed_schedule_block_num <= pbhs.dpos_irreversible_blocknum ) &&
1701 pbhs.prev_pending_schedule.schedule.producers.size() == 0
1706 ilog(
"promoting proposed schedule (set in block ${proposed_num}) to pending; current block: ${n} lib: ${lib} schedule: ${schedule} ",
1707 (
"proposed_num", *gpo.proposed_schedule_block_num)(
"n", pbhs.block_num)
1708 (
"lib", pbhs.dpos_irreversible_blocknum)
1712 SYS_ASSERT( gpo.proposed_schedule.version == pbhs.active_schedule_version + 1,
1713 producer_schedule_exception,
"wrong producer schedule version specified" );
1717 gp.proposed_schedule_block_num = std::optional<block_num_type>();
1718 gp.proposed_schedule.version=0;
1719 gp.proposed_schedule.producers.clear();
1733 if( trace->except ) {
1734 wlog(
"onblock ${block_num} is REJECTING: ${entire_trace}",(
"block_num",
head->block_num + 1)(
"entire_trace", trace));
1736 }
catch(
const std::bad_alloc& e ) {
1737 elog(
"on block transaction failed due to a std::bad_alloc" );
1739 }
catch(
const boost::interprocess::bad_alloc& e ) {
1740 elog(
"on block transaction failed due to a bad allocation" );
1743 wlog(
"on block transaction failed, but shouldn't impact block generation, system contract needs update" );
1744 edump((e.to_detail_string()));
1745 }
catch(
const std::exception& e ) {
1746 wlog(
"on block transaction failed due to unexpected exception" );
1749 elog(
"on block transaction failed due to unknown exception" );
1756 guard_pending.cancel();
1766 auto& pbhs =
pending->get_pending_block_header_state();
1773 { CPU_TARGET,
chain_config.
max_block_cpu_usage, config::block_cpu_usage_average_window_ms / config::block_interval_ms, config::maximum_elastic_resource_multiplier, {99, 100}, {1000, 999}},
1778 auto& bb = std::get<building_block>(
pending->_block_stage);
1781 ilog(
"s_header present in finalize block, adding to block header: ${s}", (
"s", bb._s_header->to_string()));
1785 auto block_ptr = std::make_shared<signed_block>( pbhs.make_block_header(
1786 bb._transaction_mroot ? *bb._transaction_mroot :
calculate_trx_merkle( bb._pending_trx_receipts ),
1787 merkle( std::move( std::get<building_block>(
pending->_block_stage)._action_receipt_digests ) ),
1788 bb._new_pending_producer_schedule,
1789 std::move( bb._new_protocol_feature_activations ),
1794 block_ptr->transactions = std::move( bb._pending_trx_receipts );
1796 auto id = block_ptr->calculate_id();
1817 std::move( bb._pending_block_header_state ),
1818 std::move( bb._pending_trx_metas ),
1819 std::move( block_ptr ),
1820 std::move( bb._new_pending_producer_schedule )
1834 "cannot call commit_block until pending block is completed" );
1836 auto bsp = std::get<completed_block>(
pending->_block_stage)._block_state;
1838 if( add_to_fork_db ) {
1847 dm_logger->on_accepted_block(bsp);
1852 if( add_to_fork_db ) {
1857 reset_pending_on_exit.cancel();
1876 const flat_set<digest_type>& currently_activated_protocol_features,
1881 for(
auto itr = new_protocol_features.begin(); itr != new_protocol_features.end(); ++itr ) {
1882 const auto&
f = *itr;
1884 auto status = pfs.is_recognized(
f, timestamp );
1888 "protocol feature with digest '${digest}' is unrecognized", (
"digest",
f) );
1892 "protocol feature with digest '${digest}' is disabled", (
"digest",
f) );
1896 "${timestamp} is too early for the earliest allowed activation time of the protocol feature with digest '${digest}'", (
"digest",
f)(
"timestamp", timestamp) );
1901 SYS_THROW( protocol_feature_exception,
"unexpected recognized_t status" );
1905 SYS_ASSERT( currently_activated_protocol_features.find(
f ) == currently_activated_protocol_features.end(),
1906 protocol_feature_exception,
1907 "protocol feature with digest '${digest}' has already been activated",
1911 auto dependency_checker = [¤tly_activated_protocol_features, &new_protocol_features, &itr]
1914 if( currently_activated_protocol_features.find(
f ) != currently_activated_protocol_features.end() )
1917 return (std::find( new_protocol_features.begin(), itr,
f ) != itr);
1920 SYS_ASSERT( pfs.validate_dependencies(
f, dependency_checker ), protocol_feature_exception,
1921 "not all dependencies of protocol feature with digest '${digest}' have been activated",
1929#define SYS_REPORT(DESC,A,B) \
1931 elog("${desc}: ${bv} != ${abv}", ("desc", DESC)("bv", A)("abv", B)); \
1952 const auto& new_protocol_feature_activations = bsp->get_new_protocol_feature_activations();
1954 auto producer_block_id = bsp->id;
1957 const bool existing_trxs_metas = !bsp->trxs_metas().empty();
1958 const bool pub_keys_recovered = bsp->is_pub_keys_recovered();
1960 std::vector<std::tuple<transaction_metadata_ptr, recover_keys_future>> trx_metas;
1961 bool use_bsp_cached =
false;
1962 if( pub_keys_recovered || (skip_auth_checks && existing_trxs_metas) ) {
1963 use_bsp_cached =
true;
1965 trx_metas.reserve( b->transactions.size() );
1966 for(
const auto& receipt : b->transactions ) {
1967 if( std::holds_alternative<packed_transaction>(receipt.trx)) {
1968 const auto& pt = std::get<packed_transaction>(receipt.trx);
1970 if( trx_meta_ptr && *trx_meta_ptr->packed_trx() != pt ) trx_meta_ptr =
nullptr;
1971 if( trx_meta_ptr && ( skip_auth_checks || !trx_meta_ptr->recovered_keys().empty() ) ) {
1973 }
else if( skip_auth_checks ) {
1975 trx_metas.emplace_back(
1990 size_t packed_idx = 0;
1991 for(
const auto& receipt : b->transactions ) {
1992 const auto& trx_receipts = std::get<building_block>(
pending->_block_stage)._pending_trx_receipts;
1993 auto num_pending_receipts = trx_receipts.size();
1994 if( std::holds_alternative<packed_transaction>(receipt.trx) ) {
1995 const auto& trx_meta = ( use_bsp_cached ? bsp->trxs_metas().at( packed_idx )
1996 : ( !!std::get<0>( trx_metas.at( packed_idx ) ) ?
1997 std::get<0>( trx_metas.at( packed_idx ) )
1998 : std::get<1>( trx_metas.at( packed_idx ) ).get() ) );
2001 }
else if( std::holds_alternative<transaction_id_type>(receipt.trx) ) {
2007 bool transaction_failed = trace && trace->except;
2009 if( transaction_failed && !transaction_can_fail) {
2011 throw *trace->except;
2016 (
"bn", b->block_num())(
"id", producer_block_id)(
"e", receipt)
2018 SYS_ASSERT( trx_receipts.size() == num_pending_receipts + 1,
2020 (
"bn", b->block_num())(
"id", producer_block_id)(
"e", receipt)
2029 std::get<building_block>(
pending->_block_stage)._transaction_mroot = b->transaction_mroot;
2032 auto s_header_it = std::find_if(b->header_extensions.begin(), b->header_extensions.end(),
2033 [](
const auto& ext) { return ext.first == s_root_extension::extension_id(); });
2034 if (s_header_it != b->header_extensions.end()) {
2035 ilog(
"Found s_root_extension in header_extensions, attempting to extract...");
2037 ilog(
"Extracted s_header: ${s_header}", (
"s_header", extracted_s_header.
to_string()));
2043 auto& ab = std::get<assembled_block>(
pending->_block_stage);
2047 if( producer_block_id != ab._id ) {
2048 elog(
"Validation block id does not match producer block id" );
2052 (
"producer_block_id", producer_block_id)(
"validator_block_id", ab._id) );
2055 if( !use_bsp_cached ) {
2056 bsp->set_trxs_metas( std::move( ab._trx_metas ), !skip_auth_checks );
2063 }
catch (
const std::bad_alloc& ) {
2065 }
catch (
const boost::interprocess::bad_alloc& ) {
2071 }
catch (
const std::exception& e ) {
2083 "invalid block transaction merkle root ${b} != ${c}", (
"b", b->transaction_mroot)(
"c", trx_mroot) );
2085 const bool skip_validate_signee =
false;
2086 auto bsp = std::make_shared<block_state>(
2091 const flat_set<digest_type>& cur_features,
2093 { check_protocol_features( timestamp, cur_features, new_features ); },
2094 skip_validate_signee
2098 "provided id ${id} does not match block id ${bid}", (
"id",
id)(
"bid", bsp->id) );
2107 auto existing = control->fork_db.get_block( id );
2108 SYS_ASSERT( !existing, fork_database_exception,
"we already know about this block: ${id}", (
"id", id) );
2110 auto prev = control->fork_db.get_block_header( b->previous );
2111 SYS_ASSERT( prev, unlinkable_block_exception,
2112 "unlinkable block ${id}", (
"id", id)(
"previous", b->previous) );
2114 return control->create_block_state_i( id, b, *prev );
2128 if( !prev )
return {};
2145 const auto& b = bsp->block;
2191 auto bsp = std::make_shared<block_state>(
2196 const flat_set<digest_type>& cur_features,
2198 { check_protocol_features( timestamp, cur_features, new_features ); },
2199 skip_validate_signee
2222 "invariant failure: cannot replay reversible blocks while in irreversible mode" );
2232 bool head_changed =
true;
2233 if( new_head->header.previous ==
head->id ) {
2238 }
catch (
const std::exception& e ) {
2242 }
else if( new_head->id !=
head->id ) {
2243 auto old_head =
head;
2244 ilog(
"switching forks from ${current_head_id} (block number ${current_head_num}) to ${new_head_id} (block number ${new_head_num})",
2245 (
"current_head_id",
head->id)(
"current_head_num",
head->block_num)(
"new_head_id", new_head->id)(
"new_head_num", new_head->block_num) );
2248 dm_logger->on_switch_forks(
head->id, new_head->id);
2253 if( branches.second.size() > 0 ) {
2254 for(
auto itr = branches.second.begin(); itr != branches.second.end(); ++itr ) {
2258 "loss of sync between fork_db and chainbase during fork switch" );
2260 if( forked_branch_cb ) forked_branch_cb( branches.second );
2263 for(
auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr ) {
2264 auto except = std::exception_ptr{};
2270 }
catch (
const std::bad_alloc& ) {
2272 }
catch (
const boost::interprocess::bad_alloc& ) {
2276 except = std::current_exception();
2277 }
catch (
const std::exception& e) {
2278 elog(
"exception thrown while switching forks ${e}", (
"e", e.
what()));
2279 except = std::current_exception();
2289 auto applied_itr = ritr.base();
2290 for(
auto itr = applied_itr; itr != branches.first.end(); ++itr ) {
2294 "loss of sync between fork_db and chainbase during fork switch reversal" );
2297 for(
auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr ) {
2301 std::rethrow_exception(except);
2305 ilog(
"successfully switched fork to new head ${new_head_id}", (
"new_head_id", new_head->id));
2307 head_changed =
false;
2318 applied_trxs =
pending->extract_trx_metas();
2322 return applied_trxs;
2327 trx_digests.reserve( trxs.size() );
2328 for(
const auto&
a : trxs )
2329 trx_digests.emplace_back(
a.digest() );
2331 return merkle( move(trx_digests) );
2335 const auto&
producers =
pending->get_pending_block_header_state().active_schedule.producers;
2337 auto update_permission = [&](
auto& permission,
auto threshold ) {
2338 auto auth =
authority( threshold, {}, {});
2340 auth.accounts.push_back({{
p.producer_name, config::active_name}, 1});
2343 if(
static_cast<authority>(permission.auth) != auth ) {
2344 db.
modify(permission, [&](
auto& po ) {
2351 auto calculate_threshold = [=](
uint32_t numerator,
uint32_t denominator ) {
2352 return ( (num_producers * numerator) / denominator ) + 1;
2356 config::active_name}),
2357 calculate_threshold( 2, 3 ) );
2360 config::majority_producers_permission_name}),
2361 calculate_threshold( 1, 2 ) );
2364 config::minority_producers_permission_name}),
2365 calculate_threshold( 1, 3 ) );
2372 auto sid = block_num & 0xffff;
2382 const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
2384 const auto total = dedupe_index.size();
2386 while( (!dedupe_index.empty()) && ( now >
fc::time_point(dedupe_index.begin()->expiration) ) ) {
2387 transaction_idx.remove(*dedupe_index.begin());
2393 dlog(
"removed ${n} expired transactions of the ${t} input dedup list, pending block time ${pt}",
2394 (
"n", num_removed)(
"t", total)(
"pt", now));
2408 if( actors.size() == 0 )
return;
2413 bool is_subset =
true;
2416 if (*actors.cbegin() >= *whitelist.cbegin() && *actors.crbegin() <= *whitelist.crbegin() ) {
2417 auto lower_bound = whitelist.cbegin();
2418 for (
const auto&
actor: actors) {
2419 lower_bound = std::lower_bound(lower_bound, whitelist.cend(),
actor);
2422 if (lower_bound == whitelist.cend() || *lower_bound !=
actor ) {
2429 lower_bound = std::next(lower_bound);
2436 static auto generate_missing_actors = [](
const flat_set<account_name>& actors,
const flat_set<account_name>& whitelist) ->
vector<account_name> {
2438 excluded.reserve( actors.size() );
2439 set_difference( actors.begin(), actors.end(),
2440 whitelist.begin(), whitelist.end(),
2441 std::back_inserter(excluded) );
2445 SYS_ASSERT( is_subset, actor_whitelist_exception,
2446 "authorizing actor(s) in transaction are not on the actor whitelist: ${actors}",
2447 (
"actors", generate_missing_actors(actors, whitelist))
2452 bool intersects =
false;
2455 if( *actors.cbegin() <= *blacklist.crbegin() && *actors.crbegin() >= *blacklist.cbegin() ) {
2456 auto lower_bound = blacklist.cbegin();
2457 for (
const auto&
actor: actors) {
2458 lower_bound = std::lower_bound(lower_bound, blacklist.cend(),
actor);
2462 if (lower_bound == blacklist.cend()) {
2467 if (*lower_bound ==
actor) {
2475 static auto generate_blacklisted_actors = [](
const flat_set<account_name>& actors,
const flat_set<account_name>&
blacklist) ->
vector<account_name> {
2477 blacklisted.reserve( actors.size() );
2478 set_intersection( actors.begin(), actors.end(),
2479 blacklist.begin(), blacklist.end(),
2480 std::back_inserter(blacklisted)
2485 SYS_ASSERT( !intersects, actor_blacklist_exception,
2486 "authorizing actor(s) in transaction are on the actor blacklist: ${actors}",
2487 (
"actors", generate_blacklisted_actors(actors, blacklist))
2495 contract_whitelist_exception,
2496 "account '${code}' is not on the contract whitelist", (
"code", code)
2500 contract_blacklist_exception,
2501 "account '${code}' is on the contract blacklist", (
"code", code)
2509 action_blacklist_exception,
2510 "action '${code}::${action}' is on the action blacklist",
2511 (
"code", code)(
"action",
action)
2519 key_blacklist_exception,
2520 "public key '${key}' is on the key blacklist",
2549 on_block_act.
account = config::system_account_name;
2550 on_block_act.
name =
"onblock"_n;
2555 trx.
actions.emplace_back(std::move(on_block_act));
2566 dm_logger->on_onblock(trx);
2584 return my->resource_limits;
2588 return my->resource_limits;
2593 return my->authorization;
2597 return my->authorization;
2602 return my->protocol_features;
2607 return my->conf.max_nonprivileged_inline_action_size;
2635 my->startup(shutdown, check_shutdown, snapshot);
2639 my->startup(shutdown, check_shutdown, genesis);
2643 my->startup(shutdown, check_shutdown);
2653 const auto& pfs = my->protocol_features.get_protocol_feature_set();
2656 auto status = pfs.is_recognized( feature_digest, cur_time );
2660 SYS_THROW( subjective_block_production_exception,
2661 "protocol feature with digest '${digest}' is unrecognized", (
"digest", feature_digest) );
2663 SYS_THROW( protocol_feature_bad_block_exception,
2664 "protocol feature with digest '${digest}' is unrecognized", (
"digest", feature_digest) );
2669 SYS_THROW( subjective_block_production_exception,
2670 "protocol feature with digest '${digest}' is disabled", (
"digest", feature_digest) );
2672 SYS_THROW( protocol_feature_bad_block_exception,
2673 "protocol feature with digest '${digest}' is disabled", (
"digest", feature_digest) );
2678 SYS_THROW( subjective_block_production_exception,
2679 "${timestamp} is too early for the earliest allowed activation time of the protocol feature with digest '${digest}'", (
"digest", feature_digest)(
"timestamp", cur_time) );
2681 SYS_THROW( protocol_feature_bad_block_exception,
2682 "${timestamp} is too early for the earliest allowed activation time of the protocol feature with digest '${digest}'", (
"digest", feature_digest)(
"timestamp", cur_time) );
2689 SYS_THROW( subjective_block_production_exception,
"unexpected recognized_t status" );
2691 SYS_THROW( protocol_feature_bad_block_exception,
"unexpected recognized_t status" );
2718 protocol_feature_exception,
2719 "protocol feature with digest '${digest}' is already activated",
2720 (
"digest", feature_digest)
2725 SYS_ASSERT( std::find( pso.preactivated_protocol_features.begin(),
2726 pso.preactivated_protocol_features.end(),
2728 ) == pso.preactivated_protocol_features.end(),
2729 protocol_feature_exception,
2730 "protocol feature with digest '${digest}' is already pre-activated",
2731 (
"digest", feature_digest)
2734 auto dependency_checker = [&](
const digest_type&
d ) ->
bool
2738 return ( std::find( pso.preactivated_protocol_features.begin(),
2739 pso.preactivated_protocol_features.end(),
2740 d ) != pso.preactivated_protocol_features.end() );
2743 SYS_ASSERT( pfs.validate_dependencies( feature_digest, dependency_checker ),
2744 protocol_feature_exception,
2745 "not all dependencies of protocol feature with digest '${digest}' have been activated or pre-activated",
2746 (
"digest", feature_digest)
2750 const auto feature = pfs.get_protocol_feature(feature_digest);
2752 dm_logger->on_preactivate_feature(feature);
2755 my->db.modify( pso, [&](
auto& ps ) {
2756 ps.preactivated_protocol_features.push_back( feature_digest );
2763 if( pso.preactivated_protocol_features.size() == 0 )
return {};
2767 for(
const auto&
f : pso.preactivated_protocol_features ) {
2768 preactivated_protocol_features.emplace_back(
f );
2771 return preactivated_protocol_features;
2775 my->check_protocol_features( my->head->header.timestamp,
2776 my->head->activated_protocol_features->protocol_features,
2777 features_to_activate );
2789 if( pso.preactivated_protocol_features.size() > 0 ) {
2790 for(
const auto&
f : pso.preactivated_protocol_features ) {
2791 new_protocol_feature_activations.emplace_back(
f );
2795 if( new_protocol_feature_activations.size() > 0 ) {
2799 my->start_block( when, confirm_block_count, new_protocol_feature_activations,
2810 if( new_protocol_feature_activations.size() > 0 ) {
2814 my->start_block( when, confirm_block_count, new_protocol_feature_activations,
2821 my->finalize_block();
2823 auto& ab = std::get<assembled_block>(my->pending->_block_stage);
2825 auto bsp = std::make_shared<block_state>(
2826 std::move( ab._pending_block_header_state ),
2827 std::move( ab._unsigned_block ),
2828 std::move( ab._trx_metas ),
2829 my->protocol_features.get_protocol_feature_set(),
2831 const flat_set<digest_type>& cur_features,
2844 my->commit_block(
true);
2848 return my->abort_block();
2852 return my->thread_pool.get_executor();
2856 return my->create_block_state_future(
id, b );
2860 return my->create_block_state(
id, b );
2868 my->push_block( bsp, forked_branch_cb, trx_lookup );
2873 uint32_t billed_cpu_time_us,
bool explicit_billed_cpu_time,
2874 int64_t subjective_cpu_bill_us ) {
2877 SYS_ASSERT( trx && !trx->implicit && !trx->scheduled, transaction_type_exception,
"Implicit/Scheduled transaction not allowed" );
2878 return my->push_transaction(trx, block_deadline, max_transaction_time, billed_cpu_time_us, explicit_billed_cpu_time, subjective_cpu_bill_us );
2883 uint32_t billed_cpu_time_us,
bool explicit_billed_cpu_time )
2887 return my->push_scheduled_transaction( trxid, block_deadline, max_transaction_time, billed_cpu_time_us, explicit_billed_cpu_time );
2891 return my->conf.actor_whitelist;
2894 return my->conf.actor_blacklist;
2897 return my->conf.contract_whitelist;
2900 return my->conf.contract_blacklist;
2903 return my->conf.action_blacklist;
2906 return my->conf.key_blacklist;
2910 my->conf.actor_whitelist = new_actor_whitelist;
2913 my->conf.actor_blacklist = new_actor_blacklist;
2916 my->conf.contract_whitelist = new_contract_whitelist;
2919 my->conf.contract_blacklist = new_contract_blacklist;
2922 for (
auto& act: new_action_blacklist) {
2923 SYS_ASSERT(act.first !=
account_name(), name_type_exception,
"Action blacklist - contract name should not be empty");
2924 SYS_ASSERT(act.second !=
action_name(), action_type_exception,
"Action blacklist - action name should not be empty");
2926 my->conf.action_blacklist = new_action_blacklist;
2929 my->conf.key_blacklist = new_key_blacklist;
2937 auto& bb = std::get<building_block>(my->pending->_block_stage);
2939 auto& check_s_header = std::get<building_block>(my->pending->_block_stage)._s_header;
2940 if (check_s_header){
2941 ilog(
"Pending building block s_header set: ${s_header}\n\t\tand matches what was passed: ${match}",
2942 (
"s_header", check_s_header->to_string())(
"match", check_s_header ==
s_header));
2945 ilog(
"Pending building block s_header NOT SET");
2950 return my->head->block_num;
2953 return my->head->header.timestamp;
2956 return my->head->id;
2959 return my->head->header.producer;
2962 return my->head->header;
2969 return my->fork_db.head()->block_num;
2973 return my->fork_db.head()->id;
2977 return my->fork_db.head()->header.timestamp;
2981 return my->fork_db.head()->header.producer;
2985 return my->fork_db.pending_head()->block_num;
2989 return my->fork_db.pending_head()->id;
2993 return my->fork_db.pending_head()->header.timestamp;
2997 return my->fork_db.pending_head()->header.producer;
3003 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3004 return std::get<completed_block>(my->pending->_block_stage)._block_state->header.timestamp;
3006 return my->pending->get_pending_block_header_state().timestamp;
3012 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3013 return std::get<completed_block>(my->pending->_block_stage)._block_state->header.block_num();
3015 return my->pending->get_pending_block_header_state().block_num;
3021 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3022 return std::get<completed_block>(my->pending->_block_stage)._block_state->header.producer;
3024 return my->pending->get_pending_block_header_state().producer;
3030 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3031 return std::get<completed_block>(my->pending->_block_stage)._block_state->valid_block_signing_authority;
3033 return my->pending->get_pending_block_header_state().valid_block_signing_authority;
3038 return my->pending->_producer_block_id;
3043 return my->pending->get_trx_receipts();
3047 return my->fork_db.root()->block_num;
3051 return my->fork_db.root()->id;
3055 return my->fork_db.root()->header.timestamp.to_time_point();
3067 auto state = my->fork_db.get_block(
id);
3070 if( bptr && bptr->calculate_id() ==
id )
return bptr;
3077 return blk_state->block;
3080 return my->blog.read_block_by_num(block_num);
3084 auto state = my->fork_db.get_block(
id);
3090 return my->fork_db.search_on_branch( my->fork_db.pending_head()->id, block_num );
3092 return my->fork_db.search_on_branch( my->fork_db.head()->id, block_num );
3100 return tapos_block_summary.block_id;
3102 const auto& blog_head = my->blog.head();
3104 bool find_in_blog = (blog_head && block_num <= blog_head->block_num());
3106 if( !find_in_blog ) {
3108 if( bsp )
return bsp->id;
3111 auto id = my->blog.read_block_id_by_num(block_num);
3114 "Could not find block: ${block}", (
"block", block_num) );
3120 return my->calculate_integrity_hash();
3125 return my->add_to_snapshot(snapshot);
3136 if( gpo.proposed_schedule_block_num ) {
3137 if( *gpo.proposed_schedule_block_num != cur_block_num )
3141 gpo.proposed_schedule.producers.begin(), gpo.proposed_schedule.producers.end() ) )
3148 decltype(end) begin;
3152 if( pending_sch.producers.size() == 0 ) {
3154 begin = active_sch.producers.begin();
3155 end = active_sch.producers.end();
3156 sch.
version = active_sch.version + 1;
3158 begin = pending_sch.producers.begin();
3159 end = pending_sch.producers.end();
3160 sch.
version = pending_sch.version + 1;
3170 ilog(
"proposed producer schedule with version ${v}", (
"v", version) );
3172 my->db.modify( gpo, [&](
auto& gp ) {
3173 gp.proposed_schedule_block_num = cur_block_num;
3174 gp.proposed_schedule = sch.
to_shared(gp.proposed_schedule.producers.get_allocator());
3180 if( !(my->pending) )
3181 return my->head->active_schedule;
3183 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3184 return std::get<completed_block>(my->pending->_block_stage)._block_state->active_schedule;
3186 return my->pending->get_pending_block_header_state().active_schedule;
3190 if( !(my->pending) )
3191 return my->head->pending_schedule.schedule;
3193 if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
3194 return std::get<completed_block>(my->pending->_block_stage)._block_state->pending_schedule.schedule;
3196 if( std::holds_alternative<assembled_block>(my->pending->_block_stage) ) {
3197 const auto& new_prods_cache = std::get<assembled_block>(my->pending->_block_stage)._new_producer_authority_cache;
3198 if( new_prods_cache ) {
3199 return *new_prods_cache;
3203 const auto& bb = std::get<building_block>(my->pending->_block_stage);
3205 if( bb._new_pending_producer_schedule )
3206 return *bb._new_pending_producer_schedule;
3208 return bb._pending_block_header_state.prev_pending_schedule.schedule;
3213 if( !gpo.proposed_schedule_block_num )
3214 return std::optional<producer_authority_schedule>();
3220 if (!my->pending || my->in_trx_requiring_checks) {
3224 const auto pb_status = my->pending->_block_status;
3227 const bool consider_skipping_on_replay =
3234 return consider_skipping_on_replay || consider_skipping_on_validate;
3248 return consider_skipping
3249 && !my->conf.disable_replay_opts
3250 && !my->in_trx_requiring_checks;
3266 return my->conf.contracts_console;
3270 return my->conf.profile_accounts.find(account) != my->conf.profile_accounts.end();
3274 return my->chain_id;
3278 return my->read_mode;
3282 return my->conf.block_validation_mode;
3286 return my->conf.terminate_at_block;
3291 auto native_handler_scope = my->apply_handlers.find( receiver );
3292 if( native_handler_scope != my->apply_handlers.end() ) {
3293 auto handler = native_handler_scope->second.find( make_pair( scope, act ) );
3294 if( handler != native_handler_scope->second.end() )
3295 return &handler->second;
3309 return my->sender_avoids_whitelist_blacklist_enforcement( sender );
3313 my->check_actor_list( actors );
3317 my->check_contract_list( code );
3321 my->check_action_list( code,
action );
3325 my->check_key_list( key );
3329 return my->pending.has_value();
3333 if( !my->pending )
return false;
3339 return my->conf.disable_all_subjective_mitigations || !
is_producing_block() || my->conf.allow_ram_billing_in_notify;
3343 return my->conf.maximum_variable_signature_length;
3350 expired_tx_exception,
3351 "transaction has expired, "
3352 "expiration is ${trx.expiration} and pending block time is ${pending_block_time}",
3355 tx_exp_too_far_exception,
3356 "Transaction expiration is too far in the future relative to the reference time of ${reference_time}, "
3357 "expiration is ${trx.expiration} and the maximum transaction lifetime is ${max_til_exp} seconds",
3359 (
"max_til_exp",chain_configuration.max_transaction_lifetime) );
3367 "Transaction's reference block did not match. Is this transaction from a different fork?",
3368 (
"tapos_summary", tapos_block_summary));
3373 const auto guard = my->conf.state_guard_size;
3374 SYS_ASSERT(free >= guard, database_guard_exception,
"database free: ${f}, guard size: ${g}", (
"f", free)(
"g",guard));
3379 return my->pending->is_protocol_feature_activated( feature_digest );
3381 const auto& activated_features = my->head->activated_protocol_features->protocol_features;
3382 return (activated_features.find( feature_digest ) != activated_features.end());
3389 ++current_block_num;
3392 return my->protocol_features.is_builtin_activated(
f, current_block_num );
3400 my->subjective_cpu_leeway = leeway;
3404 return my->subjective_cpu_leeway;
3408 SYS_ASSERT( 0 < limit && limit <= chain::config::maximum_elastic_resource_multiplier,
3410 "Invalid limit (${limit}) passed into set_greylist_limit. "
3411 "Must be between 1 and ${max}.",
3412 (
"limit", limit)(
"max", chain::config::maximum_elastic_resource_multiplier)
3414 my->conf.greylist_limit = limit;
3418 return my->conf.greylist_limit;
3422 my->conf.resource_greylist.insert(
name);
3426 my->conf.resource_greylist.erase(
name);
3430 return my->conf.resource_greylist.find(
name) != my->conf.resource_greylist.end();
3434 return my->conf.resource_greylist;
3442 rco.ram_correction += ram_bytes;
3447 rco.ram_correction = ram_bytes;
3452 dm_logger->on_add_ram_correction(*ptr, ram_bytes);
3457 return my->conf.disable_all_subjective_mitigations;
3461 return my->get_deep_mind_logger();
3465 SYS_ASSERT(
logger !=
nullptr, misc_exception,
"Invalid logger passed into enable_deep_mind, must be set" );
3466 my->deep_mind_logger =
logger;
3470 return my->earliest_available_block_num();
3472#if defined(SYSIO_SYS_VM_RUNTIME_ENABLED) || defined(SYSIO_SYS_VM_JIT_RUNTIME_ENABLED)
3474 return my->wasm_alloc;
3479 const chain_exception* e_ptr =
dynamic_cast<const chain_exception*
>( &e );
3481 if( e_ptr ==
nullptr )
return {};
3485 return e_ptr->error_code;
3491 section.read_row(header);
3498 return genesis->compute_chain_id();
3504 if (header.
version <= v4::maximum_version) {
3506 v4 global_properties;
3507 section.read_row(global_properties);
3508 chain_id = global_properties.chain_id;
3514 section.read_row(global_properties);
3515 chain_id = global_properties.
chain_id;
3534 }
catch(
const bad_database_version_exception& ) {
3543 ilog(
"Replace producer keys with ${k}", (
"k", key));
3544 mutable_db().
modify(
db().get<global_property_object>(), [&](
auto& gp ) {
3545 gp.proposed_schedule_block_num = {};
3546 gp.proposed_schedule.version = 0;
3547 gp.proposed_schedule.producers.clear();
3549 auto version = my->head->pending_schedule.schedule.version;
3550 my->head->pending_schedule = {};
3551 my->head->pending_schedule.schedule.version = version;
3552 for (
auto& prod: my->head->active_schedule.producers ) {
3553 ilog(
"${n}", (
"n", prod.producer_name));
3554 std::visit([&](
auto &auth) {
3567 mutable_db().
modify(*perm, [&](
auto&
p) {
3571 rlm.add_pending_ram_usage(account, new_size - old_size);
3572 rlm.verify_account_ram_usage(account);
3578void controller_impl::on_activation<builtin_protocol_feature_t::preactivate_feature>() {
3580 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"preactivate_feature" );
3581 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"is_feature_activated" );
3586void controller_impl::on_activation<builtin_protocol_feature_t::get_sender>() {
3588 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"get_sender" );
3593void controller_impl::on_activation<builtin_protocol_feature_t::replace_deferred>() {
3595 for(
auto itr = indx.begin(); itr != indx.end(); itr = indx.begin() ) {
3598 if( itr->ram_correction >
static_cast<uint64_t>(current_ram_usage) ) {
3599 ram_delta = -current_ram_usage;
3600 elog(
"account ${name} was to be reduced by ${adjust} bytes of RAM despite only using ${current} bytes of RAM",
3601 (
"name", itr->name)(
"adjust", itr->ram_correction)(
"current", current_ram_usage) );
3604 if (
auto dm_logger = get_deep_mind_logger()) {
3605 dm_logger->on_ram_trace(
RAM_EVENT_ID(
"${id}", (
"id", itr->id._id)),
"deferred_trx",
"correction",
"deferred_trx_ram_correction");
3614void controller_impl::on_activation<builtin_protocol_feature_t::webauthn_key>() {
3616 ps.num_supported_key_types = 3;
3621void controller_impl::on_activation<builtin_protocol_feature_t::em_key>() {
3623 ps.num_supported_key_types = 4;
3629void controller_impl::on_activation<builtin_protocol_feature_t::wtmsig_block_signatures>() {
3631 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"set_proposed_producers_ex" );
3636void controller_impl::on_activation<builtin_protocol_feature_t::action_return_value>() {
3638 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"set_action_return_value" );
3643void controller_impl::on_activation<builtin_protocol_feature_t::configurable_wasm_limits>() {
3645 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"set_wasm_parameters_packed" );
3646 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"get_wasm_parameters_packed" );
3651void controller_impl::on_activation<builtin_protocol_feature_t::blockchain_parameters>() {
3653 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"get_parameters_packed" );
3654 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"set_parameters_packed" );
3659void controller_impl::on_activation<builtin_protocol_feature_t::get_code_hash>() {
3661 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"get_code_hash" );
3666void controller_impl::on_activation<builtin_protocol_feature_t::get_block_num>() {
3668 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"get_block_num" );
3673void controller_impl::on_activation<builtin_protocol_feature_t::crypto_primitives>() {
3675 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"alt_bn128_add" );
3676 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"alt_bn128_mul" );
3677 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"alt_bn128_pair" );
3678 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"mod_exp" );
3679 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"blake2_f" );
3680 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"sha3" );
3681 add_intrinsic_to_whitelist( ps.whitelisted_intrinsics,
"k1_recover" );
constexpr uint64_t SYS_PERCENT(uint64_t value, uint32_t percentage)
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
void set_revision(uint64_t revision)
const generic_index< MultiIndexType > & get_index() const
pinnable_mapped_file::segment_manager * get_segment_manager()
void modify(const ObjectType &obj, Modifier &&m)
const ObjectType * find(CompatibleKey &&key) const
session start_undo_session(bool enabled)
void remove(const ObjectType &obj)
void commit(int64_t revision)
const ObjectType & create(Constructor &&con)
generic_index< MultiIndexType > & get_mutable_index()
const ObjectType & get(CompatibleKey &&key) const
Used to generate a useful error report when an exception is thrown.
std::string to_detail_string(log_level ll=log_level::all) const
const char * what() const noexcept override
constexpr int64_t count() const
static constexpr microseconds maximum()
wraps boost::filesystem::path to provide platform independent path manipulation.
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()
void add_to_snapshot(const snapshot_writer_ptr &snapshot) const
void initialize_database()
void read_from_snapshot(const snapshot_reader_ptr &snapshot)
void check_authorization(const vector< action > &actions, const flat_set< public_key_type > &provided_keys, const flat_set< permission_level > &provided_permissions=flat_set< permission_level >(), fc::microseconds provided_delay=fc::microseconds(0), const std::function< void()> &checktime=std::function< void()>(), bool allow_unused_keys=false, bool check_but_dont_fail=false, const flat_set< permission_level > &satisfied_authorizations=flat_set< permission_level >()) const
Check authorizations of a vector of actions with provided keys, permission levels,...
const permission_object & get_permission(const permission_level &level) const
const permission_object & create_permission(account_name account, permission_name name, permission_id_type parent, const authority &auth, time_point initial_creation_time=time_point())
const block_id_type & head_id() const
signed_block_ptr read_block_by_num(uint32_t block_num) const
uint32_t first_block_num() const
void append(const signed_block_ptr &b)
const signed_block_ptr & head() const
void reset(const genesis_state &gs, const signed_block_ptr &genesis_block)
tracks minimal information about past blocks to implement TaPOS
void set_greylist_limit(uint32_t limit)
block_state_ptr fetch_block_state_by_number(uint32_t block_num) const
signal< void(const transaction_metadata_ptr &)> accepted_transaction
void set_actor_whitelist(const flat_set< account_name > &)
const flat_set< account_name > & get_actor_blacklist() const
void check_action_list(account_name code, action_name action) const
signal< void(const block_state_ptr &)> accepted_block_header
bool is_protocol_feature_activated(const digest_type &feature_digest) const
const global_property_object & get_global_properties() const
const chainbase::database & db() const
bool is_producing_block() const
bool is_trusted_producer(const account_name &producer) const
validation_mode get_validation_mode() const
signed_block_ptr fetch_block_by_number(uint32_t block_num) const
const dynamic_global_property_object & get_dynamic_global_properties() const
account_name fork_db_pending_head_block_producer() const
block_id_type fork_db_pending_head_block_id() const
void set_actor_blacklist(const flat_set< account_name > &)
static std::optional< chain_id_type > extract_chain_id_from_db(const path &state_dir)
signal< void(const block_state_ptr &)> accepted_block
void add_to_ram_correction(account_name account, uint64_t ram_bytes)
signal< void(const block_state_ptr &)> irreversible_block
bool is_building_block() const
db_read_mode get_read_mode() const
static chain_id_type extract_chain_id(snapshot_reader &snapshot)
vector< transaction_metadata_ptr > abort_block()
account_name head_block_producer() const
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)
block_state_ptr create_block_state(const block_id_type &id, const signed_block_ptr &b) const
uint32_t head_block_num() const
void push_block(const block_state_ptr &bsp, const forked_branch_callback &cb, const trx_meta_cache_lookup &trx_lookup)
block_id_type head_block_id() const
void preactivate_feature(const digest_type &feature_digest)
std::optional< producer_authority_schedule > proposed_producers() const
void validate_expiration(const transaction &t) const
block_state_ptr head_block_state() const
void write_snapshot(const snapshot_writer_ptr &snapshot)
bool skip_auth_check() const
bool is_profiling(account_name name) const
uint32_t pending_block_num() const
const apply_handler * find_apply_handler(account_name contract, scope_name scope, action_name act) const
bool is_ram_billing_in_notify_allowed() const
authorization_manager & get_mutable_authorization_manager()
deep_mind_handler * get_deep_mind_logger() const
signal< void(const signed_block_ptr &)> pre_accepted_block
uint32_t last_irreversible_block_num() const
const producer_authority_schedule & pending_producers() const
void set_key_blacklist(const flat_set< public_key_type > &)
void set_s_header(const s_header &)
uint32_t fork_db_pending_head_block_num() const
uint32_t get_max_nonprivileged_inline_action_size() const
boost::asio::io_context & get_thread_pool()
block_id_type fork_db_head_block_id() const
const protocol_feature_manager & get_protocol_feature_manager() const
uint32_t configured_subjective_signature_length_limit() const
bool light_validation_allowed() const
void replace_account_keys(name account, name permission, const public_key_type &key)
account_name fork_db_head_block_producer() 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
void validate_db_available_size() const
signed_block_ptr fetch_block_by_id(block_id_type id) const
time_point fork_db_head_block_time() const
void enable_deep_mind(deep_mind_handler *logger)
time_point last_irreversible_block_time() const
wasm_interface & get_wasm_interface()
const flat_set< pair< account_name, action_name > > & get_action_blacklist() const
std::optional< block_id_type > pending_producer_block_id() const
@ incomplete
this is an incomplete block (either being produced by a producer or speculatively produced by a node)
@ irreversible
this block has already been applied before by this node and is considered irreversible
@ validated
this is a complete block signed by a valid producer and has been previously applied by this node and ...
@ complete
this is a complete block signed by a valid producer but is not yet irreversible nor has it yet been a...
uint32_t get_terminate_at_block() const
const authorization_manager & get_authorization_manager() const
void set_contract_blacklist(const flat_set< account_name > &)
block_state_ptr finalize_block(const signer_callback_type &signer_callback)
void validate_tapos(const transaction &t) const
block_id_type last_irreversible_block_id() const
const flat_set< account_name > & get_contract_blacklist() const
block_id_type get_block_id_for_num(uint32_t block_num) const
uint32_t get_greylist_limit() const
void remove_resource_greylist(const account_name &name)
bool is_resource_greylisted(const account_name &name) const
void check_key_list(const public_key_type &key) const
void check_actor_list(const flat_set< account_name > &actors) const
chain_id_type get_chain_id() const
bool is_builtin_activated(builtin_protocol_feature_t f) const
bool sender_avoids_whitelist_blacklist_enforcement(account_name sender) const
const flat_set< public_key_type > & get_key_blacklist() const
const flat_set< account_name > & get_resource_greylist() const
transaction_trace_ptr push_scheduled_transaction(const transaction_id_type &scheduled, fc::time_point block_deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time)
const account_object & get_account(account_name n) const
void set_contract_whitelist(const flat_set< account_name > &)
int64_t set_proposed_producers(vector< producer_authority > producers)
uint32_t earliest_available_block_num() const
time_point fork_db_pending_head_block_time() const
time_point pending_block_time() const
void validate_protocol_features(const vector< digest_type > &features_to_activate) const
signal< void(std::tuple< const transaction_trace_ptr &, const packed_transaction_ptr & >)> applied_transaction
vector< digest_type > get_preactivated_protocol_features() const
void set_subjective_cpu_leeway(fc::microseconds leeway)
bool skip_db_sessions() const
void replace_producer_keys(const public_key_type &key)
block_state_ptr fetch_block_state_by_id(block_id_type id) const
void add_resource_greylist(const account_name &name)
const block_header & head_block_header() const
bool is_known_unexpired_transaction(const transaction_id_type &id) const
std::future< block_state_ptr > create_block_state_future(const block_id_type &id, const signed_block_ptr &b)
const vector< transaction_receipt > & get_pending_trx_receipts() const
signal< void(uint32_t)> block_start
resource_limits_manager & get_mutable_resource_limits_manager()
const fork_database & fork_db() const
const producer_authority_schedule & active_producers() const
sha256 calculate_integrity_hash()
uint32_t fork_db_head_block_num() const
const flat_set< account_name > & get_actor_whitelist() const
static std::optional< uint64_t > convert_exception_to_error_code(const fc::exception &e)
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 > > &)
std::optional< fc::microseconds > get_subjective_cpu_leeway() const
bool all_subjective_mitigations_disabled() const
void startup(std::function< void()> shutdown, std::function< bool()> check_shutdown, const snapshot_reader_ptr &snapshot)
bool contracts_console() const
bool skip_trx_checks() const
controller(const config &cfg, const chain_id_type &chain_id)
void start_block(block_timestamp_type time=block_timestamp_type(), uint16_t confirm_block_count=0)
void check_contract_list(account_name code) const
Maintains global state information that frequently change.
manages light-weight state for all potential unconfirmed forks
block_state_ptr pending_head() const
block_state_ptr search_on_branch(const block_id_type &h, uint32_t block_num) const
branch_type fetch_branch(const block_id_type &h, uint32_t trim_after_block_num=std::numeric_limits< uint32_t >::max()) const
void remove(const block_id_type &id)
fetch_branch_from_impl
block_state_ptr root() const
void open(const std::function< void(block_timestamp_type, const flat_set< digest_type > &, const vector< digest_type > &)> &validator)
block_state_ptr head() const
void rollback_head_to_root()
block_header_state_ptr get_block_header(const block_id_type &id) const
void mark_valid(const block_state_ptr &h)
pair< branch_type, branch_type > fetch_branch_from(const block_id_type &first, const block_id_type &second) const
void reset(const block_header_state &root_bhs)
void add(const block_state_ptr &next_block, bool ignore_duplicate=false)
void advance_root(const block_id_type &id)
block_state_ptr get_block(const block_id_type &id) const
time_point published
this generated transaction will not be applied after this time
transaction_id_type trx_id
vector< char > packed_trx
Maintains global state information about block producer schedules and chain configuration parameters.
chain_config configuration
static void walk(const chainbase::database &db, F function)
static void create(chainbase::database &db, F cons)
maybe_session & operator=(maybe_session &&mv)
maybe_session(database &db)
maybe_session(const maybe_session &)=delete
maybe_session(maybe_session &&other)
boost::asio::io_context & get_executor()
void init(chainbase::database &db)
void popped_blocks_to(uint32_t block_num)
const protocol_feature_set & get_protocol_feature_set() const
void activate_feature(const digest_type &feature_digest, uint32_t current_block_num)
Maintains global state information about consensus protocol rules.
shared_vector< digest_type > preactivated_protocol_features
void initialize_database()
void initialize_account(const account_name &account)
void read_from_snapshot(const snapshot_reader_ptr &snapshot)
void set_block_parameters(const elastic_limit_parameters &cpu_limit_parameters, const elastic_limit_parameters &net_limit_parameters)
void process_block_usage(uint32_t block_num)
void add_to_snapshot(const snapshot_writer_ptr &snapshot) const
void add_pending_ram_usage(const account_name account, int64_t ram_delta)
void process_account_limit_updates()
void update_account_usage(const flat_set< account_name > &accounts, uint32_t ordinal)
void add_transaction_usage(const flat_set< account_name > &accounts, uint64_t cpu_usage, uint64_t net_usage, uint32_t ordinal)
int64_t get_account_ram_usage(const account_name &name) const
void verify_account_ram_usage(const account_name accunt) const
The table_id_object class tracks the mapping of (scope, code, table) to an opaque identifier.
void init_for_deferred_trx(fc::time_point published)
bool explicit_billed_cpu_time
int64_t billed_cpu_time_us
uint32_t update_billed_cpu_time(fc::time_point now)
void init_for_implicit_trx(uint64_t initial_net_usage=0)
fc::time_point block_deadline
transaction_trace_ptr trace
bool enforce_whiteblacklist
vector< digest_type > executed_action_receipt_digests
flat_set< account_name > bill_to_accounts
std::tuple< int64_t, int64_t, bool, bool > max_bandwidth_billed_accounts_can_pay(bool force_elastic_limits=false) const
void init_for_input_trx(uint64_t packed_trx_unprunable_size, uint64_t packed_trx_prunable_size)
int64_t subjective_cpu_bill_us
void current_lib(const uint32_t lib)
#define SET_APP_HANDLER(receiver, contract, action)
#define SYS_REPORT(DESC, A, B)
#define RAM_EVENT_ID(FORMAT,...)
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_LOG_AND_RETHROW()
void unpack(Stream &s, std::deque< T > &value)
void pack(Stream &s, const std::deque< T > &value)
void move_append(Container &dest, Container &&src)
scoped_exit< Callback > make_scoped_exit(Callback &&c)
constexpr microseconds seconds(int64_t s)
constexpr uint64_t billable_size_v
const std::vector< const char * > genesis_intrinsics
std::future< transaction_metadata_ptr > recover_keys_future
chainbase::shared_multi_index_container< global_property_object, indexed_by< ordered_unique< tag< by_id >, > > > global_property_multi_index
chainbase::shared_multi_index_container< code_object, indexed_by< ordered_unique< tag< by_id >, member< code_object, code_object::id_type, &code_object::id > >, ordered_unique< tag< by_code_hash >, composite_key< code_object, member< code_object, digest_type, &code_object::code_hash >, member< code_object, uint8_t, &code_object::vm_type >, member< code_object, uint8_t, &code_object::vm_version > > > > > code_index
chainbase::shared_multi_index_container< account_object, indexed_by< ordered_unique< tag< by_id >, member< account_object, account_object::id_type, &account_object::id > >, ordered_unique< tag< by_name >, member< account_object, account_name, &account_object::name > > > > account_index
chainbase::shared_multi_index_container< block_summary_object, indexed_by< ordered_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(block_summary_object, block_summary_object::id_type, id)> > > block_summary_multi_index
std::function< std::vector< signature_type >(const digest_type &)> signer_callback_type
void add_intrinsic_to_whitelist(whitelisted_intrinsics_type &whitelisted_intrinsics, std::string_view name)
secondary_index< uint128_t, index128_object_type >::index_index index128_index
builtin_protocol_feature_t
@ no_duplicate_deferred_id
@ disallow_empty_producer_schedule
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
std::variant< building_block, assembled_block, completed_block > block_stage_type
std::shared_ptr< transaction_trace > transaction_trace_ptr
typename object_to_table_id_tag< T >::tag_type object_to_table_id_tag_t
std::variant< block_signing_authority_v0 > block_signing_authority
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
secondary_index< uint64_t, index64_object_type >::index_index index64_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 database_exception
std::shared_ptr< const packed_transaction > packed_transaction_ptr
sysio::chain::action_name action_name
chainbase::shared_multi_index_container< transaction_object, indexed_by< ordered_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(transaction_object, transaction_object::id_type, id)>, ordered_unique< tag< by_trx_id >, BOOST_MULTI_INDEX_MEMBER(transaction_object, transaction_id_type, trx_id)>, ordered_unique< tag< by_expiration >, composite_key< transaction_object, BOOST_MULTI_INDEX_MEMBER(transaction_object, time_point_sec, expiration), > > > > transaction_multi_index
auto async_thread_pool(boost::asio::io_context &thread_pool, F &&f)
chainbase::shared_multi_index_container< database_header_object, indexed_by< ordered_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(database_header_object, database_header_object::id_type, id)> > > database_header_multi_index
chainbase::shared_multi_index_container< dynamic_global_property_object, indexed_by< ordered_unique< tag< by_id >, > > > dynamic_global_property_multi_index
std::shared_ptr< snapshot_writer > snapshot_writer_ptr
digest_type merkle(vector< digest_type > ids)
secondary_index< key256_t, index256_object_type >::index_index index256_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 block_validate_exception
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
unsigned char sysio_abi_bin[2132]
std::shared_ptr< snapshot_reader > snapshot_reader_ptr
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
chainbase::shared_multi_index_container< protocol_state_object, indexed_by< ordered_unique< tag< by_id >, > > > protocol_state_multi_index
std::function< void(apply_context &)> apply_handler
std::shared_ptr< block_state > block_state_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 fork_database_exception
std::shared_ptr< transaction_metadata > transaction_metadata_ptr
std::function< transaction_metadata_ptr(const transaction_id_type &)> trx_meta_cache_lookup
std::function< void(const branch_type &)> forked_branch_callback
chainbase::shared_multi_index_container< account_metadata_object, indexed_by< ordered_unique< tag< by_id >, member< account_metadata_object, account_metadata_object::id_type, &account_metadata_object::id > >, ordered_unique< tag< by_name >, member< account_metadata_object, account_name, &account_metadata_object::name > > > > account_metadata_index
secondary_index< float128_t, index_long_double_object_type, soft_long_double_less >::index_index index_long_double_index
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
schedule config_dir_name data_dir_name p2p_port http_port file_size name name keys peers producers(dont_start)) FC_REFLECT(testnet_def
const std::set< std::string > blacklist
unsigned __int64 uint64_t
vector< permission_level > authorization
pending_block_header_state _pending_block_header_state
vector< transaction_metadata_ptr > _trx_metas
std::optional< producer_authority_schedule > _new_producer_authority_cache
signed_block_ptr _unsigned_block
vector< permission_level_weight > accounts
std::optional< checksum256_type > _transaction_mroot
size_t _num_new_protocol_features_that_have_activated
std::optional< s_header > _s_header
vector< transaction_metadata_ptr > _pending_trx_metas
vector< digest_type > _new_protocol_feature_activations
pending_block_header_state _pending_block_header_state
vector< digest_type > _action_receipt_digests
building_block(const block_header_state &prev, block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector< digest_type > &new_protocol_feature_activations)
std::optional< producer_authority_schedule > _new_pending_producer_schedule
vector< transaction_receipt > _pending_trx_receipts
uint32_t target_block_net_usage_pct
the target percent (1% == 100, 100%= 10,000) of maximum net usage; exceeding this triggers congestion...
uint32_t max_block_cpu_usage
the maxiumum billable cpu usage (in microseconds) for a block
uint32_t min_transaction_cpu_usage
the minimum billable cpu usage (in microseconds) that the chain requires
uint64_t max_block_net_usage
the maxiumum net usage in instructions for a block
uint32_t target_block_cpu_usage_pct
the target percent (1% == 100, 100%= 10,000) of maximum cpu usage; exceeding this triggers congestion...
v1 Producer-voted blockchain configuration parameters
block_state_ptr _block_state
flat_set< account_name > contract_whitelist
uint32_t terminate_at_block
flat_set< account_name > actor_blacklist
flat_set< account_name > actor_whitelist
uint32_t sig_cpu_bill_pct
flat_set< account_name > contract_blacklist
flat_set< account_name > sender_bypass_whiteblacklist
flat_set< pair< account_name, action_name > > action_blacklist
flat_set< public_key_type > key_blacklist
void initialize_database(const genesis_state &genesis)
std::optional< pending_state > pending
transaction_trace_ptr push_scheduled_transaction(const transaction_id_type &trxid, fc::time_point block_deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time=false)
void check_contract_list(account_name code) const
void startup(std::function< void()> shutdown, std::function< bool()> check_shutdown, const snapshot_reader_ptr &snapshot)
deep_mind_handler * get_deep_mind_logger() const
int64_t remove_scheduled_transaction(const generated_transaction_object >o)
void read_from_snapshot(const snapshot_reader_ptr &snapshot, uint32_t blog_start, uint32_t blog_end)
protocol_feature_manager protocol_features
void set_activation_handler()
block_state_ptr create_block_state_i(const block_id_type &id, const signed_block_ptr &b, const block_header_state &prev)
apply_block
const chain_id_type chain_id
void replay_push_block(const signed_block_ptr &b, controller::block_status s)
void clear_expired_input_transactions(const fc::time_point &deadline)
signed_transaction get_on_block_transaction()
transaction_trace_ptr push_scheduled_transaction(const generated_transaction_object >o, fc::time_point block_deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time=false)
deep_mind_handler * deep_mind_logger
void finalize_block()
start_block
static std::optional< genesis_state > extract_legacy_genesis_state(snapshot_reader &snapshot, uint32_t version)
void emit(const Signal &s, Arg &&a)
map< account_name, map< handler_key, apply_handler > > apply_handlers
void update_producers_authority()
void create_block_summary(const block_id_type &id)
void startup(std::function< void()> shutdown, std::function< bool()> check_shutdown, const genesis_state &genesis)
std::function< void()> shutdown
pair< scope_name, action_name > handler_key
resource_limits_manager resource_limits
void add_to_snapshot(const snapshot_writer_ptr &snapshot)
uint32_t earliest_available_block_num() const
void set_apply_handler(account_name receiver, account_name contract, action_name action, apply_handler v)
fc::scoped_exit< std::function< void()> > make_block_restore_point()
void dmlog_applied_transaction(const transaction_trace_ptr &t)
void initialize_blockchain_state(const genesis_state &genesis)
void startup(std::function< void()> shutdown, std::function< bool()> check_shutdown)
void trigger_activation_handler(builtin_protocol_feature_t f)
void replay(std::function< bool()> check_shutdown)
static checksum256_type calculate_trx_merkle(const vector< transaction_receipt > &trxs)
void start_block(block_timestamp_type when, uint16_t confirm_block_count, const vector< digest_type > &new_protocol_feature_activations, controller::block_status s, const std::optional< block_id_type > &producer_block_id, const fc::time_point &deadline)
push_transaction
void init(std::function< bool()> check_shutdown)
transaction_trace_ptr apply_onerror(const generated_transaction >rx, fc::time_point block_deadline, fc::microseconds max_transaction_time, fc::time_point start, uint32_t &cpu_time_to_bill_us, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time=false, bool enforce_whiteblacklist=true)
const transaction_receipt & push_receipt(const T &trx, transaction_receipt_header::status_enum status, uint64_t cpu_usage_us, uint64_t net_usage)
push_scheduled_transaction
void apply_block(const block_state_ptr &bsp, controller::block_status s, const trx_meta_cache_lookup &trx_lookup)
bool in_trx_requiring_checks
if true, checks that are normally skipped on replay (e.g. auth checks) cannot be skipped
void read_contract_tables_from_snapshot(const snapshot_reader_ptr &snapshot)
named_thread_pool thread_pool
authorization_manager authorization
bool scheduled_failure_is_subjective(const fc::exception &e) const
std::optional< fc::microseconds > subjective_cpu_leeway
void commit_block(bool add_to_fork_db)
finalize_block
void push_block(const block_state_ptr &bsp, const forked_branch_callback &forked_branch_cb, const trx_meta_cache_lookup &trx_lookup)
void check_actor_list(const flat_set< account_name > &actors) const
unordered_map< builtin_protocol_feature_t, std::function< void(controller_impl &)>, enum_hash< builtin_protocol_feature_t > > protocol_feature_activation_handlers
bool failure_is_subjective(const fc::exception &e) const
block_state_ptr create_block_state(const block_id_type &id, const signed_block_ptr &b)
void check_key_list(const public_key_type &key) const
static auto validate_db_version(const chainbase::database &db)
void create_native_account(const fc::time_point &initial_timestamp, account_name name, const authority &owner, const authority &active, bool is_privileged=false)
void check_protocol_features(block_timestamp_type timestamp, const flat_set< digest_type > ¤tly_activated_protocol_features, const vector< digest_type > &new_protocol_features)
sha256 calculate_integrity_hash()
bool sender_avoids_whitelist_blacklist_enforcement(account_name sender) const
vector< transaction_metadata_ptr > abort_block()
push_block
void maybe_switch_forks(const block_state_ptr &new_head, controller::block_status s, const forked_branch_callback &forked_branch_cb, const trx_meta_cache_lookup &trx_lookup)
std::future< block_state_ptr > create_block_state_future(const block_id_type &id, const signed_block_ptr &b)
transaction_trace_ptr push_transaction(const transaction_metadata_ptr &trx, fc::time_point block_deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time, int64_t subjective_cpu_bill_us)
bool trusted_producer_light_validation
void report_block_header_diff(const block_header &b, const block_header &ab)
void add_contract_tables_to_snapshot(const snapshot_writer_ptr &snapshot) const
controller_impl(const controller::config &cfg, controller &s, protocol_feature_set &&pfs, const chain_id_type &chain_id)
uint32_t snapshot_head_block
void check_action_list(account_name code, action_name action) const
producer_authority_schedule schedule
digest_type schedule_hash
last irr block num
static constexpr wasm_config default_initial_wasm_configuration
limits for a kv database.
Immutable except for fc::from_variant.
const transaction & get_transaction() const
pending_state(maybe_session &&s, const block_header_state &prev, block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector< digest_type > &new_protocol_feature_activations)
const pending_block_header_state & get_pending_block_header_state() const
bool is_protocol_feature_activated(const digest_type &feature_digest) const
maybe_session _db_session
vector< transaction_metadata_ptr > extract_trx_metas()
std::optional< block_id_type > _producer_block_id
const vector< transaction_receipt > & get_trx_receipts() const
block_stage_type _block_stage
controller::block_status _block_status
uint32_t version
sequentially incrementing version number
static auto from_shared(const shared_producer_authority_schedule &src)
auto to_shared(chainbase::allocator< char > alloc) const
vector< producer_authority > producers