Electroneum
cryptonote_core.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 <boost/algorithm/string.hpp>
33 
34 #include "string_tools.h"
35 using namespace epee;
36 
37 #include <unordered_set>
38 #include "cryptonote_core.h"
39 #include "common/util.h"
40 #include "common/updates.h"
41 #include "common/download.h"
42 #include "common/threadpool.h"
43 #include "common/command_line.h"
44 #include "warnings.h"
45 #include "crypto/crypto.h"
46 #include "cryptonote_config.h"
47 #include "misc_language.h"
48 #include "file_io_utils.h"
49 #include <csignal>
51 #include "ringct/rctTypes.h"
53 #include "ringct/rctSigs.h"
54 #include "common/notify.h"
55 #include "version.h"
56 
57 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
58 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "cn"
59 
61 
62 #define MERROR_VER(x) MCERROR("verify", x)
63 
64 #define BAD_SEMANTICS_TXES_MAX_SIZE 100
65 
66 // basically at least how many bytes the block itself serializes to without the miner tx
67 #define BLOCK_SIZE_SANITY_LEEWAY 100
68 
69 namespace cryptonote
70 {
72  "testnet"
73  , "Run on testnet. The wallet must be launched with --testnet flag."
74  , false
75  };
77  "stagenet"
78  , "Run on stagenet. The wallet must be launched with --stagenet flag."
79  , false
80  };
82  "regtest"
83  , "Run in a regression testing mode."
84  , false
85  };
87  "fixed-difficulty"
88  , "Fixed difficulty used for testing."
89  , 0
90  };
92  "ignore-bsig"
93  , "Ignore block signature & signatory verification. Used for testing."
94  , false
95  };
97  "data-dir"
98  , "Specify data directory"
101  , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string {
102  if (testnet_stagenet[0])
103  return (boost::filesystem::path(val) / "testnet").string();
104  else if (testnet_stagenet[1])
105  return (boost::filesystem::path(val) / "stagenet").string();
106  return val;
107  }
108  };
110  "offline"
111  , "Do not listen for peers, nor connect to any"
112  };
114  "disable-dns-checkpoints"
115  , "Do not retrieve checkpoints from DNS"
116  };
118  "block-download-max-size"
119  , "Set maximum size of block download queue in bytes (0 for default)"
120  , 0
121  };
122 
123  static const command_line::arg_descriptor<bool> arg_test_drop_download = {
124  "test-drop-download"
125  , "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"
126  };
127  static const command_line::arg_descriptor<uint64_t> arg_test_drop_download_height = {
128  "test-drop-download-height"
129  , "Like test-drop-download but discards only after around certain height"
130  , 0
131  };
132  static const command_line::arg_descriptor<int> arg_test_dbg_lock_sleep = {
133  "test-dbg-lock-sleep"
134  , "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."
135  , 0
136  };
137  static const command_line::arg_descriptor<bool> arg_dns_checkpoints = {
138  "enforce-dns-checkpointing"
139  , "checkpoints from DNS server will be enforced"
140  , false
141  };
142  static const command_line::arg_descriptor<uint64_t> arg_fast_block_sync = {
143  "fast-block-sync"
144  , "Sync up most of the way by using embedded, known block hashes."
145  , 1
146  };
147  static const command_line::arg_descriptor<uint64_t> arg_prep_blocks_threads = {
148  "prep-blocks-threads"
149  , "Max number of threads to use when preparing block hashes in groups."
150  , 4
151  };
152  static const command_line::arg_descriptor<uint64_t> arg_show_time_stats = {
153  "show-time-stats"
154  , "Show time-stats when processing blocks/txs and disk synchronization."
155  , 0
156  };
157  static const command_line::arg_descriptor<size_t> arg_block_sync_size = {
158  "block-sync-size"
159  , "How many blocks to sync at once during chain synchronization (0 = adaptive)."
160  , 0
161  };
162  static const command_line::arg_descriptor<std::string> arg_check_updates = {
163  "check-updates"
164  , "Check for new versions of electroneum: [disabled|notify|download|update]"
165  , "notify"
166  };
167  static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
168  "fluffy-blocks"
169  , "Relay blocks as fluffy blocks (obsolete, now default)"
170  , true
171  };
172  static const command_line::arg_descriptor<bool> arg_no_fluffy_blocks = {
173  "no-fluffy-blocks"
174  , "Relay blocks as normal blocks"
175  , false
176  };
177  static const command_line::arg_descriptor<bool> arg_pad_transactions = {
178  "pad-transactions"
179  , "Pad relayed transactions to help defend against traffic volume analysis"
180  , false
181  };
182  static const command_line::arg_descriptor<size_t> arg_max_txpool_weight = {
183  "max-txpool-weight"
184  , "Set maximum txpool weight in bytes."
186  };
187  static const command_line::arg_descriptor<std::string> arg_block_notify = {
188  "block-notify"
189  , "Run a program for each new block, '%s' will be replaced by the block hash"
190  , ""
191  };
192  static const command_line::arg_descriptor<bool> arg_prune_blockchain = {
193  "prune-blockchain"
194  , "Prune blockchain"
195  , false
196  };
197  static const command_line::arg_descriptor<std::string> arg_reorg_notify = {
198  "reorg-notify"
199  , "Run a program for each reorg, '%s' will be replaced by the split height, "
200  "'%h' will be replaced by the new blockchain height, '%n' will be "
201  "replaced by the number of new blocks in the new chain, and '%d' will be "
202  "replaced by the number of blocks discarded from the old chain"
203  , ""
204  };
205  static const command_line::arg_descriptor<std::string> arg_block_rate_notify = {
206  "block-rate-notify"
207  , "Run a program when the block rate undergoes large fluctuations. This might "
208  "be a sign of large amounts of hash rate going on and off the Electroneum network, "
209  "and thus be of potential interest in predicting attacks. %t will be replaced "
210  "by the number of minutes for the observation window, %b by the number of "
211  "blocks observed within that window, and %e by the number of blocks that was "
212  "expected in that window. It is suggested that this notification is used to "
213  "automatically increase the number of confirmations required before a payment "
214  "is acted upon."
215  , ""
216  };
217  static const command_line::arg_descriptor<std::string> arg_validator_key = {
218  "validator-key"
219  , "Validator Key"
220  , ""
221  };
222 
224  "fallback-to-pow"
225  , "Disables all Validator feature and fallback consensus to standard Proof-of-Work (CryptoNote V1)."
226  "This argument is a decentralization safety measure in case something happens with Electroneum Ltd"
227  "so that users can fork the network to Proof of Work. (Anti Meteor Feature)."
228  "Before using this flag, please determine whether or not you want to use a checkpoint for the PoW fork (--fallback-to-pow-checkpoint-hash and --fallback-to-pow-checkpoint-height)"
229  "Please note that this is only a temporary solution so that people can continue the chain in a sensible decentralised way immediately if Electroneum ceased to exist. Long term solutions are explained in our docs folder"
230  "***WARNING: IF YOU USE THIS ARGUMENT AND MINE BLOCKS AND LATER WISH TO RETURN TO THE TIP OF THE V8 *MODERATED* BLOCKCHAIN, YOU WILL HAVE TO MANUALLY POP BLOCKS BACK USING THE DAEMON (OR IMPORT) PROGRAM"
231  , false
232  };
233 
235  "fallback-to-pow-checkpoint-height"
236  , "Used in conjunction with --fallback-to-pow. This flag allows you to specify the *height* of a checkpoint that would mark the new beginning of the PoW chain agreed upon by the community"
237  , 0
238  };
239 
241  "fallback-to-pow-checkpoint-hash"
242  , "Used in conjunction with --fallback-to-pow. This flag allows you to specify the *hash* of a checkpoint that would mark the new beginning of the PoW chain agreed upon by the community"
243  , ""
244  };
245  //using namespace electroneum::basic;
246 
247  //-----------------------------------------------------------------------------------------------
248  core::core(i_cryptonote_protocol* pprotocol):
249  m_mempool(m_blockchain_storage),
250  m_blockchain_storage(m_mempool),
251  m_miner(this),
252  m_miner_address(boost::value_initialized<account_public_address>()),
253  m_starter_message_showed(false),
254  m_target_blockchain_height(0),
255  m_checkpoints_path(""),
256  m_last_dns_checkpoints_update(0),
257  m_last_json_checkpoints_update(0),
258  m_disable_dns_checkpoints(false),
259  m_update_download(0),
260  m_nettype(UNDEFINED),
261  m_update_available(false),
262  m_pad_transactions(false)
263  {
264  m_checkpoints_updating.clear();
265  set_cryptonote_protocol(pprotocol);
266  }
268  {
269  if(pprotocol)
270  m_pprotocol = pprotocol;
271  else
272  m_pprotocol = &m_protocol_stub;
273  }
274  //-----------------------------------------------------------------------------------
276  {
277  m_blockchain_storage.set_checkpoints(std::move(chk_pts));
278  }
279  //-----------------------------------------------------------------------------------
281  {
282  m_checkpoints_path = path;
283  }
284  //-----------------------------------------------------------------------------------
285  void core::set_enforce_dns_checkpoints(bool enforce_dns)
286  {
287  m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns);
288  }
289  //-----------------------------------------------------------------------------------------------
291  {
292  if (m_nettype != MAINNET || m_disable_dns_checkpoints) return true;
293 
294  if (m_checkpoints_updating.test_and_set()) return true;
295 
296  bool res = true;
297  if (time(NULL) - m_last_dns_checkpoints_update >= 3600)
298  {
299  res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, true);
300  m_last_dns_checkpoints_update = time(NULL);
301  m_last_json_checkpoints_update = time(NULL);
302  }
303  else if (time(NULL) - m_last_json_checkpoints_update >= 600)
304  {
305  res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, false);
306  m_last_json_checkpoints_update = time(NULL);
307  }
308 
309  m_checkpoints_updating.clear();
310 
311  // if anything fishy happened getting new checkpoints, bring down the house
312  if (!res)
313  {
314  graceful_exit();
315  }
316  return res;
317  }
318  //-----------------------------------------------------------------------------------
320  return m_validators->getSerializedValidatorList();
321  }
322  //-----------------------------------------------------------------------------------
324  return m_validators->setValidatorsList(v_list, true, isEmergencyUpdate);
325  }
326 
328  return m_validators->isValid();
329  }
330  //-----------------------------------------------------------------------------------
331  void core::stop()
332  {
333  m_miner.stop();
334  m_blockchain_storage.cancel();
335 
337  {
338  boost::lock_guard<boost::mutex> lock(m_update_mutex);
339  handle = m_update_download;
340  m_update_download = 0;
341  }
342  if (handle)
343  tools::download_cancel(handle);
344  }
345  //-----------------------------------------------------------------------------------
346  void core::init_options(boost::program_options::options_description& desc)
347  {
349 
350  command_line::add_arg(desc, arg_test_drop_download);
351  command_line::add_arg(desc, arg_test_drop_download_height);
352 
358  command_line::add_arg(desc, arg_dns_checkpoints);
359  command_line::add_arg(desc, arg_prep_blocks_threads);
360  command_line::add_arg(desc, arg_fast_block_sync);
361  command_line::add_arg(desc, arg_show_time_stats);
362  command_line::add_arg(desc, arg_block_sync_size);
363  command_line::add_arg(desc, arg_check_updates);
364  command_line::add_arg(desc, arg_fluffy_blocks);
365  command_line::add_arg(desc, arg_no_fluffy_blocks);
366  command_line::add_arg(desc, arg_test_dbg_lock_sleep);
370  command_line::add_arg(desc, arg_max_txpool_weight);
371  command_line::add_arg(desc, arg_pad_transactions);
372  command_line::add_arg(desc, arg_block_notify);
373  command_line::add_arg(desc, arg_prune_blockchain);
374  command_line::add_arg(desc, arg_reorg_notify);
375  command_line::add_arg(desc, arg_block_rate_notify);
376  command_line::add_arg(desc, arg_validator_key);
380 
381  miner::init_options(desc);
383  }
384  //-----------------------------------------------------------------------------------------------
385  bool core::handle_command_line(const boost::program_options::variables_map& vm)
386  {
387  if (m_nettype != FAKECHAIN)
388  {
389  const bool testnet = command_line::get_arg(vm, arg_testnet_on);
390  const bool stagenet = command_line::get_arg(vm, arg_stagenet_on);
391  m_nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
392  }
393 
394  m_config_folder = command_line::get_arg(vm, arg_data_dir);
395 
396  auto data_dir = boost::filesystem::path(m_config_folder);
397 
398  if (m_nettype == MAINNET || m_nettype == TESTNET)
399  {
401  if (!checkpoints.init_default_checkpoints(m_nettype))
402  {
403  throw std::runtime_error("Failed to initialize checkpoints");
404  }
405  //set the pow fallback checkpoint if required
406  if(m_fallback_to_pow_checkpoint_height != 0 && m_fallback_to_pow_checkpoint_hash != ""){
407  checkpoints.add_checkpoint(m_fallback_to_pow_checkpoint_height, m_fallback_to_pow_checkpoint_hash);
408  }
409 
411 
412  boost::filesystem::path json(JSON_HASH_FILE_NAME);
413  boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json;
414 
415  set_checkpoints_file_path(checkpoint_json_hashfile_fullpath.string());
416  }
417 
418 
419  set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
420  test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
421  m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks);
422  m_pad_transactions = get_arg(vm, arg_pad_transactions);
423  m_offline = get_arg(vm, arg_offline);
424  m_disable_dns_checkpoints = m_fallback_to_pow ? true : get_arg(vm, arg_disable_dns_checkpoints);
425  if (!command_line::is_arg_defaulted(vm, arg_fluffy_blocks))
426  MWARNING(arg_fluffy_blocks.name << " is obsolete, it is now default");
427 
428  if (command_line::get_arg(vm, arg_test_drop_download) == true)
430 
431  epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, arg_test_dbg_lock_sleep);
432 
433  return true;
434  }
435  //-----------------------------------------------------------------------------------------------
437  {
438  return m_blockchain_storage.get_current_blockchain_height();
439  }
440  //-----------------------------------------------------------------------------------------------
442  {
443  top_id = m_blockchain_storage.get_tail_id(height);
444  }
445  //-----------------------------------------------------------------------------------------------
446  bool core::get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata,block>>& blocks, std::vector<cryptonote::blobdata>& txs) const
447  {
448  return m_blockchain_storage.get_blocks(start_offset, count, blocks, txs);
449  }
450  //-----------------------------------------------------------------------------------------------
451  bool core::get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata,block>>& blocks) const
452  {
453  return m_blockchain_storage.get_blocks(start_offset, count, blocks);
454  }
455  //-----------------------------------------------------------------------------------------------
456  bool core::get_blocks(uint64_t start_offset, size_t count, std::vector<block>& blocks) const
457  {
458  std::vector<std::pair<cryptonote::blobdata, cryptonote::block>> bs;
459  if (!m_blockchain_storage.get_blocks(start_offset, count, bs))
460  return false;
461  for (const auto &b: bs)
462  blocks.push_back(b.second);
463  return true;
464  }
465  //-----------------------------------------------------------------------------------------------
466  bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs) const
467  {
468  return m_blockchain_storage.get_transactions_blobs(txs_ids, txs, missed_txs);
469  }
470  //-----------------------------------------------------------------------------------------------
471  bool core::get_split_transactions_blobs(const std::vector<crypto::hash>& txs_ids, std::vector<std::tuple<crypto::hash, cryptonote::blobdata, crypto::hash, cryptonote::blobdata>>& txs, std::vector<crypto::hash>& missed_txs) const
472  {
473  return m_blockchain_storage.get_split_transactions_blobs(txs_ids, txs, missed_txs);
474  }
475  //-----------------------------------------------------------------------------------------------
476  bool core::get_txpool_backlog(std::vector<tx_backlog_entry>& backlog) const
477  {
478  m_mempool.get_transaction_backlog(backlog);
479  return true;
480  }
481  //-----------------------------------------------------------------------------------------------
482  bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs) const
483  {
484  return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs);
485  }
486  //-----------------------------------------------------------------------------------------------
487  bool core::get_alternative_blocks(std::vector<block>& blocks) const
488  {
489  return m_blockchain_storage.get_alternative_blocks(blocks);
490  }
491  //-----------------------------------------------------------------------------------------------
493  {
494  return m_blockchain_storage.get_alternative_blocks_count();
495  }
496  //-----------------------------------------------------------------------------------------------
497  bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */)
498  {
499  start_time = std::time(nullptr);
500 
501  const bool regtest = command_line::get_arg(vm, arg_regtest_on);
502  if (test_options != NULL || regtest)
503  {
504  m_nettype = FAKECHAIN;
505  }
506 
507  m_fallback_to_pow = command_line::get_arg(vm, arg_fallback_to_pow);
508  m_fallback_to_pow_checkpoint_height = command_line::get_arg(vm, arg_fallback_to_pow_checkpoint_height);
509  m_fallback_to_pow_checkpoint_hash = command_line::get_arg(vm, arg_fallback_to_pow_checkpoint_hash);
510 
511  bool r = handle_command_line(vm);
512 
515  bool db_salvage = command_line::get_arg(vm, cryptonote::arg_db_salvage) != 0;
516  bool addr_db_salvage = command_line::get_arg(vm, cryptonote::arg_addr_db_salvage) != 0;
517  bool fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
518  uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
519  std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
520  size_t max_txpool_weight = command_line::get_arg(vm, arg_max_txpool_weight);
521  bool prune_blockchain = command_line::get_arg(vm, arg_prune_blockchain);
522  std::string validator_key = command_line::get_arg(vm, arg_validator_key);
523 
524  bool is_validator_key_valid = std::count_if(validator_key.begin(), validator_key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
525  if(!is_validator_key_valid || validator_key.size() % 2 != 0) {
526  validator_key.clear();
527  }
528 
529  boost::filesystem::path folder(m_config_folder);
530  if (m_nettype == FAKECHAIN)
531  folder /= "fake";
532 
533  // make sure the data directory exists, and try to lock it
534  CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false,
535  std::string("Failed to create directory ").append(folder.string()).c_str());
536 
537  // check for blockchain.bin
538  try
539  {
540  const boost::filesystem::path old_files = folder;
541  if (boost::filesystem::exists(old_files / "blockchain.bin"))
542  {
543  MWARNING("Found old-style blockchain.bin in " << old_files.string());
544  MWARNING("Electroneum now uses a new format. You can either remove blockchain.bin to start syncing");
545  MWARNING("the blockchain anew, or use electroneum-blockchain-export and electroneum-blockchain-import to");
546  MWARNING("convert your existing blockchain.bin to the new format. See README.md for instructions.");
547  return false;
548  }
549  }
550  // folder might not be a directory, etc, etc
551  catch (...) { }
552 
553  std::unique_ptr<BlockchainDB> db(new_db(db_type));
554  if (db == NULL)
555  {
556  LOG_ERROR("Attempted to use non-existent database type");
557  return false;
558  }
559 
560  folder /= db->get_db_name();
561  MGINFO("Loading blockchain from folder " << folder.string() << " ...");
562 
563  const std::string filename = folder.string();
564  // default to fast:async:1 if overridden
566  bool sync_on_blocks = true;
567  uint64_t sync_threshold = 1;
568 
569  if (m_nettype == FAKECHAIN)
570  {
571  // reset the db by removing the database file before opening it
572  if (!db->remove_data_file(filename))
573  {
574  MERROR("Failed to remove data file in " << filename);
575  return false;
576  }
577  }
578 
579  try
580  {
581  uint64_t db_flags = 0;
582 
583  std::vector<std::string> options;
584  boost::trim(db_sync_mode);
585  boost::split(options, db_sync_mode, boost::is_any_of(" :"));
586  const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode);
587 
588  for(const auto &option : options)
589  MDEBUG("option: " << option);
590 
591  // default to fast:async:1
592  uint64_t DEFAULT_FLAGS = DBF_FAST;
593 
594  if(options.size() == 0)
595  {
596  // default to fast:async:1
597  db_flags = DEFAULT_FLAGS;
598  }
599 
600  bool safemode = false;
601  if(options.size() >= 1)
602  {
603  if(options[0] == "safe")
604  {
605  safemode = true;
606  db_flags = DBF_SAFE;
607  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_nosync;
608  }
609  else if(options[0] == "fast")
610  {
611  db_flags = DBF_FAST;
612  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
613  }
614  else if(options[0] == "fastest")
615  {
616  db_flags = DBF_FASTEST;
617  sync_threshold = 1000; // default to fastest:async:1000
618  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
619  }
620  else
621  db_flags = DEFAULT_FLAGS;
622  }
623 
624  if(options.size() >= 2 && !safemode)
625  {
626  if(options[1] == "sync")
627  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_sync;
628  else if(options[1] == "async")
629  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
630  }
631 
632  if(options.size() >= 3 && !safemode)
633  {
634  char *endptr;
635  uint64_t threshold = strtoull(options[2].c_str(), &endptr, 0);
636  if (*endptr == '\0' || !strcmp(endptr, "blocks"))
637  {
638  sync_on_blocks = true;
639  sync_threshold = threshold;
640  }
641  else if (!strcmp(endptr, "bytes"))
642  {
643  sync_on_blocks = false;
644  sync_threshold = threshold;
645  }
646  else
647  {
648  LOG_ERROR("Invalid db sync mode: " << options[2]);
649  return false;
650  }
651  }
652 
653  if (db_salvage)
654  db_flags |= DBF_SALVAGE;
655 
656  if(addr_db_salvage)
657  db_flags |= DBF_ADDR_TX_SALVAGE;
658 
659  db->open(filename, db_flags);
660  if(!db->m_open)
661  return false;
662  }
663  catch (const DB_ERROR& e)
664  {
665  LOG_ERROR("Error opening database: " << e.what());
666  return false;
667  }
668 
669  m_blockchain_storage.set_user_options(blocks_threads,
670  sync_on_blocks, sync_threshold, sync_mode, fast_sync, validator_key);
671 
672  try
673  {
674  if (!command_line::is_arg_defaulted(vm, arg_block_notify))
675  m_blockchain_storage.set_block_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_block_notify).c_str())));
676  }
677  catch (const std::exception &e)
678  {
679  MERROR("Failed to parse block notify spec: " << e.what());
680  }
681 
682  try
683  {
684  if (!command_line::is_arg_defaulted(vm, arg_reorg_notify))
685  m_blockchain_storage.set_reorg_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_reorg_notify).c_str())));
686  }
687  catch (const std::exception &e)
688  {
689  MERROR("Failed to parse reorg notify spec: " << e.what());
690  }
691 
692  try
693  {
694  if (!command_line::is_arg_defaulted(vm, arg_block_rate_notify))
695  m_block_rate_notify.reset(new tools::Notify(command_line::get_arg(vm, arg_block_rate_notify).c_str()));
696  }
697  catch (const std::exception &e)
698  {
699  MERROR("Failed to parse block rate notify spec: " << e.what());
700  }
701 
702  const std::pair<uint8_t, uint64_t> regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
703  const cryptonote::test_options regtest_test_options = {
704  regtest_hard_forks,
705  0
706  };
707  const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty);
708  const bool ignore_bsig = command_line::get_arg(vm, arg_skip_block_sig_verification);
709 
710  r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints, ignore_bsig, m_fallback_to_pow);
711 
712  r = m_mempool.init(max_txpool_weight);
713  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
714 
715  // now that we have a valid m_blockchain_storage, we can clean out any
716  // transactions in the pool that do not conform to the current fork
717  m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
718 
719  bool show_time_stats = command_line::get_arg(vm, arg_show_time_stats) != 0;
720  m_blockchain_storage.set_show_time_stats(show_time_stats);
721  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
722 
723  block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
724 
725  MGINFO("Loading checkpoints");
726 
727  // load json & DNS checkpoints, and verify them
728  // with respect to what blocks we already have
729  CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
730 
731  // DNS versions checking
732  if (check_updates_string == "disabled")
733  check_updates_level = UPDATES_DISABLED;
734  else if (check_updates_string == "notify")
735  check_updates_level = UPDATES_NOTIFY;
736  else if (check_updates_string == "download")
737  check_updates_level = UPDATES_DOWNLOAD;
738  else if (check_updates_string == "update")
739  check_updates_level = UPDATES_UPDATE;
740  else {
741  MERROR("Invalid argument to --dns-versions-check: " << check_updates_string);
742  return false;
743  }
744 
745  check_updates_level = UPDATES_DISABLED;
746 
747  r = m_miner.init(vm, m_nettype, m_fallback_to_pow);
748  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance");
749 
750  if (prune_blockchain)
751  {
752  // display a message if the blockchain is not pruned yet
753  if (!m_blockchain_storage.get_blockchain_pruning_seed())
754  {
755  MGINFO("Pruning blockchain...");
756  CHECK_AND_ASSERT_MES(m_blockchain_storage.prune_blockchain(), false, "Failed to prune blockchain");
757  }
758  else
759  {
760  CHECK_AND_ASSERT_MES(m_blockchain_storage.update_blockchain_pruning(), false, "Failed to update blockchain pruning");
761  }
762  }
763 
764  if(!m_fallback_to_pow) {
765  m_validators = std::unique_ptr<electroneum::basic::Validators>(new electroneum::basic::Validators(m_blockchain_storage.get_db(), m_pprotocol, m_nettype == TESTNET));
766  m_blockchain_storage.set_validators_list_instance(m_validators);
767 
768  if(m_blockchain_storage.get_current_blockchain_height() >= ((m_nettype == TESTNET ? 446674 : 589169) - 720 )) { //V8 Height - 1 day
769  m_validators->enable();
770  }
771  }
772 
773  return load_state_data();
774  }
775  //-----------------------------------------------------------------------------------------------
777  {
778  return m_blockchain_storage.reset_and_set_genesis_block(b);
779  }
780  //-----------------------------------------------------------------------------------------------
781  bool core::load_state_data()
782  {
783  // may be some code later
784  return true;
785  }
786  //-----------------------------------------------------------------------------------------------
788  {
789  m_miner.stop();
790  m_mempool.deinit();
791  m_blockchain_storage.deinit();
792  return true;
793  }
794  //-----------------------------------------------------------------------------------------------
796  {
797  m_test_drop_download = false;
798  }
799  //-----------------------------------------------------------------------------------------------
801  {
802  m_test_drop_download_height = height;
803  }
804  //-----------------------------------------------------------------------------------------------
806  {
807  return m_test_drop_download;
808  }
809  //-----------------------------------------------------------------------------------------------
811  {
812  if (m_test_drop_download_height == 0)
813  return true;
814 
815  if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height)
816  return true;
817 
818  return false;
819  }
820  //-----------------------------------------------------------------------------------------------
821  bool core::handle_incoming_tx_pre(const blobdata& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash, bool keeped_by_block, bool relayed, bool do_not_relay)
822  {
823  tvc = boost::value_initialized<tx_verification_context>();
824 
825  if(tx_blob.size() > get_max_tx_size())
826  {
827  LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected");
828  tvc.m_verification_failed = true;
829  tvc.m_too_big = true;
830  return false;
831  }
832 
833  tx_hash = crypto::null_hash;
834 
835  if(!parse_tx_from_blob(tx, tx_hash, tx_blob))
836  {
837  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected");
838  tvc.m_verification_failed = true;
839  return false;
840  }
841  //std::cout << "!"<< tx.vin.size() << std::endl;
842 
843  bad_semantics_txes_lock.lock();
844  for (int idx = 0; idx < 2; ++idx)
845  {
846  if (bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end())
847  {
848  bad_semantics_txes_lock.unlock();
849  LOG_PRINT_L1("Transaction already seen with bad semantics, rejected");
850  tvc.m_verification_failed = true;
851  return false;
852  }
853  }
854  bad_semantics_txes_lock.unlock();
855 
856  uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
857 
858  const size_t max_tx_version = version < HF_VERSION_PUBLIC_TX ? 1 : 3;
859  if (tx.version == 0 || tx.version > max_tx_version)
860  {
861  // v2 is the latest one we know
862  tvc.m_verification_failed = true;
863  return false;
864  }
865 
866  const size_t min_tx_version = version >= HF_VERSION_PUBLIC_TX ? 2 : 1;
867  if (tx.version < min_tx_version)
868  {
869  tvc.m_verification_failed = true;
870  return false;
871  }
872 
873  return true;
874  }
875  //-----------------------------------------------------------------------------------------------
876  bool core::handle_incoming_tx_post(const blobdata& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash, bool keeped_by_block, bool relayed, bool do_not_relay)
877  {
878  if(!check_tx_syntax(tx))
879  {
880  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected");
881  tvc.m_verification_failed = true;
882  return false;
883  }
884 
885  return true;
886  }
887  //-----------------------------------------------------------------------------------------------
888  void core::set_semantics_failed(const crypto::hash &tx_hash)
889  {
890  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
891  bad_semantics_txes_lock.lock();
892  bad_semantics_txes[0].insert(tx_hash);
893  if (bad_semantics_txes[0].size() >= BAD_SEMANTICS_TXES_MAX_SIZE)
894  {
895  std::swap(bad_semantics_txes[0], bad_semantics_txes[1]);
896  bad_semantics_txes[0].clear();
897  }
898  bad_semantics_txes_lock.unlock();
899  }
900  //-----------------------------------------------------------------------------------------------
901  bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block)
902  {
903  bool ret = true;
904  if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
905  {
906  MTRACE("Skipping semantics check for tx kept by block in embedded hash area");
907  return true;
908  }
909 
910  std::vector<const rct::rctSig*> rvv;
911  for (size_t n = 0; n < tx_info.size(); ++n)
912  {
913  if (!check_tx_semantic(*tx_info[n].tx, keeped_by_block))
914  {
915  set_semantics_failed(tx_info[n].tx_hash);
916  tx_info[n].tvc.m_verification_failed = true;
917  tx_info[n].result = false;
918  continue;
919  }
920  }
921  if (!rvv.empty() && !rct::verRctSemanticsSimple(rvv))
922  {
923  LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
924  ret = false;
925  const bool assumed_bad = rvv.size() == 1; // if there's only one tx, it must be the bad one
926  for (size_t n = 0; n < tx_info.size(); ++n)
927  {
928  if (!tx_info[n].result)
929  continue;
930  if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2)
931  continue;
932  if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
933  {
934  set_semantics_failed(tx_info[n].tx_hash);
935  tx_info[n].tvc.m_verification_failed = true;
936  tx_info[n].result = false;
937  }
938  }
939  }
940 
941  return ret;
942  }
943  //-----------------------------------------------------------------------------------------------
944  bool core::handle_incoming_txs(const std::vector<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
945  {
946  TRY_ENTRY();
947  CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
948 
949  struct result { bool res; cryptonote::transaction tx; crypto::hash hash; };
950  std::vector<result> results(tx_blobs.size());
951 
952  tvc.resize(tx_blobs.size());
955  std::vector<blobdata>::const_iterator it = tx_blobs.begin();
956  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
957  tpool.submit(&waiter, [&, i, it] {
958  try
959  {
960  results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
961  }
962  catch (const std::exception &e)
963  {
964  MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what());
965  tvc[i].m_verification_failed = true;
966  results[i].res = false;
967  }
968  });
969  }
970  waiter.wait(&tpool);
971  it = tx_blobs.begin();
972  std::vector<bool> already_have(tx_blobs.size(), false);
973  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
974  if (!results[i].res)
975  continue;
976  if(m_mempool.have_tx(results[i].hash))
977  {
978  LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool");
979  already_have[i] = true;
980  }
981  else if(m_blockchain_storage.have_tx(results[i].hash))
982  {
983  LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain");
984  already_have[i] = true;
985  }
986  else
987  {
988  tpool.submit(&waiter, [&, i, it] {
989  try
990  {
991  results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
992  }
993  catch (const std::exception &e)
994  {
995  MERROR_VER("Exception in handle_incoming_tx_post: " << e.what());
996  tvc[i].m_verification_failed = true;
997  results[i].res = false;
998  }
999  });
1000  }
1001  }
1002  waiter.wait(&tpool);
1003 
1004  std::vector<tx_verification_batch_info> tx_info;
1005  tx_info.reserve(tx_blobs.size());
1006  for (size_t i = 0; i < tx_blobs.size(); i++) {
1007  if (!results[i].res || already_have[i])
1008  continue;
1009  tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
1010  }
1011  if (!tx_info.empty())
1012  handle_incoming_tx_accumulated_batch(tx_info, keeped_by_block);
1013 
1014  bool ok = true;
1015  it = tx_blobs.begin();
1016  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
1017  if (!results[i].res)
1018  {
1019  ok = false;
1020  continue;
1021  }
1022  if (keeped_by_block)
1024  if (already_have[i])
1025  continue;
1026 
1027  const size_t weight = get_transaction_weight(results[i].tx, it->size());
1028  ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], weight, tvc[i], keeped_by_block, relayed, do_not_relay);
1029  if(tvc[i].m_verification_failed)
1030  {MERROR_VER("Transaction verification failed: " << results[i].hash);}
1031  else if(tvc[i].m_verification_impossible)
1032  {MERROR_VER("Transaction verification impossible: " << results[i].hash);}
1033 
1034  if(tvc[i].m_added_to_pool)
1035  MDEBUG("tx added: " << results[i].hash);
1036  }
1037  return ok;
1038 
1039  CATCH_ENTRY_L0("core::handle_incoming_txs()", false);
1040  }
1041  //-----------------------------------------------------------------------------------------------
1042  bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1043  {
1044  std::vector<cryptonote::blobdata> tx_blobs;
1045  tx_blobs.push_back(tx_blob);
1046  std::vector<tx_verification_context> tvcv(1);
1047  bool r = handle_incoming_txs(tx_blobs, tvcv, keeped_by_block, relayed, do_not_relay);
1048  tvc = tvcv[0];
1049  return r;
1050  }
1051  //-----------------------------------------------------------------------------------------------
1053  {
1054  st_inf.mining_speed = m_miner.get_speed();
1055  st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count();
1056  st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1057  st_inf.tx_pool_size = m_mempool.get_transactions_count();
1058  st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_tail_id());
1059  return true;
1060  }
1061 
1062  //-----------------------------------------------------------------------------------------------
1063  bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const
1064  {
1065  if(!tx.vin.size())
1066  {
1067  MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
1068  return false;
1069  }
1070 
1072  {
1073  MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx));
1074  return false;
1075  }
1076 
1077  if(!check_outs_valid(tx))
1078  {
1079  MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
1080  return false;
1081  }
1082 
1083  if(!check_etn_overflow(tx))
1084  {
1085  MERROR_VER("tx has ETN overflow, rejected for tx id= " << get_transaction_hash(tx));
1086  return false;
1087  }
1088 
1089  uint64_t amount_in = 0;
1090  get_inputs_etn_amount(tx, amount_in);
1091  uint64_t amount_out = get_outs_etn_amount(tx);
1092  // v1 & v2 tx ins/outs semantics are checked in the same way regardless of our chains height or the network height
1093  if((tx.version == 1 && amount_in <= amount_out) || (tx.version == 2 && amount_in != amount_out)) {
1094 
1095  MERROR_VER("V" << tx.version << " tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1096  << get_transaction_hash(tx));
1097  return false;
1098  }
1099 
1100  if (tx.version == 3) {
1101  // if we find a single output that isn't to the bridge, ensure it's a fee paying tx, then carry with other semantic checks
1102  bool only_bridge_dests = true;
1103  std::string portal_address_viewkey_hex_str;
1104  std::string portal_address_spendkey_hex_str;
1105  if(m_nettype == MAINNET){
1106  portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375"; //private view is just e5c8af002654f38ec39ac80edbbcd0c03c9b483379d297af0c3ca15568c7300e
1107  portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137"; // from hash_to_point(v9 fork)
1108  }else{
1109  portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
1110  portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
1111  }
1112 
1113  for (auto output: tx.vout){
1114  const auto out = boost::get<txout_to_key_public>(output.target);
1115  std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
1116  std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
1117  if(out_spendkey_str != portal_address_spendkey_hex_str || out_viewkey_str != portal_address_viewkey_hex_str){
1118  only_bridge_dests = false;
1119  if(amount_in <= amount_out){
1120  MERROR_VER("v3 tx with some outs not going to the bridge should be fee paying: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1121  << get_transaction_hash(tx));
1122  return false;
1123  }
1124  break;
1125  }
1126  }
1127  if (only_bridge_dests && amount_in < amount_out){ // allow both fee paying (pre fork) and feeless (post fork)
1128  MERROR_VER("v3 sc_migration tx has wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1129  << get_transaction_hash(tx));
1130  return false;
1131  }
1132  }
1133  // for version > 1, ringct signatures check verifies amounts match
1134 
1136  {
1137  MERROR_VER("tx is too large " << get_transaction_weight(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_block_weight_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
1138  return false;
1139  }
1140 
1141  if(tx.version >= 3)
1142  {
1143  //check if tx use different utxos
1144  if(!check_tx_inputs_utxos_diff(tx))
1145  {
1146  MERROR_VER("tx uses a single utxo more than once");
1147  return false;
1148  }
1149  }
1150  else
1151  {
1152  //check if tx use different key images
1153  if(!check_tx_inputs_keyimages_diff(tx))
1154  {
1155  MERROR_VER("tx uses a single key image more than once");
1156  return false;
1157  }
1158 
1159  if (!check_tx_inputs_keyimages_domain(tx))
1160  {
1161  MERROR_VER("tx uses key image not in the valid domain");
1162  return false;
1163  }
1164  }
1165 
1166  return true;
1167  }
1168  //-----------------------------------------------------------------------------------------------
1170  {
1171  return m_blockchain_storage.have_tx_keyimg_as_spent(key_image);
1172  }
1173  //-----------------------------------------------------------------------------------------------
1174  bool core::are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1175  {
1176  spent.clear();
1177  for(auto& ki: key_im)
1178  {
1179  spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki));
1180  }
1181  return true;
1182  }
1183  //-----------------------------------------------------------------------------------------------
1184  bool core::utxo_nonexistant(const std::vector<txin_to_key_public>& public_outputs, std::vector<bool> &spent) const
1185  {
1186  spent.clear();
1187  for(auto& po: public_outputs)
1188  {
1189  spent.push_back(m_blockchain_storage.utxo_nonexistence_from_output(po));
1190  }
1191  return true;
1192  }
1193  //-----------------------------------------------------------------------------------------------
1195  {
1196  static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
1197  if (block_sync_size > 0)
1198  return block_sync_size;
1199  if (height >= quick_height)
1202  }
1203  //-----------------------------------------------------------------------------------------------
1204  bool core::are_key_images_spent_in_pool(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1205  {
1206  spent.clear();
1207  return m_mempool.check_for_key_images(key_im, spent);
1208  }
1209  //-----------------------------------------------------------------------------------------------
1210  std::pair<uint64_t, uint64_t> core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count)
1211  {
1212  uint64_t emission_amount = 0;
1213  uint64_t total_fee_amount = 0;
1214  if (count)
1215  {
1216  const uint64_t end = start_offset + count - 1;
1217  m_blockchain_storage.for_blocks_range(start_offset, end,
1218  [this, &emission_amount, &total_fee_amount](uint64_t, const crypto::hash& hash, const block& b){
1219  std::vector<transaction> txs;
1220  std::vector<crypto::hash> missed_txs;
1221  uint64_t coinbase_amount = get_outs_etn_amount(b.miner_tx);
1222  this->get_transactions(b.tx_hashes, txs, missed_txs);
1223  uint64_t tx_fee_amount = 0;
1224  for(const auto& tx: txs)
1225  {
1226  tx_fee_amount += get_tx_fee(tx);
1227  }
1228 
1229  emission_amount += coinbase_amount - tx_fee_amount;
1230  total_fee_amount += tx_fee_amount;
1231  return true;
1232  });
1233  }
1234 
1235  return std::pair<uint64_t, uint64_t>(emission_amount, total_fee_amount);
1236  }
1237  //-----------------------------------------------------------------------------------------------
1238  bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const
1239  {
1240  std::unordered_set<crypto::key_image> ki;
1241  for(const auto& in: tx.vin)
1242  {
1243  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1244  if(!ki.insert(tokey_in.k_image).second)
1245  return false;
1246  }
1247  return true;
1248  }
1249  //-----------------------------------------------------------------------------------------------
1250  bool core::check_tx_inputs_utxos_diff(const transaction& tx) const
1251  {
1252  std::unordered_set<std::string> ins;
1253  for(const auto& in: tx.vin)
1254  {
1255  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
1256  if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
1257  return false;
1258  }
1259  return true;
1260  }
1261  //-----------------------------------------------------------------------------------------------
1262  bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const
1263  {
1264  const uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1266  {
1267  for(const auto& in: tx.vin)
1268  {
1269  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1270  for (size_t n = 1; n < tokey_in.key_offsets.size(); ++n)
1271  if (tokey_in.key_offsets[n] == 0)
1272  return false;
1273  }
1274  }
1275  return true;
1276  }
1277  //-----------------------------------------------------------------------------------------------
1278  bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const
1279  {
1280  std::unordered_set<crypto::key_image> ki;
1281  for(const auto& in: tx.vin)
1282  {
1283  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1284  if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity()))
1285  return false;
1286  }
1287  return true;
1288  }
1289  //-----------------------------------------------------------------------------------------------
1290  bool core::add_new_tx(transaction& tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1291  {
1292  crypto::hash tx_hash = get_transaction_hash(tx);
1293  blobdata bl;
1295  size_t tx_weight = get_transaction_weight(tx, bl.size());
1296  return add_new_tx(tx, tx_hash, bl, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
1297  }
1298  //-----------------------------------------------------------------------------------------------
1300  {
1301  return m_blockchain_storage.get_total_transactions();
1302  }
1303  //-----------------------------------------------------------------------------------------------
1304  bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1305  {
1306 
1307  if(m_mempool.have_tx(tx_hash))
1308  {
1309  LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool");
1310  return true;
1311  }
1312 
1313  if(m_blockchain_storage.have_tx(tx_hash))
1314  {
1315  LOG_PRINT_L2("tx " << tx_hash << " already have transaction in blockchain");
1316  return true;
1317  }
1318 
1319  uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1320  return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version);
1321  }
1322  //-----------------------------------------------------------------------------------------------
1323  bool core::relay_txpool_transactions()
1324  {
1325  // we attempt to relay txes that should be relayed, but were not
1326  std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1327  if (m_mempool.get_relayable_transactions(txs) && !txs.empty())
1328  {
1329  cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
1330  tx_verification_context tvc = AUTO_VAL_INIT(tvc);
1332  for (auto it = txs.begin(); it != txs.end(); ++it)
1333  {
1334  r.txs.push_back(it->second);
1335  }
1336  get_protocol()->relay_transactions(r, fake_context);
1337  m_mempool.set_relayed(txs);
1338  }
1339  return true;
1340  }
1341  //-----------------------------------------------------------------------------------------------
1343  {
1344  std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1346  crypto::hash tx_hash;
1347  if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
1348  {
1349  LOG_ERROR("Failed to parse relayed transaction");
1350  return;
1351  }
1352  txs.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
1353  m_mempool.set_relayed(txs);
1354  }
1355  //-----------------------------------------------------------------------------------------------
1356  bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1357  {
1358  return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce);
1359  }
1360  //-----------------------------------------------------------------------------------------------
1361  bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1362  {
1363  return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce);
1364  }
1365  //-----------------------------------------------------------------------------------------------
1366  bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
1367  {
1368  return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
1369  }
1370  //-----------------------------------------------------------------------------------------------
1371  bool core::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
1372  {
1373  return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_count);
1374  }
1375  //-----------------------------------------------------------------------------------------------
1377  {
1378  return m_blockchain_storage.get_outs(req, res);
1379  }
1380  //-----------------------------------------------------------------------------------------------
1381  bool core::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
1382  {
1383  return m_blockchain_storage.get_output_distribution(amount, from_height, to_height, start_height, distribution, base);
1384  }
1385  //-----------------------------------------------------------------------------------------------
1386  bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const
1387  {
1388  return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs);
1389  }
1390  //-----------------------------------------------------------------------------------------------
1391  bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, size_t n_txes, std::vector<std::vector<uint64_t>>& indexs) const
1392  {
1393  return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, n_txes, indexs);
1394  }
1395  //-----------------------------------------------------------------------------------------------
1397  {
1398  m_miner.pause();
1399  }
1400  //-----------------------------------------------------------------------------------------------
1402  {
1403  m_miner.resume();
1404  }
1405  //-----------------------------------------------------------------------------------------------
1407  {
1410  for (const auto &tx_hash: b.tx_hashes)
1411  {
1412  cryptonote::blobdata txblob;
1413  CHECK_AND_ASSERT_THROW_MES(pool.get_transaction(tx_hash, txblob), "Transaction not found in pool");
1414  bce.txs.push_back(txblob);
1415  }
1416  return bce;
1417  }
1418  //-----------------------------------------------------------------------------------------------
1420  {
1421  bvc = boost::value_initialized<block_verification_context>();
1422  m_miner.pause();
1423  std::vector<block_complete_entry> blocks;
1424  try
1425  {
1426  blocks.push_back(get_block_complete_entry(b, m_mempool));
1427  }
1428  catch (const std::exception &e)
1429  {
1430  m_miner.resume();
1431  return false;
1432  }
1433  std::vector<block> pblocks;
1434  if (!prepare_handle_incoming_blocks(blocks, pblocks))
1435  {
1436  MERROR("Block found, but failed to prepare to add");
1437  m_miner.resume();
1438  return false;
1439  }
1440  m_blockchain_storage.add_new_block(b, bvc);
1442 
1443  CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Mined block failed verification");
1444  if(bvc.m_added_to_main_chain)
1445  {
1446  cryptonote_connection_context exclude_context = boost::value_initialized<cryptonote_connection_context>();
1448  arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1449  std::vector<crypto::hash> missed_txs;
1450  std::vector<cryptonote::blobdata> txs;
1451  m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, missed_txs);
1452  if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b))
1453  {
1454  LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block");
1455  return true;
1456  }
1457  CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size()
1458  << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size());
1459 
1460  block_to_blob(b, arg.b.block);
1461  //pack transactions
1462  for(auto& tx: txs)
1463  arg.b.txs.push_back(tx);
1464 
1465  m_pprotocol->relay_block(arg, exclude_context);
1466 
1467  if(m_fallback_to_pow) {
1468  m_miner.resume();
1469  }
1470  } else {
1471  update_miner_block_template();
1472  m_miner.resume();
1473  }
1474  return true;
1475  }
1476  //-----------------------------------------------------------------------------------------------
1478  {
1479  m_miner.on_synchronized();
1480  }
1481  //-----------------------------------------------------------------------------------------------
1482  void core::safesyncmode(const bool onoff)
1483  {
1484  m_blockchain_storage.safesyncmode(onoff);
1485  }
1486  //-----------------------------------------------------------------------------------------------
1487  bool core::add_new_block(const block& b, block_verification_context& bvc)
1488  {
1489  return m_blockchain_storage.add_new_block(b, bvc);
1490  }
1491 
1492  //-----------------------------------------------------------------------------------------------
1493  bool core::prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks)
1494  {
1495  m_incoming_tx_lock.lock();
1496  if (!m_blockchain_storage.prepare_handle_incoming_blocks(blocks_entry, blocks))
1497  {
1499  return false;
1500  }
1501  return true;
1502  }
1503 
1504  //-----------------------------------------------------------------------------------------------
1506  {
1507  bool success = false;
1508  try {
1509  success = m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync);
1510  }
1511  catch (...) {}
1512  m_incoming_tx_lock.unlock();
1513  return success;
1514  }
1515 
1516  //-----------------------------------------------------------------------------------------------
1517  bool core::handle_incoming_block(const blobdata& block_blob, const block *b, block_verification_context& bvc, bool update_miner_blocktemplate)
1518  {
1519  TRY_ENTRY();
1520 
1521  bvc = boost::value_initialized<block_verification_context>();
1522 
1523  if (!check_incoming_block_size(block_blob))
1524  {
1525  bvc.m_verification_failed = true;
1526  return false;
1527  }
1528 
1529  if (((size_t)-1) <= 0xffffffff && block_blob.size() >= 0x3fffffff)
1530  MWARNING("This block's size is " << block_blob.size() << ", closing on the 32 bit limit");
1531 
1532  // load json & DNS checkpoints every 10min/hour respectively,
1533  // and verify them with respect to what blocks we already have
1534  CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
1535 
1536  block lb;
1537  if (!b)
1538  {
1539  crypto::hash block_hash;
1540  if(!parse_and_validate_block_from_blob(block_blob, lb, block_hash))
1541  {
1542  LOG_PRINT_L1("Failed to parse and validate new block");
1543  bvc.m_verification_failed = true;
1544  return false;
1545  }
1546  b = &lb;
1547  }
1548 
1549  add_new_block(*b, bvc);
1550 
1551  if(bvc.m_added_to_main_chain) {
1552  m_miner.resume();
1553 
1554  if(update_miner_blocktemplate)
1555  update_miner_block_template();
1556  }
1557 
1558  return true;
1559 
1560  CATCH_ENTRY_L0("core::handle_incoming_block()", false);
1561  }
1562  //-----------------------------------------------------------------------------------------------
1563  // Used by the RPC server to check the size of an incoming
1564  // block_blob
1565  bool core::check_incoming_block_size(const blobdata& block_blob) const
1566  {
1567  // note: we assume block weight is always >= block blob size, so we check incoming
1568  // blob size against the block weight limit, which acts as a sanity check without
1569  // having to parse/weigh first; in fact, since the block blob is the block header
1570  // plus the tx hashes, the weight will typically be much larger than the blob size
1571  if(block_blob.size() > m_blockchain_storage.get_current_cumulative_block_weight_limit() + BLOCK_SIZE_SANITY_LEEWAY)
1572  {
1573  LOG_PRINT_L1("WRONG BLOCK BLOB, sanity check failed on size " << block_blob.size() << ", rejected");
1574  return false;
1575  }
1576  return true;
1577  }
1578  //-----------------------------------------------------------------------------------------------
1580  {
1581  return m_blockchain_storage.get_tail_id();
1582  }
1583  //-----------------------------------------------------------------------------------------------
1585  {
1586  return m_blockchain_storage.get_db().set_block_cumulative_difficulty(height, diff);
1587  }
1588  //-----------------------------------------------------------------------------------------------
1590  {
1591  return m_blockchain_storage.get_db().get_block_cumulative_difficulty(height);
1592  }
1593  //-----------------------------------------------------------------------------------------------
1595  {
1596  return m_mempool.get_transactions_count();
1597  }
1598  //-----------------------------------------------------------------------------------------------
1599  bool core::have_block(const crypto::hash& id) const
1600  {
1601  return m_blockchain_storage.have_block(id);
1602  }
1603  //-----------------------------------------------------------------------------------------------
1604  bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const
1605  {
1606  return parse_and_validate_tx_from_blob(blob, tx, tx_hash);
1607  }
1608  //-----------------------------------------------------------------------------------------------
1609  bool core::check_tx_syntax(const transaction& tx) const
1610  {
1611  return true;
1612  }
1613  //-----------------------------------------------------------------------------------------------
1614  bool core::get_pool_transactions(std::vector<transaction>& txs, bool include_sensitive_data) const
1615  {
1616  m_mempool.get_transactions(txs, include_sensitive_data);
1617  return true;
1618  }
1619  //-----------------------------------------------------------------------------------------------
1620  bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_data) const
1621  {
1622  m_mempool.get_transaction_hashes(txs, include_sensitive_data);
1623  return true;
1624  }
1625  //-----------------------------------------------------------------------------------------------
1626  bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const
1627  {
1628  m_mempool.get_transaction_stats(stats, include_sensitive_data);
1629  return true;
1630  }
1631  //-----------------------------------------------------------------------------------------------
1633  {
1634  return m_mempool.get_transaction(id, tx);
1635  }
1636  //-----------------------------------------------------------------------------------------------
1637  bool core::pool_has_tx(const crypto::hash &id) const
1638  {
1639  return m_mempool.have_tx(id);
1640  }
1641  //-----------------------------------------------------------------------------------------------
1643  {
1644  return m_mempool.utxo_spent_in_pool(in);
1645  }
1646  //-----------------------------------------------------------------------------------------------
1647  bool core::get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_sensitive_data) const
1648  {
1649  return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos, include_sensitive_data);
1650  }
1651  //-----------------------------------------------------------------------------------------------
1652  bool core::get_pool_for_rpc(std::vector<cryptonote::rpc::tx_in_pool>& tx_infos, cryptonote::rpc::key_images_with_tx_hashes& key_image_infos) const
1653  {
1654  return m_mempool.get_pool_for_rpc(tx_infos, key_image_infos);
1655  }
1656  //-----------------------------------------------------------------------------------------------
1657  bool core::get_short_chain_history(std::list<crypto::hash>& ids) const
1658  {
1659  return m_blockchain_storage.get_short_chain_history(ids);
1660  }
1661  //-----------------------------------------------------------------------------------------------
1663  {
1664  return m_blockchain_storage.handle_get_objects(arg, rsp);
1665  }
1666  //-----------------------------------------------------------------------------------------------
1668  {
1669  return m_blockchain_storage.get_block_id_by_height(height);
1670  }
1671  //-----------------------------------------------------------------------------------------------
1672  bool core::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
1673  {
1674  return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
1675  }
1676  //-----------------------------------------------------------------------------------------------
1677  std::string core::print_pool(bool short_format) const
1678  {
1679  return m_mempool.print_pool(short_format);
1680  }
1681  //-----------------------------------------------------------------------------------------------
1682  bool core::update_miner_block_template()
1683  {
1684  m_miner.on_block_chain_update();
1685  return true;
1686  }
1687  //-----------------------------------------------------------------------------------------------
1689  {
1690  if(!m_starter_message_showed)
1691  {
1692  std::string main_message;
1693  if (m_offline)
1694  main_message = "The daemon is running offline and will not attempt to sync to the Electroneum network.";
1695  else
1696  main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
1697  MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
1698  << main_message << ENDL
1699  << ENDL
1700  << "You can set the level of process detailization through \"set_log <level|categories>\" command," << ENDL
1701  << "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL
1702  << ENDL
1703  << "Use the \"help\" command to see the list of available commands." << ENDL
1704  << "Use \"help <command>\" to see a command's documentation." << ENDL
1705  << "**********************************************************************" << ENDL);
1706  m_starter_message_showed = true;
1707  }
1708  //Don't moan about forks for now, but keep implementation around incase we need to use it at a later stage
1709  //m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this));
1710  m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
1711  m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
1712  m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
1713  m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this));
1714  m_blockchain_pruning_interval.do_call(boost::bind(&core::update_blockchain_pruning, this));
1715  m_miner.on_idle();
1716  m_mempool.on_idle();
1717 
1718  if(!m_fallback_to_pow) {
1719  m_validators->on_idle();
1720  }
1721 
1722  return true;
1723  }
1724  //-----------------------------------------------------------------------------------------------
1725  bool core::check_fork_time()
1726  {
1727  if (m_nettype == FAKECHAIN)
1728  return true;
1729 
1730  HardFork::State state = m_blockchain_storage.get_hard_fork_state();
1731  const el::Level level = el::Level::Warning;
1732  switch (state) {
1734  MCLOG_RED(level, "global", "**********************************************************************");
1735  MCLOG_RED(level, "global", "Last scheduled hard fork is too far in the past.");
1736  MCLOG_RED(level, "global", "We are most likely forked from the network. Daemon update needed now.");
1737  MCLOG_RED(level, "global", "**********************************************************************");
1738  break;
1740  MCLOG_RED(level, "global", "**********************************************************************");
1741  MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed soon.");
1742  MCLOG_RED(level, "global", "**********************************************************************");
1743  break;
1744  default:
1745  break;
1746  }
1747  return true;
1748  }
1749  //-----------------------------------------------------------------------------------------------
1751  {
1753  }
1754  //-----------------------------------------------------------------------------------------------
1756  {
1758  }
1759  //-----------------------------------------------------------------------------------------------
1761  {
1763  }
1764  //-----------------------------------------------------------------------------------------------
1766  {
1768  }
1769  //-----------------------------------------------------------------------------------------------
1770  bool core::check_updates()
1771  {
1772  static const char software[] = "electroneum";
1773 #ifdef BUILD_TAG
1774  static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
1775  static const char subdir[] = "cli"; // because it can never be simple
1776 #else
1777  static const char buildtag[] = "source";
1778  static const char subdir[] = "source"; // because it can never be simple
1779 #endif
1780 
1781  if (m_offline)
1782  return true;
1783 
1784  if (check_updates_level == UPDATES_DISABLED)
1785  return true;
1786 
1788  MCDEBUG("updates", "Checking for a new " << software << " version for " << buildtag);
1789  if (!tools::check_updates(software, buildtag, version, hash))
1790  return false;
1791 
1792  if (tools::vercmp(version.c_str(), ELECTRONEUM_VERSION) <= 0)
1793  {
1794  m_update_available = false;
1795  return true;
1796  }
1797 
1798  std::string url = tools::get_update_url(software, subdir, buildtag, version, true);
1799  MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
1800  m_update_available = true;
1801 
1802  if (check_updates_level == UPDATES_NOTIFY) {
1803  std::vector<std::string> version_split;
1804  std::vector<std::string> latest_version_split;
1805 
1806  boost::split(version_split, ELECTRONEUM_VERSION, [](char c){return c == '.';});
1807  boost::split(latest_version_split, version, [](char c){return c == '.';});
1808 
1809  // Warninig message to update to lastest software case major version differs.
1810  // This should help users to update their node before a major update or fork.
1811  for(size_t i = 0; i < 2; i++) {
1812  if(version_split[i] != latest_version_split[i]) {
1813  MCLOG_RED(el::Level::Fatal, "global", "Please update your node to the latest software (v" << version << ").");
1814  break;
1815  }
1816  }
1817 
1818  return true;
1819  }
1820 
1821  url = tools::get_update_url(software, subdir, buildtag, version, false);
1822  std::string filename;
1823  const char *slash = strrchr(url.c_str(), '/');
1824  if (slash)
1825  filename = slash + 1;
1826  else
1827  filename = std::string(software) + "-update-" + version;
1828  boost::filesystem::path path(epee::string_tools::get_current_module_folder());
1829  path /= filename;
1830 
1831  boost::unique_lock<boost::mutex> lock(m_update_mutex);
1832 
1833  if (m_update_download != 0)
1834  {
1835  MCDEBUG("updates", "Already downloading update");
1836  return true;
1837  }
1838 
1839  crypto::hash file_hash;
1840  if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash)))
1841  {
1842  MCDEBUG("updates", "We don't have that file already, downloading");
1843  const std::string tmppath = path.string() + ".tmp";
1845  {
1846  MCDEBUG("updates", "We have part of the file already, resuming download");
1847  }
1848  m_last_update_length = 0;
1849  m_update_download = tools::download_async(tmppath, url, [this, hash, path](const std::string &tmppath, const std::string &uri, bool success) {
1850  bool remove = false, good = true;
1851  if (success)
1852  {
1853  crypto::hash file_hash;
1854  if (!tools::sha256sum(tmppath, file_hash))
1855  {
1856  MCERROR("updates", "Failed to hash " << tmppath);
1857  remove = true;
1858  good = false;
1859  }
1860  else if (hash != epee::string_tools::pod_to_hex(file_hash))
1861  {
1862  MCERROR("updates", "Download from " << uri << " does not match the expected hash");
1863  remove = true;
1864  good = false;
1865  }
1866  }
1867  else
1868  {
1869  MCERROR("updates", "Failed to download " << uri);
1870  good = false;
1871  }
1872  boost::unique_lock<boost::mutex> lock(m_update_mutex);
1873  m_update_download = 0;
1874  if (success && !remove)
1875  {
1876  std::error_code e = tools::replace_file(tmppath, path.string());
1877  if (e)
1878  {
1879  MCERROR("updates", "Failed to rename downloaded file");
1880  good = false;
1881  }
1882  }
1883  else if (remove)
1884  {
1885  if (!boost::filesystem::remove(tmppath))
1886  {
1887  MCERROR("updates", "Failed to remove invalid downloaded file");
1888  good = false;
1889  }
1890  }
1891  if (good)
1892  MCLOG_CYAN(el::Level::Info, "updates", "New version downloaded to " << path.string());
1893  }, [this](const std::string &path, const std::string &uri, size_t length, ssize_t content_length) {
1894  if (length >= m_last_update_length + 1024 * 1024 * 10)
1895  {
1896  m_last_update_length = length;
1897  MCDEBUG("updates", "Downloaded " << length << "/" << (content_length ? std::to_string(content_length) : "unknown"));
1898  }
1899  return true;
1900  });
1901  }
1902  else
1903  {
1904  MCDEBUG("updates", "We already have " << path << " with expected hash");
1905  }
1906 
1907  lock.unlock();
1908 
1909  if (check_updates_level == UPDATES_DOWNLOAD)
1910  return true;
1911 
1912  MCERROR("updates", "Download/update not implemented yet");
1913  return true;
1914  }
1915  //-----------------------------------------------------------------------------------------------
1916  bool core::check_disk_space()
1917  {
1918  uint64_t free_space = get_free_space();
1919  if (free_space < 1ull * 1024 * 1024 * 1024) // 1 GB
1920  {
1921  const el::Level level = el::Level::Warning;
1922  MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder);
1923  }
1924  return true;
1925  }
1926  //-----------------------------------------------------------------------------------------------
1927  double factorial(unsigned int n)
1928  {
1929  if (n <= 1)
1930  return 1.0;
1931  double f = n;
1932  while (n-- > 1)
1933  f *= n;
1934  return f;
1935  }
1936  //-----------------------------------------------------------------------------------------------
1937  static double probability1(unsigned int blocks, unsigned int expected)
1938  {
1939  // https://www.umass.edu/wsp/resources/poisson/#computing
1940  return pow(expected, blocks) / (factorial(blocks) * exp(expected));
1941  }
1942  //-----------------------------------------------------------------------------------------------
1943  static double probability(unsigned int blocks, unsigned int expected)
1944  {
1945  double p = 0.0;
1946  if (blocks <= expected)
1947  {
1948  for (unsigned int b = 0; b <= blocks; ++b)
1949  p += probability1(b, expected);
1950  }
1951  else if (blocks > expected)
1952  {
1953  for (unsigned int b = blocks; b <= expected * 3 /* close enough */; ++b)
1954  p += probability1(b, expected);
1955  }
1956  return p;
1957  }
1958  //-----------------------------------------------------------------------------------------------
1959  bool core::check_block_rate()
1960  {
1961  MDEBUG("Not checking block rate, not applicable.");
1962  return true;
1963 
1964  if (m_offline || m_nettype == FAKECHAIN || m_target_blockchain_height > get_current_blockchain_height())
1965  {
1966  MDEBUG("Not checking block rate, offline or syncing");
1967  return true;
1968  }
1969 
1970  static constexpr double threshold = 1. / (864000 / DIFFICULTY_TARGET_V6); // one false positive every 10 days
1971 
1972  const time_t now = time(NULL);
1973  const std::vector<time_t> timestamps = m_blockchain_storage.get_last_block_timestamps(60);
1974 
1975  static const unsigned int seconds[] = { 5400, 3600, 1800, 1200, 600 };
1976  for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n)
1977  {
1978  unsigned int b = 0;
1979  const time_t time_boundary = now - static_cast<time_t>(seconds[n]);
1980  for (time_t ts: timestamps) b += ts >= time_boundary;
1981  const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V6);
1982  MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
1983  if (p < threshold)
1984  {
1985  MWARNING("There were " << b << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Electroneum network or under attack. Or it could be just sheer bad luck.");
1986 
1987  std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
1988  if (block_rate_notify)
1989  {
1990  auto expected = seconds[n] / DIFFICULTY_TARGET_V6;
1991  block_rate_notify->notify("%t", std::to_string(seconds[n] / 60).c_str(), "%b", std::to_string(b).c_str(), "%e", std::to_string(expected).c_str(), NULL);
1992  }
1993 
1994  break; // no need to look further
1995  }
1996  }
1997 
1998  return true;
1999  }
2000  //-----------------------------------------------------------------------------------------------
2002  {
2003  return m_blockchain_storage.update_blockchain_pruning();
2004  }
2005  //-----------------------------------------------------------------------------------------------
2007  {
2008  return m_blockchain_storage.check_blockchain_pruning();
2009  }
2010  //-----------------------------------------------------------------------------------------------
2011  void core::set_target_blockchain_height(uint64_t target_blockchain_height)
2012  {
2013  m_target_blockchain_height = target_blockchain_height;
2014  }
2015  //-----------------------------------------------------------------------------------------------
2017  {
2018  return m_target_blockchain_height;
2019  }
2020  //-----------------------------------------------------------------------------------------------
2022  {
2023  boost::filesystem::path path(m_config_folder);
2024  boost::filesystem::space_info si = boost::filesystem::space(path);
2025  return si.available;
2026  }
2027  //-----------------------------------------------------------------------------------------------
2029  {
2031  }
2032  //-----------------------------------------------------------------------------------------------
2034  {
2035  return get_blockchain_storage().prune_blockchain(pruning_seed);
2036  }
2037  //-----------------------------------------------------------------------------------------------
2038  std::time_t core::get_start_time() const
2039  {
2040  return start_time;
2041  }
2042  //-----------------------------------------------------------------------------------------------
2044  bool is_validator_key_valid = std::count_if(key.begin(), key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
2045  if(!is_validator_key_valid || key.size() % 2 != 0) {
2046  return false;
2047  }
2048 
2049  m_miner.pause();
2050  m_blockchain_storage.set_validator_key(key);
2051  m_miner.resume();
2052 
2053  return true;
2054  }
2055  //-----------------------------------------------------------------------------------------------
2056  std::vector<std::string> core::generate_ed25519_keypair() {
2058  }
2059  //-----------------------------------------------------------------------------------------------
2060 
2062  std::string b_str = crypto::sign_message(msg, sk);
2063  return boost::algorithm::hex(b_str);
2064  }
2065  //-----------------------------------------------------------------------------------------------
2067  {
2069  return m_blockchain_storage.get_db().get_balance(combined_key);
2070  }
2071  //-----------------------------------------------------------------------------------------------
2072  std::vector<address_outputs> core::get_address_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id, const uint64_t &batch_size, bool desc)
2073  {
2075  return m_blockchain_storage.get_db().get_addr_output_batch(combined_key, start_tx_id, batch_size, desc);
2076  }
2077  //-----------------------------------------------------------------------------------------------
2078  std::vector<address_txs> core::get_addr_tx_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id, const uint64_t &batch_size, bool desc)
2079  {
2081  return m_blockchain_storage.get_db().get_addr_tx_batch(combined_key, start_tx_id, batch_size, desc);
2082  }
2083  //-----------------------------------------------------------------------------------------------
2085  {
2086  raise(SIGTERM);
2087  }
2088 }
void on_idle()
action to take periodically
Definition: tx_pool.cpp:758
const char * res
Definition: hmac_keccak.cpp:41
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 get_test_drop_download() const
gets whether or not to drop blocks (for testing)
#define MERROR(x)
Definition: misc_log_ex.h:73
virtual bool relay_block(NOTIFY_NEW_BLOCK::request &arg, cryptonote_connection_context &exclude_context)=0
uint64_t get_current_cumulative_block_weight_limit() const
gets the block weight limit based on recent blocks
uint8_t get_hard_fork_version(uint64_t height) const
return the hard fork version for a given block height
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
void stop()
stops the daemon running
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
key curveOrder()
Definition: rctOps.h:76
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
std::vector< crypto::hash > tx_hashes
void test_drop_download_height(uint64_t height)
sets to drop blocks downloaded below a certain height
bool get_tx_fee(const transaction &tx, uint64_t &fee)
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
bool deinit()
performs safe shutdown steps for core and core components
bool get_split_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
void set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold, blockchain_db_sync_mode sync_mode, bool fast_sync, std::string validator_key)
Update the validators public key by fetching data from electroneum&#39;s endpoint.
uint32_t get_blockchain_pruning_seed() const
get the blockchain pruning seed
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request &arg, NOTIFY_RESPONSE_GET_OBJECTS::request &rsp, cryptonote_connection_context &context)
retrieves a set of blocks and their transactions, and possibly other transactions ...
#define MTRACE(x)
Definition: misc_log_ex.h:77
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
bool init(const boost::program_options::variables_map &vm, const test_options *test_options=NULL, const GetCheckpointsCallback &get_checkpoints=nullptr)
initializes the core as needed
bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context &tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
Definition: tx_pool.cpp:122
void test_drop_download()
sets to drop blocks downloaded (for testing)
bool check_outs_valid(const transaction &tx)
#define MERROR_VER(x)
virtual std::vector< address_outputs > get_addr_output_batch(const crypto::public_key &combined_key, uint64_t start_db_index=0, uint64_t batch_size=100, bool desc=false)=0
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define DBF_SALVAGE
bool utxo_nonexistence_from_output(const txin_to_key_public &public_output) const
check if a single utxo in a transaction has already been spent using the hash and out index (v3 tx on...
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
bool prepare_handle_incoming_blocks(const std::vector< block_complete_entry > &blocks_entry, std::vector< block > &blocks)
performs some preprocessing on a group of incoming blocks to speed up verification ...
std::string sign_message(std::string sk, std::string msg)
bool on_idle()
Definition: miner.cpp:178
::std::string string
Definition: gtest-port.h:1097
uint64_t get_outs_etn_amount(const transaction &tx)
A global thread pool.
Definition: threadpool.h:43
bool get_stat_info(core_stat_info &st_inf) const
gets some stats about the daemon
const command_line::arg_descriptor< size_t > arg_block_download_max_size
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
void get_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
Definition: tx_pool.cpp:904
#define DBF_FASTEST
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
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_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request &req, COMMAND_RPC_GET_OUTPUTS_BIN::response &res) const
gets specific outputs to mix with
bool handle_incoming_txs(const std::vector< blobdata > &tx_blobs, std::vector< tx_verification_context > &tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
handles a list of incoming transactions
uint64_t height
Definition: blockchain.cpp:91
user didn&#39;t specify, use db_async
Definition: blockchain.h:79
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 ...
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
Definition: updates.cpp:101
void get_transaction_hashes(std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
get a list of all transaction hashes in the pool
Definition: tx_pool.cpp:923
std::vector< blobdata > txs
Severe error information that will presumably abort application.
void set_validators_list_instance(std::unique_ptr< electroneum::basic::Validators > &v)
Definition: blockchain.h:1066
std::string print_pool(bool short_format) const
get a string containing human-readable pool information
bool set_validator_key(std::string key)
set validator key
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
const char * key
Definition: hmac_keccak.cpp:39
bool are_key_images_spent_in_pool(const std::vector< crypto::key_image > &key_im, std::vector< bool > &spent) const
check if multiple key images are spent in the transaction pool
#define MCLOG_RED(level, cat, x)
Definition: misc_log_ex.h:58
handle syncing calls instead of the backing db, synchronously
Definition: blockchain.h:80
std::function< const epee::span< const unsigned char >cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
Definition: blockchain.h:92
virtual uint64_t get_balance(const crypto::public_key &combined_key)=0
void set_block_notify(const std::shared_ptr< tools::Notify > &notify)
sets a block notify object to call for every new block
Definition: blockchain.h:785
const command_line::arg_descriptor< std::string > arg_db_sync_mode
static const std::vector< HardFork::Params > & get_hard_fork_heights(network_type nettype)
gets the hardfork heights of given network
const command_line::arg_descriptor< bool, false > arg_stagenet_on
unsigned int & g_test_dbg_lock_sleep()
Definition: syncobj.h:45
void set_enforce_dns_checkpoints(bool enforce)
configure whether or not to enforce DNS-based checkpoints
public_key addKeys(const public_key &A, const public_key &B)
Definition: crypto.h:339
#define DBF_SAFE
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
return the earliest block a given version may activate
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block&#39;s hash given a height
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block&#39;s cumulative difficulty
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &exclude_context)=0
#define JSON_HASH_FILE_NAME
Definition: checkpoints.h:39
#define DEFAULT_TXPOOL_MAX_WEIGHT
bool is_file_exist(const std::string &path)
Definition: file_io_utils.h:66
unsigned char uint8_t
Definition: stdint.h:124
difficulty_type get_block_cumulative_difficulty(uint64_t height) const
bool pool_has_tx(const crypto::hash &txid) const
checks if the pool has a transaction with the given hash
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
static threadpool & getInstance()
Definition: threadpool.h:46
Level
Represents enumeration for severity level used to determine level of logging.
block_complete_entry get_block_complete_entry(block &b, tx_memory_pool &pool)
boost::filesystem::path data_dir
Definition: main.cpp:50
uint8_t type
Definition: rctTypes.h:241
std::string & trim(std::string &str)
Definition: string_tools.h:288
size_t get_transactions_count(bool include_unrelayed_txes=true) const
get the total number of transactions in the pool
Definition: tx_pool.cpp:897
#define DBF_FAST
std::unordered_map< crypto::key_image, std::vector< crypto::hash > > key_images_with_tx_hashes
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE
bool init(const boost::program_options::variables_map &vm, network_type nettype, bool fallback_to_pow=false)
Definition: miner.cpp:291
static void init_options(boost::program_options::options_description &desc)
Definition: miner.cpp:279
#define MGINFO(x)
Definition: misc_log_ex.h:80
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
bool isValidatorsListValid()
get Validators List state
void set_checkpoints(checkpoints &&chk_pts)
assign a set of blockchain checkpoint hashes
Definition: blockchain.h:175
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 ...
virtual bool handle_block_found(block &b, block_verification_context &bvc)
stores and relays a block found by a miner
virtual std::vector< address_txs > get_addr_tx_batch(const crypto::public_key &combined_key, uint64_t start_db_index=0, uint64_t batch_size=100, bool desc=false)=0
bool utxo_nonexistant(const std::vector< txin_to_key_public > &public_outputs, std::vector< bool > &spent) const
check if multiple public outputs are found in the utxo database or not
void set_reorg_notify(const std::shared_ptr< tools::Notify > &notify)
sets a reorg notify object to call for every reorg
Definition: blockchain.h:792
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
Definition: blockchain.cpp:859
#define MDEBUG(x)
Definition: misc_log_ex.h:76
bool update_checkpoints(const std::string &file_path, bool check_dns)
loads new checkpoints from a file and optionally from DNS
std::string get_default_data_dir()
Returns the default data directory.
Definition: util.cpp:600
bool init(size_t max_txpool_weight=0)
loads pool state (if any) from disk, and initializes pool
Definition: tx_pool.cpp:1731
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
size_t get_total_transactions() const
gets the total number of transactions on the main chain
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
Definition: options.h:86
const command_line::arg_descriptor< difficulty_type > arg_fixed_difficulty
return true
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block&#39;s cumulative difficulty
electroneum::basic::list_update_outcome set_validators_list(std::string v_list, bool isEmergencyUpdate)
set the list of validators according to the serialized string passed in as parameter ...
bool handle_incoming_tx(const blobdata &tx_blob, tx_verification_context &tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
handles an incoming transaction
mdb_size_t count(MDB_cursor *cur)
size_t validate(uint8_t version)
remove transactions from the pool which are no longer valid
Definition: tx_pool.cpp:1667
bool cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
time_t time
Definition: blockchain.cpp:93
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
const command_line::arg_descriptor< bool, false > arg_testnet_on
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
BlockchainDB * new_db(const std::string &db_type)
bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash)
Definition: updates.cpp:41
void set_cryptonote_protocol(i_cryptonote_protocol *pprotocol)
set the pointer to the cryptonote protocol object to use
const command_line::arg_descriptor< bool > arg_disable_dns_checkpoints
#define TRY_ENTRY()
Definition: misc_log_ex.h:151
unsigned int uint32_t
Definition: stdint.h:126
#define DIFFICULTY_TARGET_V6
bool on_block_chain_update()
Definition: miner.cpp:148
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
virtual bool get_block_template(block &b, const account_public_address &adr, difficulty_type &diffic, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
creates a new block to mine against
bool get_pool_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
void set_enforce_dns_checkpoints(bool enforce_dns)
set whether or not we enforce DNS checkpoints
bool check_inputs_types_supported(const transaction &tx)
bool get_block_hash(const block &b, crypto::hash &res)
#define BLOCK_SIZE_SANITY_LEEWAY
bool on_idle()
calls various idle routines
i_cryptonote_protocol * get_protocol()
get the cryptonote protocol instance
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
void set_checkpoints(checkpoints &&chk_pts)
assign a set of blockchain checkpoint hashes
void graceful_exit()
tells the daemon to wind down operations and stop running
void get_blockchain_top(uint64_t &height, crypto::hash &top_id) const
get the hash and height of the most recent block
HardFork::State get_hard_fork_state() const
gets the hardfork voting state object
uint64_t get_target_blockchain_height() const
gets the target blockchain height
bool get_pool_transaction_stats(struct txpool_stats &stats, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
void set_show_time_stats(bool stats)
set whether or not to show/print time statistics
Definition: blockchain.h:804
blockchain_db_sync_mode
Definition: blockchain.h:77
bool get_pool_transaction(const crypto::hash &id, cryptonote::blobdata &tx) const
get a specific transaction from the pool
bool prune_blockchain(uint32_t pruning_seed=0)
unsigned __int64 uint64_t
Definition: stdint.h:136
bool check_blockchain_pruning()
checks the blockchain pruning if enabled
bool get_test_drop_download_height() const
gets whether or not to drop blocks
const char *const ELECTRONEUM_VERSION
#define MGINFO_YELLOW(x)
Definition: misc_log_ex.h:83
const command_line::arg_descriptor< std::string, false, true, 2 > arg_data_dir
bool reset_and_set_genesis_block(const block &b)
clears the blockchain and starts a new one
Definition: blockchain.cpp:812
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
void set_relayed(const std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &txs)
tell the pool that certain transactions were just relayed
Definition: tx_pool.cpp:870
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
Definition: zmq.h:98
bool update_checkpoints()
tells the Blockchain to update its checkpoints
bool get_transactions_and_spent_keys_info(std::vector< tx_info > &tx_infos, std::vector< spent_key_image_info > &key_image_infos, bool include_sensitive_data=true) const
get information about all transactions and key images in the pool
Definition: tx_pool.cpp:1026
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
size_t get_block_sync_size(uint64_t height) const
get the number of blocks to sync in one go
static void init_options(boost::program_options::options_description &desc)
adds command line options to the given options set
bool get_txpool_backlog(std::vector< tx_backlog_entry > &backlog) const
std::error_code replace_file(const std::string &old_name, const std::string &new_name)
std::rename wrapper for nix and something strange for windows.
Definition: util.cpp:648
blobdata block
#define false
Definition: stdbool.h:38
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
void set_target_blockchain_height(uint64_t target_blockchain_height)
sets the target blockchain height
void get_transaction_backlog(std::vector< tx_backlog_entry > &backlog, bool include_unrelayed_txes=true) const
get (weight, fee, receive time) for all transaction in the pool
Definition: tx_pool.cpp:934
void on_new_tx_from_block(const cryptonote::transaction &tx)
called when we see a tx originating from a block
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash)
Definition: util.cpp:933
bool set_genesis_block(const block &b)
clears the blockchain and starts a new one
const command_line::arg_descriptor< std::string > arg_db_type
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool update_blockchain_pruning()
incrementally prunes blockchain
std::string & get_current_module_folder()
Definition: string_tools.h:233
uint64_t get_speed() const
Definition: miner.cpp:428
POD_CLASS public_key
Definition: crypto.h:76
Useful when application has potentially harmful situtaions.
version
Supported socks variants.
Definition: socks.h:57
#define MWARNING(x)
Definition: misc_log_ex.h:74
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Definition: command_line.h:188
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
Definition: blockchain.h:963
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
virtual void on_transaction_relayed(const cryptonote::blobdata &tx)
called when a transaction is relayed
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
bool handle_incoming_block(const blobdata &block_blob, const block *b, block_verification_context &bvc, bool update_miner_blocktemplate=true)
handles an incoming block
bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
Definition: blockchain.cpp:177
const command_line::arg_descriptor< bool > arg_offline
bool check_for_key_images(const std::vector< crypto::key_image > &key_images, std::vector< bool > spent) const
check for presence of key images in the pool
Definition: tx_pool.cpp:1151
size_t get_pool_transactions_count() const
get the total number of transactions in the pool
bool is_key_image_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
Transaction pool, handles transactions which are not part of a block.
Definition: tx_pool.h:94
std::string blobdata
Definition: blobdatatype.h:39
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block&#39;s hash given a height
Definition: blockchain.cpp:901
expect< void > success() noexcept
Definition: expect.h:397
#define HF_VERSION_ENFORCE_RCT
bool download_cancel(const download_async_handle &control)
Definition: download.cpp:299
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1017
A generic BlockchainDB exception.
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
Mainly useful to represent current progress of application.
bool deinit()
attempts to save the transaction pool state to disk
Definition: tx_pool.cpp:1800
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
key identity()
Definition: rctOps.h:73
Blockchain & get_blockchain_storage()
gets the Blockchain instance
const T & move(const T &t)
Definition: gtest-port.h:1317
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
Definition: blockchain.cpp:167
void set_checkpoints_file_path(const std::string &path)
set the file path to read from when loading checkpoints
const command_line::arg_descriptor< bool > arg_fallback_to_pow
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4
#define ENDL
Definition: misc_log_ex.h:149
bool get_transaction(const crypto::hash &h, cryptonote::blobdata &txblob) const
get a specific transaction from the pool
Definition: tx_pool.cpp:1166
Definition: blake256.h:37
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
uint64_t get_free_space() const
get free disk space on the blockchain partition
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
POD_CLASS key_image
Definition: crypto.h:102
std::string get_validators_list()
Get a serialized representation of the list of validators.
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
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
const command_line::arg_descriptor< bool > arg_addr_db_salvage
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition: blockchain.h:832
#define HF_VERSION_PUBLIC_TX
const command_line::arg_descriptor< bool > arg_skip_block_sig_verification
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition: blockchain.h:858
crypto::hash get_transaction_hash(const transaction &t)
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
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
#define MCLOG_CYAN(level, cat, x)
Definition: misc_log_ex.h:63
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition: tx_pool.cpp:1196
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
bool check_etn_overflow(const transaction &tx)
const command_line::arg_descriptor< bool > arg_db_salvage
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
static void init_options(boost::program_options::options_description &desc)
init command line options
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
std::vector< std::string > generate_ed25519_keypair()
bool utxo_spent_in_pool(const txin_to_key_public &in) const
get a summary statistics of all transaction hashes in the pool
Definition: tx_pool.cpp:1220
const command_line::arg_descriptor< bool > arg_regtest_on
bool init(BlockchainDB *db, const network_type nettype=MAINNET, bool offline=false, const cryptonote::test_options *test_options=NULL, difficulty_type fixed_difficulty=0, const GetCheckpointsCallback &get_checkpoints=nullptr, bool ignore_bsig=false, bool fallback_to_pow=false)
Initialize the Blockchain state.
Definition: blockchain.cpp:334
double factorial(unsigned int n)
std::vector< address_txs > get_addr_tx_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id=0, const uint64_t &batch_size=100, bool desc=false)
DISABLE_VS_WARNINGS(4244 4345 4503) using namespace crypto
POD_CLASS hash
Definition: hash.h:50
std::vector< std::string > create_ed25519_keypair()
Definition: crypto.h:388
const command_line::arg_descriptor< uint64_t > arg_fallback_to_pow_checkpoint_height
bool prune_blockchain(uint32_t pruning_seed=0)
prune the blockchain
#define MCDEBUG(cat, x)
Definition: misc_log_ex.h:54
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
A container for blockchain checkpoints.
Definition: checkpoints.h:51
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:928
const command_line::arg_descriptor< std::string > arg_fallback_to_pow_checkpoint_hash
std::string to_string(t_connection_type type)
bool are_key_images_spent(const std::vector< crypto::key_image > &key_im, std::vector< bool > &spent) const
check if multiple key images are spent
bool get_split_transactions_blobs(const std::vector< crypto::hash > &txs_ids, std::vector< std::tuple< crypto::hash, cryptonote::blobdata, crypto::hash, cryptonote::blobdata >> &txs, std::vector< crypto::hash > &missed_txs) const
const unsigned char checkpoints[]
bool get_pool_transactions_and_spent_keys_info(std::vector< tx_info > &tx_infos, std::vector< spent_key_image_info > &key_image_infos, bool include_unrelayed_txes=true) const
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.h:376
std::shared_ptr< download_thread_control > download_async_handle
Definition: download.h:36
blobdata block_to_blob(const block &b)
std::vector< address_outputs > get_address_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id=0, const uint64_t &batch_size=100, bool desc=false)
bool pool_has_utxo_as_spent(const txin_to_key_public &in) const
get a summary statistics of all transaction hashes in the pool
epee::misc_utils::struct_init< request_t > request
#define DBF_ADDR_TX_SALVAGE
void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)
#define CATCH_ENTRY_L0(lacation, return_val)
Definition: misc_log_ex.h:165
bool get_transactions(const std::vector< crypto::hash > &txs_ids, std::vector< cryptonote::blobdata > &txs, std::vector< crypto::hash > &missed_txs) const
bool get_pool_for_rpc(std::vector< cryptonote::rpc::tx_in_pool > &tx_infos, cryptonote::rpc::key_images_with_tx_hashes &key_image_infos) const
get information about all transactions and key images in the pool
std::pair< uint64_t, uint64_t > get_coinbase_tx_sum(const uint64_t start_offset, const size_t count)
get the sum of coinbase tx amounts between blocks
bool check_incoming_block_size(const blobdata &block_blob) const
check the size of a block against the current maximum
void get_transaction_stats(struct txpool_stats &stats, bool include_unrelayed_txes=true) const
get a summary statistics of all transaction hashes in the pool
Definition: tx_pool.cpp:946
void on_synchronized()
Definition: miner.cpp:494
bool do_call(functor_t functr)
Definition: math_helper.h:263
const char * what() const
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request &resp) const
get recent block hashes for a foreign chain
bool verRctSemanticsSimple(const std::vector< const rctSig *> &rvv)
Definition: rctSigs.cpp:975
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition: command_line.h:265
bool deinit()
Uninitializes the blockchain state.
Definition: blockchain.cpp:660
uint64_t get_block_height(const block &b)
bool get_pool_for_rpc(std::vector< cryptonote::rpc::tx_in_pool > &tx_infos, cryptonote::rpc::key_images_with_tx_hashes &key_image_infos) const
get information about all transactions and key images in the pool
Definition: tx_pool.cpp:1102
rapidjson::Document json
Definition: transport.cpp:49
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
returns the earliest block a given version may activate
Definition: blockchain.h:865
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
download_async_handle download_async(const std::string &path, const std::string &url, std::function< void(const std::string &, const std::string &, bool)> result, std::function< bool(const std::string &, const std::string &, size_t, ssize_t)> progress)
Definition: download.cpp:266
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
void set_validator_key(std::string key)
set validator key
Definition: blockchain.h:1064
std::string print_pool(bool short_format) const
get a string containing human-readable pool information
Definition: tx_pool.cpp:1502
std::vector< time_t > get_last_block_timestamps(unsigned int blocks) const
returns the timestamps of the last N blocks
bool for_blocks_range(const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const block &)>) const
perform a check on all blocks in the blockchain in the given range
bool cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
#define BAD_SEMANTICS_TXES_MAX_SIZE
bool get_relayable_transactions(std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &txs) const
get a list of all relayable transactions and their hashes
Definition: tx_pool.cpp:836
size_t get_blockchain_total_transactions() const
gets the total number of transactions on the main chain
int vercmp(const char *v0, const char *v1)
Definition: util.cpp:915
uint64_t get_balance(const address_parse_info &addr)
std::time_t get_start_time() const
gets start_time
uint8_t threshold
Definition: blockchain.cpp:92
bool get_pool_transaction_hashes(std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool