32#include <boost/algorithm/string.hpp>
37#include <unordered_set>
57#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
58#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "cn"
62#define MERROR_VER(x) MCERROR("verify", x)
64#define BAD_SEMANTICS_TXES_MAX_SIZE 100
67#define BLOCK_SIZE_SANITY_LEEWAY 100
73 ,
"Run on testnet. The wallet must be launched with --testnet flag."
78 ,
"Run on stagenet. The wallet must be launched with --stagenet flag."
83 ,
"Run in a regression testing mode."
88 ,
"Fixed difficulty used for testing."
93 ,
"Ignore block signature & signatory verification. Used for testing."
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();
111 ,
"Do not listen for peers, nor connect to any"
114 "disable-dns-checkpoints"
115 ,
"Do not retrieve checkpoints from DNS"
118 "block-download-max-size"
119 ,
"Set maximum size of block download queue in bytes (0 for default)"
125 ,
"For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"
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"
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."
137 static const command_line::arg_descriptor<bool> arg_dns_checkpoints = {
138 "enforce-dns-checkpointing"
139 ,
"checkpoints from DNS server will be enforced"
142 static const command_line::arg_descriptor<uint64_t> arg_fast_block_sync = {
144 ,
"Sync up most of the way by using embedded, known block hashes."
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."
152 static const command_line::arg_descriptor<uint64_t> arg_show_time_stats = {
154 ,
"Show time-stats when processing blocks/txs and disk synchronization."
157 static const command_line::arg_descriptor<size_t> arg_block_sync_size = {
159 ,
"How many blocks to sync at once during chain synchronization (0 = adaptive)."
162 static const command_line::arg_descriptor<std::string> arg_check_updates = {
164 ,
"Check for new versions of electroneum: [disabled|notify|download|update]"
167 static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
169 ,
"Relay blocks as fluffy blocks (obsolete, now default)"
172 static const command_line::arg_descriptor<bool> arg_no_fluffy_blocks = {
174 ,
"Relay blocks as normal blocks"
177 static const command_line::arg_descriptor<bool> arg_pad_transactions = {
179 ,
"Pad relayed transactions to help defend against traffic volume analysis"
182 static const command_line::arg_descriptor<size_t> arg_max_txpool_weight = {
184 ,
"Set maximum txpool weight in bytes."
187 static const command_line::arg_descriptor<std::string> arg_block_notify = {
189 ,
"Run a program for each new block, '%s' will be replaced by the block hash"
192 static const command_line::arg_descriptor<bool> arg_prune_blockchain = {
197 static const command_line::arg_descriptor<std::string> arg_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"
205 static const command_line::arg_descriptor<std::string> arg_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 "
217 static const command_line::arg_descriptor<std::string> arg_validator_key = {
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"
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"
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"
249 m_mempool(m_blockchain_storage),
250 m_blockchain_storage(m_mempool),
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),
261 m_update_available(
false),
262 m_pad_transactions(
false)
264 m_checkpoints_updating.clear();
270 m_pprotocol = pprotocol;
272 m_pprotocol = &m_protocol_stub;
277 m_blockchain_storage.set_checkpoints(std::move(chk_pts));
282 m_checkpoints_path = path;
287 m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns);
292 if (m_nettype !=
MAINNET || m_disable_dns_checkpoints)
return true;
294 if (m_checkpoints_updating.test_and_set())
return true;
297 if (
time(NULL) - m_last_dns_checkpoints_update >= 3600)
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);
303 else if (
time(NULL) - m_last_json_checkpoints_update >= 600)
305 res = m_blockchain_storage.update_checkpoints(m_checkpoints_path,
false);
306 m_last_json_checkpoints_update =
time(NULL);
309 m_checkpoints_updating.clear();
320 return m_validators->getSerializedValidatorList();
324 return m_validators->setValidatorsList(v_list,
true, isEmergencyUpdate);
328 return m_validators->isValid();
334 m_blockchain_storage.cancel();
338 boost::lock_guard<boost::mutex> lock(m_update_mutex);
339 handle = m_update_download;
340 m_update_download = 0;
385 bool core::handle_command_line(
const boost::program_options::variables_map& vm)
396 auto data_dir = boost::filesystem::path(m_config_folder);
401 if (!
checkpoints.init_default_checkpoints(m_nettype))
403 throw std::runtime_error(
"Failed to initialize checkpoints");
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);
413 boost::filesystem::path checkpoint_json_hashfile_fullpath =
data_dir /
json;
421 m_fluffy_blocks_enabled = !
get_arg(vm, arg_no_fluffy_blocks);
422 m_pad_transactions =
get_arg(vm, arg_pad_transactions);
426 MWARNING(arg_fluffy_blocks.name <<
" is obsolete, it is now default");
438 return m_blockchain_storage.get_current_blockchain_height();
443 top_id = m_blockchain_storage.get_tail_id(
height);
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
448 return m_blockchain_storage.get_blocks(start_offset, count,
blocks, txs);
453 return m_blockchain_storage.get_blocks(start_offset, count,
blocks);
458 std::vector<std::pair<cryptonote::blobdata, cryptonote::block>> bs;
459 if (!m_blockchain_storage.get_blocks(start_offset, count, bs))
461 for (
const auto &b: bs)
462 blocks.push_back(b.second);
466 bool core::get_transactions(
const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs)
const
468 return m_blockchain_storage.get_transactions_blobs(txs_ids, txs, missed_txs);
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
473 return m_blockchain_storage.get_split_transactions_blobs(txs_ids, txs, missed_txs);
478 m_mempool.get_transaction_backlog(backlog);
482 bool core::get_transactions(
const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs)
const
484 return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs);
489 return m_blockchain_storage.get_alternative_blocks(
blocks);
494 return m_blockchain_storage.get_alternative_blocks_count();
499 start_time = std::time(
nullptr);
511 bool r = handle_command_line(vm);
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();
529 boost::filesystem::path folder(m_config_folder);
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());
540 const boost::filesystem::path old_files = folder;
541 if (boost::filesystem::exists(old_files /
"blockchain.bin"))
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.");
553 std::unique_ptr<BlockchainDB> db(
new_db(db_type));
556 LOG_ERROR(
"Attempted to use non-existent database type");
560 folder /= db->get_db_name();
561 MGINFO(
"Loading blockchain from folder " << folder.string() <<
" ...");
563 const std::string filename = folder.string();
566 bool sync_on_blocks =
true;
572 if (!db->remove_data_file(filename))
574 MERROR(
"Failed to remove data file in " << filename);
583 std::vector<std::string> options;
584 boost::trim(db_sync_mode);
585 boost::split(options, db_sync_mode, boost::is_any_of(
" :"));
588 for(
const auto &
option : options)
594 if(options.size() == 0)
597 db_flags = DEFAULT_FLAGS;
600 bool safemode =
false;
601 if(options.size() >= 1)
603 if(options[0] ==
"safe")
609 else if(options[0] ==
"fast")
614 else if(options[0] ==
"fastest")
617 sync_threshold = 1000;
621 db_flags = DEFAULT_FLAGS;
624 if(options.size() >= 2 && !safemode)
626 if(options[1] ==
"sync")
628 else if(options[1] ==
"async")
632 if(options.size() >= 3 && !safemode)
636 if (*endptr ==
'\0' || !strcmp(endptr,
"blocks"))
638 sync_on_blocks =
true;
641 else if (!strcmp(endptr,
"bytes"))
643 sync_on_blocks =
false;
648 LOG_ERROR(
"Invalid db sync mode: " << options[2]);
659 db->open(filename, db_flags);
669 m_blockchain_storage.set_user_options(blocks_threads,
670 sync_on_blocks, sync_threshold, sync_mode, fast_sync, validator_key);
677 catch (
const std::exception &e)
679 MERROR(
"Failed to parse block notify spec: " << e.
what());
687 catch (
const std::exception &e)
689 MERROR(
"Failed to parse reorg notify spec: " << e.
what());
697 catch (
const std::exception &e)
699 MERROR(
"Failed to parse block rate notify spec: " << e.
what());
710 r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options :
test_options, fixed_difficulty, get_checkpoints, ignore_bsig, m_fallback_to_pow);
712 r = m_mempool.init(max_txpool_weight);
717 m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
720 m_blockchain_storage.set_show_time_stats(show_time_stats);
725 MGINFO(
"Loading checkpoints");
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;
741 MERROR(
"Invalid argument to --dns-versions-check: " << check_updates_string);
745 check_updates_level = UPDATES_DISABLED;
747 r = m_miner.init(vm, m_nettype, m_fallback_to_pow);
753 if (!m_blockchain_storage.get_blockchain_pruning_seed())
755 MGINFO(
"Pruning blockchain...");
756 CHECK_AND_ASSERT_MES(m_blockchain_storage.prune_blockchain(),
false,
"Failed to prune blockchain");
760 CHECK_AND_ASSERT_MES(m_blockchain_storage.update_blockchain_pruning(),
false,
"Failed to update blockchain pruning");
764 if(!m_fallback_to_pow) {
766 m_blockchain_storage.set_validators_list_instance(m_validators);
768 if(m_blockchain_storage.get_current_blockchain_height() >= ((m_nettype ==
TESTNET ? 446674 : 589169) - 720 )) {
769 m_validators->enable();
773 return load_state_data();
778 return m_blockchain_storage.reset_and_set_genesis_block(b);
781 bool core::load_state_data()
791 m_blockchain_storage.deinit();
797 m_test_drop_download =
false;
802 m_test_drop_download_height =
height;
807 return m_test_drop_download;
812 if (m_test_drop_download_height == 0)
823 tvc = boost::value_initialized<tx_verification_context>();
827 LOG_PRINT_L1(
"WRONG TRANSACTION BLOB, too big size " << tx_blob.size() <<
", rejected");
833 tx_hash = crypto::null_hash;
835 if(!parse_tx_from_blob(tx, tx_hash, tx_blob))
837 LOG_PRINT_L1(
"WRONG TRANSACTION BLOB, Failed to parse, rejected");
843 bad_semantics_txes_lock.lock();
844 for (
int idx = 0; idx < 2; ++idx)
846 if (bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end())
848 bad_semantics_txes_lock.unlock();
849 LOG_PRINT_L1(
"Transaction already seen with bad semantics, rejected");
854 bad_semantics_txes_lock.unlock();
856 uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
867 if (tx.
version < min_tx_version)
878 if(!check_tx_syntax(tx))
880 LOG_PRINT_L1(
"WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash <<
" syntax, rejected");
881 tvc.m_verification_failed =
true;
888 void core::set_semantics_failed(
const crypto::hash &tx_hash)
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);
895 std::swap(bad_semantics_txes[0], bad_semantics_txes[1]);
896 bad_semantics_txes[0].clear();
898 bad_semantics_txes_lock.unlock();
901 bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &
tx_info,
bool keeped_by_block)
906 MTRACE(
"Skipping semantics check for tx kept by block in embedded hash area");
910 std::vector<const rct::rctSig*> rvv;
911 for (
size_t n = 0; n < tx_info.size(); ++n)
913 if (!check_tx_semantic(*tx_info[n].tx, keeped_by_block))
915 set_semantics_failed(tx_info[n].tx_hash);
916 tx_info[n].tvc.m_verification_failed =
true;
917 tx_info[n].result =
false;
923 LOG_PRINT_L1(
"One transaction among this group has bad semantics, verifying one at a time");
925 const bool assumed_bad = rvv.size() == 1;
926 for (
size_t n = 0; n < tx_info.size(); ++n)
928 if (!tx_info[n].result)
934 set_semantics_failed(tx_info[n].tx_hash);
935 tx_info[n].tvc.m_verification_failed =
true;
936 tx_info[n].result =
false;
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)
950 std::vector<result> results(tx_blobs.size());
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] {
960 results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
962 catch (
const std::exception &e)
964 MERROR_VER(
"Exception in handle_incoming_tx_pre: " << e.what());
965 tvc[i].m_verification_failed =
true;
966 results[i].res =
false;
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) {
976 if(m_mempool.have_tx(results[i].hash))
978 LOG_PRINT_L2(
"tx " << results[i].hash <<
"already have transaction in tx_pool");
979 already_have[i] =
true;
981 else if(m_blockchain_storage.have_tx(results[i].hash))
983 LOG_PRINT_L2(
"tx " << results[i].hash <<
" already have transaction in blockchain");
984 already_have[i] =
true;
988 tpool.
submit(&waiter, [&, i, it] {
991 results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, keeped_by_block, relayed, do_not_relay);
993 catch (
const std::exception &e)
995 MERROR_VER(
"Exception in handle_incoming_tx_post: " << e.what());
996 tvc[i].m_verification_failed =
true;
997 results[i].res =
false;
1002 waiter.
wait(&tpool);
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])
1009 tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
1012 handle_incoming_tx_accumulated_batch(
tx_info, keeped_by_block);
1015 it = tx_blobs.begin();
1016 for (
size_t i = 0; i < tx_blobs.size(); i++, ++it) {
1017 if (!results[i].
res)
1022 if (keeped_by_block)
1024 if (already_have[i])
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);}
1034 if(tvc[i].m_added_to_pool)
1035 MDEBUG(
"tx added: " << results[i].hash);
1044 std::vector<cryptonote::blobdata> tx_blobs;
1045 tx_blobs.push_back(tx_blob);
1046 std::vector<tx_verification_context> tvcv(1);
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();
1063 bool core::check_tx_semantic(
const transaction& tx,
bool keeped_by_block)
const
1093 if((tx.
version == 1 && amount_in <= amount_out) || (tx.
version == 2 && amount_in != amount_out)) {
1095 MERROR_VER(
"V" << tx.
version <<
" tx with wrong amounts: ins " << amount_in <<
", outs " << amount_out <<
", rejected for tx id= "
1102 bool only_bridge_dests =
true;
1103 std::string portal_address_viewkey_hex_str;
1104 std::string portal_address_spendkey_hex_str;
1106 portal_address_viewkey_hex_str =
"2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
1107 portal_address_spendkey_hex_str =
"8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137";
1109 portal_address_viewkey_hex_str =
"5866666666666666666666666666666666666666666666666666666666666666";
1110 portal_address_spendkey_hex_str =
"5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3";
1113 for (
auto output: tx.
vout){
1114 const auto out = boost::get<txout_to_key_public>(output.target);
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= "
1127 if (only_bridge_dests && amount_in < amount_out){
1128 MERROR_VER(
"v3 sc_migration tx has wrong amounts: ins " << amount_in <<
", outs " << amount_out <<
", rejected for tx id= "
1144 if(!check_tx_inputs_utxos_diff(tx))
1146 MERROR_VER(
"tx uses a single utxo more than once");
1153 if(!check_tx_inputs_keyimages_diff(tx))
1155 MERROR_VER(
"tx uses a single key image more than once");
1159 if (!check_tx_inputs_keyimages_domain(tx))
1161 MERROR_VER(
"tx uses key image not in the valid domain");
1171 return m_blockchain_storage.have_tx_keyimg_as_spent(key_image);
1177 for(
auto& ki: key_im)
1179 spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki));
1187 for(
auto& po: public_outputs)
1189 spent.push_back(m_blockchain_storage.utxo_nonexistence_from_output(po));
1197 if (block_sync_size > 0)
1198 return block_sync_size;
1199 if (
height >= quick_height)
1207 return m_mempool.check_for_key_images(key_im, spent);
1216 const uint64_t end = start_offset + count - 1;
1217 m_blockchain_storage.for_blocks_range(start_offset, end,
1219 std::vector<transaction> txs;
1220 std::vector<crypto::hash> missed_txs;
1224 for(
const auto& tx: txs)
1229 emission_amount += coinbase_amount - tx_fee_amount;
1230 total_fee_amount += tx_fee_amount;
1235 return std::pair<uint64_t, uint64_t>(emission_amount, total_fee_amount);
1238 bool core::check_tx_inputs_keyimages_diff(
const transaction& tx)
const
1240 std::unordered_set<crypto::key_image> ki;
1241 for(
const auto& in: tx.
vin)
1244 if(!ki.insert(tokey_in.k_image).second)
1250 bool core::check_tx_inputs_utxos_diff(
const transaction& tx)
const
1252 std::unordered_set<std::string> ins;
1253 for(
const auto& in: tx.vin)
1256 if(!ins.insert(std::string(tokey_in.tx_hash.data, 32) + std::to_string(tokey_in.relative_offset)).second)
1262 bool core::check_tx_inputs_ring_members_diff(
const transaction& tx)
const
1264 const uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
1267 for(
const auto& in: tx.vin)
1270 for (
size_t n = 1; n < tokey_in.key_offsets.size(); ++n)
1271 if (tokey_in.key_offsets[n] == 0)
1278 bool core::check_tx_inputs_keyimages_domain(
const transaction& tx)
const
1280 std::unordered_set<crypto::key_image> ki;
1281 for(
const auto& in: tx.vin)
1296 return add_new_tx(tx, tx_hash, bl, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
1301 return m_blockchain_storage.get_total_transactions();
1307 if(m_mempool.
have_tx(tx_hash))
1309 LOG_PRINT_L2(
"tx " << tx_hash <<
"already have transaction in tx_pool");
1313 if(m_blockchain_storage.
have_tx(tx_hash))
1315 LOG_PRINT_L2(
"tx " << tx_hash <<
" already have transaction in blockchain");
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);
1323 bool core::relay_txpool_transactions()
1326 std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1327 if (m_mempool.get_relayable_transactions(txs) && !txs.empty())
1329 cryptonote_connection_context fake_context =
AUTO_VAL_INIT(fake_context);
1332 for (
auto it = txs.begin(); it != txs.end(); ++it)
1334 r.txs.push_back(it->second);
1337 m_mempool.set_relayed(txs);
1344 std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
1349 LOG_ERROR(
"Failed to parse relayed transaction");
1352 txs.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
1353 m_mempool.set_relayed(txs);
1358 return m_blockchain_storage.create_block_template(b, adr, diffic,
height, expected_reward, ex_nonce);
1363 return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic,
height, expected_reward, ex_nonce);
1368 return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
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
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);
1378 return m_blockchain_storage.get_outs(req,
res);
1383 return m_blockchain_storage.get_output_distribution(amount, from_height, to_height, start_height, distribution, base);
1388 return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs);
1393 return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, n_txes, indexs);
1414 bce.
txs.push_back(txblob);
1421 bvc = boost::value_initialized<block_verification_context>();
1423 std::vector<block_complete_entry>
blocks;
1428 catch (
const std::exception &e)
1433 std::vector<block> pblocks;
1436 MERROR(
"Block found, but failed to prepare to add");
1440 m_blockchain_storage.add_new_block(b, bvc);
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);
1454 LOG_PRINT_L1(
"Block found but, seems that reorganize just happened after that, do not relay this block");
1458 <<
", b.tx_hashes.size()=" << b.
tx_hashes.size() <<
", missed_txs.size()" << missed_txs.size());
1463 arg.b.txs.push_back(tx);
1465 m_pprotocol->relay_block(arg, exclude_context);
1467 if(m_fallback_to_pow) {
1471 update_miner_block_template();
1479 m_miner.on_synchronized();
1484 m_blockchain_storage.safesyncmode(onoff);
1495 m_incoming_tx_lock.lock();
1496 if (!m_blockchain_storage.prepare_handle_incoming_blocks(blocks_entry,
blocks))
1507 bool success =
false;
1509 success = m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync);
1512 m_incoming_tx_lock.unlock();
1521 bvc = boost::value_initialized<block_verification_context>();
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");
1542 LOG_PRINT_L1(
"Failed to parse and validate new block");
1549 add_new_block(*b, bvc);
1554 if(update_miner_blocktemplate)
1555 update_miner_block_template();
1571 if(block_blob.size() > m_blockchain_storage.get_current_cumulative_block_weight_limit() +
BLOCK_SIZE_SANITY_LEEWAY)
1573 LOG_PRINT_L1(
"WRONG BLOCK BLOB, sanity check failed on size " << block_blob.size() <<
", rejected");
1581 return m_blockchain_storage.get_tail_id();
1586 return m_blockchain_storage.get_db().set_block_cumulative_difficulty(
height, diff);
1591 return m_blockchain_storage.get_db().get_block_cumulative_difficulty(
height);
1596 return m_mempool.get_transactions_count();
1601 return m_blockchain_storage.have_block(
id);
1609 bool core::check_tx_syntax(
const transaction& tx)
const
1616 m_mempool.get_transactions(txs, include_sensitive_data);
1622 m_mempool.get_transaction_hashes(txs, include_sensitive_data);
1628 m_mempool.get_transaction_stats(stats, include_sensitive_data);
1634 return m_mempool.get_transaction(
id, tx);
1639 return m_mempool.have_tx(
id);
1644 return m_mempool.utxo_spent_in_pool(in);
1649 return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos, include_sensitive_data);
1654 return m_mempool.get_pool_for_rpc(tx_infos, key_image_infos);
1659 return m_blockchain_storage.get_short_chain_history(ids);
1664 return m_blockchain_storage.handle_get_objects(arg, rsp);
1669 return m_blockchain_storage.get_block_id_by_height(
height);
1674 return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
1679 return m_mempool.print_pool(short_format);
1682 bool core::update_miner_block_template()
1690 if(!m_starter_message_showed)
1692 std::string main_message;
1694 main_message =
"The daemon is running offline and will not attempt to sync to the Electroneum network.";
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
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
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;
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));
1716 m_mempool.on_idle();
1718 if(!m_fallback_to_pow) {
1719 m_validators->on_idle();
1725 bool core::check_fork_time()
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",
"**********************************************************************");
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",
"**********************************************************************");
1770 bool core::check_updates()
1772 static const char software[] =
"electroneum";
1774 static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
1775 static const char subdir[] =
"cli";
1777 static const char buildtag[] =
"source";
1778 static const char subdir[] =
"source";
1784 if (check_updates_level == UPDATES_DISABLED)
1788 MCDEBUG(
"updates",
"Checking for a new " << software <<
" version for " << buildtag);
1794 m_update_available =
false;
1799 MCLOG_CYAN(
el::Level::Info,
"global",
"Version " <<
version <<
" of " << software <<
" for " << buildtag <<
" is available: " << url <<
", SHA256 hash " << hash);
1800 m_update_available =
true;
1802 if (check_updates_level == UPDATES_NOTIFY) {
1803 std::vector<std::string> version_split;
1804 std::vector<std::string> latest_version_split;
1807 boost::split(latest_version_split,
version, [](
char c){
return c ==
'.';});
1811 for(
size_t i = 0; i < 2; i++) {
1812 if(version_split[i] != latest_version_split[i]) {
1822 std::string filename;
1823 const char *slash = strrchr(url.c_str(),
'/');
1825 filename = slash + 1;
1827 filename = std::string(software) +
"-update-" +
version;
1831 boost::unique_lock<boost::mutex> lock(m_update_mutex);
1833 if (m_update_download != 0)
1835 MCDEBUG(
"updates",
"Already downloading update");
1842 MCDEBUG(
"updates",
"We don't have that file already, downloading");
1843 const std::string tmppath = path.string() +
".tmp";
1846 MCDEBUG(
"updates",
"We have part of the file already, resuming download");
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;
1856 MCERROR(
"updates",
"Failed to hash " << tmppath);
1862 MCERROR(
"updates",
"Download from " << uri <<
" does not match the expected hash");
1869 MCERROR(
"updates",
"Failed to download " << uri);
1872 boost::unique_lock<boost::mutex> lock(m_update_mutex);
1873 m_update_download = 0;
1874 if (success && !remove)
1879 MCERROR(
"updates",
"Failed to rename downloaded file");
1885 if (!boost::filesystem::remove(tmppath))
1887 MCERROR(
"updates",
"Failed to remove invalid downloaded file");
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)
1896 m_last_update_length = length;
1897 MCDEBUG(
"updates",
"Downloaded " << length <<
"/" << (content_length ? std::to_string(content_length) :
"unknown"));
1904 MCDEBUG(
"updates",
"We already have " << path <<
" with expected hash");
1909 if (check_updates_level == UPDATES_DOWNLOAD)
1912 MCERROR(
"updates",
"Download/update not implemented yet");
1916 bool core::check_disk_space()
1919 if (free_space < 1ull * 1024 * 1024 * 1024)
1922 MCLOG_RED(level,
"global",
"Free space is below 1 GB on " << m_config_folder);
1937 static double probability1(
unsigned int blocks,
unsigned int expected)
1943 static double probability(
unsigned int blocks,
unsigned int expected)
1946 if (blocks <= expected)
1948 for (
unsigned int b = 0; b <= blocks; ++b)
1949 p += probability1(b, expected);
1951 else if (blocks > expected)
1953 for (
unsigned int b = blocks; b <= expected * 3 ; ++b)
1954 p += probability1(b, expected);
1959 bool core::check_block_rate()
1961 MDEBUG(
"Not checking block rate, not applicable.");
1966 MDEBUG(
"Not checking block rate, offline or syncing");
1972 const time_t now =
time(NULL);
1973 const std::vector<time_t> timestamps = m_blockchain_storage.get_last_block_timestamps(60);
1975 static const unsigned int seconds[] = { 5400, 3600, 1800, 1200, 600 };
1976 for (
size_t n = 0; n <
sizeof(seconds)/
sizeof(seconds[0]); ++n)
1979 const time_t time_boundary = now -
static_cast<time_t
>(seconds[n]);
1980 for (time_t ts: timestamps) b += ts >= time_boundary;
1982 MDEBUG(
"blocks in the last " << seconds[n] / 60 <<
" minutes: " << b <<
" (probability " << p <<
")");
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.");
1987 std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
1988 if (block_rate_notify)
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);
2003 return m_blockchain_storage.update_blockchain_pruning();
2008 return m_blockchain_storage.check_blockchain_pruning();
2013 m_target_blockchain_height = target_blockchain_height;
2018 return m_target_blockchain_height;
2023 boost::filesystem::path path(m_config_folder);
2024 boost::filesystem::space_info si = boost::filesystem::space(path);
2025 return si.available;
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) {
2050 m_blockchain_storage.set_validator_key(
key);
2063 return boost::algorithm::hex(b_str);
2069 return m_blockchain_storage.get_db().get_balance(combined_key);
2075 return m_blockchain_storage.get_db().get_addr_output_batch(combined_key, start_tx_id, batch_size, desc);
2081 return m_blockchain_storage.get_db().get_addr_tx_batch(combined_key, start_tx_id, batch_size, desc);
#define DBF_ADDR_TX_SALVAGE
const unsigned char checkpoints[]
#define JSON_HASH_FILE_NAME
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
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
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
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.
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)
bool on_block_chain_update()
std::vector< txin_v > vin
std::vector< tx_out > vout
rct::rctSig rct_signatures
Transaction pool, handles transactions which are not part of a block.
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
bool get_transaction(const crypto::hash &h, cryptonote::blobdata &txblob) const
get a specific transaction from the pool
#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 MCLOG_CYAN(level, cat, x)
#define MCLOG_RED(level, cat, x)
#define CATCH_ENTRY_L0(lacation, return_val)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
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)
std::string sign_message(const std::string &message, const std::string &privateKey)
std::vector< std::string > create_ed25519_keypair()
std::unordered_map< crypto::key_image, std::vector< crypto::hash > > key_images_with_tx_hashes
Holds cryptonote related classes and helpers.
const command_line::arg_descriptor< std::string, false, true, 2 > arg_data_dir
boost::multiprecision::uint128_t difficulty_type
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)
@ db_async
handle syncing calls instead of the backing db, asynchronously
@ db_nosync
Leave syncing up to the backing db (safest, but slowest because of disk I/O).
@ db_sync
handle syncing calls instead of the backing db, synchronously
@ db_defaultsync
user didn't specify, use db_async
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.
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)
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()
bool is_file_exist(const std::string &path)
void scalarmultKey(key &aP, const key &P, const key &a)
bool verRctSemanticsSimple(const std::vector< const rctSig * > &rvv)
boost::filesystem::path data_dir
unsigned __int64 uint64_t
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
crypto::public_key m_view_public_key
crypto::public_key m_spend_public_key
account_public_address address
std::vector< blobdata > txs
bool m_added_to_main_chain
bool m_verification_failed
std::vector< crypto::hash > tx_hashes
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &exclude_context)=0
bool m_verification_failed
#define CRITICAL_REGION_LOCAL(x)
const char *const ELECTRONEUM_VERSION
#define DISABLE_VS_WARNINGS(w)