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 },
103 static const uint64_t mainnet_hard_fork_version_1_till = 307499;
105 static const struct {
110 } testnet_hard_forks[] = {
112 { 1, 1, 0, 1341378000 },
113 { 6, 190060, 0, 1523263057 },
114 { 7, 215000, 0, 1530615600 },
115 { 8, 446674, 0, 1562889600 },
116 { 9, 707121, 0, 1595615809 },
117 { 10, 1165235, 0, 1631789441 },
119 static const uint64_t testnet_hard_fork_version_1_till = 190059;
121 static const struct {
126 } stagenet_hard_forks[] = {
128 { 1, 1, 0, 1341378000 },
131 { 2, 32000, 0, 1521000000 },
132 { 3, 33000, 0, 1521120000 },
133 { 4, 34000, 0, 1521240000 },
134 { 5, 35000, 0, 1521360000 },
135 { 6, 36000, 0, 1521480000 },
136 { 7, 37000, 0, 1521600000 },
137 { 8, 38000, 0, 1521800000 },
138 { 9, 39000, 0, 1522000000 },
139 { 10, 1165235, 0, 1631789441 },
144 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),
145 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),
147 m_long_term_effective_median_block_weight(0),
148 m_long_term_block_weights_cache_tip_hash(
crypto::null_hash),
150 m_difficulty_for_next_block_top_hash(
crypto::null_hash),
151 m_difficulty_for_next_block(1),
153 m_batch_success(
true)
161 catch (
const std::exception &e) { }
187 template <
class visitor_t>
188 bool 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
204 std::vector<output_data_t> outputs;
207 auto it = m_scan_table.find(tx_prefix_hash);
208 if (it != m_scan_table.end())
210 auto its = it->second.find(tx_in_to_key.
k_image);
211 if (its != it->second.end())
213 outputs = its->second;
223 if (absolute_offsets.size() != outputs.size())
238 if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
240 MDEBUG(
"Additional outputs needed: " << absolute_offsets.size() - outputs.size());
241 std::vector < uint64_t > add_offsets;
242 std::vector<output_data_t> add_outputs;
243 add_outputs.reserve(absolute_offsets.size() - outputs.size());
244 for (
size_t i = outputs.size(); i < absolute_offsets.size(); i++)
245 add_offsets.push_back(absolute_offsets[i]);
249 if (add_offsets.size() != add_outputs.size())
260 outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
265 for (
const uint64_t& i : absolute_offsets)
273 if (
count < outputs.size())
281 MERROR_VER(
"Failed to handle_output for output no = " <<
count <<
", with absolute offset " << i);
287 MERROR_VER(
"Output does not exist! amount = " << tx_in_to_key.
amount <<
", absolute_offset = " << i);
292 if(++
count == absolute_offsets.size() && pmax_related_block_height)
296 if(*pmax_related_block_height < h)
298 *pmax_related_block_height = h;
342 LOG_ERROR(
"Attempted to init Blockchain with null DB");
347 LOG_ERROR(
"Attempted to init Blockchain with unopened DB");
356 m_fixed_difficulty = fixed_difficulty;
357 m_ignore_bsig = ignore_bsig;
358 m_fallback_to_pow = fallback_to_pow;
359 if (m_hardfork ==
nullptr)
362 m_hardfork =
new HardFork(*db, 1, 0);
364 m_hardfork =
new HardFork(*db, 1, testnet_hard_fork_version_1_till);
366 m_hardfork =
new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
375 for (
size_t n = 0; n <
sizeof(testnet_hard_forks) /
sizeof(testnet_hard_forks[0]); ++n)
376 m_hardfork->
add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
380 for (
size_t n = 0; n <
sizeof(stagenet_hard_forks) /
sizeof(stagenet_hard_forks[0]); ++n)
381 m_hardfork->
add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
385 for (
size_t n = 0; n <
sizeof(mainnet_hard_forks) /
sizeof(mainnet_hard_forks[0]); ++n)
386 m_hardfork->
add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
398 MINFO(
"Blockchain not loaded, generating genesis block.");
421 uint64_t timestamp_diff =
time(NULL) - top_block_timestamp;
424 if(!top_block_timestamp)
425 timestamp_diff =
time(NULL) - 1397818133;
429 m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (
new boost::asio::io_service::work(m_async_service));
431 m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
433 #if defined(PER_BLOCK_CHECKPOINT)
435 load_compiled_in_block_hashes(get_checkpoints);
449 if (ideal_hf_version <= 1 || ideal_hf_version == top_block.
major_version)
451 if (num_popped_blocks > 0)
452 MGINFO(
"Initial popping done, top block: " << top_id <<
", top height: " << top_height <<
", block version: " << (
uint64_t)top_block.
major_version);
457 if (num_popped_blocks == 0)
458 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);
459 if (num_popped_blocks % 100 == 0)
460 MGINFO(
"Popping blocks... " << top_height);
463 std::vector<transaction> popped_txs;
466 m_db->pop_block(popped_block, popped_txs);
470 catch (
const std::exception& e)
472 MERROR(
"Error popping block from blockchain: " << e.what());
477 MERROR(
"Error popping block from blockchain, throwing!");
483 if (num_popped_blocks > 0)
485 m_timestamps_and_difficulties_height = 0;
500 if (!update_next_cumulative_weight_limit())
510 bool res =
init(db, nettype, offline, NULL);
529 catch (
const std::exception& e)
531 MERROR(
std::string(
"Error syncing blockchain db: ") + e.what() +
"-- shutting down now to prevent issues!");
536 MERROR(
"There was an issue storing the blockchain, shutting down now to prevent issues!");
541 if(m_show_time_stats)
542 MINFO(
"Blockchain stored OK, took: " <<
save <<
" ms");
550 MTRACE(
"Stopping blockchain read/write activity");
553 m_async_work_idle.reset();
554 m_async_pool.join_all();
555 m_async_service.stop();
565 MTRACE(
"Local blockchain read/write activity stopped successfully");
568 catch (
const std::exception& e)
574 LOG_ERROR(
"There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
597 if (blockchain_height > 0)
598 nblocks = std::min(nblocks, blockchain_height - 1);
599 for (i=0; i < nblocks; ++i)
601 pop_block_from_blockchain();
604 catch (
const std::exception& e)
606 LOG_ERROR(
"Error when popping blocks after processing " << i <<
" blocks: " << e.what());
619 block Blockchain::pop_block_from_blockchain()
624 m_timestamps_and_difficulties_height = 0;
627 std::vector<transaction> popped_txs;
633 m_db->pop_block(popped_block, popped_txs);
637 catch (
const std::exception& e)
639 LOG_ERROR(
"Error popping block from blockchain: " << e.what());
644 LOG_ERROR(
"Error popping block from blockchain, throwing!");
674 bool r = m_tx_pool.
add_tx(tx, tvc,
true,
true,
false,
version);
677 LOG_ERROR(
"Error returning transaction to tx_pool");
682 MWARNING(pruned <<
" pruned txes could not be added back to the txpool");
684 m_blocks_longhash_table.clear();
685 m_scan_table.clear();
686 m_blocks_txs_check.clear();
687 m_check_txin_table.clear();
693 invalidate_block_template_cache();
702 m_timestamps_and_difficulties_height = 0;
703 m_alternative_chains.clear();
704 invalidate_block_template_cache();
711 if (!update_next_cumulative_weight_limit())
757 bool genesis_included =
false;
759 while(current_back_offset < sz)
763 if(sz-current_back_offset == 0)
765 genesis_included =
true;
769 ++current_back_offset;
773 current_multiplier *= 2;
774 current_back_offset += current_multiplier;
779 if (!genesis_included)
801 catch (
const std::exception& e)
830 blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
831 if (m_alternative_chains.end() != it_alt)
833 blk = it_alt->second.bl;
839 catch (
const std::exception& e)
859 if (m_fixed_difficulty)
861 return m_db->
height() ? m_fixed_difficulty : 1;
873 if (top_hash == m_difficulty_for_next_block_top_hash)
874 return m_difficulty_for_next_block;
878 std::vector<uint64_t> timestamps;
879 std::vector<difficulty_type> difficulties;
884 uint64_t v6height = 0, v7height = 0, v8height = 0;
886 v6height = mainnet_hard_forks[1].height;
887 v7height = mainnet_hard_forks[2].height;
888 v8height = mainnet_hard_forks[3].height;
889 }
else if(m_nettype ==
TESTNET) {
890 v6height = testnet_hard_forks[1].height;
891 v7height = testnet_hard_forks[2].height;
892 v8height = testnet_hard_forks[3].height;
894 v6height = stagenet_hard_forks[5].height;
895 v7height = stagenet_hard_forks[5].height;
896 v8height = stagenet_hard_forks[5].height;
910 m_timestamps.clear();
911 m_difficulties.clear();
913 difficultyBlocksCount =
height - v8height;
922 if (m_timestamps_and_difficulties_height != 0 && ((
height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficultyBlocksCount)
928 while (m_timestamps.size() > difficultyBlocksCount)
929 m_timestamps.erase(m_timestamps.begin());
930 while (m_difficulties.size() > difficultyBlocksCount)
931 m_difficulties.erase(m_difficulties.begin());
933 m_timestamps_and_difficulties_height =
height;
934 timestamps = m_timestamps;
935 difficulties = m_difficulties;
944 difficulties.clear();
947 timestamps.reserve(
height - offset);
948 difficulties.reserve(
height - offset);
950 for (; offset <
height; offset++)
956 m_timestamps_and_difficulties_height =
height;
957 m_timestamps = timestamps;
958 m_difficulties = difficulties;
965 m_difficulty_for_next_block_top_hash = top_hash;
966 m_difficulty_for_next_block = diff;
975 std::vector<time_t> timestamps(
blocks);
994 const size_t V7_DIFFICULTY_BLOCKS_COUNT = 735;
995 const size_t V7_DIFFICULTY_TARGET = 120;
997 std::vector<uint64_t> timestamps;
998 std::vector<difficulty_type> difficulties;
1000 uint64_t start_height = v7height - V7_DIFFICULTY_BLOCKS_COUNT;
1003 for(
uint64_t i = 0; start_height + i < v7height; i++) {
1022 timestamps.erase(timestamps.begin());
1023 difficulties.erase(difficulties.begin());
1026 diff = difficulties.back() +
next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1030 m_timestamps.clear();
1031 m_difficulties.clear();
1038 bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
uint64_t rollback_height)
1044 if (rollback_height > m_db->
height())
1049 m_timestamps_and_difficulties_height = 0;
1052 while (m_db->
height() != rollback_height)
1054 pop_block_from_blockchain();
1061 for (
auto& bl : original_chain)
1064 bool r = handle_block_to_main_chain(bl, bvc);
1070 MINFO(
"Rollback to height " << rollback_height <<
" was successful.");
1071 if (!original_chain.empty())
1073 MINFO(
"Restoration to previous blockchain successful as well.");
1080 bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::const_iterator>& alt_chain,
bool discard_disconnected_chain)
1086 m_timestamps_and_difficulties_height = 0;
1089 CHECK_AND_ASSERT_MES(alt_chain.size(),
false,
"switch_to_alternative_blockchain: empty chain passed");
1092 if (!m_db->
block_exists(alt_chain.front()->second.bl.prev_id))
1094 LOG_ERROR(
"Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!");
1100 std::list<block> disconnected_chain;
1101 while (m_db->
top_block_hash() != alt_chain.front()->second.bl.prev_id)
1103 block b = pop_block_from_blockchain();
1104 disconnected_chain.push_front(b);
1107 auto split_height = m_db->
height();
1110 for(
auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++)
1112 auto ch_ent = *alt_ch_iter;
1116 bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
1122 MERROR(
"Failed to switch to alternative blockchain");
1127 rollback_blockchain_switching(disconnected_chain, split_height);
1132 add_block_as_invalid(ch_ent->second,
get_block_hash(ch_ent->second.bl));
1133 MERROR(
"The block was inserted as invalid while connecting new alternative chain, block_id: " <<
get_block_hash(ch_ent->second.bl));
1134 m_alternative_chains.erase(*alt_ch_iter++);
1136 for(
auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); )
1138 add_block_as_invalid((*alt_ch_to_orph_iter)->second, (*alt_ch_to_orph_iter)->first);
1139 m_alternative_chains.erase(*alt_ch_to_orph_iter++);
1146 const size_t discarded_blocks = disconnected_chain.size();
1147 if(!discard_disconnected_chain)
1150 for (
auto& old_ch_ent : disconnected_chain)
1153 bool r = handle_alternative_block(old_ch_ent,
get_block_hash(old_ch_ent), bvc);
1156 MERROR(
"Failed to push ex-main chain blocks to alternative chain ");
1164 for (
auto ch_ent: alt_chain)
1166 m_alternative_chains.erase(ch_ent);
1171 std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
1176 MGINFO_GREEN(
"REORGANIZE SUCCESS! on height: " << split_height <<
", new blockchain size: " << m_db->
height());
1182 difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(
const std::list<blocks_ext_by_hash::const_iterator>& alt_chain, block_extended_info& bei)
const
1184 if (m_fixed_difficulty)
1186 return m_db->
height() ? m_fixed_difficulty : 1;
1190 std::vector<uint64_t> timestamps;
1191 std::vector<difficulty_type> cumulative_difficulties;
1193 uint64_t v6height = 0, v7height = 0, v8height = 0;
1196 v6height = mainnet_hard_forks[1].height;
1197 v7height = mainnet_hard_forks[2].height;
1198 v8height = mainnet_hard_forks[3].height;
1199 }
else if(m_nettype ==
TESTNET) {
1200 v6height = testnet_hard_forks[1].height;
1201 v7height = testnet_hard_forks[2].height;
1202 v8height = testnet_hard_forks[3].height;
1204 v6height = stagenet_hard_forks[5].height;
1205 v7height = stagenet_hard_forks[5].height;
1206 v8height = stagenet_hard_forks[5].height;
1214 if((bei.height >= v8height) && (bei.height < v8height + 720))
1217 difficultyBlocksCount = bei.height - v8height;
1222 if(alt_chain.size()< difficultyBlocksCount)
1228 size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height;
1230 size_t main_chain_count = difficultyBlocksCount - std::min(
static_cast<size_t>(difficultyBlocksCount), alt_chain.size());
1233 main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
1235 size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
1237 if(!main_chain_start_offset)
1238 ++main_chain_start_offset;
1241 for(; main_chain_start_offset < main_chain_stop_offset; ++main_chain_start_offset)
1248 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);
1250 for (
auto it : alt_chain)
1252 timestamps.push_back(it->second.bl.timestamp);
1253 cumulative_difficulties.push_back(it->second.cumulative_difficulty);
1260 timestamps.resize(
static_cast<size_t>(difficultyBlocksCount));
1261 cumulative_difficulties.resize(
static_cast<size_t>(difficultyBlocksCount));
1263 size_t max_i = timestamps.size()-1;
1265 for(
auto it: boost::adaptors::reverse(alt_chain))
1267 timestamps[max_i -
count] = it->second.bl.timestamp;
1268 cumulative_difficulties[max_i -
count] = it->second.cumulative_difficulty;
1270 if(
count >= difficultyBlocksCount)
1295 MWARNING(
"The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.
miner_tx.
vin[0]).height <<
", expected: " <<
height);
1322 etn_in_use += o.amount;
1323 partial_block_reward =
false;
1328 MERROR_VER(
"miner tx output " <<
print_etn(o.amount) <<
" is not a valid decomposed amount");
1334 std::vector<uint64_t> last_blocks_weights;
1338 MERROR_VER(
"block weight " << cumulative_block_weight <<
" is bigger than allowed for this blockchain");
1341 if(base_reward + fee < etn_in_use && already_generated_coins > 0)
1349 if(base_reward + fee != etn_in_use && already_generated_coins > 0)
1351 MDEBUG(
"coinbase transaction doesn't use full amount of block reward: spent: " << etn_in_use <<
", block reward " << base_reward + fee <<
"(" << base_reward <<
"+" << fee <<
")");
1361 if(base_reward + fee != etn_in_use)
1362 partial_block_reward =
true;
1363 base_reward = etn_in_use - fee;
1369 void Blockchain::get_last_n_blocks_weights(std::vector<uint64_t>& weights,
size_t count)
const
1380 size_t start_offset = h - std::min<size_t>(h,
count);
1393 bool cached =
false;
1397 if (tip_height < blockchain_height &&
count == (
size_t)m_long_term_block_weights_cache_rolling_median.
size())
1400 cached = tip_hash == m_long_term_block_weights_cache_tip_hash;
1405 MTRACE(
"requesting " <<
count <<
" from " << start_height <<
", cached");
1406 return m_long_term_block_weights_cache_rolling_median.
median();
1411 if (tip_height > 0 &&
count == (
size_t)m_long_term_block_weights_cache_rolling_median.
size() && tip_height < blockchain_height)
1414 if (old_tip_hash == m_long_term_block_weights_cache_tip_hash)
1416 MTRACE(
"requesting " <<
count <<
" from " << start_height <<
", incremental");
1417 m_long_term_block_weights_cache_tip_hash = tip_hash;
1419 return m_long_term_block_weights_cache_rolling_median.
median();
1423 MTRACE(
"requesting " <<
count <<
" from " << start_height <<
", uncached");
1425 m_long_term_block_weights_cache_tip_hash = tip_hash;
1426 m_long_term_block_weights_cache_rolling_median.
clear();
1428 m_long_term_block_weights_cache_rolling_median.
insert(w);
1429 return m_long_term_block_weights_cache_rolling_median.
median();
1435 return m_current_block_cumul_weight_limit;
1441 return m_current_block_cumul_weight_median;
1458 size_t median_weight;
1465 if (m_btc_valid && !from_block) {
1472 MDEBUG(
"Using cached template");
1475 diffic = m_btc_difficulty;
1477 expected_reward = m_btc_expected_reward;
1480 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));
1481 invalidate_block_template_cache();
1489 auto it_prev = m_alternative_chains.find(*from_block);
1491 if(it_prev == m_alternative_chains.end() && !parent_in_main)
1493 MERROR(
"Unknown from block");
1498 std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1500 std::vector<uint64_t> timestamps;
1501 if (!build_alt_chain(*from_block, alt_chain, timestamps, bvc))
1509 height = from_block_height + 1;
1513 height = alt_chain.back()->second.height + 1;
1528 median_weight = it_prev->second.block_cumulative_weight - it_prev->second.block_cumulative_weight / 20;
1529 already_generated_coins = alt_chain.back()->second.already_generated_coins;
1537 diffic = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1545 median_weight = m_current_block_cumul_weight_limit / 2;
1552 if (!check_block_timestamp(b, median_ts))
1566 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1567 size_t real_txs_weight = 0;
1571 auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
1572 if (cur_res == m_tx_pool.m_transactions.end())
1574 LOG_ERROR(
"Creating block template: error: transaction not found");
1578 real_txs_weight += cur_tx.
weight;
1579 real_fee += cur_tx.
fee;
1582 LOG_ERROR(
"Creating block template: error: invalid transaction weight");
1588 LOG_ERROR(
"Creating block template: error: cannot get inputs amount");
1592 LOG_ERROR(
"Creating block template: error: invalid fee");
1595 if (txs_weight != real_txs_weight)
1597 LOG_ERROR(
"Creating block template: error: wrongly calculated transaction weight");
1599 if (fee != real_fee)
1601 LOG_ERROR(
"Creating block template: error: wrongly calculated fee");
1604 ", median weight " << median_weight <<
1605 ", already generated coins " << already_generated_coins <<
1606 ", transaction weight " << txs_weight <<
1616 size_t max_outs = hf_version >= 4 ? 1 : 11;
1617 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);
1620 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1622 ", cumulative weight " << cumulative_weight);
1624 for (
size_t try_count = 0; try_count != 10; ++try_count)
1626 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);
1630 if (coinbase_weight > cumulative_weight - txs_weight)
1632 cumulative_weight = txs_weight + coinbase_weight;
1633 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1634 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1635 ", cumulative weight " << cumulative_weight <<
" is greater than before");
1640 if (coinbase_weight < cumulative_weight - txs_weight)
1642 size_t delta = cumulative_weight - txs_weight - coinbase_weight;
1643 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1644 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1645 ", cumulative weight " << txs_weight + coinbase_weight <<
1646 " is less than before, adding " << delta <<
" zero bytes");
1657 MDEBUG(
"Miner tx creation has no luck with delta_extra size = " << delta <<
" and " << delta - 1);
1658 cumulative_weight += delta - 1;
1661 MDEBUG(
"Setting extra for block: " << b.
miner_tx.
extra.size() <<
", try_count=" << try_count);
1665 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1666 MDEBUG(
"Creating block template: miner tx weight " << coinbase_weight <<
1667 ", cumulative weight " << cumulative_weight <<
" is now good");
1673 if(!m_fallback_to_pow && hf_version >= 8) {
1674 sign_block(b, m_validator_key);
1679 LOG_ERROR(
"Failed to create_block_template with " << 10 <<
" tries");
1688 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.");
1695 bool Blockchain::verify_block_signature(
const block& b) {
1699 for(
auto &
key : public_keys) {
1717 bool Blockchain::complete_timestamps_vector(
uint64_t start_top_height, std::vector<uint64_t>& timestamps)
const
1726 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());
1727 size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
1728 timestamps.reserve(timestamps.size() + start_top_height - stop_offset);
1729 while (start_top_height != stop_offset)
1737 bool 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
1740 blocks_ext_by_hash::const_iterator alt_it = m_alternative_chains.find(prev_id);
1742 while(alt_it != m_alternative_chains.end())
1744 alt_chain.push_front(alt_it);
1745 timestamps.push_back(alt_it->second.bl.timestamp);
1746 alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id);
1751 if(!alt_chain.empty())
1758 if (!m_db->
block_exists(alt_chain.front()->second.bl.prev_id))
1760 MERROR(
"alternate chain does not appear to connect to main chain...");
1766 CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id,
false,
"alternative chain has wrong connection to main chain");
1767 complete_timestamps_vector(m_db->
get_block_height(alt_chain.front()->second.bl.prev_id), timestamps);
1775 CHECK_AND_ASSERT_MES(parent_in_main,
false,
"internal error: broken imperative condition: parent_in_main");
1793 m_timestamps_and_difficulties_height = 0;
1795 if(0 == block_height)
1804 if(!m_fallback_to_pow) {
1810 if(!m_validators->
isValid()) {
1815 if(!verify_block_signature(b)) {
1816 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has wrong digital signature");
1829 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());
1837 LOG_PRINT_L1(
"Block with id: " <<
id << std::endl <<
"has old version for height " << block_height);
1844 auto it_prev = m_alternative_chains.find(b.
prev_id);
1846 if(it_prev != m_alternative_chains.end() || parent_in_main)
1849 std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1850 std::vector<uint64_t> timestamps;
1851 if (!build_alt_chain(b.
prev_id, alt_chain, timestamps, bvc))
1855 block_extended_info bei = boost::value_initialized<block_extended_info>();
1858 bei.height = prev_height + 1;
1860 bei.already_generated_coins = block_reward + (alt_chain.size() ? it_prev->second.already_generated_coins : m_db->
get_block_already_generated_coins(prev_height));
1864 std::vector<uint8_t> prev_signatory = alt_chain.size() ? it_prev->second.bl.signatory : m_db->
get_block(b.
prev_id).
signatory;
1870 if(!check_block_timestamp(timestamps, b))
1872 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" for alternative chain, has invalid timestamp: " << b.
timestamp);
1877 bool is_a_checkpoint;
1878 if(!m_checkpoints.
check_block(bei.height,
id, is_a_checkpoint))
1880 LOG_ERROR(
"CHECKPOINT VALIDATION FAILED");
1886 difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1892 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);
1897 if(!prevalidate_miner_transaction(b, bei.height))
1908 if (alt_chain.size())
1910 bei.cumulative_difficulty = it_prev->second.cumulative_difficulty;
1917 bei.cumulative_difficulty += current_diff;
1921 auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(
id, bei));
1922 CHECK_AND_ASSERT_MES(i_res.second,
false,
"insertion of new alternative block returned as it already exist");
1923 alt_chain.push_back(i_res.first);
1929 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);
1931 bool r = switch_to_alternative_blockchain(alt_chain,
true);
1938 else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty)
1941 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);
1943 bool r = switch_to_alternative_blockchain(alt_chain,
false);
1952 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);
1960 MERROR_VER(
"Block recognized as orphaned and rejected, id = " <<
id <<
", height " << block_height
1961 <<
", parent in alt " << (it_prev != m_alternative_chains.end()) <<
", parent in main " << parent_in_main
1972 if(start_offset >= m_db->
height())
1980 for(
const auto& blk :
blocks)
1982 std::vector<crypto::hash> missed_ids;
1984 CHECK_AND_ASSERT_MES(!missed_ids.size(),
false,
"has missed transactions in own block in main blockchain");
1995 if(start_offset >=
height)
1999 for(
size_t i = start_offset; i < start_offset +
count && i <
height;i++)
2024 std::vector<std::pair<cryptonote::blobdata,block>>
blocks;
2029 std::vector<crypto::hash> missed_tx_ids;
2038 if (missed_tx_ids.size() != 0)
2043 LOG_ERROR(
"Error retrieving blocks, missed " << missed_tx_ids.size()
2044 <<
" transactions for block with hash: " <<
get_block_hash(bl.second)
2052 rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
2070 blocks.reserve(m_alternative_chains.size());
2071 for (
const auto& alt_bl: m_alternative_chains)
2073 blocks.push_back(alt_bl.second.bl);
2082 return m_alternative_chains.size();
2093 while (num_outs > 0)
2118 res.outs.reserve(req.outputs.size());
2120 std::vector<cryptonote::output_data_t> data;
2123 std::vector<uint64_t> amounts, offsets;
2124 amounts.reserve(req.outputs.size());
2125 offsets.reserve(req.outputs.size());
2126 for (
const auto &i: req.outputs)
2128 amounts.push_back(i.amount);
2129 offsets.push_back(i.index);
2132 if (data.size() != req.outputs.size())
2134 MERROR(
"Unexpected output data size: expected " << req.outputs.size() <<
", got " << data.size());
2137 for (
const auto &t: data)
2138 res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
2142 for (
size_t i = 0; i < req.outputs.size(); ++i)
2145 res.outs[i].txid = toi.first;
2149 catch (
const std::exception &e)
2159 key = o_data.pubkey;
2160 mask = o_data.commitment;
2172 case STAGENET: start_height = stagenet_hard_forks[3].height;
break;
2173 case TESTNET: start_height = testnet_hard_forks[3].height;
break;
2174 case MAINNET: start_height = mainnet_hard_forks[3].height;
break;
2175 case FAKECHAIN: start_height = 0;
break;
2176 default:
return false;
2183 if (to_height > 0 && to_height < from_height)
2186 const uint64_t real_start_height = start_height;
2187 if (from_height > start_height)
2188 start_height = from_height;
2190 distribution.clear();
2194 if (start_height >= db_height || to_height >= db_height)
2198 std::vector<uint64_t> heights;
2199 heights.reserve(to_height + 1 - start_height);
2200 uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
2201 for (
uint64_t h = real_start_height; h <= to_height; ++h)
2202 heights.push_back(h);
2204 if (start_height > 0)
2206 base = distribution[0];
2207 distribution.erase(distribution.begin());
2227 if(qblock_ids.empty())
2229 MCERROR(
"net.p2p",
"Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() <<
", dropping connection");
2237 if(qblock_ids.back() != gen_hash)
2240 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");
2246 auto bl_it = qblock_ids.begin();
2248 for(; bl_it != qblock_ids.end(); bl_it++)
2255 catch (
const std::exception& e)
2257 MWARNING(
"Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
2264 if(bl_it == qblock_ids.end())
2266 MERROR(
"Internal error handling connection, can't find split point");
2271 starter_offset = split_height;
2288 MERROR(
"Attempted to get block difficulty for height above blockchain height");
2298 template<
class t_
ids_container,
class t_blocks_container,
class t_missed_container>
2305 for (
const auto& block_hash : block_ids)
2315 LOG_ERROR(
"Invalid block: " << block_hash);
2317 missed_bs.push_back(block_hash);
2321 missed_bs.push_back(block_hash);
2323 catch (
const std::exception& e)
2333 template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2340 for (
const auto& tx_hash : txs_ids)
2347 else if (!pruned && m_db->
get_tx_blob(tx_hash, tx))
2350 missed_txs.push_back(tx_hash);
2352 catch (
const std::exception& e)
2363 const char* begin =
static_cast<const char*
>(bd.data());
2364 const char* end = begin + bd.size();
2365 int read = tools::read_varint(begin, end,
version);
2367 throw std::runtime_error(
"Internal error getting transaction version");
2371 template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2378 for (
const auto& tx_hash : txs_ids)
2388 MERROR(
"Prunable data hash not found for " << tx_hash);
2392 std::get<3>(txs.back()).clear();
2395 missed_txs.push_back(tx_hash);
2397 catch (
const std::exception& e)
2405 template<
class t_
ids_container,
class t_tx_container,
class t_missed_container>
2412 for (
const auto& tx_hash : txs_ids)
2427 missed_txs.push_back(tx_hash);
2429 catch (
const std::exception& e)
2453 uint64_t stop_height = current_height;
2479 resp.cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
2480 resp.cumulative_difficulty_top64 = ((wide_cumulative_difficulty >> 64) & 0xffffffffffffffff).convert_to<
uint64_t>();
2490 bool 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
2496 if(req_start_block > 0)
2499 if (req_start_block >= m_db->
height())
2503 start_height = req_start_block;
2515 size_t count = 0, size = 0;
2516 blocks.reserve(std::min(std::min(max_count, (
size_t)10000), (
size_t)(total_height - start_height)));
2524 std::vector<crypto::hash> mis;
2525 std::vector<cryptonote::blobdata> txs;
2528 size +=
blocks.back().first.first.size();
2529 for (
const auto &t: txs)
2533 blocks.back().second.reserve(txs.size());
2534 for (
size_t i = 0; i < txs.size(); ++i)
2547 return add_block_as_invalid(bei, h);
2550 bool Blockchain::add_block_as_invalid(
const block_extended_info& bei,
const crypto::hash& h)
2554 auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
2555 CHECK_AND_ASSERT_MES(i_res.second,
false,
"at insertion invalid by tx returned status existed");
2556 MINFO(
"BLOCK ADDED AS INVALID: " << h << std::endl <<
", prev_id=" << bei.bl.prev_id <<
", m_invalid_blocks count=" << m_invalid_blocks.size());
2567 LOG_PRINT_L2(
"block " <<
id <<
" found in main chain");
2571 if(m_alternative_chains.count(
id))
2573 LOG_PRINT_L2(
"block " <<
id <<
" found in m_alternative_chains");
2577 if(m_invalid_blocks.count(
id))
2579 LOG_PRINT_L2(
"block " <<
id <<
" found in m_invalid_blocks");
2590 return handle_block_to_main_chain(bl,
id, bvc);
2609 bool Blockchain::check_for_double_spend(
const transaction& tx, key_images_container& keys_this_block)
const
2613 struct add_transaction_input_visitor:
public boost::static_visitor<bool>
2615 key_images_container& m_spent_keys;
2617 add_transaction_input_visitor(key_images_container& spent_keys,
BlockchainDB* db) :
2618 m_spent_keys(spent_keys), m_db(db)
2632 auto r = m_spent_keys.insert(ki);
2643 bool operator()(
const txin_gen& tx)
const
2663 if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in))
2680 MERROR_VER(
"get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2701 MERROR_VER(
"get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2711 indexs = indices.front();
2717 #if defined(PER_BLOCK_CHECKPOINT)
2719 if (m_db->
height() < m_blocks_hash_check.size())
2724 if(m_show_time_stats)
2726 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;
2727 MINFO(
"HASH: " <<
"-" <<
" I/M/O: " << tx.
vin.size() <<
"/" << ring_size <<
"/" << tx.
vout.size() <<
" H: " << 0 <<
" chcktx: " <<
a);
2746 #if defined(PER_BLOCK_CHECKPOINT)
2748 if (m_db->
height() < m_blocks_hash_check.size() && kept_by_block)
2750 max_used_block_id = null_hash;
2751 max_used_block_height = 0;
2759 if(m_show_time_stats)
2761 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;
2768 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());
2782 for (
auto &o: tx.
vout) {
2792 for (
const auto &o: tx.
vout) {
2795 const txout_to_key &out_to_key = boost::get<txout_to_key>(o.target);
2818 std::vector<uint64_t> supported_prefixes{address_prefix, integrated_address_prefix, subaddress_prefix};
2820 if(std::find(supported_prefixes.begin(), supported_prefixes.end(), out_to_key_public.
m_address_prefix) == supported_prefixes.end()) {
2838 const auto &in_to_key = boost::get<txin_to_key>(in);
2855 const auto &in_to_key = boost::get<txin_to_key_public>(in);
2863 bool Blockchain::expand_transaction_2(
transaction &tx,
const crypto::hash &tx_prefix_hash,
const std::vector<std::vector<rct::ctkey>> &pubkeys)
2877 size_t sig_index = 0;
2878 if(pmax_used_block_height)
2879 *pmax_used_block_height = 0;
2887 if (tx.
version > max_tx_version)
2889 MERROR_VER(
"transaction version " << (
unsigned)tx.
version <<
" is higher than max accepted version " << max_tx_version);
2895 if (tx.
version < min_tx_version)
2897 MERROR_VER(
"transaction version " << (
unsigned)tx.
version <<
" is lower than min accepted version " << min_tx_version);
2906 std::unordered_set<std::string> ins;
2907 for(
const auto& in: tx.
vin)
2925 for (
size_t i = 0; i < tx.
vin.size(); ++i)
2931 if (in_to_key.
amount <= 0)
2976 if (hf_version >= 6)
2978 size_t n_unmixable = 0, n_mixable = 0;
2979 size_t mixin = std::numeric_limits<size_t>::max();
2981 for (
const auto& txin : tx.
vin)
2986 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
2993 <<
"), and more than one mixable input with unmixable inputs");
2999 if (in_to_key.
amount == 0)
3011 if (n_outputs <= min_mixin)
3028 if (mixin < min_mixin)
3030 if (n_unmixable == 0)
3038 MERROR_VER(
"Tx " <<
get_transaction_hash(tx) <<
" has too low ring size (" << (mixin + 1) <<
"), and more than one mixable input with unmixable inputs");
3048 for (
size_t n = 0; n < tx.
vin.size(); ++n)
3053 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3054 if (last_key_image && memcmp(&in_to_key.
k_image, last_key_image,
sizeof(*last_key_image)) >= 0)
3056 MERROR_VER(
"transaction has unsorted inputs");
3060 last_key_image = &in_to_key.
k_image;
3064 auto it = m_check_txin_table.find(tx_prefix_hash);
3065 if(it == m_check_txin_table.end())
3067 m_check_txin_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, bool>());
3068 it = m_check_txin_table.find(tx_prefix_hash);
3069 assert(it != m_check_txin_table.end());
3072 std::vector<std::vector<rct::ctkey>> pubkeys(tx.
vin.size());
3073 std::vector < uint64_t > results;
3074 results.resize(tx.
vin.size(), 0);
3081 for (
const auto& txin : tx.
vin)
3086 const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3101 #if defined(CACHE_VIN_RESULTS)
3102 auto itk = it->second.find(in_to_key.
k_image);
3103 if(itk != it->second.end())
3121 it->second[in_to_key.
k_image] =
false;
3123 if (pmax_used_block_height)
3125 MERROR_VER(
" *pmax_used_block_height: " << *pmax_used_block_height);
3135 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);
3139 check_ring_signature(tx_prefix_hash, in_to_key.
k_image, pubkeys[sig_index], tx.
signatures[sig_index], results[sig_index]);
3140 if (!results[sig_index])
3142 it->second[in_to_key.
k_image] =
false;
3145 if (pmax_used_block_height)
3147 MERROR_VER(
"*pmax_used_block_height: " << *pmax_used_block_height);
3152 it->second[in_to_key.
k_image] =
true;
3160 waiter.
wait(&tpool);
3162 bool failed =
false;
3163 for (
size_t i = 0; i < tx.
vin.size(); i++)
3165 const txin_to_key& in_to_key = boost::get<txin_to_key>(tx.
vin[i]);
3166 it->second[in_to_key.
k_image] = results[i];
3167 if(!failed && !results[i])
3173 MERROR_VER(
"Failed to check ring signatures!");
3183 std::vector<const crypto::public_key *> p_output_keys;
3184 p_output_keys.reserve(pubkeys.size());
3185 for (
auto &
key : pubkeys)
3211 if (median_block_weight < min_block_weight)
3212 median_block_weight = min_block_weight;
3218 div128_32(hi, lo, min_block_weight, &hi, &lo);
3219 div128_32(hi, lo, median_block_weight, &hi, &lo);
3227 uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
3228 lo = mul128(unscaled_fee_base, block_reward, &hi);
3234 div128_32(hi, lo, 1000000, &hi, &lo);
3239 uint64_t qlo = (lo + mask - 1) / mask * mask;
3252 uint64_t already_generated_coins = 0;
3256 median = m_current_block_cumul_weight_limit / 2;
3269 needed_fee = tx_weight * fee_per_byte;
3272 needed_fee = (needed_fee + mask - 1) / mask * mask;
3287 needed_fee = tx_weight / 1024;
3288 needed_fee += (tx_weight % 1024) ? 1 : 0;
3289 needed_fee *= fee_per_kb;
3292 if (fee < needed_fee - needed_fee / 50)
3317 std::vector<uint64_t> weights;
3319 weights.reserve(grace_blocks);
3320 for (
size_t i = 0; i < grace_blocks; ++i)
3321 weights.push_back(min_block_weight);
3324 if(
median <= min_block_weight)
3325 median = min_block_weight;
3338 MDEBUG(
"Estimating " << grace_blocks <<
"-block fee at " <<
print_etn(fee) <<
"/" << (per_byte ?
"byte" :
"kB"));
3345 bool Blockchain::is_tx_spendtime_unlocked(
uint64_t unlock_time)
const
3372 bool 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)
3380 struct outputs_visitor
3382 std::vector<rct::ctkey >& m_output_keys;
3384 outputs_visitor(std::vector<rct::ctkey>& output_keys,
const Blockchain& bch) :
3385 m_output_keys(output_keys), m_bch(bch)
3391 if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
3393 MERROR_VER(
"One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
3402 m_output_keys.push_back(
rct::ctkey({rct::pk2rct(pubkey), commitment}));
3407 output_keys.clear();
3410 outputs_visitor vi(output_keys, *
this);
3411 if (!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height))
3419 MERROR_VER(
"Output keys for tx with amount = " << txin.
amount <<
" and count indexes " << txin.
key_offsets.size() <<
" returned wrong keys count " << output_keys.size());
3422 if (tx_version == 1) {
3423 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());
3430 uint64_t Blockchain::get_adjusted_time()
const
3438 bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps,
const block& b,
uint64_t& median_ts)
const
3459 bool Blockchain::check_block_timestamp(
const block& b,
uint64_t& median_ts)
const
3468 const auto h = m_db->
height();
3476 std::vector<uint64_t> timestamps;
3480 timestamps.reserve(h - offset);
3481 for(;offset < h; ++offset)
3486 return check_block_timestamp(timestamps, b, median_ts);
3489 void Blockchain::return_tx_to_pool(std::vector<std::pair<transaction, blobdata>> &txs)
3492 for (
auto& tx : txs)
3502 if (!m_tx_pool.
add_tx(tx.first, tx_hash, tx.second, weight, tvc,
true,
true,
false,
version))
3514 for (
const auto &txid: txids)
3520 bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
3521 MINFO(
"Removing txid " << txid <<
" from the pool");
3522 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))
3524 MERROR(
"Failed to remove txid " << txid <<
" from the pool");
3542 static bool seen_future_version =
false;
3547 ++blockchain_height;
3550 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"has wrong prev_id: " << bl.
prev_id << std::endl <<
"expected: " << top_hash);
3558 if(!m_fallback_to_pow) {
3564 if(!m_validators->
isValid()) {
3569 if(!verify_block_signature(bl) && !m_ignore_bsig) {
3570 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has wrong digital signature");
3575 MERROR_VER(
"Block with id: " <<
id << std::endl <<
" has the same signatory as the previous block, which is not allowed");
3586 seen_future_version =
true;
3588 MCLOG_RED(level,
"global",
"**********************************************************************");
3589 MCLOG_RED(level,
"global",
"A block was seen on the network with a version higher than the last");
3590 MCLOG_RED(level,
"global",
"known one. This may be an old version of the daemon, and a software");
3591 MCLOG_RED(level,
"global",
"update may be required to sync further. Try running: update check");
3592 MCLOG_RED(level,
"global",
"**********************************************************************");
3596 if (!m_hardfork->
check(bl))
3608 if(!check_block_timestamp(bl))
3610 MERROR_VER(
"Block with id: " <<
id << std::endl <<
"has invalid timestamp: " << bl.
timestamp);
3642 bool precomputed =
false;
3643 bool fast_check =
false;
3644 #if defined(PER_BLOCK_CHECKPOINT)
3645 if (blockchain_height < m_blocks_hash_check.size())
3648 if (memcmp(&
hash, &m_blocks_hash_check[m_db->
height()],
sizeof(
hash)) != 0)
3650 MERROR_VER(
"Block with id is INVALID: " <<
id);
3660 auto it = m_blocks_longhash_table.find(
id);
3661 if (it != m_blocks_longhash_table.end())
3664 proof_of_work = it->second;
3670 if(!
check_hash(proof_of_work, current_diffic))
3672 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);
3682 if(!m_checkpoints.
check_block(blockchain_height,
id))
3684 LOG_ERROR(
"CHECKPOINT VALIDATION FAILED");
3692 longhash_calculating_time += m_fake_pow_calc_time;
3697 if(!prevalidate_miner_transaction(bl, blockchain_height))
3699 MERROR_VER(
"Block with id: " <<
id <<
" failed to pass prevalidation");
3705 size_t cumulative_block_weight = coinbase_weight;
3707 std::vector<std::pair<transaction, blobdata>> txs;
3708 key_images_container keys;
3719 size_t tx_index = 0;
3728 size_t tx_weight = 0;
3730 bool relayed =
false, do_not_relay =
false, double_spend_seen =
false, nonexistent_utxo_seen =
false;
3736 MERROR(
"Block with id: " <<
id <<
" attempting to add transaction already in blockchain with id: " << tx_id);
3738 return_tx_to_pool(txs);
3747 if(!m_tx_pool.
take_tx(tx_id, tx_tmp, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3749 MERROR_VER(
"Block with id: " <<
id <<
" has at least one unknown transaction with id: " << tx_id);
3751 return_tx_to_pool(txs);
3781 #if defined(PER_BLOCK_CHECKPOINT)
3789 MERROR_VER(
"Block with id: " <<
id <<
" has at least one transaction (id: " << tx_id <<
") with wrong inputs.");
3792 add_block_as_invalid(bl,
id);
3793 MERROR_VER(
"Block with id " <<
id <<
" added as invalid because of wrong inputs in transactions");
3794 MERROR_VER(
"tx_index " << tx_index <<
", m_blocks_txs_check " << m_blocks_txs_check.size() <<
":");
3795 for (
const auto &h: m_blocks_txs_check)
MERROR_VER(
" " << h);
3797 return_tx_to_pool(txs);
3801 #if defined(PER_BLOCK_CHECKPOINT)
3806 if (tx_index >= m_blocks_txs_check.size() || memcmp(&m_blocks_txs_check[tx_index++], &tx_id,
sizeof(tx_id)) != 0)
3808 MERROR_VER(
"Block with id: " <<
id <<
" has at least one transaction (id: " << tx_id <<
") with wrong inputs.");
3810 add_block_as_invalid(bl,
id);
3811 MERROR_VER(
"Block with id " <<
id <<
" added as invalid because of wrong inputs in transactions");
3813 return_tx_to_pool(txs);
3821 cumulative_block_weight += tx_weight;
3824 m_blocks_txs_check.clear();
3831 MERROR_VER(
"Block with id: " <<
id <<
" has incorrect miner transaction");
3833 return_tx_to_pool(txs);
3838 size_t block_weight;
3842 block_weight = cumulative_block_weight;
3843 cumulative_difficulty = current_diffic;
3848 already_generated_coins = base_reward < (
ETN_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward :
ETN_SUPPLY;
3849 if(blockchain_height)
3854 block_processing_time += m_fake_pow_calc_time;
3865 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);
3869 LOG_ERROR(
"Error adding block with hash: " <<
id <<
" to blockchain, what = " << e.
what());
3870 m_batch_success =
false;
3872 return_tx_to_pool(txs);
3875 catch (
const std::exception& e)
3878 LOG_ERROR(
"Error adding block with hash: " <<
id <<
" to blockchain, what = " << e.what());
3879 m_batch_success =
false;
3881 return_tx_to_pool(txs);
3887 LOG_ERROR(
"Blocks that failed verification should not reach here");
3893 if (!update_next_cumulative_weight_limit())
3895 MERROR(
"Failed to update next cumulative weight limit");
3896 pop_block_from_blockchain();
3900 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");
3901 if(m_show_time_stats)
3903 MINFO(
"Height: " << new_height <<
" coinbase weight: " << coinbase_weight <<
" cumm: "
3904 << cumulative_block_weight <<
" p/t: " << block_processing_time <<
" ("
3905 << target_calculating_time <<
"/" << longhash_calculating_time <<
"/"
3906 <<
t1 <<
"/" <<
t2 <<
"/" <<
t3 <<
"/" << t_exists <<
"/" << t_pool
3907 <<
"/" << t_checktx <<
"/" << t_dblspnd <<
"/" << vmt <<
"/" << addblock <<
")ms");
3916 invalidate_block_template_cache();
3918 std::shared_ptr<tools::Notify> block_notify = m_block_notify;
3957 const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
3961 return block_weight;
3963 uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
3966 uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
3967 uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
3969 return long_term_block_weight;
3972 bool Blockchain::update_next_cumulative_weight_limit(
uint64_t *long_term_effective_median_block_weight)
3974 PERF_TIMER(update_next_cumulative_weight_limit);
3986 std::vector<uint64_t> weights;
3989 long_term_block_weight = weights.back();
4002 uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4003 if (nblocks == db_height)
4005 long_term_median = get_long_term_block_weight_median(db_height - nblocks - 1, nblocks);
4010 uint64_t short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5;
4011 long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4015 long_term_median = long_term_block_weight;
4020 m_long_term_block_weights_cache_rolling_median.
insert(long_term_block_weight);
4021 long_term_median = m_long_term_block_weights_cache_rolling_median.
median();
4025 std::vector<uint64_t> weights;
4031 m_current_block_cumul_weight_median = effective_median_block_weight;
4034 if (m_current_block_cumul_weight_median <= full_reward_zone)
4035 m_current_block_cumul_weight_median = full_reward_zone;
4037 m_current_block_cumul_weight_limit = m_current_block_cumul_weight_median * 2;
4039 if (long_term_effective_median_block_weight)
4040 *long_term_effective_median_block_weight = m_long_term_effective_median_block_weight;
4057 LOG_PRINT_L3(
"block with id = " <<
id <<
" already exists");
4059 m_blocks_txs_check.clear();
4069 bool r = handle_alternative_block(bl,
id, bvc);
4070 m_blocks_txs_check.clear();
4076 return handle_block_to_main_chain(bl,
id, bvc);
4089 for (
const auto& pt : pts)
4092 if (pt.first >= blockchain_height)
4102 LOG_ERROR(
"Local blockchain failed to pass a checkpoint, rolling back!");
4103 std::list<block>
empty;
4104 rollback_blockchain_switching(
empty, pt.first - 2);
4108 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");
4128 if (m_enforce_dns_checkpoints && check_dns && !m_offline)
4135 else if (check_dns && !m_offline)
4145 MERROR(
"One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
4156 m_enforce_dns_checkpoints = enforce_checkpoints;
4171 map.emplace(
id, pow);
4183 MTRACE(
"Blockchain::" << __func__);
4189 if (m_batch_success)
4195 catch (
const std::exception &e)
4197 MERROR(
"Exception in cleanup_handle_incoming_blocks: " << e.what());
4200 if (
success && m_sync_counter > 0)
4208 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)))
4210 MDEBUG(
"Sync threshold met, syncing");
4214 m_bytes_to_sync = 0;
4217 else if(m_db_sync_mode ==
db_sync)
4229 m_blocks_longhash_table.clear();
4230 m_scan_table.clear();
4231 m_blocks_txs_check.clear();
4232 m_check_txin_table.clear();
4249 catch (
const std::exception& e)
4268 MTRACE(
"Blockchain::" << __func__);
4272 size_t total_txs = 0;
4292 if(blocks_entry.size() == 0)
4295 for (
const auto &entry : blocks_entry)
4297 bytes += entry.block.size();
4298 for (
const auto &tx_blob : entry.txs)
4300 bytes += tx_blob.size();
4302 total_txs += entry.txs.size();
4304 m_bytes_to_sync += bytes;
4305 while (!(stop_batch = m_db->
batch_start(blocks_entry.size(), bytes))) {
4306 m_blockchain_lock.
unlock();
4310 m_blockchain_lock.
lock();
4312 m_batch_success =
true;
4315 if ((
height + blocks_entry.size()) < m_blocks_hash_check.size())
4318 bool blocks_exist =
false;
4321 blocks.resize(blocks_entry.size());
4326 if(threads > m_max_prepare_blocks_threads)
4327 threads = m_max_prepare_blocks_threads;
4329 unsigned int batches = blocks_entry.size() / threads;
4330 unsigned int extra = blocks_entry.size() % threads;
4331 MDEBUG(
"block_batches: " << batches);
4332 std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
4333 auto it = blocks_entry.begin();
4334 unsigned blockidx = 0;
4337 for (
unsigned i = 0; i < threads; i++)
4339 for (
unsigned int j = 0; j < batches; j++, ++blockidx)
4352 MDEBUG(
"Skipping prepare blocks. New blocks don't belong to chain.");
4358 blocks_exist =
true;
4360 std::advance(it, 1);
4364 for (
unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
4373 blocks_exist =
true;
4375 std::advance(it, 1);
4380 m_blocks_longhash_table.clear();
4383 for (
unsigned int i = 0; i < threads; i++)
4385 unsigned nblocks = batches;
4389 thread_height += nblocks;
4392 waiter.
wait(&tpool);
4397 for (
const auto & map : maps)
4399 m_blocks_longhash_table.insert(map.begin(), map.end());
4409 MDEBUG(
"Skipping remainder of prepare blocks. Blocks exist.");
4413 m_fake_scan_time = 0;
4414 m_fake_pow_calc_time = 0;
4416 m_scan_table.clear();
4417 m_check_txin_table.clear();
4420 m_fake_pow_calc_time = prepare / blocks_entry.size();
4422 if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
4423 MDEBUG(
"Prepare blocks took: " << prepare <<
" ms");
4428 std::vector < uint64_t > amounts;
4430 std::map<uint64_t, std::vector<uint64_t>> offset_map;
4432 std::map<uint64_t, std::vector<output_data_t>> tx_map;
4433 std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
4435 #define SCAN_TABLE_QUIT(m) \
4438 m_scan_table.clear(); \
4443 size_t tx_index = 0, block_index = 0;
4444 for (
const auto &entry : blocks_entry)
4449 for (
const auto &tx_blob : entry.txs)
4451 if (tx_index >= txes.size())
4461 auto its = m_scan_table.find(tx_prefix_hash);
4462 if (its != m_scan_table.end())
4465 m_scan_table.emplace(tx_prefix_hash, std::unordered_map<
crypto::key_image, std::vector<output_data_t>>());
4466 its = m_scan_table.find(tx_prefix_hash);
4467 assert(its != m_scan_table.end());
4472 for (
const auto &txin : tx.
vin)
4474 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4477 auto it = its->second.find(in_to_key.
k_image);
4478 if (it != its->second.end())
4481 amounts.push_back(in_to_key.
amount);
4486 std::sort(amounts.begin(), amounts.end());
4487 auto last = std::unique(amounts.begin(), amounts.end());
4488 amounts.erase(last, amounts.end());
4491 for (
const uint64_t &amount : amounts)
4493 if (offset_map.find(amount) == offset_map.end())
4494 offset_map.emplace(amount, std::vector<uint64_t>());
4496 if (tx_map.find(amount) == tx_map.end())
4497 tx_map.emplace(amount, std::vector<output_data_t>());
4503 for (
const auto &txin : tx.
vin)
4505 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4508 for (
const auto & offset : absolute_offsets)
4509 offset_map[in_to_key.
amount].push_back(offset);
4518 for (
auto &offsets : offset_map)
4520 std::sort(offsets.second.begin(), offsets.second.end());
4521 auto last = std::unique(offsets.second.begin(), offsets.second.end());
4522 offsets.second.erase(last, offsets.second.end());
4530 if (threads > 1 && amounts.size() > 1)
4534 for (
size_t i = 0; i < amounts.size(); i++)
4539 waiter.
wait(&tpool);
4543 for (
size_t i = 0; i < amounts.size(); i++)
4552 for (
const auto &entry : blocks_entry)
4557 for (
const auto &tx_blob : entry.txs)
4559 if (tx_index >= txes.size())
4562 const crypto::hash &tx_prefix_hash = txes[tx_index].second;
4565 auto its = m_scan_table.find(tx_prefix_hash);
4566 if (its == m_scan_table.end())
4571 for (
const auto &txin : tx.
vin)
4573 const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4576 std::vector<output_data_t> outputs;
4577 for (
const uint64_t & offset_needed : needed_offsets)
4582 for (
const uint64_t &offset_found : offset_map[in_to_key.
amount])
4584 if (offset_needed == offset_found)
4593 if (found && pos < tx_map[in_to_key.
amount].size())
4594 outputs.push_back(tx_map[in_to_key.
amount].at(pos));
4599 its->second.emplace(in_to_key.
k_image, outputs);
4607 m_fake_scan_time = scantable / total_txs;
4608 if(m_show_time_stats)
4609 MDEBUG(
"Prepare scantable took: " << scantable <<
" ms");
4668 m_db_default_sync =
true;
4671 m_db_sync_mode = sync_mode;
4672 m_fast_sync = fast_sync;
4673 m_db_sync_on_blocks = sync_on_blocks;
4674 m_db_sync_threshold = sync_threshold;
4675 m_max_prepare_blocks_threads = maxthreads;
4677 if(!validator_key.empty()) {
4678 m_validator_key = boost::algorithm::unhex(validator_key);
4687 if (m_db_default_sync)
4701 static const std::vector<HardFork::Params> mainnet_heights = []()
4703 std::vector<HardFork::Params> heights;
4704 for (
const auto& i : mainnet_hard_forks)
4705 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4708 static const std::vector<HardFork::Params> testnet_heights = []()
4710 std::vector<HardFork::Params> heights;
4711 for (
const auto& i : testnet_hard_forks)
4712 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4715 static const std::vector<HardFork::Params> stagenet_heights = []()
4717 std::vector<HardFork::Params> heights;
4718 for (
const auto& i : stagenet_hard_forks)
4719 heights.emplace_back(i.version, i.height, i.threshold, i.time);
4722 static const std::vector<HardFork::Params> dummy;
4725 case MAINNET:
return mainnet_heights;
4726 case TESTNET:
return testnet_heights;
4727 case STAGENET:
return stagenet_heights;
4728 default:
return dummy;
4749 std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
4751 for (
const auto &i: m_alternative_chains)
4755 for (
const auto &j: m_alternative_chains)
4757 if (j.second.bl.prev_id == top)
4765 std::vector<crypto::hash> chain;
4766 auto h = i.second.bl.prev_id;
4767 chain.push_back(top);
4768 blocks_ext_by_hash::const_iterator prev;
4769 while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
4772 h = prev->second.bl.prev_id;
4774 chains.push_back(std::make_pair(i.second, chain));
4785 #if defined(PER_BLOCK_CHECKPOINT)
4786 static const char expected_block_hashes_hash[] =
"53a9384ca5384025e657622b5d66fac67c03f9b863b91abe9516eda47cceaeb5";
4789 if (get_checkpoints ==
nullptr || !m_fast_sync)
4803 MERROR(
"Failed to hash precomputed blocks data");
4806 MINFO(
"precomputed blocks hash: " <<
hash <<
", expected " << expected_block_hashes_hash);
4810 MERROR(
"Failed to parse expected block hashes hash");
4814 if (
hash != expected_hash)
4816 MERROR(
"Block hash data does not match expected hash");
4824 const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
4825 if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) /
sizeof(
hash))
4827 MERROR(
"Block hash data is too large");
4830 const size_t size_needed = 4 + nblocks *
sizeof(
crypto::hash);
4831 if(nblocks > 0 && nblocks > m_db->
height() &&
checkpoints.size() >= size_needed)
4834 for (
uint32_t i = 0; i < nblocks; i++)
4838 p +=
sizeof(
hash.data);
4839 m_blocks_hash_check.push_back(
hash);
4841 MINFO(nblocks <<
" block hashes loaded");
4850 std::vector<transaction> txs;
4855 bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
4861 m_tx_pool.
take_tx(tx_hash, pool_tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen);
4871 #if defined(PER_BLOCK_CHECKPOINT)
4872 return height < m_blocks_hash_check.size();
4880 m_blockchain_lock.
lock();
4885 m_blockchain_lock.
unlock();
4913 void Blockchain::invalidate_block_template_cache()
4915 MDEBUG(
"Invalidating block template cache");
4916 m_btc_valid =
false;
4921 MDEBUG(
"Setting block template cache");
4924 m_btc_nonce = nonce;
4925 m_btc_difficulty = diff;
4927 m_btc_expected_reward = expected_reward;
4928 m_btc_pool_cookie = pool_cookie;
4943 template bool Blockchain::get_transactions(
const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&)
const;
4945 template 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()
thrown when a requested block does not exist
The BlockchainDB backing store interface declaration/contract.
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const =0
get a txpool transaction's blob
virtual bool for_all_key_images(std::function< bool(const crypto::key_image &)>) const =0
runs a function over all key images stored
virtual bool check_chainstate_utxo(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
virtual 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 =0
runs a function over all txpool transactions
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block's hash
virtual bool get_prunable_tx_hash(const crypto::hash &tx_hash, crypto::hash &prunable_hash) const =0
fetches the prunable transaction hash
virtual void set_hard_fork(HardFork *hf)
virtual 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) const =0
return a histogram of outputs on the blockchain
virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the transaction blob with the given hash
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const =0
get the number of transactions in the txpool
virtual void close()=0
close the BlockchainDB
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &details)=0
update a txpool transaction's metadata
virtual uint64_t get_tx_count() const =0
fetches the total number of transactions ever
virtual void batch_stop()=0
ends a batch transaction
virtual uint64_t get_block_height(const crypto::hash &h) const =0
gets the height of the block with a given hash
virtual block get_block(const crypto::hash &h) const
fetches the block with the given hash
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block's cumulative difficulty
virtual uint64_t get_tx_block_height(const crypto::hash &h) const =0
fetches the height of a transaction's block
virtual bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const =0
get a txpool transaction's metadata
virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector< uint64_t > &distribution, uint64_t &base) const =0
virtual bool for_all_transactions(std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const =0
runs a function over all transactions stored
virtual std::vector< uint64_t > get_block_weights(uint64_t start_height, size_t count) const =0
fetch the last N blocks' weights
virtual bool is_read_only() const =0
is BlockchainDB in read-only mode?
virtual uint64_t height() const =0
fetch the current blockchain height
virtual bool can_thread_bulk_indices() const =0
epee::critical_section m_synchronization_lock
A lock, currently for when BlockchainLMDB needs to resize the backing db file.
virtual uint64_t get_top_block_timestamp() const =0
fetch the top block's timestamp
virtual void safesyncmode(const bool onoff)=0
toggle safe syncs for the DB
virtual void remove_txpool_tx(const crypto::hash &txid)=0
remove a txpool transaction
virtual block get_top_block() const =0
fetch the top block
virtual uint64_t get_num_outputs(const uint64_t &amount) const =0
fetches the number of outputs of a given amount
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block's already generated coins
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output's tx hash and index
virtual void sync()=0
sync the BlockchainDB with disk
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block's cumulative difficulty
bool is_open() const
Gets the current open/ready state of the BlockchainDB.
virtual std::vector< uint64_t > get_block_cumulative_rct_outputs(const std::vector< uint64_t > &heights) const =0
fetch a block's cumulative number of rct outputs
virtual bool has_key_image(const crypto::key_image &img) const =0
check if a key image is stored as spent
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &details)=0
add a txpool transaction
virtual size_t get_block_weight(const uint64_t &height) const =0
fetch a block's weight
virtual std::vector< std::vector< uint64_t > > get_tx_amount_output_indices(const uint64_t tx_id, size_t n_txes=1) const =0
gets output indices (amount-specific) for a transaction's outputs
virtual void add_max_block_size(uint64_t sz)=0
add a new max block size
virtual uint64_t get_tx_unlock_time(const crypto::hash &h) const =0
fetch a transaction's unlock time/height
virtual void reset()=0
Remove everything from the BlockchainDB.
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
virtual bool check_pruning()=0
checks pruning was done correctly, iff enabled
virtual void batch_abort()=0
aborts a batch transaction
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)=0
tells the BlockchainDB to start a new "batch" of blocks
virtual bool for_blocks_range(const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const cryptonote::block &)>) const =0
runs a function over a range of blocks
virtual bool get_pruned_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the pruned transaction blob with the given hash
virtual std::vector< uint64_t > get_long_term_block_weights(uint64_t start_height, size_t count) const =0
fetch the last N blocks' long term weights
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 output_data_t get_output_key(const uint64_t &amount, const uint64_t &index, bool include_commitmemt=true) const =0
get some of an output's data
virtual difficulty_type get_block_difficulty(const uint64_t &height) const =0
fetch a block's difficulty
virtual uint64_t get_block_long_term_weight(const uint64_t &height) const =0
fetch a block's long term weight
virtual bool update_pruning()=0
prunes recent blockchain changes as needed, iff pruning is enabled
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block's timestamp
virtual bool prune_blockchain(uint32_t pruning_seed=0)=0
prunes the blockchain
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block's hash
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
virtual bool get_prunable_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the prunable transaction blob with the given hash
virtual uint64_t get_utxo_unlock_time(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
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 (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
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_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
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 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
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
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
std::list< std::pair< block_extended_info, std::vector< crypto::hash > > > get_alternative_chains() const
returns a set of known alternate chains
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 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
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
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 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 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
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 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_ideal_version() const
returns the latest "ideal" version
void on_block_popped(uint64_t new_chain_height)
called when one or more blocks are popped from the blockchain
void init()
initialize the object
uint8_t get_current_version() const
returns the current version
bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
returns information about current voting state
bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time)
add a new hardfork height
bool reorganize_from_chain_height(uint64_t height)
bool check(const cryptonote::block &block) const
check whether a new block would be accepted
bool check_for_height(const cryptonote::block &block, uint64_t height) const
same as check, but for a particular height, rather than the top
State get_state(time_t t) const
returns current state at the given time
thrown when a spent key image exists, but shouldn't, namely when adding a block
thrown when a requested output does not exist
thrown when a requested transaction does not exist
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
bool is_in_checkpoint_zone(uint64_t height) const
checks if there is a checkpoint in the future
bool check_for_conflicts(const checkpoints &other) const
checks if our checkpoints container conflicts with another
bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
checks if alternate chain blocks should be kept for a given height
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
load new checkpoints from json
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.
void unlock() const
unlocks the transaction pool
void lock() const
locks the transaction pool
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash &top_block_id)
action to take when notified of a block removed from the blockchain
bool fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
Chooses transactions for a block to include.
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash &top_block_id)
action to take when notified of a block added to the blockchain
bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context &tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
uint64_t cookie() const
return the cookie
void get_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
bool take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t &tx_weight, uint64_t &fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &nonexistent_utxo_seen)
takes a transaction with the given hash from the pool
Validator getValidatorByKey(string key)
vector< string > getApplicablePublicKeys(uint64_t height, bool convert_to_byte=false)
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
expect< void > success() noexcept
void * memcpy(void *a, const void *b, size_t c)
#define MCLOG_RED(level, cat, x)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
void save(Archive &a, const std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
std::string const GENESIS_TX
uint32_t const GENESIS_NONCE
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)
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)
bool is_v1_tx(const blobdata_ref &tx_blob)
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)
const config_t & get_config(network_type nettype)
@ 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)
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)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
std::function< const epee::span< const unsigned char >cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
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)
std::string to_string(t_connection_type type)
mdb_size_t count(MDB_cursor *cur)
const T & move(const T &t)
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
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
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
rct::key commitment() const
#define CRITICAL_REGION_LOCAL1(x)
#define CRITICAL_REGION_LOCAL(x)
#define CRITICAL_REGION_END()
#define CRITICAL_REGION_BEGIN(x)
struct hash_func hashes[]
DISABLE_VS_WARNINGS(4244 4345 4503) using namespace crypto
provides the implementation of varint's