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)
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 fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
517  uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
518  std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
519  size_t max_txpool_weight = command_line::get_arg(vm, arg_max_txpool_weight);
520  bool prune_blockchain = command_line::get_arg(vm, arg_prune_blockchain);
521  std::string validator_key = command_line::get_arg(vm, arg_validator_key);
522 
523  bool is_validator_key_valid = std::count_if(validator_key.begin(), validator_key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
524  if(!is_validator_key_valid || validator_key.size() % 2 != 0) {
525  validator_key.clear();
526  }
527 
528  boost::filesystem::path folder(m_config_folder);
529  if (m_nettype == FAKECHAIN)
530  folder /= "fake";
531 
532  // make sure the data directory exists, and try to lock it
533  CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false,
534  std::string("Failed to create directory ").append(folder.string()).c_str());
535 
536  // check for blockchain.bin
537  try
538  {
539  const boost::filesystem::path old_files = folder;
540  if (boost::filesystem::exists(old_files / "blockchain.bin"))
541  {
542  MWARNING("Found old-style blockchain.bin in " << old_files.string());
543  MWARNING("Electroneum now uses a new format. You can either remove blockchain.bin to start syncing");
544  MWARNING("the blockchain anew, or use electroneum-blockchain-export and electroneum-blockchain-import to");
545  MWARNING("convert your existing blockchain.bin to the new format. See README.md for instructions.");
546  return false;
547  }
548  }
549  // folder might not be a directory, etc, etc
550  catch (...) { }
551 
552  std::unique_ptr<BlockchainDB> db(new_db(db_type));
553  if (db == NULL)
554  {
555  LOG_ERROR("Attempted to use non-existent database type");
556  return false;
557  }
558 
559  folder /= db->get_db_name();
560  MGINFO("Loading blockchain from folder " << folder.string() << " ...");
561 
562  const std::string filename = folder.string();
563  // default to fast:async:1 if overridden
565  bool sync_on_blocks = true;
566  uint64_t sync_threshold = 1;
567 
568  if (m_nettype == FAKECHAIN)
569  {
570  // reset the db by removing the database file before opening it
571  if (!db->remove_data_file(filename))
572  {
573  MERROR("Failed to remove data file in " << filename);
574  return false;
575  }
576  }
577 
578  try
579  {
580  uint64_t db_flags = 0;
581 
582  std::vector<std::string> options;
583  boost::trim(db_sync_mode);
584  boost::split(options, db_sync_mode, boost::is_any_of(" :"));
585  const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode);
586 
587  for(const auto &option : options)
588  MDEBUG("option: " << option);
589 
590  // default to fast:async:1
591  uint64_t DEFAULT_FLAGS = DBF_FAST;
592 
593  if(options.size() == 0)
594  {
595  // default to fast:async:1
596  db_flags = DEFAULT_FLAGS;
597  }
598 
599  bool safemode = false;
600  if(options.size() >= 1)
601  {
602  if(options[0] == "safe")
603  {
604  safemode = true;
605  db_flags = DBF_SAFE;
606  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_nosync;
607  }
608  else if(options[0] == "fast")
609  {
610  db_flags = DBF_FAST;
611  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
612  }
613  else if(options[0] == "fastest")
614  {
615  db_flags = DBF_FASTEST;
616  sync_threshold = 1000; // default to fastest:async:1000
617  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
618  }
619  else
620  db_flags = DEFAULT_FLAGS;
621  }
622 
623  if(options.size() >= 2 && !safemode)
624  {
625  if(options[1] == "sync")
626  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_sync;
627  else if(options[1] == "async")
628  sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
629  }
630 
631  if(options.size() >= 3 && !safemode)
632  {
633  char *endptr;
634  uint64_t threshold = strtoull(options[2].c_str(), &endptr, 0);
635  if (*endptr == '\0' || !strcmp(endptr, "blocks"))
636  {
637  sync_on_blocks = true;
638  sync_threshold = threshold;
639  }
640  else if (!strcmp(endptr, "bytes"))
641  {
642  sync_on_blocks = false;
643  sync_threshold = threshold;
644  }
645  else
646  {
647  LOG_ERROR("Invalid db sync mode: " << options[2]);
648  return false;
649  }
650  }
651 
652  if (db_salvage)
653  db_flags |= DBF_SALVAGE;
654 
655  db->open(filename, db_flags);
656  if(!db->m_open)
657  return false;
658  }
659  catch (const DB_ERROR& e)
660  {
661  LOG_ERROR("Error opening database: " << e.what());
662  return false;
663  }
664 
665  m_blockchain_storage.set_user_options(blocks_threads,
666  sync_on_blocks, sync_threshold, sync_mode, fast_sync, validator_key);
667 
668  try
669  {
670  if (!command_line::is_arg_defaulted(vm, arg_block_notify))
671  m_blockchain_storage.set_block_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_block_notify).c_str())));
672  }
673  catch (const std::exception &e)
674  {
675  MERROR("Failed to parse block notify spec: " << e.what());
676  }
677 
678  try
679  {
680  if (!command_line::is_arg_defaulted(vm, arg_reorg_notify))
681  m_blockchain_storage.set_reorg_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_reorg_notify).c_str())));
682  }
683  catch (const std::exception &e)
684  {
685  MERROR("Failed to parse reorg notify spec: " << e.what());
686  }
687 
688  try
689  {
690  if (!command_line::is_arg_defaulted(vm, arg_block_rate_notify))
691  m_block_rate_notify.reset(new tools::Notify(command_line::get_arg(vm, arg_block_rate_notify).c_str()));
692  }
693  catch (const std::exception &e)
694  {
695  MERROR("Failed to parse block rate notify spec: " << e.what());
696  }
697 
698  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)};
699  const cryptonote::test_options regtest_test_options = {
700  regtest_hard_forks,
701  0
702  };
703  const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty);
704  const bool ignore_bsig = command_line::get_arg(vm, arg_skip_block_sig_verification);
705 
706  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);
707 
708  r = m_mempool.init(max_txpool_weight);
709  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
710 
711  // now that we have a valid m_blockchain_storage, we can clean out any
712  // transactions in the pool that do not conform to the current fork
713  m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
714 
715  bool show_time_stats = command_line::get_arg(vm, arg_show_time_stats) != 0;
716  m_blockchain_storage.set_show_time_stats(show_time_stats);
717  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
718 
719  block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
720 
721  MGINFO("Loading checkpoints");
722 
723  // load json & DNS checkpoints, and verify them
724  // with respect to what blocks we already have
725  CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
726 
727  // DNS versions checking
728  if (check_updates_string == "disabled")
729  check_updates_level = UPDATES_DISABLED;
730  else if (check_updates_string == "notify")
731  check_updates_level = UPDATES_NOTIFY;
732  else if (check_updates_string == "download")
733  check_updates_level = UPDATES_DOWNLOAD;
734  else if (check_updates_string == "update")
735  check_updates_level = UPDATES_UPDATE;
736  else {
737  MERROR("Invalid argument to --dns-versions-check: " << check_updates_string);
738  return false;
739  }
740 
741  check_updates_level = UPDATES_DISABLED;
742 
743  r = m_miner.init(vm, m_nettype, m_fallback_to_pow);
744  CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance");
745 
746  if (prune_blockchain)
747  {
748  // display a message if the blockchain is not pruned yet
749  if (!m_blockchain_storage.get_blockchain_pruning_seed())
750  {
751  MGINFO("Pruning blockchain...");
752  CHECK_AND_ASSERT_MES(m_blockchain_storage.prune_blockchain(), false, "Failed to prune blockchain");
753  }
754  else
755  {
756  CHECK_AND_ASSERT_MES(m_blockchain_storage.update_blockchain_pruning(), false, "Failed to update blockchain pruning");
757  }
758  }
759 
760  if(!m_fallback_to_pow) {
761  m_validators = std::unique_ptr<electroneum::basic::Validators>(new electroneum::basic::Validators(m_blockchain_storage.get_db(), m_pprotocol, m_nettype == TESTNET));
762  m_blockchain_storage.set_validators_list_instance(m_validators);
763 
764  if(m_blockchain_storage.get_current_blockchain_height() >= ((m_nettype == TESTNET ? 446674 : 589169) - 720 )) { //V8 Height - 1 day
765  m_validators->enable();
766  }
767  }
768 
769  return load_state_data();
770  }
771  //-----------------------------------------------------------------------------------------------
773  {
774  return m_blockchain_storage.reset_and_set_genesis_block(b);
775  }
776  //-----------------------------------------------------------------------------------------------
777  bool core::load_state_data()
778  {
779  // may be some code later
780  return true;
781  }
782  //-----------------------------------------------------------------------------------------------
784  {
785  m_miner.stop();
786  m_mempool.deinit();
787  m_blockchain_storage.deinit();
788  return true;
789  }
790  //-----------------------------------------------------------------------------------------------
792  {
793  m_test_drop_download = false;
794  }
795  //-----------------------------------------------------------------------------------------------
797  {
798  m_test_drop_download_height = height;
799  }
800  //-----------------------------------------------------------------------------------------------
802  {
803  return m_test_drop_download;
804  }
805  //-----------------------------------------------------------------------------------------------
807  {
808  if (m_test_drop_download_height == 0)
809  return true;
810 
811  if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height)
812  return true;
813 
814  return false;
815  }
816  //-----------------------------------------------------------------------------------------------
817  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)
818  {
819  tvc = boost::value_initialized<tx_verification_context>();
820 
821  if(tx_blob.size() > get_max_tx_size())
822  {
823  LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected");
824  tvc.m_verification_failed = true;
825  tvc.m_too_big = true;
826  return false;
827  }
828 
829  tx_hash = crypto::null_hash;
830 
831  if(!parse_tx_from_blob(tx, tx_hash, tx_blob))
832  {
833  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected");
834  tvc.m_verification_failed = true;
835  return false;
836  }
837  //std::cout << "!"<< tx.vin.size() << std::endl;
838 
839  bad_semantics_txes_lock.lock();
840  for (int idx = 0; idx < 2; ++idx)
841  {
842  if (bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end())
843  {
844  bad_semantics_txes_lock.unlock();
845  LOG_PRINT_L1("Transaction already seen with bad semantics, rejected");
846  tvc.m_verification_failed = true;
847  return false;
848  }
849  }
850  bad_semantics_txes_lock.unlock();
851 
852  uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
853 
854  const size_t max_tx_version = version < HF_VERSION_PUBLIC_TX ? 1 : 3;
855  if (tx.version == 0 || tx.version > max_tx_version)
856  {
857  // v2 is the latest one we know
858  tvc.m_verification_failed = true;
859  return false;
860  }
861 
862  const size_t min_tx_version = version >= HF_VERSION_PUBLIC_TX ? 2 : 1;
863  if (tx.version < min_tx_version)
864  {
865  tvc.m_verification_failed = true;
866  return false;
867  }
868 
869  return true;
870  }
871  //-----------------------------------------------------------------------------------------------
872  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)
873  {
874  if(!check_tx_syntax(tx))
875  {
876  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected");
877  tvc.m_verification_failed = true;
878  return false;
879  }
880 
881  return true;
882  }
883  //-----------------------------------------------------------------------------------------------
884  void core::set_semantics_failed(const crypto::hash &tx_hash)
885  {
886  LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
887  bad_semantics_txes_lock.lock();
888  bad_semantics_txes[0].insert(tx_hash);
889  if (bad_semantics_txes[0].size() >= BAD_SEMANTICS_TXES_MAX_SIZE)
890  {
891  std::swap(bad_semantics_txes[0], bad_semantics_txes[1]);
892  bad_semantics_txes[0].clear();
893  }
894  bad_semantics_txes_lock.unlock();
895  }
896  //-----------------------------------------------------------------------------------------------
897  bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block)
898  {
899  bool ret = true;
900  if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
901  {
902  MTRACE("Skipping semantics check for tx kept by block in embedded hash area");
903  return true;
904  }
905 
906  std::vector<const rct::rctSig*> rvv;
907  for (size_t n = 0; n < tx_info.size(); ++n)
908  {
909  if (!check_tx_semantic(*tx_info[n].tx, keeped_by_block))
910  {
911  set_semantics_failed(tx_info[n].tx_hash);
912  tx_info[n].tvc.m_verification_failed = true;
913  tx_info[n].result = false;
914  continue;
915  }
916  }
917  if (!rvv.empty() && !rct::verRctSemanticsSimple(rvv))
918  {
919  LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
920  ret = false;
921  const bool assumed_bad = rvv.size() == 1; // if there's only one tx, it must be the bad one
922  for (size_t n = 0; n < tx_info.size(); ++n)
923  {
924  if (!tx_info[n].result)
925  continue;
926  if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2)
927  continue;
928  if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
929  {
930  set_semantics_failed(tx_info[n].tx_hash);
931  tx_info[n].tvc.m_verification_failed = true;
932  tx_info[n].result = false;
933  }
934  }
935  }
936 
937  return ret;
938  }
939  //-----------------------------------------------------------------------------------------------
940  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)
941  {
942  TRY_ENTRY();
943  CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
944 
945  struct result { bool res; cryptonote::transaction tx; crypto::hash hash; };
946  std::vector<result> results(tx_blobs.size());
947 
948  tvc.resize(tx_blobs.size());
951  std::vector<blobdata>::const_iterator it = tx_blobs.begin();
952  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
953  tpool.submit(&waiter, [&, i, it] {
954  try
955  {
956  results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
957  }
958  catch (const std::exception &e)
959  {
960  MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what());
961  tvc[i].m_verification_failed = true;
962  results[i].res = false;
963  }
964  });
965  }
966  waiter.wait(&tpool);
967  it = tx_blobs.begin();
968  std::vector<bool> already_have(tx_blobs.size(), false);
969  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
970  if (!results[i].res)
971  continue;
972  if(m_mempool.have_tx(results[i].hash))
973  {
974  LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool");
975  already_have[i] = true;
976  }
977  else if(m_blockchain_storage.have_tx(results[i].hash))
978  {
979  LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain");
980  already_have[i] = true;
981  }
982  else
983  {
984  tpool.submit(&waiter, [&, i, it] {
985  try
986  {
987  results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
988  }
989  catch (const std::exception &e)
990  {
991  MERROR_VER("Exception in handle_incoming_tx_post: " << e.what());
992  tvc[i].m_verification_failed = true;
993  results[i].res = false;
994  }
995  });
996  }
997  }
998  waiter.wait(&tpool);
999 
1000  std::vector<tx_verification_batch_info> tx_info;
1001  tx_info.reserve(tx_blobs.size());
1002  for (size_t i = 0; i < tx_blobs.size(); i++) {
1003  if (!results[i].res || already_have[i])
1004  continue;
1005  tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
1006  }
1007  if (!tx_info.empty())
1008  handle_incoming_tx_accumulated_batch(tx_info, keeped_by_block);
1009 
1010  bool ok = true;
1011  it = tx_blobs.begin();
1012  for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
1013  if (!results[i].res)
1014  {
1015  ok = false;
1016  continue;
1017  }
1018  if (keeped_by_block)
1020  if (already_have[i])
1021  continue;
1022 
1023  const size_t weight = get_transaction_weight(results[i].tx, it->size());
1024  ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], weight, tvc[i], keeped_by_block, relayed, do_not_relay);
1025  if(tvc[i].m_verification_failed)
1026  {MERROR_VER("Transaction verification failed: " << results[i].hash);}
1027  else if(tvc[i].m_verification_impossible)
1028  {MERROR_VER("Transaction verification impossible: " << results[i].hash);}
1029 
1030  if(tvc[i].m_added_to_pool)
1031  MDEBUG("tx added: " << results[i].hash);
1032  }
1033  return ok;
1034 
1035  CATCH_ENTRY_L0("core::handle_incoming_txs()", false);
1036  }
1037  //-----------------------------------------------------------------------------------------------
1038  bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1039  {
1040  std::vector<cryptonote::blobdata> tx_blobs;
1041  tx_blobs.push_back(tx_blob);
1042  std::vector<tx_verification_context> tvcv(1);
1043  bool r = handle_incoming_txs(tx_blobs, tvcv, keeped_by_block, relayed, do_not_relay);
1044  tvc = tvcv[0];
1045  return r;
1046  }
1047  //-----------------------------------------------------------------------------------------------
1049  {
1050  st_inf.mining_speed = m_miner.get_speed();
1051  st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count();
1052  st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1053  st_inf.tx_pool_size = m_mempool.get_transactions_count();
1054  st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_tail_id());
1055  return true;
1056  }
1057 
1058  //-----------------------------------------------------------------------------------------------
1059  bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const
1060  {
1061  if(!tx.vin.size())
1062  {
1063  MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
1064  return false;
1065  }
1066 
1068  {
1069  MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx));
1070  return false;
1071  }
1072 
1073  if(!check_outs_valid(tx))
1074  {
1075  MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
1076  return false;
1077  }
1078 
1079  if(!check_etn_overflow(tx))
1080  {
1081  MERROR_VER("tx has ETN overflow, rejected for tx id= " << get_transaction_hash(tx));
1082  return false;
1083  }
1084 
1085  uint64_t amount_in = 0;
1086  get_inputs_etn_amount(tx, amount_in);
1087  uint64_t amount_out = get_outs_etn_amount(tx);
1088 
1089  if((tx.version != 2 && amount_in <= amount_out) || (tx.version == 2 && amount_in != amount_out)) {
1090  MERROR_VER("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1091  << get_transaction_hash(tx));
1092  return false;
1093  }
1094  // for version > 1, ringct signatures check verifies amounts match
1095 
1097  {
1098  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);
1099  return false;
1100  }
1101 
1102  if(tx.version >= 3)
1103  {
1104  //check if tx use different utxos
1105  if(!check_tx_inputs_utxos_diff(tx))
1106  {
1107  MERROR_VER("tx uses a single utxo more than once");
1108  return false;
1109  }
1110  }
1111  else
1112  {
1113  //check if tx use different key images
1114  if(!check_tx_inputs_keyimages_diff(tx))
1115  {
1116  MERROR_VER("tx uses a single key image more than once");
1117  return false;
1118  }
1119 
1120  if (!check_tx_inputs_keyimages_domain(tx))
1121  {
1122  MERROR_VER("tx uses key image not in the valid domain");
1123  return false;
1124  }
1125  }
1126 
1127  return true;
1128  }
1129  //-----------------------------------------------------------------------------------------------
1131  {
1132  return m_blockchain_storage.have_tx_keyimg_as_spent(key_image);
1133  }
1134  //-----------------------------------------------------------------------------------------------
1135  bool core::are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1136  {
1137  spent.clear();
1138  for(auto& ki: key_im)
1139  {
1140  spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki));
1141  }
1142  return true;
1143  }
1144  //-----------------------------------------------------------------------------------------------
1146  {
1147  static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
1148  if (block_sync_size > 0)
1149  return block_sync_size;
1150  if (height >= quick_height)
1153  }
1154  //-----------------------------------------------------------------------------------------------
1155  bool core::are_key_images_spent_in_pool(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1156  {
1157  spent.clear();
1158  return m_mempool.check_for_key_images(key_im, spent);
1159  }
1160  //-----------------------------------------------------------------------------------------------
1161  std::pair<uint64_t, uint64_t> core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count)
1162  {
1163  uint64_t emission_amount = 0;
1164  uint64_t total_fee_amount = 0;
1165  if (count)
1166  {
1167  const uint64_t end = start_offset + count - 1;
1168  m_blockchain_storage.for_blocks_range(start_offset, end,
1169  [this, &emission_amount, &total_fee_amount](uint64_t, const crypto::hash& hash, const block& b){
1170  std::vector<transaction> txs;
1171  std::vector<crypto::hash> missed_txs;
1172  uint64_t coinbase_amount = get_outs_etn_amount(b.miner_tx);
1173  this->get_transactions(b.tx_hashes, txs, missed_txs);
1174  uint64_t tx_fee_amount = 0;
1175  for(const auto& tx: txs)
1176  {
1177  tx_fee_amount += get_tx_fee(tx);
1178  }
1179 
1180  emission_amount += coinbase_amount - tx_fee_amount;
1181  total_fee_amount += tx_fee_amount;
1182  return true;
1183  });
1184  }
1185 
1186  return std::pair<uint64_t, uint64_t>(emission_amount, total_fee_amount);
1187  }
1188  //-----------------------------------------------------------------------------------------------
1189  bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const
1190  {
1191  std::unordered_set<crypto::key_image> ki;
1192  for(const auto& in: tx.vin)
1193  {
1194  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1195  if(!ki.insert(tokey_in.k_image).second)
1196  return false;
1197  }
1198  return true;
1199  }
1200  //-----------------------------------------------------------------------------------------------
1201  bool core::check_tx_inputs_utxos_diff(const transaction& tx) const
1202  {
1203  std::unordered_set<std::string> ins;
1204  for(const auto& in: tx.vin)
1205  {
1206  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
1207  if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
1208  return false;
1209  }
1210  return true;
1211  }
1212  //-----------------------------------------------------------------------------------------------
1213  bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const
1214  {
1215  const uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1217  {
1218  for(const auto& in: tx.vin)
1219  {
1220  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1221  for (size_t n = 1; n < tokey_in.key_offsets.size(); ++n)
1222  if (tokey_in.key_offsets[n] == 0)
1223  return false;
1224  }
1225  }
1226  return true;
1227  }
1228  //-----------------------------------------------------------------------------------------------
1229  bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const
1230  {
1231  std::unordered_set<crypto::key_image> ki;
1232  for(const auto& in: tx.vin)
1233  {
1234  CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1235  if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity()))
1236  return false;
1237  }
1238  return true;
1239  }
1240  //-----------------------------------------------------------------------------------------------
1241  bool core::add_new_tx(transaction& tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1242  {
1243  crypto::hash tx_hash = get_transaction_hash(tx);
1244  blobdata bl;
1246  size_t tx_weight = get_transaction_weight(tx, bl.size());
1247  return add_new_tx(tx, tx_hash, bl, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
1248  }
1249  //-----------------------------------------------------------------------------------------------
1251  {
1252  return m_blockchain_storage.get_total_transactions();
1253  }
1254  //-----------------------------------------------------------------------------------------------
1255  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)
1256  {
1257 
1258  if(m_mempool.have_tx(tx_hash))
1259  {
1260  LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool");
1261  return true;
1262  }
1263 
1264  if(m_blockchain_storage.have_tx(tx_hash))
1265  {
1266  LOG_PRINT_L2("tx " << tx_hash << " already have transaction in blockchain");
1267  return true;
1268  }
1269 
1270  uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1271  return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version);
1272  }
1273  //-----------------------------------------------------------------------------------------------
1274  bool core::relay_txpool_transactions()
1275  {
1276  // we attempt to relay txes that should be relayed, but were not
1277  std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1278  if (m_mempool.get_relayable_transactions(txs) && !txs.empty())
1279  {
1280  cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
1281  tx_verification_context tvc = AUTO_VAL_INIT(tvc);
1283  for (auto it = txs.begin(); it != txs.end(); ++it)
1284  {
1285  r.txs.push_back(it->second);
1286  }
1287  get_protocol()->relay_transactions(r, fake_context);
1288  m_mempool.set_relayed(txs);
1289  }
1290  return true;
1291  }
1292  //-----------------------------------------------------------------------------------------------
1294  {
1295  std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1297  crypto::hash tx_hash;
1298  if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
1299  {
1300  LOG_ERROR("Failed to parse relayed transaction");
1301  return;
1302  }
1303  txs.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
1304  m_mempool.set_relayed(txs);
1305  }
1306  //-----------------------------------------------------------------------------------------------
1307  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)
1308  {
1309  return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce);
1310  }
1311  //-----------------------------------------------------------------------------------------------
1312  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)
1313  {
1314  return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce);
1315  }
1316  //-----------------------------------------------------------------------------------------------
1317  bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
1318  {
1319  return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
1320  }
1321  //-----------------------------------------------------------------------------------------------
1322  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
1323  {
1324  return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_count);
1325  }
1326  //-----------------------------------------------------------------------------------------------
1328  {
1329  return m_blockchain_storage.get_outs(req, res);
1330  }
1331  //-----------------------------------------------------------------------------------------------
1332  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
1333  {
1334  return m_blockchain_storage.get_output_distribution(amount, from_height, to_height, start_height, distribution, base);
1335  }
1336  //-----------------------------------------------------------------------------------------------
1337  bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const
1338  {
1339  return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs);
1340  }
1341  //-----------------------------------------------------------------------------------------------
1342  bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, size_t n_txes, std::vector<std::vector<uint64_t>>& indexs) const
1343  {
1344  return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, n_txes, indexs);
1345  }
1346  //-----------------------------------------------------------------------------------------------
1348  {
1349  m_miner.pause();
1350  }
1351  //-----------------------------------------------------------------------------------------------
1353  {
1354  m_miner.resume();
1355  }
1356  //-----------------------------------------------------------------------------------------------
1358  {
1361  for (const auto &tx_hash: b.tx_hashes)
1362  {
1363  cryptonote::blobdata txblob;
1364  CHECK_AND_ASSERT_THROW_MES(pool.get_transaction(tx_hash, txblob), "Transaction not found in pool");
1365  bce.txs.push_back(txblob);
1366  }
1367  return bce;
1368  }
1369  //-----------------------------------------------------------------------------------------------
1371  {
1372  bvc = boost::value_initialized<block_verification_context>();
1373  m_miner.pause();
1374  std::vector<block_complete_entry> blocks;
1375  try
1376  {
1377  blocks.push_back(get_block_complete_entry(b, m_mempool));
1378  }
1379  catch (const std::exception &e)
1380  {
1381  m_miner.resume();
1382  return false;
1383  }
1384  std::vector<block> pblocks;
1385  if (!prepare_handle_incoming_blocks(blocks, pblocks))
1386  {
1387  MERROR("Block found, but failed to prepare to add");
1388  m_miner.resume();
1389  return false;
1390  }
1391  m_blockchain_storage.add_new_block(b, bvc);
1393 
1394  CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Mined block failed verification");
1395  if(bvc.m_added_to_main_chain)
1396  {
1397  cryptonote_connection_context exclude_context = boost::value_initialized<cryptonote_connection_context>();
1399  arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1400  std::vector<crypto::hash> missed_txs;
1401  std::vector<cryptonote::blobdata> txs;
1402  m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, missed_txs);
1403  if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b))
1404  {
1405  LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block");
1406  return true;
1407  }
1408  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()
1409  << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size());
1410 
1411  block_to_blob(b, arg.b.block);
1412  //pack transactions
1413  for(auto& tx: txs)
1414  arg.b.txs.push_back(tx);
1415 
1416  m_pprotocol->relay_block(arg, exclude_context);
1417 
1418  if(m_fallback_to_pow) {
1419  m_miner.resume();
1420  }
1421  } else {
1422  update_miner_block_template();
1423  m_miner.resume();
1424  }
1425  return true;
1426  }
1427  //-----------------------------------------------------------------------------------------------
1429  {
1430  m_miner.on_synchronized();
1431  }
1432  //-----------------------------------------------------------------------------------------------
1433  void core::safesyncmode(const bool onoff)
1434  {
1435  m_blockchain_storage.safesyncmode(onoff);
1436  }
1437  //-----------------------------------------------------------------------------------------------
1438  bool core::add_new_block(const block& b, block_verification_context& bvc)
1439  {
1440  return m_blockchain_storage.add_new_block(b, bvc);
1441  }
1442 
1443  //-----------------------------------------------------------------------------------------------
1444  bool core::prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks)
1445  {
1446  m_incoming_tx_lock.lock();
1447  if (!m_blockchain_storage.prepare_handle_incoming_blocks(blocks_entry, blocks))
1448  {
1450  return false;
1451  }
1452  return true;
1453  }
1454 
1455  //-----------------------------------------------------------------------------------------------
1457  {
1458  bool success = false;
1459  try {
1460  success = m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync);
1461  }
1462  catch (...) {}
1463  m_incoming_tx_lock.unlock();
1464  return success;
1465  }
1466 
1467  //-----------------------------------------------------------------------------------------------
1468  bool core::handle_incoming_block(const blobdata& block_blob, const block *b, block_verification_context& bvc, bool update_miner_blocktemplate)
1469  {
1470  TRY_ENTRY();
1471 
1472  bvc = boost::value_initialized<block_verification_context>();
1473 
1474  if (!check_incoming_block_size(block_blob))
1475  {
1476  bvc.m_verification_failed = true;
1477  return false;
1478  }
1479 
1480  if (((size_t)-1) <= 0xffffffff && block_blob.size() >= 0x3fffffff)
1481  MWARNING("This block's size is " << block_blob.size() << ", closing on the 32 bit limit");
1482 
1483  // load json & DNS checkpoints every 10min/hour respectively,
1484  // and verify them with respect to what blocks we already have
1485  CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
1486 
1487  block lb;
1488  if (!b)
1489  {
1490  crypto::hash block_hash;
1491  if(!parse_and_validate_block_from_blob(block_blob, lb, block_hash))
1492  {
1493  LOG_PRINT_L1("Failed to parse and validate new block");
1494  bvc.m_verification_failed = true;
1495  return false;
1496  }
1497  b = &lb;
1498  }
1499 
1500  add_new_block(*b, bvc);
1501 
1502  if(bvc.m_added_to_main_chain) {
1503  m_miner.resume();
1504 
1505  if(update_miner_blocktemplate)
1506  update_miner_block_template();
1507  }
1508 
1509  return true;
1510 
1511  CATCH_ENTRY_L0("core::handle_incoming_block()", false);
1512  }
1513  //-----------------------------------------------------------------------------------------------
1514  // Used by the RPC server to check the size of an incoming
1515  // block_blob
1516  bool core::check_incoming_block_size(const blobdata& block_blob) const
1517  {
1518  // note: we assume block weight is always >= block blob size, so we check incoming
1519  // blob size against the block weight limit, which acts as a sanity check without
1520  // having to parse/weigh first; in fact, since the block blob is the block header
1521  // plus the tx hashes, the weight will typically be much larger than the blob size
1522  if(block_blob.size() > m_blockchain_storage.get_current_cumulative_block_weight_limit() + BLOCK_SIZE_SANITY_LEEWAY)
1523  {
1524  LOG_PRINT_L1("WRONG BLOCK BLOB, sanity check failed on size " << block_blob.size() << ", rejected");
1525  return false;
1526  }
1527  return true;
1528  }
1529  //-----------------------------------------------------------------------------------------------
1531  {
1532  return m_blockchain_storage.get_tail_id();
1533  }
1534  //-----------------------------------------------------------------------------------------------
1536  {
1537  return m_blockchain_storage.get_db().set_block_cumulative_difficulty(height, diff);
1538  }
1539  //-----------------------------------------------------------------------------------------------
1541  {
1542  return m_blockchain_storage.get_db().get_block_cumulative_difficulty(height);
1543  }
1544  //-----------------------------------------------------------------------------------------------
1546  {
1547  return m_mempool.get_transactions_count();
1548  }
1549  //-----------------------------------------------------------------------------------------------
1550  bool core::have_block(const crypto::hash& id) const
1551  {
1552  return m_blockchain_storage.have_block(id);
1553  }
1554  //-----------------------------------------------------------------------------------------------
1555  bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const
1556  {
1557  return parse_and_validate_tx_from_blob(blob, tx, tx_hash);
1558  }
1559  //-----------------------------------------------------------------------------------------------
1560  bool core::check_tx_syntax(const transaction& tx) const
1561  {
1562  return true;
1563  }
1564  //-----------------------------------------------------------------------------------------------
1565  bool core::get_pool_transactions(std::vector<transaction>& txs, bool include_sensitive_data) const
1566  {
1567  m_mempool.get_transactions(txs, include_sensitive_data);
1568  return true;
1569  }
1570  //-----------------------------------------------------------------------------------------------
1571  bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_data) const
1572  {
1573  m_mempool.get_transaction_hashes(txs, include_sensitive_data);
1574  return true;
1575  }
1576  //-----------------------------------------------------------------------------------------------
1577  bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const
1578  {
1579  m_mempool.get_transaction_stats(stats, include_sensitive_data);
1580  return true;
1581  }
1582  //-----------------------------------------------------------------------------------------------
1584  {
1585  return m_mempool.get_transaction(id, tx);
1586  }
1587  //-----------------------------------------------------------------------------------------------
1588  bool core::pool_has_tx(const crypto::hash &id) const
1589  {
1590  return m_mempool.have_tx(id);
1591  }
1592  //-----------------------------------------------------------------------------------------------
1593  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
1594  {
1595  return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos, include_sensitive_data);
1596  }
1597  //-----------------------------------------------------------------------------------------------
1598  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
1599  {
1600  return m_mempool.get_pool_for_rpc(tx_infos, key_image_infos);
1601  }
1602  //-----------------------------------------------------------------------------------------------
1603  bool core::get_short_chain_history(std::list<crypto::hash>& ids) const
1604  {
1605  return m_blockchain_storage.get_short_chain_history(ids);
1606  }
1607  //-----------------------------------------------------------------------------------------------
1609  {
1610  return m_blockchain_storage.handle_get_objects(arg, rsp);
1611  }
1612  //-----------------------------------------------------------------------------------------------
1614  {
1615  return m_blockchain_storage.get_block_id_by_height(height);
1616  }
1617  //-----------------------------------------------------------------------------------------------
1618  bool core::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
1619  {
1620  return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
1621  }
1622  //-----------------------------------------------------------------------------------------------
1623  std::string core::print_pool(bool short_format) const
1624  {
1625  return m_mempool.print_pool(short_format);
1626  }
1627  //-----------------------------------------------------------------------------------------------
1628  bool core::update_miner_block_template()
1629  {
1630  m_miner.on_block_chain_update();
1631  return true;
1632  }
1633  //-----------------------------------------------------------------------------------------------
1635  {
1636  if(!m_starter_message_showed)
1637  {
1638  std::string main_message;
1639  if (m_offline)
1640  main_message = "The daemon is running offline and will not attempt to sync to the Electroneum network.";
1641  else
1642  main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
1643  MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
1644  << main_message << ENDL
1645  << ENDL
1646  << "You can set the level of process detailization through \"set_log <level|categories>\" command," << ENDL
1647  << "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL
1648  << ENDL
1649  << "Use the \"help\" command to see the list of available commands." << ENDL
1650  << "Use \"help <command>\" to see a command's documentation." << ENDL
1651  << "**********************************************************************" << ENDL);
1652  m_starter_message_showed = true;
1653  }
1654  //Don't moan about forks for now, but keep implementation around incase we need to use it at a later stage
1655  //m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this));
1656  m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
1657  m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
1658  m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
1659  m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this));
1660  m_blockchain_pruning_interval.do_call(boost::bind(&core::update_blockchain_pruning, this));
1661  m_miner.on_idle();
1662  m_mempool.on_idle();
1663 
1664  if(!m_fallback_to_pow) {
1665  m_validators->on_idle();
1666  }
1667 
1668  return true;
1669  }
1670  //-----------------------------------------------------------------------------------------------
1671  bool core::check_fork_time()
1672  {
1673  if (m_nettype == FAKECHAIN)
1674  return true;
1675 
1676  HardFork::State state = m_blockchain_storage.get_hard_fork_state();
1677  const el::Level level = el::Level::Warning;
1678  switch (state) {
1680  MCLOG_RED(level, "global", "**********************************************************************");
1681  MCLOG_RED(level, "global", "Last scheduled hard fork is too far in the past.");
1682  MCLOG_RED(level, "global", "We are most likely forked from the network. Daemon update needed now.");
1683  MCLOG_RED(level, "global", "**********************************************************************");
1684  break;
1686  MCLOG_RED(level, "global", "**********************************************************************");
1687  MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed soon.");
1688  MCLOG_RED(level, "global", "**********************************************************************");
1689  break;
1690  default:
1691  break;
1692  }
1693  return true;
1694  }
1695  //-----------------------------------------------------------------------------------------------
1697  {
1699  }
1700  //-----------------------------------------------------------------------------------------------
1702  {
1704  }
1705  //-----------------------------------------------------------------------------------------------
1707  {
1709  }
1710  //-----------------------------------------------------------------------------------------------
1712  {
1714  }
1715  //-----------------------------------------------------------------------------------------------
1716  bool core::check_updates()
1717  {
1718  static const char software[] = "electroneum";
1719 #ifdef BUILD_TAG
1720  static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
1721  static const char subdir[] = "cli"; // because it can never be simple
1722 #else
1723  static const char buildtag[] = "source";
1724  static const char subdir[] = "source"; // because it can never be simple
1725 #endif
1726 
1727  if (m_offline)
1728  return true;
1729 
1730  if (check_updates_level == UPDATES_DISABLED)
1731  return true;
1732 
1734  MCDEBUG("updates", "Checking for a new " << software << " version for " << buildtag);
1735  if (!tools::check_updates(software, buildtag, version, hash))
1736  return false;
1737 
1738  if (tools::vercmp(version.c_str(), ELECTRONEUM_VERSION) <= 0)
1739  {
1740  m_update_available = false;
1741  return true;
1742  }
1743 
1744  std::string url = tools::get_update_url(software, subdir, buildtag, version, true);
1745  MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
1746  m_update_available = true;
1747 
1748  if (check_updates_level == UPDATES_NOTIFY) {
1749  std::vector<std::string> version_split;
1750  std::vector<std::string> latest_version_split;
1751 
1752  boost::split(version_split, ELECTRONEUM_VERSION, [](char c){return c == '.';});
1753  boost::split(latest_version_split, version, [](char c){return c == '.';});
1754 
1755  // Warninig message to update to lastest software case major version differs.
1756  // This should help users to update their node before a major update or fork.
1757  for(size_t i = 0; i < 2; i++) {
1758  if(version_split[i] != latest_version_split[i]) {
1759  MCLOG_RED(el::Level::Fatal, "global", "Please update your node to the latest software (v" << version << ").");
1760  break;
1761  }
1762  }
1763 
1764  return true;
1765  }
1766 
1767  url = tools::get_update_url(software, subdir, buildtag, version, false);
1768  std::string filename;
1769  const char *slash = strrchr(url.c_str(), '/');
1770  if (slash)
1771  filename = slash + 1;
1772  else
1773  filename = std::string(software) + "-update-" + version;
1774  boost::filesystem::path path(epee::string_tools::get_current_module_folder());
1775  path /= filename;
1776 
1777  boost::unique_lock<boost::mutex> lock(m_update_mutex);
1778 
1779  if (m_update_download != 0)
1780  {
1781  MCDEBUG("updates", "Already downloading update");
1782  return true;
1783  }
1784 
1785  crypto::hash file_hash;
1786  if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash)))
1787  {
1788  MCDEBUG("updates", "We don't have that file already, downloading");
1789  const std::string tmppath = path.string() + ".tmp";
1791  {
1792  MCDEBUG("updates", "We have part of the file already, resuming download");
1793  }
1794  m_last_update_length = 0;
1795  m_update_download = tools::download_async(tmppath, url, [this, hash, path](const std::string &tmppath, const std::string &uri, bool success) {
1796  bool remove = false, good = true;
1797  if (success)
1798  {
1799  crypto::hash file_hash;
1800  if (!tools::sha256sum(tmppath, file_hash))
1801  {
1802  MCERROR("updates", "Failed to hash " << tmppath);
1803  remove = true;
1804  good = false;
1805  }
1806  else if (hash != epee::string_tools::pod_to_hex(file_hash))
1807  {
1808  MCERROR("updates", "Download from " << uri << " does not match the expected hash");
1809  remove = true;
1810  good = false;
1811  }
1812  }
1813  else
1814  {
1815  MCERROR("updates", "Failed to download " << uri);
1816  good = false;
1817  }
1818  boost::unique_lock<boost::mutex> lock(m_update_mutex);
1819  m_update_download = 0;
1820  if (success && !remove)
1821  {
1822  std::error_code e = tools::replace_file(tmppath, path.string());
1823  if (e)
1824  {
1825  MCERROR("updates", "Failed to rename downloaded file");
1826  good = false;
1827  }
1828  }
1829  else if (remove)
1830  {
1831  if (!boost::filesystem::remove(tmppath))
1832  {
1833  MCERROR("updates", "Failed to remove invalid downloaded file");
1834  good = false;
1835  }
1836  }
1837  if (good)
1838  MCLOG_CYAN(el::Level::Info, "updates", "New version downloaded to " << path.string());
1839  }, [this](const std::string &path, const std::string &uri, size_t length, ssize_t content_length) {
1840  if (length >= m_last_update_length + 1024 * 1024 * 10)
1841  {
1842  m_last_update_length = length;
1843  MCDEBUG("updates", "Downloaded " << length << "/" << (content_length ? std::to_string(content_length) : "unknown"));
1844  }
1845  return true;
1846  });
1847  }
1848  else
1849  {
1850  MCDEBUG("updates", "We already have " << path << " with expected hash");
1851  }
1852 
1853  lock.unlock();
1854 
1855  if (check_updates_level == UPDATES_DOWNLOAD)
1856  return true;
1857 
1858  MCERROR("updates", "Download/update not implemented yet");
1859  return true;
1860  }
1861  //-----------------------------------------------------------------------------------------------
1862  bool core::check_disk_space()
1863  {
1864  uint64_t free_space = get_free_space();
1865  if (free_space < 1ull * 1024 * 1024 * 1024) // 1 GB
1866  {
1867  const el::Level level = el::Level::Warning;
1868  MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder);
1869  }
1870  return true;
1871  }
1872  //-----------------------------------------------------------------------------------------------
1873  double factorial(unsigned int n)
1874  {
1875  if (n <= 1)
1876  return 1.0;
1877  double f = n;
1878  while (n-- > 1)
1879  f *= n;
1880  return f;
1881  }
1882  //-----------------------------------------------------------------------------------------------
1883  static double probability1(unsigned int blocks, unsigned int expected)
1884  {
1885  // https://www.umass.edu/wsp/resources/poisson/#computing
1886  return pow(expected, blocks) / (factorial(blocks) * exp(expected));
1887  }
1888  //-----------------------------------------------------------------------------------------------
1889  static double probability(unsigned int blocks, unsigned int expected)
1890  {
1891  double p = 0.0;
1892  if (blocks <= expected)
1893  {
1894  for (unsigned int b = 0; b <= blocks; ++b)
1895  p += probability1(b, expected);
1896  }
1897  else if (blocks > expected)
1898  {
1899  for (unsigned int b = blocks; b <= expected * 3 /* close enough */; ++b)
1900  p += probability1(b, expected);
1901  }
1902  return p;
1903  }
1904  //-----------------------------------------------------------------------------------------------
1905  bool core::check_block_rate()
1906  {
1907  MDEBUG("Not checking block rate, not applicable.");
1908  return true;
1909 
1910  if (m_offline || m_nettype == FAKECHAIN || m_target_blockchain_height > get_current_blockchain_height())
1911  {
1912  MDEBUG("Not checking block rate, offline or syncing");
1913  return true;
1914  }
1915 
1916  static constexpr double threshold = 1. / (864000 / DIFFICULTY_TARGET_V6); // one false positive every 10 days
1917 
1918  const time_t now = time(NULL);
1919  const std::vector<time_t> timestamps = m_blockchain_storage.get_last_block_timestamps(60);
1920 
1921  static const unsigned int seconds[] = { 5400, 3600, 1800, 1200, 600 };
1922  for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n)
1923  {
1924  unsigned int b = 0;
1925  const time_t time_boundary = now - static_cast<time_t>(seconds[n]);
1926  for (time_t ts: timestamps) b += ts >= time_boundary;
1927  const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V6);
1928  MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
1929  if (p < threshold)
1930  {
1931  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.");
1932 
1933  std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
1934  if (block_rate_notify)
1935  {
1936  auto expected = seconds[n] / DIFFICULTY_TARGET_V6;
1937  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);
1938  }
1939 
1940  break; // no need to look further
1941  }
1942  }
1943 
1944  return true;
1945  }
1946  //-----------------------------------------------------------------------------------------------
1948  {
1949  return m_blockchain_storage.update_blockchain_pruning();
1950  }
1951  //-----------------------------------------------------------------------------------------------
1953  {
1954  return m_blockchain_storage.check_blockchain_pruning();
1955  }
1956  //-----------------------------------------------------------------------------------------------
1957  void core::set_target_blockchain_height(uint64_t target_blockchain_height)
1958  {
1959  m_target_blockchain_height = target_blockchain_height;
1960  }
1961  //-----------------------------------------------------------------------------------------------
1963  {
1964  return m_target_blockchain_height;
1965  }
1966  //-----------------------------------------------------------------------------------------------
1968  {
1969  boost::filesystem::path path(m_config_folder);
1970  boost::filesystem::space_info si = boost::filesystem::space(path);
1971  return si.available;
1972  }
1973  //-----------------------------------------------------------------------------------------------
1975  {
1977  }
1978  //-----------------------------------------------------------------------------------------------
1980  {
1981  return get_blockchain_storage().prune_blockchain(pruning_seed);
1982  }
1983  //-----------------------------------------------------------------------------------------------
1984  std::time_t core::get_start_time() const
1985  {
1986  return start_time;
1987  }
1988  //-----------------------------------------------------------------------------------------------
1990  bool is_validator_key_valid = std::count_if(key.begin(), key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
1991  if(!is_validator_key_valid || key.size() % 2 != 0) {
1992  return false;
1993  }
1994 
1995  m_miner.pause();
1996  m_blockchain_storage.set_validator_key(key);
1997  m_miner.resume();
1998 
1999  return true;
2000  }
2001  //-----------------------------------------------------------------------------------------------
2002  std::vector<std::string> core::generate_ed25519_keypair() {
2004  }
2005  //-----------------------------------------------------------------------------------------------
2006 
2008  std::string b_str = crypto::sign_message(msg, sk);
2009  return boost::algorithm::hex(b_str);
2010  }
2011  //-----------------------------------------------------------------------------------------------
2013  {
2015  return m_blockchain_storage.get_db().get_balance(combined_key);
2016  }
2017  //-----------------------------------------------------------------------------------------------
2018  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)
2019  {
2021  return m_blockchain_storage.get_db().get_addr_output_batch(combined_key, start_tx_id, batch_size, desc);
2022  }
2023  //-----------------------------------------------------------------------------------------------
2025  {
2026  raise(SIGTERM);
2027  }
2028 }
return true
uint64_t height
Definition: blockchain.cpp:91
time_t time
Definition: blockchain.cpp:93
uint8_t threshold
Definition: blockchain.cpp:92
#define DBF_SAFE
#define DBF_FAST
#define DBF_FASTEST
#define DBF_SALVAGE
const unsigned char checkpoints[]
#define JSON_HASH_FILE_NAME
Definition: checkpoints.h:39
static void init_options(boost::program_options::options_description &desc)
init command line options
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block's cumulative difficulty
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
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block's cumulative difficulty
virtual uint64_t get_balance(const crypto::public_key &combined_key)=0
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:723
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
Definition: blockchain.cpp:787
bool prepare_handle_incoming_blocks(const std::vector< block_complete_entry > &blocks_entry, std::vector< block > &blocks)
performs some preprocessing on a group of incoming blocks to speed up verification
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:815
bool init(BlockchainDB *db, const network_type nettype=MAINNET, bool offline=false, const cryptonote::test_options *test_options=NULL, difficulty_type fixed_difficulty=0, const GetCheckpointsCallback &get_checkpoints=nullptr, bool ignore_bsig=false, bool fallback_to_pow=false)
Initialize the Blockchain state.
Definition: blockchain.cpp:331
bool prune_blockchain(uint32_t pruning_seed=0)
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
get recent block hashes for a foreign chain
bool get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vector< uint64_t > &indexs) const
gets the global indices for outputs from a given transaction
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:814
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
bool get_split_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
void set_enforce_dns_checkpoints(bool enforce)
configure whether or not to enforce DNS-based checkpoints
bool update_checkpoints(const std::string &file_path, bool check_dns)
loads new checkpoints from a file and optionally from DNS
void set_show_time_stats(bool stats)
set whether or not to show/print time statistics
Definition: blockchain.h:794
bool deinit()
Uninitializes the blockchain state.
Definition: blockchain.cpp:546
static const std::vector< HardFork::Params > & get_hard_fork_heights(network_type nettype)
gets the hardfork heights of given network
HardFork::State get_hard_fork_state() const
gets the hardfork voting state object
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:775
void set_reorg_notify(const std::shared_ptr< tools::Notify > &notify)
sets a reorg notify object to call for every reorg
Definition: blockchain.h:782
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
void on_new_tx_from_block(const cryptonote::transaction &tx)
called when we see a tx originating from a block
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
uint64_t get_current_cumulative_block_weight_limit() const
gets the block weight limit based on recent blocks
std::vector< time_t > get_last_block_timestamps(unsigned int blocks) const
returns the timestamps of the last N blocks
Definition: blockchain.cpp:970
bool for_blocks_range(const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const block &)>) const
perform a check on all blocks in the blockchain in the given range
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
bool cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition: blockchain.h:848
void set_validator_key(std::string key)
set validator key
Definition: blockchain.h:1039
void set_validators_list_instance(std::unique_ptr< electroneum::basic::Validators > &v)
Definition: blockchain.h:1041
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
Definition: blockchain.h:953
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition: blockchain.h:822
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1007
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
Definition: blockchain.cpp:164
size_t get_total_transactions() const
gets the total number of transactions on the main chain
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
returns the earliest block a given version may activate
Definition: blockchain.h:855
bool reset_and_set_genesis_block(const block &b)
clears the blockchain and starts a new one
Definition: blockchain.cpp:698
void set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold, blockchain_db_sync_mode sync_mode, bool fast_sync, std::string validator_key)
Update the validators public key by fetching data from electroneum's endpoint.
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
Definition: blockchain.cpp:745
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
get blocks and transactions from blocks based on start height and count
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request &req, COMMAND_RPC_GET_OUTPUTS_BIN::response &res) const
gets specific outputs to mix with
bool create_block_template(block &b, const account_public_address &miner_address, difficulty_type &di, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
creates a new block to mine against
bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
Definition: blockchain.cpp:174
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request &arg, NOTIFY_RESPONSE_GET_OBJECTS::request &rsp)
retrieves a set of blocks and their transactions, and possibly other transactions
bool get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:319
void set_checkpoints(checkpoints &&chk_pts)
assign a set of blockchain checkpoint hashes
Definition: blockchain.h:175
A generic BlockchainDB exception.
const char * what() const
A container for blockchain checkpoints.
Definition: checkpoints.h:52
size_t get_pool_transactions_count() const
get the total number of transactions in the pool
bool pool_has_tx(const crypto::hash &txid) const
checks if the pool has a transaction with the given hash
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)
void safesyncmode(const bool onoff)
Put DB in safe sync mode.
bool update_blockchain_pruning()
incrementally prunes blockchain
virtual bool handle_block_found(block &b, block_verification_context &bvc)
stores and relays a block found by a miner
bool set_validator_key(std::string key)
set validator key
void get_blockchain_top(uint64_t &height, crypto::hash &top_id) const
get the hash and height of the most recent block
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
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
void stop()
stops the daemon running
bool is_key_image_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
void set_cryptonote_protocol(i_cryptonote_protocol *pprotocol)
set the pointer to the cryptonote protocol object to use
uint8_t get_hard_fork_version(uint64_t height) const
return the hard fork version for a given block height
static void init_options(boost::program_options::options_description &desc)
adds command line options to the given options set
bool get_transactions(const std::vector< crypto::hash > &txs_ids, std::vector< cryptonote::blobdata > &txs, std::vector< crypto::hash > &missed_txs) const
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 get_test_drop_download_height() const
gets whether or not to drop blocks
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 graceful_exit()
tells the daemon to wind down operations and stop running
void test_drop_download_height(uint64_t height)
sets to drop blocks downloaded below a certain height
bool get_short_chain_history(std::list< crypto::hash > &ids) const
gets the hashes for a subset of the blockchain
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
bool on_idle()
calls various idle routines
uint64_t get_free_space() const
get free disk space on the blockchain partition
uint32_t get_blockchain_pruning_seed() const
get the blockchain pruning seed
difficulty_type get_block_cumulative_difficulty(uint64_t height) const
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)
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
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
bool set_genesis_block(const block &b)
clears the blockchain and starts a new one
Blockchain & get_blockchain_storage()
gets the Blockchain instance
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
size_t get_blockchain_total_transactions() const
gets the total number of transactions on the main chain
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
bool get_test_drop_download() const
gets whether or not to drop blocks (for testing)
bool cleanup_handle_incoming_blocks(bool force_sync=false)
incoming blocks post-processing, cleanup, and disk sync
bool isValidatorsListValid()
get Validators List state
bool get_pool_transaction_stats(struct txpool_stats &stats, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
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
bool get_stat_info(core_stat_info &st_inf) const
gets some stats about the daemon
void set_checkpoints_file_path(const std::string &path)
set the file path to read from when loading checkpoints
bool check_blockchain_pruning()
checks the blockchain pruning if enabled
std::string sign_message(std::string sk, std::string msg)
size_t get_block_sync_size(uint64_t height) const
get the number of blocks to sync in one go
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 deinit()
performs safe shutdown steps for core and core components
uint64_t get_balance(const address_parse_info &addr)
bool update_checkpoints()
tells the Blockchain to update its checkpoints
std::time_t get_start_time() const
gets start_time
void set_checkpoints(checkpoints &&chk_pts)
assign a set of blockchain checkpoint hashes
std::string print_pool(bool short_format) const
get a string containing human-readable pool information
std::string get_validators_list()
Get a serialized representation of the list of validators.
bool handle_incoming_block(const blobdata &block_blob, const block *b, block_verification_context &bvc, bool update_miner_blocktemplate=true)
handles an incoming block
void set_target_blockchain_height(uint64_t target_blockchain_height)
sets the target blockchain height
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
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
i_cryptonote_protocol * get_protocol()
get the cryptonote protocol instance
uint64_t get_target_blockchain_height() const
gets the target blockchain height
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
void set_enforce_dns_checkpoints(bool enforce_dns)
set whether or not we enforce DNS checkpoints
bool check_incoming_block_size(const blobdata &block_blob) const
check the size of a block against the current maximum
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
void test_drop_download()
sets to drop blocks downloaded (for testing)
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 prune_blockchain(uint32_t pruning_seed=0)
prune the blockchain
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
return the earliest block a given version may activate
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
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 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
std::vector< std::string > generate_ed25519_keypair()
bool get_pool_transaction(const crypto::hash &id, cryptonote::blobdata &tx) const
get a specific transaction from the pool
virtual void on_transaction_relayed(const cryptonote::blobdata &tx)
called when a transaction is relayed
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 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
bool get_pool_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
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 get_txpool_backlog(std::vector< tx_backlog_entry > &backlog) const
bool get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vector< uint64_t > &indexs) const
gets the global indices for outputs from a given transaction
void on_synchronized()
Definition: miner.cpp:488
uint64_t get_speed() const
Definition: miner.cpp:422
static void init_options(boost::program_options::options_description &desc)
Definition: miner.cpp:279
bool on_block_chain_update()
Definition: miner.cpp:148
bool init(const boost::program_options::variables_map &vm, network_type nettype, bool fallback_to_pow=false)
Definition: miner.cpp:291
bool on_idle()
Definition: miner.cpp:178
Transaction pool, handles transactions which are not part of a block.
Definition: tx_pool.h:95
void on_idle()
action to take periodically
Definition: tx_pool.cpp:587
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:699
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:931
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition: tx_pool.cpp:1025
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:752
bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context &tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
Definition: tx_pool.cpp:120
void get_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
Definition: tx_pool.cpp:733
bool 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:855
bool init(size_t max_txpool_weight=0)
loads pool state (if any) from disk, and initializes pool
Definition: tx_pool.cpp:1554
std::string print_pool(bool short_format) const
get a string containing human-readable pool information
Definition: tx_pool.cpp:1325
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:763
size_t validate(uint8_t version)
remove transactions from the pool which are no longer valid
Definition: tx_pool.cpp:1490
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:775
size_t get_transactions_count(bool include_unrelayed_txes=true) const
get the total number of transactions in the pool
Definition: tx_pool.cpp:726
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:665
bool get_transaction(const crypto::hash &h, cryptonote::blobdata &txblob) const
get a specific transaction from the pool
Definition: tx_pool.cpp:995
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:980
bool deinit()
attempts to save the transaction pool state to disk
Definition: tx_pool.cpp:1623
bool do_call(functor_t functr)
Definition: math_helper.h:263
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
A global thread pool.
Definition: threadpool.h:43
static threadpool & getInstance()
Definition: threadpool.h:45
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
#define HF_VERSION_PUBLIC_TX
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE
#define HF_VERSION_ENFORCE_RCT
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT
#define DEFAULT_TXPOOL_MAX_WEIGHT
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4
#define DIFFICULTY_TARGET_V6
#define BAD_SEMANTICS_TXES_MAX_SIZE
#define MERROR_VER(x)
#define BLOCK_SIZE_SANITY_LEEWAY
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
expect< void > success() noexcept
Definition: expect.h:397
const char * res
Definition: hmac_keccak.cpp:41
const char * key
Definition: hmac_keccak.cpp:39
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MWARNING(x)
Definition: misc_log_ex.h:74
#define MDEBUG(x)
Definition: misc_log_ex.h:76
#define MCLOG_CYAN(level, cat, x)
Definition: misc_log_ex.h:63
#define MCLOG_RED(level, cat, x)
Definition: misc_log_ex.h:58
#define CATCH_ENTRY_L0(lacation, return_val)
Definition: misc_log_ex.h:165
#define MGINFO_YELLOW(x)
Definition: misc_log_ex.h:83
#define ENDL
Definition: misc_log_ex.h:149
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
#define MGINFO(x)
Definition: misc_log_ex.h:80
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define MTRACE(x)
Definition: misc_log_ex.h:77
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
#define TRY_ENTRY()
Definition: misc_log_ex.h:151
#define MCDEBUG(cat, x)
Definition: misc_log_ex.h:54
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
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
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
public_key addKeys(const public_key &A, const public_key &B)
Definition: crypto.h:337
std::vector< std::string > create_ed25519_keypair()
Definition: crypto.h:386
POD_CLASS public_key
Definition: crypto.h:76
POD_CLASS key_image
Definition: crypto.h:102
POD_CLASS hash
Definition: hash.h:50
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.h:374
std::unordered_map< crypto::key_image, std::vector< crypto::hash > > key_images_with_tx_hashes
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
const command_line::arg_descriptor< std::string, false, true, 2 > arg_data_dir
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
uint64_t get_outs_etn_amount(const transaction &tx)
const command_line::arg_descriptor< bool > arg_db_salvage
bool get_tx_fee(const transaction &tx, uint64_t &fee)
double factorial(unsigned int n)
const command_line::arg_descriptor< bool > arg_regtest_on
const command_line::arg_descriptor< bool > arg_offline
block_complete_entry get_block_complete_entry(block &b, tx_memory_pool &pool)
const command_line::arg_descriptor< difficulty_type > arg_fixed_difficulty
bool get_block_hash(const block &b, crypto::hash &res)
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
uint64_t get_block_height(const block &b)
const command_line::arg_descriptor< bool > arg_fallback_to_pow
const command_line::arg_descriptor< bool, false > arg_testnet_on
BlockchainDB * new_db(const std::string &db_type)
blockchain_db_sync_mode
Definition: blockchain.h:78
@ db_async
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
@ db_nosync
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
@ db_sync
handle syncing calls instead of the backing db, synchronously
Definition: blockchain.h:80
@ db_defaultsync
user didn't specify, use db_async
Definition: blockchain.h:79
const command_line::arg_descriptor< std::string > arg_fallback_to_pow_checkpoint_hash
crypto::hash get_transaction_hash(const transaction &t)
bool check_outs_valid(const transaction &tx)
const command_line::arg_descriptor< std::string > arg_db_type
blobdata block_to_blob(const block &b)
const command_line::arg_descriptor< bool, false > arg_stagenet_on
const command_line::arg_descriptor< uint64_t > arg_fallback_to_pow_checkpoint_height
const command_line::arg_descriptor< bool > arg_disable_dns_checkpoints
bool check_etn_overflow(const transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
const command_line::arg_descriptor< bool > arg_skip_block_sig_verification
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
bool check_inputs_types_supported(const transaction &tx)
const command_line::arg_descriptor< size_t > arg_block_download_max_size
const command_line::arg_descriptor< std::string > arg_db_sync_mode
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
std::function< const epee::span< const unsigned char >cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
Definition: blockchain.h:92
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
Level
Represents enumeration for severity level used to determine level of logging.
@ Warning
Useful when application has potentially harmful situtaions.
@ Info
Mainly useful to represent current progress of application.
@ Fatal
Severe error information that will presumably abort application.
unsigned int & g_test_dbg_lock_sleep()
Definition: syncobj.h:45
bool is_file_exist(const std::string &path)
Definition: file_io_utils.h:66
std::string to_string(t_connection_type type)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
std::string & trim(std::string &str)
Definition: string_tools.h:288
std::string & get_current_module_folder()
Definition: string_tools.h:233
mdb_size_t count(MDB_cursor *cur)
version
Supported socks variants.
Definition: socks.h:58
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
Definition: zmq.h:98
key curveOrder()
Definition: rctOps.h:76
@ RCTTypeBulletproof2
Definition: rctTypes.h:233
@ RCTTypeBulletproof
Definition: rctTypes.h:232
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
bool verRctSemanticsSimple(const std::vector< const rctSig * > &rvv)
Definition: rctSigs.cpp:975
key identity()
Definition: rctOps.h:73
::std::string string
Definition: gtest-port.h:1097
const T & move(const T &t)
Definition: gtest-port.h:1317
int vercmp(const char *v0, const char *v1)
Definition: util.cpp:915
std::shared_ptr< download_thread_control > download_async_handle
Definition: download.h:36
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
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 download_cancel(const download_async_handle &control)
Definition: download.cpp:299
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash)
Definition: util.cpp:933
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
bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash)
Definition: updates.cpp:41
std::string get_default_data_dir()
Returns the default data directory.
Definition: util.cpp:600
boost::filesystem::path data_dir
Definition: main.cpp:50
#define false
Definition: stdbool.h:38
unsigned int uint32_t
Definition: stdint.h:126
unsigned char uint8_t
Definition: stdint.h:124
unsigned __int64 uint64_t
Definition: stdint.h:136
epee::misc_utils::struct_init< request_t > request
std::vector< blobdata > txs
blobdata block
std::vector< crypto::hash > tx_hashes
virtual bool relay_block(NOTIFY_NEW_BLOCK::request &arg, cryptonote_connection_context &exclude_context)=0
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &exclude_context)=0
Definition: options.h:87
uint8_t type
Definition: rctTypes.h:241
Definition: blake256.h:37
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
rapidjson::Document json
Definition: transport.cpp:49
DISABLE_VS_WARNINGS(4244 4345 4503) using namespace crypto
const char *const ELECTRONEUM_VERSION