Electroneum
Loading...
Searching...
No Matches
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"
35using 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
69namespace 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 //-----------------------------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------------
280 void core::set_checkpoints_file_path(const std::string& path)
281 {
282 m_checkpoints_path = path;
283 }
284 //-----------------------------------------------------------------------------------
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 {
315 }
316 return res;
317 }
318 //-----------------------------------------------------------------------------------
320 return m_validators->getSerializedValidatorList();
321 }
322 //-----------------------------------------------------------------------------------
323 electroneum::basic::list_update_outcome core::set_validators_list(std::string v_list, bool isEmergencyUpdate) {
324 return m_validators->setValidatorsList(v_list, true, isEmergencyUpdate);
325 }
326
328 return m_validators->isValid();
329 }
330 //-----------------------------------------------------------------------------------
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)
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
383 }
384 //-----------------------------------------------------------------------------------------------
385 bool core::handle_command_line(const boost::program_options::variables_map& vm)
386 {
387 if (m_nettype != FAKECHAIN)
388 {
389 const bool testnet = command_line::get_arg(vm, arg_testnet_on);
390 const bool stagenet = command_line::get_arg(vm, arg_stagenet_on);
391 m_nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
392 }
393
394 m_config_folder = command_line::get_arg(vm, arg_data_dir);
395
396 auto data_dir = boost::filesystem::path(m_config_folder);
397
398 if (m_nettype == MAINNET || m_nettype == TESTNET)
399 {
401 if (!checkpoints.init_default_checkpoints(m_nettype))
402 {
403 throw std::runtime_error("Failed to initialize checkpoints");
404 }
405 //set the pow fallback checkpoint if required
406 if(m_fallback_to_pow_checkpoint_height != 0 && m_fallback_to_pow_checkpoint_hash != ""){
407 checkpoints.add_checkpoint(m_fallback_to_pow_checkpoint_height, m_fallback_to_pow_checkpoint_hash);
408 }
409
410 set_checkpoints(std::move(checkpoints));
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
513 std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type);
514 std::string db_sync_mode = command_line::get_arg(vm, cryptonote::arg_db_sync_mode);
515 bool db_salvage = command_line::get_arg(vm, cryptonote::arg_db_salvage) != 0;
516 bool addr_db_salvage = command_line::get_arg(vm, cryptonote::arg_addr_db_salvage) != 0;
517 bool fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
518 uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
519 std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
520 size_t max_txpool_weight = command_line::get_arg(vm, arg_max_txpool_weight);
521 bool prune_blockchain = command_line::get_arg(vm, arg_prune_blockchain);
522 std::string validator_key = command_line::get_arg(vm, arg_validator_key);
523
524 bool is_validator_key_valid = std::count_if(validator_key.begin(), validator_key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
525 if(!is_validator_key_valid || validator_key.size() % 2 != 0) {
526 validator_key.clear();
527 }
528
529 boost::filesystem::path folder(m_config_folder);
530 if (m_nettype == FAKECHAIN)
531 folder /= "fake";
532
533 // make sure the data directory exists, and try to lock it
534 CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false,
535 std::string("Failed to create directory ").append(folder.string()).c_str());
536
537 // check for blockchain.bin
538 try
539 {
540 const boost::filesystem::path old_files = folder;
541 if (boost::filesystem::exists(old_files / "blockchain.bin"))
542 {
543 MWARNING("Found old-style blockchain.bin in " << old_files.string());
544 MWARNING("Electroneum now uses a new format. You can either remove blockchain.bin to start syncing");
545 MWARNING("the blockchain anew, or use electroneum-blockchain-export and electroneum-blockchain-import to");
546 MWARNING("convert your existing blockchain.bin to the new format. See README.md for instructions.");
547 return false;
548 }
549 }
550 // folder might not be a directory, etc, etc
551 catch (...) { }
552
553 std::unique_ptr<BlockchainDB> db(new_db(db_type));
554 if (db == NULL)
555 {
556 LOG_ERROR("Attempted to use non-existent database type");
557 return false;
558 }
559
560 folder /= db->get_db_name();
561 MGINFO("Loading blockchain from folder " << folder.string() << " ...");
562
563 const std::string filename = folder.string();
564 // default to fast:async:1 if overridden
566 bool sync_on_blocks = true;
567 uint64_t sync_threshold = 1;
568
569 if (m_nettype == FAKECHAIN)
570 {
571 // reset the db by removing the database file before opening it
572 if (!db->remove_data_file(filename))
573 {
574 MERROR("Failed to remove data file in " << filename);
575 return false;
576 }
577 }
578
579 try
580 {
581 uint64_t db_flags = 0;
582
583 std::vector<std::string> options;
584 boost::trim(db_sync_mode);
585 boost::split(options, db_sync_mode, boost::is_any_of(" :"));
586 const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode);
587
588 for(const auto &option : options)
589 MDEBUG("option: " << option);
590
591 // default to fast:async:1
592 uint64_t DEFAULT_FLAGS = DBF_FAST;
593
594 if(options.size() == 0)
595 {
596 // default to fast:async:1
597 db_flags = DEFAULT_FLAGS;
598 }
599
600 bool safemode = false;
601 if(options.size() >= 1)
602 {
603 if(options[0] == "safe")
604 {
605 safemode = true;
606 db_flags = DBF_SAFE;
607 sync_mode = db_sync_mode_is_default ? db_defaultsync : db_nosync;
608 }
609 else if(options[0] == "fast")
610 {
611 db_flags = DBF_FAST;
612 sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
613 }
614 else if(options[0] == "fastest")
615 {
616 db_flags = DBF_FASTEST;
617 sync_threshold = 1000; // default to fastest:async:1000
618 sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
619 }
620 else
621 db_flags = DEFAULT_FLAGS;
622 }
623
624 if(options.size() >= 2 && !safemode)
625 {
626 if(options[1] == "sync")
627 sync_mode = db_sync_mode_is_default ? db_defaultsync : db_sync;
628 else if(options[1] == "async")
629 sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async;
630 }
631
632 if(options.size() >= 3 && !safemode)
633 {
634 char *endptr;
635 uint64_t threshold = strtoull(options[2].c_str(), &endptr, 0);
636 if (*endptr == '\0' || !strcmp(endptr, "blocks"))
637 {
638 sync_on_blocks = true;
639 sync_threshold = threshold;
640 }
641 else if (!strcmp(endptr, "bytes"))
642 {
643 sync_on_blocks = false;
644 sync_threshold = threshold;
645 }
646 else
647 {
648 LOG_ERROR("Invalid db sync mode: " << options[2]);
649 return false;
650 }
651 }
652
653 if (db_salvage)
654 db_flags |= DBF_SALVAGE;
655
656 if(addr_db_salvage)
657 db_flags |= DBF_ADDR_TX_SALVAGE;
658
659 db->open(filename, db_flags);
660 if(!db->m_open)
661 return false;
662 }
663 catch (const DB_ERROR& e)
664 {
665 LOG_ERROR("Error opening database: " << e.what());
666 return false;
667 }
668
669 m_blockchain_storage.set_user_options(blocks_threads,
670 sync_on_blocks, sync_threshold, sync_mode, fast_sync, validator_key);
671
672 try
673 {
674 if (!command_line::is_arg_defaulted(vm, arg_block_notify))
675 m_blockchain_storage.set_block_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_block_notify).c_str())));
676 }
677 catch (const std::exception &e)
678 {
679 MERROR("Failed to parse block notify spec: " << e.what());
680 }
681
682 try
683 {
684 if (!command_line::is_arg_defaulted(vm, arg_reorg_notify))
685 m_blockchain_storage.set_reorg_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_reorg_notify).c_str())));
686 }
687 catch (const std::exception &e)
688 {
689 MERROR("Failed to parse reorg notify spec: " << e.what());
690 }
691
692 try
693 {
694 if (!command_line::is_arg_defaulted(vm, arg_block_rate_notify))
695 m_block_rate_notify.reset(new tools::Notify(command_line::get_arg(vm, arg_block_rate_notify).c_str()));
696 }
697 catch (const std::exception &e)
698 {
699 MERROR("Failed to parse block rate notify spec: " << e.what());
700 }
701
702 const std::pair<uint8_t, uint64_t> regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
703 const cryptonote::test_options regtest_test_options = {
704 regtest_hard_forks,
705 0
706 };
707 const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty);
708 const bool ignore_bsig = command_line::get_arg(vm, arg_skip_block_sig_verification);
709
710 r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints, ignore_bsig, m_fallback_to_pow);
711
712 r = m_mempool.init(max_txpool_weight);
713 CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
714
715 // now that we have a valid m_blockchain_storage, we can clean out any
716 // transactions in the pool that do not conform to the current fork
717 m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
718
719 bool show_time_stats = command_line::get_arg(vm, arg_show_time_stats) != 0;
720 m_blockchain_storage.set_show_time_stats(show_time_stats);
721 CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
722
723 block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
724
725 MGINFO("Loading checkpoints");
726
727 // load json & DNS checkpoints, and verify them
728 // with respect to what blocks we already have
729 CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
730
731 // DNS versions checking
732 if (check_updates_string == "disabled")
733 check_updates_level = UPDATES_DISABLED;
734 else if (check_updates_string == "notify")
735 check_updates_level = UPDATES_NOTIFY;
736 else if (check_updates_string == "download")
737 check_updates_level = UPDATES_DOWNLOAD;
738 else if (check_updates_string == "update")
739 check_updates_level = UPDATES_UPDATE;
740 else {
741 MERROR("Invalid argument to --dns-versions-check: " << check_updates_string);
742 return false;
743 }
744
745 check_updates_level = UPDATES_DISABLED;
746
747 r = m_miner.init(vm, m_nettype, m_fallback_to_pow);
748 CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance");
749
751 {
752 // display a message if the blockchain is not pruned yet
753 if (!m_blockchain_storage.get_blockchain_pruning_seed())
754 {
755 MGINFO("Pruning blockchain...");
756 CHECK_AND_ASSERT_MES(m_blockchain_storage.prune_blockchain(), false, "Failed to prune blockchain");
757 }
758 else
759 {
760 CHECK_AND_ASSERT_MES(m_blockchain_storage.update_blockchain_pruning(), false, "Failed to update blockchain pruning");
761 }
762 }
763
764 if(!m_fallback_to_pow) {
765 m_validators = std::unique_ptr<electroneum::basic::Validators>(new electroneum::basic::Validators(m_blockchain_storage.get_db(), m_pprotocol, m_nettype == TESTNET));
766 m_blockchain_storage.set_validators_list_instance(m_validators);
767
768 if(m_blockchain_storage.get_current_blockchain_height() >= ((m_nettype == TESTNET ? 446674 : 589169) - 720 )) { //V8 Height - 1 day
769 m_validators->enable();
770 }
771 }
772
773 return load_state_data();
774 }
775 //-----------------------------------------------------------------------------------------------
777 {
778 return m_blockchain_storage.reset_and_set_genesis_block(b);
779 }
780 //-----------------------------------------------------------------------------------------------
781 bool core::load_state_data()
782 {
783 // may be some code later
784 return true;
785 }
786 //-----------------------------------------------------------------------------------------------
788 {
789 m_miner.stop();
790 m_mempool.deinit();
791 m_blockchain_storage.deinit();
792 return true;
793 }
794 //-----------------------------------------------------------------------------------------------
796 {
797 m_test_drop_download = false;
798 }
799 //-----------------------------------------------------------------------------------------------
801 {
802 m_test_drop_download_height = height;
803 }
804 //-----------------------------------------------------------------------------------------------
806 {
807 return m_test_drop_download;
808 }
809 //-----------------------------------------------------------------------------------------------
811 {
812 if (m_test_drop_download_height == 0)
813 return true;
814
815 if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height)
816 return true;
817
818 return false;
819 }
820 //-----------------------------------------------------------------------------------------------
821 bool core::handle_incoming_tx_pre(const blobdata& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash, bool keeped_by_block, bool relayed, bool do_not_relay)
822 {
823 tvc = boost::value_initialized<tx_verification_context>();
824
825 if(tx_blob.size() > get_max_tx_size())
826 {
827 LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected");
828 tvc.m_verification_failed = true;
829 tvc.m_too_big = true;
830 return false;
831 }
832
833 tx_hash = crypto::null_hash;
834
835 if(!parse_tx_from_blob(tx, tx_hash, tx_blob))
836 {
837 LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected");
838 tvc.m_verification_failed = true;
839 return false;
840 }
841 //std::cout << "!"<< tx.vin.size() << std::endl;
842
843 bad_semantics_txes_lock.lock();
844 for (int idx = 0; idx < 2; ++idx)
845 {
846 if (bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end())
847 {
848 bad_semantics_txes_lock.unlock();
849 LOG_PRINT_L1("Transaction already seen with bad semantics, rejected");
850 tvc.m_verification_failed = true;
851 return false;
852 }
853 }
854 bad_semantics_txes_lock.unlock();
855
856 uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
857
858 const size_t max_tx_version = version < HF_VERSION_PUBLIC_TX ? 1 : 3;
859 if (tx.version == 0 || tx.version > max_tx_version)
860 {
861 // v2 is the latest one we know
862 tvc.m_verification_failed = true;
863 return false;
864 }
865
866 const size_t min_tx_version = version >= HF_VERSION_PUBLIC_TX ? 2 : 1;
867 if (tx.version < min_tx_version)
868 {
869 tvc.m_verification_failed = true;
870 return false;
871 }
872
873 return true;
874 }
875 //-----------------------------------------------------------------------------------------------
876 bool core::handle_incoming_tx_post(const blobdata& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash, bool keeped_by_block, bool relayed, bool do_not_relay)
877 {
878 if(!check_tx_syntax(tx))
879 {
880 LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected");
881 tvc.m_verification_failed = true;
882 return false;
883 }
884
885 return true;
886 }
887 //-----------------------------------------------------------------------------------------------
888 void core::set_semantics_failed(const crypto::hash &tx_hash)
889 {
890 LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
891 bad_semantics_txes_lock.lock();
892 bad_semantics_txes[0].insert(tx_hash);
893 if (bad_semantics_txes[0].size() >= BAD_SEMANTICS_TXES_MAX_SIZE)
894 {
895 std::swap(bad_semantics_txes[0], bad_semantics_txes[1]);
896 bad_semantics_txes[0].clear();
897 }
898 bad_semantics_txes_lock.unlock();
899 }
900 //-----------------------------------------------------------------------------------------------
901 bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block)
902 {
903 bool ret = true;
904 if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
905 {
906 MTRACE("Skipping semantics check for tx kept by block in embedded hash area");
907 return true;
908 }
909
910 std::vector<const rct::rctSig*> rvv;
911 for (size_t n = 0; n < tx_info.size(); ++n)
912 {
913 if (!check_tx_semantic(*tx_info[n].tx, keeped_by_block))
914 {
915 set_semantics_failed(tx_info[n].tx_hash);
916 tx_info[n].tvc.m_verification_failed = true;
917 tx_info[n].result = false;
918 continue;
919 }
920 }
921 if (!rvv.empty() && !rct::verRctSemanticsSimple(rvv))
922 {
923 LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
924 ret = false;
925 const bool assumed_bad = rvv.size() == 1; // if there's only one tx, it must be the bad one
926 for (size_t n = 0; n < tx_info.size(); ++n)
927 {
928 if (!tx_info[n].result)
929 continue;
930 if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2)
931 continue;
932 if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
933 {
934 set_semantics_failed(tx_info[n].tx_hash);
935 tx_info[n].tvc.m_verification_failed = true;
936 tx_info[n].result = false;
937 }
938 }
939 }
940
941 return ret;
942 }
943 //-----------------------------------------------------------------------------------------------
944 bool core::handle_incoming_txs(const std::vector<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
945 {
946 TRY_ENTRY();
947 CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
948
949 struct result { bool res; cryptonote::transaction tx; crypto::hash hash; };
950 std::vector<result> results(tx_blobs.size());
951
952 tvc.resize(tx_blobs.size());
955 std::vector<blobdata>::const_iterator it = tx_blobs.begin();
956 for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
957 tpool.submit(&waiter, [&, i, it] {
958 try
959 {
960 results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
961 }
962 catch (const std::exception &e)
963 {
964 MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what());
965 tvc[i].m_verification_failed = true;
966 results[i].res = false;
967 }
968 });
969 }
970 waiter.wait(&tpool);
971 it = tx_blobs.begin();
972 std::vector<bool> already_have(tx_blobs.size(), false);
973 for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
974 if (!results[i].res)
975 continue;
976 if(m_mempool.have_tx(results[i].hash))
977 {
978 LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool");
979 already_have[i] = true;
980 }
981 else if(m_blockchain_storage.have_tx(results[i].hash))
982 {
983 LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain");
984 already_have[i] = true;
985 }
986 else
987 {
988 tpool.submit(&waiter, [&, i, it] {
989 try
990 {
991 results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
992 }
993 catch (const std::exception &e)
994 {
995 MERROR_VER("Exception in handle_incoming_tx_post: " << e.what());
996 tvc[i].m_verification_failed = true;
997 results[i].res = false;
998 }
999 });
1000 }
1001 }
1002 waiter.wait(&tpool);
1003
1004 std::vector<tx_verification_batch_info> tx_info;
1005 tx_info.reserve(tx_blobs.size());
1006 for (size_t i = 0; i < tx_blobs.size(); i++) {
1007 if (!results[i].res || already_have[i])
1008 continue;
1009 tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
1010 }
1011 if (!tx_info.empty())
1012 handle_incoming_tx_accumulated_batch(tx_info, keeped_by_block);
1013
1014 bool ok = true;
1015 it = tx_blobs.begin();
1016 for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
1017 if (!results[i].res)
1018 {
1019 ok = false;
1020 continue;
1021 }
1022 if (keeped_by_block)
1024 if (already_have[i])
1025 continue;
1026
1027 const size_t weight = get_transaction_weight(results[i].tx, it->size());
1028 ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], weight, tvc[i], keeped_by_block, relayed, do_not_relay);
1029 if(tvc[i].m_verification_failed)
1030 {MERROR_VER("Transaction verification failed: " << results[i].hash);}
1031 else if(tvc[i].m_verification_impossible)
1032 {MERROR_VER("Transaction verification impossible: " << results[i].hash);}
1033
1034 if(tvc[i].m_added_to_pool)
1035 MDEBUG("tx added: " << results[i].hash);
1036 }
1037 return ok;
1038
1039 CATCH_ENTRY_L0("core::handle_incoming_txs()", false);
1040 }
1041 //-----------------------------------------------------------------------------------------------
1042 bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1043 {
1044 std::vector<cryptonote::blobdata> tx_blobs;
1045 tx_blobs.push_back(tx_blob);
1046 std::vector<tx_verification_context> tvcv(1);
1047 bool r = handle_incoming_txs(tx_blobs, tvcv, keeped_by_block, relayed, do_not_relay);
1048 tvc = tvcv[0];
1049 return r;
1050 }
1051 //-----------------------------------------------------------------------------------------------
1053 {
1054 st_inf.mining_speed = m_miner.get_speed();
1055 st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count();
1056 st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1057 st_inf.tx_pool_size = m_mempool.get_transactions_count();
1058 st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_tail_id());
1059 return true;
1060 }
1061
1062 //-----------------------------------------------------------------------------------------------
1063 bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const
1064 {
1065 if(!tx.vin.size())
1066 {
1067 MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
1068 return false;
1069 }
1070
1072 {
1073 MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx));
1074 return false;
1075 }
1076
1077 if(!check_outs_valid(tx))
1078 {
1079 MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
1080 return false;
1081 }
1082
1083 if(!check_etn_overflow(tx))
1084 {
1085 MERROR_VER("tx has ETN overflow, rejected for tx id= " << get_transaction_hash(tx));
1086 return false;
1087 }
1088
1089 uint64_t amount_in = 0;
1090 get_inputs_etn_amount(tx, amount_in);
1091 uint64_t amount_out = get_outs_etn_amount(tx);
1092 // v1 & v2 tx ins/outs semantics are checked in the same way regardless of our chains height or the network height
1093 if((tx.version == 1 && amount_in <= amount_out) || (tx.version == 2 && amount_in != amount_out)) {
1094
1095 MERROR_VER("V" << tx.version << " tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1096 << get_transaction_hash(tx));
1097 return false;
1098 }
1099
1100 if (tx.version == 3) {
1101 // if we find a single output that isn't to the bridge, ensure it's a fee paying tx, then carry with other semantic checks
1102 bool only_bridge_dests = true;
1103 std::string portal_address_viewkey_hex_str;
1104 std::string portal_address_spendkey_hex_str;
1105 if(m_nettype == MAINNET){
1106 portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375"; //private view is just e5c8af002654f38ec39ac80edbbcd0c03c9b483379d297af0c3ca15568c7300e
1107 portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137"; // from hash_to_point(v9 fork)
1108 }else{
1109 portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
1110 portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
1111 }
1112
1113 for (auto output: tx.vout){
1114 const auto out = boost::get<txout_to_key_public>(output.target);
1115 std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
1116 std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
1117 if(out_spendkey_str != portal_address_spendkey_hex_str || out_viewkey_str != portal_address_viewkey_hex_str){
1118 only_bridge_dests = false;
1119 if(amount_in <= amount_out){
1120 MERROR_VER("v3 tx with some outs not going to the bridge should be fee paying: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1121 << get_transaction_hash(tx));
1122 return false;
1123 }
1124 break;
1125 }
1126 }
1127 if (only_bridge_dests && amount_in < amount_out){ // allow both fee paying (pre fork) and feeless (post fork)
1128 MERROR_VER("v3 sc_migration tx has wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= "
1129 << get_transaction_hash(tx));
1130 return false;
1131 }
1132 }
1133 // for version > 1, ringct signatures check verifies amounts match
1134
1135 if(!keeped_by_block && get_transaction_weight(tx) >= m_blockchain_storage.get_current_cumulative_block_weight_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE)
1136 {
1137 MERROR_VER("tx is too large " << get_transaction_weight(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_block_weight_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
1138 return false;
1139 }
1140
1141 if(tx.version >= 3)
1142 {
1143 //check if tx use different utxos
1144 if(!check_tx_inputs_utxos_diff(tx))
1145 {
1146 MERROR_VER("tx uses a single utxo more than once");
1147 return false;
1148 }
1149 }
1150 else
1151 {
1152 //check if tx use different key images
1153 if(!check_tx_inputs_keyimages_diff(tx))
1154 {
1155 MERROR_VER("tx uses a single key image more than once");
1156 return false;
1157 }
1158
1159 if (!check_tx_inputs_keyimages_domain(tx))
1160 {
1161 MERROR_VER("tx uses key image not in the valid domain");
1162 return false;
1163 }
1164 }
1165
1166 return true;
1167 }
1168 //-----------------------------------------------------------------------------------------------
1169 bool core::is_key_image_spent(const crypto::key_image &key_image) const
1170 {
1171 return m_blockchain_storage.have_tx_keyimg_as_spent(key_image);
1172 }
1173 //-----------------------------------------------------------------------------------------------
1174 bool core::are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1175 {
1176 spent.clear();
1177 for(auto& ki: key_im)
1178 {
1179 spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki));
1180 }
1181 return true;
1182 }
1183 //-----------------------------------------------------------------------------------------------
1184 bool core::utxo_nonexistant(const std::vector<txin_to_key_public>& public_outputs, std::vector<bool> &spent) const
1185 {
1186 spent.clear();
1187 for(auto& po: public_outputs)
1188 {
1189 spent.push_back(m_blockchain_storage.utxo_nonexistence_from_output(po));
1190 }
1191 return true;
1192 }
1193 //-----------------------------------------------------------------------------------------------
1195 {
1196 static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
1197 if (block_sync_size > 0)
1198 return block_sync_size;
1199 if (height >= quick_height)
1202 }
1203 //-----------------------------------------------------------------------------------------------
1204 bool core::are_key_images_spent_in_pool(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
1205 {
1206 spent.clear();
1207 return m_mempool.check_for_key_images(key_im, spent);
1208 }
1209 //-----------------------------------------------------------------------------------------------
1210 std::pair<uint64_t, uint64_t> core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count)
1211 {
1212 uint64_t emission_amount = 0;
1213 uint64_t total_fee_amount = 0;
1214 if (count)
1215 {
1216 const uint64_t end = start_offset + count - 1;
1217 m_blockchain_storage.for_blocks_range(start_offset, end,
1218 [this, &emission_amount, &total_fee_amount](uint64_t, const crypto::hash& hash, const block& b){
1219 std::vector<transaction> txs;
1220 std::vector<crypto::hash> missed_txs;
1221 uint64_t coinbase_amount = get_outs_etn_amount(b.miner_tx);
1222 this->get_transactions(b.tx_hashes, txs, missed_txs);
1223 uint64_t tx_fee_amount = 0;
1224 for(const auto& tx: txs)
1225 {
1226 tx_fee_amount += get_tx_fee(tx);
1227 }
1228
1229 emission_amount += coinbase_amount - tx_fee_amount;
1230 total_fee_amount += tx_fee_amount;
1231 return true;
1232 });
1233 }
1234
1235 return std::pair<uint64_t, uint64_t>(emission_amount, total_fee_amount);
1236 }
1237 //-----------------------------------------------------------------------------------------------
1238 bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const
1239 {
1240 std::unordered_set<crypto::key_image> ki;
1241 for(const auto& in: tx.vin)
1242 {
1243 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1244 if(!ki.insert(tokey_in.k_image).second)
1245 return false;
1246 }
1247 return true;
1248 }
1249 //-----------------------------------------------------------------------------------------------
1250 bool core::check_tx_inputs_utxos_diff(const transaction& tx) const
1251 {
1252 std::unordered_set<std::string> ins;
1253 for(const auto& in: tx.vin)
1254 {
1255 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, tokey_in, false);
1256 if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
1257 return false;
1258 }
1259 return true;
1260 }
1261 //-----------------------------------------------------------------------------------------------
1262 bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const
1263 {
1264 const uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1266 {
1267 for(const auto& in: tx.vin)
1268 {
1269 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1270 for (size_t n = 1; n < tokey_in.key_offsets.size(); ++n)
1271 if (tokey_in.key_offsets[n] == 0)
1272 return false;
1273 }
1274 }
1275 return true;
1276 }
1277 //-----------------------------------------------------------------------------------------------
1278 bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const
1279 {
1280 std::unordered_set<crypto::key_image> ki;
1281 for(const auto& in: tx.vin)
1282 {
1283 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
1284 if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity()))
1285 return false;
1286 }
1287 return true;
1288 }
1289 //-----------------------------------------------------------------------------------------------
1290 bool core::add_new_tx(transaction& tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1291 {
1292 crypto::hash tx_hash = get_transaction_hash(tx);
1293 blobdata bl;
1295 size_t tx_weight = get_transaction_weight(tx, bl.size());
1296 return add_new_tx(tx, tx_hash, bl, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
1297 }
1298 //-----------------------------------------------------------------------------------------------
1300 {
1301 return m_blockchain_storage.get_total_transactions();
1302 }
1303 //-----------------------------------------------------------------------------------------------
1304 bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
1305 {
1306
1307 if(m_mempool.have_tx(tx_hash))
1308 {
1309 LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool");
1310 return true;
1311 }
1312
1313 if(m_blockchain_storage.have_tx(tx_hash))
1314 {
1315 LOG_PRINT_L2("tx " << tx_hash << " already have transaction in blockchain");
1316 return true;
1317 }
1318
1319 uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1320 return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version);
1321 }
1322 //-----------------------------------------------------------------------------------------------
1323 bool core::relay_txpool_transactions()
1324 {
1325 // we attempt to relay txes that should be relayed, but were not
1326 std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1327 if (m_mempool.get_relayable_transactions(txs) && !txs.empty())
1328 {
1329 cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
1330 tx_verification_context tvc = AUTO_VAL_INIT(tvc);
1332 for (auto it = txs.begin(); it != txs.end(); ++it)
1333 {
1334 r.txs.push_back(it->second);
1335 }
1336 get_protocol()->relay_transactions(r, fake_context);
1337 m_mempool.set_relayed(txs);
1338 }
1339 return true;
1340 }
1341 //-----------------------------------------------------------------------------------------------
1343 {
1344 std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1346 crypto::hash tx_hash;
1347 if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
1348 {
1349 LOG_ERROR("Failed to parse relayed transaction");
1350 return;
1351 }
1352 txs.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
1353 m_mempool.set_relayed(txs);
1354 }
1355 //-----------------------------------------------------------------------------------------------
1356 bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1357 {
1358 return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce);
1359 }
1360 //-----------------------------------------------------------------------------------------------
1361 bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
1362 {
1363 return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce);
1364 }
1365 //-----------------------------------------------------------------------------------------------
1366 bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
1367 {
1368 return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
1369 }
1370 //-----------------------------------------------------------------------------------------------
1371 bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
1372 {
1373 return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_count);
1374 }
1375 //-----------------------------------------------------------------------------------------------
1377 {
1378 return m_blockchain_storage.get_outs(req, res);
1379 }
1380 //-----------------------------------------------------------------------------------------------
1381 bool core::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) const
1382 {
1383 return m_blockchain_storage.get_output_distribution(amount, from_height, to_height, start_height, distribution, base);
1384 }
1385 //-----------------------------------------------------------------------------------------------
1386 bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const
1387 {
1388 return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs);
1389 }
1390 //-----------------------------------------------------------------------------------------------
1391 bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, size_t n_txes, std::vector<std::vector<uint64_t>>& indexs) const
1392 {
1393 return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, n_txes, indexs);
1394 }
1395 //-----------------------------------------------------------------------------------------------
1397 {
1398 m_miner.pause();
1399 }
1400 //-----------------------------------------------------------------------------------------------
1402 {
1403 m_miner.resume();
1404 }
1405 //-----------------------------------------------------------------------------------------------
1407 {
1410 for (const auto &tx_hash: b.tx_hashes)
1411 {
1412 cryptonote::blobdata txblob;
1413 CHECK_AND_ASSERT_THROW_MES(pool.get_transaction(tx_hash, txblob), "Transaction not found in pool");
1414 bce.txs.push_back(txblob);
1415 }
1416 return bce;
1417 }
1418 //-----------------------------------------------------------------------------------------------
1420 {
1421 bvc = boost::value_initialized<block_verification_context>();
1422 m_miner.pause();
1423 std::vector<block_complete_entry> blocks;
1424 try
1425 {
1426 blocks.push_back(get_block_complete_entry(b, m_mempool));
1427 }
1428 catch (const std::exception &e)
1429 {
1430 m_miner.resume();
1431 return false;
1432 }
1433 std::vector<block> pblocks;
1435 {
1436 MERROR("Block found, but failed to prepare to add");
1437 m_miner.resume();
1438 return false;
1439 }
1440 m_blockchain_storage.add_new_block(b, bvc);
1442
1443 CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Mined block failed verification");
1444 if(bvc.m_added_to_main_chain)
1445 {
1446 cryptonote_connection_context exclude_context = boost::value_initialized<cryptonote_connection_context>();
1448 arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
1449 std::vector<crypto::hash> missed_txs;
1450 std::vector<cryptonote::blobdata> txs;
1451 m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, missed_txs);
1452 if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b))
1453 {
1454 LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block");
1455 return true;
1456 }
1457 CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size()
1458 << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size());
1459
1460 block_to_blob(b, arg.b.block);
1461 //pack transactions
1462 for(auto& tx: txs)
1463 arg.b.txs.push_back(tx);
1464
1465 m_pprotocol->relay_block(arg, exclude_context);
1466
1467 if(m_fallback_to_pow) {
1468 m_miner.resume();
1469 }
1470 } else {
1471 update_miner_block_template();
1472 m_miner.resume();
1473 }
1474 return true;
1475 }
1476 //-----------------------------------------------------------------------------------------------
1478 {
1479 m_miner.on_synchronized();
1480 }
1481 //-----------------------------------------------------------------------------------------------
1482 void core::safesyncmode(const bool onoff)
1483 {
1484 m_blockchain_storage.safesyncmode(onoff);
1485 }
1486 //-----------------------------------------------------------------------------------------------
1487 bool core::add_new_block(const block& b, block_verification_context& bvc)
1488 {
1489 return m_blockchain_storage.add_new_block(b, bvc);
1490 }
1491
1492 //-----------------------------------------------------------------------------------------------
1493 bool core::prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks)
1494 {
1495 m_incoming_tx_lock.lock();
1496 if (!m_blockchain_storage.prepare_handle_incoming_blocks(blocks_entry, blocks))
1497 {
1499 return false;
1500 }
1501 return true;
1502 }
1503
1504 //-----------------------------------------------------------------------------------------------
1506 {
1507 bool success = false;
1508 try {
1509 success = m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync);
1510 }
1511 catch (...) {}
1512 m_incoming_tx_lock.unlock();
1513 return success;
1514 }
1515
1516 //-----------------------------------------------------------------------------------------------
1517 bool core::handle_incoming_block(const blobdata& block_blob, const block *b, block_verification_context& bvc, bool update_miner_blocktemplate)
1518 {
1519 TRY_ENTRY();
1520
1521 bvc = boost::value_initialized<block_verification_context>();
1522
1523 if (!check_incoming_block_size(block_blob))
1524 {
1525 bvc.m_verification_failed = true;
1526 return false;
1527 }
1528
1529 if (((size_t)-1) <= 0xffffffff && block_blob.size() >= 0x3fffffff)
1530 MWARNING("This block's size is " << block_blob.size() << ", closing on the 32 bit limit");
1531
1532 // load json & DNS checkpoints every 10min/hour respectively,
1533 // and verify them with respect to what blocks we already have
1534 CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
1535
1536 block lb;
1537 if (!b)
1538 {
1539 crypto::hash block_hash;
1540 if(!parse_and_validate_block_from_blob(block_blob, lb, block_hash))
1541 {
1542 LOG_PRINT_L1("Failed to parse and validate new block");
1543 bvc.m_verification_failed = true;
1544 return false;
1545 }
1546 b = &lb;
1547 }
1548
1549 add_new_block(*b, bvc);
1550
1551 if(bvc.m_added_to_main_chain) {
1552 m_miner.resume();
1553
1554 if(update_miner_blocktemplate)
1555 update_miner_block_template();
1556 }
1557
1558 return true;
1559
1560 CATCH_ENTRY_L0("core::handle_incoming_block()", false);
1561 }
1562 //-----------------------------------------------------------------------------------------------
1563 // Used by the RPC server to check the size of an incoming
1564 // block_blob
1565 bool core::check_incoming_block_size(const blobdata& block_blob) const
1566 {
1567 // note: we assume block weight is always >= block blob size, so we check incoming
1568 // blob size against the block weight limit, which acts as a sanity check without
1569 // having to parse/weigh first; in fact, since the block blob is the block header
1570 // plus the tx hashes, the weight will typically be much larger than the blob size
1571 if(block_blob.size() > m_blockchain_storage.get_current_cumulative_block_weight_limit() + BLOCK_SIZE_SANITY_LEEWAY)
1572 {
1573 LOG_PRINT_L1("WRONG BLOCK BLOB, sanity check failed on size " << block_blob.size() << ", rejected");
1574 return false;
1575 }
1576 return true;
1577 }
1578 //-----------------------------------------------------------------------------------------------
1580 {
1581 return m_blockchain_storage.get_tail_id();
1582 }
1583 //-----------------------------------------------------------------------------------------------
1585 {
1586 return m_blockchain_storage.get_db().set_block_cumulative_difficulty(height, diff);
1587 }
1588 //-----------------------------------------------------------------------------------------------
1590 {
1591 return m_blockchain_storage.get_db().get_block_cumulative_difficulty(height);
1592 }
1593 //-----------------------------------------------------------------------------------------------
1595 {
1596 return m_mempool.get_transactions_count();
1597 }
1598 //-----------------------------------------------------------------------------------------------
1599 bool core::have_block(const crypto::hash& id) const
1600 {
1601 return m_blockchain_storage.have_block(id);
1602 }
1603 //-----------------------------------------------------------------------------------------------
1604 bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const
1605 {
1606 return parse_and_validate_tx_from_blob(blob, tx, tx_hash);
1607 }
1608 //-----------------------------------------------------------------------------------------------
1609 bool core::check_tx_syntax(const transaction& tx) const
1610 {
1611 return true;
1612 }
1613 //-----------------------------------------------------------------------------------------------
1614 bool core::get_pool_transactions(std::vector<transaction>& txs, bool include_sensitive_data) const
1615 {
1616 m_mempool.get_transactions(txs, include_sensitive_data);
1617 return true;
1618 }
1619 //-----------------------------------------------------------------------------------------------
1620 bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_data) const
1621 {
1622 m_mempool.get_transaction_hashes(txs, include_sensitive_data);
1623 return true;
1624 }
1625 //-----------------------------------------------------------------------------------------------
1626 bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const
1627 {
1628 m_mempool.get_transaction_stats(stats, include_sensitive_data);
1629 return true;
1630 }
1631 //-----------------------------------------------------------------------------------------------
1633 {
1634 return m_mempool.get_transaction(id, tx);
1635 }
1636 //-----------------------------------------------------------------------------------------------
1637 bool core::pool_has_tx(const crypto::hash &id) const
1638 {
1639 return m_mempool.have_tx(id);
1640 }
1641 //-----------------------------------------------------------------------------------------------
1643 {
1644 return m_mempool.utxo_spent_in_pool(in);
1645 }
1646 //-----------------------------------------------------------------------------------------------
1647 bool core::get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_sensitive_data) const
1648 {
1649 return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos, include_sensitive_data);
1650 }
1651 //-----------------------------------------------------------------------------------------------
1652 bool core::get_pool_for_rpc(std::vector<cryptonote::rpc::tx_in_pool>& tx_infos, cryptonote::rpc::key_images_with_tx_hashes& key_image_infos) const
1653 {
1654 return m_mempool.get_pool_for_rpc(tx_infos, key_image_infos);
1655 }
1656 //-----------------------------------------------------------------------------------------------
1657 bool core::get_short_chain_history(std::list<crypto::hash>& ids) const
1658 {
1659 return m_blockchain_storage.get_short_chain_history(ids);
1660 }
1661 //-----------------------------------------------------------------------------------------------
1663 {
1664 return m_blockchain_storage.handle_get_objects(arg, rsp);
1665 }
1666 //-----------------------------------------------------------------------------------------------
1668 {
1669 return m_blockchain_storage.get_block_id_by_height(height);
1670 }
1671 //-----------------------------------------------------------------------------------------------
1672 bool core::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
1673 {
1674 return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
1675 }
1676 //-----------------------------------------------------------------------------------------------
1677 std::string core::print_pool(bool short_format) const
1678 {
1679 return m_mempool.print_pool(short_format);
1680 }
1681 //-----------------------------------------------------------------------------------------------
1682 bool core::update_miner_block_template()
1683 {
1684 m_miner.on_block_chain_update();
1685 return true;
1686 }
1687 //-----------------------------------------------------------------------------------------------
1689 {
1690 if(!m_starter_message_showed)
1691 {
1692 std::string main_message;
1693 if (m_offline)
1694 main_message = "The daemon is running offline and will not attempt to sync to the Electroneum network.";
1695 else
1696 main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
1697 MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
1698 << main_message << ENDL
1699 << ENDL
1700 << "You can set the level of process detailization through \"set_log <level|categories>\" command," << ENDL
1701 << "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL
1702 << ENDL
1703 << "Use the \"help\" command to see the list of available commands." << ENDL
1704 << "Use \"help <command>\" to see a command's documentation." << ENDL
1705 << "**********************************************************************" << ENDL);
1706 m_starter_message_showed = true;
1707 }
1708 //Don't moan about forks for now, but keep implementation around incase we need to use it at a later stage
1709 //m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this));
1710 m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
1711 m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
1712 m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
1713 m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this));
1714 m_blockchain_pruning_interval.do_call(boost::bind(&core::update_blockchain_pruning, this));
1715 m_miner.on_idle();
1716 m_mempool.on_idle();
1717
1718 if(!m_fallback_to_pow) {
1719 m_validators->on_idle();
1720 }
1721
1722 return true;
1723 }
1724 //-----------------------------------------------------------------------------------------------
1725 bool core::check_fork_time()
1726 {
1727 if (m_nettype == FAKECHAIN)
1728 return true;
1729
1730 HardFork::State state = m_blockchain_storage.get_hard_fork_state();
1731 const el::Level level = el::Level::Warning;
1732 switch (state) {
1734 MCLOG_RED(level, "global", "**********************************************************************");
1735 MCLOG_RED(level, "global", "Last scheduled hard fork is too far in the past.");
1736 MCLOG_RED(level, "global", "We are most likely forked from the network. Daemon update needed now.");
1737 MCLOG_RED(level, "global", "**********************************************************************");
1738 break;
1740 MCLOG_RED(level, "global", "**********************************************************************");
1741 MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed soon.");
1742 MCLOG_RED(level, "global", "**********************************************************************");
1743 break;
1744 default:
1745 break;
1746 }
1747 return true;
1748 }
1749 //-----------------------------------------------------------------------------------------------
1754 //-----------------------------------------------------------------------------------------------
1759 //-----------------------------------------------------------------------------------------------
1764 //-----------------------------------------------------------------------------------------------
1769 //-----------------------------------------------------------------------------------------------
1770 bool core::check_updates()
1771 {
1772 static const char software[] = "electroneum";
1773#ifdef BUILD_TAG
1774 static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
1775 static const char subdir[] = "cli"; // because it can never be simple
1776#else
1777 static const char buildtag[] = "source";
1778 static const char subdir[] = "source"; // because it can never be simple
1779#endif
1780
1781 if (m_offline)
1782 return true;
1783
1784 if (check_updates_level == UPDATES_DISABLED)
1785 return true;
1786
1787 std::string version, hash;
1788 MCDEBUG("updates", "Checking for a new " << software << " version for " << buildtag);
1789 if (!tools::check_updates(software, buildtag, version, hash))
1790 return false;
1791
1792 if (tools::vercmp(version.c_str(), ELECTRONEUM_VERSION) <= 0)
1793 {
1794 m_update_available = false;
1795 return true;
1796 }
1797
1798 std::string url = tools::get_update_url(software, subdir, buildtag, version, true);
1799 MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
1800 m_update_available = true;
1801
1802 if (check_updates_level == UPDATES_NOTIFY) {
1803 std::vector<std::string> version_split;
1804 std::vector<std::string> latest_version_split;
1805
1806 boost::split(version_split, ELECTRONEUM_VERSION, [](char c){return c == '.';});
1807 boost::split(latest_version_split, version, [](char c){return c == '.';});
1808
1809 // Warninig message to update to lastest software case major version differs.
1810 // This should help users to update their node before a major update or fork.
1811 for(size_t i = 0; i < 2; i++) {
1812 if(version_split[i] != latest_version_split[i]) {
1813 MCLOG_RED(el::Level::Fatal, "global", "Please update your node to the latest software (v" << version << ").");
1814 break;
1815 }
1816 }
1817
1818 return true;
1819 }
1820
1821 url = tools::get_update_url(software, subdir, buildtag, version, false);
1822 std::string filename;
1823 const char *slash = strrchr(url.c_str(), '/');
1824 if (slash)
1825 filename = slash + 1;
1826 else
1827 filename = std::string(software) + "-update-" + version;
1828 boost::filesystem::path path(epee::string_tools::get_current_module_folder());
1829 path /= filename;
1830
1831 boost::unique_lock<boost::mutex> lock(m_update_mutex);
1832
1833 if (m_update_download != 0)
1834 {
1835 MCDEBUG("updates", "Already downloading update");
1836 return true;
1837 }
1838
1839 crypto::hash file_hash;
1840 if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash)))
1841 {
1842 MCDEBUG("updates", "We don't have that file already, downloading");
1843 const std::string tmppath = path.string() + ".tmp";
1845 {
1846 MCDEBUG("updates", "We have part of the file already, resuming download");
1847 }
1848 m_last_update_length = 0;
1849 m_update_download = tools::download_async(tmppath, url, [this, hash, path](const std::string &tmppath, const std::string &uri, bool success) {
1850 bool remove = false, good = true;
1851 if (success)
1852 {
1853 crypto::hash file_hash;
1854 if (!tools::sha256sum(tmppath, file_hash))
1855 {
1856 MCERROR("updates", "Failed to hash " << tmppath);
1857 remove = true;
1858 good = false;
1859 }
1860 else if (hash != epee::string_tools::pod_to_hex(file_hash))
1861 {
1862 MCERROR("updates", "Download from " << uri << " does not match the expected hash");
1863 remove = true;
1864 good = false;
1865 }
1866 }
1867 else
1868 {
1869 MCERROR("updates", "Failed to download " << uri);
1870 good = false;
1871 }
1872 boost::unique_lock<boost::mutex> lock(m_update_mutex);
1873 m_update_download = 0;
1874 if (success && !remove)
1875 {
1876 std::error_code e = tools::replace_file(tmppath, path.string());
1877 if (e)
1878 {
1879 MCERROR("updates", "Failed to rename downloaded file");
1880 good = false;
1881 }
1882 }
1883 else if (remove)
1884 {
1885 if (!boost::filesystem::remove(tmppath))
1886 {
1887 MCERROR("updates", "Failed to remove invalid downloaded file");
1888 good = false;
1889 }
1890 }
1891 if (good)
1892 MCLOG_CYAN(el::Level::Info, "updates", "New version downloaded to " << path.string());
1893 }, [this](const std::string &path, const std::string &uri, size_t length, ssize_t content_length) {
1894 if (length >= m_last_update_length + 1024 * 1024 * 10)
1895 {
1896 m_last_update_length = length;
1897 MCDEBUG("updates", "Downloaded " << length << "/" << (content_length ? std::to_string(content_length) : "unknown"));
1898 }
1899 return true;
1900 });
1901 }
1902 else
1903 {
1904 MCDEBUG("updates", "We already have " << path << " with expected hash");
1905 }
1906
1907 lock.unlock();
1908
1909 if (check_updates_level == UPDATES_DOWNLOAD)
1910 return true;
1911
1912 MCERROR("updates", "Download/update not implemented yet");
1913 return true;
1914 }
1915 //-----------------------------------------------------------------------------------------------
1916 bool core::check_disk_space()
1917 {
1918 uint64_t free_space = get_free_space();
1919 if (free_space < 1ull * 1024 * 1024 * 1024) // 1 GB
1920 {
1921 const el::Level level = el::Level::Warning;
1922 MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder);
1923 }
1924 return true;
1925 }
1926 //-----------------------------------------------------------------------------------------------
1927 double factorial(unsigned int n)
1928 {
1929 if (n <= 1)
1930 return 1.0;
1931 double f = n;
1932 while (n-- > 1)
1933 f *= n;
1934 return f;
1935 }
1936 //-----------------------------------------------------------------------------------------------
1937 static double probability1(unsigned int blocks, unsigned int expected)
1938 {
1939 // https://www.umass.edu/wsp/resources/poisson/#computing
1940 return pow(expected, blocks) / (factorial(blocks) * exp(expected));
1941 }
1942 //-----------------------------------------------------------------------------------------------
1943 static double probability(unsigned int blocks, unsigned int expected)
1944 {
1945 double p = 0.0;
1946 if (blocks <= expected)
1947 {
1948 for (unsigned int b = 0; b <= blocks; ++b)
1949 p += probability1(b, expected);
1950 }
1951 else if (blocks > expected)
1952 {
1953 for (unsigned int b = blocks; b <= expected * 3 /* close enough */; ++b)
1954 p += probability1(b, expected);
1955 }
1956 return p;
1957 }
1958 //-----------------------------------------------------------------------------------------------
1959 bool core::check_block_rate()
1960 {
1961 MDEBUG("Not checking block rate, not applicable.");
1962 return true;
1963
1964 if (m_offline || m_nettype == FAKECHAIN || m_target_blockchain_height > get_current_blockchain_height())
1965 {
1966 MDEBUG("Not checking block rate, offline or syncing");
1967 return true;
1968 }
1969
1970 static constexpr double threshold = 1. / (864000 / DIFFICULTY_TARGET_V6); // one false positive every 10 days
1971
1972 const time_t now = time(NULL);
1973 const std::vector<time_t> timestamps = m_blockchain_storage.get_last_block_timestamps(60);
1974
1975 static const unsigned int seconds[] = { 5400, 3600, 1800, 1200, 600 };
1976 for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n)
1977 {
1978 unsigned int b = 0;
1979 const time_t time_boundary = now - static_cast<time_t>(seconds[n]);
1980 for (time_t ts: timestamps) b += ts >= time_boundary;
1981 const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V6);
1982 MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
1983 if (p < threshold)
1984 {
1985 MWARNING("There were " << b << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Electroneum network or under attack. Or it could be just sheer bad luck.");
1986
1987 std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
1988 if (block_rate_notify)
1989 {
1990 auto expected = seconds[n] / DIFFICULTY_TARGET_V6;
1991 block_rate_notify->notify("%t", std::to_string(seconds[n] / 60).c_str(), "%b", std::to_string(b).c_str(), "%e", std::to_string(expected).c_str(), NULL);
1992 }
1993
1994 break; // no need to look further
1995 }
1996 }
1997
1998 return true;
1999 }
2000 //-----------------------------------------------------------------------------------------------
2002 {
2003 return m_blockchain_storage.update_blockchain_pruning();
2004 }
2005 //-----------------------------------------------------------------------------------------------
2007 {
2008 return m_blockchain_storage.check_blockchain_pruning();
2009 }
2010 //-----------------------------------------------------------------------------------------------
2011 void core::set_target_blockchain_height(uint64_t target_blockchain_height)
2012 {
2013 m_target_blockchain_height = target_blockchain_height;
2014 }
2015 //-----------------------------------------------------------------------------------------------
2017 {
2018 return m_target_blockchain_height;
2019 }
2020 //-----------------------------------------------------------------------------------------------
2022 {
2023 boost::filesystem::path path(m_config_folder);
2024 boost::filesystem::space_info si = boost::filesystem::space(path);
2025 return si.available;
2026 }
2027 //-----------------------------------------------------------------------------------------------
2032 //-----------------------------------------------------------------------------------------------
2034 {
2035 return get_blockchain_storage().prune_blockchain(pruning_seed);
2036 }
2037 //-----------------------------------------------------------------------------------------------
2038 std::time_t core::get_start_time() const
2039 {
2040 return start_time;
2041 }
2042 //-----------------------------------------------------------------------------------------------
2043 bool core::set_validator_key(std::string key) {
2044 bool is_validator_key_valid = std::count_if(key.begin(), key.end(), [](int c) {return !std::isxdigit(c);}) == 0;
2045 if(!is_validator_key_valid || key.size() % 2 != 0) {
2046 return false;
2047 }
2048
2049 m_miner.pause();
2050 m_blockchain_storage.set_validator_key(key);
2051 m_miner.resume();
2052
2053 return true;
2054 }
2055 //-----------------------------------------------------------------------------------------------
2056 std::vector<std::string> core::generate_ed25519_keypair() {
2058 }
2059 //-----------------------------------------------------------------------------------------------
2060
2061 std::string core::sign_message(std::string sk, std::string msg) {
2062 std::string b_str = crypto::sign_message(msg, sk);
2063 return boost::algorithm::hex(b_str);
2064 }
2065 //-----------------------------------------------------------------------------------------------
2067 {
2069 return m_blockchain_storage.get_db().get_balance(combined_key);
2070 }
2071 //-----------------------------------------------------------------------------------------------
2072 std::vector<address_outputs> core::get_address_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id, const uint64_t &batch_size, bool desc)
2073 {
2075 return m_blockchain_storage.get_db().get_addr_output_batch(combined_key, start_tx_id, batch_size, desc);
2076 }
2077 //-----------------------------------------------------------------------------------------------
2078 std::vector<address_txs> core::get_addr_tx_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id, const uint64_t &batch_size, bool desc)
2079 {
2081 return m_blockchain_storage.get_db().get_addr_tx_batch(combined_key, start_tx_id, batch_size, desc);
2082 }
2083 //-----------------------------------------------------------------------------------------------
2085 {
2086 raise(SIGTERM);
2087 }
2088}
uint64_t height
uint8_t version
time_t time
#define MERROR_VER(x)
uint8_t threshold
#define DBF_SAFE
#define DBF_FAST
#define DBF_FASTEST
#define DBF_ADDR_TX_SALVAGE
#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
bool prune_blockchain(uint32_t pruning_seed=0)
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 on_new_tx_from_block(const cryptonote::transaction &tx)
called when we see a tx originating from a block
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition blockchain.h:858
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition blockchain.h:832
uint32_t get_blockchain_pruning_seed() const
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
returns the earliest block a given version may activate
Definition blockchain.h:865
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
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 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 pool_has_utxo_as_spent(const txin_to_key_public &in) const
get a summary statistics of all transaction hashes in the pool
bool set_genesis_block(const block &b)
clears the blockchain and starts a new one
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)
core(i_cryptonote_protocol *pprotocol)
constructor
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
bool utxo_nonexistant(const std::vector< txin_to_key_public > &public_outputs, std::vector< bool > &spent) const
check if multiple public outputs are found in the utxo database or not
void set_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 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
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 get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block > > &blocks, std::vector< cryptonote::blobdata > &txs) const
std::vector< address_txs > get_addr_tx_batch_history(const address_parse_info &addr, const uint64_t &start_tx_id=0, const uint64_t &batch_size=100, bool desc=false)
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()
Blockchain & get_blockchain_storage()
gets the Blockchain instance
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
static void init_options(boost::program_options::options_description &desc)
Definition miner.cpp:280
bool on_block_chain_update()
Definition miner.cpp:149
Transaction pool, handles transactions which are not part of a block.
Definition tx_pool.h:95
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition tx_pool.cpp:1215
bool get_transaction(const crypto::hash &h, cryptonote::blobdata &txblob) const
get a specific transaction from the pool
Definition tx_pool.cpp:1185
void wait(threadpool *tpool)
A global thread pool.
Definition threadpool.h:44
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
static threadpool & getInstance()
Definition threadpool.h:46
#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 BLOCK_SIZE_SANITY_LEEWAY
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
const char * res
const char * key
#define AUTO_VAL_INIT(v)
#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)
#define MGINFO_YELLOW(x)
Definition misc_log_ex.h:83
#define ENDL
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_PRINT_L1(x)
#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)
#define MTRACE(x)
Definition misc_log_ex.h:77
#define LOG_PRINT_L2(x)
#define TRY_ENTRY()
#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)
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
public_key addKeys(const public_key &A, const public_key &B)
Definition crypto.h:339
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
POD_CLASS hash
Definition hash.h:50
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition crypto.h:376
std::vector< std::string > create_ed25519_keypair()
Definition crypto.h:388
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)
const command_line::arg_descriptor< bool > arg_addr_db_salvage
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)
std::function< const epee::span< const unsigned char >(cryptonote::network_type network)> GetCheckpointsCallback
Callback routine that returns checkpoints data for specific network type.
Definition blockchain.h:92
bool 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
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
epee::misc_utils::struct_init< core_stat_info_t > core_stat_info
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
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)
std::string pod_to_hex(const t_pod_type &s)
std::string & get_current_module_folder()
key curveOrder()
Definition rctOps.h:76
void scalarmultKey(key &aP, const key &P, const key &a)
Definition rctOps.cpp:368
@ RCTTypeBulletproof2
Definition rctTypes.h:233
@ RCTTypeBulletproof
Definition rctTypes.h:232
bool verRctSemanticsSimple(const std::vector< const rctSig * > &rvv)
Definition rctSigs.cpp:975
key identity()
Definition rctOps.h:73
int vercmp(const char *v0, const char *v1)
Definition util.cpp:915
std::shared_ptr< download_thread_control > download_async_handle
Definition download.h:37
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 true
#define false
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
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
std::vector< blobdata > txs
blobdata block
std::vector< crypto::hash > tx_hashes
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &exclude_context)=0
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:228
rapidjson::Document json
Definition transport.cpp:49
const char *const ELECTRONEUM_VERSION
#define DISABLE_VS_WARNINGS(w)
Definition warnings.h:18