diff options
33 files changed, 444 insertions, 147 deletions
diff --git a/external/boost/archive/portable_binary_oarchive.hpp b/external/boost/archive/portable_binary_oarchive.hpp index 9ed30d064..e2dcb9456 100644 --- a/external/boost/archive/portable_binary_oarchive.hpp +++ b/external/boost/archive/portable_binary_oarchive.hpp @@ -41,19 +41,24 @@ class portable_binary_oarchive_exception : public boost::archive::archive_exception
{
public:
- typedef enum {
+ enum exception_code {
invalid_flags
- } exception_code;
- portable_binary_oarchive_exception(exception_code c = invalid_flags )
+ } m_exception_code ;
+ portable_binary_oarchive_exception(exception_code c = invalid_flags ) :
+ boost::archive::archive_exception(boost::archive::archive_exception::other_exception),
+ m_exception_code(c)
{}
virtual const char *what( ) const throw( )
{
const char *msg = "programmer error";
- switch(code){
+ switch(m_exception_code){
case invalid_flags:
msg = "cannot be both big and little endian";
+ break;
default:
- boost::archive::archive_exception::what();
+ msg = boost::archive::archive_exception::what();
+ assert(false);
+ break;
}
return msg;
}
diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c index 377512ebe..b3de9702f 100644 --- a/external/db_drivers/liblmdb/mdb.c +++ b/external/db_drivers/liblmdb/mdb.c @@ -6288,6 +6288,10 @@ release: if (rc) return rc; } +#ifdef MDB_VL32 + if (mc->mc_ovpg == mp) + mc->mc_ovpg = NULL; +#endif mc->mc_db->md_overflow_pages -= ovpages; return 0; } diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 01a59e079..d62a250ff 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -78,6 +78,23 @@ std::string blockchain_db_types(const std::string& sep) return ret; } +std::string arg_db_type_description = "Specify database type, available: " + cryptonote::blockchain_db_types(", "); +const command_line::arg_descriptor<std::string> arg_db_type = { + "db-type" +, arg_db_type_description.c_str() +, DEFAULT_DB_TYPE +}; +const command_line::arg_descriptor<std::string> arg_db_sync_mode = { + "db-sync-mode" +, "Specify sync option, using format [safe|fast|fastest]:[sync|async]:[nblocks_per_sync]." +, "fast:async:1000" +}; +const command_line::arg_descriptor<bool> arg_db_salvage = { + "db-salvage" +, "Try to salvage a blockchain database if it seems corrupted" +, false +}; + BlockchainDB *new_db(const std::string& db_type) { if (db_type == "lmdb") @@ -89,6 +106,13 @@ BlockchainDB *new_db(const std::string& db_type) return NULL; } +void BlockchainDB::init_options(boost::program_options::options_description& desc) +{ + command_line::add_arg(desc, arg_db_type); + command_line::add_arg(desc, arg_db_sync_mode); + command_line::add_arg(desc, arg_db_salvage); +} + void BlockchainDB::pop_block() { block blk; diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index ad246d85e..85a494ce7 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -33,6 +33,8 @@ #include <list> #include <string> #include <exception> +#include <boost/program_options.hpp> +#include "common/command_line.h" #include "crypto/hash.h" #include "cryptonote_protocol/blobdatatype.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -101,6 +103,10 @@ namespace cryptonote /** a pair of <transaction hash, output index>, typedef for convenience */ typedef std::pair<crypto::hash, uint64_t> tx_out_index; +extern const command_line::arg_descriptor<std::string> arg_db_type; +extern const command_line::arg_descriptor<std::string> arg_db_sync_mode; +extern const command_line::arg_descriptor<bool, false> arg_db_salvage; + #pragma pack(push, 1) /** @@ -536,6 +542,11 @@ public: virtual ~BlockchainDB() { }; /** + * @brief init command line options + */ + static void init_options(boost::program_options::options_description& desc); + + /** * @brief reset profiling stats */ void reset_stats(); diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 4100d9cca..b6978bdc4 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -2604,6 +2604,16 @@ void BlockchainLMDB::batch_commit() memset(&m_wcursors, 0, sizeof(m_wcursors)); } +void BlockchainLMDB::cleanup_batch() +{ + // for destruction of batch transaction + m_write_txn = nullptr; + delete m_write_batch_txn; + m_write_batch_txn = nullptr; + m_batch_active = false; + memset(&m_wcursors, 0, sizeof(m_wcursors)); +} + void BlockchainLMDB::batch_stop() { LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -2618,15 +2628,18 @@ void BlockchainLMDB::batch_stop() check_open(); LOG_PRINT_L3("batch transaction: committing..."); TIME_MEASURE_START(time1); - m_write_txn->commit(); - TIME_MEASURE_FINISH(time1); - time_commit1 += time1; - // for destruction of batch transaction - m_write_txn = nullptr; - delete m_write_batch_txn; - m_write_batch_txn = nullptr; - m_batch_active = false; - memset(&m_wcursors, 0, sizeof(m_wcursors)); + try + { + m_write_txn->commit(); + TIME_MEASURE_FINISH(time1); + time_commit1 += time1; + cleanup_batch(); + } + catch (const std::exception &e) + { + cleanup_batch(); + throw; + } LOG_PRINT_L3("batch transaction: end"); } diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 3a11ddf0d..90274b904 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -368,6 +368,9 @@ private: // migrate from DB version 0 to 1 void migrate_0_1(); + void cleanup_batch(); + +private: MDB_env* m_env; MDB_dbi m_blocks; diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index ded854ca4..635a70b10 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -208,7 +208,8 @@ int check_flush(cryptonote::core &core, std::list<block_complete_entry> &blocks, } } // each download block - core.cleanup_handle_incoming_blocks(); + if (!core.cleanup_handle_incoming_blocks()) + return 1; blocks.clear(); return 0; @@ -316,9 +317,9 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE); throw std::runtime_error("Aborting: chunk size exceeds buffer size"); } - if (chunk_size > 100000) + if (chunk_size > CHUNK_SIZE_WARNING_THRESHOLD) { - MINFO("NOTE: chunk_size " << chunk_size << " > 100000"); + MINFO("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD); } else if (chunk_size == 0) { MFATAL("ERROR: chunk_size == 0"); @@ -326,9 +327,19 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path } import_file.read(buffer_block, chunk_size); if (! import_file) { - MFATAL("ERROR: unexpected end of file: bytes read before error: " - << import_file.gcount() << " of chunk_size " << chunk_size); - return 2; + if (import_file.eof()) + { + std::cout << refresh_string; + MINFO("End of file reached - file was truncated"); + quit = 1; + break; + } + else + { + MFATAL("ERROR: unexpected end of file: bytes read before error: " + << import_file.gcount() << " of chunk_size " << chunk_size); + return 2; + } } bytes_read += chunk_size; MDEBUG("Total bytes read: " << bytes_read); @@ -394,7 +405,10 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path blocks.push_back({block, txs}); int ret = check_flush(core, blocks, false); if (ret) + { + quit = 2; // make sure we don't commit partial block data break; + } } else { @@ -682,18 +696,12 @@ int main(int argc, char* argv[]) MINFO("bootstrap file path: " << import_file_path); MINFO("database path: " << m_config_folder); + cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects + cryptonote::core core(&pr); + try { - // fake_core needed for verification to work when enabled. - // - // NOTE: don't need fake_core method of doing things when we're going to call - // BlockchainDB add_block() directly and have available the 3 block - // properties to do so. Both ways work, but fake core isn't necessary in that - // circumstance. - - cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects - cryptonote::core core(&pr); core.disable_dns_checkpoints(true); if (!core.init(vm, NULL)) { @@ -721,23 +729,19 @@ int main(int argc, char* argv[]) import_from_file(core, import_file_path, block_stop); + // ensure db closed + // - transactions properly checked and handled + // - disk sync if needed + // + core.deinit(); } catch (const DB_ERROR& e) { std::cout << std::string("Error loading blockchain db: ") + e.what() + " -- shutting down now" << ENDL; + core.deinit(); return 1; } - // destructors called at exit: - // - // ensure db closed - // - transactions properly checked and handled - // - disk sync if needed - // - // fake_core object's destructor is called when it goes out of scope. For an - // LMDB fake_core, it calls Blockchain::deinit() on its object, which in turn - // calls delete on its BlockchainDB derived class' object, which closes its - // files. return 0; CATCH_ENTRY("Import error", 1); diff --git a/src/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index af934bf29..6fb5e1131 100644 --- a/src/blockchain_utilities/blockchain_utilities.h +++ b/src/blockchain_utilities/blockchain_utilities.h @@ -34,6 +34,7 @@ // bounds checking is done before writing to buffer, but buffer size // should be a sensible maximum #define BUFFER_SIZE 1000000 +#define CHUNK_SIZE_WARNING_THRESHOLD 500000 #define NUM_BLOCKS_PER_CHUNK 1 #define BLOCKCHAIN_RAW "blockchain.raw" diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index d5bb37d93..2b1a5d6c7 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -436,10 +436,10 @@ uint64_t BootstrapFile::count_blocks(const std::string& import_file_path) << " height: " << h-1); throw std::runtime_error("Aborting: chunk size exceeds buffer size"); } - if (chunk_size > 100000) + if (chunk_size > CHUNK_SIZE_WARNING_THRESHOLD) { std::cout << refresh_string; - MDEBUG("NOTE: chunk_size " << chunk_size << " > 100000" << " height: " + MDEBUG("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD << " << height: " << h-1); } else if (chunk_size <= 0) { diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat Binary files differindex a15f53e67..15fa042cf 100644 --- a/src/blocks/checkpoints.dat +++ b/src/blocks/checkpoints.dat diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index ad66b2009..666b3267f 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -32,7 +32,6 @@ #include <boost/algorithm/string/compare.hpp> #include <boost/algorithm/string/predicate.hpp> #include <unordered_set> -#include "blockchain_db/db_types.h" #include "common/i18n.h" #include "cryptonote_config.h" #include "string_tools.h" @@ -96,22 +95,6 @@ namespace command_line , "checkpoints from DNS server will be enforced" , false }; - std::string arg_db_type_description = "Specify database type, available: " + cryptonote::blockchain_db_types(", "); - const command_line::arg_descriptor<std::string> arg_db_type = { - "db-type" - , arg_db_type_description.c_str() - , DEFAULT_DB_TYPE - }; - const command_line::arg_descriptor<std::string> arg_db_sync_mode = { - "db-sync-mode" - , "Specify sync option, using format [safe|fast|fastest]:[sync|async]:[nblocks_per_sync]." - , "fast:async:1000" - }; - const arg_descriptor<bool> arg_db_salvage = { - "db-salvage" - , "Try to salvage a blockchain database if it seems corrupted" - , false - }; const command_line::arg_descriptor<uint64_t> arg_fast_block_sync = { "fast-block-sync" , "Sync up most of the way by using embedded, known block hashes." @@ -137,4 +120,9 @@ namespace command_line , "Check for new versions of monero: [disabled|notify|download|update]" , "notify" }; + const arg_descriptor<bool> arg_fluffy_blocks = { + "fluffy-blocks" + , "Relay blocks as fluffy blocks where possible (automatic on testnet)" + , false + }; } diff --git a/src/common/command_line.h b/src/common/command_line.h index 03ba35a5b..d4231acd0 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -212,12 +212,10 @@ namespace command_line extern const arg_descriptor<int> arg_test_dbg_lock_sleep; extern const arg_descriptor<bool, false> arg_testnet_on; extern const arg_descriptor<bool> arg_dns_checkpoints; - extern const arg_descriptor<std::string> arg_db_type; - extern const arg_descriptor<std::string> arg_db_sync_mode; - extern const arg_descriptor<bool, false> arg_db_salvage; extern const arg_descriptor<uint64_t> arg_fast_block_sync; extern const arg_descriptor<uint64_t> arg_prep_blocks_threads; extern const arg_descriptor<uint64_t> arg_show_time_stats; extern const arg_descriptor<size_t> arg_block_sync_size; extern const arg_descriptor<std::string> arg_check_updates; + extern const arg_descriptor<bool> arg_fluffy_blocks; } diff --git a/src/cryptonote_basic/checkpoints.cpp b/src/cryptonote_basic/checkpoints.cpp index 103a4a33e..98e509561 100644 --- a/src/cryptonote_basic/checkpoints.cpp +++ b/src/cryptonote_basic/checkpoints.cpp @@ -167,6 +167,8 @@ namespace cryptonote ADD_CHECKPOINT(1100000, "3fd720c5c8b3072fc1ccda922dec1ef25f9ed88a1e6ad4103d0fe00b180a5903"); ADD_CHECKPOINT(1150000, "1dd16f626d18e1e988490dfd06de5920e22629c972c58b4d8daddea0038627b2"); ADD_CHECKPOINT(1200000, "fa7d13a90850882060479d100141ff84286599ae39c3277c8ea784393f882d1f"); + ADD_CHECKPOINT(1300000, "31b34272343a44a9f4ac7de7a8fcf3b7d8a3124d7d6870affd510d2f37e74cd0"); + ADD_CHECKPOINT(1390000, "a8f5649dd4ded60eedab475f2bec8c934681c07e3cf640e9be0617554f13ff6c"); return true; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index c1faa703f..69d2edf65 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3582,12 +3582,23 @@ void Blockchain::block_longhash_worker(uint64_t height, const std::vector<block> //------------------------------------------------------------------ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) { + bool success = false; + MTRACE("Blockchain::" << __func__); CRITICAL_REGION_BEGIN(m_blockchain_lock); TIME_MEASURE_START(t1); - m_db->batch_stop(); - if (m_sync_counter > 0) + try + { + m_db->batch_stop(); + success = true; + } + catch (const std::exception &e) + { + MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what()); + } + + if (success && m_sync_counter > 0) { if (force_sync) { @@ -3622,7 +3633,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) CRITICAL_REGION_END(); m_tx_pool.unlock(); - return true; + return success; } //------------------------------------------------------------------ @@ -4118,7 +4129,7 @@ void Blockchain::cancel() } #if defined(PER_BLOCK_CHECKPOINT) -static const char expected_block_hashes_hash[] = "23d8a8c73de7b2383c72a016d9a6034e69d62dd48077d1c414e064ceab6daa94"; +static const char expected_block_hashes_hash[] = "d3ca80d50661684cde0e715d46d7c19704d2e216b21ed088af9fd4ef37ed4d65"; void Blockchain::load_compiled_in_block_hashes() { if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr && get_blocks_dat_size(m_testnet) > 0) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index c406dd0b4..c3aeb15f0 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -156,20 +156,19 @@ namespace cryptonote command_line::add_arg(desc, command_line::arg_testnet_on); command_line::add_arg(desc, command_line::arg_dns_checkpoints); - command_line::add_arg(desc, command_line::arg_db_type); command_line::add_arg(desc, command_line::arg_prep_blocks_threads); command_line::add_arg(desc, command_line::arg_fast_block_sync); - command_line::add_arg(desc, command_line::arg_db_sync_mode); - command_line::add_arg(desc, command_line::arg_db_salvage); command_line::add_arg(desc, command_line::arg_show_time_stats); command_line::add_arg(desc, command_line::arg_block_sync_size); command_line::add_arg(desc, command_line::arg_check_updates); + command_line::add_arg(desc, command_line::arg_fluffy_blocks); // we now also need some of net_node's options (p2p bind arg, for separate data dir) command_line::add_arg(desc, nodetool::arg_testnet_p2p_bind_port, false); command_line::add_arg(desc, nodetool::arg_p2p_bind_port, false); miner::init_options(desc); + BlockchainDB::init_options(desc); } //----------------------------------------------------------------------------------------------- bool core::handle_command_line(const boost::program_options::variables_map& vm) @@ -199,6 +198,7 @@ namespace cryptonote set_enforce_dns_checkpoints(command_line::get_arg(vm, command_line::arg_dns_checkpoints)); test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height)); + m_fluffy_blocks_enabled = m_testnet || get_arg(vm, command_line::arg_fluffy_blocks); if (command_line::get_arg(vm, command_line::arg_test_drop_download) == true) test_drop_download(); @@ -279,9 +279,9 @@ namespace cryptonote m_config_folder_mempool = m_config_folder_mempool + "/" + m_port; } - std::string db_type = command_line::get_arg(vm, command_line::arg_db_type); - std::string db_sync_mode = command_line::get_arg(vm, command_line::arg_db_sync_mode); - bool db_salvage = command_line::get_arg(vm, command_line::arg_db_salvage) != 0; + std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type); + std::string db_sync_mode = command_line::get_arg(vm, cryptonote::arg_db_sync_mode); + bool db_salvage = command_line::get_arg(vm, cryptonote::arg_db_salvage) != 0; bool fast_sync = command_line::get_arg(vm, command_line::arg_fast_block_sync) != 0; uint64_t blocks_threads = command_line::get_arg(vm, command_line::arg_prep_blocks_threads); std::string check_updates_string = command_line::get_arg(vm, command_line::arg_check_updates); @@ -585,6 +585,8 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- bool core::handle_incoming_txs(const std::list<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { + TRY_ENTRY(); + struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; }; std::vector<result> results(tx_blobs.size()); @@ -593,7 +595,15 @@ namespace cryptonote std::list<blobdata>::const_iterator it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { region.run([&, i, it] { - results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); + try + { + results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); + } + catch (const std::exception &e) + { + MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what()); + results[i].res = false; + } }); } }); @@ -613,7 +623,15 @@ namespace cryptonote else { region.run([&, i, it] { - results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); + try + { + results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); + } + catch (const std::exception &e) + { + MERROR_VER("Exception in handle_incoming_tx_post: " << e.what()); + results[i].res = false; + } }); } } @@ -638,6 +656,8 @@ namespace cryptonote MDEBUG("tx added: " << results[i].hash); } return ok; + + CATCH_ENTRY_L0("core::handle_incoming_txs()", false); } //----------------------------------------------------------------------------------------------- bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) @@ -1064,17 +1084,20 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- bool core::cleanup_handle_incoming_blocks(bool force_sync) { + bool success = false; try { - m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync); + success = m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync); } catch (...) {} m_incoming_tx_lock.unlock(); - return true; + return success; } //----------------------------------------------------------------------------------------------- bool core::handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate) { + TRY_ENTRY(); + // load json & DNS checkpoints every 10min/hour respectively, // and verify them with respect to what blocks we already have CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); @@ -1098,6 +1121,8 @@ namespace cryptonote if(update_miner_blocktemplate && bvc.m_added_to_main_chain) update_miner_block_template(); return true; + + CATCH_ENTRY_L0("core::handle_incoming_block()", false); } //----------------------------------------------------------------------------------------------- // Used by the RPC server to check the size of an incoming diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index f565afd87..8e17569a9 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -728,6 +728,13 @@ namespace cryptonote */ bool get_testnet() const { return m_testnet; }; + /** + * @brief get whether fluffy blocks are enabled + * + * @return whether fluffy blocks are enabled + */ + bool fluffy_blocks_enabled() const { return m_fluffy_blocks_enabled; } + private: /** @@ -945,6 +952,8 @@ namespace cryptonote tools::download_async_handle m_update_download; size_t m_last_update_length; boost::mutex m_update_mutex; + + bool m_fluffy_blocks_enabled; }; } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 265a4ca3e..e61d95ac3 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -92,7 +92,7 @@ namespace cryptonote LockedTXN(Blockchain &b): m_blockchain(b), m_batch(false) { m_batch = m_blockchain.get_db().batch_start(); } - ~LockedTXN() { if (m_batch) { m_blockchain.get_db().batch_stop(); } } + ~LockedTXN() { try { if (m_batch) { m_blockchain.get_db().batch_stop(); } } catch (const std::exception &e) { MWARNING("LockedTXN dtor filtering exception: " << e.what()); } } private: Blockchain &m_blockchain; bool m_batch; @@ -863,6 +863,9 @@ namespace cryptonote std::unordered_set<crypto::key_image> k_images; LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool"); + + LockedTXN lock(m_blockchain); + auto sorted_it = m_txs_by_fee_and_receive_time.begin(); while (sorted_it != m_txs_by_fee_and_receive_time.end()) { diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index e762cf9c8..803d948cc 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -364,7 +364,12 @@ namespace cryptonote block_verification_context bvc = boost::value_initialized<block_verification_context>(); m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block - m_core.cleanup_handle_incoming_blocks(true); + if (!m_core.cleanup_handle_incoming_blocks(true)) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + m_core.resume_mine(); + return 1; + } m_core.resume_mine(); if(bvc.m_verifivation_failed) { @@ -623,7 +628,12 @@ namespace cryptonote block_verification_context bvc = boost::value_initialized<block_verification_context>(); m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block - m_core.cleanup_handle_incoming_blocks(true); + if (!m_core.cleanup_handle_incoming_blocks(true)) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + m_core.resume_mine(); + return 1; + } m_core.resume_mine(); if( bvc.m_verifivation_failed ) @@ -930,6 +940,7 @@ namespace cryptonote { const uint64_t subchain_height = start_height + arg.blocks.size(); LOG_DEBUG_CC(context, "These are old blocks, ignoring: blocks " << start_height << " - " << (subchain_height-1) << ", blockchain height " << m_core.get_current_blockchain_height()); + m_block_queue.remove_spans(context.m_connection_id, start_height); goto skip; } @@ -1055,7 +1066,11 @@ skip: })) LOG_ERROR_CCONTEXT("span connection id not found"); - m_core.cleanup_handle_incoming_blocks(); + if (!m_core.cleanup_handle_incoming_blocks()) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + return 1; + } // in case the peer had dropped beforehand, remove the span anyway so other threads can wake up and get it m_block_queue.remove_spans(span_connection_id, start_height); return 1; @@ -1080,7 +1095,12 @@ skip: })) LOG_ERROR_CCONTEXT("span connection id not found"); - m_core.cleanup_handle_incoming_blocks(); + if (!m_core.cleanup_handle_incoming_blocks()) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + return 1; + } + // in case the peer had dropped beforehand, remove the span anyway so other threads can wake up and get it m_block_queue.remove_spans(span_connection_id, start_height); return 1; @@ -1094,7 +1114,12 @@ skip: })) LOG_ERROR_CCONTEXT("span connection id not found"); - m_core.cleanup_handle_incoming_blocks(); + if (!m_core.cleanup_handle_incoming_blocks()) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + return 1; + } + // in case the peer had dropped beforehand, remove the span anyway so other threads can wake up and get it m_block_queue.remove_spans(span_connection_id, start_height); return 1; @@ -1107,7 +1132,11 @@ skip: MCINFO("sync-info", "Block process time (" << blocks.size() << " blocks, " << num_txs << " txs): " << block_process_time_full + transactions_process_time_full << " (" << transactions_process_time_full << "/" << block_process_time_full << ") ms"); - m_core.cleanup_handle_incoming_blocks(); + if (!m_core.cleanup_handle_incoming_blocks()) + { + LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + return 1; + } m_block_queue.remove_spans(span_connection_id, start_height); @@ -1593,7 +1622,7 @@ skip: { if (peer_id && exclude_context.m_connection_id != context.m_connection_id) { - if(m_core.get_testnet() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS)) + if(m_core.fluffy_blocks_enabled() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS)) { LOG_DEBUG_CC(context, "PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK"); fluffyConnections.push_back(context.m_connection_id); diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 12f7c5fa4..9df698547 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -231,7 +231,7 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "print_coinbase_tx_sum" , std::bind(&t_command_parser_executor::print_coinbase_tx_sum, &m_parser, p::_1) - , "Print sum of coinbase transactions (start height, block count)" + , "Print sum of coinbase transactions <start height> [block count]" ); m_command_lookup.set_handler( "alt_chain_info" diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 456eeee64..44d2dae43 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -142,7 +142,7 @@ int main(int argc, char const * argv[]) epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, command_line::arg_test_dbg_lock_sleep); - std::string db_type = command_line::get_arg(vm, command_line::arg_db_type); + std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type); // verify that blockchaindb type is valid if(!cryptonote::blockchain_valid_db_type(db_type)) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 3d6a01cd1..cda6f3f95 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -420,16 +420,17 @@ bool t_rpc_command_executor::show_status() { } std::time_t uptime = std::time(nullptr) - ires.start_time; + uint64_t net_height = ires.target_height > ires.height ? ires.target_height : ires.height; tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections, uptime %ud %uh %um %us") % (unsigned long long)ires.height - % (unsigned long long)(ires.target_height >= ires.height ? ires.target_height : ires.height) + % (unsigned long long)net_height % get_sync_percentage(ires) % (ires.testnet ? "testnet" : "mainnet") % (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) ) : "not mining") % get_mining_speed(ires.difficulty / ires.target) % (unsigned)hfres.version - % get_fork_extra_info(hfres.earliest_height, ires.height, ires.target) + % get_fork_extra_info(hfres.earliest_height, net_height, ires.target) % (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked") % (unsigned)ires.outgoing_connections_count % (unsigned)ires.incoming_connections_count diff --git a/src/debug_utilities/CMakeLists.txt b/src/debug_utilities/CMakeLists.txt index e6d49fd61..99198dc57 100644 --- a/src/debug_utilities/CMakeLists.txt +++ b/src/debug_utilities/CMakeLists.txt @@ -37,7 +37,6 @@ monero_add_executable(cn_deserialize target_link_libraries(cn_deserialize LINK_PRIVATE cryptonote_core - common blockchain_db p2p epee diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 43c5ea5f0..6ea2d48fd 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_boost_serialization.h @@ -59,6 +59,8 @@ namespace boost { a & na.m_ip; a & na.m_port; + if (!typename Archive::is_saving()) + na.init_ids(); } diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index b526277a8..dbbe07972 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -125,7 +125,7 @@ namespace cryptonote MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted) MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted) MAP_JON_RPC_WE_IF("sync_info", on_sync_info, COMMAND_RPC_SYNC_INFO, !m_restricted) - MAP_JON_RPC_WE_IF("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG, !m_restricted) + MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG) END_JSON_RPC_MAP() END_URI_MAP2() diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 479adcafc..857e2af6e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -391,6 +391,61 @@ bool simple_wallet::payment_id(const std::vector<std::string> &args/* = std::vec return true; } +bool simple_wallet::print_fee_info(const std::vector<std::string> &args/* = std::vector<std::string>()*/) +{ + if (!try_connect_to_daemon()) + { + fail_msg_writer() << tr("Cannot connect to daemon"); + return true; + } + const uint64_t per_kb_fee = m_wallet->get_per_kb_fee(); + const uint64_t typical_size_kb = 13; + message_writer() << (boost::format(tr("Current fee is %s monero per kB")) % print_money(per_kb_fee)).str(); + + std::vector<uint64_t> fees; + for (uint32_t priority = 1; priority <= 4; ++priority) + { + uint64_t mult = m_wallet->get_fee_multiplier(priority); + fees.push_back(per_kb_fee * typical_size_kb * mult); + } + std::vector<std::pair<uint64_t, uint64_t>> blocks; + try + { + uint64_t base_size = typical_size_kb * 1024; + blocks = m_wallet->estimate_backlog(base_size, base_size + 1023, fees); + } + catch (const std::exception &e) + { + fail_msg_writer() << tr("Error: failed to estimate backlog array size: ") << e.what(); + return true; + } + if (blocks.size() != 4) + { + fail_msg_writer() << tr("Error: bad estimated backlog array size"); + return true; + } + + for (uint32_t priority = 1; priority <= 4; ++priority) + { + uint64_t nblocks_low = blocks[priority - 1].first; + uint64_t nblocks_high = blocks[priority - 1].second; + if (nblocks_low > 0) + { + std::string msg; + if (priority == m_wallet->get_default_priority() || (m_wallet->get_default_priority() == 0 && priority == 2)) + msg = tr(" (current)"); + uint64_t minutes_low = nblocks_low * DIFFICULTY_TARGET_V2 / 60, minutes_high = nblocks_high * DIFFICULTY_TARGET_V2 / 60; + if (nblocks_high == nblocks_low) + message_writer() << (boost::format(tr("%u block (%u minutes) backlog at priority %u%s")) % nblocks_low % minutes_low % priority % msg).str(); + else + message_writer() << (boost::format(tr("%u to %u block (%u to %u minutes) backlog at priority %u")) % nblocks_low % nblocks_high % minutes_low % minutes_high % priority).str(); + } + else + message_writer() << tr("No backlog at priority ") << priority; + } + return true; +} + bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { const auto pwd_container = get_and_verify_password(); @@ -722,6 +777,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("show_transfer", boost::bind(&simple_wallet::show_transfer, this, _1), tr("Show information about a transfer to/from this address")); m_cmd_binder.set_handler("password", boost::bind(&simple_wallet::change_password, this, _1), tr("Change wallet password")); m_cmd_binder.set_handler("payment_id", boost::bind(&simple_wallet::payment_id, this, _1), tr("Generate a new random full size payment id - these will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids")); + m_cmd_binder.set_handler("fee", boost::bind(&simple_wallet::print_fee_info, this, _1), tr("Print information about fee and current transaction backlog")); m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help")); } //---------------------------------------------------------------------------------------------------- @@ -2431,6 +2487,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri break; default: LOG_ERROR("Unknown transfer method, using original"); + /* FALLTHRU */ case TransferOriginal: ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon); break; @@ -2461,9 +2518,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri } try { - uint64_t nblocks = m_wallet->estimate_backlog(size, fee); - if (nblocks > 0) - prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No)")) % nblocks).str(); + std::vector<std::pair<uint64_t, uint64_t>> nblocks = m_wallet->estimate_backlog(size, size, {fee}); + if (nblocks.size() != 1) + { + prompt << "Internal error checking for backlog. " << tr("Is this okay anyway? (Y/Yes/N/No): "); + } + else + { + if (nblocks[0].first > 0) + prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No)")) % nblocks[0].first).str(); + } } catch (const std::exception &e) { diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index eac4cbc99..079fae9f5 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -175,6 +175,7 @@ namespace cryptonote bool show_transfer(const std::vector<std::string> &args); bool change_password(const std::vector<std::string>& args); bool payment_id(const std::vector<std::string> &args); + bool print_fee_info(const std::vector<std::string> &args); uint64_t get_daemon_blockchain_height(std::string& err); bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c0974f880..7afc1f449 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -379,7 +379,32 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas const cryptonote::account_public_address address = m_wallet->get_account().get_keys().m_account_address; try { + // Generate view only wallet view_wallet->generate(path, password, address, viewkey); + + // Export/Import outputs + auto outputs = m_wallet->export_outputs(); + view_wallet->import_outputs(outputs); + + // Copy scanned blockchain + auto bc = m_wallet->export_blockchain(); + view_wallet->import_blockchain(bc); + + // copy payments + auto payments = m_wallet->export_payments(); + view_wallet->import_payments(payments); + + // copy confirmed outgoing payments + std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments; + m_wallet->get_payments_out(out_payments, 0); + view_wallet->import_payments_out(out_payments); + + // Export/Import key images + // We already know the spent status from the outputs we exported, thus no need to check them again + auto key_images = m_wallet->export_key_images(); + uint64_t spent = 0; + uint64_t unspent = 0; + view_wallet->import_key_images(key_images,spent,unspent,false); m_status = Status_Ok; } catch (const std::exception &e) { LOG_ERROR("Error creating view only wallet: " << e.what()); @@ -387,6 +412,8 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas m_errorString = e.what(); return false; } + // Store wallet + view_wallet->store(); return true; } @@ -862,6 +889,11 @@ bool WalletImpl::exportKeyImages(const string &filename) bool WalletImpl::importKeyImages(const string &filename) { + if (!trustedDaemon()) { + m_status = Status_Error; + m_errorString = tr("Key images can only be imported with a trusted daemon"); + return false; + } try { uint64_t spent = 0, unspent = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 09ca8efe1..323a3a7fe 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3457,12 +3457,15 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal return true; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::get_fee_multiplier(uint32_t priority, int fee_algorithm) const +uint64_t wallet2::get_fee_multiplier(uint32_t priority, int fee_algorithm) { static const uint64_t old_multipliers[3] = {1, 2, 3}; static const uint64_t new_multipliers[3] = {1, 20, 166}; static const uint64_t newer_multipliers[4] = {1, 4, 20, 166}; + if (fee_algorithm == -1) + fee_algorithm = get_fee_algorithm(); + // 0 -> default (here, x1 till fee algorithm 2, x4 from it) if (priority == 0) priority = m_default_priority; @@ -5098,6 +5101,9 @@ uint64_t wallet2::get_approximate_blockchain_height() const const int seconds_per_block = DIFFICULTY_TARGET_V2; // Calculated blockchain height uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block; + // testnet got some huge rollbacks, so the estimation is way off + if (m_testnet && approx_blockchain_height > 105000) + approx_blockchain_height -= 105000; LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height); return approx_blockchain_height; } @@ -5330,7 +5336,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, uint64_t &spent, uint64_t &unspent) +uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent) { COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req); COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); @@ -5379,34 +5385,88 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag m_transfers[n].m_key_image_known = true; } - m_daemon_rpc_mutex.lock(); - bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout); - m_daemon_rpc_mutex.unlock(); - THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); - THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent"); - THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, daemon_resp.status); - THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != signed_key_images.size(), error::wallet_internal_error, - "daemon returned wrong response for is_key_image_spent, wrong amounts count = " + - std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(signed_key_images.size())); - + if(check_spent) + { + m_daemon_rpc_mutex.lock(); + bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout); + m_daemon_rpc_mutex.unlock(); + THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent"); + THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent"); + THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, daemon_resp.status); + THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != signed_key_images.size(), error::wallet_internal_error, + "daemon returned wrong response for is_key_image_spent, wrong amounts count = " + + std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(signed_key_images.size())); + for (size_t n = 0; n < daemon_resp.spent_status.size(); ++n) + { + transfer_details &td = m_transfers[n]; + td.m_spent = daemon_resp.spent_status[n] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT; + } + } spent = 0; unspent = 0; - for (size_t n = 0; n < daemon_resp.spent_status.size(); ++n) + for(size_t i = 0; i < m_transfers.size(); ++i) { - transfer_details &td = m_transfers[n]; + transfer_details &td = m_transfers[i]; uint64_t amount = td.amount(); - td.m_spent = daemon_resp.spent_status[n] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT; if (td.m_spent) spent += amount; else unspent += amount; - LOG_PRINT_L2("Transfer " << n << ": " << print_money(amount) << " (" << td.m_global_output_index << "): " - << (td.m_spent ? "spent" : "unspent") << " (key image " << req.key_images[n] << ")"); + LOG_PRINT_L2("Transfer " << i << ": " << print_money(amount) << " (" << td.m_global_output_index << "): " + << (td.m_spent ? "spent" : "unspent") << " (key image " << req.key_images[i] << ")"); } - LOG_PRINT_L1("Total: " << print_money(spent) << " spent, " << print_money(unspent) << " unspent"); - + MDEBUG("Total: " << print_money(spent) << " spent, " << print_money(unspent) << " unspent"); return m_transfers[signed_key_images.size() - 1].m_block_height; } +wallet2::payment_container wallet2::export_payments() const +{ + payment_container payments; + for (auto const &p : m_payments) + { + payments.emplace(p); + } + return payments; +} +void wallet2::import_payments(const payment_container &payments) +{ + m_payments.clear(); + for (auto const &p : payments) + { + m_payments.emplace(p); + } +} +void wallet2::import_payments_out(const std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> &confirmed_payments) +{ + m_confirmed_txs.clear(); + for (auto const &p : confirmed_payments) + { + m_confirmed_txs.emplace(p); + } +} + +std::vector<crypto::hash> wallet2::export_blockchain() const +{ + std::vector<crypto::hash> bc; + for (auto const &b : m_blockchain) + { + bc.push_back(b); + } + return bc; +} + +void wallet2::import_blockchain(const std::vector<crypto::hash> &bc) +{ + m_blockchain.clear(); + for (auto const &b : bc) + { + m_blockchain.push_back(b); + } + cryptonote::block genesis; + generate_genesis(genesis); + crypto::hash genesis_hash = get_block_hash(genesis); + check_genesis(genesis_hash); + m_local_bc_height = m_blockchain.size(); +} //---------------------------------------------------------------------------------------------------- std::vector<tools::wallet2::transfer_details> wallet2::export_outputs() const { @@ -5747,10 +5807,14 @@ bool wallet2::is_synced() const return get_blockchain_current_height() >= height; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::estimate_backlog(uint64_t blob_size, uint64_t fee) +std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t min_blob_size, uint64_t max_blob_size, const std::vector<uint64_t> &fees) { - THROW_WALLET_EXCEPTION_IF(blob_size == 0, error::wallet_internal_error, "Invalid 0 fee"); - THROW_WALLET_EXCEPTION_IF(fee == 0, error::wallet_internal_error, "Invalid 0 fee"); + THROW_WALLET_EXCEPTION_IF(min_blob_size == 0, error::wallet_internal_error, "Invalid 0 fee"); + THROW_WALLET_EXCEPTION_IF(max_blob_size == 0, error::wallet_internal_error, "Invalid 0 fee"); + for (uint64_t fee: fees) + { + THROW_WALLET_EXCEPTION_IF(fee == 0, error::wallet_internal_error, "Invalid 0 fee"); + } // get txpool backlog epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request> req = AUTO_VAL_INIT(req); @@ -5776,27 +5840,35 @@ uint64_t wallet2::estimate_backlog(uint64_t blob_size, uint64_t fee) THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_info"); THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_info"); THROW_WALLET_EXCEPTION_IF(resp_t.result.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error); + uint64_t full_reward_zone = resp_t.result.block_size_limit / 2; - double our_fee_byte = fee / (double)blob_size; - uint64_t priority_size = 0; - for (const auto &i: res.result.backlog) + std::vector<std::pair<uint64_t, uint64_t>> blocks; + for (uint64_t fee: fees) { - if (i.blob_size == 0) + double our_fee_byte_min = fee / (double)min_blob_size, our_fee_byte_max = fee / (double)max_blob_size; + uint64_t priority_size_min = 0, priority_size_max = 0; + for (const auto &i: res.result.backlog) { - MWARNING("Got 0 sized blob from txpool, ignored"); - continue; + if (i.blob_size == 0) + { + MWARNING("Got 0 sized blob from txpool, ignored"); + continue; + } + double this_fee_byte = i.fee / (double)i.blob_size; + if (this_fee_byte >= our_fee_byte_min) + priority_size_min += i.blob_size; + if (this_fee_byte >= our_fee_byte_max) + priority_size_max += i.blob_size; } - double this_fee_byte = i.fee / (double)i.blob_size; - if (this_fee_byte < our_fee_byte) - continue; - priority_size += i.blob_size; - } - uint64_t full_reward_zone = resp_t.result.block_size_limit / 2; - uint64_t nblocks = (priority_size + full_reward_zone - 1) / full_reward_zone; - MDEBUG("estimate_backlog: priority_size " << priority_size << " for " << our_fee_byte << " (" << our_fee_byte << " piconero fee/byte), " - << nblocks << " blocks at block size " << full_reward_zone); - return nblocks; + uint64_t nblocks_min = (priority_size_min + full_reward_zone - 1) / full_reward_zone; + uint64_t nblocks_max = (priority_size_max + full_reward_zone - 1) / full_reward_zone; + MDEBUG("estimate_backlog: priority_size " << priority_size_min << " - " << priority_size_max << " for " << fee + << " (" << our_fee_byte_min << " - " << our_fee_byte_max << " piconero byte fee), " + << nblocks_min << " - " << nblocks_max << " blocks at block size " << full_reward_zone); + blocks.push_back(std::make_pair(nblocks_min, nblocks_max)); + } + return blocks; } //---------------------------------------------------------------------------------------------------- void wallet2::generate_genesis(cryptonote::block& b) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f30c97635..adf03abcc 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -582,12 +582,17 @@ namespace tools std::string sign(const std::string &data) const; bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const; + // Import/Export wallet data std::vector<tools::wallet2::transfer_details> export_outputs() const; size_t import_outputs(const std::vector<tools::wallet2::transfer_details> &outputs); - + payment_container export_payments() const; + void import_payments(const payment_container &payments); + void import_payments_out(const std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> &confirmed_payments); + std::vector<crypto::hash> export_blockchain() const; + void import_blockchain(const std::vector<crypto::hash> &bc); bool export_key_images(const std::string filename); std::vector<std::pair<crypto::key_image, crypto::signature>> export_key_images() const; - uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, uint64_t &spent, uint64_t &unspent); + uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent = true); uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); void update_pool_state(bool refreshed = false); @@ -604,7 +609,10 @@ namespace tools bool is_synced() const; - uint64_t estimate_backlog(uint64_t blob_size, uint64_t fee); + std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_blob_size, uint64_t max_blob_size, const std::vector<uint64_t> &fees); + + uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1); + uint64_t get_per_kb_fee(); private: /*! @@ -646,9 +654,7 @@ namespace tools void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const; uint64_t get_upper_transaction_size_limit(); std::vector<uint64_t> get_unspent_amounts_vector(); - uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm) const; uint64_t get_dynamic_per_kb_fee_estimate(); - uint64_t get_per_kb_fee(); float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const; std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money) const; void set_spent(size_t idx, uint64_t height); diff --git a/tests/core_proxy/CMakeLists.txt b/tests/core_proxy/CMakeLists.txt index 680e34911..d22fecc9c 100644 --- a/tests/core_proxy/CMakeLists.txt +++ b/tests/core_proxy/CMakeLists.txt @@ -39,8 +39,6 @@ target_link_libraries(core_proxy PRIVATE cryptonote_core cryptonote_protocol - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h index c4fb462e3..85518612a 100644 --- a/tests/core_proxy/core_proxy.h +++ b/tests/core_proxy/core_proxy.h @@ -100,5 +100,6 @@ namespace tests uint8_t get_ideal_hard_fork_version(uint64_t height) const { return 0; } uint8_t get_hard_fork_version(uint64_t height) const { return 0; } cryptonote::difficulty_type get_block_cumulative_difficulty(uint64_t height) const { return 0; } + bool fluffy_blocks_enabled() const { return false; } }; } diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index cb77f8f56..853d46a12 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -30,8 +30,6 @@ add_executable(block_fuzz_tests block.cpp fuzzer.cpp) target_link_libraries(block_fuzz_tests PRIVATE cryptonote_core - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -44,8 +42,6 @@ add_executable(transaction_fuzz_tests transaction.cpp fuzzer.cpp) target_link_libraries(transaction_fuzz_tests PRIVATE cryptonote_core - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -59,8 +55,6 @@ target_link_libraries(signature_fuzz_tests PRIVATE wallet cryptonote_core - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -74,8 +68,6 @@ target_link_libraries(cold-outputs_fuzz_tests PRIVATE wallet cryptonote_core - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -89,8 +81,6 @@ target_link_libraries(cold-transaction_fuzz_tests PRIVATE wallet cryptonote_core - common - blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} diff --git a/tests/unit_tests/ban.cpp b/tests/unit_tests/ban.cpp index bcffc85c9..82ff058b1 100644 --- a/tests/unit_tests/ban.cpp +++ b/tests/unit_tests/ban.cpp @@ -77,6 +77,7 @@ public: uint8_t get_ideal_hard_fork_version(uint64_t height) const { return 0; } uint8_t get_hard_fork_version(uint64_t height) const { return 0; } cryptonote::difficulty_type get_block_cumulative_difficulty(uint64_t height) const { return 0; } + bool fluffy_blocks_enabled() const { return false; } }; typedef nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<test_core>> Server; |