Electroneum
blockchain.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #include <algorithm>
33 #include <cstdio>
34 #include <boost/filesystem.hpp>
35 #include <boost/range/adaptor/reversed.hpp>
36 
37 #include "include_base_utils.h"
39 #include "tx_pool.h"
40 #include "blockchain.h"
43 #include "cryptonote_config.h"
44 #include "cryptonote_basic/miner.h"
45 #include "misc_language.h"
46 #include "profile_tools.h"
47 #include "file_io_utils.h"
48 #include "int-util.h"
49 #include "common/threadpool.h"
51 #include "warnings.h"
52 #include "crypto/hash.h"
53 #include "cryptonote_core.h"
54 #include "ringct/rctSigs.h"
55 #include "common/perf_timer.h"
56 #include "common/notify.h"
57 #include "common/varint.h"
58 #include "common/pruning.h"
59 
60 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
61 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "blockchain"
62 
63 #define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100*1024*1024) // 100 MB
64 
65 #define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100*1024*1024) // 100 MB
66 
67 using namespace crypto;
68 
69 //#include "serialization/json_archive.h"
70 
71 /* TODO:
72  * Clean up code:
73  * Possibly change how outputs are referred to/indexed in blockchain and wallets
74  *
75  */
76 
77 using namespace cryptonote;
79 extern "C" void slow_hash_allocate_state();
80 extern "C" void slow_hash_free_state();
81 
83 
84 #define MERROR_VER(x) MCERROR("verify", x)
85 
86 // used to overestimate the block reward when estimating a per kB to use
87 #define BLOCK_REWARD_OVERESTIMATE (10 * 1000000000000)
88 
89 static const struct {
93  time_t time;
94 } mainnet_hard_forks[] = {
95  // version 1 from the start of the blockchain
96  { 1, 1, 0, 1341378000 },
97  { 6, 307500, 0, 1538815057 }, //1538815057
98  { 7, 324500, 0, 1538985600 }, // Estimated July 5th, 8:30AM UTC
99  { 8, 589169, 0, 1562547600 },
100  { 9, 862866, 0, 1595615809 }, // Estimated July 22th, 2020
101  { 10, 1175315, 0, 1632999041 }, // Estimated Sep 30th 2021
102  { 11, 1811310, 0, 1709652642 }, // Estimated 5th March 2024 //
103 };
104 static const uint64_t mainnet_hard_fork_version_1_till = 307499;
105 
106 static const struct {
110  time_t time;
111 } testnet_hard_forks[] = {
112  // version 1 from the start of the blockchain
113  { 1, 1, 0, 1341378000 },
114  { 6, 190060, 0, 1523263057 },
115  { 7, 215000, 0, 1530615600 },
116  { 8, 446674, 0, 1562889600 },
117  { 9, 707121, 0, 1595615809 },
118  { 10, 1086402, 0, 1631789441 }, // Estimated Sep 16th 2021
119  { 11, 1455270, 0, 1693256672 } // Estimated Aug 30th 2023
120 };
121 static const uint64_t testnet_hard_fork_version_1_till = 190059;
122 
123 static const struct {
127  time_t time;
128 } stagenet_hard_forks[] = {
129  // version 1 from the start of the blockchain
130  { 1, 1, 0, 1341378000 },
131 
132  // versions 2-9 in rapid succession from March 13th, 2018
133  { 2, 32000, 0, 1521000000 },
134  { 3, 33000, 0, 1521120000 },
135  { 4, 34000, 0, 1521240000 },
136  { 5, 35000, 0, 1521360000 },
137  { 6, 36000, 0, 1521480000 },
138  { 7, 37000, 0, 1521600000 },
139  { 8, 38000, 0, 1521800000 },
140  { 9, 39000, 0, 1522000000 },
141  { 10, 1086402, 0, 1631789441 }, // Estimated Sep 16th 2021
142  // TODO { 11, XXXXXXX, 0, XXXXXXXXXX }, // Estimated XXXXXXX
143 };
144 
145 //------------------------------------------------------------------
146 Blockchain::Blockchain(tx_memory_pool& tx_pool) :
147  m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
148  m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false),
149  m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
150  m_long_term_effective_median_block_weight(0),
151  m_long_term_block_weights_cache_tip_hash(crypto::null_hash),
152  m_long_term_block_weights_cache_rolling_median(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
153  m_difficulty_for_next_block_top_hash(crypto::null_hash),
154  m_difficulty_for_next_block(1),
155  m_btc_valid(false),
156  m_batch_success(true)
157 {
158  LOG_PRINT_L3("Blockchain::" << __func__);
159 }
160 //------------------------------------------------------------------
162 {
163  try { deinit(); }
164  catch (const std::exception &e) { /* ignore */ }
165 }
166 //------------------------------------------------------------------
167 bool Blockchain::have_tx(const crypto::hash &id) const
168 {
169  LOG_PRINT_L3("Blockchain::" << __func__);
170  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
171  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
172  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
173  // lock if it is otherwise needed.
174  return m_db->tx_exists(id);
175 }
176 //------------------------------------------------------------------
178 {
179  LOG_PRINT_L3("Blockchain::" << __func__);
180  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
181  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
182  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
183  // lock if it is otherwise needed.
184  return m_db->has_key_image(key_im);
185 }
186 //------------------------------------------------------------------
187 // This function makes sure that each "input" in an input (mixins) exists
188 // and collects the public key for each from the transaction it was included in
189 // via the visitor passed to it.
190 template <class visitor_t>
191 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
192 {
193  LOG_PRINT_L3("Blockchain::" << __func__);
194 
195  // ND: Disable locking and make method private.
196  //CRITICAL_REGION_LOCAL(m_blockchain_lock);
197 
198  // verify that the input has key offsets (that it exists properly, really)
199  if(!tx_in_to_key.key_offsets.size())
200  return false;
201 
202  // cryptonote_format_utils uses relative offsets for indexing to the global
203  // outputs list. that is to say that absolute offset #2 is absolute offset
204  // #1 plus relative offset #2.
205  // TODO: Investigate if this is necessary / why this is done.
206  std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets);
207  std::vector<output_data_t> outputs;
208 
209  bool found = false;
210  auto it = m_scan_table.find(tx_prefix_hash);
211  if (it != m_scan_table.end())
212  {
213  auto its = it->second.find(tx_in_to_key.k_image);
214  if (its != it->second.end())
215  {
216  outputs = its->second;
217  found = true;
218  }
219  }
220 
221  if (!found)
222  {
223  try
224  {
225  m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.amount, 1), absolute_offsets, outputs, true);
226  if (absolute_offsets.size() != outputs.size())
227  {
228  MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
229  return false;
230  }
231  }
232  catch (...)
233  {
234  MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
235  return false;
236  }
237  }
238  else
239  {
240  // check for partial results and add the rest if needed;
241  if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
242  {
243  MDEBUG("Additional outputs needed: " << absolute_offsets.size() - outputs.size());
244  std::vector < uint64_t > add_offsets;
245  std::vector<output_data_t> add_outputs;
246  add_outputs.reserve(absolute_offsets.size() - outputs.size());
247  for (size_t i = outputs.size(); i < absolute_offsets.size(); i++)
248  add_offsets.push_back(absolute_offsets[i]);
249  try
250  {
251  m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.amount, 1), add_offsets, add_outputs, true);
252  if (add_offsets.size() != add_outputs.size())
253  {
254  MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
255  return false;
256  }
257  }
258  catch (...)
259  {
260  MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
261  return false;
262  }
263  outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
264  }
265  }
266 
267  size_t count = 0;
268  for (const uint64_t& i : absolute_offsets)
269  {
270  try
271  {
273  try
274  {
275  // get tx hash and output index for output
276  if (count < outputs.size())
277  output_index = outputs.at(count);
278  else
279  output_index = m_db->get_output_key(tx_in_to_key.amount, i);
280 
281  // call to the passed boost visitor to grab the public key for the output
282  if (!vis.handle_output(output_index.unlock_time, output_index.pubkey, output_index.commitment))
283  {
284  MERROR_VER("Failed to handle_output for output no = " << count << ", with absolute offset " << i);
285  return false;
286  }
287  }
288  catch (...)
289  {
290  MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i);
291  return false;
292  }
293 
294  // if on last output and pmax_related_block_height not null pointer
295  if(++count == absolute_offsets.size() && pmax_related_block_height)
296  {
297  // set *pmax_related_block_height to tx block height for this output
298  auto h = output_index.height;
299  if(*pmax_related_block_height < h)
300  {
301  *pmax_related_block_height = h;
302  }
303  }
304 
305  }
306  catch (const OUTPUT_DNE& e)
307  {
308  MERROR_VER("Output does not exist: " << e.what());
309  return false;
310  }
311  catch (const TX_DNE& e)
312  {
313  MERROR_VER("Transaction does not exist: " << e.what());
314  return false;
315  }
316 
317  }
318 
319  return true;
320 }
321 //------------------------------------------------------------------
323 {
324  LOG_PRINT_L3("Blockchain::" << __func__);
325  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
326  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
327  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
328  // lock if it is otherwise needed.
329  return m_db->height();
330 }
331 //------------------------------------------------------------------
332 //FIXME: possibly move this into the constructor, to avoid accidentally
333 // dereferencing a null BlockchainDB pointer
334 bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback& get_checkpoints/* = nullptr*/, bool ignore_bsig, bool fallback_to_pow)
335 {
336  LOG_PRINT_L3("Blockchain::" << __func__);
337 
338  CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options");
339 
340  CRITICAL_REGION_LOCAL(m_tx_pool);
341  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
342 
343  if (db == nullptr)
344  {
345  LOG_ERROR("Attempted to init Blockchain with null DB");
346  return false;
347  }
348  if (!db->is_open())
349  {
350  LOG_ERROR("Attempted to init Blockchain with unopened DB");
351  delete db;
352  return false;
353  }
354 
355  m_db = db;
356 
357  m_nettype = test_options != NULL ? FAKECHAIN : nettype;
358  m_offline = offline;
359  m_fixed_difficulty = fixed_difficulty;
360  m_ignore_bsig = ignore_bsig;
361  m_fallback_to_pow = fallback_to_pow;
362  if (m_hardfork == nullptr)
363  {
364  if (m_nettype == FAKECHAIN || m_nettype == STAGENET)
365  m_hardfork = new HardFork(*db, 1, 0);
366  else if (m_nettype == TESTNET)
367  m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
368  else
369  m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
370  }
371  if (m_nettype == FAKECHAIN)
372  {
373  for (size_t n = 0; test_options->hard_forks[n].first; ++n)
374  m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1);
375  }
376  else if (m_nettype == TESTNET)
377  {
378  for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
379  m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
380  }
381  else if (m_nettype == STAGENET)
382  {
383  for (size_t n = 0; n < sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]); ++n)
384  m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
385  }
386  else
387  {
388  for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
389  m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
390  }
391  m_hardfork->init();
392 
393  m_db->set_hard_fork(m_hardfork);
394 
395  // if the blockchain is new, add the genesis block
396  // this feels kinda kludgy to do it this way, but can be looked at later.
397  // TODO: add function to create and store genesis block,
398  // taking testnet into account
399  if(!m_db->height())
400  {
401  MINFO("Blockchain not loaded, generating genesis block.");
402  block bl;
403  block_verification_context bvc = boost::value_initialized<block_verification_context>();
405  db_wtxn_guard wtxn_guard(m_db);
406  add_new_block(bl, bvc);
407  CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Failed to add genesis block to blockchain");
408  }
409  // TODO: if blockchain load successful, verify blockchain against both
410  // hard-coded and runtime-loaded (and enforced) checkpoints.
411  else
412  {
413  }
414 
415  if (m_nettype != FAKECHAIN)
416  {
417  m_db->set_batch_transactions(true);
418  }
419 
420  db_rtxn_guard rtxn_guard(m_db);
421 
422  // check how far behind we are
423  uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
424  uint64_t timestamp_diff = time(NULL) - top_block_timestamp;
425 
426  // genesis block has no timestamp, could probably change it to have timestamp of 1397818133...
427  if(!top_block_timestamp)
428  timestamp_diff = time(NULL) - 1397818133;
429 
430  // create general purpose async service queue
431 
432  m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (new boost::asio::io_service::work(m_async_service));
433  // we only need 1
434  m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
435 
436 #if defined(PER_BLOCK_CHECKPOINT)
437  if (m_nettype != FAKECHAIN)
438  load_compiled_in_block_hashes(get_checkpoints);
439 #endif
440 
441  MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block());
442 
443  rtxn_guard.stop();
444 
445  uint64_t num_popped_blocks = 0;
446  while (!m_db->is_read_only())
447  {
448  uint64_t top_height;
449  const crypto::hash top_id = m_db->top_block_hash(&top_height);
450  const block top_block = m_db->get_top_block();
451  const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height);
452  if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version)
453  {
454  if (num_popped_blocks > 0)
455  MGINFO("Initial popping done, top block: " << top_id << ", top height: " << top_height << ", block version: " << (uint64_t)top_block.major_version);
456  break;
457  }
458  else
459  {
460  if (num_popped_blocks == 0)
461  MGINFO("Current top block " << top_id << " at height " << top_height << " has version " << (uint64_t)top_block.major_version << " which disagrees with the ideal version " << (uint64_t)ideal_hf_version);
462  if (num_popped_blocks % 100 == 0)
463  MGINFO("Popping blocks... " << top_height);
464  ++num_popped_blocks;
465  block popped_block;
466  std::vector<transaction> popped_txs;
467  try
468  {
469  m_db->pop_block(popped_block, popped_txs);
470  }
471  // anything that could cause this to throw is likely catastrophic,
472  // so we re-throw
473  catch (const std::exception& e)
474  {
475  MERROR("Error popping block from blockchain: " << e.what());
476  throw;
477  }
478  catch (...)
479  {
480  MERROR("Error popping block from blockchain, throwing!");
481  throw;
482  }
483  }
484  }
485 
486  if (num_popped_blocks > 0)
487  {
488  m_timestamps_and_difficulties_height = 0;
490  uint64_t top_block_height;
491  crypto::hash top_block_hash = get_tail_id(top_block_height);
492  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
493  }
494 
496  {
497  m_long_term_block_weights_window = test_options->long_term_block_weight_window;
498  m_long_term_block_weights_cache_rolling_median = epee::misc_utils::rolling_median_t<uint64_t>(m_long_term_block_weights_window);
499  }
500 
501  {
502  db_txn_guard txn_guard(m_db, m_db->is_read_only());
503  if (!update_next_cumulative_weight_limit())
504  return false;
505  }
506 
507  {
508  if(!m_db->is_read_only())
509  {
510  uint64_t top_height;
511  m_db->top_block_hash(&top_height);
512 
513  if(top_height >= 1175315)
514  {
515  block b = m_db->get_block_from_height(1175315);
516  const auto &txout = boost::get<txout_to_key_public>(b.miner_tx.vout[0].target);
517  std::vector<cryptonote::address_outputs> addr_outs = m_db->get_addr_output_all(addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
518 
519  if(addr_outs.empty()) {
520  MGINFO("Recomputing address_outputs database...");
521  m_db->top_block_hash(&top_height);
522  uint64_t diff = top_height - 1175200;
523  for(auto i = 0; i < diff; i++) {
524  block popped_block;
525  std::vector<transaction> popped_txs;
526  try
527  {
528  m_db->pop_block(popped_block, popped_txs);
529  }
530  catch (const std::exception& e)
531  {
532  MERROR("Error popping block from blockchain: " << e.what());
533  throw;
534  }
535  catch (...)
536  {
537  MERROR("Error popping block from blockchain, throwing!");
538  throw;
539  }
540  }
541  if (diff > 0)
542  {
544  uint64_t top_block_height;
545  crypto::hash top_block_hash = get_tail_id(top_block_height);
546  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
547  }
548  MGINFO("Address_outputs database recomputed OK");
549  }
550  }
551  }
552  }
553 
554  // GO BACK AND POPULATE A DATABASE OF KEY: COMBINED KEY , VALUE: TX INPUT
555  {
556  db_txn_guard txn_guard(m_db, m_db->is_read_only());
557  if(!m_db->is_read_only())
558  {
559  uint64_t top_height;
560  m_db->top_block_hash(&top_height);
561  uint64_t private_to_public_fork_height = m_nettype == MAINNET ? 1175315 : 1086402;
562  if(top_height >= private_to_public_fork_height)
563  {
564  block b = m_db->get_block_from_height(private_to_public_fork_height);
565  const auto &txout = boost::get<txout_to_key_public>(b.miner_tx.vout[0].target);
566  std::vector<cryptonote::address_txs> addr_txs = m_db->get_addr_tx_all(addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
567  if(addr_txs.empty()) {
568  MGINFO("Populating addr tx database...");
569  m_db->top_block_hash(&top_height);
570  // begin at the private to public fork block and store the data in addr_tx db one block at a time
571  uint64_t working_height = private_to_public_fork_height;
572  while (working_height <= top_height) {
573  block working_block = m_db->get_block_from_height(working_height);
574  //deal with miner tx first
575  for( auto vout: working_block.miner_tx.vout){ // all vouts are of type txout to key public
576  const auto &txout = boost::get<txout_to_key_public>(vout.target);
577  m_db->add_addr_tx(get_transaction_hash(working_block.miner_tx), addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
578 
579  }
580  //deal with all other tx
581  std::vector<transaction> transactions = m_db->get_tx_list(working_block.tx_hashes);
582  for (auto tx : transactions){
583  auto hash = get_transaction_hash(tx);
584  std::unordered_set<crypto::public_key> addr_tx_addresses;
585  for (size_t i = 0; i < tx.vin.size(); i++){
586  if (tx.vin[i].type() == typeid(txin_to_key_public))
587  {
588  const auto &txin = boost::get<txin_to_key_public>(tx.vin[i]);
589  transaction parent_tx = m_db->get_tx(txin.tx_hash);
590  const auto &txout = boost::get<txout_to_key_public>(parent_tx.vout[txin.relative_offset].target); //previous tx out that this tx in references
591  crypto::public_key combined_key = addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key);
592  if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){ //if addr hasn't been used for another input yet, add the unique addr tx record for this address
593  m_db->add_addr_tx(hash, combined_key);
594  addr_tx_addresses.emplace(combined_key);
595  }
596  }
597  }
598  for(size_t i = 0; i < tx.vout.size(); i++){ // all vouts are of type txout to key public
599  const auto &txout = boost::get<txout_to_key_public>(tx.vout[i].target);
600  crypto::public_key combined_key = addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key);
601  if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){ //if addr hasn't been used for another input yet, add the unique addr tx record for this address
602  m_db->add_addr_tx(tx.hash, combined_key);
603  addr_tx_addresses.emplace(combined_key);
604  }
605  }
606  }
607  ++working_height;
608  }
609  MGINFO("Addr_txs database recomputed OK");
610  }
611 
612  }
613  }
614 
615  txn_guard.stop();
616  }
617  return true;
618 }
619 //------------------------------------------------------------------
620 bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const network_type nettype, bool offline)
621 {
622  if (hf != nullptr)
623  m_hardfork = hf;
624  bool res = init(db, nettype, offline, NULL);
625  if (hf == nullptr)
626  hf = m_hardfork;
627  return res;
628 }
629 //------------------------------------------------------------------
631 {
632  LOG_PRINT_L3("Blockchain::" << __func__);
633  // lock because the rpc_thread command handler also calls this
635 
637  // TODO: make sure sync(if this throws that it is not simply ignored higher
638  // up the call stack
639  try
640  {
641  m_db->sync();
642  }
643  catch (const std::exception& e)
644  {
645  MERROR(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
646  throw;
647  }
648  catch (...)
649  {
650  MERROR("There was an issue storing the blockchain, shutting down now to prevent issues!");
651  throw;
652  }
653 
655  if(m_show_time_stats)
656  MINFO("Blockchain stored OK, took: " << save << " ms");
657  return true;
658 }
659 //------------------------------------------------------------------
661 {
662  LOG_PRINT_L3("Blockchain::" << __func__);
663 
664  MTRACE("Stopping blockchain read/write activity");
665 
666  // stop async service
667  m_async_work_idle.reset();
668  m_async_pool.join_all();
669  m_async_service.stop();
670 
671  // as this should be called if handling a SIGSEGV, need to check
672  // if m_db is a NULL pointer (and thus may have caused the illegal
673  // memory operation), otherwise we may cause a loop.
674  try
675  {
676  if (m_db)
677  {
678  m_db->close();
679  MTRACE("Local blockchain read/write activity stopped successfully");
680  }
681  }
682  catch (const std::exception& e)
683  {
684  LOG_ERROR(std::string("Error closing blockchain db: ") + e.what());
685  }
686  catch (...)
687  {
688  LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
689  }
690 
691  delete m_hardfork;
692  m_hardfork = NULL;
693  delete m_db;
694  m_db = NULL;
695  return true;
696 }
697 //------------------------------------------------------------------
698 // This function removes blocks from the top of blockchain.
699 // It starts a batch and calls private method pop_block_from_blockchain().
701 {
702  uint64_t i;
703  CRITICAL_REGION_LOCAL(m_tx_pool);
704  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
705 
706  bool stop_batch = m_db->batch_start();
707 
708  try
709  {
710  const uint64_t blockchain_height = m_db->height();
711  if (blockchain_height > 0)
712  nblocks = std::min(nblocks, blockchain_height - 1);
713  for (i=0; i < nblocks; ++i)
714  {
715  pop_block_from_blockchain();
716  }
717  }
718  catch (const std::exception& e)
719  {
720  LOG_ERROR("Error when popping blocks after processing " << i << " blocks: " << e.what());
721  if (stop_batch)
722  m_db->batch_abort();
723  return;
724  }
725 
726  if (stop_batch)
727  m_db->batch_stop();
728 }
729 //------------------------------------------------------------------
730 // This function tells BlockchainDB to remove the top block from the
731 // blockchain and then returns all transactions (except the miner tx, of course)
732 // from it to the tx_pool
733 block Blockchain::pop_block_from_blockchain()
734 {
735  LOG_PRINT_L3("Blockchain::" << __func__);
736  CRITICAL_REGION_LOCAL(m_blockchain_lock);
737 
738  m_timestamps_and_difficulties_height = 0;
739 
740  block popped_block;
741  std::vector<transaction> popped_txs;
742 
743  CHECK_AND_ASSERT_THROW_MES(m_db->height() > 1, "Cannot pop the genesis block");
744 
745  try
746  {
747  m_db->pop_block(popped_block, popped_txs);
748  }
749  // anything that could cause this to throw is likely catastrophic,
750  // so we re-throw
751  catch (const std::exception& e)
752  {
753  LOG_ERROR("Error popping block from blockchain: " << e.what());
754  throw;
755  }
756  catch (...)
757  {
758  LOG_ERROR("Error popping block from blockchain, throwing!");
759  throw;
760  }
761 
762  // make sure the hard fork object updates its current version
763  m_hardfork->on_block_popped(1);
764 
765  // return transactions from popped block to the tx_pool
766  size_t pruned = 0;
767  for (transaction& tx : popped_txs)
768  {
769  if (tx.pruned)
770  {
771  ++pruned;
772  continue;
773  }
774  if (!is_coinbase(tx))
775  {
777 
778  // FIXME: HardFork
779  // Besides the below, popping a block should also remove the last entry
780  // in hf_versions.
782 
783  // We assume that if they were in a block, the transactions are already
784  // known to the network as a whole. However, if we had mined that block,
785  // that might not be always true. Unlikely though, and always relaying
786  // these again might cause a spike of traffic as many nodes re-relay
787  // all the transactions in a popped block when a reorg happens.
788  bool r = m_tx_pool.add_tx(tx, tvc, true, true, false, version);
789  if (!r)
790  {
791  LOG_ERROR("Error returning transaction to tx_pool");
792  }
793  }
794  }
795  if (pruned)
796  MWARNING(pruned << " pruned txes could not be added back to the txpool");
797 
798  m_blocks_longhash_table.clear();
799  m_scan_table.clear();
800  m_blocks_txs_check.clear();
801  m_check_txin_table.clear();
802 
803  CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
804  uint64_t top_block_height;
805  crypto::hash top_block_hash = get_tail_id(top_block_height);
806  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
807  invalidate_block_template_cache();
808 
809  return popped_block;
810 }
811 //------------------------------------------------------------------
813 {
814  LOG_PRINT_L3("Blockchain::" << __func__);
815  CRITICAL_REGION_LOCAL(m_blockchain_lock);
816  m_timestamps_and_difficulties_height = 0;
817  m_alternative_chains.clear();
818  invalidate_block_template_cache();
819  m_db->reset();
820  m_hardfork->init();
821 
822  db_wtxn_guard wtxn_guard(m_db);
823  block_verification_context bvc = boost::value_initialized<block_verification_context>();
824  add_new_block(b, bvc);
825  if (!update_next_cumulative_weight_limit())
826  return false;
827  return bvc.m_added_to_main_chain && !bvc.m_verification_failed;
828 }
829 //------------------------------------------------------------------
831 {
832  LOG_PRINT_L3("Blockchain::" << __func__);
833  CRITICAL_REGION_LOCAL(m_blockchain_lock);
834  return m_db->top_block_hash(&height);
835 }
836 //------------------------------------------------------------------
838 {
839  LOG_PRINT_L3("Blockchain::" << __func__);
840  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
841  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
842  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
843  // lock if it is otherwise needed.
844  return m_db->top_block_hash();
845 }
846 //------------------------------------------------------------------
847 /*TODO: this function was...poorly written. As such, I'm not entirely
848  * certain on what it was supposed to be doing. Need to look into this,
849  * but it doesn't seem terribly important just yet.
850  *
851  * puts into list <ids> a list of hashes representing certain blocks
852  * from the blockchain in reverse chronological order
853  *
854  * the blocks chosen, at the time of this writing, are:
855  * the most recent 11
856  * powers of 2 less recent from there, so 13, 17, 25, etc...
857  *
858  */
859 bool Blockchain::get_short_chain_history(std::list<crypto::hash>& ids) const
860 {
861  LOG_PRINT_L3("Blockchain::" << __func__);
862  CRITICAL_REGION_LOCAL(m_blockchain_lock);
863  uint64_t i = 0;
864  uint64_t current_multiplier = 1;
865  uint64_t sz = m_db->height();
866 
867  if(!sz)
868  return true;
869 
870  db_rtxn_guard rtxn_guard(m_db);
871  bool genesis_included = false;
872  uint64_t current_back_offset = 1;
873  while(current_back_offset < sz)
874  {
875  ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
876 
877  if(sz-current_back_offset == 0)
878  {
879  genesis_included = true;
880  }
881  if(i < 10)
882  {
883  ++current_back_offset;
884  }
885  else
886  {
887  current_multiplier *= 2;
888  current_back_offset += current_multiplier;
889  }
890  ++i;
891  }
892 
893  if (!genesis_included)
894  {
895  ids.push_back(m_db->get_block_hash_from_height(0));
896  }
897 
898  return true;
899 }
900 //------------------------------------------------------------------
902 {
903  LOG_PRINT_L3("Blockchain::" << __func__);
904  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
905  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
906  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
907  // lock if it is otherwise needed.
908  try
909  {
910  return m_db->get_block_hash_from_height(height);
911  }
912  catch (const BLOCK_DNE& e)
913  {
914  }
915  catch (const std::exception& e)
916  {
917  MERROR(std::string("Something went wrong fetching block hash by height: ") + e.what());
918  throw;
919  }
920  catch (...)
921  {
922  MERROR(std::string("Something went wrong fetching block hash by height"));
923  throw;
924  }
925  return null_hash;
926 }
927 //------------------------------------------------------------------
928 bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
929 {
930  LOG_PRINT_L3("Blockchain::" << __func__);
931  CRITICAL_REGION_LOCAL(m_blockchain_lock);
932 
933  // try to find block in main chain
934  try
935  {
936  blk = m_db->get_block(h);
937  if (orphan)
938  *orphan = false;
939  return true;
940  }
941  // try to find block in alternative chain
942  catch (const BLOCK_DNE& e)
943  {
944  blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
945  if (m_alternative_chains.end() != it_alt)
946  {
947  blk = it_alt->second.bl;
948  if (orphan)
949  *orphan = true;
950  return true;
951  }
952  }
953  catch (const std::exception& e)
954  {
955  MERROR(std::string("Something went wrong fetching block by hash: ") + e.what());
956  throw;
957  }
958  catch (...)
959  {
960  MERROR(std::string("Something went wrong fetching block hash by hash"));
961  throw;
962  }
963 
964  return false;
965 }
966 //------------------------------------------------------------------
967 // This function aggregates the cumulative difficulties and timestamps of the
968 // last DIFFICULTY_BLOCKS_COUNT blocks and passes them to next_difficulty,
969 // returning the result of that call. Ignores the genesis block, and can use
970 // less blocks than desired if there aren't enough.
972 {
973  if (m_fixed_difficulty)
974  {
975  return m_db->height() ? m_fixed_difficulty : 1;
976  }
977 
978  LOG_PRINT_L3("Blockchain::" << __func__);
979 
980  crypto::hash top_hash = get_tail_id();
981  {
982  CRITICAL_REGION_LOCAL(m_difficulty_lock);
983  // we can call this without the blockchain lock, it might just give us
984  // something a bit out of date, but that's fine since anything which
985  // requires the blockchain lock will have acquired it in the first place,
986  // and it will be unlocked only when called from the getinfo RPC
987  if (top_hash == m_difficulty_for_next_block_top_hash)
988  return m_difficulty_for_next_block;
989  }
990 
991  CRITICAL_REGION_LOCAL(m_blockchain_lock);
992  std::vector<uint64_t> timestamps;
993  std::vector<difficulty_type> difficulties;
995  top_hash = get_tail_id(height); // get it again now that we have the lock
996  ++height; // top block height to blockchain height
997 
998  uint64_t v6height = 0, v7height = 0, v8height = 0;
999  if(m_nettype == MAINNET) {
1000  v6height = mainnet_hard_forks[1].height;
1001  v7height = mainnet_hard_forks[2].height;
1002  v8height = mainnet_hard_forks[3].height;
1003  } else if(m_nettype == TESTNET) {
1004  v6height = testnet_hard_forks[1].height;
1005  v7height = testnet_hard_forks[2].height;
1006  v8height = testnet_hard_forks[3].height;
1007  } else if(m_nettype == STAGENET) {
1008  v6height = stagenet_hard_forks[5].height;
1009  v7height = stagenet_hard_forks[5].height;
1010  v8height = stagenet_hard_forks[5].height;
1011  } else if(m_nettype == UNDEFINED){
1012  MERROR(std::string("Something went wrong defining the network type."));
1013  }
1014 
1015 
1016  uint32_t difficultyBlocksCount = (height >= v6height && height < v7height) ? DIFFICULTY_BLOCKS_COUNT_V6 : DIFFICULTY_BLOCKS_COUNT;
1017 
1018  // After v8 allow the difficulty window to grow linearly (from zero) back to DIFFICULTY_BLOCKS_COUNT.
1019  if((height >= v8height) && (height < v8height + 720))
1020  {
1021  // Initial clear of the caches when we hit v8.
1022  if(height == v8height)
1023  {
1024  m_timestamps.clear();
1025  m_difficulties.clear();
1026  }
1027  difficultyBlocksCount = height - v8height;
1028  }
1029 
1030  // ND: Speedup
1031  // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
1032  // then when the next block difficulty is queried, push the latest height data and
1033  // pop the oldest one from the list. This only requires 1x read per height instead
1034  // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
1035  // Post v8 we will only re-enter this scope after the first DIFFICULTY_BLOCKS_COUNT blocks due to the last condition.
1036  if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficultyBlocksCount)
1037  {
1038  uint64_t index = height - 1;
1039  m_timestamps.push_back(m_db->get_block_timestamp(index));
1040  m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
1041 
1042  while (m_timestamps.size() > difficultyBlocksCount)
1043  m_timestamps.erase(m_timestamps.begin());
1044  while (m_difficulties.size() > difficultyBlocksCount)
1045  m_difficulties.erase(m_difficulties.begin());
1046 
1047  m_timestamps_and_difficulties_height = height;
1048  timestamps = m_timestamps;
1049  difficulties = m_difficulties;
1050  }
1051  else
1052  {
1053  uint64_t offset = height - std::min < uint64_t > (height, static_cast<uint64_t>(difficultyBlocksCount));
1054  if (offset == 0)
1055  ++offset;
1056 
1057  timestamps.clear();
1058  difficulties.clear();
1059  if (height > offset)
1060  {
1061  timestamps.reserve(height - offset);
1062  difficulties.reserve(height - offset);
1063  }
1064  for (; offset < height; offset++)
1065  {
1066  timestamps.push_back(m_db->get_block_timestamp(offset));
1067  difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
1068  }
1069 
1070  m_timestamps_and_difficulties_height = height;
1071  m_timestamps = timestamps;
1072  m_difficulties = difficulties;
1073  }
1074  size_t target = get_difficulty_target();
1075  const uint8_t version = (height >= v6height && height < v7height) ? 6 : 1;
1076  difficulty_type diff = next_difficulty(timestamps, difficulties, target, version);
1077 
1078  CRITICAL_REGION_LOCAL1(m_difficulty_lock);
1079  m_difficulty_for_next_block_top_hash = top_hash;
1080  m_difficulty_for_next_block = diff;
1081  return diff;
1082 }
1083 //------------------------------------------------------------------
1084 std::vector<time_t> Blockchain::get_last_block_timestamps(unsigned int blocks) const
1085 {
1086  uint64_t height = m_db->height();
1087  if (blocks > height)
1088  blocks = height;
1089  std::vector<time_t> timestamps(blocks);
1090  while (blocks--)
1091  timestamps[blocks] = m_db->get_block_timestamp(height - blocks - 1);
1092  return timestamps;
1093 }
1094 //------------------------------------------------------------------
1095 // This function fixes the differing difficulty bug by re-calculate and rewriting
1096 // the correct cumulative difficulty for blocks starting from V7 based on the
1097 // correct 735 blocks input in the difficulty algorithm.
1099 
1100  auto height = m_db->height();
1101  const uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
1102 
1103  if(height != v8height) {
1104  return;
1105  }
1106 
1107  const uint64_t v7height = m_nettype == TESTNET ? 215000 : 324500;
1108  const size_t V7_DIFFICULTY_BLOCKS_COUNT = 735;
1109  const size_t V7_DIFFICULTY_TARGET = 120;
1110 
1111  std::vector<uint64_t> timestamps;
1112  std::vector<difficulty_type> difficulties;
1113 
1114  uint64_t start_height = v7height - V7_DIFFICULTY_BLOCKS_COUNT;
1115 
1116  // Populate the timestamps & difficulties vectors with data from 735 blocks prior to V7 fork height (324500)
1117  for(uint64_t i = 0; start_height + i < v7height; i++) {
1118  timestamps.push_back(m_db->get_block_timestamp(start_height + i));
1119  difficulties.push_back(m_db->get_block_cumulative_difficulty(start_height + i));
1120  }
1121 
1122  // Calculate the cumulative difficulty of block 324500 based on the 735 prior blocks' timestamp and difficulty values
1123  difficulty_type diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1124 
1125  // Override block's 324500 cumulative difficulty
1126  m_db->set_block_cumulative_difficulty(v7height, diff);
1127 
1128  // Iterate over V7 blocks, starting from 324500 until current block height
1129  for(uint64_t i = v7height; i < height - 1; i++) {
1130 
1131  // Add "324500 + i" timestamp & difficulty into the vectors
1132  timestamps.push_back(m_db->get_block_timestamp(i));
1133  difficulties.push_back(m_db->get_block_cumulative_difficulty(i));
1134 
1135  // Erase the vector's first position maintaining its 735 size
1136  timestamps.erase(timestamps.begin());
1137  difficulties.erase(difficulties.begin());
1138 
1139  // Calculate/set the correct cumulative difficulty of block "324500 + i"
1140  diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1141  m_db->set_block_cumulative_difficulty(i + 1, diff);
1142  }
1143 
1144  m_timestamps.clear();
1145  m_difficulties.clear();
1146 }
1147 
1148 //------------------------------------------------------------------
1149 // This function removes blocks from the blockchain until it gets to the
1150 // position where the blockchain switch started and then re-adds the blocks
1151 // that had been removed.
1152 bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain, uint64_t rollback_height)
1153 {
1154  LOG_PRINT_L3("Blockchain::" << __func__);
1155  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1156 
1157  // fail if rollback_height passed is too high
1158  if (rollback_height > m_db->height())
1159  {
1160  return true;
1161  }
1162 
1163  m_timestamps_and_difficulties_height = 0;
1164 
1165  // remove blocks from blockchain until we get back to where we should be.
1166  while (m_db->height() != rollback_height)
1167  {
1168  pop_block_from_blockchain();
1169  }
1170 
1171  // make sure the hard fork object updates its current version
1172  m_hardfork->reorganize_from_chain_height(rollback_height);
1173 
1174  //return back original chain
1175  for (auto& bl : original_chain)
1176  {
1177  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1178  bool r = handle_block_to_main_chain(bl, bvc);
1179  CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC! failed to add (again) block while chain switching during the rollback!");
1180  }
1181 
1182  m_hardfork->reorganize_from_chain_height(rollback_height);
1183 
1184  MINFO("Rollback to height " << rollback_height << " was successful.");
1185  if (!original_chain.empty())
1186  {
1187  MINFO("Restoration to previous blockchain successful as well.");
1188  }
1189  return true;
1190 }
1191 //------------------------------------------------------------------
1192 // This function attempts to switch to an alternate chain, returning
1193 // boolean based on success therein.
1194 bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::const_iterator>& alt_chain, bool discard_disconnected_chain)
1195 {
1196  //TODO: Public
1197  LOG_PRINT_L3("Blockchain::" << __func__);
1198  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1199 
1200  m_timestamps_and_difficulties_height = 0;
1201 
1202  // if empty alt chain passed (not sure how that could happen), return false
1203  CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
1204 
1205  // verify that main chain has front of alt chain's parent block
1206  if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
1207  {
1208  LOG_ERROR("Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!");
1209  return false;
1210  }
1211 
1212  // pop blocks from the blockchain until the top block is the parent
1213  // of the front block of the alt chain.
1214  std::list<block> disconnected_chain;
1215  while (m_db->top_block_hash() != alt_chain.front()->second.bl.prev_id)
1216  {
1217  block b = pop_block_from_blockchain();
1218  disconnected_chain.push_front(b);
1219  }
1220 
1221  auto split_height = m_db->height();
1222 
1223  //connecting new alternative chain
1224  for(auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++)
1225  {
1226  auto ch_ent = *alt_ch_iter;
1227  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1228 
1229  // add block to main chain
1230  bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
1231 
1232  // if adding block to main chain failed, rollback to previous state and
1233  // return false
1234  if(!r || !bvc.m_added_to_main_chain)
1235  {
1236  MERROR("Failed to switch to alternative blockchain");
1237 
1238  // rollback_blockchain_switching should be moved to two different
1239  // functions: rollback and apply_chain, but for now we pretend it is
1240  // just the latter (because the rollback was done above).
1241  rollback_blockchain_switching(disconnected_chain, split_height);
1242 
1243  // FIXME: Why do we keep invalid blocks around? Possibly in case we hear
1244  // about them again so we can immediately dismiss them, but needs some
1245  // looking into.
1246  add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
1247  MERROR("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
1248  m_alternative_chains.erase(*alt_ch_iter++);
1249 
1250  for(auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); )
1251  {
1252  add_block_as_invalid((*alt_ch_to_orph_iter)->second, (*alt_ch_to_orph_iter)->first);
1253  m_alternative_chains.erase(*alt_ch_to_orph_iter++);
1254  }
1255  return false;
1256  }
1257  }
1258 
1259  // if we're to keep the disconnected blocks, add them as alternates
1260  const size_t discarded_blocks = disconnected_chain.size();
1261  if(!discard_disconnected_chain)
1262  {
1263  //pushing old chain as alternative chain
1264  for (auto& old_ch_ent : disconnected_chain)
1265  {
1266  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1267  bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
1268  if(!r)
1269  {
1270  MERROR("Failed to push ex-main chain blocks to alternative chain ");
1271  // previously this would fail the blockchain switching, but I don't
1272  // think this is bad enough to warrant that.
1273  }
1274  }
1275  }
1276 
1277  //removing alt_chain entries from alternative chains container
1278  for (auto ch_ent: alt_chain)
1279  {
1280  m_alternative_chains.erase(ch_ent);
1281  }
1282 
1283  m_hardfork->reorganize_from_chain_height(split_height);
1284 
1285  std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
1286  if (reorg_notify)
1287  reorg_notify->notify("%s", std::to_string(split_height).c_str(), "%h", std::to_string(m_db->height()).c_str(),
1288  "%n", std::to_string(m_db->height() - split_height).c_str(), "%d", std::to_string(discarded_blocks).c_str(), NULL);
1289 
1290  MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
1291  return true;
1292 }
1293 //------------------------------------------------------------------
1294 // This function calculates the difficulty target for the block being added to
1295 // an alternate chain.
1296 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
1297 {
1298  if (m_fixed_difficulty)
1299  {
1300  return m_db->height() ? m_fixed_difficulty : 1;
1301  }
1302 
1303  LOG_PRINT_L3("Blockchain::" << __func__);
1304  std::vector<uint64_t> timestamps;
1305  std::vector<difficulty_type> cumulative_difficulties;
1306 
1307  uint64_t v6height = 0, v7height = 0, v8height = 0;
1308 
1309  if(m_nettype == MAINNET) {
1310  v6height = mainnet_hard_forks[1].height;
1311  v7height = mainnet_hard_forks[2].height;
1312  v8height = mainnet_hard_forks[3].height;
1313  } else if(m_nettype == TESTNET) {
1314  v6height = testnet_hard_forks[1].height;
1315  v7height = testnet_hard_forks[2].height;
1316  v8height = testnet_hard_forks[3].height;
1317  } else if(m_nettype == STAGENET) {
1318  v6height = stagenet_hard_forks[5].height;
1319  v7height = stagenet_hard_forks[5].height;
1320  v8height = stagenet_hard_forks[5].height;
1321  } else if(m_nettype == UNDEFINED){
1322  MERROR(std::string("Something went wrong defining the network type."));
1323  }
1324 
1325  uint32_t difficultyBlocksCount = (bei.height >= v6height && bei.height < v7height) ? DIFFICULTY_BLOCKS_COUNT_V6 : DIFFICULTY_BLOCKS_COUNT;
1326 
1327  // Account for the difficulty reset in v8
1328  if((bei.height >= v8height) && (bei.height < v8height + 720))
1329  {
1330  //No analogous cache to clear (ie m_timestamps, m_difficulties)for alt-chain
1331  difficultyBlocksCount = bei.height - v8height;
1332  }
1333 
1334  // if the alt chain isn't long enough to calculate the difficulty target
1335  // based on its blocks alone, need to get more blocks from the main chain
1336  if(alt_chain.size()< difficultyBlocksCount)
1337  {
1338  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1339 
1340  // Figure out start and stop offsets for main chain blocks
1341  // End of alt chain height
1342  size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height;
1343  // How many blocks from the main chain will be needed?
1344  size_t main_chain_count = difficultyBlocksCount - std::min(static_cast<size_t>(difficultyBlocksCount), alt_chain.size());
1345  // If the amount of blocks we said we need from the main chain is more than the top height of the alt chain,
1346  // we necessarily take less blocks from the main chain (as many as is possible).
1347  main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
1348  // Height on the main chain to begin pulling the blocks.
1349  size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
1350 
1351  if(!main_chain_start_offset)
1352  ++main_chain_start_offset; //skip genesis block
1353 
1354  // get difficulties and timestamps from relevant main chain blocks
1355  for(; main_chain_start_offset < main_chain_stop_offset; ++main_chain_start_offset)
1356  {
1357  timestamps.push_back(m_db->get_block_timestamp(main_chain_start_offset));
1358  cumulative_difficulties.push_back(m_db->get_block_cumulative_difficulty(main_chain_start_offset));
1359  }
1360 
1361  // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check?
1362  CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= difficultyBlocksCount, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << difficultyBlocksCount);
1363 
1364  for (auto it : alt_chain)
1365  {
1366  timestamps.push_back(it->second.bl.timestamp);
1367  cumulative_difficulties.push_back(it->second.cumulative_difficulty);
1368  }
1369  }
1370  // if the alt chain is long enough for the difficulty calc, grab difficulties
1371  // and timestamps from it alone
1372  else
1373  {
1374  timestamps.resize(static_cast<size_t>(difficultyBlocksCount));
1375  cumulative_difficulties.resize(static_cast<size_t>(difficultyBlocksCount));
1376  size_t count = 0;
1377  size_t max_i = timestamps.size()-1;
1378  // get difficulties and timestamps from most recent blocks in alt chain
1379  for(auto it: boost::adaptors::reverse(alt_chain))
1380  {
1381  timestamps[max_i - count] = it->second.bl.timestamp;
1382  cumulative_difficulties[max_i - count] = it->second.cumulative_difficulty;
1383  count++;
1384  if(count >= difficultyBlocksCount)
1385  break;
1386  }
1387  }
1388 
1389  // FIXME: This will fail if fork activation heights are subject to voting - Does this need fixing for the V6 fork?
1390  size_t target = get_difficulty_target();
1391 
1392  const uint8_t version = m_hardfork->get_ideal_version(bei.height);
1393  // calculate the difficulty target for the block and return it
1394  return next_difficulty(timestamps, cumulative_difficulties, target, version);
1395 }
1396 //------------------------------------------------------------------
1397 // This function does a sanity check on basic things that all miner
1398 // transactions have in common, such as:
1399 // one input, of type txin_gen, with height set to the block's height
1400 // correct miner tx unlock time
1401 // a non-overflowing tx amount (dubious necessity on this check)
1402 bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height)
1403 {
1404  LOG_PRINT_L3("Blockchain::" << __func__);
1405  CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
1406  CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
1407  if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
1408  {
1409  MWARNING("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height);
1410  return false;
1411  }
1412  MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
1413  uint8_t hf_version = get_current_hard_fork_version();
1414  CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + (hf_version > 7 ? ETN_MINED_ETN_UNLOCK_WINDOW_V8 : CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW), false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + (hf_version > 7 ? ETN_MINED_ETN_UNLOCK_WINDOW_V8 : CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW));
1415 
1416  //check outs overflow
1417  //NOTE: not entirely sure this is necessary, given that this function is
1418  // designed simply to make sure the total amount for a transaction
1419  // does not overflow a uint64_t, and this transaction *is* a uint64_t...
1421  {
1422  MERROR("miner transaction has ETN overflow in block " << get_block_hash(b));
1423  return false;
1424  }
1425 
1426  return true;
1427 }
1428 //------------------------------------------------------------------
1429 // This function validates the miner transaction reward and for v11, that the coinbase is going to thew burn address.
1430 bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_block_weight, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins, bool &partial_block_reward, uint8_t version)
1431 {
1432  if (version >= 11){
1433  std::string coinbase_burn_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
1434  std::string coinbase_burn_address_spendkey_hex_str = "9511fabcb699b4f9dffc1779713d0dd7eb1ca56ba5b8ab8d3253a0a6ccf736b3";
1435  for (auto &o: b.miner_tx.vout) {
1436  const auto out = boost::get<txout_to_key_public>(o.target);
1437  std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
1438  std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
1439  if(out_spendkey_str != coinbase_burn_address_spendkey_hex_str || out_viewkey_str != coinbase_burn_address_viewkey_hex_str){
1440  MERROR_VER("v11 miner tx output " << print_etn(o.amount) << " is being sent to an address other than the burn address");
1441  return false;
1442  }
1443  }
1444  }
1445 
1446  LOG_PRINT_L3("Blockchain::" << __func__);
1447  //validate reward
1448  uint64_t etn_in_use = 0;
1449  for (auto& o: b.miner_tx.vout)
1450  etn_in_use += o.amount;
1451  partial_block_reward = false;
1452 
1453  if (version == 3) {
1454  for (auto &o: b.miner_tx.vout) {
1455  if (!is_valid_decomposed_amount(o.amount)) {
1456  MERROR_VER("miner tx output " << print_etn(o.amount) << " is not a valid decomposed amount");
1457  return false;
1458  }
1459  }
1460  }
1461 
1462  std::vector<uint64_t> last_blocks_weights;
1463  get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
1464  if (!get_block_reward(epee::misc_utils::median(last_blocks_weights), cumulative_block_weight, already_generated_coins, base_reward, version, get_current_blockchain_height(), get_nettype()))
1465  {
1466  MERROR_VER("block weight " << cumulative_block_weight << " is bigger than allowed for this blockchain");
1467  return false;
1468  }
1469  if(base_reward + fee < etn_in_use && already_generated_coins > 0)
1470  {
1471  MERROR_VER("coinbase transaction spend too much ETN (" << print_etn(etn_in_use) << "). Block reward is " << print_etn(base_reward + fee) << "(" << print_etn(base_reward) << "+" << print_etn(fee) << ")");
1472  return false;
1473  }
1474  // From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
1475  if (version < 2)
1476  {
1477  if(base_reward + fee != etn_in_use && already_generated_coins > 0)
1478  {
1479  MDEBUG("coinbase transaction doesn't use full amount of block reward: spent: " << etn_in_use << ", block reward " << base_reward + fee << "(" << base_reward << "+" << fee << ")");
1480  return false;
1481  }
1482  }
1483  else
1484  {
1485  // from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward
1486  // to show the amount of coins that were actually generated, the remainder will be pushed back for later
1487  // emission. This modifies the emission curve very slightly.
1488  CHECK_AND_ASSERT_MES(etn_in_use - fee <= base_reward, false, "base reward calculation bug");
1489  if(base_reward + fee != etn_in_use)
1490  partial_block_reward = true;
1491  base_reward = etn_in_use - fee;
1492  }
1493  return true;
1494 }
1495 //------------------------------------------------------------------
1496 // get the block weights of the last <count> blocks, and return by reference <sz>.
1497 void Blockchain::get_last_n_blocks_weights(std::vector<uint64_t>& weights, size_t count) const
1498 {
1499  LOG_PRINT_L3("Blockchain::" << __func__);
1500  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1501  auto h = m_db->height();
1502 
1503  // this function is meaningless for an empty blockchain...granted it should never be empty
1504  if(h == 0)
1505  return;
1506 
1507  // add weight of last <count> blocks to vector <weights> (or less, if blockchain size < count)
1508  size_t start_offset = h - std::min<size_t>(h, count);
1509  weights = m_db->get_block_weights(start_offset, count);
1510 }
1511 //------------------------------------------------------------------
1512 uint64_t Blockchain::get_long_term_block_weight_median(uint64_t start_height, size_t count) const
1513 {
1514  LOG_PRINT_L3("Blockchain::" << __func__);
1515  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1516 
1517  PERF_TIMER(get_long_term_block_weights);
1518 
1519  CHECK_AND_ASSERT_THROW_MES(count > 0, "count == 0");
1520 
1521  bool cached = false;
1522  uint64_t blockchain_height = m_db->height();
1523  uint64_t tip_height = start_height + count - 1;
1524  crypto::hash tip_hash = crypto::null_hash;
1525  if (tip_height < blockchain_height && count == (size_t)m_long_term_block_weights_cache_rolling_median.size())
1526  {
1527  tip_hash = m_db->get_block_hash_from_height(tip_height);
1528  cached = tip_hash == m_long_term_block_weights_cache_tip_hash;
1529  }
1530 
1531  if (cached)
1532  {
1533  MTRACE("requesting " << count << " from " << start_height << ", cached");
1534  return m_long_term_block_weights_cache_rolling_median.median();
1535  }
1536 
1537  // in the vast majority of uncached cases, most is still cached,
1538  // as we just move the window one block up:
1539  if (tip_height > 0 && count == (size_t)m_long_term_block_weights_cache_rolling_median.size() && tip_height < blockchain_height)
1540  {
1541  crypto::hash old_tip_hash = m_db->get_block_hash_from_height(tip_height - 1);
1542  if (old_tip_hash == m_long_term_block_weights_cache_tip_hash)
1543  {
1544  MTRACE("requesting " << count << " from " << start_height << ", incremental");
1545  m_long_term_block_weights_cache_tip_hash = tip_hash;
1546  m_long_term_block_weights_cache_rolling_median.insert(m_db->get_block_long_term_weight(tip_height));
1547  return m_long_term_block_weights_cache_rolling_median.median();
1548  }
1549  }
1550 
1551  MTRACE("requesting " << count << " from " << start_height << ", uncached");
1552  std::vector<uint64_t> weights = m_db->get_long_term_block_weights(start_height, count);
1553  m_long_term_block_weights_cache_tip_hash = tip_hash;
1554  m_long_term_block_weights_cache_rolling_median.clear();
1555  for (uint64_t w: weights)
1556  m_long_term_block_weights_cache_rolling_median.insert(w);
1557  return m_long_term_block_weights_cache_rolling_median.median();
1558 }
1559 //------------------------------------------------------------------
1561 {
1562  LOG_PRINT_L3("Blockchain::" << __func__);
1563  return m_current_block_cumul_weight_limit;
1564 }
1565 //------------------------------------------------------------------
1567 {
1568  LOG_PRINT_L3("Blockchain::" << __func__);
1569  return m_current_block_cumul_weight_median;
1570 }
1571 //------------------------------------------------------------------
1572 //TODO: This function only needed minor modification to work with BlockchainDB,
1573 // and *works*. As such, to reduce the number of things that might break
1574 // in moving to BlockchainDB, this function will remain otherwise
1575 // unchanged for the time being.
1576 //
1577 // This function makes a new block for a miner to mine the hash for
1578 //
1579 // FIXME: this codebase references #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1580 // in a lot of places. That flag is not referenced in any of the code
1581 // nor any of the makefiles, howeve. Need to look into whether or not it's
1582 // necessary at all.
1583 bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1584 {
1585  LOG_PRINT_L3("Blockchain::" << __func__);
1586  size_t median_weight;
1587  uint64_t already_generated_coins;
1588  //uint64_t pool_cookie;
1589 
1590  m_tx_pool.lock();
1591  const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
1592  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1593  if (m_btc_valid && !from_block) {
1594  // The pool cookie is atomic. The lack of locking is OK, as if it changes
1595  // just as we compare it, we'll just use a slightly old template, but
1596  // this would be the case anyway if we'd lock, and the change happened
1597  // just after the block template was created
1598  if (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address)) && m_btc_nonce == ex_nonce
1599  && m_btc_pool_cookie == m_tx_pool.cookie() && m_btc.prev_id == get_tail_id()) {
1600  MDEBUG("Using cached template");
1601  m_btc.timestamp = time(NULL); // update timestamp unconditionally
1602  b = m_btc;
1603  diffic = m_btc_difficulty;
1604  height = m_btc_height;
1605  expected_reward = m_btc_expected_reward;
1606  return true;
1607  }
1608  MDEBUG("Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address))) << ", nonce " << (m_btc_nonce == ex_nonce) << ", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()) << ", from_block " << (!!from_block));
1609  invalidate_block_template_cache();
1610  }
1611 
1612  if (from_block)
1613  {
1614  //build alternative subchain, front -> mainchain, back -> alternative head
1615  //block is not related with head of main chain
1616  //first of all - look in alternative chains container
1617  auto it_prev = m_alternative_chains.find(*from_block);
1618  bool parent_in_main = m_db->block_exists(*from_block);
1619  if(it_prev == m_alternative_chains.end() && !parent_in_main)
1620  {
1621  MERROR("Unknown from block");
1622  return false;
1623  }
1624 
1625  //we have new block in alternative chain
1626  std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1627  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1628  std::vector<uint64_t> timestamps;
1629  if (!build_alt_chain(*from_block, alt_chain, timestamps, bvc))
1630  return false;
1631 
1632  if (parent_in_main)
1633  {
1634  cryptonote::block prev_block;
1635  CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
1636  uint64_t from_block_height = cryptonote::get_block_height(prev_block);
1637  height = from_block_height + 1;
1638  }
1639  else
1640  {
1641  height = alt_chain.back()->second.height + 1;
1642  }
1643  b.major_version = m_hardfork->get_ideal_version(height);
1644  b.minor_version = m_hardfork->get_ideal_version();
1645  b.prev_id = *from_block;
1646 
1647  // cheat and use the weight of the block we start from, virtually certain to be acceptable
1648  // and use 1.9 times rather than 2 times so we're even more sure
1649  if (parent_in_main)
1650  {
1651  median_weight = m_db->get_block_weight(height - 1);
1652  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1653  }
1654  else
1655  {
1656  median_weight = it_prev->second.block_cumulative_weight - it_prev->second.block_cumulative_weight / 20;
1657  already_generated_coins = alt_chain.back()->second.already_generated_coins;
1658  }
1659 
1660  // FIXME: consider moving away from block_extended_info at some point
1661  block_extended_info bei = boost::value_initialized<block_extended_info>();
1662  bei.bl = b;
1663  bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(*from_block) + 1;
1664 
1665  diffic = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1666  }
1667  else
1668  {
1669  height = m_db->height();
1670  b.major_version = m_hardfork->get_current_version();
1671  b.minor_version = m_hardfork->get_ideal_version();
1672  b.prev_id = get_tail_id();
1673  median_weight = m_current_block_cumul_weight_limit / 2;
1674  diffic = get_difficulty_for_next_block();
1675  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1676  }
1677  b.timestamp = time(NULL);
1678 
1679  uint64_t median_ts;
1680  if (!check_block_timestamp(b, median_ts))
1681  {
1682  b.timestamp = median_ts;
1683  }
1684 
1685  CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
1686 
1687  size_t txs_weight;
1688  uint64_t fee;
1689  if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version))
1690  {
1691  return false;
1692  }
1693  //pool_cookie = m_tx_pool.cookie();
1694 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1695  size_t real_txs_weight = 0;
1696  uint64_t real_fee = 0;
1697  for(crypto::hash &cur_hash: b.tx_hashes)
1698  {
1699  auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
1700  if (cur_res == m_tx_pool.m_transactions.end())
1701  {
1702  LOG_ERROR("Creating block template: error: transaction not found");
1703  continue;
1704  }
1705  tx_memory_pool::tx_details &cur_tx = cur_res->second;
1706  real_txs_weight += cur_tx.weight;
1707  real_fee += cur_tx.fee;
1708  if (cur_tx.weight != get_transaction_weight(cur_tx.tx))
1709  {
1710  LOG_ERROR("Creating block template: error: invalid transaction weight");
1711  }
1712 
1713  uint64_t inputs_amount;
1714  if (!get_inputs_etn_amount(cur_tx.tx, inputs_amount))
1715  {
1716  LOG_ERROR("Creating block template: error: cannot get inputs amount");
1717  }
1718  else if (cur_tx.fee != inputs_amount - get_outs_etn_amount(cur_tx.tx))
1719  {
1720  LOG_ERROR("Creating block template: error: invalid fee");
1721  }
1722  }
1723  if (txs_weight != real_txs_weight)
1724  {
1725  LOG_ERROR("Creating block template: error: wrongly calculated transaction weight");
1726  }
1727  if (fee != real_fee)
1728  {
1729  LOG_ERROR("Creating block template: error: wrongly calculated fee");
1730  }
1731  MDEBUG("Creating block template: height " << height <<
1732  ", median weight " << median_weight <<
1733  ", already generated coins " << already_generated_coins <<
1734  ", transaction weight " << txs_weight <<
1735  ", fee " << fee);
1736 #endif
1737 
1738  /*
1739  two-phase miner transaction generation: we don't know exact block weight until we prepare block, but we don't know reward until we know
1740  block weight, so first miner transaction generated with fake amount of etn, and with phase we know think we know expected block weight
1741  */
1742  //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
1743  uint8_t hf_version = b.major_version;
1744  size_t max_outs = hf_version >= 4 ? 1 : 11;
1745  bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1746  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
1747  size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
1748 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1749  MDEBUG("Creating block template: miner tx weight " << get_transaction_weight(b.miner_tx) <<
1750  ", cumulative weight " << cumulative_weight);
1751 #endif
1752  for (size_t try_count = 0; try_count != 10; ++try_count)
1753  {
1754  r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1755 
1756  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
1757  size_t coinbase_weight = get_transaction_weight(b.miner_tx);
1758  if (coinbase_weight > cumulative_weight - txs_weight)
1759  {
1760  cumulative_weight = txs_weight + coinbase_weight;
1761 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1762  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1763  ", cumulative weight " << cumulative_weight << " is greater than before");
1764 #endif
1765  continue;
1766  }
1767 
1768  if (coinbase_weight < cumulative_weight - txs_weight)
1769  {
1770  size_t delta = cumulative_weight - txs_weight - coinbase_weight;
1771 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1772  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1773  ", cumulative weight " << txs_weight + coinbase_weight <<
1774  " is less than before, adding " << delta << " zero bytes");
1775 #endif
1776  b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
1777  //here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
1778  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1779  {
1780  CHECK_AND_ASSERT_MES(cumulative_weight + 1 == txs_weight + get_transaction_weight(b.miner_tx), false, "unexpected case: cumulative_weight=" << cumulative_weight << " + 1 is not equal txs_cumulative_weight=" << txs_weight << " + get_transaction_weight(b.miner_tx)=" << get_transaction_weight(b.miner_tx));
1781  b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
1782  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1783  {
1784  //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_weight
1785  MDEBUG("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1);
1786  cumulative_weight += delta - 1;
1787  continue;
1788  }
1789  MDEBUG("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count);
1790  }
1791  }
1792  CHECK_AND_ASSERT_MES(cumulative_weight == txs_weight + get_transaction_weight(b.miner_tx), false, "unexpected case: cumulative_weight=" << cumulative_weight << " is not equal txs_cumulative_weight=" << txs_weight << " + get_transaction_weight(b.miner_tx)=" << get_transaction_weight(b.miner_tx));
1793 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1794  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1795  ", cumulative weight " << cumulative_weight << " is now good");
1796 #endif
1797 
1798  //if (!from_block)
1799  // cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, pool_cookie);
1800 
1801  if(!m_fallback_to_pow && hf_version >= 8) {
1802  sign_block(b, m_validator_key);
1803  }
1804 
1805  return true;
1806  }
1807  LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
1808  return false;
1809 }
1810 
1812  crypto::hash tx_tree_hash = get_tx_tree_hash(b);
1813 
1814  std::string signature = crypto::sign_message(std::string(reinterpret_cast<char const*>(tx_tree_hash.data), sizeof(tx_tree_hash.data)), privateKey);
1815  if(signature.empty() || signature.size() != 64) {
1816  LOG_ERROR("The daemon has failed to digitally sign a block and therefore it cannot be accepted by the network. Please check your validator-key configuration before resuming mining.");
1817  return;
1818  }
1819 
1820  b.signature = std::vector<uint8_t>(signature.begin(), signature.end());
1821 }
1822 
1824  crypto::hash tx_tree_hash = get_tx_tree_hash(b);
1825  const std::vector<std::string> public_keys = m_validators->getApplicablePublicKeys(m_db->height(), true);
1826 
1827  for(auto &key : public_keys) {
1828  if(crypto::verify_signature(std::string(reinterpret_cast<char const *>(tx_tree_hash.data), sizeof(tx_tree_hash.data)),
1829  key, std::string(b.signature.begin(), b.signature.end()))){
1830  b.signatory = std::vector<uint8_t>(key.begin(), key.end());
1831  return true;
1832  }
1833  }
1834  return false;
1835 }
1836 
1837 //------------------------------------------------------------------
1838 bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1839 {
1840  return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce);
1841 }
1842 //------------------------------------------------------------------
1843 // for an alternate chain, get the timestamps from the main chain to complete
1844 // the needed number of timestamps for the BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW.
1845 bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps) const
1846 {
1847  LOG_PRINT_L3("Blockchain::" << __func__);
1848 
1849  if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
1850  return true;
1851 
1852  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1853  size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size();
1854  CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height());
1855  size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
1856  timestamps.reserve(timestamps.size() + start_top_height - stop_offset);
1857  while (start_top_height != stop_offset)
1858  {
1859  timestamps.push_back(m_db->get_block_timestamp(start_top_height));
1860  --start_top_height;
1861  }
1862  return true;
1863 }
1864 //------------------------------------------------------------------
1865 bool Blockchain::build_alt_chain(const crypto::hash &prev_id, std::list<blocks_ext_by_hash::const_iterator>& alt_chain, std::vector<uint64_t> &timestamps, block_verification_context& bvc) const
1866 {
1867  //build alternative subchain, front -> mainchain, back -> alternative head
1868  blocks_ext_by_hash::const_iterator alt_it = m_alternative_chains.find(prev_id);
1869  timestamps.clear();
1870  while(alt_it != m_alternative_chains.end())
1871  {
1872  alt_chain.push_front(alt_it);
1873  timestamps.push_back(alt_it->second.bl.timestamp);
1874  alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id);
1875  }
1876 
1877  // if block to be added connects to known blocks that aren't part of the
1878  // main chain -- that is, if we're adding on to an alternate chain
1879  if(!alt_chain.empty())
1880  {
1881  // make sure alt chain doesn't somehow start past the end of the main chain
1882  CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height");
1883 
1884  // make sure that the blockchain contains the block that should connect
1885  // this alternate chain with it.
1886  if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
1887  {
1888  MERROR("alternate chain does not appear to connect to main chain...");
1889  return false;
1890  }
1891 
1892  // make sure block connects correctly to the main chain
1893  auto h = m_db->get_block_hash_from_height(alt_chain.front()->second.height - 1);
1894  CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id, false, "alternative chain has wrong connection to main chain");
1895  complete_timestamps_vector(m_db->get_block_height(alt_chain.front()->second.bl.prev_id), timestamps);
1896  }
1897  // if block not associated with known alternate chain
1898  else
1899  {
1900  // if block parent is not part of main chain or an alternate chain,
1901  // we ignore it
1902  bool parent_in_main = m_db->block_exists(prev_id);
1903  CHECK_AND_ASSERT_MES(parent_in_main, false, "internal error: broken imperative condition: parent_in_main");
1904 
1905  complete_timestamps_vector(m_db->get_block_height(prev_id), timestamps);
1906  }
1907 
1908  return true;
1909 }
1910 //------------------------------------------------------------------
1911 // If a block is to be added and its parent block is not the current
1912 // main chain top block, then we need to see if we know about its parent block.
1913 // If its parent block is part of a known forked chain, then we need to see
1914 // if that chain is long enough to become the main chain and re-org accordingly
1915 // if so. If not, we need to hang on to the block in case it becomes part of
1916 // a long forked chain eventually.
1917 bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc)
1918 {
1919  LOG_PRINT_L3("Blockchain::" << __func__);
1920  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1921  m_timestamps_and_difficulties_height = 0;
1922  uint64_t block_height = get_block_height(b);
1923  if(0 == block_height)
1924  {
1925  MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0.");
1926  bvc.m_verification_failed = true;
1927  return false;
1928  }
1929 
1930  if(b.major_version >= 8) {
1931 
1932  if(!m_fallback_to_pow) {
1933 
1934  if(!m_validators->isEnabled()) {
1935  m_validators->enable();
1936  }
1937 
1938  if(!m_validators->isValid()) {
1939  bvc.m_validator_list_update_failed = true;
1940  return false;
1941  }
1942 
1943  if(!verify_block_signature(b)) {
1944  MERROR_VER("Block with id: " << id << std::endl << " has wrong digital signature");
1945  bvc.m_verification_failed = true;
1946  return false;
1947  }
1948  }
1949  }
1950 
1951  // this basically says if the blockchain is smaller than the first
1952  // checkpoint then alternate blocks are allowed. Alternatively, if the
1953  // last checkpoint *before* the end of the current chain is also before
1954  // the block to be added, then this is fine.
1955  if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
1956  {
1957  MERROR_VER("Block with id: " << id << std::endl << " can't be accepted for alternative chain, block height: " << block_height << std::endl << " blockchain height: " << get_current_blockchain_height());
1958  bvc.m_verification_failed = true;
1959  return false;
1960  }
1961 
1962  // this is a cheap test
1963  if (!m_hardfork->check_for_height(b, block_height))
1964  {
1965  LOG_PRINT_L1("Block with id: " << id << std::endl << "has old version for height " << block_height);
1966  bvc.m_verification_failed = true;
1967  return false;
1968  }
1969 
1970  //block is not related with head of main chain
1971  //first of all - look in alternative chains container
1972  auto it_prev = m_alternative_chains.find(b.prev_id);
1973  bool parent_in_main = m_db->block_exists(b.prev_id);
1974  if(it_prev != m_alternative_chains.end() || parent_in_main)
1975  {
1976  //we have new block in alternative chain
1977  std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1978  std::vector<uint64_t> timestamps;
1979  if (!build_alt_chain(b.prev_id, alt_chain, timestamps, bvc))
1980  return false;
1981 
1982  // FIXME: consider moving away from block_extended_info at some point
1983  block_extended_info bei = boost::value_initialized<block_extended_info>();
1984  bei.bl = b;
1985  const uint64_t prev_height = alt_chain.size() ? it_prev->second.height : m_db->get_block_height(b.prev_id);
1986  bei.height = prev_height + 1;
1987  uint64_t block_reward = get_outs_etn_amount(b.miner_tx);
1988  bei.already_generated_coins = block_reward + (alt_chain.size() ? it_prev->second.already_generated_coins : m_db->get_block_already_generated_coins(prev_height));
1989 
1990  if(!m_fallback_to_pow && b.major_version >= 8)
1991  {
1992  std::vector<uint8_t> prev_signatory = alt_chain.size() ? it_prev->second.bl.signatory : m_db->get_block(b.prev_id).signatory;
1993  CHECK_AND_ASSERT_MES(b.signatory != prev_signatory, false, "a single validator can't mine blocks in sequence");
1994  }
1995 
1996  // verify that the block's timestamp is within the acceptable range
1997  // (not earlier than the median of the last X blocks)
1998  if(!check_block_timestamp(timestamps, b))
1999  {
2000  MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, has invalid timestamp: " << b.timestamp);
2001  bvc.m_verification_failed = true;
2002  return false;
2003  }
2004 
2005  bool is_a_checkpoint;
2006  if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint))
2007  {
2008  LOG_ERROR("CHECKPOINT VALIDATION FAILED");
2009  bvc.m_verification_failed = true;
2010  return false;
2011  }
2012 
2013  // Check the block's hash against the difficulty target for its alt chain
2014  difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
2015  CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
2016  crypto::hash proof_of_work = null_hash;
2017  get_block_longhash(bei.bl, proof_of_work, bei.height);
2018  if(!check_hash(proof_of_work, current_diff))
2019  {
2020  MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
2021  bvc.m_verification_failed = true;
2022  return false;
2023  }
2024 
2025  if(!prevalidate_miner_transaction(b, bei.height))
2026  {
2027  MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction.");
2028  bvc.m_verification_failed = true;
2029  return false;
2030  }
2031 
2032  // FIXME:
2033  // this brings up an interesting point: consider allowing to get block
2034  // difficulty both by height OR by hash, not just height.
2035  difficulty_type main_chain_cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->height() - 1);
2036  if (alt_chain.size())
2037  {
2038  bei.cumulative_difficulty = it_prev->second.cumulative_difficulty;
2039  }
2040  else
2041  {
2042  // passed-in block's previous block's cumulative difficulty, found on the main chain
2043  bei.cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->get_block_height(b.prev_id));
2044  }
2045  bei.cumulative_difficulty += current_diff;
2046 
2047  // add block to alternate blocks storage,
2048  // as well as the current "alt chain" container
2049  auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
2050  CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
2051  alt_chain.push_back(i_res.first);
2052 
2053  // FIXME: is it even possible for a checkpoint to show up not on the main chain?
2054  if(is_a_checkpoint)
2055  {
2056  //do reorganize!
2057  MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height);
2058 
2059  bool r = switch_to_alternative_blockchain(alt_chain, true);
2060 
2061  if(r) bvc.m_added_to_main_chain = true;
2062  else bvc.m_verification_failed = true;
2063 
2064  return r;
2065  }
2066  else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
2067  {
2068  //do reorganize!
2069  MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty);
2070 
2071  bool r = switch_to_alternative_blockchain(alt_chain, false);
2072  if (r)
2073  bvc.m_added_to_main_chain = true;
2074  else
2075  bvc.m_verification_failed = true;
2076  return r;
2077  }
2078  else
2079  {
2080  MGINFO_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff);
2081  return true;
2082  }
2083  }
2084  else
2085  {
2086  //block orphaned
2087  bvc.m_marked_as_orphaned = true;
2088  MERROR_VER("Block recognized as orphaned and rejected, id = " << id << ", height " << block_height
2089  << ", parent in alt " << (it_prev != m_alternative_chains.end()) << ", parent in main " << parent_in_main
2090  << " (parent " << b.prev_id << ", current top " << get_tail_id() << ", chain height " << get_current_blockchain_height() << ")");
2091  }
2092 
2093  return true;
2094 }
2095 //------------------------------------------------------------------
2096 bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata,block>>& blocks, std::vector<cryptonote::blobdata>& txs) const
2097 {
2098  LOG_PRINT_L3("Blockchain::" << __func__);
2099  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2100  if(start_offset >= m_db->height())
2101  return false;
2102 
2103  if (!get_blocks(start_offset, count, blocks))
2104  {
2105  return false;
2106  }
2107 
2108  for(const auto& blk : blocks)
2109  {
2110  std::vector<crypto::hash> missed_ids;
2111  get_transactions_blobs(blk.second.tx_hashes, txs, missed_ids);
2112  CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain");
2113  }
2114 
2115  return true;
2116 }
2117 //------------------------------------------------------------------
2118 bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata,block>>& blocks) const
2119 {
2120  LOG_PRINT_L3("Blockchain::" << __func__);
2121  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2122  const uint64_t height = m_db->height();
2123  if(start_offset >= height)
2124  return false;
2125 
2126  blocks.reserve(blocks.size() + height - start_offset);
2127  for(size_t i = start_offset; i < start_offset + count && i < height;i++)
2128  {
2129  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(i), block()));
2130  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2131  {
2132  LOG_ERROR("Invalid block");
2133  return false;
2134  }
2135  }
2136  return true;
2137 }
2138 //------------------------------------------------------------------
2139 //TODO: This function *looks* like it won't need to be rewritten
2140 // to use BlockchainDB, as it calls other functions that were,
2141 // but it warrants some looking into later.
2142 //
2143 //FIXME: This function appears to want to return false if any transactions
2144 // that belong with blocks are missing, but not if blocks themselves
2145 // are missing.
2147 {
2148  LOG_PRINT_L3("Blockchain::" << __func__);
2149  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2150  db_rtxn_guard rtxn_guard (m_db);
2151  rsp.current_blockchain_height = get_current_blockchain_height();
2152  std::vector<std::pair<cryptonote::blobdata,block>> blocks;
2153  get_blocks(arg.blocks, blocks, rsp.missed_ids);
2154 
2155  for (auto& bl: blocks)
2156  {
2157  std::vector<crypto::hash> missed_tx_ids;
2158 
2159  rsp.blocks.push_back(block_complete_entry());
2160  block_complete_entry& e = rsp.blocks.back();
2161 
2162  // FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids
2163  // is for missed blocks, not missed transactions as well.
2164  get_transactions_blobs(bl.second.tx_hashes, e.txs, missed_tx_ids);
2165 
2166  if (missed_tx_ids.size() != 0)
2167  {
2168  // do not display an error if the peer asked for an unpruned block which we are not meant to have
2170  {
2171  LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size()
2172  << " transactions for block with hash: " << get_block_hash(bl.second)
2173  << std::endl
2174  );
2175  }
2176 
2177  // append missed transaction hashes to response missed_ids field,
2178  // as done below if any standalone transactions were requested
2179  // and missed.
2180  rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
2181  return false;
2182  }
2183 
2184  //pack block
2185  e.block = std::move(bl.first);
2186  }
2187  //get and pack other transactions, if needed
2188  get_transactions_blobs(arg.txs, rsp.txs, rsp.missed_ids);
2189 
2190  return true;
2191 }
2192 //------------------------------------------------------------------
2193 bool Blockchain::get_alternative_blocks(std::vector<block>& blocks) const
2194 {
2195  LOG_PRINT_L3("Blockchain::" << __func__);
2196  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2197 
2198  blocks.reserve(m_alternative_chains.size());
2199  for (const auto& alt_bl: m_alternative_chains)
2200  {
2201  blocks.push_back(alt_bl.second.bl);
2202  }
2203  return true;
2204 }
2205 //------------------------------------------------------------------
2207 {
2208  LOG_PRINT_L3("Blockchain::" << __func__);
2209  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2210  return m_alternative_chains.size();
2211 }
2212 //------------------------------------------------------------------
2213 // This function adds the output specified by <amount, i> to the result_outs container
2214 // unlocked and other such checks should be done by here.
2216 {
2217  uint64_t num_outs = m_db->get_num_outputs(amount);
2218  // ensure we don't include outputs that aren't yet eligible to be used
2219  // outpouts are sorted by height
2220  const uint64_t blockchain_height = m_db->height();
2221  while (num_outs > 0)
2222  {
2223  const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
2224  const uint64_t height = m_db->get_tx_block_height(toi.first);
2226  break;
2227  --num_outs;
2228  }
2229 
2230  return num_outs;
2231 }
2232 
2234 {
2235  output_data_t data = m_db->get_output_key(amount, global_index);
2236  return data.pubkey;
2237 }
2238 
2239 //------------------------------------------------------------------
2241 {
2242  LOG_PRINT_L3("Blockchain::" << __func__);
2243  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2244 
2245  res.outs.clear();
2246  res.outs.reserve(req.outputs.size());
2247 
2248  std::vector<cryptonote::output_data_t> data;
2249  try
2250  {
2251  std::vector<uint64_t> amounts, offsets;
2252  amounts.reserve(req.outputs.size());
2253  offsets.reserve(req.outputs.size());
2254  for (const auto &i: req.outputs)
2255  {
2256  amounts.push_back(i.amount);
2257  offsets.push_back(i.index);
2258  }
2259  m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
2260  if (data.size() != req.outputs.size())
2261  {
2262  MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size());
2263  return false;
2264  }
2265  for (const auto &t: data)
2266  res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
2267 
2268  if (req.get_txid)
2269  {
2270  for (size_t i = 0; i < req.outputs.size(); ++i)
2271  {
2272  tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index);
2273  res.outs[i].txid = toi.first;
2274  }
2275  }
2276  }
2277  catch (const std::exception &e)
2278  {
2279  return false;
2280  }
2281  return true;
2282 }
2283 //------------------------------------------------------------------
2284 void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint64_t& index, crypto::public_key& key, rct::key& mask, bool& unlocked) const
2285 {
2286  const auto o_data = m_db->get_output_key(amount, index);
2287  key = o_data.pubkey;
2288  mask = o_data.commitment;
2289  tx_out_index toi = m_db->get_output_tx_and_index(amount, index);
2290  unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
2291 }
2292 //------------------------------------------------------------------
2293 bool Blockchain::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
2294 {
2295  // rct outputs don't exist before v4
2296  if (amount == 0)
2297  {
2298  switch (m_nettype)
2299  {
2300  case STAGENET: start_height = stagenet_hard_forks[3].height; break;
2301  case TESTNET: start_height = testnet_hard_forks[3].height; break;
2302  case MAINNET: start_height = mainnet_hard_forks[3].height; break;
2303  case FAKECHAIN: start_height = 0; break;
2304  default: return false;
2305  }
2306  }
2307  else
2308  start_height = 0;
2309  base = 0;
2310 
2311  if (to_height > 0 && to_height < from_height)
2312  return false;
2313 
2314  const uint64_t real_start_height = start_height;
2315  if (from_height > start_height)
2316  start_height = from_height;
2317 
2318  distribution.clear();
2319  uint64_t db_height = m_db->height();
2320  if (db_height == 0)
2321  return false;
2322  if (start_height >= db_height || to_height >= db_height)
2323  return false;
2324  if (amount == 0)
2325  {
2326  std::vector<uint64_t> heights;
2327  heights.reserve(to_height + 1 - start_height);
2328  uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
2329  for (uint64_t h = real_start_height; h <= to_height; ++h)
2330  heights.push_back(h);
2331  distribution = m_db->get_block_cumulative_rct_outputs(heights);
2332  if (start_height > 0)
2333  {
2334  base = distribution[0];
2335  distribution.erase(distribution.begin());
2336  }
2337  return true;
2338  }
2339  else
2340  {
2341  return m_db->get_output_distribution(amount, start_height, to_height, distribution, base);
2342  }
2343 }
2344 //------------------------------------------------------------------
2345 // This function takes a list of block hashes from another node
2346 // on the network to find where the split point is between us and them.
2347 // This is used to see what to send another node that needs to sync.
2348 bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, uint64_t& starter_offset) const
2349 {
2350  LOG_PRINT_L3("Blockchain::" << __func__);
2351  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2352 
2353  // make sure the request includes at least the genesis block, otherwise
2354  // how can we expect to sync from the client that the block list came from?
2355  if(qblock_ids.empty())
2356  {
2357  MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << ", dropping connection");
2358  return false;
2359  }
2360 
2361  db_rtxn_guard rtxn_guard(m_db);
2362  // make sure that the last block in the request's block list matches
2363  // the genesis block
2364  auto gen_hash = m_db->get_block_hash_from_height(0);
2365  if(qblock_ids.back() != gen_hash)
2366  {
2367  LOG_PRINT_L0("Genesis Block Mismatch");
2368  MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
2369  return false;
2370  }
2371 
2372  // Find the first block the foreign chain has that we also have.
2373  // Assume qblock_ids is in reverse-chronological order.
2374  auto bl_it = qblock_ids.begin();
2375  uint64_t split_height = 0;
2376  for(; bl_it != qblock_ids.end(); bl_it++)
2377  {
2378  try
2379  {
2380  if (m_db->block_exists(*bl_it, &split_height))
2381  break;
2382  }
2383  catch (const std::exception& e)
2384  {
2385  MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
2386  return false;
2387  }
2388  }
2389 
2390  // this should be impossible, as we checked that we share the genesis block,
2391  // but just in case...
2392  if(bl_it == qblock_ids.end())
2393  {
2394  MERROR("Internal error handling connection, can't find split point");
2395  return false;
2396  }
2397 
2398  //we start to put block ids INCLUDING last known id, just to make other side be sure
2399  starter_offset = split_height;
2400  return true;
2401 }
2402 //------------------------------------------------------------------
2404 {
2405  LOG_PRINT_L3("Blockchain::" << __func__);
2406  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2407  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2408  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2409  // lock if it is otherwise needed.
2410  try
2411  {
2412  return m_db->get_block_difficulty(i);
2413  }
2414  catch (const BLOCK_DNE& e)
2415  {
2416  MERROR("Attempted to get block difficulty for height above blockchain height");
2417  }
2418  return 0;
2419 }
2420 //------------------------------------------------------------------
2421 template<typename T> void reserve_container(std::vector<T> &v, size_t N) { v.reserve(N); }
2422 template<typename T> void reserve_container(std::list<T> &v, size_t N) { }
2423 //------------------------------------------------------------------
2424 //TODO: return type should be void, throw on exception
2425 // alternatively, return true only if no blocks missed
2426 template<class t_ids_container, class t_blocks_container, class t_missed_container>
2427 bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const
2428 {
2429  LOG_PRINT_L3("Blockchain::" << __func__);
2430  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2431 
2432  reserve_container(blocks, block_ids.size());
2433  for (const auto& block_hash : block_ids)
2434  {
2435  try
2436  {
2437  uint64_t height = 0;
2438  if (m_db->block_exists(block_hash, &height))
2439  {
2440  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(height), block()));
2441  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2442  {
2443  LOG_ERROR("Invalid block: " << block_hash);
2444  blocks.pop_back();
2445  missed_bs.push_back(block_hash);
2446  }
2447  }
2448  else
2449  missed_bs.push_back(block_hash);
2450  }
2451  catch (const std::exception& e)
2452  {
2453  return false;
2454  }
2455  }
2456  return true;
2457 }
2458 //------------------------------------------------------------------
2459 //TODO: return type should be void, throw on exception
2460 // alternatively, return true only if no transactions missed
2461 template<class t_ids_container, class t_tx_container, class t_missed_container>
2462 bool Blockchain::get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool pruned) const
2463 {
2464  LOG_PRINT_L3("Blockchain::" << __func__);
2465  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2466 
2467  reserve_container(txs, txs_ids.size());
2468  for (const auto& tx_hash : txs_ids)
2469  {
2470  try
2471  {
2473  if (pruned && m_db->get_pruned_tx_blob(tx_hash, tx))
2474  txs.push_back(std::move(tx));
2475  else if (!pruned && m_db->get_tx_blob(tx_hash, tx))
2476  txs.push_back(std::move(tx));
2477  else
2478  missed_txs.push_back(tx_hash);
2479  }
2480  catch (const std::exception& e)
2481  {
2482  return false;
2483  }
2484  }
2485  return true;
2486 }
2487 //------------------------------------------------------------------
2489 {
2490  size_t version;
2491  const char* begin = static_cast<const char*>(bd.data());
2492  const char* end = begin + bd.size();
2493  int read = tools::read_varint(begin, end, version);
2494  if (read <= 0)
2495  throw std::runtime_error("Internal error getting transaction version");
2496  return version;
2497 }
2498 //------------------------------------------------------------------
2499 template<class t_ids_container, class t_tx_container, class t_missed_container>
2500 bool Blockchain::get_split_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
2501 {
2502  LOG_PRINT_L3("Blockchain::" << __func__);
2503  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2504 
2505  reserve_container(txs, txs_ids.size());
2506  for (const auto& tx_hash : txs_ids)
2507  {
2508  try
2509  {
2511  if (m_db->get_pruned_tx_blob(tx_hash, tx))
2512  {
2513  txs.push_back(std::make_tuple(tx_hash, std::move(tx), crypto::null_hash, cryptonote::blobdata()));
2514  if (!is_v1_tx(std::get<1>(txs.back())) && !m_db->get_prunable_tx_hash(tx_hash, std::get<2>(txs.back())))
2515  {
2516  MERROR("Prunable data hash not found for " << tx_hash);
2517  return false;
2518  }
2519  if (!m_db->get_prunable_tx_blob(tx_hash, std::get<3>(txs.back())))
2520  std::get<3>(txs.back()).clear();
2521  }
2522  else
2523  missed_txs.push_back(tx_hash);
2524  }
2525  catch (const std::exception& e)
2526  {
2527  return false;
2528  }
2529  }
2530  return true;
2531 }
2532 //------------------------------------------------------------------
2533 template<class t_ids_container, class t_tx_container, class t_missed_container>
2534 bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
2535 {
2536  LOG_PRINT_L3("Blockchain::" << __func__);
2537  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2538 
2539  reserve_container(txs, txs_ids.size());
2540  for (const auto& tx_hash : txs_ids)
2541  {
2542  try
2543  {
2545  if (m_db->get_tx_blob(tx_hash, tx))
2546  {
2547  txs.push_back(transaction());
2548  if (!parse_and_validate_tx_from_blob(tx, txs.back()))
2549  {
2550  LOG_ERROR("Invalid transaction");
2551  return false;
2552  }
2553  }
2554  else
2555  missed_txs.push_back(tx_hash);
2556  }
2557  catch (const std::exception& e)
2558  {
2559  return false;
2560  }
2561  }
2562  return true;
2563 }
2564 //------------------------------------------------------------------
2565 // Find the split point between us and foreign blockchain and return
2566 // (by reference) the most recent common block hash along with up to
2567 // BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.
2568 bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::vector<crypto::hash>& hashes, uint64_t& start_height, uint64_t& current_height, bool clip_pruned) const
2569 {
2570  LOG_PRINT_L3("Blockchain::" << __func__);
2571  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2572 
2573  // if we can't find the split point, return false
2574  if(!find_blockchain_supplement(qblock_ids, start_height))
2575  {
2576  return false;
2577  }
2578 
2579  db_rtxn_guard rtxn_guard(m_db);
2580  current_height = get_current_blockchain_height();
2581  uint64_t stop_height = current_height;
2582  if (clip_pruned)
2583  {
2584  const uint32_t pruning_seed = get_blockchain_pruning_seed();
2585  start_height = tools::get_next_unpruned_block_height(start_height, current_height, pruning_seed);
2586  stop_height = tools::get_next_pruned_block_height(start_height, current_height, pruning_seed);
2587  }
2588  size_t count = 0;
2589  hashes.reserve(std::min((size_t)(stop_height - start_height), (size_t)BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT));
2590  for(size_t i = start_height; i < stop_height && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++)
2591  {
2592  hashes.push_back(m_db->get_block_hash_from_height(i));
2593  }
2594 
2595  return true;
2596 }
2597 
2598 bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
2599 {
2600  LOG_PRINT_L3("Blockchain::" << __func__);
2601  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2602 
2603  bool result = find_blockchain_supplement(qblock_ids, resp.m_block_ids, resp.start_height, resp.total_height, true);
2604  if (result)
2605  {
2606  cryptonote::difficulty_type wide_cumulative_difficulty = m_db->get_block_cumulative_difficulty(resp.total_height - 1);
2607  resp.cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
2608  resp.cumulative_difficulty_top64 = ((wide_cumulative_difficulty >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
2609  }
2610 
2611  return result;
2612 }
2613 //------------------------------------------------------------------
2614 //FIXME: change argument to std::vector, low priority
2615 // find split point between ours and foreign blockchain (or start at
2616 // blockchain height <req_start_block>), and return up to max_count FULL
2617 // blocks by reference.
2618 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
2619 {
2620  LOG_PRINT_L3("Blockchain::" << __func__);
2621  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2622 
2623  // if a specific start height has been requested
2624  if(req_start_block > 0)
2625  {
2626  // if requested height is higher than our chain, return false -- we can't help
2627  if (req_start_block >= m_db->height())
2628  {
2629  return false;
2630  }
2631  start_height = req_start_block;
2632  }
2633  else
2634  {
2635  if(!find_blockchain_supplement(qblock_ids, start_height))
2636  {
2637  return false;
2638  }
2639  }
2640 
2641  db_rtxn_guard rtxn_guard(m_db);
2642  total_height = get_current_blockchain_height();
2643  size_t count = 0, size = 0;
2644  blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
2645  for(uint64_t i = start_height; i < total_height && count < max_count && (size < FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE || count < 3); i++, count++)
2646  {
2647  blocks.resize(blocks.size()+1);
2648  blocks.back().first.first = m_db->get_block_blob_from_height(i);
2649  block b;
2650  CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first.first, b), false, "internal error, invalid block");
2651  blocks.back().first.second = get_miner_tx_hash ? cryptonote::get_transaction_hash(b.miner_tx) : crypto::null_hash;
2652  std::vector<crypto::hash> mis;
2653  std::vector<cryptonote::blobdata> txs;
2654  get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
2655  CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
2656  size += blocks.back().first.first.size();
2657  for (const auto &t: txs)
2658  size += t.size();
2659 
2660  CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size(), false, "mismatched sizes of b.tx_hashes and txs");
2661  blocks.back().second.reserve(txs.size());
2662  for (size_t i = 0; i < txs.size(); ++i)
2663  {
2664  blocks.back().second.push_back(std::make_pair(b.tx_hashes[i], std::move(txs[i])));
2665  }
2666  }
2667  return true;
2668 }
2669 //------------------------------------------------------------------
2670 bool Blockchain::add_block_as_invalid(const block& bl, const crypto::hash& h)
2671 {
2672  LOG_PRINT_L3("Blockchain::" << __func__);
2673  block_extended_info bei = AUTO_VAL_INIT(bei);
2674  bei.bl = bl;
2675  return add_block_as_invalid(bei, h);
2676 }
2677 //------------------------------------------------------------------
2678 bool Blockchain::add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h)
2679 {
2680  LOG_PRINT_L3("Blockchain::" << __func__);
2681  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2682  auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
2683  CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed");
2684  MINFO("BLOCK ADDED AS INVALID: " << h << std::endl << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size());
2685  return true;
2686 }
2687 //------------------------------------------------------------------
2689 {
2690  LOG_PRINT_L3("Blockchain::" << __func__);
2691  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2692 
2693  if(m_db->block_exists(id))
2694  {
2695  LOG_PRINT_L2("block " << id << " found in main chain");
2696  return true;
2697  }
2698 
2699  if(m_alternative_chains.count(id))
2700  {
2701  LOG_PRINT_L2("block " << id << " found in m_alternative_chains");
2702  return true;
2703  }
2704 
2705  if(m_invalid_blocks.count(id))
2706  {
2707  LOG_PRINT_L2("block " << id << " found in m_invalid_blocks");
2708  return true;
2709  }
2710 
2711  return false;
2712 }
2713 //------------------------------------------------------------------
2714 bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_context& bvc)
2715 {
2716  LOG_PRINT_L3("Blockchain::" << __func__);
2717  crypto::hash id = get_block_hash(bl);
2718  return handle_block_to_main_chain(bl, id, bvc);
2719 }
2720 //------------------------------------------------------------------
2722 {
2723  LOG_PRINT_L3("Blockchain::" << __func__);
2724  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2725  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2726  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2727  // lock if it is otherwise needed.
2728  return m_db->get_tx_count();
2729 }
2730 //------------------------------------------------------------------
2731 // This function checks each input in the transaction <tx> to make sure it
2732 // has not been used already, and adds its key to the container <keys_this_block>.
2733 //
2734 // This container should be managed by the code that validates blocks so we don't
2735 // have to store the used keys in a given block in the permanent storage only to
2736 // remove them later if the block fails validation.
2737 bool Blockchain::check_for_double_spend(const transaction& tx, key_images_container& keys_this_block) const
2738 {
2739  LOG_PRINT_L3("Blockchain::" << __func__);
2740  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2741  struct add_transaction_input_visitor: public boost::static_visitor<bool>
2742  {
2743  key_images_container& m_spent_keys;
2744  BlockchainDB* m_db;
2745  add_transaction_input_visitor(key_images_container& spent_keys, BlockchainDB* db) :
2746  m_spent_keys(spent_keys), m_db(db)
2747  {
2748  }
2749  bool operator()(const txin_to_key& in) const
2750  {
2751  const crypto::key_image& ki = in.k_image;
2752 
2753  // attempt to insert the newly-spent key into the container of
2754  // keys spent this block. If this fails, the key was spent already
2755  // in this block, return false to flag that a double spend was detected.
2756  //
2757  // if the insert into the block-wide spent keys container succeeds,
2758  // check the blockchain-wide spent keys container and make sure the
2759  // key wasn't used in another block already.
2760  auto r = m_spent_keys.insert(ki);
2761  if(!r.second || m_db->has_key_image(ki))
2762  {
2763  //double spend detected
2764  return false;
2765  }
2766 
2767  // if no double-spend detected, return true
2768  return true;
2769  }
2770 
2771  bool operator()(const txin_gen& tx) const
2772  {
2773  return true;
2774  }
2775  bool operator()(const txin_to_script& tx) const
2776  {
2777  return false;
2778  }
2779  bool operator()(const txin_to_scripthash& tx) const
2780  {
2781  return false;
2782  }
2783  bool operator()(const txin_to_key_public& tx) const
2784  {
2785  return false;
2786  }
2787  };
2788 
2789  for (const txin_v& in : tx.vin)
2790  {
2791  if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in))
2792  {
2793  LOG_ERROR("Double spend detected!");
2794  return false;
2795  }
2796  }
2797 
2798  return true;
2799 }
2800 //------------------------------------------------------------------
2801 bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, size_t n_txes, std::vector<std::vector<uint64_t>>& indexs) const
2802 {
2803  LOG_PRINT_L3("Blockchain::" << __func__);
2804  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2805  uint64_t tx_index;
2806  if (!m_db->tx_exists(tx_id, tx_index))
2807  {
2808  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2809  return false;
2810  }
2811 
2812  //no output indexes for tx.version >= 2 (public tx)
2813  if (m_db->get_tx(tx_id).version >= 2)
2814  return true;
2815 
2816  indexs = m_db->get_tx_amount_output_indices(tx_index, n_txes);
2817  CHECK_AND_ASSERT_MES(n_txes == indexs.size(), false, "Wrong indexs size");
2818 
2819  return true;
2820 }
2821 //------------------------------------------------------------------
2822 bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const
2823 {
2824  LOG_PRINT_L3("Blockchain::" << __func__);
2825  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2826  uint64_t tx_index;
2827  if (!m_db->tx_exists(tx_id, tx_index))
2828  {
2829  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2830  return false;
2831  }
2832 
2833  //no output indexes for tx.version >= 2 (public tx)
2834  if (m_db->get_tx(tx_id).version >= 2)
2835  return true;
2836 
2837  std::vector<std::vector<uint64_t>> indices = m_db->get_tx_amount_output_indices(tx_index, 1);
2838  CHECK_AND_ASSERT_MES(indices.size() == 1, false, "Wrong indices size");
2839  indexs = indices.front();
2840  return true;
2841 }
2842 //------------------------------------------------------------------
2844 {
2845 #if defined(PER_BLOCK_CHECKPOINT)
2846  // check if we're doing per-block checkpointing
2847  if (m_db->height() < m_blocks_hash_check.size())
2848  {
2850  m_blocks_txs_check.push_back(get_transaction_hash(tx));
2852  if(m_show_time_stats)
2853  {
2854  size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
2855  MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
2856  }
2857  }
2858 #endif
2859 }
2860 //------------------------------------------------------------------
2861 //FIXME: it seems this function is meant to be merely a wrapper around
2862 // another function of the same name, this one adding one bit of
2863 // functionality. Should probably move anything more than that
2864 // (getting the hash of the block at height max_used_block_id)
2865 // to the other function to keep everything in one place.
2866 // This function overloads its sister function with
2867 // an extra value (hash of highest block that holds an output used as input)
2868 // as a return-by-reference.
2869 bool Blockchain::check_tx_inputs(transaction& tx, uint64_t& max_used_block_height, crypto::hash& max_used_block_id, tx_verification_context &tvc, bool kept_by_block)
2870 {
2871  LOG_PRINT_L3("Blockchain::" << __func__);
2872  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2873 
2874 #if defined(PER_BLOCK_CHECKPOINT)
2875  // check if we're doing per-block checkpointing
2876  if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
2877  {
2878  max_used_block_id = null_hash;
2879  max_used_block_height = 0;
2880  return true;
2881  }
2882 #endif
2883 
2885  bool res = check_tx_inputs(tx, tvc, &max_used_block_height);
2887  if(m_show_time_stats)
2888  {
2889  size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
2890  MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx) << " W: " << get_transaction_weight(tx));
2891  }
2892  if (!res)
2893  return false;
2894 
2895  // If kept_by_block we might witness max_used_block_height > chain height because the tx inputs are referencing outputs at a higher height on the orphaned chain.
2896  CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height());
2897  max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
2898  return true;
2899 }
2900 //------------------------------------------------------------------
2902 {
2903  LOG_PRINT_L3("Blockchain::" << __func__);
2904  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2905 
2906  const uint8_t hf_version = m_hardfork->get_current_version();
2907 
2908  // from hard fork 2, we forbid dust and compound outputs
2909  if (hf_version >= HF_VERSION_FORBID_DUST_OUTPUTS) {
2910  for (auto &o: tx.vout) {
2911  if (!is_valid_decomposed_amount(o.amount)) {
2912  tvc.m_invalid_output = true;
2913  return false;
2914  }
2915  }
2916  }
2917 
2918  // from v4, forbid invalid pubkeys
2919  if (hf_version >= HF_VERSION_FORBID_INVALID_PUBKEYS) {
2920  for (const auto &o: tx.vout) {
2921  if (hf_version < HF_VERSION_PUBLIC_TX) {
2922  if (o.target.type() == typeid(txout_to_key)) {
2923  const txout_to_key &out_to_key = boost::get<txout_to_key>(o.target);
2924  if (!crypto::check_key(out_to_key.key)) {
2925  tvc.m_invalid_output = true;
2926  return false;
2927  }
2928  }
2929  }
2930  else {
2931  //do a sanity check on output type before checking destination
2932  if (o.target.type() != typeid(txout_to_key_public)) {
2933  return false;
2934  }
2935  const txout_to_key_public &out_to_key_public = boost::get<txout_to_key_public>(o.target);
2936  if (!crypto::check_key(out_to_key_public.address.m_spend_public_key) ||
2937  !crypto::check_key(out_to_key_public.address.m_view_public_key)) {
2938  tvc.m_invalid_output = true;
2939  return false;
2940  }
2941 
2942  uint64_t address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
2943  uint64_t integrated_address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
2944  uint64_t subaddress_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
2945 
2946  std::vector<uint64_t> supported_prefixes{address_prefix, integrated_address_prefix, subaddress_prefix};
2947 
2948  if(std::find(supported_prefixes.begin(), supported_prefixes.end(), out_to_key_public.m_address_prefix) == supported_prefixes.end()) {
2949  tvc.m_invalid_output = true;
2950  return false;
2951  }
2952  }
2953  }
2954  }
2955  return true;
2956 }
2957 //------------------------------------------------------------------
2959 {
2960  LOG_PRINT_L3("Blockchain::" << __func__);
2961 
2962  for (const txin_v& in: tx.vin)
2963  {
2964  if(in.type() == typeid(txin_to_key))
2965  {
2966  const auto &in_to_key = boost::get<txin_to_key>(in);
2967  if(have_tx_keyimg_as_spent(in_to_key.k_image))
2968  return true;
2969  }
2970  }
2971 
2972  return false;
2973 }
2974 //------------------------------------------------------------------
2976 {
2977  LOG_PRINT_L3("Blockchain::" << __func__);
2978 
2979  for (const txin_v& in: tx.vin)
2980  {
2981  if(in.type() == typeid(txin_to_key_public))
2982  {
2983  const auto &in_to_key = boost::get<txin_to_key_public>(in);
2984  if(!m_db->check_chainstate_utxo(in_to_key.tx_hash, in_to_key.relative_offset))
2985  return true;
2986  }
2987  }
2988  return false;
2989 }
2990 
2991 //------------------------------------------------------------------
2992 //check for a single output
2994 {
2995  LOG_PRINT_L3("Blockchain::" << __func__);
2996 
2997  if(!m_db->check_chainstate_utxo(public_output.tx_hash, public_output.relative_offset))
2998  return true;
2999 
3000  return false;
3001 }
3002 bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys)
3003 {
3004  return true;
3005 }
3006 //------------------------------------------------------------------
3007 // This function validates transaction inputs and their keys.
3008 // FIXME: consider moving functionality specific to one input into
3009 // check_tx_input() rather than here, and use this function simply
3010 // to iterate the inputs as necessary (splitting the task
3011 // using threads, etc.)
3012 bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, uint64_t* pmax_used_block_height)
3013 {
3015  LOG_PRINT_L3("Blockchain::" << __func__);
3016  size_t sig_index = 0;
3017  if(pmax_used_block_height)
3018  *pmax_used_block_height = 0;
3019 
3020  crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
3021 
3022  const uint8_t hf_version = m_hardfork->get_current_version();
3023 
3024  // min/max tx version based on HF
3025  const size_t max_tx_version = hf_version < HF_VERSION_PUBLIC_TX ? 1 : 3;
3026  if (tx.version > max_tx_version)
3027  {
3028  MERROR_VER("transaction version " << (unsigned)tx.version << " is higher than max accepted version " << max_tx_version);
3029  tvc.m_verification_failed = true;
3030  return false;
3031  }
3032 
3033  const size_t min_tx_version = hf_version >= HF_VERSION_PUBLIC_TX ? 2 : 1;
3034  if (tx.version < min_tx_version)
3035  {
3036  MERROR_VER("transaction version " << (unsigned)tx.version << " is lower than min accepted version " << min_tx_version);
3037  tvc.m_verification_failed = true;
3038  return false;
3039  }
3040 
3041  if (tx.version >= 3) //only public inputs allowed
3042  {
3043 
3044  //check for duplicate inputs
3045  std::unordered_set<std::string> ins;
3046  for(const auto& in: tx.vin)
3047  {
3048  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
3049  if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
3050  {
3051  tvc.m_invalid_input = true;
3052  tvc.m_verification_failed = true;
3053  return false;
3054  }
3055  }
3056 
3057  if(tx.vin.size() != tx.signatures.size())
3058  {
3059  tvc.m_invalid_input = true;
3060  tvc.m_verification_failed = true;
3061  return false;
3062  }
3063 
3064  for (size_t i = 0; i < tx.vin.size(); ++i)
3065  {
3066  CHECK_AND_ASSERT_MES(tx.vin[i].type() == typeid(txin_to_key_public), false, "wrong type id in tx input at Blockchain::check_tx_inputs");
3067 
3068  const txin_to_key_public& in_to_key = boost::get<txin_to_key_public>(tx.vin[i]);
3069 
3070  if (in_to_key.amount <= 0)
3071  {
3072  tvc.m_invalid_input = true;
3073  tvc.m_verification_failed = true;
3074  return false;
3075  }
3076 
3077  transaction parent_tx;
3078  if (!m_db->get_tx(in_to_key.tx_hash, parent_tx))
3079  {
3080  tvc.m_invalid_input = true;
3081  tvc.m_verification_failed = true;
3082  return false;
3083  }
3084 
3085  CHECK_AND_ASSERT_MES(parent_tx.vout.size() > in_to_key.relative_offset, false, "wrong relative_offset in tx input at Blockchain::check_tx_inputs");
3086  CHECK_AND_ASSERT_MES(parent_tx.vout.at(in_to_key.relative_offset).amount == in_to_key.amount, false, "wrong amount in tx input at Blockchain::check_tx_inputs");
3087 
3088  if (!m_db->check_chainstate_utxo(in_to_key.tx_hash, in_to_key.relative_offset))
3089  {
3090  tvc.m_utxo_nonexistent = true;
3091  tvc.m_verification_failed = true;
3092  return false;
3093  }
3094 
3095  if(!is_tx_spendtime_unlocked(m_db->get_utxo_unlock_time(in_to_key.tx_hash, in_to_key.relative_offset))){
3096  tvc.m_verification_failed = true;
3097  return false;
3098  }
3099 
3100  // check signature
3101  const txout_to_key_public& out_to_key = boost::get<txout_to_key_public>(parent_tx.vout[in_to_key.relative_offset].target);
3102  bool valid = crypto::verify_input_signature(tx_prefix_hash, i, out_to_key.address.m_view_public_key, out_to_key.address.m_spend_public_key, tx.signatures[i][0]);
3103  if (!valid)
3104  {
3105  tvc.m_verification_failed = true;
3106  return false;
3107  }
3108  }
3109 
3110  return true; //returns check_tx_inputs. no extra work required for public tx
3111  }
3112 
3113  // from hard fork 2, we require mixin at least 2 unless one output cannot mix with 2 others
3114  // if one output cannot mix with 2 others, we accept at most 1 output that can mix
3115  if (hf_version >= 6)
3116  {
3117  size_t n_unmixable = 0, n_mixable = 0;
3118  size_t mixin = std::numeric_limits<size_t>::max();
3119  const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 0;
3120  for (const auto& txin : tx.vin)
3121  {
3122  // non txin_to_key inputs will be rejected below
3123  if (txin.type() == typeid(txin_to_key))
3124  {
3125  const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3126 
3127  // Ensure Ring Size = 1 from V6
3128  if (hf_version >= HF_VERSION_ENFORCE_0_DECOY_TXS && hf_version < HF_VERSION_ENFORCE_0_DECOY_TXS_END &&
3129  in_to_key.key_offsets.size() != DEFAULT_RINGSIZE)
3130  {
3131  MERROR_VER("Tx " << get_transaction_hash(tx) << " must have a ringsize of (" << (DEFAULT_RINGSIZE)
3132  << "), and more than one mixable input with unmixable inputs");
3133  tvc.m_low_mixin = true;
3134  return false;
3135  }
3136  // End
3137 
3138  if (in_to_key.amount == 0)
3139  {
3140  // always consider rct inputs mixable. Even if there's not enough rct
3141  // inputs on the chain to mix with, this is going to be the case for
3142  // just a few blocks right after the fork at most
3143  ++n_mixable;
3144  }
3145  else
3146  {
3147  uint64_t n_outputs = m_db->get_num_outputs(in_to_key.amount);
3148  MDEBUG("output size " << print_etn(in_to_key.amount) << ": " << n_outputs << " available");
3149  // n_outputs includes the output we're considering
3150  if (n_outputs <= min_mixin)
3151  ++n_unmixable;
3152  else
3153  ++n_mixable;
3154  }
3155  if (in_to_key.key_offsets.size() - 1 < mixin)
3156  mixin = in_to_key.key_offsets.size() - 1;
3157  }
3158  }
3159 
3160  if (((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && mixin != 10) || (hf_version >= HF_VERSION_MIN_MIXIN_10+2 && mixin > 10))
3161  {
3162  MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (mixin + 1) << "), it should be 11");
3163  tvc.m_low_mixin = true;
3164  return false;
3165  }
3166 
3167  if (mixin < min_mixin)
3168  {
3169  if (n_unmixable == 0)
3170  {
3171  MERROR_VER("Tx " << get_transaction_hash(tx) << " has too low ring size (" << (mixin + 1) << "), and no unmixable inputs");
3172  tvc.m_low_mixin = true;
3173  return false;
3174  }
3175  if (n_mixable > 1)
3176  {
3177  MERROR_VER("Tx " << get_transaction_hash(tx) << " has too low ring size (" << (mixin + 1) << "), and more than one mixable input with unmixable inputs");
3178  tvc.m_low_mixin = true;
3179  return false;
3180  }
3181  }
3182  }
3183 
3184  // from v7, sorted ins
3185  if (hf_version >= HF_VERSION_ORDERED_TX_INPUTS) {
3186  const crypto::key_image *last_key_image = NULL;
3187  for (size_t n = 0; n < tx.vin.size(); ++n)
3188  {
3189  const txin_v &txin = tx.vin[n];
3190  if (txin.type() == typeid(txin_to_key))
3191  {
3192  const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3193  if (last_key_image && memcmp(&in_to_key.k_image, last_key_image, sizeof(*last_key_image)) >= 0)
3194  {
3195  MERROR_VER("transaction has unsorted inputs");
3196  tvc.m_verification_failed = true;
3197  return false;
3198  }
3199  last_key_image = &in_to_key.k_image;
3200  }
3201  }
3202  }
3203  auto it = m_check_txin_table.find(tx_prefix_hash);
3204  if(it == m_check_txin_table.end())
3205  {
3206  m_check_txin_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, bool>());
3207  it = m_check_txin_table.find(tx_prefix_hash);
3208  assert(it != m_check_txin_table.end());
3209  }
3210 
3211  std::vector<std::vector<rct::ctkey>> pubkeys(tx.vin.size());
3212  std::vector < uint64_t > results;
3213  results.resize(tx.vin.size(), 0);
3214 
3217  const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(&tpool); });
3218  int threads = tpool.get_max_concurrency();
3219 
3220  for (const auto& txin : tx.vin)
3221  {
3222  // make sure output being spent is of type txin_to_key, rather than
3223  // e.g. txin_gen, which is only used for miner transactions
3224  CHECK_AND_ASSERT_MES(txin.type() == typeid(txin_to_key), false, "wrong type id in tx input at Blockchain::check_tx_inputs");
3225  const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
3226 
3227  // make sure tx output has key offset(s) (is signed to be used)
3228  CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "empty in_to_key.key_offsets in transaction with id " << get_transaction_hash(tx));
3229 
3230  if(have_tx_keyimg_as_spent(in_to_key.k_image))
3231  {
3232  MERROR_VER("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image));
3233  tvc.m_double_spend = true;
3234  return false;
3235  }
3236 
3237  // basically, make sure number of inputs == number of signatures
3238  CHECK_AND_ASSERT_MES(sig_index < tx.signatures.size(), false, "wrong transaction: not signature entry for input with index= " << sig_index);
3239 
3240 #if defined(CACHE_VIN_RESULTS)
3241  auto itk = it->second.find(in_to_key.k_image);
3242  if(itk != it->second.end())
3243  {
3244  if(!itk->second)
3245  {
3246  MERROR_VER("Failed ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
3247  return false;
3248  }
3249 
3250  // txin has been verified already, skip
3251  sig_index++;
3252  continue;
3253  }
3254 #endif
3255 
3256  // make sure that output being spent matches up correctly with the
3257  // signature spending it.
3258  if (!check_tx_input(tx.version, in_to_key, tx_prefix_hash, tx.signatures[sig_index], tx.rct_signatures, pubkeys[sig_index], pmax_used_block_height))
3259  {
3260  it->second[in_to_key.k_image] = false;
3261  MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
3262  if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
3263  {
3264  MERROR_VER(" *pmax_used_block_height: " << *pmax_used_block_height);
3265  }
3266 
3267  return false;
3268  }
3269 
3270  if (threads > 1)
3271  {
3272  // ND: Speedup
3273  // 1. Thread ring signature verification if possible.
3274  tpool.submit(&waiter, boost::bind(&Blockchain::check_ring_signature, this, std::cref(tx_prefix_hash), std::cref(in_to_key.k_image), std::cref(pubkeys[sig_index]), std::cref(tx.signatures[sig_index]), std::ref(results[sig_index])), true);
3275  }
3276  else
3277  {
3278  check_ring_signature(tx_prefix_hash, in_to_key.k_image, pubkeys[sig_index], tx.signatures[sig_index], results[sig_index]);
3279  if (!results[sig_index])
3280  {
3281  it->second[in_to_key.k_image] = false;
3282  MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
3283 
3284  if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
3285  {
3286  MERROR_VER("*pmax_used_block_height: " << *pmax_used_block_height);
3287  }
3288 
3289  return false;
3290  }
3291  it->second[in_to_key.k_image] = true;
3292  }
3293 
3294  sig_index++;
3295  }
3296 
3297  if (threads > 1)
3298  {
3299  waiter.wait(&tpool);
3300  // save results to table, passed or otherwise
3301  bool failed = false;
3302  for (size_t i = 0; i < tx.vin.size(); i++)
3303  {
3304  const txin_to_key& in_to_key = boost::get<txin_to_key>(tx.vin[i]);
3305  it->second[in_to_key.k_image] = results[i];
3306  if(!failed && !results[i])
3307  failed = true;
3308  }
3309 
3310  if (failed)
3311  {
3312  MERROR_VER("Failed to check ring signatures!");
3313  return false;
3314  }
3315  }
3316  return true;
3317 }
3318 
3319 //------------------------------------------------------------------
3320 void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image, const std::vector<rct::ctkey> &pubkeys, const std::vector<crypto::signature>& sig, uint64_t &result)
3321 {
3322  std::vector<const crypto::public_key *> p_output_keys;
3323  p_output_keys.reserve(pubkeys.size());
3324  for (auto &key : pubkeys)
3325  {
3326  // rct::key and crypto::public_key have the same structure, avoid object ctor/memcpy
3327  p_output_keys.push_back(&(const crypto::public_key&)key.dest);
3328  }
3329 
3330  result = crypto::check_ring_signature(tx_prefix_hash, key_image, p_output_keys, sig.data()) ? 1 : 0;
3331 }
3332 
3333 //------------------------------------------------------------------
3335 {
3336  static uint64_t mask = 0;
3337  if (mask == 0)
3338  {
3339  mask = 1;
3341  mask *= 10;
3342  }
3343  return mask;
3344 }
3345 
3346 //------------------------------------------------------------------
3347 uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
3348 {
3349  const uint64_t min_block_weight = get_min_block_weight(version);
3350  if (median_block_weight < min_block_weight)
3351  median_block_weight = min_block_weight;
3352  uint64_t hi, lo;
3353 
3355  {
3356  lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
3357  div128_32(hi, lo, min_block_weight, &hi, &lo);
3358  div128_32(hi, lo, median_block_weight, &hi, &lo);
3359  assert(hi == 0);
3360  lo /= 5;
3361  return lo;
3362  }
3363 
3365 
3366  uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
3367  lo = mul128(unscaled_fee_base, block_reward, &hi);
3368  static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
3369  static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large");
3370 
3371  // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
3372  div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
3373  div128_32(hi, lo, 1000000, &hi, &lo);
3374  assert(hi == 0);
3375 
3376  // quantize fee up to 8 decimals
3378  uint64_t qlo = (lo + mask - 1) / mask * mask;
3379  MDEBUG("lo " << print_etn(lo) << ", qlo " << print_etn(qlo) << ", mask " << mask);
3380 
3381  return qlo;
3382 }
3383 
3384 //------------------------------------------------------------------
3385 bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
3386 {
3388  const uint64_t blockchain_height = m_db->height();
3389 
3390  uint64_t median = 0;
3391  uint64_t already_generated_coins = 0;
3392  uint64_t base_reward = 0;
3394  {
3395  median = m_current_block_cumul_weight_limit / 2;
3396  const uint64_t blockchain_height = m_db->height();
3397  already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3398  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, blockchain_height, get_nettype()))
3399  return false;
3400  }
3401 
3402  uint64_t needed_fee;
3404  {
3405  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3406  uint64_t fee_per_byte = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
3407  MDEBUG("Using " << print_etn(fee_per_byte) << "/byte fee");
3408  needed_fee = tx_weight * fee_per_byte;
3409  // quantize fee up to 8 decimals
3410  const uint64_t mask = get_fee_quantization_mask();
3411  needed_fee = (needed_fee + mask - 1) / mask * mask;
3412  }
3413  else
3414  {
3415  uint64_t fee_per_kb;
3417  {
3418  if (version >= 11) {
3419  fee_per_kb = FEE_PER_KB_V11;
3420  } else if (version < 11 && version >= 6) {
3421  fee_per_kb = FEE_PER_KB_V6;
3422  } else {
3423  fee_per_kb = FEE_PER_KB;
3424  }
3425  }
3426  else
3427  {
3428  fee_per_kb = get_dynamic_base_fee(base_reward, median, version);
3429  }
3430  MDEBUG("Using " << print_etn(fee_per_kb) << "/kB fee");
3431 
3432  needed_fee = tx_weight / 1024;
3433  needed_fee += (tx_weight % 1024) ? 1 : 0;
3434  needed_fee *= fee_per_kb;
3435  }
3436 
3437  if (fee < needed_fee - needed_fee / 50) // keep a little 2% buffer on acceptance - no integer overflow
3438  {
3439  MERROR_VER("transaction fee is not enough: " << print_etn(fee) << ", minimum fee: " << print_etn(needed_fee));
3440  return false;
3441  }
3442  return true;
3443 }
3444 
3445 //------------------------------------------------------------------
3447 {
3449  const uint64_t db_height = m_db->height();
3450 
3452  if (version >= 11) {
3453  return FEE_PER_KB_V11;
3454  } else if (version < 11 && version >= 6) {
3455  return FEE_PER_KB_V6;
3456  } else {
3457  return FEE_PER_KB;
3458  }
3459  }
3460 
3461  if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
3462  grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;
3463 
3464  const uint64_t min_block_weight = get_min_block_weight(version);
3465  std::vector<uint64_t> weights;
3466  get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
3467  weights.reserve(grace_blocks);
3468  for (size_t i = 0; i < grace_blocks; ++i)
3469  weights.push_back(min_block_weight);
3470 
3472  if(median <= min_block_weight)
3473  median = min_block_weight;
3474 
3475  uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0;
3476  uint64_t base_reward;
3477  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, get_current_blockchain_height(), get_nettype()))
3478  {
3479  MERROR("Failed to determine block reward, using placeholder " << print_etn(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
3480  base_reward = BLOCK_REWARD_OVERESTIMATE;
3481  }
3482 
3483  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3484  uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
3485  const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
3486  MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_etn(fee) << "/" << (per_byte ? "byte" : "kB"));
3487  return fee;
3488 }
3489 
3490 //------------------------------------------------------------------
3491 // This function checks to see if a tx is unlocked. unlock_time is either
3492 // a block index or a unix time.
3493 bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
3494 {
3495  LOG_PRINT_L3("Blockchain::" << __func__);
3496  if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
3497  {
3498  // ND: Instead of calling get_current_blockchain_height(), call m_db->height()
3499  // directly as get_current_blockchain_height() locks the recursive mutex.
3500  if(m_db->height()-1 + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
3501  return true;
3502  else
3503  return false;
3504  }
3505  else
3506  {
3507  //interpret as time
3508  uint64_t current_time = static_cast<uint64_t>(time(NULL));
3509  if(current_time + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS >= unlock_time)
3510  return true;
3511  else
3512  return false;
3513  }
3514  return false;
3515 }
3516 //------------------------------------------------------------------
3517 // This function locates all outputs associated with a given input (mixins)
3518 // and validates that they exist and are usable. It also checks the ring
3519 // signature for each input.
3520 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)
3521 {
3522  LOG_PRINT_L3("Blockchain::" << __func__);
3523 
3524  // ND:
3525  // 1. Disable locking and make method private.
3526  //CRITICAL_REGION_LOCAL(m_blockchain_lock);
3527 
3528  struct outputs_visitor
3529  {
3530  std::vector<rct::ctkey >& m_output_keys;
3531  const Blockchain& m_bch;
3532  outputs_visitor(std::vector<rct::ctkey>& output_keys, const Blockchain& bch) :
3533  m_output_keys(output_keys), m_bch(bch)
3534  {
3535  }
3536  bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey, const rct::key &commitment)
3537  {
3538  //check tx unlock time
3539  if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
3540  {
3541  MERROR_VER("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
3542  return false;
3543  }
3544 
3545  // The original code includes a check for the output corresponding to this input
3546  // to be a txout_to_key. This is removed, as the database does not store this info,
3547  // but only txout_to_key outputs are stored in the DB in the first place, done in
3548  // Blockchain*::add_output
3549 
3550  m_output_keys.push_back(rct::ctkey({rct::pk2rct(pubkey), commitment}));
3551  return true;
3552  }
3553  };
3554 
3555  output_keys.clear();
3556 
3557  // collect output keys
3558  outputs_visitor vi(output_keys, *this);
3559  if (!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height))
3560  {
3561  MERROR_VER("Failed to get output keys for tx with amount = " << print_etn(txin.amount) << " and count indexes " << txin.key_offsets.size());
3562  return false;
3563  }
3564 
3565  if(txin.key_offsets.size() != output_keys.size())
3566  {
3567  MERROR_VER("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size());
3568  return false;
3569  }
3570  if (tx_version == 1) {
3571  CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(), false, "internal error: tx signatures count=" << sig.size() << " mismatch with outputs keys count for inputs=" << output_keys.size());
3572  }
3573  // rct_signatures will be expanded after this
3574  return true;
3575 }
3576 //------------------------------------------------------------------
3577 //TODO: Is this intended to do something else? Need to look into the todo there.
3578 uint64_t Blockchain::get_adjusted_time() const
3579 {
3580  LOG_PRINT_L3("Blockchain::" << __func__);
3581  //TODO: add collecting median time
3582  return time(NULL);
3583 }
3584 //------------------------------------------------------------------
3585 //TODO: revisit, has changed a bit on upstream
3586 bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const
3587 {
3588  LOG_PRINT_L3("Blockchain::" << __func__);
3589  median_ts = epee::misc_utils::median(timestamps);
3590 
3591  if(b.timestamp < median_ts)
3592  {
3593  MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
3594  return false;
3595  }
3596 
3597  return true;
3598 }
3599 //------------------------------------------------------------------
3600 // This function grabs the timestamps from the most recent <n> blocks,
3601 // where n = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW. If there are not those many
3602 // blocks in the blockchain, the timestap is assumed to be valid. If there
3603 // are, this function returns:
3604 // true if the block's timestamp is not less than the timestamp of the
3605 // median of the selected blocks
3606 // false otherwise
3607 bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const
3608 {
3609  LOG_PRINT_L3("Blockchain::" << __func__);
3610  if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT)
3611  {
3612  MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
3613  return false;
3614  }
3615 
3616  const auto h = m_db->height();
3617 
3618  // if not enough blocks, no proper median yet, return true
3620  {
3621  return true;
3622  }
3623 
3624  std::vector<uint64_t> timestamps;
3625 
3626  // need most recent 60 blocks, get index of first of those
3627  size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
3628  timestamps.reserve(h - offset);
3629  for(;offset < h; ++offset)
3630  {
3631  timestamps.push_back(m_db->get_block_timestamp(offset));
3632  }
3633 
3634  return check_block_timestamp(timestamps, b, median_ts);
3635 }
3636 //------------------------------------------------------------------
3637 void Blockchain::return_tx_to_pool(std::vector<std::pair<transaction, blobdata>> &txs)
3638 {
3640  for (auto& tx : txs)
3641  {
3643  // We assume that if they were in a block, the transactions are already
3644  // known to the network as a whole. However, if we had mined that block,
3645  // that might not be always true. Unlikely though, and always relaying
3646  // these again might cause a spike of traffic as many nodes re-relay
3647  // all the transactions in a popped block when a reorg happens.
3648  const size_t weight = get_transaction_weight(tx.first, tx.second.size());
3649  const crypto::hash tx_hash = get_transaction_hash(tx.first);
3650  if (!m_tx_pool.add_tx(tx.first, tx_hash, tx.second, weight, tvc, true, true, false, version))
3651  {
3652  MERROR("Failed to return taken transaction with hash: " << get_transaction_hash(tx.first) << " to tx_pool");
3653  }
3654  }
3655 }
3656 //------------------------------------------------------------------
3657 bool Blockchain::flush_txes_from_pool(const std::vector<crypto::hash> &txids)
3658 {
3659  CRITICAL_REGION_LOCAL(m_tx_pool);
3660 
3661  bool res = true;
3662  for (const auto &txid: txids)
3663  {
3665  cryptonote::blobdata txblob;
3666  size_t tx_weight;
3667  uint64_t fee;
3668  bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
3669  MINFO("Removing txid " << txid << " from the pool");
3670  if(m_tx_pool.have_tx(txid) && !m_tx_pool.take_tx(txid, tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3671  {
3672  MERROR("Failed to remove txid " << txid << " from the pool");
3673  res = false;
3674  }
3675  }
3676  return res;
3677 }
3678 //------------------------------------------------------------------
3679 // Needs to validate the block and acquire each transaction from the
3680 // transaction mem_pool, then pass the block and transactions to
3681 // m_db->add_block()
3682 bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc)
3683 {
3684  LOG_PRINT_L3("Blockchain::" << __func__);
3685 
3686  TIME_MEASURE_START(block_processing_time);
3687  CRITICAL_REGION_LOCAL(m_blockchain_lock);
3689 
3690  static bool seen_future_version = false;
3691 
3692  db_rtxn_guard rtxn_guard(m_db);
3693  uint64_t blockchain_height;
3694  const crypto::hash top_hash = get_tail_id(blockchain_height);
3695  ++blockchain_height; // block height to chain height
3696  if(bl.prev_id != top_hash)
3697  {
3698  MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << top_hash);
3699  bvc.m_verification_failed = true;
3700 leave:
3701  return false;
3702  }
3703 
3704  if(bl.major_version >= 8 && m_nettype != FAKECHAIN) {
3705 
3706  if(!m_fallback_to_pow) {
3707 
3708  if(!m_validators->isEnabled()) {
3709  m_validators->enable();
3710  }
3711 
3712  if(!m_validators->isValid()) {
3713  bvc.m_validator_list_update_failed = true;
3714  goto leave;
3715  }
3716 
3717  if(!verify_block_signature(bl) && !m_ignore_bsig) {
3718  MERROR_VER("Block with id: " << id << std::endl << " has wrong digital signature");
3719  bvc.m_verification_failed = true;
3720  goto leave;
3721  }
3722  if(bl.signatory == m_db->get_block(bl.prev_id).signatory && !m_ignore_bsig){
3723  MERROR_VER("Block with id: " << id << std::endl << " has the same signatory as the previous block, which is not allowed");
3724  bvc.m_verification_failed = true;
3725  bvc.m_sequential_block = true;
3726  goto leave;
3727  }
3728  }
3729  }
3730 
3731  // warn users if they're running an old version
3732  if (!seen_future_version && bl.major_version > m_hardfork->get_ideal_version())
3733  {
3734  seen_future_version = true;
3735  const el::Level level = el::Level::Warning;
3736  MCLOG_RED(level, "global", "**********************************************************************");
3737  MCLOG_RED(level, "global", "A block was seen on the network with a version higher than the last");
3738  MCLOG_RED(level, "global", "known one. This may be an old version of the daemon, and a software");
3739  MCLOG_RED(level, "global", "update may be required to sync further. Try running: update check");
3740  MCLOG_RED(level, "global", "**********************************************************************");
3741  }
3742 
3743  // this is a cheap test
3744  if (!m_hardfork->check(bl))
3745  {
3746  MERROR_VER("Block with id: " << id << std::endl << "has old version: " << (unsigned)bl.major_version << std::endl << "current: " << (unsigned)m_hardfork->get_current_version());
3747  bvc.m_verification_failed = true;
3748  goto leave;
3749  }
3750 
3753 
3754  // make sure block timestamp is not less than the median timestamp
3755  // of a set number of the most recent blocks.
3756  if(!check_block_timestamp(bl))
3757  {
3758  MERROR_VER("Block with id: " << id << std::endl << "has invalid timestamp: " << bl.timestamp);
3759  bvc.m_verification_failed = true;
3760  goto leave;
3761  }
3762 
3764  //check proof of work
3765  TIME_MEASURE_START(target_calculating_time);
3766 
3767  // get the target difficulty for the block.
3768  // the calculation can overflow, among other failure cases,
3769  // so we need to check the return type.
3770  // FIXME: get_difficulty_for_next_block can also assert, look into
3771  // changing this to throwing exceptions instead so we can clean up.
3773  CHECK_AND_ASSERT_MES(current_diffic, false, "!!!!!!!!! difficulty overhead !!!!!!!!!");
3774 
3775  TIME_MEASURE_FINISH(target_calculating_time);
3776 
3777  TIME_MEASURE_START(longhash_calculating_time);
3778 
3779  crypto::hash proof_of_work = null_hash;
3780 
3781  // Formerly the code below contained an if loop with the following condition
3782  // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
3783  // however, this caused the daemon to not bother checking PoW for blocks
3784  // before checkpoints, which is very dangerous behaviour. We moved the PoW
3785  // validation out of the next chunk of code to make sure that we correctly
3786  // check PoW now.
3787  // FIXME: height parameter is not used...should it be used or should it not
3788  // be a parameter?
3789  // validate proof_of_work versus difficulty target
3790  bool precomputed = false;
3791  bool fast_check = false;
3792 #if defined(PER_BLOCK_CHECKPOINT)
3793  if (blockchain_height < m_blocks_hash_check.size())
3794  {
3795  auto hash = get_block_hash(bl);
3796  if (memcmp(&hash, &m_blocks_hash_check[m_db->height()], sizeof(hash)) != 0)
3797  {
3798  MERROR_VER("Block with id is INVALID: " << id);
3799  bvc.m_verification_failed = true;
3800  goto leave;
3801  }
3802 
3803  fast_check = true;
3804  }
3805  else
3806 #endif
3807  {
3808  auto it = m_blocks_longhash_table.find(id);
3809  if (it != m_blocks_longhash_table.end())
3810  {
3811  precomputed = true;
3812  proof_of_work = it->second;
3813  }
3814  else
3815  proof_of_work = get_block_longhash(bl, blockchain_height);
3816 
3817  // validate proof_of_work versus difficulty target
3818  if(!check_hash(proof_of_work, current_diffic))
3819  {
3820  MERROR_VER("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << " at height " << blockchain_height << ", unexpected difficulty: " << current_diffic);
3821  bvc.m_verification_failed = true;
3822  goto leave;
3823  }
3824  }
3825 
3826  // If we're at a checkpoint, ensure that our hardcoded checkpoint hash
3827  // is correct.
3828  if(m_checkpoints.is_in_checkpoint_zone(blockchain_height))
3829  {
3830  if(!m_checkpoints.check_block(blockchain_height, id))
3831  {
3832  LOG_ERROR("CHECKPOINT VALIDATION FAILED");
3833  bvc.m_verification_failed = true;
3834  goto leave;
3835  }
3836  }
3837 
3838  TIME_MEASURE_FINISH(longhash_calculating_time);
3839  if (precomputed)
3840  longhash_calculating_time += m_fake_pow_calc_time;
3841 
3843 
3844  // sanity check basic miner tx properties;
3845  if(!prevalidate_miner_transaction(bl, blockchain_height))
3846  {
3847  MERROR_VER("Block with id: " << id << " failed to pass prevalidation");
3848  bvc.m_verification_failed = true;
3849  goto leave;
3850  }
3851 
3852  size_t coinbase_weight = get_transaction_weight(bl.miner_tx);
3853  size_t cumulative_block_weight = coinbase_weight;
3854 
3855  std::vector<std::pair<transaction, blobdata>> txs;
3856  key_images_container keys;
3857 
3858  uint64_t fee_summary = 0;
3859  uint64_t t_checktx = 0;
3860  uint64_t t_exists = 0;
3861  uint64_t t_pool = 0;
3862  uint64_t t_dblspnd = 0;
3864 
3865 // XXX old code adds miner tx here
3866 
3867  size_t tx_index = 0;
3868  // Iterate over the block's transaction hashes, grabbing each
3869  // from the tx_pool and validating them. Each is then added
3870  // to txs. Keys spent in each are added to <keys> by the double spend check.
3871  txs.reserve(bl.tx_hashes.size());
3872  for (const crypto::hash& tx_id : bl.tx_hashes)
3873  {
3874  transaction tx_tmp;
3875  blobdata txblob;
3876  size_t tx_weight = 0;
3877  uint64_t fee = 0;
3878  bool relayed = false, do_not_relay = false, double_spend_seen = false, nonexistent_utxo_seen = false;
3879  TIME_MEASURE_START(aa);
3880 
3881 // XXX old code does not check whether tx exists
3882  if (m_db->tx_exists(tx_id))
3883  {
3884  MERROR("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id);
3885  bvc.m_verification_failed = true;
3886  return_tx_to_pool(txs);
3887  goto leave;
3888  }
3889 
3890  TIME_MEASURE_FINISH(aa);
3891  t_exists += aa;
3892  TIME_MEASURE_START(bb);
3893 
3894  // get transaction with hash <tx_id> from tx_pool
3895  if(!m_tx_pool.take_tx(tx_id, tx_tmp, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3896  {
3897  MERROR_VER("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
3898  bvc.m_verification_failed = true;
3899  return_tx_to_pool(txs);
3900  goto leave;
3901  }
3902 
3903  TIME_MEASURE_FINISH(bb);
3904  t_pool += bb;
3905  // add the transaction to the temp list of transactions, so we can either
3906  // store the list of transactions all at once or return the ones we've
3907  // taken from the tx_pool back to it if the block fails verification.
3908  txs.push_back(std::make_pair(std::move(tx_tmp), std::move(txblob)));
3909  transaction &tx = txs.back().first;
3910  TIME_MEASURE_START(dd);
3911 
3912  // FIXME: the storage should not be responsible for validation.
3913  // If it does any, it is merely a sanity check.
3914  // Validation is the purview of the Blockchain class
3915  // - TW
3916  //
3917  // ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly.
3918  // if (!check_for_double_spend(tx, keys))
3919  // {
3920  // LOG_PRINT_L0("Double spend detected in transaction (id: " << tx_id);
3921  // bvc.m_verification_failed = true;
3922  // break;
3923  // }
3924 
3925  TIME_MEASURE_FINISH(dd);
3926  t_dblspnd += dd;
3927  TIME_MEASURE_START(cc);
3928 
3929 #if defined(PER_BLOCK_CHECKPOINT)
3930  if (!fast_check)
3931 #endif
3932  {
3933  // validate that transaction inputs and the keys spending them are correct.
3935  if(!check_tx_inputs(tx, tvc))
3936  {
3937  MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
3938 
3939  //TODO: why is this done? make sure that keeping invalid blocks makes sense.
3940  add_block_as_invalid(bl, id);
3941  MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions");
3942  MERROR_VER("tx_index " << tx_index << ", m_blocks_txs_check " << m_blocks_txs_check.size() << ":");
3943  for (const auto &h: m_blocks_txs_check) MERROR_VER(" " << h);
3944  bvc.m_verification_failed = true;
3945  return_tx_to_pool(txs);
3946  goto leave;
3947  }
3948  }
3949 #if defined(PER_BLOCK_CHECKPOINT)
3950  else
3951  {
3952  // ND: if fast_check is enabled for blocks, there is no need to check
3953  // the transaction inputs, but do some sanity checks anyway.
3954  if (tx_index >= m_blocks_txs_check.size() || memcmp(&m_blocks_txs_check[tx_index++], &tx_id, sizeof(tx_id)) != 0)
3955  {
3956  MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
3957  //TODO: why is this done? make sure that keeping invalid blocks makes sense.
3958  add_block_as_invalid(bl, id);
3959  MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions");
3960  bvc.m_verification_failed = true;
3961  return_tx_to_pool(txs);
3962  goto leave;
3963  }
3964  }
3965 #endif
3966  TIME_MEASURE_FINISH(cc);
3967  t_checktx += cc;
3968  fee_summary += fee;
3969  cumulative_block_weight += tx_weight;
3970  }
3971 
3972  m_blocks_txs_check.clear();
3973 
3974  TIME_MEASURE_START(vmt);
3975  uint64_t base_reward = 0;
3976  uint64_t already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3977  if(!validate_miner_transaction(bl, cumulative_block_weight, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward, m_hardfork->get_current_version()))
3978  {
3979  MERROR_VER("Block with id: " << id << " has incorrect miner transaction");
3980  bvc.m_verification_failed = true;
3981  return_tx_to_pool(txs);
3982  goto leave;
3983  }
3984 
3985  TIME_MEASURE_FINISH(vmt);
3986  size_t block_weight;
3987  difficulty_type cumulative_difficulty;
3988 
3989  // populate various metadata about the block to be stored alongside it.
3990  block_weight = cumulative_block_weight;
3991  cumulative_difficulty = current_diffic;
3992  // In the "tail" state when the minimum subsidy (implemented in get_block_reward) is in effect, the number of
3993  // coins will eventually exceed ETN_SUPPLY and overflow a uint64. To prevent overflow, cap already_generated_coins
3994  // at ETN_SUPPLY. already_generated_coins is only used to compute the block subsidy and ETN_SUPPLY yields a
3995  // subsidy of 0 under the base formula and therefore the minimum subsidy >0 in the tail state.
3996  already_generated_coins = base_reward < (ETN_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward : ETN_SUPPLY;
3997  if(blockchain_height)
3998  cumulative_difficulty += m_db->get_block_cumulative_difficulty(blockchain_height - 1);
3999 
4000  TIME_MEASURE_FINISH(block_processing_time);
4001  if(precomputed)
4002  block_processing_time += m_fake_pow_calc_time;
4003 
4004  rtxn_guard.stop();
4005  TIME_MEASURE_START(addblock);
4006  uint64_t new_height = 0;
4007  if (!bvc.m_verification_failed)
4008  {
4009  try
4010  {
4011  uint64_t long_term_block_weight = get_next_long_term_block_weight(block_weight);
4013  new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs);
4014  }
4015  catch (const KEY_IMAGE_EXISTS& e)
4016  {
4017  LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
4018  m_batch_success = false;
4019  bvc.m_verification_failed = true;
4020  return_tx_to_pool(txs);
4021  return false;
4022  }
4023  catch (const std::exception& e)
4024  {
4025  //TODO: figure out the best way to deal with this failure
4026  LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
4027  m_batch_success = false;
4028  bvc.m_verification_failed = true;
4029  return_tx_to_pool(txs);
4030  return false;
4031  }
4032  }
4033  else
4034  {
4035  LOG_ERROR("Blocks that failed verification should not reach here");
4036  }
4037 
4038  TIME_MEASURE_FINISH(addblock);
4039 
4040  // do this after updating the hard fork state since the weight limit may change due to fork
4041  if (!update_next_cumulative_weight_limit())
4042  {
4043  MERROR("Failed to update next cumulative weight limit");
4044  pop_block_from_blockchain();
4045  return false;
4046  }
4047 
4048  MINFO("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_etn(fee_summary + base_reward) << "(" << print_etn(base_reward) << " + " << print_etn(fee_summary) << "), coinbase_weight: " << coinbase_weight << ", cumulative weight: " << cumulative_block_weight << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
4049  if(m_show_time_stats)
4050  {
4051  MINFO("Height: " << new_height << " coinbase weight: " << coinbase_weight << " cumm: "
4052  << cumulative_block_weight << " p/t: " << block_processing_time << " ("
4053  << target_calculating_time << "/" << longhash_calculating_time << "/"
4054  << t1 << "/" << t2 << "/" << t3 << "/" << t_exists << "/" << t_pool
4055  << "/" << t_checktx << "/" << t_dblspnd << "/" << vmt << "/" << addblock << ")ms");
4056  }
4057 
4058  bvc.m_added_to_main_chain = true;
4059  ++m_sync_counter;
4060 
4061  // appears to be a NOP *and* is called elsewhere. wat?
4062  m_tx_pool.on_blockchain_inc(new_height, id);
4063  get_difficulty_for_next_block(); // just to cache it
4064  invalidate_block_template_cache();
4065 
4066  std::shared_ptr<tools::Notify> block_notify = m_block_notify;
4067  if (block_notify)
4068  block_notify->notify("%s", epee::string_tools::pod_to_hex(id).c_str(), NULL);
4069 
4070  return true;
4071 }
4072 //------------------------------------------------------------------
4074 {
4075  m_tx_pool.lock();
4077  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4078 
4079  return m_db->prune_blockchain(pruning_seed);
4080 }
4081 //------------------------------------------------------------------
4083 {
4084  m_tx_pool.lock();
4086  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4087 
4088  return m_db->update_pruning();
4089 }
4090 //------------------------------------------------------------------
4092 {
4093  m_tx_pool.lock();
4095  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4096 
4097  return m_db->check_pruning();
4098 }
4099 //------------------------------------------------------------------
4101 {
4103 
4104  const uint64_t db_height = m_db->height();
4105  const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4106 
4107  const uint8_t hf_version = get_current_hard_fork_version();
4108  if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
4109  return block_weight;
4110 
4111  uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
4112  uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
4113 
4114  uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
4115  uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4116 
4117  return long_term_block_weight;
4118 }
4119 //------------------------------------------------------------------
4120 bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effective_median_block_weight)
4121 {
4122  PERF_TIMER(update_next_cumulative_weight_limit);
4123 
4124  LOG_PRINT_L3("Blockchain::" << __func__);
4125 
4126  // when we reach this, the last hf version is not yet written to the db
4127  const uint64_t db_height = m_db->height();
4128  const uint8_t hf_version = get_current_hard_fork_version();
4129  uint64_t full_reward_zone = get_min_block_weight(hf_version);
4130  uint64_t long_term_block_weight;
4131 
4132  if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
4133  {
4134  std::vector<uint64_t> weights;
4135  get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
4136  m_current_block_cumul_weight_median = epee::misc_utils::median(weights);
4137  long_term_block_weight = weights.back();
4138  }
4139  else
4140  {
4141  const uint64_t block_weight = m_db->get_block_weight(db_height - 1);
4142 
4143  uint64_t long_term_median;
4144  if (db_height == 1)
4145  {
4147  }
4148  else
4149  {
4150  uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4151  if (nblocks == db_height)
4152  --nblocks;
4153  long_term_median = get_long_term_block_weight_median(db_height - nblocks - 1, nblocks);
4154  }
4155 
4156  m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
4157 
4158  uint64_t short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5;
4159  long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4160 
4161  if (db_height == 1)
4162  {
4163  long_term_median = long_term_block_weight;
4164  }
4165  else
4166  {
4167  m_long_term_block_weights_cache_tip_hash = m_db->get_block_hash_from_height(db_height - 1);
4168  m_long_term_block_weights_cache_rolling_median.insert(long_term_block_weight);
4169  long_term_median = m_long_term_block_weights_cache_rolling_median.median();
4170  }
4171  m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
4172 
4173  std::vector<uint64_t> weights;
4174  get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
4175 
4176  uint64_t short_term_median = epee::misc_utils::median(weights);
4177  uint64_t effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight);
4178 
4179  m_current_block_cumul_weight_median = effective_median_block_weight;
4180  }
4181 
4182  if (m_current_block_cumul_weight_median <= full_reward_zone)
4183  m_current_block_cumul_weight_median = full_reward_zone;
4184 
4185  m_current_block_cumul_weight_limit = m_current_block_cumul_weight_median * 2;
4186 
4187  if (long_term_effective_median_block_weight)
4188  *long_term_effective_median_block_weight = m_long_term_effective_median_block_weight;
4189 
4190  if (!m_db->is_read_only())
4191  m_db->add_max_block_size(m_current_block_cumul_weight_limit);
4192 
4193  return true;
4194 }
4195 //------------------------------------------------------------------
4197 {
4198  LOG_PRINT_L3("Blockchain::" << __func__);
4199  crypto::hash id = get_block_hash(bl);
4200  CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
4201  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4202  db_rtxn_guard rtxn_guard(m_db);
4203  if(have_block(id))
4204  {
4205  LOG_PRINT_L3("block with id = " << id << " already exists");
4206  bvc.m_already_exists = true;
4207  m_blocks_txs_check.clear();
4208  return false;
4209  }
4210 
4211  //check that block refers to chain tail
4212  if(!(bl.prev_id == get_tail_id()))
4213  {
4214  //chain switching or wrong block
4215  bvc.m_added_to_main_chain = false;
4216  rtxn_guard.stop();
4217  bool r = handle_alternative_block(bl, id, bvc);
4218  m_blocks_txs_check.clear();
4219  return r;
4220  //never relay alternative blocks
4221  }
4222 
4223  rtxn_guard.stop();
4224  return handle_block_to_main_chain(bl, id, bvc);
4225 }
4226 //------------------------------------------------------------------
4227 //TODO: Refactor, consider returning a failure height and letting
4228 // caller decide course of action.
4229 void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce)
4230 {
4231  const auto& pts = points.get_points();
4232  bool stop_batch;
4233 
4234  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4235  stop_batch = m_db->batch_start();
4236  const uint64_t blockchain_height = m_db->height();
4237  for (const auto& pt : pts)
4238  {
4239  // if the checkpoint is for a block we don't have yet, move on
4240  if (pt.first >= blockchain_height)
4241  {
4242  continue;
4243  }
4244 
4245  if (!points.check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
4246  {
4247  // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
4248  if (enforce)
4249  {
4250  LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
4251  std::list<block> empty;
4252  rollback_blockchain_switching(empty, pt.first - 2);
4253 
4254  //Flush the txpool if we've just popped blocks due to failed checkpoint.
4255  std::vector<crypto::hash> txs;
4256  m_tx_pool.get_transaction_hashes(txs, true);
4257  flush_txes_from_pool(txs);
4258  }
4259  else
4260  {
4261  LOG_ERROR("WARNING: local blockchain failed to pass a ElectroneumPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
4262  }
4263  }
4264  }
4265  if (stop_batch)
4266  m_db->batch_stop();
4267 }
4268 //------------------------------------------------------------------
4269 // returns false if any of the checkpoints loading returns false.
4270 // That should happen only if a checkpoint is added that conflicts
4271 // with an existing checkpoint.
4272 bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns)
4273 {
4274  if (!m_checkpoints.load_checkpoints_from_json(file_path))
4275  {
4276  return false;
4277  }
4278 
4279  // if we're checking both dns and json, load checkpoints from dns.
4280  // if we're not hard-enforcing dns checkpoints, handle accordingly
4281  if (m_enforce_dns_checkpoints && check_dns && !m_offline)
4282  {
4283  if (!m_checkpoints.load_checkpoints_from_dns())
4284  {
4285  return false;
4286  }
4287  }
4288  else if (check_dns && !m_offline)
4289  {
4290  checkpoints dns_points;
4291  dns_points.load_checkpoints_from_dns();
4292  if (m_checkpoints.check_for_conflicts(dns_points))
4293  {
4294  check_against_checkpoints(dns_points, false);
4295  }
4296  else
4297  {
4298  MERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
4299  }
4300  }
4301 
4302  check_against_checkpoints(m_checkpoints, true);
4303 
4304  return true;
4305 }
4306 //------------------------------------------------------------------
4307 void Blockchain::set_enforce_dns_checkpoints(bool enforce_checkpoints)
4308 {
4309  m_enforce_dns_checkpoints = enforce_checkpoints;
4310 }
4311 
4312 //------------------------------------------------------------------
4313 void Blockchain::block_longhash_worker(uint64_t height, const epee::span<const block> &blocks, std::unordered_map<crypto::hash, crypto::hash> &map) const
4314 {
4315  TIME_MEASURE_START(t);
4317 
4318  for (const auto & block : blocks)
4319  {
4320  if (m_cancel)
4321  break;
4324  map.emplace(id, pow);
4325  }
4326 
4329 }
4330 
4331 //------------------------------------------------------------------
4333 {
4334  bool success = false;
4335 
4336  MTRACE("Blockchain::" << __func__);
4337  CRITICAL_REGION_BEGIN(m_blockchain_lock);
4339 
4340  try
4341  {
4342  if (m_batch_success)
4343  m_db->batch_stop();
4344  else
4345  m_db->batch_abort();
4346  success = true;
4347  }
4348  catch (const std::exception &e)
4349  {
4350  MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what());
4351  }
4352 
4353  if (success && m_sync_counter > 0)
4354  {
4355  if (force_sync)
4356  {
4357  if(m_db_sync_mode != db_nosync)
4358  store_blockchain();
4359  m_sync_counter = 0;
4360  }
4361  else if (m_db_sync_threshold && ((m_db_sync_on_blocks && m_sync_counter >= m_db_sync_threshold) || (!m_db_sync_on_blocks && m_bytes_to_sync >= m_db_sync_threshold)))
4362  {
4363  MDEBUG("Sync threshold met, syncing");
4364  if(m_db_sync_mode == db_async)
4365  {
4366  m_sync_counter = 0;
4367  m_bytes_to_sync = 0;
4368  m_async_service.dispatch(boost::bind(&Blockchain::store_blockchain, this));
4369  }
4370  else if(m_db_sync_mode == db_sync)
4371  {
4372  store_blockchain();
4373  }
4374  else // db_nosync
4375  {
4376  // DO NOTHING, not required to call sync.
4377  }
4378  }
4379  }
4380 
4382  m_blocks_longhash_table.clear();
4383  m_scan_table.clear();
4384  m_blocks_txs_check.clear();
4385  m_check_txin_table.clear();
4386 
4388  m_tx_pool.unlock();
4389 
4391 
4392  return success;
4393 }
4394 
4395 //------------------------------------------------------------------
4396 void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs) const
4397 {
4398  try
4399  {
4400  m_db->get_output_key(epee::span<const uint64_t>(&amount, 1), offsets, outputs, true);
4401  }
4402  catch (const std::exception& e)
4403  {
4404  MERROR_VER("EXCEPTION: " << e.what());
4405  }
4406  catch (...)
4407  {
4408 
4409  }
4410 }
4411 
4412 //------------------------------------------------------------------
4413 // ND: Speedups:
4414 // 1. Thread long_hash computations if possible (m_max_prepare_blocks_threads = nthreads, default = 4)
4415 // 2. Group all amounts (from txs) and related absolute offsets and form a table of tx_prefix_hash
4416 // vs [k_image, output_keys] (m_scan_table). This is faster because it takes advantage of bulk queries
4417 // and is threaded if possible. The table (m_scan_table) will be used later when querying output
4418 // keys.
4419 bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks)
4420 {
4421  MTRACE("Blockchain::" << __func__);
4422  TIME_MEASURE_START(prepare);
4423  bool stop_batch;
4424  uint64_t bytes = 0;
4425  size_t total_txs = 0;
4426  blocks.clear();
4427 
4428  // Order of locking must be:
4429  // m_incoming_tx_lock (optional)
4430  // m_tx_pool lock
4431  // blockchain lock
4432  //
4433  // Something which takes the blockchain lock may never take the txpool lock
4434  // if it has not provably taken the txpool lock earlier
4435  //
4436  // The txpool lock is now taken in prepare_handle_incoming_blocks
4437  // and released in cleanup_handle_incoming_blocks. This avoids issues
4438  // when something uses the pool, which now uses the blockchain and
4439  // needs a batch, since a batch could otherwise be active while the
4440  // txpool and blockchain locks were not held
4441 
4442  m_tx_pool.lock();
4443  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4444 
4445  if(blocks_entry.size() == 0)
4446  return false;
4447 
4448  for (const auto &entry : blocks_entry)
4449  {
4450  bytes += entry.block.size();
4451  for (const auto &tx_blob : entry.txs)
4452  {
4453  bytes += tx_blob.size();
4454  }
4455  total_txs += entry.txs.size();
4456  }
4457  m_bytes_to_sync += bytes;
4458  while (!(stop_batch = m_db->batch_start(blocks_entry.size(), bytes))) {
4459  m_blockchain_lock.unlock();
4460  m_tx_pool.unlock();
4462  m_tx_pool.lock();
4463  m_blockchain_lock.lock();
4464  }
4465  m_batch_success = true;
4466 
4467  const uint64_t height = m_db->height();
4468  if ((height + blocks_entry.size()) < m_blocks_hash_check.size())
4469  return true;
4470 
4471  bool blocks_exist = false;
4473  unsigned threads = tpool.get_max_concurrency();
4474  blocks.resize(blocks_entry.size());
4475 
4476  if (1)
4477  {
4478  // limit threads, default limit = 4
4479  if(threads > m_max_prepare_blocks_threads)
4480  threads = m_max_prepare_blocks_threads;
4481 
4482  unsigned int batches = blocks_entry.size() / threads;
4483  unsigned int extra = blocks_entry.size() % threads;
4484  MDEBUG("block_batches: " << batches);
4485  std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
4486  auto it = blocks_entry.begin();
4487  unsigned blockidx = 0;
4488 
4489  const crypto::hash tophash = m_db->top_block_hash();
4490  for (unsigned i = 0; i < threads; i++)
4491  {
4492  for (unsigned int j = 0; j < batches; j++, ++blockidx)
4493  {
4494  block &block = blocks[blockidx];
4495  crypto::hash block_hash;
4496 
4497  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4498  return false;
4499 
4500  // check first block and skip all blocks if its not chained properly
4501  if (blockidx == 0)
4502  {
4503  if (block.prev_id != tophash)
4504  {
4505  MDEBUG("Skipping prepare blocks. New blocks don't belong to chain.");
4506  blocks.clear();
4507  return true;
4508  }
4509  }
4510  if (have_block(block_hash))
4511  blocks_exist = true;
4512 
4513  std::advance(it, 1);
4514  }
4515  }
4516 
4517  for (unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
4518  {
4519  block &block = blocks[blockidx];
4520  crypto::hash block_hash;
4521 
4522  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4523  return false;
4524 
4525  if (have_block(block_hash))
4526  blocks_exist = true;
4527 
4528  std::advance(it, 1);
4529  }
4530 
4531  if (!blocks_exist)
4532  {
4533  m_blocks_longhash_table.clear();
4534  uint64_t thread_height = height;
4536  for (unsigned int i = 0; i < threads; i++)
4537  {
4538  unsigned nblocks = batches;
4539  if (i < extra)
4540  ++nblocks;
4541  tpool.submit(&waiter, boost::bind(&Blockchain::block_longhash_worker, this, thread_height, epee::span<const block>(&blocks[thread_height - height], nblocks), std::ref(maps[i])), true);
4542  thread_height += nblocks;
4543  }
4544 
4545  waiter.wait(&tpool);
4546 
4547  if (m_cancel)
4548  return false;
4549 
4550  for (const auto & map : maps)
4551  {
4552  m_blocks_longhash_table.insert(map.begin(), map.end());
4553  }
4554  }
4555  }
4556 
4557  if (m_cancel)
4558  return false;
4559 
4560  if (blocks_exist)
4561  {
4562  MDEBUG("Skipping remainder of prepare blocks. Blocks exist.");
4563  return true;
4564  }
4565 
4566  m_fake_scan_time = 0;
4567  m_fake_pow_calc_time = 0;
4568 
4569  m_scan_table.clear();
4570  m_check_txin_table.clear();
4571 
4572  TIME_MEASURE_FINISH(prepare);
4573  m_fake_pow_calc_time = prepare / blocks_entry.size();
4574 
4575  if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
4576  MDEBUG("Prepare blocks took: " << prepare << " ms");
4577 
4578  TIME_MEASURE_START(scantable);
4579 
4580  // [input] stores all unique amounts found
4581  std::vector < uint64_t > amounts;
4582  // [input] stores all absolute_offsets for each amount
4583  std::map<uint64_t, std::vector<uint64_t>> offset_map;
4584  // [output] stores all output_data_t for each absolute_offset
4585  std::map<uint64_t, std::vector<output_data_t>> tx_map;
4586  std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
4587 
4588 #define SCAN_TABLE_QUIT(m) \
4589  do { \
4590  MERROR_VER(m) ;\
4591  m_scan_table.clear(); \
4592  return false; \
4593  } while(0); \
4594 
4595  // generate sorted tables for all amounts and absolute offsets
4596  size_t tx_index = 0, block_index = 0;
4597  for (const auto &entry : blocks_entry)
4598  {
4599  if (m_cancel)
4600  return false;
4601 
4602  for (const auto &tx_blob : entry.txs)
4603  {
4604  if (tx_index >= txes.size())
4605  SCAN_TABLE_QUIT("tx_index is out of sync");
4606  transaction &tx = txes[tx_index].first;
4607  crypto::hash &tx_prefix_hash = txes[tx_index].second;
4608  ++tx_index;
4609 
4610  if (!parse_and_validate_tx_base_from_blob(tx_blob, tx))
4611  SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
4612  cryptonote::get_transaction_prefix_hash(tx, tx_prefix_hash);
4613 
4614  auto its = m_scan_table.find(tx_prefix_hash);
4615  if (its != m_scan_table.end())
4616  SCAN_TABLE_QUIT("Duplicate tx found from incoming blocks.");
4617 
4618  m_scan_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, std::vector<output_data_t>>());
4619  its = m_scan_table.find(tx_prefix_hash);
4620  assert(its != m_scan_table.end());
4621 
4622  if(tx.version <= 2)
4623  {
4624  // get all amounts from tx.vin(s)
4625  for (const auto &txin : tx.vin)
4626  {
4627  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4628 
4629  // check for duplicate
4630  auto it = its->second.find(in_to_key.k_image);
4631  if (it != its->second.end())
4632  SCAN_TABLE_QUIT("Duplicate key_image found from incoming blocks.");
4633 
4634  amounts.push_back(in_to_key.amount);
4635  }
4636  }
4637 
4638  // sort and remove duplicate amounts from amounts list
4639  std::sort(amounts.begin(), amounts.end());
4640  auto last = std::unique(amounts.begin(), amounts.end());
4641  amounts.erase(last, amounts.end());
4642 
4643  // add amount to the offset_map and tx_map
4644  for (const uint64_t &amount : amounts)
4645  {
4646  if (offset_map.find(amount) == offset_map.end())
4647  offset_map.emplace(amount, std::vector<uint64_t>());
4648 
4649  if (tx_map.find(amount) == tx_map.end())
4650  tx_map.emplace(amount, std::vector<output_data_t>());
4651  }
4652 
4653  if(tx.version <= 2)
4654  {
4655  // add new absolute_offsets to offset_map
4656  for (const auto &txin : tx.vin)
4657  {
4658  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4659  // no need to check for duplicate here.
4660  auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4661  for (const auto & offset : absolute_offsets)
4662  offset_map[in_to_key.amount].push_back(offset);
4663 
4664  }
4665  }
4666  }
4667  ++block_index;
4668  }
4669 
4670  // sort and remove duplicate absolute_offsets in offset_map
4671  for (auto &offsets : offset_map)
4672  {
4673  std::sort(offsets.second.begin(), offsets.second.end());
4674  auto last = std::unique(offsets.second.begin(), offsets.second.end());
4675  offsets.second.erase(last, offsets.second.end());
4676  }
4677 
4678  // gather all the output keys
4679  threads = tpool.get_max_concurrency();
4680  if (!m_db->can_thread_bulk_indices())
4681  threads = 1;
4682 
4683  if (threads > 1 && amounts.size() > 1)
4684  {
4686 
4687  for (size_t i = 0; i < amounts.size(); i++)
4688  {
4689  uint64_t amount = amounts[i];
4690  tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount])), true);
4691  }
4692  waiter.wait(&tpool);
4693  }
4694  else
4695  {
4696  for (size_t i = 0; i < amounts.size(); i++)
4697  {
4698  uint64_t amount = amounts[i];
4699  output_scan_worker(amount, offset_map[amount], tx_map[amount]);
4700  }
4701  }
4702 
4703  // now generate a table for each tx_prefix and k_image hashes
4704  tx_index = 0;
4705  for (const auto &entry : blocks_entry)
4706  {
4707  if (m_cancel)
4708  return false;
4709 
4710  for (const auto &tx_blob : entry.txs)
4711  {
4712  if (tx_index >= txes.size())
4713  SCAN_TABLE_QUIT("tx_index is out of sync");
4714  const transaction &tx = txes[tx_index].first;
4715  const crypto::hash &tx_prefix_hash = txes[tx_index].second;
4716  ++tx_index;
4717 
4718  auto its = m_scan_table.find(tx_prefix_hash);
4719  if (its == m_scan_table.end())
4720  SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks.");
4721 
4722  if(tx.version >= 3) continue;
4723 
4724  for (const auto &txin : tx.vin)
4725  {
4726  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4727  auto needed_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4728 
4729  std::vector<output_data_t> outputs;
4730  for (const uint64_t & offset_needed : needed_offsets)
4731  {
4732  size_t pos = 0;
4733  bool found = false;
4734 
4735  for (const uint64_t &offset_found : offset_map[in_to_key.amount])
4736  {
4737  if (offset_needed == offset_found)
4738  {
4739  found = true;
4740  break;
4741  }
4742 
4743  ++pos;
4744  }
4745 
4746  if (found && pos < tx_map[in_to_key.amount].size())
4747  outputs.push_back(tx_map[in_to_key.amount].at(pos));
4748  else
4749  break;
4750  }
4751 
4752  its->second.emplace(in_to_key.k_image, outputs);
4753  }
4754  }
4755  }
4756 
4757  TIME_MEASURE_FINISH(scantable);
4758  if (total_txs > 0)
4759  {
4760  m_fake_scan_time = scantable / total_txs;
4761  if(m_show_time_stats)
4762  MDEBUG("Prepare scantable took: " << scantable << " ms");
4763  }
4764 
4765  return true;
4766 }
4767 
4769 {
4770  m_db->add_txpool_tx(txid, blob, meta);
4771 }
4772 
4774 {
4775  m_db->update_txpool_tx(txid, meta);
4776 }
4777 
4779 {
4780  m_db->remove_txpool_tx(txid);
4781 }
4782 
4783 uint64_t Blockchain::get_txpool_tx_count(bool include_unrelayed_txes) const
4784 {
4785  return m_db->get_txpool_tx_count(include_unrelayed_txes);
4786 }
4787 
4789 {
4790  return m_db->get_txpool_tx_meta(txid, meta);
4791 }
4792 
4794 {
4795  return m_db->get_txpool_tx_blob(txid, bd);
4796 }
4797 
4799 {
4800  return m_db->get_txpool_tx_blob(txid);
4801 }
4802 
4803 bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, bool include_unrelayed_txes) const
4804 {
4805  return m_db->for_all_txpool_txes(f, include_blob, include_unrelayed_txes);
4806 }
4807 
4809 {
4811  {
4813  }
4815 }
4816 
4817 void Blockchain::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)
4818 {
4819  if (sync_mode == db_defaultsync)
4820  {
4821  m_db_default_sync = true;
4822  sync_mode = db_async;
4823  }
4824  m_db_sync_mode = sync_mode;
4825  m_fast_sync = fast_sync;
4826  m_db_sync_on_blocks = sync_on_blocks;
4827  m_db_sync_threshold = sync_threshold;
4828  m_max_prepare_blocks_threads = maxthreads;
4829 
4830  if(!validator_key.empty()) {
4831  m_validator_key = boost::algorithm::unhex(validator_key);
4832  }
4833 }
4834 
4835 void Blockchain::safesyncmode(const bool onoff)
4836 {
4837  /* all of this is no-op'd if the user set a specific
4838  * --db-sync-mode at startup.
4839  */
4840  if (m_db_default_sync)
4841  {
4842  m_db->safesyncmode(onoff);
4843  m_db_sync_mode = onoff ? db_nosync : db_async;
4844  }
4845 }
4846 
4848 {
4849  return m_hardfork->get_state();
4850 }
4851 
4852 const std::vector<HardFork::Params>& Blockchain::get_hard_fork_heights(network_type nettype)
4853 {
4854  static const std::vector<HardFork::Params> mainnet_heights = []()
4855  {
4856  std::vector<HardFork::Params> heights;
4857  for (const auto& i : mainnet_hard_forks)
4858  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4859  return heights;
4860  }();
4861  static const std::vector<HardFork::Params> testnet_heights = []()
4862  {
4863  std::vector<HardFork::Params> heights;
4864  for (const auto& i : testnet_hard_forks)
4865  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4866  return heights;
4867  }();
4868  static const std::vector<HardFork::Params> stagenet_heights = []()
4869  {
4870  std::vector<HardFork::Params> heights;
4871  for (const auto& i : stagenet_hard_forks)
4872  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4873  return heights;
4874  }();
4875  static const std::vector<HardFork::Params> dummy;
4876  switch (nettype)
4877  {
4878  case MAINNET: return mainnet_heights;
4879  case TESTNET: return testnet_heights;
4880  case STAGENET: return stagenet_heights;
4881  default: return dummy;
4882  }
4883 }
4884 
4886 {
4887  return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
4888 }
4889 
4891 {
4893 }
4894 
4895 std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const
4896 {
4897  return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
4898 }
4899 
4900 std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> Blockchain::get_alternative_chains() const
4901 {
4902  std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
4903 
4904  for (const auto &i: m_alternative_chains)
4905  {
4906  const crypto::hash &top = i.first;
4907  bool found = false;
4908  for (const auto &j: m_alternative_chains)
4909  {
4910  if (j.second.bl.prev_id == top)
4911  {
4912  found = true;
4913  break;
4914  }
4915  }
4916  if (!found)
4917  {
4918  std::vector<crypto::hash> chain;
4919  auto h = i.second.bl.prev_id;
4920  chain.push_back(top);
4921  blocks_ext_by_hash::const_iterator prev;
4922  while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
4923  {
4924  chain.push_back(h);
4925  h = prev->second.bl.prev_id;
4926  }
4927  chains.push_back(std::make_pair(i.second, chain));
4928  }
4929  }
4930  return chains;
4931 }
4932 
4934 {
4935  m_cancel = true;
4936 }
4937 
4938 #if defined(PER_BLOCK_CHECKPOINT)
4939 static const char expected_block_hashes_hash[] = "53a9384ca5384025e657622b5d66fac67c03f9b863b91abe9516eda47cceaeb5";
4940 void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
4941 {
4942  if (get_checkpoints == nullptr || !m_fast_sync)
4943  {
4944  return;
4945  }
4946  const epee::span<const unsigned char> &checkpoints = get_checkpoints(m_nettype);
4947  if (!checkpoints.empty())
4948  {
4949  MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)");
4950  if (m_nettype == MAINNET)
4951  {
4952  // first check hash
4954  if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash))
4955  {
4956  MERROR("Failed to hash precomputed blocks data");
4957  return;
4958  }
4959  MINFO("precomputed blocks hash: " << hash << ", expected " << expected_block_hashes_hash);
4960  cryptonote::blobdata expected_hash_data;
4961  if (!epee::string_tools::parse_hexstr_to_binbuff(std::string(expected_block_hashes_hash), expected_hash_data) || expected_hash_data.size() != sizeof(crypto::hash))
4962  {
4963  MERROR("Failed to parse expected block hashes hash");
4964  return;
4965  }
4966  const crypto::hash expected_hash = *reinterpret_cast<const crypto::hash*>(expected_hash_data.data());
4967  if (hash != expected_hash)
4968  {
4969  MERROR("Block hash data does not match expected hash");
4970  return;
4971  }
4972  }
4973 
4974  if (checkpoints.size() > 4)
4975  {
4976  const unsigned char *p = checkpoints.data();
4977  const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
4978  if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash))
4979  {
4980  MERROR("Block hash data is too large");
4981  return;
4982  }
4983  const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
4984  if(nblocks > 0 && nblocks > m_db->height() && checkpoints.size() >= size_needed)
4985  {
4986  p += sizeof(uint32_t);
4987  for (uint32_t i = 0; i < nblocks; i++)
4988  {
4990  memcpy(hash.data, p, sizeof(hash.data));
4991  p += sizeof(hash.data);
4992  m_blocks_hash_check.push_back(hash);
4993  }
4994  MINFO(nblocks << " block hashes loaded");
4995 
4996  // FIXME: clear tx_pool because the process might have been
4997  // terminated and caused it to store txs kept by blocks.
4998  // The core will not call check_tx_inputs(..) for these
4999  // transactions in this case. Consequently, the sanity check
5000  // for tx hashes will fail in handle_block_to_main_chain(..)
5001  CRITICAL_REGION_LOCAL(m_tx_pool);
5002 
5003  std::vector<transaction> txs;
5004  m_tx_pool.get_transactions(txs);
5005 
5006  size_t tx_weight;
5007  uint64_t fee;
5008  bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
5009  transaction pool_tx;
5010  blobdata txblob;
5011  for(const transaction &tx : txs)
5012  {
5013  crypto::hash tx_hash = get_transaction_hash(tx);
5014  m_tx_pool.take_tx(tx_hash, pool_tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen);
5015  }
5016  }
5017  }
5018  }
5019 }
5020 #endif
5021 
5023 {
5024 #if defined(PER_BLOCK_CHECKPOINT)
5025  return height < m_blocks_hash_check.size();
5026 #else
5027  return false;
5028 #endif
5029 }
5030 
5032 {
5033  m_blockchain_lock.lock();
5034 }
5035 
5037 {
5038  m_blockchain_lock.unlock();
5039 }
5040 
5041 bool Blockchain::for_all_key_images(std::function<bool(const crypto::key_image&)> f) const
5042 {
5043  return m_db->for_all_key_images(f);
5044 }
5045 
5046 bool Blockchain::for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const block&)> f) const
5047 {
5048  return m_db->for_blocks_range(h1, h2, f);
5049 }
5050 
5051 bool Blockchain::for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)> f, bool pruned) const
5052 {
5053  return m_db->for_all_transactions(f, pruned);
5054 }
5055 
5056 bool Blockchain::for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const
5057 {
5058  return m_db->for_all_outputs(f);;
5059 }
5060 
5061 bool Blockchain::for_all_outputs(uint64_t amount, std::function<bool(uint64_t height)> f) const
5062 {
5063  return m_db->for_all_outputs(amount, f);;
5064 }
5065 
5066 void Blockchain::invalidate_block_template_cache()
5067 {
5068  MDEBUG("Invalidating block template cache");
5069  m_btc_valid = false;
5070 }
5071 
5072 void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t pool_cookie)
5073 {
5074  MDEBUG("Setting block template cache");
5075  m_btc = b;
5076  m_btc_address = address;
5077  m_btc_nonce = nonce;
5078  m_btc_difficulty = diff;
5079  m_btc_height = height;
5080  m_btc_expected_reward = expected_reward;
5081  m_btc_pool_cookie = pool_cookie;
5082  m_btc_valid = true;
5083 }
5084 
5086 
5087  block blk;
5089 
5090  std::string signatory = std::string(blk.signatory.begin(), blk.signatory.end());
5091  return m_validators->getValidatorByKey(boost::algorithm::hex(signatory));
5092 
5093 }
5094 
5095 namespace cryptonote {
5096 template bool Blockchain::get_transactions(const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&) const;
5097 template bool Blockchain::get_transactions_blobs(const std::vector<crypto::hash>&, std::vector<cryptonote::blobdata>&, std::vector<crypto::hash>&, bool) const;
5098 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;
5099 }
const char * res
Definition: hmac_keccak.cpp:41
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool verify_block_signature(const block &b)
Verify block&#39;s digital signature.
bool is_within_compiled_block_hash_area() const
Definition: blockchain.h:1016
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
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
#define MERROR(x)
Definition: misc_log_ex.h:73
const config_t & get_config(network_type nettype)
virtual bool update_pruning()=0
prunes recent blockchain changes as needed, iff pruning is enabled
uint64_t get_current_cumulative_block_weight_limit() const
gets the block weight limit based on recent blocks
vector< string > getApplicablePublicKeys(uint64_t height, bool convert_to_byte=false)
Definition: validators.h:176
bool check_outs_overflow(const transaction &tx)
uint64_t cookie() const
return the cookie
Definition: tx_pool.h:381
bool is_coinbase(const transaction &tx)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE
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
#define FEE_PER_KB_V11
virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the transaction blob with the given hash
void slow_hash_allocate_state()
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
virtual uint64_t get_tx_block_height(const crypto::hash &h) const =0
fetches the height of a transaction&#39;s block
std::vector< crypto::hash > tx_hashes
void slow_hash_free_state()
uint64_t height
the height of the block in the blockchain
Definition: blockchain.h:117
bool get_split_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
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&#39;s endpoint.
void pop_blocks(uint64_t nblocks)
removes blocks from the top of the blockchain
Definition: blockchain.cpp:700
bool reorganize_from_chain_height(uint64_t height)
Definition: hardfork.cpp:242
#define MTRACE(x)
Definition: misc_log_ex.h:77
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
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&#39;s key and unlocked state
#define MINFO(x)
Definition: misc_log_ex.h:75
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
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)
Definition: tx_pool.cpp:122
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
void save(Archive &a, const std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
void normalize_v7_difficulties()
Normalize the cumulative difficulty for V7 blocks, fixing the differing difficulty among nodes...
#define PERF_TIMER(name)
Definition: perf_timer.h:82
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
virtual void batch_abort()=0
aborts a batch transaction
virtual bool has_key_image(const crypto::key_image &img) const =0
check if a key image is stored as spent
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const =0
get a txpool transaction&#39;s blob
bool utxo_nonexistence_from_output(const txin_to_key_public &public_output) const
check if a single utxo in a transaction has already been spent using the hash and out index (v3 tx on...
#define HF_VERSION_FORBID_INVALID_PUBKEYS
difficulty_type next_difficulty(std::vector< uint64_t > timestamps, std::vector< difficulty_type > cumulative_difficulties, size_t target_seconds, uint8_t version)
Definition: difficulty.cpp:210
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
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 ...
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block&#39;s timestamp
::std::string string
Definition: gtest-port.h:1097
uint64_t get_outs_etn_amount(const transaction &tx)
bool utxo_nonexistent(const transaction &tx) const
check if any utxo in a transaction has already been spent using the tx (v3 tx onwards) ...
#define HF_VERSION_ENFORCE_0_DECOY_TXS
A global thread pool.
Definition: threadpool.h:43
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
std::vector< uint8_t > signatory
void get_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
Definition: tx_pool.cpp:904
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
get recent block hashes for a foreign chain
#define CRYPTONOTE_MAX_BLOCK_NUMBER
size_t get_object_blobsize(const t_object &o)
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
Validator getValidatorByKey(string key)
Definition: validators.h:188
bool check(const cryptonote::block &block) const
check whether a new block would be accepted
Definition: hardfork.cpp:116
uint64_t height
Definition: blockchain.cpp:91
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT
user didn&#39;t specify, use db_async
Definition: blockchain.h:79
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
bool store_blockchain()
stores the blockchain
Definition: blockchain.cpp:630
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 ...
void get_transaction_hashes(std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
get a list of all transaction hashes in the pool
Definition: tx_pool.cpp:923
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &details)=0
add a txpool transaction
std::vector< blobdata > txs
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
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)
Definition: crypto.h:333
#define SCAN_TABLE_QUIT(m)
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME_V6
virtual uint64_t get_block_height(const crypto::hash &h) const =0
gets the height of the block with a given hash
provides the implementation of varint&#39;s
size_t get_min_block_weight(uint8_t version)
epee::critical_section m_synchronization_lock
A lock, currently for when BlockchainLMDB needs to resize the backing db file.
uint64_t get_next_pruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:93
const char * key
Definition: hmac_keccak.cpp:39
#define MCLOG_RED(level, cat, x)
Definition: misc_log_ex.h:58
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
crypto namespace.
Definition: crypto.cpp:58
void init()
initialize the object
Definition: hardfork.cpp:169
handle syncing calls instead of the backing db, synchronously
Definition: blockchain.h:80
std::function< const epee::span< const unsigned char >cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
Definition: blockchain.h:92
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
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output&#39;s tx hash and index
void remove_txpool_tx(const crypto::hash &txid)
virtual std::vector< address_txs > get_addr_tx_all(const crypto::public_key &combined_key)=0
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD
static const std::vector< HardFork::Params > & get_hard_fork_heights(network_type nettype)
gets the hardfork heights of given network
transaction tx
the transaction
Definition: tx_pool.h:405
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
cryptonote::account_public_address address
void set_enforce_dns_checkpoints(bool enforce)
configure whether or not to enforce DNS-based checkpoints
std::vector< uint64_t > key_offsets
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
public_key addKeys(const public_key &A, const public_key &B)
Definition: crypto.h:339
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
#define FEE_PER_KB
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
bool key_images_already_spent(const transaction &tx) const
check if any key image in a transaction has already been spent
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block&#39;s cumulative difficulty
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
Definition: checkpoints.cpp:96
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta)
#define HF_VERSION_ENFORCE_0_DECOY_TXS_END
#define HF_VERSION_MIN_MIXIN_4
unsigned char uint8_t
Definition: stdint.h:124
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
#define ETN_SUPPLY
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
static threadpool & getInstance()
Definition: threadpool.h:46
virtual void safesyncmode(const bool onoff)=0
toggle safe syncs for the DB
Level
Represents enumeration for severity level used to determine level of logging.
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
struct hash_func hashes[]
#define MERROR_VER(x)
Definition: blockchain.cpp:84
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
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
#define MGINFO(x)
Definition: misc_log_ex.h:80
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
tuple make_tuple()
Definition: gtest-tuple.h:675
void on_block_popped(uint64_t new_chain_height)
called when one or more blocks are popped from the blockchain
Definition: hardfork.cpp:287
#define CRITICAL_REGION_END()
Definition: syncobj.h:233
virtual uint64_t get_num_outputs(const uint64_t &amount) const =0
fetches the number of outputs of a given amount
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
Definition: tx_pool.cpp:702
virtual void add_max_block_size(uint64_t sz)=0
add a new max block size
std::vector< uint8_t > extra
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
uint64_t get_current_cumulative_block_weight_median() const
gets the block weight median based on recent blocks (same window as for the limit) ...
virtual bool get_pruned_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the pruned transaction blob with the given hash
#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE
Definition: blockchain.cpp:65
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
Definition: blockchain.cpp:859
virtual bool get_prunable_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the prunable transaction blob with the given hash
#define DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT
#define MDEBUG(x)
Definition: misc_log_ex.h:76
virtual void close()=0
close the BlockchainDB
virtual std::vector< address_outputs > get_addr_output_all(const crypto::public_key &combined_key)=0
std::string privateKey
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const =0
get the number of transactions in the txpool
#define ETN_MINED_ETN_UNLOCK_WINDOW_V8
bool update_checkpoints(const std::string &file_path, bool check_dns)
loads new checkpoints from a file and optionally from DNS
thrown when a requested transaction does not exist
thrown when a spent key image exists, but shouldn&#39;t, namely when adding a block
std::list< std::pair< block_extended_info, std::vector< crypto::hash > > > get_alternative_chains() const
returns a set of known alternate chains
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
size_t get_total_transactions() const
gets the total number of transactions on the main chain
virtual bool check_chainstate_utxo(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
#define BLOCK_REWARD_OVERESTIMATE
Definition: blockchain.cpp:87
#define HF_VERSION_FORBID_DUST_OUTPUTS
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
return true
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
Definition: tx_pool.cpp:1180
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block&#39;s cumulative difficulty
virtual size_t get_block_weight(const uint64_t &height) const =0
fetch a block&#39;s weight
size_t get_transaction_version(const cryptonote::blobdata &bd)
bool get_block_longhash(const block &b, crypto::hash &res, uint64_t height)
bool flush_txes_from_pool(const std::vector< crypto::hash > &txids)
remove transactions from the transaction pool (if present)
#define MGINFO_GREEN(x)
Definition: misc_log_ex.h:82
virtual std::vector< uint64_t > get_block_weights(uint64_t start_height, size_t count) const =0
fetch the last N blocks&#39; weights
mdb_size_t count(MDB_cursor *cur)
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
time_t time
Definition: blockchain.cpp:93
#define PER_KB_FEE_QUANTIZATION_DECIMALS
bool is_valid_decomposed_amount(uint64_t amount)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
bool for_all_key_images(std::function< bool(const crypto::key_image &)>) const
perform a check on all key images in the blockchain
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
uint64_t unlock_time
Definition: chaingen.h:295
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&#39;s data
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
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
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&#39;s inputs
#define HF_VERSION_MIN_MIXIN_6
#define FEE_PER_KB_V6
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
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 block get_block_from_height(const uint64_t &height) const
fetch a block by height
unsigned int uint32_t
Definition: stdint.h:126
#define DIFFICULTY_TARGET_V6
bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature)
Definition: crypto.h:380
uint64_t get_num_mature_outputs(uint64_t amount) const
get number of outputs of an amount past the minimum spendable age
#define CRITICAL_REGION_BEGIN(x)
Definition: syncobj.h:229
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
#define HF_VERSION_DYNAMIC_FEE
virtual bool get_prunable_tx_hash(const crypto::hash &tx_hash, crypto::hash &prunable_hash) const =0
fetches the prunable transaction hash
uint64_t get_next_unpruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:69
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 get_block_hash(const block &b, crypto::hash &res)
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&#39;s outputs
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
crypto::public_key get_output_key(uint64_t amount, uint64_t global_index) const
get the public key for an output
virtual bool is_read_only() const =0
is BlockchainDB in read-only mode?
void sign_block(block &b, std::string privateKey)
Digitally sign the block.
virtual bool can_thread_bulk_indices() const =0
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
HardFork::State get_hard_fork_state() const
gets the hardfork voting state object
std::string const GENESIS_TX
static uint64_t get_fee_quantization_mask()
get fee quantization mask
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
crypto::public_key pubkey
the output&#39;s public key (for spend verification)
t3
Definition: pow225521.h:103
#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5
blockchain_db_sync_mode
Definition: blockchain.h:77
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
bool check_hash(const crypto::hash &hash, difficulty_type difficulty)
Definition: difficulty.cpp:203
bool prune_blockchain(uint32_t pruning_seed=0)
#define DYNAMIC_FEE_PER_KB_BASE_FEE
unsigned int get_max_concurrency() const
Definition: threadpool.cpp:92
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
#define DEFAULT_RINGSIZE
unsigned __int64 uint64_t
Definition: stdint.h:136
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW
std::string get_time_interval_string(const time_t &time_)
Definition: time_helper.h:120
bool reset_and_set_genesis_block(const block &b)
clears the blockchain and starts a new one
Definition: blockchain.cpp:812
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
Definition: blockchain.cpp:971
#define MGINFO_BLUE(x)
Definition: misc_log_ex.h:84
#define DIFFICULTY_BLOCKS_COUNT
void check_against_checkpoints(const checkpoints &points, bool enforce)
check the blockchain against a set of checkpoints
bool check_for_height(const cryptonote::block &block, uint64_t height) const
same as check, but for a particular height, rather than the top
Definition: hardfork.cpp:129
virtual void sync()=0
sync the BlockchainDB with disk
virtual block get_top_block() const =0
fetch the top block
virtual uint64_t height() const =0
fetch the current blockchain height
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
virtual void batch_stop()=0
ends a batch transaction
virtual uint64_t get_tx_unlock_time(const crypto::hash &h) const =0
fetch a transaction&#39;s unlock time/height
virtual std::vector< uint64_t > get_long_term_block_weights(uint64_t start_height, size_t count) const =0
fetch the last N blocks&#39; long term weights
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
load new checkpoints from json
uint64_t fee
the transaction&#39;s fee amount
Definition: tx_pool.h:408
blobdata block
#define false
Definition: stdbool.h:38
virtual bool for_all_key_images(std::function< bool(const crypto::key_image &)>) const =0
runs a function over all key images stored
void on_new_tx_from_block(const cryptonote::transaction &tx)
called when we see a tx originating from a block
virtual void add_addr_tx(const crypto::hash tx_hash, const crypto::public_key &combined_key)=0
thrown when a requested block does not exist
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
bool sleep_no_w(long ms)
virtual void remove_txpool_tx(const crypto::hash &txid)=0
remove a txpool transaction
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash)
Definition: util.cpp:933
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
POD_CLASS public_key
Definition: crypto.h:76
Useful when application has potentially harmful situtaions.
#define MWARNING(x)
Definition: misc_log_ex.h:74
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
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
#define CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
bool check_fee(size_t tx_weight, uint64_t fee) const
validate a transaction&#39;s fee
bool is_open() const
Gets the current open/ready state of the BlockchainDB.
size_t weight
the transaction&#39;s weight
Definition: tx_pool.h:407
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
Definition: blockchain.cpp:177
uint8_t version
Definition: blockchain.cpp:90
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
Definition: hardfork.cpp:409
std::vector< std::vector< crypto::signature > > signatures
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
virtual void set_hard_fork(HardFork *hf)
virtual difficulty_type get_block_difficulty(const uint64_t &height) const =0
fetch a block&#39;s difficulty
Transaction pool, handles transactions which are not part of a block.
Definition: tx_pool.h:94
~Blockchain()
Blockchain destructor.
Definition: blockchain.cpp:161
std::string blobdata
Definition: blobdatatype.h:39
t2
Definition: pow22523.h:103
type_vec_type median(std::vector< type_vec_type > &v)
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block&#39;s hash given a height
Definition: blockchain.cpp:901
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
expect< void > success() noexcept
Definition: expect.h:397
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
uint32_t get_mempool_tx_livetime() const
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1017
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 unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
POD_CLASS signature
Definition: crypto.h:108
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
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
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
The BlockchainDB backing store interface declaration/contract.
std::vector< uint8_t > signature
virtual uint64_t get_utxo_unlock_time(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
crypto::public_key key
const T & move(const T &t)
Definition: gtest-port.h:1317
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
Definition: blockchain.cpp:167
virtual bool prune_blockchain(uint32_t pruning_seed=0)=0
prunes the blockchain
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block&#39;s hash
information about a single transaction
Definition: tx_pool.h:403
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
POD_CLASS key_image
Definition: crypto.h:102
a struct containing txpool per transaction metadata
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
void * memcpy(void *a, const void *b, size_t c)
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition: blockchain.h:832
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
#define HF_VERSION_PUBLIC_TX
crypto::key_image k_image
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition: blockchain.h:858
uint64_t get_next_long_term_block_weight(uint64_t block_weight) const
gets the long term block weight for a new block
crypto::hash get_transaction_hash(const transaction &t)
bool has_unpruned_block(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:44
uint64_t get_difficulty_target() const
get difficulty target based on chain and hardfork version
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition: tx_pool.cpp:1196
difficulty_type block_difficulty(uint64_t i) const
gets the difficulty of the block with a given height
bool check_key(const public_key &key)
Definition: crypto.h:256
t1
Definition: pow22523.h:58
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
#define HF_VERSION_ORDERED_TX_INPUTS
virtual uint64_t get_tx_count() const =0
fetches the total number of transactions ever
uint32_t const GENESIS_NONCE
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
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.
Definition: tx_pool.cpp:1535
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1073
virtual bool check_pruning()=0
checks pruning was done correctly, iff enabled
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
virtual std::vector< transaction > get_tx_list(const std::vector< crypto::hash > &hlist) const =0
fetches a list of transactions based on their hashes
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.
Definition: blockchain.cpp:334
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
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)
Definition: crypto.h:303
#define DIFFICULTY_TARGET
thrown when a requested output does not exist
State get_state(time_t t) const
returns current state at the given time
Definition: hardfork.cpp:327
void reserve_container(std::vector< T > &v, size_t N)
DISABLE_VS_WARNINGS(4244 4345 4503) using namespace crypto
POD_CLASS hash
Definition: hash.h:50
bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time)
add a new hardfork height
Definition: hardfork.cpp:74
bool load_checkpoints_from_dns(network_type nettype=MAINNET)
load new checkpoints from DNS
void get_tx_tree_hash(const std::vector< crypto::hash > &tx_hashes, crypto::hash &h)
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
Definition: tx_pool.cpp:1188
#define HF_VERSION_MIN_MIXIN_10
std::pair< crypto::hash, uint64_t > tx_out_index
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
A container for blockchain checkpoints.
Definition: checkpoints.h:51
const char * address
Definition: multisig.cpp:37
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:928
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)
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::string to_string(t_connection_type type)
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.h:376
const std::map< uint64_t, crypto::hash > & get_points() const
gets the checkpoints container
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block&#39;s already generated coins
bool check_tx_outputs(const transaction &tx, tx_verification_context &tvc)
check that a transaction&#39;s outputs conform to current standards
blobdata block_to_blob(const block &b)
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &details)=0
update a txpool transaction&#39;s metadata
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
virtual bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const =0
get a txpool transaction&#39;s metadata
container for passing a block and metadata about it on the blockchain
Definition: blockchain.h:114
virtual void reset()=0
Remove everything from the BlockchainDB.
#define HF_VERSION_PER_BYTE_FEE
const std::pair< uint8_t, uint64_t > * hard_forks
electroneum::basic::Validator get_validator_by_height(uint64_t height)
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS
bool is_v1_tx(const blobdata_ref &tx_blob)
virtual block get_block(const crypto::hash &h) const
fetches the block with the given hash
virtual uint64_t get_top_block_timestamp() const =0
fetch the top block&#39;s timestamp
a struct containing output metadata
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
#define DIFFICULTY_BLOCKS_COUNT_V6
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX
virtual uint64_t get_block_long_term_weight(const uint64_t &height) const =0
fetch a block&#39;s long term weight
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5
const char * what() const
void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
const size_t long_term_block_weight_window
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
bool deinit()
Uninitializes the blockchain state.
Definition: blockchain.cpp:660
uint64_t get_block_height(const block &b)
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 check_for_conflicts(const checkpoints &other) const
checks if our checkpoints container conflicts with another
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
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
bool is_in_checkpoint_zone(uint64_t height) const
checks if there is a checkpoint in the future
Definition: checkpoints.cpp:91
virtual std::vector< uint64_t > get_block_cumulative_rct_outputs(const std::vector< uint64_t > &heights) const =0
fetch a block&#39;s cumulative number of rct outputs
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 cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
rct::key commitment() const
Definition: chaingen.h:323
uint8_t threshold
Definition: blockchain.cpp:92