34#include <boost/filesystem.hpp>
35#include <boost/range/adaptor/reversed.hpp>
60#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
61#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "blockchain"
63#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100*1024*1024)
65#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100*1024*1024)
84#define MERROR_VER(x) MCERROR("verify", x)
87#define BLOCK_REWARD_OVERESTIMATE (10 * 1000000000000)
94} mainnet_hard_forks[] = {
96 { 1, 1, 0, 1341378000 },
97 { 6, 307500, 0, 1538815057 },
98 { 7, 324500, 0, 1538985600 },
99 { 8, 589169, 0, 1562547600 },
100 { 9, 862866, 0, 1595615809 },
101 { 10, 1175315, 0, 1632999041 },
102 { 11, 1811310, 0, 1709652642 },
104static const uint64_t mainnet_hard_fork_version_1_till = 307499;
111} testnet_hard_forks[] = {
113 { 1, 1, 0, 1341378000 },
114 { 6, 190060, 0, 1523263057 },
115 { 7, 215000, 0, 1530615600 },
116 { 8, 446674, 0, 1562889600 },
117 { 9, 707121, 0, 1595615809 },
118 { 10, 1086402, 0, 1631789441 },
119 { 11, 1455270, 0, 1693256672 }
121static const uint64_t testnet_hard_fork_version_1_till = 190059;
128} stagenet_hard_forks[] = {
130 { 1, 1, 0, 1341378000 },
133 { 2, 32000, 0, 1521000000 },
134 { 3, 33000, 0, 1521120000 },
135 { 4, 34000, 0, 1521240000 },
136 { 5, 35000, 0, 1521360000 },
137 { 6, 36000, 0, 1521480000 },
138 { 7, 37000, 0, 1521600000 },
139 { 8, 38000, 0, 1521800000 },
140 { 9, 39000, 0, 1522000000 },
141 { 10, 1086402, 0, 1631789441 },
147 m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
148 m_enforce_dns_checkpoints(
false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(
true), m_db_sync_threshold(1), m_db_sync_mode(
db_async), m_db_default_sync(
false), m_fast_sync(
true), m_show_time_stats(
false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(
false),
150 m_long_term_effective_median_block_weight(0),
151 m_long_term_block_weights_cache_tip_hash(
crypto::null_hash),
153 m_difficulty_for_next_block_top_hash(
crypto::null_hash),
154 m_difficulty_for_next_block(1),
156 m_batch_success(
true)
164 catch (
const std::exception &e) { }
174 return m_db->tx_exists(
id);
184 return m_db->has_key_image(key_im);
190template <
class visitor_t>
191bool Blockchain::scan_outputkeys_for_indexes(
size_t tx_version,
const txin_to_key& tx_in_to_key, visitor_t &vis,
const crypto::hash &tx_prefix_hash,
uint64_t* pmax_related_block_height)
const
207 std::vector<output_data_t> outputs;
210 auto it = m_scan_table.find(tx_prefix_hash);
211 if (it != m_scan_table.end())
213 auto its = it->second.find(tx_in_to_key.
k_image);
214 if (its != it->second.end())
216 outputs = its->second;
225 m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.
amount, 1), absolute_offsets, outputs,
true);
226 if (absolute_offsets.size() != outputs.size())
241 if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
243 MDEBUG(
"Additional outputs needed: " << absolute_offsets.size() - outputs.size());
244 std::vector < uint64_t > add_offsets;
245 std::vector<output_data_t> add_outputs;
246 add_outputs.reserve(absolute_offsets.size() - outputs.size());
247 for (
size_t i = outputs.size(); i < absolute_offsets.size(); i++)
248 add_offsets.push_back(absolute_offsets[i]);
251 m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.
amount, 1), add_offsets, add_outputs,
true);
252 if (add_offsets.size() != add_outputs.size())
263 outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
268 for (
const uint64_t& i : absolute_offsets)
272 output_data_t output_index;
276 if (count < outputs.size())
277 output_index = outputs.at(count);
279 output_index = m_db->get_output_key(tx_in_to_key.
amount, i);
284 MERROR_VER(
"Failed to handle_output for output no = " << count <<
", with absolute offset " << i);
290 MERROR_VER(
"Output does not exist! amount = " << tx_in_to_key.
amount <<
", absolute_offset = " << i);
295 if(++count == absolute_offsets.size() && pmax_related_block_height)
298 auto h = output_index.
height;
299 if(*pmax_related_block_height < h)
301 *pmax_related_block_height = h;
306 catch (
const OUTPUT_DNE& e)
311 catch (
const TX_DNE& e)
329 return m_db->height();
345 LOG_ERROR(
"Attempted to init Blockchain with null DB");
350 LOG_ERROR(
"Attempted to init Blockchain with unopened DB");
359 m_fixed_difficulty = fixed_difficulty;
360 m_ignore_bsig = ignore_bsig;
361 m_fallback_to_pow = fallback_to_pow;
362 if (m_hardfork ==
nullptr)
365 m_hardfork =
new HardFork(*db, 1, 0);
367 m_hardfork =
new HardFork(*db, 1, testnet_hard_fork_version_1_till);
369 m_hardfork =
new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
378 for (
size_t n = 0; n <
sizeof(testnet_hard_forks) /
sizeof(testnet_hard_forks[0]); ++n)
379 m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
383 for (
size_t n = 0; n <
sizeof(stagenet_hard_forks) /
sizeof(stagenet_hard_forks[0]); ++n)
384 m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
388 for (
size_t n = 0; n <
sizeof(mainnet_hard_forks) /
sizeof(mainnet_hard_forks[0]); ++n)
389 m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
393 m_db->set_hard_fork(m_hardfork);
401 MINFO(
"Blockchain not loaded, generating genesis block.");
417 m_db->set_batch_transactions(
true);
423 uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
424 uint64_t timestamp_diff =
time(NULL) - top_block_timestamp;
427 if(!top_block_timestamp)
428 timestamp_diff =
time(NULL) - 1397818133;
432 m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (
new boost::asio::io_service::work(m_async_service));
434 m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
436#if defined(PER_BLOCK_CHECKPOINT)
438 load_compiled_in_block_hashes(get_checkpoints);
446 while (!m_db->is_read_only())
449 const crypto::hash top_id = m_db->top_block_hash(&top_height);
450 const block top_block = m_db->get_top_block();
452 if (ideal_hf_version <= 1 || ideal_hf_version == top_block.
major_version)
454 if (num_popped_blocks > 0)
455 MGINFO(
"Initial popping done, top block: " << top_id <<
", top height: " << top_height <<
", block version: " << (
uint64_t)top_block.
major_version);
460 if (num_popped_blocks == 0)
461 MGINFO(
"Current top block " << top_id <<
" at height " << top_height <<
" has version " << (
uint64_t)top_block.
major_version <<
" which disagrees with the ideal version " << (
uint64_t)ideal_hf_version);
462 if (num_popped_blocks % 100 == 0)
463 MGINFO(
"Popping blocks... " << top_height);
466 std::vector<transaction> popped_txs;
469 m_db->pop_block(popped_block, popped_txs);
473 catch (
const std::exception& e)
475 MERROR(
"Error popping block from blockchain: " << e.what());
480 MERROR(
"Error popping block from blockchain, throwing!");
486 if (num_popped_blocks > 0)
488 m_timestamps_and_difficulties_height = 0;
492 m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
503 if (!update_next_cumulative_weight_limit())
508 if(!m_db->is_read_only())
511 m_db->top_block_hash(&top_height);
513 if(top_height >= 1175315)
515 block b = m_db->get_block_from_height(1175315);
516 const auto &txout = boost::get<txout_to_key_public>(b.
miner_tx.
vout[0].target);
517 std::vector<cryptonote::address_outputs> addr_outs = m_db->get_addr_output_all(
addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
519 if(addr_outs.empty()) {
520 MGINFO(
"Recomputing address_outputs database...");
521 m_db->top_block_hash(&top_height);
522 uint64_t diff = top_height - 1175200;
523 for(
auto i = 0; i < diff; i++) {
525 std::vector<transaction> popped_txs;
528 m_db->pop_block(popped_block, popped_txs);
530 catch (
const std::exception& e)
532 MERROR(
"Error popping block from blockchain: " << e.what());
537 MERROR(
"Error popping block from blockchain, throwing!");
546 m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
548 MGINFO(
"Address_outputs database recomputed OK");
557 if(!m_db->is_read_only())
560 m_db->top_block_hash(&top_height);
561 uint64_t private_to_public_fork_height = m_nettype ==
MAINNET ? 1175315 : 1086402;
562 if(top_height >= private_to_public_fork_height)
564 block b = m_db->get_block_from_height(private_to_public_fork_height);
565 const auto &txout = boost::get<txout_to_key_public>(b.
miner_tx.
vout[0].target);
566 std::vector<cryptonote::address_txs> addr_txs = m_db->get_addr_tx_all(
addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
567 if(addr_txs.empty()) {
568 MGINFO(
"Populating addr tx database...");
569 m_db->top_block_hash(&top_height);
571 uint64_t working_height = private_to_public_fork_height;
572 while (working_height <= top_height) {
573 block working_block = m_db->get_block_from_height(working_height);
576 const auto &txout = boost::get<txout_to_key_public>(vout.target);
581 std::vector<transaction> transactions = m_db->get_tx_list(working_block.
tx_hashes);
582 for (
auto tx : transactions){
584 std::unordered_set<crypto::public_key> addr_tx_addresses;
585 for (
size_t i = 0; i < tx.vin.size(); i++){
588 const auto &txin = boost::get<txin_to_key_public>(tx.vin[i]);
589 transaction parent_tx = m_db->get_tx(txin.tx_hash);
590 const auto &txout = boost::get<txout_to_key_public>(parent_tx.
vout[txin.relative_offset].target);
592 if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){
593 m_db->add_addr_tx(
hash, combined_key);
594 addr_tx_addresses.emplace(combined_key);
598 for(
size_t i = 0; i < tx.vout.size(); i++){
599 const auto &txout = boost::get<txout_to_key_public>(tx.vout[i].target);
601 if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){
602 m_db->add_addr_tx(tx.hash, combined_key);
603 addr_tx_addresses.emplace(combined_key);
609 MGINFO(
"Addr_txs database recomputed OK");
624 bool res =
init(db, nettype, offline, NULL);
643 catch (
const std::exception& e)
645 MERROR(std::string(
"Error syncing blockchain db: ") + e.what() +
"-- shutting down now to prevent issues!");
650 MERROR(
"There was an issue storing the blockchain, shutting down now to prevent issues!");
655 if(m_show_time_stats)
656 MINFO(
"Blockchain stored OK, took: " << save <<
" ms");
664 MTRACE(
"Stopping blockchain read/write activity");
667 m_async_work_idle.reset();
668 m_async_pool.join_all();
669 m_async_service.stop();
679 MTRACE(
"Local blockchain read/write activity stopped successfully");
682 catch (
const std::exception& e)
684 LOG_ERROR(std::string(
"Error closing blockchain db: ") + e.what());
688 LOG_ERROR(
"There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
706 bool stop_batch = m_db->batch_start();
710 const uint64_t blockchain_height = m_db->height();
711 if (blockchain_height > 0)
712 nblocks = std::min(nblocks, blockchain_height - 1);
713 for (i=0; i < nblocks; ++i)
715 pop_block_from_blockchain();
718 catch (
const std::exception& e)
720 LOG_ERROR(
"Error when popping blocks after processing " << i <<
" blocks: " << e.what());
733block Blockchain::pop_block_from_blockchain()
738 m_timestamps_and_difficulties_height = 0;
741 std::vector<transaction> popped_txs;
747 m_db->pop_block(popped_block, popped_txs);
751 catch (
const std::exception& e)
753 LOG_ERROR(
"Error popping block from blockchain: " << e.what());
758 LOG_ERROR(
"Error popping block from blockchain, throwing!");
763 m_hardfork->on_block_popped(1);
767 for (transaction& tx : popped_txs)
776 cryptonote::tx_verification_context tvc =
AUTO_VAL_INIT(tvc);
788 bool r = m_tx_pool.add_tx(tx, tvc,
true,
true,
false,
version);
791 LOG_ERROR(
"Error returning transaction to tx_pool");
796 MWARNING(pruned <<
" pruned txes could not be added back to the txpool");
798 m_blocks_longhash_table.clear();
799 m_scan_table.clear();
800 m_blocks_txs_check.clear();
801 m_check_txin_table.clear();
806 m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
807 invalidate_block_template_cache();
816 m_timestamps_and_difficulties_height = 0;
817 m_alternative_chains.clear();
818 invalidate_block_template_cache();
825 if (!update_next_cumulative_weight_limit())
834 return m_db->top_block_hash(&
height);
844 return m_db->top_block_hash();
871 bool genesis_included =
false;
873 while(current_back_offset < sz)
875 ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
877 if(sz-current_back_offset == 0)
879 genesis_included =
true;
883 ++current_back_offset;
887 current_multiplier *= 2;
888 current_back_offset += current_multiplier;
893 if (!genesis_included)
895 ids.push_back(m_db->get_block_hash_from_height(0));
910 return m_db->get_block_hash_from_height(
height);
915 catch (
const std::exception& e)
917 MERROR(std::string(
"Something went wrong fetching block hash by height: ") + e.
what());
922 MERROR(std::string(
"Something went wrong fetching block hash by height"));
936 blk = m_db->get_block(h);
944 blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
945 if (m_alternative_chains.end() != it_alt)
947 blk = it_alt->second.bl;
953 catch (
const std::exception& e)
955 MERROR(std::string(
"Something went wrong fetching block by hash: ") + e.
what());
960 MERROR(std::string(
"Something went wrong fetching block hash by hash"));
973 if (m_fixed_difficulty)
975 return m_db->height() ? m_fixed_difficulty : 1;
987 if (top_hash == m_difficulty_for_next_block_top_hash)
988 return m_difficulty_for_next_block;
992 std::vector<uint64_t> timestamps;
993 std::vector<difficulty_type> difficulties;
998 uint64_t v6height = 0, v7height = 0, v8height = 0;
1000 v6height = mainnet_hard_forks[1].height;
1001 v7height = mainnet_hard_forks[2].height;
1002 v8height = mainnet_hard_forks[3].height;
1003 }
else if(m_nettype ==
TESTNET) {
1004 v6height = testnet_hard_forks[1].height;
1005 v7height = testnet_hard_forks[2].height;
1006 v8height = testnet_hard_forks[3].height;
1008 v6height = stagenet_hard_forks[5].height;
1009 v7height = stagenet_hard_forks[5].height;
1010 v8height = stagenet_hard_forks[5].height;
1012 MERROR(std::string(
"Something went wrong defining the network type."));
1024 m_timestamps.clear();
1025 m_difficulties.clear();
1027 difficultyBlocksCount =
height - v8height;
1036 if (m_timestamps_and_difficulties_height != 0 && ((
height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficultyBlocksCount)
1039 m_timestamps.push_back(m_db->get_block_timestamp(index));
1040 m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
1042 while (m_timestamps.size() > difficultyBlocksCount)
1043 m_timestamps.erase(m_timestamps.begin());
1044 while (m_difficulties.size() > difficultyBlocksCount)
1045 m_difficulties.erase(m_difficulties.begin());
1047 m_timestamps_and_difficulties_height =
height;
1048 timestamps = m_timestamps;
1049 difficulties = m_difficulties;
1058 difficulties.clear();
1061 timestamps.reserve(
height - offset);
1062 difficulties.reserve(
height - offset);
1064 for (; offset <
height; offset++)
1066 timestamps.push_back(m_db->get_block_timestamp(offset));
1067 difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
1070 m_timestamps_and_difficulties_height =
height;
1071 m_timestamps = timestamps;
1072 m_difficulties = difficulties;
1079 m_difficulty_for_next_block_top_hash = top_hash;
1080 m_difficulty_for_next_block = diff;
1089 std::vector<time_t> timestamps(
blocks);
1100 auto height = m_db->height();
1108 const size_t V7_DIFFICULTY_BLOCKS_COUNT = 735;
1109 const size_t V7_DIFFICULTY_TARGET = 120;
1111 std::vector<uint64_t> timestamps;
1112 std::vector<difficulty_type> difficulties;
1114 uint64_t start_height = v7height - V7_DIFFICULTY_BLOCKS_COUNT;
1117 for(
uint64_t i = 0; start_height + i < v7height; i++) {
1118 timestamps.push_back(m_db->get_block_timestamp(start_height + i));
1119 difficulties.push_back(m_db->get_block_cumulative_difficulty(start_height + i));
1126 m_db->set_block_cumulative_difficulty(v7height, diff);
1132 timestamps.push_back(m_db->get_block_timestamp(i));
1133 difficulties.push_back(m_db->get_block_cumulative_difficulty(i));
1136 timestamps.erase(timestamps.begin());
1137 difficulties.erase(difficulties.begin());
1140 diff = difficulties.back() +
next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1141 m_db->set_block_cumulative_difficulty(i + 1, diff);
1144 m_timestamps.clear();
1145 m_difficulties.clear();
1152bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
uint64_t rollback_height)
1158 if (rollback_height > m_db->
height())
1163 m_timestamps_and_difficulties_height = 0;
1166 while (m_db->
height() != rollback_height)
1168 pop_block_from_blockchain();
1172 m_hardfork->reorganize_from_chain_height(rollback_height);
1175 for (
auto& bl : original_chain)
1177 block_verification_context bvc = boost::value_initialized<block_verification_context>();
1178 bool r = handle_block_to_main_chain(bl, bvc);
1182 m_hardfork->reorganize_from_chain_height(rollback_height);
1184 MINFO(
"Rollback to height " << rollback_height <<
" was successful.");
1185 if (!original_chain.empty())
1187 MINFO(
"Restoration to previous blockchain successful as well.");
1194bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::const_iterator>& alt_chain,
bool discard_disconnected_chain)
1200 m_timestamps_and_difficulties_height = 0;
1203 CHECK_AND_ASSERT_MES(alt_chain.size(),
false,
"switch_to_alternative_blockchain: empty chain passed");
1206 if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
1208 LOG_ERROR(
"Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!");
1214 std::list<block> disconnected_chain;
1215 while (m_db->top_block_hash() != alt_chain.front()->second.bl.prev_id)
1217 block b = pop_block_from_blockchain();
1218 disconnected_chain.push_front(b);
1221 auto split_height = m_db->height();
1224 for(
auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++)
1226 auto ch_ent = *alt_ch_iter;
1227 block_verification_context bvc = boost::value_initialized<block_verification_context>();
1230 bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
1236 MERROR(
"Failed to switch to alternative blockchain");
1241 rollback_blockchain_switching(disconnected_chain, split_height);
1246 add_block_as_invalid(ch_ent->second,
get_block_hash(ch_ent->second.bl));
1247 MERROR(
"The block was inserted as invalid while connecting new alternative chain, block_id: " <<
get_block_hash(ch_ent->second.bl));
1248 m_alternative_chains.erase(*alt_ch_iter++);
1250 for(
auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); )
1252 add_block_as_invalid((*alt_ch_to_orph_iter)->second, (*alt_ch_to_orph_iter)->first);
1253 m_alternative_chains.erase(*alt_ch_to_orph_iter++);
1260 const size_t discarded_blocks = disconnected_chain.size();
1261 if(!discard_disconnected_chain)
1264 for (
auto& old_ch_ent : disconnected_chain)
1266 block_verification_context bvc = boost::value_initialized<block_verification_context>();
1267 bool r = handle_alternative_block(old_ch_ent,
get_block_hash(old_ch_ent), bvc);
1270 MERROR(
"Failed to push ex-main chain blocks to alternative chain ");
1278 for (
auto ch_ent: alt_chain)
1280 m_alternative_chains.erase(ch_ent);
1283 m_hardfork->reorganize_from_chain_height(split_height);
1285 std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
1287 reorg_notify->notify(
"%s", std::to_string(split_height).c_str(),
"%h", std::to_string(m_db->height()).c_str(),
1288 "%n", std::to_string(m_db->height() - split_height).c_str(),
"%d", std::to_string(discarded_blocks).c_str(), NULL);
1290 MGINFO_GREEN(
"REORGANIZE SUCCESS! on height: " << split_height <<
", new blockchain size: " << m_db->height());
1296difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(
const std::list<blocks_ext_by_hash::const_iterator>& alt_chain, block_extended_info& bei)
const
1298 if (m_fixed_difficulty)
1300 return m_db->height() ? m_fixed_difficulty : 1;
1304 std::vector<uint64_t> timestamps;
1305 std::vector<difficulty_type> cumulative_difficulties;
1307 uint64_t v6height = 0, v7height = 0, v8height = 0;
1310 v6height = mainnet_hard_forks[1].height;
1311 v7height = mainnet_hard_forks[2].height;
1312 v8height = mainnet_hard_forks[3].height;
1313 }
else if(m_nettype ==
TESTNET) {
1314 v6height = testnet_hard_forks[1].height;
1315 v7height = testnet_hard_forks[2].height;
1316 v8height = testnet_hard_forks[3].height;
1318 v6height = stagenet_hard_forks[5].height;
1319 v7height = stagenet_hard_forks[5].height;
1320 v8height = stagenet_hard_forks[5].height;
1322 MERROR(std::string(
"Something went wrong defining the network type."));
1328 if((bei.height >= v8height) && (bei.height < v8height + 720))
1331 difficultyBlocksCount = bei.height - v8height;
1336 if(alt_chain.size()< difficultyBlocksCount)
1342 size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height;
1344 size_t main_chain_count = difficultyBlocksCount - std::min(
static_cast<size_t>(difficultyBlocksCount), alt_chain.size());
1347 main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
1349 size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
1351 if(!main_chain_start_offset)
1352 ++main_chain_start_offset;
1355 for(; main_chain_start_offset < main_chain_stop_offset; ++main_chain_start_offset)
1357 timestamps.push_back(m_db->get_block_timestamp(main_chain_start_offset));
1358 cumulative_difficulties.push_back(m_db->get_block_cumulative_difficulty(main_chain_start_offset));
1362 CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= difficultyBlocksCount,
false,
"Internal error, alt_chain.size()[" << alt_chain.size() <<
"] + vtimestampsec.size()[" << timestamps.size() <<
"] NOT <= DIFFICULTY_WINDOW[]" << difficultyBlocksCount);
1364 for (
auto it : alt_chain)
1366 timestamps.push_back(it->second.bl.timestamp);
1367 cumulative_difficulties.push_back(it->second.cumulative_difficulty);
1374 timestamps.resize(
static_cast<size_t>(difficultyBlocksCount));
1375 cumulative_difficulties.resize(
static_cast<size_t>(difficultyBlocksCount));
1377 size_t max_i = timestamps.size()-1;
1379 for(
auto it: boost::adaptors::reverse(alt_chain))
1381 timestamps[max_i -
count] = it->second.bl.timestamp;
1382 cumulative_difficulties[max_i -
count] = it->second.cumulative_difficulty;
1384 if(count >= difficultyBlocksCount)
1392 const uint8_t version = m_hardfork->get_ideal_version(bei.height);
1409 MWARNING(
"The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.
miner_tx.
vin[0]).height <<
", expected: " <<
height);
1433 std::string coinbase_burn_address_viewkey_hex_str =
"5866666666666666666666666666666666666666666666666666666666666666";
1434 std::string coinbase_burn_address_spendkey_hex_str =
"9511fabcb699b4f9dffc1779713d0dd7eb1ca56ba5b8ab8d3253a0a6ccf736b3";
1436 const auto out = boost::get<txout_to_key_public>(o.target);
1439 if(out_spendkey_str != coinbase_burn_address_spendkey_hex_str || out_viewkey_str != coinbase_burn_address_viewkey_hex_str){
1440 MERROR_VER(
"v11 miner tx output " <<
print_etn(o.amount) <<
" is being sent to an address other than the burn address");
1450 etn_in_use += o.amount;
1451 partial_block_reward =
false;
1456 MERROR_VER(
"miner tx output " <<
print_etn(o.amount) <<
" is not a valid decomposed amount");
1462 std::vector<uint64_t> last_blocks_weights;
1466 MERROR_VER(
"block weight " << cumulative_block_weight <<
" is bigger than allowed for this blockchain");
1469 if(base_reward + fee < etn_in_use && already_generated_coins > 0)
1477 if(base_reward + fee != etn_in_use && already_generated_coins > 0)
1479 MDEBUG(
"coinbase transaction doesn't use full amount of block reward: spent: " << etn_in_use <<
", block reward " << base_reward + fee <<
"(" << base_reward <<
"+" << fee <<
")");
1489 if(base_reward + fee != etn_in_use)
1490 partial_block_reward =
true;
1491 base_reward = etn_in_use - fee;
1497void Blockchain::get_last_n_blocks_weights(std::vector<uint64_t>& weights,
size_t count)
const
1501 auto h = m_db->height();
1508 size_t start_offset = h - std::min<size_t>(h, count);
1509 weights = m_db->get_block_weights(start_offset, count);
1512uint64_t Blockchain::get_long_term_block_weight_median(
uint64_t start_height,
size_t count)
const
1521 bool cached =
false;
1522 uint64_t blockchain_height = m_db->height();
1525 if (tip_height < blockchain_height && count == (
size_t)m_long_term_block_weights_cache_rolling_median.size())
1527 tip_hash = m_db->get_block_hash_from_height(tip_height);
1528 cached = tip_hash == m_long_term_block_weights_cache_tip_hash;
1533 MTRACE(
"requesting " << count <<
" from " << start_height <<
", cached");
1534 return m_long_term_block_weights_cache_rolling_median.median();
1539 if (tip_height > 0 && count == (
size_t)m_long_term_block_weights_cache_rolling_median.size() && tip_height < blockchain_height)
1541 crypto::hash old_tip_hash = m_db->get_block_hash_from_height(tip_height - 1);
1542 if (old_tip_hash == m_long_term_block_weights_cache_tip_hash)
1544 MTRACE(
"requesting " << count <<
" from " << start_height <<
", incremental");
1545 m_long_term_block_weights_cache_tip_hash = tip_hash;
1546 m_long_term_block_weights_cache_rolling_median.insert(m_db->get_block_long_term_weight(tip_height));
1547 return m_long_term_block_weights_cache_rolling_median.median();
1551 MTRACE(
"requesting " << count <<
" from " << start_height <<
", uncached");
1552 std::vector<uint64_t> weights = m_db->get_long_term_block_weights(start_height, count);
1553 m_long_term_block_weights_cache_tip_hash = tip_hash;
1554 m_long_term_block_weights_cache_rolling_median.clear();
1556 m_long_term_block_weights_cache_rolling_median.insert(w);
1557 return m_long_term_block_weights_cache_rolling_median.median();
1563 return m_current_block_cumul_weight_limit;
1569 return m_current_block_cumul_weight_median;
1586 size_t median_weight;
1593 if (m_btc_valid && !from_block) {
1599 && m_btc_pool_cookie == m_tx_pool.cookie() && m_btc.prev_id ==
get_tail_id()) {
1600 MDEBUG(
"Using cached template");
1601 m_btc.timestamp =
time(NULL);
1603 diffic = m_btc_difficulty;
1605 expected_reward = m_btc_expected_reward;
1608 MDEBUG(
"Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address,
sizeof(
cryptonote::account_public_address))) <<
", nonce " << (m_btc_nonce == ex_nonce) <<
", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()) <<
", from_block " << (!!from_block));
1609 invalidate_block_template_cache();
1617 auto it_prev = m_alternative_chains.find(*from_block);
1618 bool parent_in_main = m_db->block_exists(*from_block);
1619 if(it_prev == m_alternative_chains.end() && !parent_in_main)
1621 MERROR(
"Unknown from block");
1626 std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1628 std::vector<uint64_t> timestamps;
1629 if (!build_alt_chain(*from_block, alt_chain, timestamps, bvc))
1637 height = from_block_height + 1;
1641 height = alt_chain.back()->second.height + 1;
1651 median_weight = m_db->get_block_weight(
height - 1);
1652 already_generated_coins = m_db->get_block_already_generated_coins(
height - 1);
1656 median_weight = it_prev->second.block_cumulative_weight - it_prev->second.block_cumulative_weight / 20;
1657 already_generated_coins = alt_chain.back()->second.already_generated_coins;
1663 bei.
height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(*from_block) + 1;
1665 diffic = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1673 median_weight = m_current_block_cumul_weight_limit / 2;
1675 already_generated_coins = m_db->get_block_already_generated_coins(
height - 1);
1680 if (!check_block_timestamp(b, median_ts))
1689 if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.
major_version))
1694#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1695 size_t real_txs_weight = 0;
1699 auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
1700 if (cur_res == m_tx_pool.m_transactions.end())
1702 LOG_ERROR(
"Creating block template: error: transaction not found");
1706 real_txs_weight += cur_tx.
weight;
1707 real_fee += cur_tx.
fee;
1710 LOG_ERROR(
"Creating block template: error: invalid transaction weight");
1716 LOG_ERROR(
"Creating block template: error: cannot get inputs amount");
1720 LOG_ERROR(
"Creating block template: error: invalid fee");
1723 if (txs_weight != real_txs_weight)
1725 LOG_ERROR(
"Creating block template: error: wrongly calculated transaction weight");
1727 if (fee != real_fee)
1729 LOG_ERROR(
"Creating block template: error: wrongly calculated fee");
1732 ", median weight " << median_weight <<
1733 ", already generated coins " << already_generated_coins <<
1734 ", transaction weight " << txs_weight <<
1744 size_t max_outs = hf_version >= 4 ? 1 : 11;
1745 bool r =
construct_miner_tx(
height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.
miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1748#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1750 ", cumulative weight " << cumulative_weight);
1752 for (
size_t try_count = 0; try_count != 10; ++try_count)
1754 r =
construct_miner_tx(
height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.
miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1758 if (coinbase_weight > cumulative_weight - txs_weight)
1760 cumulative_weight = txs_weight + coinbase_weight;
1761#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1762 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1763 ", cumulative weight " << cumulative_weight <<
" is greater than before");
1768 if (coinbase_weight < cumulative_weight - txs_weight)
1770 size_t delta = cumulative_weight - txs_weight - coinbase_weight;
1771#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1772 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1773 ", cumulative weight " << txs_weight + coinbase_weight <<
1774 " is less than before, adding " << delta <<
" zero bytes");
1785 MDEBUG(
"Miner tx creation has no luck with delta_extra size = " << delta <<
" and " << delta - 1);
1786 cumulative_weight += delta - 1;
1789 MDEBUG(
"Setting extra for block: " << b.
miner_tx.
extra.size() <<
", try_count=" << try_count);
1793#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1794 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1795 ", cumulative weight " << cumulative_weight <<
" is now good");
1801 if(!m_fallback_to_pow && hf_version >= 8) {
1807 LOG_ERROR(
"Failed to create_block_template with " << 10 <<
" tries");
1816 LOG_ERROR(
"The daemon has failed to digitally sign a block and therefore it cannot be accepted by the network. Please check your validator-key configuration before resuming mining.");
1825 const std::vector<std::string> public_keys = m_validators->getApplicablePublicKeys(m_db->height(),
true);
1827 for(
auto &
key : public_keys) {
1828 if(
crypto::verify_signature(std::string(
reinterpret_cast<char const *
>(tx_tree_hash.data),
sizeof(tx_tree_hash.data)),
1845bool Blockchain::complete_timestamps_vector(
uint64_t start_top_height, std::vector<uint64_t>& timestamps)
const
1854 CHECK_AND_ASSERT_MES(start_top_height < m_db->
height(),
false,
"internal error: passed start_height not < " <<
" m_db->height() -- " << start_top_height <<
" >= " << m_db->
height());
1855 size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
1856 timestamps.reserve(timestamps.size() + start_top_height - stop_offset);
1857 while (start_top_height != stop_offset)
1865bool Blockchain::build_alt_chain(
const crypto::hash &prev_id, std::list<blocks_ext_by_hash::const_iterator>& alt_chain, std::vector<uint64_t> ×tamps,
block_verification_context& bvc)
const
1868 blocks_ext_by_hash::const_iterator alt_it = m_alternative_chains.find(prev_id);
1870 while(alt_it != m_alternative_chains.end())
1872 alt_chain.push_front(alt_it);
1873 timestamps.push_back(alt_it->second.bl.timestamp);
1874 alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id);
1879 if(!alt_chain.empty())
1882 CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height,
false,
"main blockchain wrong height");
1886 if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
1888 MERROR(
"alternate chain does not appear to connect to main chain...");
1893 auto h = m_db->get_block_hash_from_height(alt_chain.front()->second.height - 1);
1894 CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id,
false,
"alternative chain has wrong connection to main chain");
1895 complete_timestamps_vector(m_db->get_block_height(alt_chain.front()->second.bl.prev_id), timestamps);
1902 bool parent_in_main = m_db->block_exists(prev_id);
1903 CHECK_AND_ASSERT_MES(parent_in_main,
false,
"internal error: broken imperative condition: parent_in_main");
1905 complete_timestamps_vector(m_db->get_block_height(prev_id), timestamps);
1921 m_timestamps_and_difficulties_height = 0;
1923 if(0 == block_height)
1932 if(!m_fallback_to_pow) {
1934 if(!m_validators->isEnabled()) {
1935 m_validators->enable();
1938 if(!m_validators->isValid()) {
1944 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has wrong digital signature");
1957 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" can't be accepted for alternative chain, block height: " << block_height << std::endl <<
" blockchain height: " <<
get_current_blockchain_height());
1963 if (!m_hardfork->check_for_height(b, block_height))
1965 LOG_PRINT_L1(
"Block with id: " <<
id << std::endl <<
"has old version for height " << block_height);
1972 auto it_prev = m_alternative_chains.find(b.
prev_id);
1973 bool parent_in_main = m_db->block_exists(b.
prev_id);
1974 if(it_prev != m_alternative_chains.end() || parent_in_main)
1977 std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1978 std::vector<uint64_t> timestamps;
1979 if (!build_alt_chain(b.
prev_id, alt_chain, timestamps, bvc))
1985 const uint64_t prev_height = alt_chain.size() ? it_prev->second.height : m_db->get_block_height(b.
prev_id);
1986 bei.height = prev_height + 1;
1988 bei.already_generated_coins = block_reward + (alt_chain.size() ? it_prev->second.already_generated_coins : m_db->get_block_already_generated_coins(prev_height));
1992 std::vector<uint8_t> prev_signatory = alt_chain.size() ? it_prev->second.bl.signatory : m_db->get_block(b.
prev_id).signatory;
1998 if(!check_block_timestamp(timestamps, b))
2000 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" for alternative chain, has invalid timestamp: " << b.
timestamp);
2005 bool is_a_checkpoint;
2006 if(!m_checkpoints.check_block(bei.height,
id, is_a_checkpoint))
2008 LOG_ERROR(
"CHECKPOINT VALIDATION FAILED");
2014 difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
2020 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl <<
" expected difficulty: " << current_diff);
2025 if(!prevalidate_miner_transaction(b, bei.height))
2035 difficulty_type main_chain_cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->height() - 1);
2036 if (alt_chain.size())
2038 bei.cumulative_difficulty = it_prev->second.cumulative_difficulty;
2043 bei.cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->get_block_height(b.
prev_id));
2045 bei.cumulative_difficulty += current_diff;
2049 auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(
id, bei));
2050 CHECK_AND_ASSERT_MES(i_res.second,
false,
"insertion of new alternative block returned as it already exist");
2051 alt_chain.push_back(i_res.first);
2057 MGINFO_GREEN(
"###### REORGANIZE on height: " << alt_chain.front()->second.height <<
" of " << m_db->height() - 1 <<
", checkpoint is found in alternative chain on height " << bei.height);
2059 bool r = switch_to_alternative_blockchain(alt_chain,
true);
2066 else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty)
2069 MGINFO_GREEN(
"###### REORGANIZE on height: " << alt_chain.front()->second.height <<
" of " << m_db->height() - 1 <<
" with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl <<
" alternative blockchain size: " << alt_chain.size() <<
" with cum_difficulty " << bei.cumulative_difficulty);
2071 bool r = switch_to_alternative_blockchain(alt_chain,
false);
2080 MGINFO_BLUE(
"----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl <<
"id:\t" <<
id << std::endl <<
"PoW:\t" << proof_of_work << std::endl <<
"difficulty:\t" << current_diff);
2088 MERROR_VER(
"Block recognized as orphaned and rejected, id = " <<
id <<
", height " << block_height
2089 <<
", parent in alt " << (it_prev != m_alternative_chains.end()) <<
", parent in main " << parent_in_main
2100 if(start_offset >= m_db->height())
2108 for(
const auto& blk :
blocks)
2110 std::vector<crypto::hash> missed_ids;
2112 CHECK_AND_ASSERT_MES(!missed_ids.size(),
false,
"has missed transactions in own block in main blockchain");
2123 if(start_offset >=
height)
2127 for(
size_t i = start_offset; i < start_offset + count && i <
height;i++)
2129 blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(i),
block()));
2152 std::vector<std::pair<cryptonote::blobdata,block>>
blocks;
2157 std::vector<crypto::hash> missed_tx_ids;
2166 if (missed_tx_ids.size() != 0)
2171 LOG_ERROR(
"Error retrieving blocks, missed " << missed_tx_ids.size()
2172 <<
" transactions for block with hash: " <<
get_block_hash(bl.second)
2180 rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
2185 e.
block = std::move(bl.first);
2198 blocks.reserve(m_alternative_chains.size());
2199 for (
const auto& alt_bl: m_alternative_chains)
2201 blocks.push_back(alt_bl.second.bl);
2210 return m_alternative_chains.size();
2217 uint64_t num_outs = m_db->get_num_outputs(amount);
2220 const uint64_t blockchain_height = m_db->height();
2221 while (num_outs > 0)
2223 const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
2235 output_data_t data = m_db->get_output_key(amount, global_index);
2246 res.outs.reserve(req.outputs.size());
2248 std::vector<cryptonote::output_data_t> data;
2251 std::vector<uint64_t> amounts, offsets;
2252 amounts.reserve(req.outputs.size());
2253 offsets.reserve(req.outputs.size());
2254 for (
const auto &i: req.outputs)
2256 amounts.push_back(i.amount);
2257 offsets.push_back(i.index);
2260 if (data.size() != req.outputs.size())
2262 MERROR(
"Unexpected output data size: expected " << req.outputs.size() <<
", got " << data.size());
2265 for (
const auto &t: data)
2266 res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
2270 for (
size_t i = 0; i < req.outputs.size(); ++i)
2272 tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index);
2273 res.outs[i].txid = toi.first;
2277 catch (
const std::exception &e)
2286 const auto o_data = m_db->get_output_key(amount, index);
2287 key = o_data.pubkey;
2288 mask = o_data.commitment;
2289 tx_out_index toi = m_db->get_output_tx_and_index(amount, index);
2290 unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
2300 case STAGENET: start_height = stagenet_hard_forks[3].height;
break;
2301 case TESTNET: start_height = testnet_hard_forks[3].height;
break;
2302 case MAINNET: start_height = mainnet_hard_forks[3].height;
break;
2303 case FAKECHAIN: start_height = 0;
break;
2304 default:
return false;
2311 if (to_height > 0 && to_height < from_height)
2314 const uint64_t real_start_height = start_height;
2315 if (from_height > start_height)
2316 start_height = from_height;
2318 distribution.clear();
2319 uint64_t db_height = m_db->height();
2322 if (start_height >= db_height || to_height >= db_height)
2326 std::vector<uint64_t> heights;
2327 heights.reserve(to_height + 1 - start_height);
2328 uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
2329 for (
uint64_t h = real_start_height; h <= to_height; ++h)
2330 heights.push_back(h);
2331 distribution = m_db->get_block_cumulative_rct_outputs(heights);
2332 if (start_height > 0)
2334 base = distribution[0];
2335 distribution.erase(distribution.begin());
2341 return m_db->get_output_distribution(amount, start_height, to_height, distribution, base);
2355 if(qblock_ids.empty())
2357 MCERROR(
"net.p2p",
"Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() <<
", dropping connection");
2364 auto gen_hash = m_db->get_block_hash_from_height(0);
2365 if(qblock_ids.back() != gen_hash)
2368 MCERROR(
"net.p2p",
"Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl <<
"id: " << qblock_ids.back() <<
", " << std::endl <<
"expected: " << gen_hash <<
"," << std::endl <<
" dropping connection");
2374 auto bl_it = qblock_ids.begin();
2376 for(; bl_it != qblock_ids.end(); bl_it++)
2380 if (m_db->block_exists(*bl_it, &split_height))
2383 catch (
const std::exception& e)
2385 MWARNING(
"Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
2392 if(bl_it == qblock_ids.end())
2394 MERROR(
"Internal error handling connection, can't find split point");
2399 starter_offset = split_height;
2412 return m_db->get_block_difficulty(i);
2416 MERROR(
"Attempted to get block difficulty for height above blockchain height");
2426template<
class t_
ids_container,
class t_blocks_container,
class t_missed_container>
2433 for (
const auto& block_hash : block_ids)
2438 if (m_db->block_exists(block_hash, &
height))
2440 blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(
height),
block()));
2443 LOG_ERROR(
"Invalid block: " << block_hash);
2445 missed_bs.push_back(block_hash);
2449 missed_bs.push_back(block_hash);
2451 catch (
const std::exception& e)
2461template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2468 for (
const auto& tx_hash : txs_ids)
2473 if (pruned && m_db->get_pruned_tx_blob(tx_hash, tx))
2474 txs.push_back(std::move(tx));
2475 else if (!pruned && m_db->get_tx_blob(tx_hash, tx))
2476 txs.push_back(std::move(tx));
2478 missed_txs.push_back(tx_hash);
2480 catch (
const std::exception& e)
2491 const char* begin =
static_cast<const char*
>(bd.data());
2492 const char* end = begin + bd.size();
2495 throw std::runtime_error(
"Internal error getting transaction version");
2499template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2506 for (
const auto& tx_hash : txs_ids)
2511 if (m_db->get_pruned_tx_blob(tx_hash, tx))
2513 txs.push_back(std::make_tuple(tx_hash, std::move(tx), crypto::null_hash,
cryptonote::blobdata()));
2514 if (!is_v1_tx(std::get<1>(txs.back())) && !m_db->get_prunable_tx_hash(tx_hash, std::get<2>(txs.back())))
2516 MERROR(
"Prunable data hash not found for " << tx_hash);
2519 if (!m_db->get_prunable_tx_blob(tx_hash, std::get<3>(txs.back())))
2520 std::get<3>(txs.back()).clear();
2523 missed_txs.push_back(tx_hash);
2525 catch (
const std::exception& e)
2533template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2540 for (
const auto& tx_hash : txs_ids)
2545 if (m_db->get_tx_blob(tx_hash, tx))
2555 missed_txs.push_back(tx_hash);
2557 catch (
const std::exception& e)
2581 uint64_t stop_height = current_height;
2592 hashes.push_back(m_db->get_block_hash_from_height(i));
2607 resp.cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
2608 resp.cumulative_difficulty_top64 = ((wide_cumulative_difficulty >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
2618bool Blockchain::find_blockchain_supplement(
const uint64_t req_start_block,
const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >&
blocks,
uint64_t& total_height,
uint64_t& start_height,
bool pruned,
bool get_miner_tx_hash,
size_t max_count)
const
2624 if(req_start_block > 0)
2627 if (req_start_block >= m_db->height())
2631 start_height = req_start_block;
2643 size_t count = 0, size = 0;
2644 blocks.reserve(std::min(std::min(max_count, (
size_t)10000), (
size_t)(total_height - start_height)));
2648 blocks.back().first.first = m_db->get_block_blob_from_height(i);
2652 std::vector<crypto::hash> mis;
2653 std::vector<cryptonote::blobdata> txs;
2656 size +=
blocks.back().first.first.size();
2657 for (
const auto &t: txs)
2661 blocks.back().second.reserve(txs.size());
2662 for (
size_t i = 0; i < txs.size(); ++i)
2664 blocks.back().second.push_back(std::make_pair(b.
tx_hashes[i], std::move(txs[i])));
2675 return add_block_as_invalid(bei, h);
2678bool Blockchain::add_block_as_invalid(
const block_extended_info& bei,
const crypto::hash& h)
2682 auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
2683 CHECK_AND_ASSERT_MES(i_res.second,
false,
"at insertion invalid by tx returned status existed");
2684 MINFO(
"BLOCK ADDED AS INVALID: " << h << std::endl <<
", prev_id=" << bei.bl.prev_id <<
", m_invalid_blocks count=" << m_invalid_blocks.size());
2693 if(m_db->block_exists(
id))
2695 LOG_PRINT_L2(
"block " <<
id <<
" found in main chain");
2699 if(m_alternative_chains.count(
id))
2701 LOG_PRINT_L2(
"block " <<
id <<
" found in m_alternative_chains");
2705 if(m_invalid_blocks.count(
id))
2707 LOG_PRINT_L2(
"block " <<
id <<
" found in m_invalid_blocks");
2718 return handle_block_to_main_chain(bl,
id, bvc);
2728 return m_db->get_tx_count();
2737bool Blockchain::check_for_double_spend(
const transaction& tx, key_images_container& keys_this_block)
const
2741 struct add_transaction_input_visitor:
public boost::static_visitor<bool>
2743 key_images_container& m_spent_keys;
2745 add_transaction_input_visitor(key_images_container& spent_keys,
BlockchainDB* db) :
2746 m_spent_keys(spent_keys), m_db(db)
2760 auto r = m_spent_keys.insert(ki);
2771 bool operator()(
const txin_gen& tx)
const
2775 bool operator()(
const txin_to_script& tx)
const
2779 bool operator()(
const txin_to_scripthash& tx)
const
2783 bool operator()(
const txin_to_key_public& tx)
const
2791 if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in))
2806 if (!m_db->tx_exists(tx_id, tx_index))
2808 MERROR_VER(
"get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2813 if (m_db->get_tx(tx_id).version >= 2)
2816 indexs = m_db->get_tx_amount_output_indices(tx_index, n_txes);
2827 if (!m_db->tx_exists(tx_id, tx_index))
2829 MERROR_VER(
"get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2834 if (m_db->get_tx(tx_id).version >= 2)
2837 std::vector<std::vector<uint64_t>> indices = m_db->get_tx_amount_output_indices(tx_index, 1);
2839 indexs = indices.front();
2845#if defined(PER_BLOCK_CHECKPOINT)
2847 if (m_db->height() < m_blocks_hash_check.size())
2852 if(m_show_time_stats)
2854 size_t ring_size = !tx.
vin.empty() && tx.
vin[0].type() ==
typeid(
txin_to_key) ? boost::get<txin_to_key>(tx.
vin[0]).key_offsets.size() : 0;
2855 MINFO(
"HASH: " <<
"-" <<
" I/M/O: " << tx.
vin.size() <<
"/" << ring_size <<
"/" << tx.
vout.size() <<
" H: " << 0 <<
" chcktx: " <<
a);
2874#if defined(PER_BLOCK_CHECKPOINT)
2876 if (m_db->
height() < m_blocks_hash_check.size() && kept_by_block)
2878 max_used_block_id = null_hash;
2879 max_used_block_height = 0;
2887 if(m_show_time_stats)
2889 size_t ring_size = !tx.
vin.empty() && tx.
vin[0].type() ==
typeid(
txin_to_key) ? boost::get<txin_to_key>(tx.
vin[0]).key_offsets.size() : 0;
2896 CHECK_AND_ASSERT_MES(max_used_block_height < m_db->
height(),
false,
"internal error: max used block index=" << max_used_block_height <<
" is not less then blockchain size = " << m_db->height());
2897 max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
2906 const uint8_t hf_version = m_hardfork->get_current_version();
2910 for (
auto &o: tx.
vout) {
2920 for (
const auto &o: tx.
vout) {
2923 const txout_to_key &out_to_key = boost::get<txout_to_key>(o.target);
2946 std::vector<uint64_t> supported_prefixes{address_prefix, integrated_address_prefix, subaddress_prefix};
2948 if(std::find(supported_prefixes.begin(), supported_prefixes.end(), out_to_key_public.
m_address_prefix) == supported_prefixes.end()) {
2966 const auto &in_to_key = boost::get<txin_to_key>(in);
2983 const auto &in_to_key = boost::get<txin_to_key_public>(in);
2984 if(!m_db->check_chainstate_utxo(in_to_key.tx_hash, in_to_key.relative_offset))
3002bool Blockchain::expand_transaction_2(
transaction &tx,
const crypto::hash &tx_prefix_hash,
const std::vector<std::vector<rct::ctkey>> &pubkeys)
3016 size_t sig_index = 0;
3017 if(pmax_used_block_height)
3018 *pmax_used_block_height = 0;
3026 if (tx.
version > max_tx_version)
3028 MERROR_VER(
"transaction version " << (
unsigned)tx.
version <<
" is higher than max accepted version " << max_tx_version);
3034 if (tx.
version < min_tx_version)
3036 MERROR_VER(
"transaction version " << (
unsigned)tx.
version <<
" is lower than min accepted version " << min_tx_version);
3045 std::unordered_set<std::string> ins;
3046 for(
const auto& in: tx.
vin)
3049 if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
3064 for (
size_t i = 0; i < tx.
vin.size(); ++i)
3066 CHECK_AND_ASSERT_MES(tx.
vin[i].type() ==
typeid(txin_to_key_public),
false,
"wrong type id in tx input at Blockchain::check_tx_inputs");
3068 const txin_to_key_public& in_to_key = boost::get<txin_to_key_public>(tx.
vin[i]);
3070 if (in_to_key.
amount <= 0)
3077 transaction parent_tx;
3078 if (!m_db->get_tx(in_to_key.
tx_hash, parent_tx))
3101 const txout_to_key_public& out_to_key = boost::get<txout_to_key_public>(parent_tx.
vout[in_to_key.
relative_offset].target);
3115 if (hf_version >= 6)
3117 size_t n_unmixable = 0, n_mixable = 0;
3118 size_t mixin = std::numeric_limits<size_t>::max();
3120 for (
const auto& txin : tx.
vin)
3123 if (txin.type() ==
typeid(txin_to_key))
3125 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3132 <<
"), and more than one mixable input with unmixable inputs");
3138 if (in_to_key.
amount == 0)
3150 if (n_outputs <= min_mixin)
3167 if (mixin < min_mixin)
3169 if (n_unmixable == 0)
3177 MERROR_VER(
"Tx " <<
get_transaction_hash(tx) <<
" has too low ring size (" << (mixin + 1) <<
"), and more than one mixable input with unmixable inputs");
3187 for (
size_t n = 0; n < tx.
vin.size(); ++n)
3190 if (txin.type() ==
typeid(txin_to_key))
3192 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3193 if (last_key_image && memcmp(&in_to_key.
k_image, last_key_image,
sizeof(*last_key_image)) >= 0)
3195 MERROR_VER(
"transaction has unsorted inputs");
3199 last_key_image = &in_to_key.
k_image;
3203 auto it = m_check_txin_table.find(tx_prefix_hash);
3204 if(it == m_check_txin_table.end())
3206 m_check_txin_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, bool>());
3207 it = m_check_txin_table.find(tx_prefix_hash);
3208 assert(it != m_check_txin_table.end());
3211 std::vector<std::vector<rct::ctkey>> pubkeys(tx.
vin.size());
3212 std::vector < uint64_t > results;
3213 results.resize(tx.
vin.size(), 0);
3216 tools::threadpool::waiter waiter;
3220 for (
const auto& txin : tx.
vin)
3224 CHECK_AND_ASSERT_MES(txin.type() ==
typeid(txin_to_key),
false,
"wrong type id in tx input at Blockchain::check_tx_inputs");
3225 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3240#if defined(CACHE_VIN_RESULTS)
3241 auto itk = it->second.find(in_to_key.
k_image);
3242 if(itk != it->second.end())
3260 it->second[in_to_key.
k_image] =
false;
3262 if (pmax_used_block_height)
3264 MERROR_VER(
" *pmax_used_block_height: " << *pmax_used_block_height);
3274 tpool.
submit(&waiter, boost::bind(&Blockchain::check_ring_signature,
this, std::cref(tx_prefix_hash), std::cref(in_to_key.
k_image), std::cref(pubkeys[sig_index]), std::cref(tx.
signatures[sig_index]), std::ref(results[sig_index])),
true);
3278 check_ring_signature(tx_prefix_hash, in_to_key.
k_image, pubkeys[sig_index], tx.
signatures[sig_index], results[sig_index]);
3279 if (!results[sig_index])
3281 it->second[in_to_key.
k_image] =
false;
3284 if (pmax_used_block_height)
3286 MERROR_VER(
"*pmax_used_block_height: " << *pmax_used_block_height);
3291 it->second[in_to_key.
k_image] =
true;
3299 waiter.
wait(&tpool);
3301 bool failed =
false;
3302 for (
size_t i = 0; i < tx.
vin.size(); i++)
3304 const txin_to_key& in_to_key = boost::get<txin_to_key>(tx.
vin[i]);
3305 it->second[in_to_key.
k_image] = results[i];
3306 if(!failed && !results[i])
3312 MERROR_VER(
"Failed to check ring signatures!");
3322 std::vector<const crypto::public_key *> p_output_keys;
3323 p_output_keys.reserve(pubkeys.size());
3324 for (
auto &
key : pubkeys)
3350 if (median_block_weight < min_block_weight)
3351 median_block_weight = min_block_weight;
3357 div128_32(hi, lo, min_block_weight, &hi, &lo);
3358 div128_32(hi, lo, median_block_weight, &hi, &lo);
3366 uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
3367 lo = mul128(unscaled_fee_base, block_reward, &hi);
3373 div128_32(hi, lo, 1000000, &hi, &lo);
3378 uint64_t qlo = (lo + mask - 1) / mask * mask;
3388 const uint64_t blockchain_height = m_db->height();
3391 uint64_t already_generated_coins = 0;
3395 median = m_current_block_cumul_weight_limit / 2;
3396 const uint64_t blockchain_height = m_db->height();
3397 already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3408 needed_fee = tx_weight * fee_per_byte;
3411 needed_fee = (needed_fee + mask - 1) / mask * mask;
3432 needed_fee = tx_weight / 1024;
3433 needed_fee += (tx_weight % 1024) ? 1 : 0;
3434 needed_fee *= fee_per_kb;
3437 if (fee < needed_fee - needed_fee / 50)
3449 const uint64_t db_height = m_db->height();
3465 std::vector<uint64_t> weights;
3467 weights.reserve(grace_blocks);
3468 for (
size_t i = 0; i < grace_blocks; ++i)
3469 weights.push_back(min_block_weight);
3472 if(median <= min_block_weight)
3473 median = min_block_weight;
3475 uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0;
3486 MDEBUG(
"Estimating " << grace_blocks <<
"-block fee at " <<
print_etn(fee) <<
"/" << (per_byte ?
"byte" :
"kB"));
3493bool Blockchain::is_tx_spendtime_unlocked(
uint64_t unlock_time)
const
3520bool Blockchain::check_tx_input(
size_t tx_version,
const txin_to_key& txin,
const crypto::hash& tx_prefix_hash,
const std::vector<crypto::signature>& sig,
const rct::rctSig &rct_signatures, std::vector<rct::ctkey> &output_keys,
uint64_t* pmax_related_block_height)
3528 struct outputs_visitor
3530 std::vector<rct::ctkey >& m_output_keys;
3531 const Blockchain& m_bch;
3532 outputs_visitor(std::vector<rct::ctkey>& output_keys,
const Blockchain& bch) :
3533 m_output_keys(output_keys), m_bch(bch)
3539 if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
3541 MERROR_VER(
"One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
3550 m_output_keys.push_back(rct::ctkey({rct::pk2rct(pubkey), commitment}));
3555 output_keys.clear();
3558 outputs_visitor vi(output_keys, *
this);
3559 if (!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height))
3567 MERROR_VER(
"Output keys for tx with amount = " << txin.
amount <<
" and count indexes " << txin.
key_offsets.size() <<
" returned wrong keys count " << output_keys.size());
3570 if (tx_version == 1) {
3571 CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(),
false,
"internal error: tx signatures count=" << sig.size() <<
" mismatch with outputs keys count for inputs=" << output_keys.size());
3578uint64_t Blockchain::get_adjusted_time()
const
3586bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps,
const block& b,
uint64_t& median_ts)
const
3607bool Blockchain::check_block_timestamp(
const block& b,
uint64_t& median_ts)
const
3616 const auto h = m_db->height();
3624 std::vector<uint64_t> timestamps;
3628 timestamps.reserve(h - offset);
3629 for(;offset < h; ++offset)
3631 timestamps.push_back(m_db->get_block_timestamp(offset));
3634 return check_block_timestamp(timestamps, b, median_ts);
3637void Blockchain::return_tx_to_pool(std::vector<std::pair<transaction, blobdata>> &txs)
3640 for (
auto& tx : txs)
3642 cryptonote::tx_verification_context tvc =
AUTO_VAL_INIT(tvc);
3650 if (!m_tx_pool.add_tx(tx.first, tx_hash, tx.second, weight, tvc,
true,
true,
false,
version))
3662 for (
const auto &txid: txids)
3668 bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
3669 MINFO(
"Removing txid " << txid <<
" from the pool");
3670 if(m_tx_pool.have_tx(txid) && !m_tx_pool.take_tx(txid, tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3672 MERROR(
"Failed to remove txid " << txid <<
" from the pool");
3690 static bool seen_future_version =
false;
3695 ++blockchain_height;
3698 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"has wrong prev_id: " << bl.
prev_id << std::endl <<
"expected: " << top_hash);
3706 if(!m_fallback_to_pow) {
3712 if(!m_validators->isValid()) {
3718 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has wrong digital signature");
3722 if(bl.
signatory == m_db->get_block(bl.
prev_id).signatory && !m_ignore_bsig){
3723 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has the same signatory as the previous block, which is not allowed");
3732 if (!seen_future_version && bl.
major_version > m_hardfork->get_ideal_version())
3734 seen_future_version =
true;
3736 MCLOG_RED(level,
"global",
"**********************************************************************");
3737 MCLOG_RED(level,
"global",
"A block was seen on the network with a version higher than the last");
3738 MCLOG_RED(level,
"global",
"known one. This may be an old version of the daemon, and a software");
3739 MCLOG_RED(level,
"global",
"update may be required to sync further. Try running: update check");
3740 MCLOG_RED(level,
"global",
"**********************************************************************");
3744 if (!m_hardfork->check(bl))
3746 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"has old version: " << (
unsigned)bl.
major_version << std::endl <<
"current: " << (
unsigned)m_hardfork->get_current_version());
3756 if(!check_block_timestamp(bl))
3758 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"has invalid timestamp: " << bl.
timestamp);
3790 bool precomputed =
false;
3791 bool fast_check =
false;
3792#if defined(PER_BLOCK_CHECKPOINT)
3793 if (blockchain_height < m_blocks_hash_check.size())
3796 if (memcmp(&
hash, &m_blocks_hash_check[m_db->height()],
sizeof(
hash)) != 0)
3798 MERROR_VER(
"Block with id is INVALID: " <<
id);
3808 auto it = m_blocks_longhash_table.find(
id);
3809 if (it != m_blocks_longhash_table.end())
3812 proof_of_work = it->second;
3818 if(!
check_hash(proof_of_work, current_diffic))
3820 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"does not have enough proof of work: " << proof_of_work <<
" at height " << blockchain_height <<
", unexpected difficulty: " << current_diffic);
3828 if(m_checkpoints.is_in_checkpoint_zone(blockchain_height))
3830 if(!m_checkpoints.check_block(blockchain_height,
id))
3832 LOG_ERROR(
"CHECKPOINT VALIDATION FAILED");
3840 longhash_calculating_time += m_fake_pow_calc_time;
3845 if(!prevalidate_miner_transaction(bl, blockchain_height))
3847 MERROR_VER(
"Block with id: " <<
id <<
" failed to pass prevalidation");
3853 size_t cumulative_block_weight = coinbase_weight;
3855 std::vector<std::pair<transaction, blobdata>> txs;
3856 key_images_container keys;
3867 size_t tx_index = 0;
3876 size_t tx_weight = 0;
3878 bool relayed =
false, do_not_relay =
false, double_spend_seen =
false, nonexistent_utxo_seen =
false;
3882 if (m_db->tx_exists(tx_id))
3884 MERROR(
"Block with id: " <<
id <<
" attempting to add transaction already in blockchain with id: " << tx_id);
3886 return_tx_to_pool(txs);
3895 if(!m_tx_pool.take_tx(tx_id, tx_tmp, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3897 MERROR_VER(
"Block with id: " <<
id <<
" has at least one unknown transaction with id: " << tx_id);
3899 return_tx_to_pool(txs);
3908 txs.push_back(std::make_pair(std::move(tx_tmp), std::move(txblob)));
3909 transaction &tx = txs.back().first;
3929#if defined(PER_BLOCK_CHECKPOINT)
3934 tx_verification_context tvc;
3937 MERROR_VER(
"Block with id: " <<
id <<
" has at least one transaction (id: " << tx_id <<
") with wrong inputs.");
3940 add_block_as_invalid(bl,
id);
3941 MERROR_VER(
"Block with id " <<
id <<
" added as invalid because of wrong inputs in transactions");
3942 MERROR_VER(
"tx_index " << tx_index <<
", m_blocks_txs_check " << m_blocks_txs_check.size() <<
":");
3943 for (
const auto &h: m_blocks_txs_check)
MERROR_VER(
" " << h);
3945 return_tx_to_pool(txs);
3949#if defined(PER_BLOCK_CHECKPOINT)
3954 if (tx_index >= m_blocks_txs_check.size() || memcmp(&m_blocks_txs_check[tx_index++], &tx_id,
sizeof(tx_id)) != 0)
3956 MERROR_VER(
"Block with id: " <<
id <<
" has at least one transaction (id: " << tx_id <<
") with wrong inputs.");
3958 add_block_as_invalid(bl,
id);
3959 MERROR_VER(
"Block with id " <<
id <<
" added as invalid because of wrong inputs in transactions");
3961 return_tx_to_pool(txs);
3969 cumulative_block_weight += tx_weight;
3972 m_blocks_txs_check.clear();
3976 uint64_t already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3977 if(!validate_miner_transaction(bl, cumulative_block_weight, fee_summary, base_reward, already_generated_coins, bvc.
m_partial_block_reward, m_hardfork->get_current_version()))
3979 MERROR_VER(
"Block with id: " <<
id <<
" has incorrect miner transaction");
3981 return_tx_to_pool(txs);
3986 size_t block_weight;
3990 block_weight = cumulative_block_weight;
3991 cumulative_difficulty = current_diffic;
3996 already_generated_coins = base_reward < (
ETN_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward :
ETN_SUPPLY;
3997 if(blockchain_height)
3998 cumulative_difficulty += m_db->get_block_cumulative_difficulty(blockchain_height - 1);
4002 block_processing_time += m_fake_pow_calc_time;
4013 new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs);
4015 catch (
const KEY_IMAGE_EXISTS& e)
4017 LOG_ERROR(
"Error adding block with hash: " <<
id <<
" to blockchain, what = " << e.
what());
4018 m_batch_success =
false;
4020 return_tx_to_pool(txs);
4023 catch (
const std::exception& e)
4026 LOG_ERROR(
"Error adding block with hash: " <<
id <<
" to blockchain, what = " << e.what());
4027 m_batch_success =
false;
4029 return_tx_to_pool(txs);
4035 LOG_ERROR(
"Blocks that failed verification should not reach here");
4041 if (!update_next_cumulative_weight_limit())
4043 MERROR(
"Failed to update next cumulative weight limit");
4044 pop_block_from_blockchain();
4048 MINFO(
"+++++ BLOCK SUCCESSFULLY ADDED" << std::endl <<
"id:\t" <<
id << std::endl <<
"PoW:\t" << proof_of_work << std::endl <<
"HEIGHT " << new_height-1 <<
", difficulty:\t" << current_diffic << std::endl <<
"block reward: " <<
print_etn(fee_summary + base_reward) <<
"(" <<
print_etn(base_reward) <<
" + " <<
print_etn(fee_summary) <<
"), coinbase_weight: " << coinbase_weight <<
", cumulative weight: " << cumulative_block_weight <<
", " << block_processing_time <<
"(" << target_calculating_time <<
"/" << longhash_calculating_time <<
")ms");
4049 if(m_show_time_stats)
4051 MINFO(
"Height: " << new_height <<
" coinbase weight: " << coinbase_weight <<
" cumm: "
4052 << cumulative_block_weight <<
" p/t: " << block_processing_time <<
" ("
4053 << target_calculating_time <<
"/" << longhash_calculating_time <<
"/"
4054 <<
t1 <<
"/" <<
t2 <<
"/" <<
t3 <<
"/" << t_exists <<
"/" << t_pool
4055 <<
"/" << t_checktx <<
"/" << t_dblspnd <<
"/" << vmt <<
"/" << addblock <<
")ms");
4062 m_tx_pool.on_blockchain_inc(new_height,
id);
4064 invalidate_block_template_cache();
4066 std::shared_ptr<tools::Notify> block_notify = m_block_notify;
4079 return m_db->prune_blockchain(pruning_seed);
4088 return m_db->update_pruning();
4097 return m_db->check_pruning();
4104 const uint64_t db_height = m_db->height();
4105 const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4109 return block_weight;
4111 uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
4114 uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
4115 uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4117 return long_term_block_weight;
4120bool Blockchain::update_next_cumulative_weight_limit(
uint64_t *long_term_effective_median_block_weight)
4122 PERF_TIMER(update_next_cumulative_weight_limit);
4134 std::vector<uint64_t> weights;
4137 long_term_block_weight = weights.back();
4150 uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4151 if (nblocks == db_height)
4153 long_term_median = get_long_term_block_weight_median(db_height - nblocks - 1, nblocks);
4158 uint64_t short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5;
4159 long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4163 long_term_median = long_term_block_weight;
4167 m_long_term_block_weights_cache_tip_hash = m_db->get_block_hash_from_height(db_height - 1);
4168 m_long_term_block_weights_cache_rolling_median.insert(long_term_block_weight);
4169 long_term_median = m_long_term_block_weights_cache_rolling_median.median();
4173 std::vector<uint64_t> weights;
4179 m_current_block_cumul_weight_median = effective_median_block_weight;
4182 if (m_current_block_cumul_weight_median <= full_reward_zone)
4183 m_current_block_cumul_weight_median = full_reward_zone;
4185 m_current_block_cumul_weight_limit = m_current_block_cumul_weight_median * 2;
4187 if (long_term_effective_median_block_weight)
4188 *long_term_effective_median_block_weight = m_long_term_effective_median_block_weight;
4190 if (!m_db->is_read_only())
4191 m_db->add_max_block_size(m_current_block_cumul_weight_limit);
4205 LOG_PRINT_L3(
"block with id = " <<
id <<
" already exists");
4207 m_blocks_txs_check.clear();
4217 bool r = handle_alternative_block(bl,
id, bvc);
4218 m_blocks_txs_check.clear();
4224 return handle_block_to_main_chain(bl,
id, bvc);
4235 stop_batch = m_db->batch_start();
4236 const uint64_t blockchain_height = m_db->height();
4237 for (
const auto& pt : pts)
4240 if (pt.first >= blockchain_height)
4245 if (!points.
check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
4250 LOG_ERROR(
"Local blockchain failed to pass a checkpoint, rolling back!");
4251 std::list<block> empty;
4252 rollback_blockchain_switching(empty, pt.first - 2);
4255 std::vector<crypto::hash> txs;
4256 m_tx_pool.get_transaction_hashes(txs,
true);
4261 LOG_ERROR(
"WARNING: local blockchain failed to pass a ElectroneumPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
4274 if (!m_checkpoints.load_checkpoints_from_json(file_path))
4281 if (m_enforce_dns_checkpoints && check_dns && !m_offline)
4283 if (!m_checkpoints.load_checkpoints_from_dns())
4288 else if (check_dns && !m_offline)
4292 if (m_checkpoints.check_for_conflicts(dns_points))
4298 MERROR(
"One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
4309 m_enforce_dns_checkpoints = enforce_checkpoints;
4324 map.emplace(
id, pow);
4334 bool success =
false;
4336 MTRACE(
"Blockchain::" << __func__);
4342 if (m_batch_success)
4345 m_db->batch_abort();
4348 catch (
const std::exception &e)
4350 MERROR(
"Exception in cleanup_handle_incoming_blocks: " << e.what());
4353 if (success && m_sync_counter > 0)
4361 else if (m_db_sync_threshold && ((m_db_sync_on_blocks && m_sync_counter >= m_db_sync_threshold) || (!m_db_sync_on_blocks && m_bytes_to_sync >= m_db_sync_threshold)))
4363 MDEBUG(
"Sync threshold met, syncing");
4367 m_bytes_to_sync = 0;
4370 else if(m_db_sync_mode ==
db_sync)
4382 m_blocks_longhash_table.clear();
4383 m_scan_table.clear();
4384 m_blocks_txs_check.clear();
4385 m_check_txin_table.clear();
4402 catch (
const std::exception& e)
4421 MTRACE(
"Blockchain::" << __func__);
4425 size_t total_txs = 0;
4445 if(blocks_entry.size() == 0)
4448 for (
const auto &entry : blocks_entry)
4450 bytes += entry.block.size();
4451 for (
const auto &tx_blob : entry.txs)
4453 bytes += tx_blob.size();
4455 total_txs += entry.txs.size();
4457 m_bytes_to_sync += bytes;
4458 while (!(stop_batch = m_db->batch_start(blocks_entry.size(), bytes))) {
4459 m_blockchain_lock.unlock();
4463 m_blockchain_lock.lock();
4465 m_batch_success =
true;
4468 if ((
height + blocks_entry.size()) < m_blocks_hash_check.size())
4471 bool blocks_exist =
false;
4474 blocks.resize(blocks_entry.size());
4479 if(threads > m_max_prepare_blocks_threads)
4480 threads = m_max_prepare_blocks_threads;
4482 unsigned int batches = blocks_entry.size() / threads;
4483 unsigned int extra = blocks_entry.size() % threads;
4484 MDEBUG(
"block_batches: " << batches);
4485 std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
4486 auto it = blocks_entry.begin();
4487 unsigned blockidx = 0;
4490 for (
unsigned i = 0; i < threads; i++)
4492 for (
unsigned int j = 0; j < batches; j++, ++blockidx)
4505 MDEBUG(
"Skipping prepare blocks. New blocks don't belong to chain.");
4511 blocks_exist =
true;
4513 std::advance(it, 1);
4517 for (
unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
4526 blocks_exist =
true;
4528 std::advance(it, 1);
4533 m_blocks_longhash_table.clear();
4536 for (
unsigned int i = 0; i < threads; i++)
4538 unsigned nblocks = batches;
4542 thread_height += nblocks;
4545 waiter.
wait(&tpool);
4550 for (
const auto & map : maps)
4552 m_blocks_longhash_table.insert(map.begin(), map.end());
4562 MDEBUG(
"Skipping remainder of prepare blocks. Blocks exist.");
4566 m_fake_scan_time = 0;
4567 m_fake_pow_calc_time = 0;
4569 m_scan_table.clear();
4570 m_check_txin_table.clear();
4573 m_fake_pow_calc_time = prepare / blocks_entry.size();
4575 if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
4576 MDEBUG(
"Prepare blocks took: " << prepare <<
" ms");
4581 std::vector < uint64_t > amounts;
4583 std::map<uint64_t, std::vector<uint64_t>> offset_map;
4585 std::map<uint64_t, std::vector<output_data_t>> tx_map;
4586 std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
4588#define SCAN_TABLE_QUIT(m) \
4591 m_scan_table.clear(); \
4596 size_t tx_index = 0, block_index = 0;
4597 for (
const auto &entry : blocks_entry)
4602 for (
const auto &tx_blob : entry.txs)
4604 if (tx_index >= txes.size())
4614 auto its = m_scan_table.find(tx_prefix_hash);
4615 if (its != m_scan_table.end())
4618 m_scan_table.emplace(tx_prefix_hash, std::unordered_map<
crypto::key_image, std::vector<output_data_t>>());
4619 its = m_scan_table.find(tx_prefix_hash);
4620 assert(its != m_scan_table.end());
4625 for (
const auto &txin : tx.
vin)
4627 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4630 auto it = its->second.find(in_to_key.
k_image);
4631 if (it != its->second.end())
4634 amounts.push_back(in_to_key.
amount);
4639 std::sort(amounts.begin(), amounts.end());
4640 auto last = std::unique(amounts.begin(), amounts.end());
4641 amounts.erase(last, amounts.end());
4644 for (
const uint64_t &amount : amounts)
4646 if (offset_map.find(amount) == offset_map.end())
4647 offset_map.emplace(amount, std::vector<uint64_t>());
4649 if (tx_map.find(amount) == tx_map.end())
4650 tx_map.emplace(amount, std::vector<output_data_t>());
4656 for (
const auto &txin : tx.
vin)
4658 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4661 for (
const auto & offset : absolute_offsets)
4662 offset_map[in_to_key.
amount].push_back(offset);
4671 for (
auto &offsets : offset_map)
4673 std::sort(offsets.second.begin(), offsets.second.end());
4674 auto last = std::unique(offsets.second.begin(), offsets.second.end());
4675 offsets.second.erase(last, offsets.second.end());
4680 if (!m_db->can_thread_bulk_indices())
4683 if (threads > 1 && amounts.size() > 1)
4687 for (
size_t i = 0; i < amounts.size(); i++)
4692 waiter.
wait(&tpool);
4696 for (
size_t i = 0; i < amounts.size(); i++)
4705 for (
const auto &entry : blocks_entry)
4710 for (
const auto &tx_blob : entry.txs)
4712 if (tx_index >= txes.size())
4715 const crypto::hash &tx_prefix_hash = txes[tx_index].second;
4718 auto its = m_scan_table.find(tx_prefix_hash);
4719 if (its == m_scan_table.end())
4724 for (
const auto &txin : tx.
vin)
4726 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4729 std::vector<output_data_t> outputs;
4730 for (
const uint64_t & offset_needed : needed_offsets)
4735 for (
const uint64_t &offset_found : offset_map[in_to_key.
amount])
4737 if (offset_needed == offset_found)
4746 if (found && pos < tx_map[in_to_key.
amount].size())
4747 outputs.push_back(tx_map[in_to_key.
amount].at(pos));
4752 its->second.emplace(in_to_key.
k_image, outputs);
4760 m_fake_scan_time = scantable / total_txs;
4761 if(m_show_time_stats)
4762 MDEBUG(
"Prepare scantable took: " << scantable <<
" ms");
4770 m_db->add_txpool_tx(txid, blob, meta);
4775 m_db->update_txpool_tx(txid, meta);
4780 m_db->remove_txpool_tx(txid);
4785 return m_db->get_txpool_tx_count(include_unrelayed_txes);
4790 return m_db->get_txpool_tx_meta(txid, meta);
4795 return m_db->get_txpool_tx_blob(txid, bd);
4800 return m_db->get_txpool_tx_blob(txid);
4805 return m_db->for_all_txpool_txes(f, include_blob, include_unrelayed_txes);
4821 m_db_default_sync =
true;
4824 m_db_sync_mode = sync_mode;
4825 m_fast_sync = fast_sync;
4826 m_db_sync_on_blocks = sync_on_blocks;
4827 m_db_sync_threshold = sync_threshold;
4828 m_max_prepare_blocks_threads = maxthreads;
4830 if(!validator_key.empty()) {
4831 m_validator_key = boost::algorithm::unhex(validator_key);
4840 if (m_db_default_sync)
4842 m_db->safesyncmode(onoff);
4849 return m_hardfork->get_state();
4854 static const std::vector<HardFork::Params> mainnet_heights = []()
4856 std::vector<HardFork::Params> heights;
4857 for (
const auto& i : mainnet_hard_forks)
4858 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4861 static const std::vector<HardFork::Params> testnet_heights = []()
4863 std::vector<HardFork::Params> heights;
4864 for (
const auto& i : testnet_hard_forks)
4865 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4868 static const std::vector<HardFork::Params> stagenet_heights = []()
4870 std::vector<HardFork::Params> heights;
4871 for (
const auto& i : stagenet_hard_forks)
4872 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4875 static const std::vector<HardFork::Params> dummy;
4878 case MAINNET:
return mainnet_heights;
4879 case TESTNET:
return testnet_heights;
4880 case STAGENET:
return stagenet_heights;
4881 default:
return dummy;
4887 return m_hardfork->get_voting_info(
version, window, votes,
threshold, earliest_height, voting);
4897 return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
4902 std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
4904 for (
const auto &i: m_alternative_chains)
4908 for (
const auto &j: m_alternative_chains)
4910 if (j.second.bl.prev_id == top)
4918 std::vector<crypto::hash> chain;
4919 auto h = i.second.bl.prev_id;
4920 chain.push_back(top);
4921 blocks_ext_by_hash::const_iterator prev;
4922 while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
4925 h = prev->second.bl.prev_id;
4927 chains.push_back(std::make_pair(i.second, chain));
4938#if defined(PER_BLOCK_CHECKPOINT)
4939static const char expected_block_hashes_hash[] =
"53a9384ca5384025e657622b5d66fac67c03f9b863b91abe9516eda47cceaeb5";
4942 if (get_checkpoints ==
nullptr || !m_fast_sync)
4956 MERROR(
"Failed to hash precomputed blocks data");
4959 MINFO(
"precomputed blocks hash: " <<
hash <<
", expected " << expected_block_hashes_hash);
4963 MERROR(
"Failed to parse expected block hashes hash");
4967 if (
hash != expected_hash)
4969 MERROR(
"Block hash data does not match expected hash");
4977 const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
4978 if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) /
sizeof(
hash))
4980 MERROR(
"Block hash data is too large");
4983 const size_t size_needed = 4 + nblocks *
sizeof(
crypto::hash);
4984 if(nblocks > 0 && nblocks > m_db->height() &&
checkpoints.size() >= size_needed)
4987 for (
uint32_t i = 0; i < nblocks; i++)
4991 p +=
sizeof(
hash.data);
4992 m_blocks_hash_check.push_back(
hash);
4994 MINFO(nblocks <<
" block hashes loaded");
5003 std::vector<transaction> txs;
5004 m_tx_pool.get_transactions(txs);
5008 bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
5009 transaction pool_tx;
5011 for(
const transaction &tx : txs)
5014 m_tx_pool.take_tx(tx_hash, pool_tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen);
5024#if defined(PER_BLOCK_CHECKPOINT)
5025 return height < m_blocks_hash_check.size();
5033 m_blockchain_lock.lock();
5038 m_blockchain_lock.unlock();
5043 return m_db->for_all_key_images(f);
5048 return m_db->for_blocks_range(h1, h2, f);
5053 return m_db->for_all_transactions(f, pruned);
5066void Blockchain::invalidate_block_template_cache()
5068 MDEBUG(
"Invalidating block template cache");
5069 m_btc_valid =
false;
5074 MDEBUG(
"Setting block template cache");
5077 m_btc_nonce = nonce;
5078 m_btc_difficulty = diff;
5080 m_btc_expected_reward = expected_reward;
5081 m_btc_pool_cookie = pool_cookie;
5091 return m_validators->getValidatorByKey(boost::algorithm::hex(signatory));
5096template bool Blockchain::get_transactions(
const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&)
const;
5098template bool Blockchain::get_split_transactions_blobs(
const std::vector<crypto::hash>&, std::vector<std::tuple<crypto::hash, cryptonote::blobdata, crypto::hash, cryptonote::blobdata>>&, std::vector<crypto::hash>&)
const;
#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE
size_t get_transaction_version(const cryptonote::blobdata &bd)
void reserve_container(std::vector< T > &v, size_t N)
#define SCAN_TABLE_QUIT(m)
void slow_hash_allocate_state()
#define BLOCK_REWARD_OVERESTIMATE
void slow_hash_free_state()
const unsigned char checkpoints[]
thrown when a requested block does not exist
The BlockchainDB backing store interface declaration/contract.
virtual uint64_t height() const =0
fetch the current blockchain height
bool is_open() const
Gets the current open/ready state of the BlockchainDB.
virtual bool has_key_image(const crypto::key_image &img) const =0
check if a key image is stored as spent
virtual size_t get_block_weight(const uint64_t &height) const =0
fetch a block's weight
virtual bool for_all_outputs(std::function< bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const =0
runs a function over all outputs stored
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block's timestamp
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
bool utxo_nonexistent(const transaction &tx) const
check if any utxo in a transaction has already been spent using the tx (v3 tx onwards)
bool check_fee(size_t tx_weight, uint64_t fee) const
validate a transaction's fee
bool prepare_handle_incoming_blocks(const std::vector< block_complete_entry > &blocks_entry, std::vector< block > &blocks)
performs some preprocessing on a group of incoming blocks to speed up verification
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
bool init(BlockchainDB *db, const network_type nettype=MAINNET, bool offline=false, const cryptonote::test_options *test_options=NULL, difficulty_type fixed_difficulty=0, const GetCheckpointsCallback &get_checkpoints=nullptr, bool ignore_bsig=false, bool fallback_to_pow=false)
Initialize the Blockchain state.
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
bool prune_blockchain(uint32_t pruning_seed=0)
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t ¤t_height, bool clip_pruned) const
get recent block hashes for a foreign chain
bool get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vector< uint64_t > &indexs) const
gets the global indices for outputs from a given transaction
void normalize_v7_difficulties()
Normalize the cumulative difficulty for V7 blocks, fixing the differing difficulty among nodes.
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
crypto::public_key get_output_key(uint64_t amount, uint64_t global_index) const
get the public key for an output
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta)
network_type get_nettype() const
get blockchain nettype
bool get_split_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
bool for_all_outputs(std::function< bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)>) const
perform a check on all outputs in the blockchain
void set_enforce_dns_checkpoints(bool enforce)
configure whether or not to enforce DNS-based checkpoints
bool check_blockchain_pruning()
uint64_t get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
get dynamic per kB or byte fee estimate for the next few blocks
void output_scan_worker(const uint64_t amount, const std::vector< uint64_t > &offsets, std::vector< output_data_t > &outputs) const
get a number of outputs of a specific amount
uint64_t get_next_long_term_block_weight(uint64_t block_weight) const
gets the long term block weight for a new block
bool update_checkpoints(const std::string &file_path, bool check_dns)
loads new checkpoints from a file and optionally from DNS
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
bool is_within_compiled_block_hash_area() const
~Blockchain()
Blockchain destructor.
bool deinit()
Uninitializes the blockchain state.
static const std::vector< HardFork::Params > & get_hard_fork_heights(network_type nettype)
gets the hardfork heights of given network
HardFork::State get_hard_fork_state() const
gets the hardfork voting state object
uint64_t get_current_cumulative_block_weight_median() const
gets the block weight median based on recent blocks (same window as for the limit)
difficulty_type block_difficulty(uint64_t i) const
gets the difficulty of the block with a given height
electroneum::basic::Validator get_validator_by_height(uint64_t height)
bool key_images_already_spent(const transaction &tx) const
check if any key image in a transaction has already been spent
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block > > &blocks, std::vector< cryptonote::blobdata > &txs) const
get blocks and transactions from blocks based on start height and count
bool verify_block_signature(const block &b)
Verify block's digital signature.
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
bool update_blockchain_pruning()
void on_new_tx_from_block(const cryptonote::transaction &tx)
called when we see a tx originating from a block
void check_against_checkpoints(const checkpoints &points, bool enforce)
check the blockchain against a set of checkpoints
Blockchain(tx_memory_pool &tx_pool)
Blockchain constructor.
bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector< uint64_t > &distribution, uint64_t &base) const
gets per block distribution of outputs of a given amount
bool check_tx_outputs(const transaction &tx, tx_verification_context &tvc)
check that a transaction's outputs conform to current standards
uint64_t get_current_cumulative_block_weight_limit() const
gets the block weight limit based on recent blocks
std::vector< time_t > get_last_block_timestamps(unsigned int blocks) const
returns the timestamps of the last N blocks
bool for_blocks_range(const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const block &)>) const
perform a check on all blocks in the blockchain in the given range
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
bool store_blockchain()
stores the blockchain
uint64_t get_num_mature_outputs(uint64_t amount) const
get number of outputs of an amount past the minimum spendable age
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
bool utxo_nonexistence_from_output(const txin_to_key_public &public_output) const
check if a single utxo in a transaction has already been spent using the hash and out index (v3 tx on...
std::list< std::pair< block_extended_info, std::vector< crypto::hash > > > get_alternative_chains() const
returns a set of known alternate chains
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
bool cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
void remove_txpool_tx(const crypto::hash &txid)
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
bool for_all_transactions(std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const
perform a check on all transactions in the blockchain
uint64_t get_difficulty_target() const
get difficulty target based on chain and hardfork version
void block_longhash_worker(uint64_t height, const epee::span< const block > &blocks, std::unordered_map< crypto::hash, crypto::hash > &map) const
computes the "short" and "long" hashes for a set of blocks
static uint64_t get_fee_quantization_mask()
get fee quantization mask
uint32_t get_mempool_tx_livetime() const
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
uint32_t get_blockchain_pruning_seed() const
static uint64_t get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
get dynamic per kB or byte fee for a given block weight
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
bool for_all_key_images(std::function< bool(const crypto::key_image &)>) const
perform a check on all key images in the blockchain
std::map< uint64_t, std::tuple< uint64_t, uint64_t, uint64_t > > get_output_histogram(const std::vector< uint64_t > &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count=0) const
return a histogram of outputs on the blockchain
size_t get_total_transactions() const
gets the total number of transactions on the main chain
bool reset_and_set_genesis_block(const block &b)
clears the blockchain and starts a new one
void set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold, blockchain_db_sync_mode sync_mode, bool fast_sync, std::string validator_key)
Update the validators public key by fetching data from electroneum's endpoint.
bool flush_txes_from_pool(const std::vector< crypto::hash > &txids)
remove transactions from the transaction pool (if present)
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request &req, COMMAND_RPC_GET_OUTPUTS_BIN::response &res) const
gets specific outputs to mix with
bool create_block_template(block &b, const account_public_address &miner_address, difficulty_type &di, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
creates a new block to mine against
bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
void sign_block(block &b, std::string privateKey)
Digitally sign the block.
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request &arg, NOTIFY_RESPONSE_GET_OBJECTS::request &rsp)
retrieves a set of blocks and their transactions, and possibly other transactions
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
void get_output_key_mask_unlocked(const uint64_t &amount, const uint64_t &index, crypto::public_key &key, rct::key &mask, bool &unlocked) const
gets an output's key and unlocked state
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
void pop_blocks(uint64_t nblocks)
removes blocks from the top of the blockchain
bool check_tx_inputs(transaction &tx, uint64_t &pmax_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block=false)
validates a transaction's inputs
bool get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
get information about hardfork voting for a version
const char * what() const
uint8_t get_current_version() const
returns the current version
A container for blockchain checkpoints.
bool check_block(uint64_t height, const crypto::hash &h, bool &is_a_checkpoint) const
checks if the given height and hash agree with the checkpoints
bool load_checkpoints_from_dns(network_type nettype=MAINNET)
load new checkpoints from DNS
const std::map< uint64_t, crypto::hash > & get_points() const
gets the checkpoints container
std::vector< uint8_t > extra
std::vector< txin_v > vin
std::vector< tx_out > vout
rct::rctSig rct_signatures
std::vector< std::vector< crypto::signature > > signatures
Transaction pool, handles transactions which are not part of a block.
Non-owning sequence of data. Does not deep copy.
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME
#define HF_VERSION_PUBLIC_TX
#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD
#define HF_VERSION_FORBID_INVALID_PUBKEYS
#define HF_VERSION_MIN_MIXIN_6
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
#define HF_VERSION_FORBID_DUST_OUTPUTS
#define HF_VERSION_DYNAMIC_FEE
#define CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR
#define DIFFICULTY_BLOCKS_COUNT_V6
#define DIFFICULTY_TARGET
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME_V6
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
#define HF_VERSION_ENFORCE_0_DECOY_TXS
#define PER_KB_FEE_QUANTIZATION_DECIMALS
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
#define DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
#define DIFFICULTY_TARGET_V6
#define DIFFICULTY_BLOCKS_COUNT
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
#define DYNAMIC_FEE_PER_KB_BASE_FEE
#define ETN_MINED_ETN_UNLOCK_WINDOW_V8
#define HF_VERSION_ENFORCE_0_DECOY_TXS_END
#define CRYPTONOTE_MAX_BLOCK_NUMBER
#define HF_VERSION_MIN_MIXIN_10
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS
#define HF_VERSION_ORDERED_TX_INPUTS
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
#define HF_VERSION_PER_BYTE_FEE
#define HF_VERSION_MIN_MIXIN_4
#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE
void * memcpy(void *a, const void *b, size_t c)
void slow_hash_allocate_state()
void slow_hash_free_state()
#define MCLOG_RED(level, cat, x)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature)
bool check_key(const public_key &key)
bool verify_input_signature(const hash &prefix_hash, const uint32_t input_index, const public_key pub_view, const public_key pub_spend, signature sig)
public_key addKeys(const public_key &A, const public_key &B)
std::string sign_message(const std::string &message, const std::string &privateKey)
bool check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const signature *sig)
Holds cryptonote related classes and helpers.
bool is_valid_decomposed_amount(uint64_t amount)
boost::multiprecision::uint128_t difficulty_type
uint64_t get_outs_etn_amount(const transaction &tx)
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
void get_tx_tree_hash(const std::vector< crypto::hash > &tx_hashes, crypto::hash &h)
difficulty_type next_difficulty(std::vector< uint64_t > timestamps, std::vector< difficulty_type > cumulative_difficulties, size_t target_seconds, uint8_t version)
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
bool get_block_hash(const block &b, crypto::hash &res)
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
uint64_t get_block_height(const block &b)
@ db_async
handle syncing calls instead of the backing db, asynchronously
@ db_nosync
Leave syncing up to the backing db (safest, but slowest because of disk I/O).
@ db_sync
handle syncing calls instead of the backing db, synchronously
@ db_defaultsync
user didn't specify, use db_async
size_t get_min_block_weight(uint8_t version)
bool check_hash(const crypto::hash &hash, difficulty_type difficulty)
crypto::hash get_transaction_hash(const transaction &t)
std::function< const epee::span< const unsigned char >(cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
bool is_coinbase(const transaction &tx)
blobdata block_to_blob(const block &b)
bool check_outs_overflow(const transaction &tx)
bool get_block_longhash(const block &b, crypto::hash &res, uint64_t height)
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction &tx, const blobdata &extra_nonce, size_t max_outs, uint8_t hard_fork_version, network_type nettype)
std::pair< crypto::hash, uint64_t > tx_out_index
size_t get_object_blobsize(const t_object &o)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
const config_t & get_config(network_type nettype)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
Level
Represents enumeration for severity level used to determine level of logging.
@ Warning
Useful when application has potentially harmful situtaions.
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
std::string get_time_interval_string(const time_t &time_)
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
type_vec_type median(std::vector< type_vec_type > &v)
mdb_size_t count(MDB_cursor *cur)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
unsigned __int64 uint64_t
container for passing a block and metadata about it on the blockchain
uint64_t height
the height of the block in the blockchain
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
crypto::public_key m_view_public_key
crypto::public_key m_spend_public_key
std::vector< blobdata > txs
bool m_added_to_main_chain
bool m_validator_list_update_failed
bool m_marked_as_orphaned
bool m_partial_block_reward
bool m_verification_failed
std::vector< uint8_t > signature
std::vector< uint8_t > signatory
std::vector< crypto::hash > tx_hashes
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
a struct containing output metadata
uint64_t unlock_time
the output's unlock time (or height)
uint64_t height
the height of the block which created the output
rct::key commitment
the output's amount commitment (for spend verification)
crypto::public_key pubkey
the output's public key (for spend verification)
const size_t long_term_block_weight_window
const std::pair< uint8_t, uint64_t > * hard_forks
information about a single transaction
transaction tx
the transaction
uint64_t fee
the transaction's fee amount
size_t weight
the transaction's weight
bool m_verification_failed
crypto::key_image k_image
std::vector< uint64_t > key_offsets
uint64_t m_address_prefix
cryptonote::account_public_address address
#define CRITICAL_REGION_LOCAL1(x)
#define CRITICAL_REGION_LOCAL(x)
#define CRITICAL_REGION_END()
#define CRITICAL_REGION_BEGIN(x)
struct hash_func hashes[]
provides the implementation of varint's
#define DISABLE_VS_WARNINGS(w)