5 #include <openssl/md5.h>
7 #include <boost/iostreams/device/mapped_file.hpp>
8 #include <boost/core/ignore_unused.hpp>
10 #include <fc/smart_ref_impl.hpp>
11 #include <fc/uint128.hpp>
12 #include <fc/container/deque.hpp>
13 #include <fc/io/fstream.hpp>
14 #include <fc/io/json.hpp>
125 return _betting_service;
130 return _betting_matcher;
135 return _betting_resolver;
146 , _evaluator_registry(self)
148 , _betting_service(_self.account_service(),
160 , _betting_resolver(_self.account_service(),
171 , data_service_factory(*this)
172 , db_accessor_factory(static_cast<dba::
db_index&>(*this))
185 return data_dir /
"block_log";
204 const fc::path& shared_mem_dir,
205 uint64_t shared_file_size,
206 uint32_t chainbase_flags,
211 chainbase::database::open(shared_mem_dir, chainbase_flags, shared_file_size);
221 if (chainbase_flags & chainbase::database::read_write)
223 if (!find<dynamic_global_property_object>())
224 with_write_lock([&]() {
init_genesis(genesis_state); });
226 if (!fc::exists(data_dir))
228 fc::create_directories(data_dir);
233 auto log_head = _block_log.
head();
236 with_write_lock([&]() {
237 for_each_index([&](chainbase::abstract_generic_index_i& item) { item.undo_all(); });
239 for_each_index([&](chainbase::abstract_generic_index_i& item) {
241 "Chainbase revision does not match head block num. Reindex blockchain.",
252 FC_ASSERT(head_block.valid() && head_block->id() ==
head_block_id(),
253 "Chain state does not match block log. Reindex blockchain.");
261 const auto& chain_id = get<chain_property_object>().chain_id;
263 "Current chain id is not equal initial chain id = ${id}", (
"id", chain_id));
265 catch (fc::exception& err)
267 throw std::logic_error(std::string(
"Invalid chain id: ") + err.to_detail_string());
272 with_read_lock([&]() {
276 catch (fc::exception& err)
278 throw std::logic_error(std::string(
"Can't initialize hardforks: ") + err.to_detail_string());
281 FC_CAPTURE_LOG_AND_RETHROW((data_dir)(shared_mem_dir)(shared_file_size))
285 const fc::path& shared_mem_dir,
286 uint64_t shared_file_size,
292 ilog(
"Reindexing Blockchain");
294 wipe(data_dir, shared_mem_dir,
false);
295 open(data_dir, shared_mem_dir, shared_file_size, chainbase::database::read_write, genesis_state);
298 auto start = fc::time_point::now();
299 SCORUM_ASSERT(_block_log.
head(), block_log_exception,
"No blocks in block log. Cannot reindex an empty chain.");
301 auto last_block_num = _block_log.
head()->block_num();
302 uint log_interval_sz = std::max(last_block_num / 100u, 1000u);
304 ilog(
"Replaying ${n} blocks...", (
"n", last_block_num));
306 with_write_lock([&]() {
308 while (itr.first.block_num() <= last_block_num)
310 auto cur_block_num = itr.first.block_num();
311 if (cur_block_num % log_interval_sz == 0 || cur_block_num == last_block_num)
313 double percent = (cur_block_num * double(100)) / last_block_num;
314 ilog(
"${p}% applied. ${m}M free.",
315 (
"p", (boost::format(
"%5.2f") % percent).str())(
"m", get_free_memory() / (1024 * 1024)));
318 if (cur_block_num != last_block_num)
324 for_each_index([&](chainbase::abstract_generic_index_i& item) { item.set_revision(
head_block_num()); });
327 if (_block_log.
head()->block_num())
332 auto end = fc::time_point::now();
333 ilog(
"Done reindexing, elapsed time: ${t} sec", (
"t",
double((end - start).count()) / 1000000.0));
335 FC_CAPTURE_AND_RETHROW((data_dir)(shared_mem_dir)(shared_file_size)(skip_flags)(genesis_state))
338 void database::wipe(
const fc::path& data_dir,
const fc::path& shared_mem_dir,
bool include_blocks)
341 chainbase::database::wipe(shared_mem_dir);
344 fc::path block_log_file = block_log_path(data_dir);
350 void database::close()
361 chainbase::database::flush();
367 chainbase::database::close();
373 FC_CAPTURE_AND_RETHROW()
380 return fetch_block_by_id(
id).valid();
382 FC_CAPTURE_AND_RETHROW()
394 const auto& trx_idx = get_index<transaction_index>().indices().get<by_trx_id>();
395 return trx_idx.find(
id) != trx_idx.end();
397 FC_CAPTURE_AND_RETHROW()
422 auto b = _block_log.read_block_by_num(block_num);
429 std::shared_ptr<fork_item> fitem = _fork_db.fetch_block_on_main_branch_by_number(block_num);
437 FC_CAPTURE_AND_RETHROW((block_num))
447 optional<signed_block> database::fetch_block_by_id(
const block_id_type&
id)
const
451 auto b = _fork_db.fetch_block(
id);
456 if (tmp && tmp->id() ==
id)
467 FC_CAPTURE_AND_RETHROW()
470 optional<signed_block> database::fetch_block_by_number(uint32_t block_num)
const
474 optional<signed_block> b;
476 auto results = _fork_db.fetch_block_by_number(block_num);
477 if (results.size() == 1)
479 b = results[0]->data;
483 b = _block_log.read_block_by_num(block_num);
491 optional<signed_block> database::read_block_by_number(uint32_t block_num)
const
493 return _block_log.read_block_by_num(block_num);
500 auto& index = get_index<transaction_index>().indices().get<by_trx_id>();
501 auto itr = index.find(trx_id);
502 FC_ASSERT(itr != index.end());
504 fc::raw::unpack(itr->packed_trx, trx);
508 FC_CAPTURE_AND_RETHROW()
511 std::vector<block_id_type> database::get_block_ids_on_fork(
block_id_type head_of_fork)
const
515 std::pair<fork_database::branch_type, fork_database::branch_type> branches
516 = _fork_db.fetch_branch_from(head_block_id(), head_of_fork);
517 if (!((branches.first.back()->previous_id() == branches.second.back()->previous_id())))
519 edump((head_of_fork)(head_block_id())(branches.first.size())(branches.second.size()));
520 assert(branches.first.back()->previous_id() == branches.second.back()->previous_id());
522 std::vector<block_id_type>
result;
523 for (
const item_ptr& fork_block : branches.second)
525 result.emplace_back(fork_block->id);
527 result.emplace_back(branches.first.back()->previous_id());
530 FC_CAPTURE_AND_RETHROW()
535 return get<chain_property_object>().chain_id;
540 return _node_property_object;
543 const time_point_sec database::calculate_discussion_payout_time(
const comment_object& comment)
const
545 return comment.cashout_time;
548 uint32_t database::witness_participation_rate()
const
554 void database::add_checkpoints(
const flat_map<uint32_t, block_id_type>& checkpts)
556 for (
const auto& i : checkpts)
558 _checkpoints[i.first] = i.second;
562 bool database::before_last_checkpoint()
const
564 return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >= head_block_num());
573 bool database::push_block(
const signed_block& new_block, uint32_t skip)
579 debug_log(ctx,
"push_block skip=${s}", (
"s", skip));
583 with_write_lock([&]() {
587 result = _push_block(new_block);
590 FC_CAPTURE_AND_RETHROW(((std::string)ctx))
602 void database::_maybe_warn_multiple_production(uint32_t height)
const
604 auto blocks = _fork_db.fetch_block_by_number(height);
605 if (blocks.size() > 1)
607 std::vector<std::pair<account_name_type, fc::time_point_sec>> witness_time_pairs;
608 for (
const auto& b : blocks)
611 witness_time_pairs.push_back(std::make_pair(b->data.witness, b->data.timestamp));
614 ilog(
"Encountered block num collision at block ${n} due to a fork, witnesses are: ${w}",
615 (
"n", height)(
"w", witness_time_pairs));
620 bool database::_push_block(
const signed_block& new_block)
622 block_info ctx(new_block);
628 uint32_t skip = get_node_properties().skip_flags;
631 if (!(skip & skip_fork_db))
633 std::shared_ptr<fork_item> new_head = _fork_db.push_block(new_block);
635 debug_log(ctx,
"new_head_block=${b}", (
"b", (std::string)block_info(new_head->data)));
637 _maybe_warn_multiple_production(new_head->num);
640 if (new_head->data.previous != head_block_id())
642 debug_log(ctx,
"current head block_id=${h_id}", (
"h_id", head_block_id()));
643 debug_log(ctx,
"previous head block_id=${priv_id}", (
"priv_id", new_head->data.previous));
647 if (new_head->data.block_num() > head_block_num())
649 debug_log(ctx,
"current nead block_num=${h_num}", (
"h_num", head_block_num()));
650 debug_log(ctx,
"new head block number=${f_num}", (
"f_num", new_head->data.block_num()));
651 debug_log(ctx,
"switching to fork with block=${b}", (
"b", (std::string)block_info(new_head->data)));
653 auto branches = _fork_db.fetch_branch_from(new_head->data.id(), head_block_id());
656 while (head_block_id() != branches.second.back()->data.previous)
658 debug_log(ctx,
"popping block_id=${id}", (
"id", head_block_id()));
663 for (
auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr)
665 debug_log(ctx,
"pushing blocks from fork block=${b}",
666 (
"b", (std::string)block_info((*ritr)->data)));
667 optional<fc::exception> except;
670 auto session = start_undo_session();
671 apply_block((*ritr)->data, skip);
672 debug_log(ctx,
"applied block=${b}", (
"b", (std::string)block_info((*ritr)->data)));
675 catch (
const fc::exception& e)
681 debug_log(ctx,
"failed to push fork block exception=${e}",
682 (
"e", except->to_detail_string()));
684 while (ritr != branches.first.rend())
686 debug_log(ctx,
"removing_block=${b} from fork",
687 (
"b", (std::string)block_info((*ritr)->data)));
688 _fork_db.remove((*ritr)->data.id());
691 _fork_db.set_head(branches.second.front());
694 while (head_block_id() != branches.second.back()->data.previous)
696 debug_log(ctx,
"popping block_id=${id}", (
"id", head_block_id()));
701 for (
auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr)
703 auto session = start_undo_session();
704 apply_block((*ritr)->data, skip);
705 debug_log(ctx,
"applied block=${b}", (
"b", (std::string)block_info((*ritr)->data)));
712 debug_log(ctx,
"_push_block result=true");
717 debug_log(ctx,
"_push_block result=false");
725 auto session = start_undo_session();
726 apply_block(new_block, skip);
729 catch (
const fc::exception& e)
731 ctx_elog(ctx,
"failed to push new block exception=${e}", (
"e", e.to_detail_string()));
732 _fork_db.remove(new_block.id());
736 debug_log(ctx,
"_push_block result=false");
739 FC_CAPTURE_AND_RETHROW(((std::string)ctx))
757 size_t trx_size = fc::raw::pack_size(trx);
760 <= (obtain_service<dbs_dynamic_global_property>().get().median_chain_props.maximum_block_size - 256));
763 set_producing(
false);
767 set_producing(
false);
771 FC_CAPTURE_AND_RETHROW((trx))
778 if (!_pending_tx_session.valid())
780 _pending_tx_session = start_undo_session();
788 auto temp_session = start_undo_session();
789 _apply_transaction(trx);
790 _pending_tx.push_back(trx);
793 for_each_index([&](chainbase::abstract_generic_index_i& item) { item.squash(); });
794 temp_session->push();
797 notify_on_pending_transaction(trx);
802 const fc::ecc::private_key& block_signing_private_key,
808 debug_log(ctx,
"generate_block skip=${s}", (
"s", skip));
814 result = _generate_block(when, witness_owner, block_signing_private_key);
817 FC_CAPTURE_AND_RETHROW(((std::string)ctx))
823 signed_block database::_generate_block(fc::time_point_sec when,
825 const fc::ecc::private_key& block_signing_private_key)
831 auto& witness_svc = witness_service();
833 uint32_t skip = get_node_properties().skip_flags;
834 uint32_t slot_num = get_slot_at_time(when);
835 FC_ASSERT(slot_num > 0);
836 std::string scheduled_witness = get_scheduled_witness(slot_num);
837 FC_ASSERT(scheduled_witness == witness_owner);
839 const auto& witness_obj = witness_svc.get(witness_owner);
841 if (!(skip & skip_witness_signature))
843 FC_ASSERT(witness_obj.signing_key == block_signing_private_key.get_public_key());
846 static const size_t max_block_header_size = fc::raw::pack_size(signed_block_header()) + 4;
847 auto maximum_block_size = obtain_service<dbs_dynamic_global_property>()
849 .median_chain_props.maximum_block_size;
850 size_t total_block_size = max_block_header_size;
852 signed_block pending_block;
854 with_write_lock([&]() {
866 _pending_tx_session.reset();
867 _pending_tx_session = start_undo_session();
869 uint64_t postponed_tx_count = 0;
871 for (
const signed_transaction& tx : _pending_tx)
876 if (tx.expiration < when)
881 uint64_t new_total_size = total_block_size + fc::raw::pack_size(tx);
884 if (new_total_size >= maximum_block_size)
886 postponed_tx_count++;
892 auto temp_session = start_undo_session();
893 _apply_transaction(tx);
894 for_each_index([&](chainbase::abstract_generic_index_i& item) { item.squash(); });
895 temp_session->push();
897 total_block_size += fc::raw::pack_size(tx);
898 pending_block.transactions.push_back(tx);
900 catch (
const fc::exception& e)
907 if (postponed_tx_count > 0)
909 wlog(
"Postponed ${n} transactions due to block size limit", (
"n", postponed_tx_count));
912 _pending_tx_session.reset();
921 pending_block.previous = head_block_id();
922 pending_block.timestamp = when;
923 pending_block.transaction_merkle_root = pending_block.calculate_merkle_root();
924 pending_block.witness = witness_owner;
926 const auto& witness = witness_svc.get(witness_owner);
933 const auto& hfp = obtain_service<dbs_hardfork_property>().get();
935 if (hfp.current_hardfork_version
937 && (witness.hardfork_version_vote != _hardfork_versions[hfp.last_hardfork + 1]
938 || witness.hardfork_time_vote
939 != _hardfork_times[hfp.last_hardfork + 1]))
943 hardfork_version_vote(_hardfork_versions[hfp.last_hardfork + 1], _hardfork_times[hfp.last_hardfork + 1])));
945 else if (hfp.current_hardfork_version
947 && witness.hardfork_version_vote
952 hardfork_version_vote(_hardfork_versions[hfp.last_hardfork], _hardfork_times[hfp.last_hardfork])));
955 if (!(skip & skip_witness_signature))
957 pending_block.sign(block_signing_private_key);
961 if (!(skip & skip_block_size_check))
963 FC_ASSERT(fc::raw::pack_size(pending_block) <= SCORUM_MAX_BLOCK_SIZE);
966 push_block(pending_block, skip);
968 debug_log(ctx,
"_generate_block result=${b}", (
"b", (std::string)block_info(pending_block)));
970 return pending_block;
977 void database::pop_block()
990 _pending_tx_session.reset();
991 auto head_id = head_block_id();
994 optional<signed_block> head_block = fetch_block_by_id(head_id);
995 SCORUM_ASSERT(head_block.valid(), pop_empty_chain,
"there are no blocks to pop");
997 _fork_db.pop_block();
999 for_each_index([&](chainbase::abstract_generic_index_i& item) { item.undo(); });
1001 _popped_tx.insert(_popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end());
1005 FC_CAPTURE_AND_RETHROW(((std::string)ctx))
1008 void database::clear_pending()
1012 assert((_pending_tx.size() == 0) || _pending_tx_session.valid());
1013 _pending_tx.clear();
1014 _pending_tx_session.reset();
1016 FC_CAPTURE_AND_RETHROW()
1031 return operation_notification(_current_trx_id, _current_block_num, _current_trx_in_block, _current_op_in_trx, op);
1034 inline void database::push_virtual_operation(
const operation& op)
1036 if (_options & opt_notify_virtual_op_applying)
1040 auto note = create_notification(op);
1043 debug_log(ctx,
"virt operation pre_apply BEGIN");
1044 notify_pre_apply_operation(note);
1045 debug_log(ctx,
"virt operation pre_apply END");
1046 debug_log(ctx,
"virt operation post_apply BEGIN");
1047 notify_post_apply_operation(note);
1048 debug_log(ctx,
"virt operation post_apply END");
1052 inline void database::push_hf_operation(
const operation& op)
1056 auto note = create_notification(op);
1057 notify_pre_apply_operation(note);
1058 notify_post_apply_operation(note);
1095 fc::time_point_sec database::get_slot_time(uint32_t slot_num)
const
1099 return fc::time_point_sec();
1105 if (head_block_num() == 0)
1108 fc::time_point_sec genesis_time = dpo.
time;
1109 return genesis_time + slot_num * interval;
1112 int64_t head_block_abs_slot = head_block_time().sec_since_epoch() / interval;
1113 fc::time_point_sec head_slot_time(head_block_abs_slot * interval);
1119 return head_slot_time + (slot_num * interval);
1122 uint32_t database::get_slot_at_time(fc::time_point_sec when)
const
1124 fc::time_point_sec first_slot_time = get_slot_time(1);
1125 if (when < first_slot_time)
1132 void database::account_recovery_processing()
1135 const auto& rec_req_idx = get_index<account_recovery_request_index>().indices().get<by_expiration>();
1136 auto rec_req = rec_req_idx.begin();
1138 while (rec_req != rec_req_idx.end() && rec_req->expires <= head_block_time())
1141 rec_req = rec_req_idx.begin();
1145 const auto& hist_idx = get_index<owner_authority_history_index>().indices();
1146 auto hist = hist_idx.begin();
1148 while (hist != hist_idx.end()
1152 hist = hist_idx.begin();
1156 const auto& change_req_idx = get_index<change_recovery_account_request_index>().indices().get<by_effective_date>();
1157 auto change_req = change_req_idx.begin();
1159 auto& account_svc = account_service();
1160 while (change_req != change_req_idx.end() && change_req->effective_on <= head_block_time())
1162 modify(account_svc.get_account(change_req->account_to_recover),
1163 [&](account_object& a) { a.recovery_account = change_req->recovery_account; });
1166 change_req = change_req_idx.begin();
1170 void database::expire_escrow_ratification()
1172 const auto& escrow_idx = get_index<escrow_index>().indices().get<by_ratification_deadline>();
1173 auto escrow_itr = escrow_idx.lower_bound(
false);
1175 auto& account_svc = account_service();
1177 while (escrow_itr != escrow_idx.end() && !escrow_itr->is_approved()
1178 && escrow_itr->ratification_deadline <= head_block_time())
1180 const auto& old_escrow = *escrow_itr;
1183 const auto& from_account = account_svc.get_account(old_escrow.from);
1184 account_svc.increase_balance(from_account, old_escrow.scorum_balance + old_escrow.pending_fee);
1190 void database::process_decline_voting_rights()
1192 const auto& request_idx = get_index<decline_voting_rights_request_index>().indices().get<by_effective_date>();
1193 auto itr = request_idx.begin();
1195 auto& account_svc = account_service();
1197 while (itr != request_idx.end() && itr->effective_date <= head_block_time())
1199 const auto& account = get(itr->account);
1202 std::array<share_type, SCORUM_MAX_PROXY_RECURSION_DEPTH + 1> delta;
1203 delta[0] = -account.scorumpower.amount;
1206 delta[i + 1] = -account.proxied_vsf_votes[i];
1208 account_svc.adjust_proxied_witness_votes(account, delta);
1210 account_svc.clear_witness_votes(account);
1212 modify(get(itr->account), [&](account_object& a) {
1214 a.proxy = SCORUM_PROXY_TO_SELF_ACCOUNT;
1218 itr = request_idx.begin();
1222 time_point_sec database::head_block_time()
const
1224 return obtain_service<dbs_dynamic_global_property>().get().time;
1227 uint32_t database::head_block_num()
const
1229 return obtain_service<dbs_dynamic_global_property>().get().head_block_number;
1234 return obtain_service<dbs_dynamic_global_property>().get().head_block_id;
1240 auto b = fetch_block_by_id(head_block_id());
1247 ret =
block_info(head_block_time(), obtain_service<dbs_dynamic_global_property>().get().current_witness);
1254 return _node_property_object;
1257 uint32_t database::last_non_undoable_block_num()
const
1259 return obtain_service<dbs_dynamic_global_property>().get().last_irreversible_block_num;
1262 void database::initialize_evaluators()
1264 _my->_evaluator_registry.register_evaluator<account_create_evaluator>();
1265 _my->_evaluator_registry.register_evaluator<account_create_with_delegation_evaluator>();
1266 _my->_evaluator_registry.register_evaluator<account_update_evaluator>();
1267 _my->_evaluator_registry.register_evaluator<account_witness_proxy_evaluator>();
1268 _my->_evaluator_registry.register_evaluator<account_witness_vote_evaluator>();
1269 _my->_evaluator_registry.register_evaluator<atomicswap_initiate_evaluator>();
1270 _my->_evaluator_registry.register_evaluator<atomicswap_redeem_evaluator>();
1271 _my->_evaluator_registry.register_evaluator<atomicswap_refund_evaluator>();
1272 _my->_evaluator_registry.register_evaluator<change_recovery_account_evaluator>();
1273 _my->_evaluator_registry.register_evaluator<comment_evaluator>();
1274 _my->_evaluator_registry.register_evaluator<comment_options_evaluator>();
1275 _my->_evaluator_registry.register_evaluator<decline_voting_rights_evaluator>();
1276 _my->_evaluator_registry.register_evaluator<delegate_scorumpower_evaluator>();
1277 _my->_evaluator_registry.register_evaluator<delete_comment_evaluator>();
1278 _my->_evaluator_registry.register_evaluator<escrow_approve_evaluator>();
1279 _my->_evaluator_registry.register_evaluator<escrow_dispute_evaluator>();
1280 _my->_evaluator_registry.register_evaluator<escrow_release_evaluator>();
1281 _my->_evaluator_registry.register_evaluator<escrow_transfer_evaluator>();
1282 _my->_evaluator_registry.register_evaluator<prove_authority_evaluator>();
1283 _my->_evaluator_registry.register_evaluator<recover_account_evaluator>();
1284 _my->_evaluator_registry.register_evaluator<request_account_recovery_evaluator>();
1285 _my->_evaluator_registry.register_evaluator<transfer_evaluator>();
1286 _my->_evaluator_registry.register_evaluator<transfer_to_scorumpower_evaluator>();
1288 _my->_evaluator_registry.register_evaluator<witness_update_evaluator>();
1300 _my->_evaluator_registry.register_evaluator(
1302 _my->_evaluator_registry.register_evaluator(
new cancel_game_evaluator(*
this, _my->get_betting_service(), *
this));
1304 _my->_evaluator_registry.register_evaluator(
1306 _my->_evaluator_registry.register_evaluator(
1311 _my->get_betting_matcher(),
1312 _my->get_betting_service(),
1313 get_dba<game_object>(),
1314 get_dba<account_object>(),
1315 get_dba<bet_uuid_history_object>()));
1320 *
this, account_service(), get_dba<registration_pool_object>(), get_dba<registration_committee_member_object>(),
1321 get_dba<reg_pool_sp_delegation_object>()));
1322 _my->_evaluator_registry.register_evaluator(
1324 _my->_evaluator_registry.register_evaluator(
1326 _my->_evaluator_registry.register_evaluator(
1328 _my->_evaluator_registry.register_evaluator(
1330 _my->_evaluator_registry.register_evaluator(
1332 _my->_evaluator_registry.register_evaluator(
1336 void database::initialize_indexes()
1338 add_index<account_authority_index>();
1339 add_index<account_index>();
1340 add_index<account_registration_bonus_index>();
1341 add_index<account_blogging_statistic_index>();
1342 add_index<account_recovery_request_index>();
1343 add_index<block_summary_index>();
1344 add_index<fund_budget_index>();
1345 add_index<post_budget_index>();
1346 add_index<banner_budget_index>();
1347 add_index<chain_property_index>();
1348 add_index<change_recovery_account_request_index>();
1349 add_index<comment_index>();
1350 add_index<comment_statistic_scr_index>();
1351 add_index<comment_statistic_sp_index>();
1352 add_index<comment_vote_index>();
1353 add_index<decline_voting_rights_request_index>();
1354 add_index<dynamic_global_property_index>();
1355 add_index<escrow_index>();
1356 add_index<hardfork_property_index>();
1357 add_index<owner_authority_history_index>();
1358 add_index<proposal_object_index>();
1359 add_index<registration_committee_member_index>();
1360 add_index<registration_pool_index>();
1361 add_index<content_reward_fund_scr_index>();
1362 add_index<content_reward_fund_sp_index>();
1363 add_index<content_fifa_world_cup_2018_bounty_reward_fund_index>();
1364 add_index<content_reward_balancer_scr_index>();
1365 add_index<voters_reward_balancer_scr_index>();
1366 add_index<voters_reward_balancer_sp_index>();
1367 add_index<transaction_index>();
1368 add_index<scorumpower_delegation_expiration_index>();
1369 add_index<scorumpower_delegation_index>();
1370 add_index<reg_pool_sp_delegation_index>();
1371 add_index<withdraw_scorumpower_route_index>();
1372 add_index<withdraw_scorumpower_route_statistic_index>();
1373 add_index<withdraw_scorumpower_index>();
1374 add_index<witness_index>();
1375 add_index<witness_schedule_index>();
1376 add_index<witness_vote_index>();
1377 add_index<atomicswap_contract_index>();
1379 add_index<dev_committee_index>();
1380 add_index<dev_committee_member_index>();
1382 add_index<witness_reward_in_sp_migration_index>();
1383 add_index<advertising_property_index>();
1385 add_index<game_index>();
1387 add_index<betting_property_index>();
1388 add_index<pending_bet_index>();
1389 add_index<matched_bet_index>();
1391 add_index<bet_uuid_history_index>();
1392 add_index<game_uuid_history_index>();
1393 add_index<nft_index>();
1394 add_index<game_round_index>();
1396 _plugin_index_signal();
1401 database::with_write_lock([&]() {
1402 auto session = start_undo_session();
1403 _apply_transaction(trx);
1407 void database::set_flush_interval(uint32_t flush_blocks)
1409 _flush_blocks = flush_blocks;
1410 _next_flush_block = 0;
1419 debug_log(ctx,
"apply_block skip=${s}", (
"s", skip));
1425 auto block_num = next_block.
block_num();
1426 if (_checkpoints.size() && _checkpoints.rbegin()->second !=
block_id_type())
1428 auto itr = _checkpoints.find(block_num);
1429 if (itr != _checkpoints.end())
1430 FC_ASSERT(next_block.
id() == itr->second,
"Block did not match checkpoint",
1431 (
"checkpoint", *itr)(
"block_id", next_block.
id()));
1433 if (_checkpoints.rbegin()->first >= block_num)
1434 skip = skip_witness_signature | skip_transaction_signatures | skip_transaction_dupe_check | skip_fork_db
1435 | skip_block_size_check | skip_tapos_check
1436 | skip_authority_check
1439 | skip_undo_history_check | skip_witness_schedule_check | skip_validate | skip_validate_invariants;
1445 if (is_producing() || !(skip & skip_validate_invariants))
1449 validate_invariants();
1452 FC_CAPTURE_AND_RETHROW(((std::string)ctx));
1454 FC_CAPTURE_AND_LOG(((std::string)ctx));
1460 if (_flush_blocks != 0)
1462 if (_next_flush_block == 0)
1464 uint32_t lep = block_num + 1 + _flush_blocks * 9 / 10;
1465 uint32_t rep = block_num + 1 + _flush_blocks;
1468 uint32_t span = rep - lep;
1472 uint64_t now = uint64_t(fc::time_point::now().time_since_epoch().count());
1475 _next_flush_block = x;
1479 if (_next_flush_block == block_num)
1481 _next_flush_block = 0;
1483 chainbase::database::flush();
1487 show_free_memory(
false);
1491 FC_CAPTURE_AND_RETHROW(((std::string)ctx))
1494 void database::show_free_memory(
bool force)
1496 uint32_t free_gb = uint32_t(get_free_memory() / (1024 * 1024 * 1024));
1497 if (force || (free_gb < _last_free_gb_printed) || (free_gb > _last_free_gb_printed + 1))
1499 ilog(
"Free memory is now ${n}G", (
"n", free_gb));
1500 _last_free_gb_printed = free_gb;
1505 uint32_t free_mb = uint32_t(get_free_memory() / (1024 * 1024));
1509 elog(
"Free memory is now ${n}M. Increase shared file size immediately!", (
"n", free_mb));
1522 notify_pre_applied_block(next_block);
1524 uint32_t next_block_num = next_block.
block_num();
1527 uint32_t skip = get_node_properties().skip_flags;
1529 if (!(skip & skip_merkle_check))
1537 "calc", merkle_root)(
"next_block", next_block)(
"id", next_block.
id()));
1539 catch (fc::assert_exception& e)
1543 const auto& merkle_map = get_shared_db_merkle();
1544 auto itr = merkle_map.find(next_block_num);
1546 if (itr == merkle_map.end() || itr->second != merkle_root)
1548 debug_log(ctx,
"rethrow merkle check fail");
1555 const witness_object& signing_witness = validate_block_header(skip, next_block);
1557 _current_block_num = next_block_num;
1558 _current_trx_in_block = 0;
1560 const auto& gprops = obtain_service<dbs_dynamic_global_property>().get();
1561 auto block_size = fc::raw::pack_size(next_block);
1562 FC_ASSERT(block_size <= gprops.median_chain_props.maximum_block_size,
"Block Size is too Big",
1563 (
"next_block_num", next_block_num)(
"block_size",
1564 block_size)(
"max", gprops.median_chain_props.maximum_block_size));
1571 process_header_extensions(next_block);
1573 const auto& witness = witness_service().get(next_block.
witness);
1574 const auto& hardfork_state = obtain_service<dbs_hardfork_property>().get();
1575 FC_ASSERT(witness.running_version >= hardfork_state.current_hardfork_version,
1576 "Block produced by witness that is not running current hardfork",
1577 (
"witness", witness)(
"next_block.witness", next_block.
witness)(
"hardfork_state", hardfork_state));
1592 apply_transaction(trx, skip);
1593 ++_current_trx_in_block;
1596 debug_log(ctx,
"update_global_dynamic_data");
1597 update_global_dynamic_data(next_block);
1598 debug_log(ctx,
"update_signing_witness");
1599 update_signing_witness(signing_witness, next_block);
1601 debug_log(ctx,
"update_last_irreversible_block");
1602 update_last_irreversible_block();
1605 create_block_summary(next_block);
1606 debug_log(ctx,
"clear_expired_transactions");
1607 clear_expired_transactions();
1608 debug_log(ctx,
"clear_expired_delegations");
1609 clear_expired_delegations();
1612 update_witness_schedule();
1616 _current_block_num, ctx);
1629 get_dba<game_object>(), get_dba<dynamic_global_property_object>())
1633 get_dba<dynamic_global_property_object>())
1636 debug_log(ctx,
"account_recovery_processing");
1637 account_recovery_processing();
1638 debug_log(ctx,
"expire_escrow_ratification");
1639 expire_escrow_ratification();
1640 debug_log(ctx,
"process_decline_voting_rights");
1641 process_decline_voting_rights();
1643 debug_log(ctx,
"clear_expired_proposals");
1644 obtain_service<dbs_proposal>().clear_expired_proposals();
1647 process_hardforks();
1650 notify_applied_block(next_block);
1654 FC_CAPTURE_LOG_AND_RETHROW(((std::string)ctx))
1659 auto& witness_svc = witness_service();
1665 switch (itr->which())
1671 auto reported_version = itr->get<
version>();
1672 const auto& signing_witness = witness_svc.get(next_block.
witness);
1675 if (reported_version != signing_witness.running_version)
1684 const auto& signing_witness = witness_svc.get(next_block.
witness);
1688 || hfv.hf_time != signing_witness.hardfork_time_vote)
1697 FC_ASSERT(
false,
"Unknown extension in block header");
1707 notify_on_applied_transaction(trx);
1714 _current_trx_id = trx.
id();
1715 uint32_t skip = get_node_properties().skip_flags;
1717 if (!(skip & skip_validate))
1722 auto& trx_idx = get_index<transaction_index>();
1723 auto trx_id = trx.
id();
1725 FC_ASSERT((skip & skip_transaction_dupe_check)
1726 || trx_idx.indices().get<by_trx_id>().find(trx_id) == trx_idx.indices().get<by_trx_id>().end(),
1727 "Duplicate transaction check failed", (
"trx_ix", trx_id));
1729 if (!(skip & (skip_transaction_signatures | skip_authority_check)))
1731 auto get_active = [&](
const std::string& name) {
1732 return authority(get<account_authority_object, by_account>(name).
active);
1734 auto get_owner = [&](
const std::string& name) {
1735 return authority(get<account_authority_object, by_account>(name).
owner);
1737 auto get_posting = [&](
const std::string& name) {
1743 trx.
verify_authority(get_chain_id(), get_active, get_owner, get_posting, SCORUM_MAX_SIG_CHECK_DEPTH);
1745 catch (protocol::tx_missing_active_auth& e)
1747 if (get_shared_db_merkle().find(head_block_num() + 1) == get_shared_db_merkle().end())
1756 if (BOOST_LIKELY(head_block_num() > 0))
1758 if (!(skip & skip_tapos_check))
1760 const auto& tapos_block_summary = get<block_summary_object>(trx.
ref_block_num);
1764 transaction_tapos_exception,
"",
1766 tapos_block_summary.block_id._hash[1]));
1769 fc::time_point_sec now = head_block_time();
1780 if (!(skip & skip_transaction_dupe_check))
1789 notify_on_pre_apply_transaction(trx);
1792 _current_op_in_trx = 0;
1797 apply_operation(op);
1798 ++_current_op_in_trx;
1800 FC_CAPTURE_AND_RETHROW((op));
1804 FC_CAPTURE_AND_RETHROW((trx))
1809 auto note = create_notification(op);
1811 notify_pre_apply_operation(note);
1812 _my->_evaluator_registry.get_evaluator(op).apply(op);
1813 notify_post_apply_operation(note);
1820 FC_ASSERT(head_block_id() == next_block.
previous,
"",
1821 (
"head_block_id", head_block_id())(
"next.prev", next_block.
previous));
1823 head_block_time() < next_block.
timestamp,
"",
1824 (
"head_block_time", head_block_time())(
"next", next_block.
timestamp)(
"blocknum", next_block.
block_num()));
1828 if (!(skip & skip_witness_signature))
1833 if (!(skip & skip_witness_schedule_check))
1835 uint32_t slot_num = get_slot_at_time(next_block.
timestamp);
1836 FC_ASSERT(slot_num > 0);
1838 std::string scheduled_witness = get_scheduled_witness(slot_num);
1840 if (witness.
owner != scheduled_witness)
1842 wdump((obtain_service<dbs_dynamic_global_property>().get())(next_block.
block_num())(next_block));
1845 FC_ASSERT(witness.
owner == scheduled_witness,
"Witness produced block at wrong time",
1846 (
"block witness", next_block.
witness)(
"scheduled", scheduled_witness)(
"slot_num", slot_num));
1851 FC_CAPTURE_AND_RETHROW()
1861 FC_CAPTURE_AND_RETHROW()
1869 auto& witness_svc = witness_service();
1871 uint32_t missed_blocks = 0;
1872 if (head_block_time() != fc::time_point_sec())
1874 missed_blocks = get_slot_at_time(b.
timestamp);
1875 assert(missed_blocks != 0);
1878 if (missed_blocks > 0)
1880 dlog(
"{\"missed_blocks\": ${missed_blocks}, \"last_block\": {\"last_block_num\": ${last_block_num}, "
1881 "\"info\": ${last_block}}, \"new_block\": {\"new_block_num\": ${new_block_num}, \"info\": "
1884 "last_block", fetch_block_by_id(_dgp.
head_block_id))(
"new_block_num",
1888 for (uint32_t i = 0; i < missed_blocks; ++i)
1890 const auto& witness_missed = witness_svc.get(get_scheduled_witness(i + 1));
1891 if (witness_missed.owner != b.
witness)
1911 for (uint32_t i = 0; i < missed_blocks + 1; i++)
1924 if (!(get_node_properties().skip_flags & skip_undo_history_check))
1928 undo_database_exception,
1929 "The database does not have enough undo history to support a blockchain with so many missed blocks. "
1930 "Please add a checkpoint if you would like to continue applying blocks beyond this point.",
1932 "max_undo", SCORUM_MAX_UNDO_HISTORY));
1935 FC_CAPTURE_AND_RETHROW()
1944 FC_CAPTURE_AND_RETHROW()
1947 void database::update_last_irreversible_block()
1968 auto& witness_svc = witness_service();
1971 std::vector<const witness_object*> wit_objs;
1978 static_assert(SCORUM_IRREVERSIBLE_THRESHOLD > 0,
"irreversible threshold must be nonzero");
1987 std::nth_element(wit_objs.begin(), wit_objs.begin() + offset, wit_objs.end(),
1989 return a->last_confirmed_block_num < b->last_confirmed_block_num;
1992 uint32_t new_last_irreversible_block_num = wit_objs[offset]->last_confirmed_block_num;
2005 if (!(get_node_properties().skip_flags & skip_block_log))
2008 const auto& tmp_head = _block_log.head();
2009 uint64_t log_head_num = 0;
2013 log_head_num = tmp_head->block_num();
2020 std::shared_ptr<fork_item> block = _fork_db.fetch_block_on_main_branch_by_number(log_head_num + 1);
2021 FC_ASSERT(block,
"Current fork in the fork database does not contain the last_irreversible_block");
2022 _block_log.append(block->data);
2032 FC_CAPTURE_AND_RETHROW()
2035 void database::clear_expired_transactions()
2039 auto& transaction_idx = get_index<transaction_index>();
2040 const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
2041 while ((!dedupe_index.empty()) && (head_block_time() > dedupe_index.begin()->expiration))
2043 remove(*dedupe_index.begin());
2047 void database::clear_expired_delegations()
2049 auto now = head_block_time();
2050 const auto& delegations_by_exp = get_index<scorumpower_delegation_expiration_index, by_expiration>();
2051 const auto& account_svc = account_service();
2052 auto itr = delegations_by_exp.begin();
2053 while (itr != delegations_by_exp.end() && itr->expiration < now)
2055 modify(account_svc.get_account(itr->delegator),
2056 [&](account_object& a) { a.delegated_scorumpower -= itr->scorumpower; });
2061 itr = delegations_by_exp.begin();
2067 return _my->_genesis_persistent_state;
2070 void database::init_hardforks(time_point_sec genesis_time)
2072 _hardfork_times[0] = genesis_time;
2077 FC_ASSERT(SCORUM_HARDFORK_0_1 == 1,
"Invalid hardfork #1 configuration");
2078 _hardfork_times[SCORUM_HARDFORK_0_1] = fc::time_point_sec(SCORUM_HARDFORK_0_1_TIME);
2079 _hardfork_versions[SCORUM_HARDFORK_0_1] = SCORUM_HARDFORK_0_1_VERSION;
2081 FC_ASSERT(SCORUM_HARDFORK_0_2 == 2,
"Invalid hardfork #2 configuration");
2082 _hardfork_times[SCORUM_HARDFORK_0_2] = fc::time_point_sec(SCORUM_HARDFORK_0_2_TIME);
2083 _hardfork_versions[SCORUM_HARDFORK_0_2] = SCORUM_HARDFORK_0_2_VERSION;
2085 FC_ASSERT(SCORUM_HARDFORK_0_3 == 3,
"Invalid hardfork #3 configuration");
2086 _hardfork_times[SCORUM_HARDFORK_0_3] = fc::time_point_sec(SCORUM_HARDFORK_0_3_TIME);
2087 _hardfork_versions[SCORUM_HARDFORK_0_3] = SCORUM_HARDFORK_0_3_VERSION;
2089 FC_ASSERT(SCORUM_HARDFORK_0_4 == 4,
"Invalid hardfork #4 configuration");
2090 _hardfork_times[SCORUM_HARDFORK_0_4] = fc::time_point_sec(SCORUM_HARDFORK_0_4_TIME);
2091 _hardfork_versions[SCORUM_HARDFORK_0_4] = SCORUM_HARDFORK_0_4_VERSION;
2093 FC_ASSERT(SCORUM_HARDFORK_0_5 == 5,
"Invalid hardfork #5 configuration");
2094 _hardfork_times[SCORUM_HARDFORK_0_5] = fc::time_point_sec(SCORUM_HARDFORK_0_5_TIME);
2095 _hardfork_versions[SCORUM_HARDFORK_0_5] = SCORUM_HARDFORK_0_5_VERSION;
2097 FC_ASSERT(SCORUM_HARDFORK_0_6 == 6,
"Invalid hardfork #6 configuration");
2098 _hardfork_times[SCORUM_HARDFORK_0_6] = fc::time_point_sec(SCORUM_HARDFORK_0_6_TIME);
2099 _hardfork_versions[SCORUM_HARDFORK_0_6] = SCORUM_HARDFORK_0_6_VERSION;
2101 const auto& hardforks = obtain_service<dbs_hardfork_property>().get();
2102 FC_ASSERT(hardforks.last_hardfork <= SCORUM_NUM_HARDFORKS,
"Chain knows of more hardforks than configuration",
2103 (
"hardforks.last_hardfork", hardforks.last_hardfork)(
"SCORUM_NUM_HARDFORKS", SCORUM_NUM_HARDFORKS));
2105 "Blockchain version is older than last applied hardfork");
2109 void database::process_hardforks()
2114 const auto& hardforks = obtain_service<dbs_hardfork_property>().get();
2116 while (_hardfork_versions[hardforks.last_hardfork] < hardforks.next_hardfork
2117 && hardforks.next_hardfork_time <= head_block_time())
2119 if (hardforks.last_hardfork < SCORUM_NUM_HARDFORKS)
2121 apply_hardfork(hardforks.last_hardfork + 1);
2125 throw unknown_hardfork_exception();
2129 FC_CAPTURE_AND_RETHROW()
2132 bool database::has_hardfork(uint32_t hardfork)
const
2134 return obtain_service<dbs_hardfork_property>().get().processed_hardforks.size() > hardfork;
2137 void database::set_hardfork(uint32_t hardfork,
bool apply_now)
2139 auto const& hardforks = obtain_service<dbs_hardfork_property>().get();
2141 for (uint32_t i = hardforks.last_hardfork + 1; i <= hardfork && i <= SCORUM_NUM_HARDFORKS; i++)
2143 modify(hardforks, [&](hardfork_property_object& hpo) {
2144 hpo.next_hardfork = _hardfork_versions[i];
2145 hpo.next_hardfork_time = head_block_time();
2155 void database::apply_hardfork(uint32_t hardfork)
2157 if (_options & opt_log_hardforks)
2159 elog(
"HARDFORK ${hf} at block ${b}", (
"hf", hardfork)(
"b", head_block_num()));
2168 obtain_service<dbs_hardfork_property>().update([&](hardfork_property_object& hfp) {
2169 FC_ASSERT(hardfork == hfp.last_hardfork + 1,
"Hardfork being applied out of order",
2170 (
"hardfork", hardfork)(
"hfp.last_hardfork", hfp.last_hardfork));
2171 FC_ASSERT(hfp.processed_hardforks.size() == hardfork,
"Hardfork being applied out of order");
2172 hfp.processed_hardforks.push_back(_hardfork_times[hardfork]);
2173 hfp.last_hardfork = hardfork;
2174 hfp.current_hardfork_version = _hardfork_versions[hardfork];
2175 FC_ASSERT(hfp.processed_hardforks[hfp.last_hardfork] == _hardfork_times[hfp.last_hardfork],
2176 "Hardfork processing failed sanity check...");
2185 void database::validate_invariants()
const
2191 const auto& account_svc = account_service();
2192 const auto& gpo = obtain_service<dbs_dynamic_global_property>().get();
2194 const auto accounts_circulating = account_svc.accounts_circulating_capital();
2196 total_supply += accounts_circulating.scr;
2198 total_supply += accounts_circulating.pending_scr;
2202 const auto& witness_idx = get_index<witness_index>().indices();
2203 for (
auto itr = witness_idx.begin(); itr != witness_idx.end(); ++itr)
2205 FC_ASSERT(itr->votes <= gpo.total_scorumpower.amount,
"${vs} > ${tvs}",
2206 (
"vs", itr->votes)(
"tvs", gpo.total_scorumpower.amount));
2209 const auto& escrow_idx = get_index<escrow_index>().indices().get<by_id>();
2210 for (
auto itr = escrow_idx.begin(); itr != escrow_idx.end(); ++itr)
2212 total_supply += itr->scorum_balance;
2213 total_supply += itr->pending_fee;
2216 total_supply += obtain_service<dbs_content_reward_fund_scr>().get().activity_reward_balance;
2218 +=
asset(obtain_service<dbs_content_reward_fund_sp>().get().activity_reward_balance.amount,
SCORUM_SYMBOL);
2220 auto& fifa_2018_reward_service = obtain_service<dbs_content_fifa_world_cup_2018_bounty_reward_fund>();
2221 if (fifa_2018_reward_service.is_exists())
2223 total_supply +=
asset(fifa_2018_reward_service.get().activity_reward_balance.amount,
SCORUM_SYMBOL);
2227 total_supply += obtain_service<dbs_content_reward_scr>().get().balance;
2228 total_supply += obtain_service<dbs_voters_reward_scr>().get().balance;
2229 total_supply += obtain_service<dbs_voters_reward_sp>().get().balance.
amount;
2231 for (
const post_budget_object& budget : obtain_service<dbs_post_budget>().get_budgets())
2233 total_supply += budget.balance;
2234 total_supply += budget.owner_pending_income;
2235 total_supply += budget.budget_pending_outgo;
2240 total_supply += budget.balance;
2241 total_supply += budget.owner_pending_income;
2242 total_supply += budget.budget_pending_outgo;
2245 if (obtain_service<dbs_fund_budget>().is_exists())
2247 total_supply += obtain_service<dbs_fund_budget>().get().balance.
amount;
2250 if (obtain_service<dbs_registration_pool>().is_exists())
2252 auto& pool = obtain_service<dbs_registration_pool>().get();
2253 total_supply += pool.balance;
2257 total_supply +=
asset(obtain_service<dbs_dev_pool>().get().sp_balance.amount,
SCORUM_SYMBOL);
2258 total_supply += obtain_service<dbs_dev_pool>().get().scr_balance;
2260 if (obtain_service<dbs_witness_reward_in_sp_migration>().is_exists())
2262 total_supply +=
asset(obtain_service<dbs_witness_reward_in_sp_migration>().get().balance,
SCORUM_SYMBOL);
2265 const auto& atomicswap_contract_idx = get_index<atomicswap_contract_index, by_id>();
2266 for (
auto itr = atomicswap_contract_idx.begin(); itr != atomicswap_contract_idx.end(); ++itr)
2268 total_supply += itr->
amount;
2272 const auto& matched_bets = get_index<matched_bet_index, by_id>();
2273 for (
auto itr = matched_bets.begin(); itr != matched_bets.end(); ++itr)
2275 total_supply += itr->bet1_data.stake;
2276 total_supply += itr->bet2_data.stake;
2279 const auto& pending_bets = get_index<pending_bet_index, by_id>();
2280 for (
auto itr = pending_bets.begin(); itr != pending_bets.end(); ++itr)
2282 total_supply += itr->data.stake;
2285 FC_ASSERT(total_supply <= asset::maximum(
SCORUM_SYMBOL),
"Assets SCR overflow");
2286 FC_ASSERT(accounts_circulating.sp <= asset::maximum(
SP_SYMBOL),
"Assets SP overflow");
2288 FC_ASSERT(gpo.total_supply == total_supply,
"",
2289 (
"gpo.total_supply", gpo.total_supply)
2290 (
"total_supply", total_supply));
2292 FC_ASSERT(gpo.total_scorumpower == accounts_circulating.sp,
"",
2293 (
"gpo.total_supply", gpo.total_supply)
2294 (
"gpo.total_scorumpower", gpo.total_scorumpower)
2295 (
"gpo.circulating_capital", gpo.circulating_capital)
2296 (
"accounts_circulating.sp", accounts_circulating.sp)
2297 (
"accounts_circulating.scr", accounts_circulating.scr));
2299 FC_ASSERT(gpo.circulating_capital.amount - gpo.total_scorumpower.amount == accounts_circulating.scr.amount,
"",
2300 (
"gpo.total_supply", gpo.total_supply)
2301 (
"gpo.total_scorumpower", gpo.total_scorumpower)
2302 (
"gpo.circulating_capital", gpo.circulating_capital)
2303 (
"accounts_circulating.sp", accounts_circulating.sp)
2304 (
"accounts_circulating.scr", accounts_circulating.scr));
2306 FC_ASSERT(gpo.total_scorumpower.amount == accounts_circulating.vsf_votes,
"",
2307 (
"total_scorumpower", gpo.total_scorumpower)
2308 (
"accounts_circulating.total_vsf_votes", accounts_circulating.vsf_votes));
2310 FC_ASSERT(gpo.total_pending_scr == accounts_circulating.pending_scr,
"",
2311 (
"total_pending_scr", gpo.total_pending_scr)
2312 (
"accounts_circulating.pending_scr", accounts_circulating.pending_scr));
2314 FC_ASSERT(gpo.total_pending_sp == accounts_circulating.pending_sp,
"",
2315 (
"total_pending_sp", gpo.total_pending_sp)
2316 (
"accounts_circulating.pending_sp", accounts_circulating.pending_sp));
2320 FC_CAPTURE_LOG_AND_RETHROW((head_block_num()));
const optional< signed_block > & head() const
optional< signed_block > read_block_by_num(uint32_t block_num) const
void open(const fc::path &file)
std::pair< signed_block, uint64_t > read_block(uint64_t file_pos) const
tracks minimal information about past blocks to implement TaPOS
evaluator_registry< operation > _evaluator_registry
betting_matcher_i & get_betting_matcher()
database_impl(database &self)
betting_resolver_i & get_betting_resolver()
betting_service_i & get_betting_service()
genesis_persistent_state_type _genesis_persistent_state
tracks the blockchain state in an extensible manner
void init_genesis(const genesis_state_type &genesis_state)
uint32_t get_reindex_skip_flags() const
void validate_invariants() const
void set_initial_timestamp(const genesis_state_type &genesis_state)
void init_hardforks(fc::time_point_sec genesis_time)
void reindex(const fc::path &data_dir, const fc::path &shared_mem_dir, uint64_t shared_file_size, uint32_t skip_flags, const genesis_state_type &genesis_state)
Rebuild object graph from block history and open detabase.
static fc::path block_log_path(const fc::path &data_dir)
@ skip_authority_check
used while reindexing – disables any checking of authority on transactions
@ skip_validate
used prior to checkpoint, skips validate() call on transaction
@ skip_merkle_check
used while reindexing
@ skip_transaction_dupe_check
used while reindexing
@ skip_witness_schedule_check
used while reindexing
@ skip_tapos_check
used while reindexing – note this skips expiration check as well
@ skip_witness_signature
used while reindexing
@ skip_block_log
used to skip block logging on reindex
@ skip_validate_invariants
used to skip database invariant check on block application
@ skip_transaction_signatures
used by non-witness nodes
void open(const fc::path &data_dir, const fc::path &shared_mem_dir, uint64_t shared_file_size, uint32_t chainbase_flags, const genesis_state_type &genesis_state)
Open a database, creating a new one if necessary.
void initialize_evaluators()
block_id_type head_block_id() const
uint32_t head_block_num() const
void apply_block(const signed_block &next_block, uint32_t skip=skip_nothing)
void initialize_indexes()
Reset the object graph in-memory.
void wipe(const fc::path &data_dir, const fc::path &shared_mem_dir, bool include_blocks)
wipe Delete database from disk, and potentially the raw chain as well.
Maintains global state information.
uint32_t last_irreversible_block_num
last irreversible block num
uint8_t participation_count
Divide by 128 to compute participation percentage.
block_id_type head_block_id
Current head block id.
fc::uint128_t recent_slots_filled
used to compute witness participation.
uint32_t head_block_number
Current head block number.
account_name_type current_witness
Head block signed by current witness.
time_point_sec time
Current head block time.
void start_block(signed_block b)
Contains per-node database configuration.
void apply(ContextType &ctx)
uint64_t last_confirmed_block_num
time_point_sec hardfork_time_vote
hardfork_version hardfork_version_vote
public_key_type signing_key
uint8_t num_scheduled_witnesses
fc::array< account_name_type, SCORUM_MAX_WITNESSES_LIMIT > current_shuffled_witnesses
#define SCORUM_DB_FREE_MEMORY_THRESHOLD_MB
#define SCORUM_OWNER_AUTH_RECOVERY_PERIOD
#define SCORUM_WITNESS_MISSED_BLOCKS_THRESHOLD
#define SCORUM_BLOCKCHAIN_HARDFORK_VERSION
#define SCORUM_100_PERCENT
#define SCORUM_START_MINER_VOTING_BLOCK
#define SCORUM_MAX_PROXY_RECURSION_DEPTH
#define SCORUM_BLOCKCHAIN_VERSION
#define SCORUM_MAX_WITNESSES
#define SCORUM_MAX_TIME_UNTIL_EXPIRATION
#define SCORUM_BLOCKID_POOL_SIZE
#define SCORUM_BLOCK_INTERVAL
#define SCORUM_TRY_NOTIFY(signal,...)
#define debug_log(CTX, FORMAT,...)
#define SCORUM_ASSERT(expr, exc_type, FORMAT,...)
void remove_all(db_index &db_idx, utils::bidir_range< const TObject > items)
void remove(db_index &db_idx, const TObject &o)
chainbase::database_index< chainbase::segment_manager > db_index
void without_pending_transactions(database &db, std::vector< signed_transaction > &&pending_transactions, Lambda callback)
void with_skip_flags(database &db, uint32_t skip_flags, Lambda callback)
std::shared_ptr< fork_item > item_ptr
fc::ripemd160 transaction_id_type
fc::static_variant< vote_operation, comment_operation, transfer_operation, transfer_to_scorumpower_operation, withdraw_scorumpower_operation, account_create_by_committee_operation, account_create_operation, account_create_with_delegation_operation, account_update_operation, witness_update_operation, account_witness_vote_operation, account_witness_proxy_operation, delete_comment_operation, comment_options_operation, set_withdraw_scorumpower_route_to_account_operation, set_withdraw_scorumpower_route_to_dev_pool_operation, prove_authority_operation, request_account_recovery_operation, recover_account_operation, change_recovery_account_operation, escrow_approve_operation, escrow_dispute_operation, escrow_release_operation, escrow_transfer_operation, decline_voting_rights_operation, delegate_scorumpower_operation, create_budget_operation, close_budget_operation, proposal_vote_operation, proposal_create_operation, atomicswap_initiate_operation, atomicswap_redeem_operation, atomicswap_refund_operation, close_budget_by_advertising_moderator_operation, update_budget_operation, create_game_operation, cancel_game_operation, update_game_markets_operation, update_game_start_time_operation, post_game_results_operation, post_bet_operation, cancel_pending_bets_operation, delegate_sp_from_reg_pool_operation, create_nft_operation, update_nft_meta_operation, create_game_round_operation, update_game_round_result_operation, adjust_nft_experience_operation, update_nft_name_operation, author_reward_operation, comment_benefficiary_reward_operation, comment_payout_update_operation, comment_reward_operation, curation_reward_operation, hardfork_operation, producer_reward_operation, active_sp_holders_reward_operation, return_scorumpower_delegation_operation, shutdown_witness_operation, witness_miss_block_operation, expired_contract_refund_operation, acc_finished_vesting_withdraw_operation, devpool_finished_vesting_withdraw_operation, acc_to_acc_vesting_withdraw_operation, devpool_to_acc_vesting_withdraw_operation, acc_to_devpool_vesting_withdraw_operation, devpool_to_devpool_vesting_withdraw_operation, proposal_virtual_operation, budget_outgo_operation, budget_owner_income_operation, active_sp_holders_reward_legacy_operation, budget_closing_operation, bets_matched_operation, game_status_changed_operation, bet_resolved_operation, bet_cancelled_operation, bet_restored_operation, bet_updated_operation > operation
fc::fixed_string_16 account_name_type
static_variant< void_t, version, hardfork_version_vote > block_header_extensions
fc::ripemd160 block_id_type
bool is_virtual_operation(const operation &op)
chain_id_type initial_chain_id
time_point_sec initial_timestamp
std::vector< signed_transaction > transactions
checksum_type calculate_merkle_root() const
void verify_authority(const chain_id_type &chain_id, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
transaction_id_type id() const
std::vector< operation > operations
fc::time_point_sec expiration
uint32_t ref_block_prefix