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