diff options
-rw-r--r-- | src/blockchain_db/berkeleydb/db_bdb.cpp | 3 | ||||
-rw-r--r-- | src/blockchain_db/berkeleydb/db_bdb.h | 2 | ||||
-rw-r--r-- | src/blockchain_db/blockchain_db.h | 9 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 56 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.h | 3 | ||||
-rw-r--r-- | src/blockchain_utilities/fake_core.h | 4 | ||||
-rw-r--r-- | src/cryptonote_core/account.cpp | 8 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 14 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 11 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 32 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.h | 15 | ||||
-rw-r--r-- | src/wallet/api/address_book.cpp | 54 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 18 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet2_api.h | 5 | ||||
-rw-r--r-- | tests/unit_tests/hardfork.cpp | 2 |
16 files changed, 169 insertions, 69 deletions
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp index 137ed9dc6..57d8371bd 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.cpp +++ b/src/blockchain_db/berkeleydb/db_bdb.cpp @@ -1813,9 +1813,10 @@ bool BlockchainBDB::has_key_image(const crypto::key_image& img) const // Ostensibly BerkeleyDB has batch transaction support built-in, // so the following few functions will be NOP. -void BlockchainBDB::batch_start(uint64_t batch_num_blocks) +bool BlockchainBDB::batch_start(uint64_t batch_num_blocks) { LOG_PRINT_L3("BlockchainBDB::" << __func__); + return false; } void BlockchainBDB::batch_commit() diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h index f320ab0e3..266e780c6 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.h +++ b/src/blockchain_db/berkeleydb/db_bdb.h @@ -324,7 +324,7 @@ public: ); virtual void set_batch_transactions(bool batch_transactions); - virtual void batch_start(uint64_t batch_num_blocks=0); + virtual bool batch_start(uint64_t batch_num_blocks=0); virtual void batch_commit(); virtual void batch_stop(); virtual void batch_abort(); diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index b39cb1801..455e0c811 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -655,16 +655,17 @@ public: * been called. In either case, it should end the batch and write to its * backing store. * - * If a batch is already in-progress, this function should throw a DB_ERROR. - * This exception may change in the future if it is deemed necessary to - * have a more granular exception type for this scenario. + * If a batch is already in-progress, this function must return false. + * If a batch was started by this call, it must return true. * * If any of this cannot be done, the subclass should throw the corresponding * subclass of DB_EXCEPTION * * @param batch_num_blocks number of blocks to batch together + * + * @return true if we started the batch, false if already started */ - virtual void batch_start(uint64_t batch_num_blocks=0) = 0; + virtual bool batch_start(uint64_t batch_num_blocks=0) = 0; /** * @brief ends a batch transaction diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index ba2cb60bd..ca79ab4f8 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -543,6 +543,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks) con uint64_t min_block_size = 4 * 1024; uint64_t block_stop = 0; + uint64_t m_height = height(); if (m_height > 1) block_stop = m_height - 1; uint64_t block_start = 0; @@ -593,6 +594,7 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; + uint64_t m_height = height(); CURSOR(block_heights) blk_height bh = {blk_hash, m_height}; @@ -654,6 +656,7 @@ void BlockchainLMDB::remove_block() LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t m_height = height(); if (m_height == 0) throw0(BLOCK_DNE ("Attempting to remove block from an empty blockchain")); @@ -691,6 +694,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; + uint64_t m_height = height(); int result; uint64_t tx_id = m_num_txs; @@ -787,6 +791,7 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash, LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; + uint64_t m_height = height(); int result = 0; @@ -1018,7 +1023,6 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions) m_write_txn = nullptr; m_write_batch_txn = nullptr; m_batch_active = false; - m_height = 0; m_cum_size = 0; m_cum_count = 0; @@ -1143,7 +1147,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) if ((result = mdb_stat(txn, m_blocks, &db_stats))) throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str())); LOG_PRINT_L2("Setting m_height to: " << db_stats.ms_entries); - m_height = db_stats.ms_entries; + uint64_t m_height = db_stats.ms_entries; // get and keep current number of txs if ((result = mdb_stat(txn, m_txs, &db_stats))) @@ -1294,7 +1298,6 @@ void BlockchainLMDB::reset() throw0(DB_ERROR(lmdb_error("Failed to write version to database: ", result).c_str())); txn.commit(); - m_height = 0; m_num_outputs = 0; m_cum_size = 0; m_cum_count = 0; @@ -1515,6 +1518,7 @@ uint64_t BlockchainLMDB::get_top_block_timestamp() const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t m_height = height(); // if no blocks, return 0 if (m_height == 0) @@ -1666,6 +1670,7 @@ crypto::hash BlockchainLMDB::top_block_hash() const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t m_height = height(); if (m_height != 0) { return get_block_hash_from_height(m_height - 1); @@ -1678,6 +1683,7 @@ block BlockchainLMDB::get_top_block() const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t m_height = height(); if (m_height != 0) { @@ -1692,8 +1698,14 @@ uint64_t BlockchainLMDB::height() const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + TXN_PREFIX_RDONLY(); + int result; - return m_height; + // get current height + MDB_stat db_stats; + if ((result = mdb_stat(m_txn, m_blocks, &db_stats))) + throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str())); + return db_stats.ms_entries; } bool BlockchainLMDB::tx_exists(const crypto::hash& h) const @@ -2242,15 +2254,15 @@ bool BlockchainLMDB::for_all_outputs(std::function<bool(uint64_t amount, const c } // batch_num_blocks: (optional) Used to check if resize needed before batch transaction starts. -void BlockchainLMDB::batch_start(uint64_t batch_num_blocks) +bool BlockchainLMDB::batch_start(uint64_t batch_num_blocks) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); if (! m_batch_transactions) throw0(DB_ERROR("batch transactions not enabled")); if (m_batch_active) - throw0(DB_ERROR("batch transaction already in progress")); + return false; if (m_write_batch_txn != nullptr) - throw0(DB_ERROR("batch transaction already in progress")); + return false; if (m_write_txn) throw0(DB_ERROR("batch transaction attempted, but m_write_txn already in use")); check_open(); @@ -2276,6 +2288,7 @@ void BlockchainLMDB::batch_start(uint64_t batch_num_blocks) memset(&m_wcursors, 0, sizeof(m_wcursors)); LOG_PRINT_L3("batch transaction: begin"); + return true; } void BlockchainLMDB::batch_commit() @@ -2287,6 +2300,9 @@ void BlockchainLMDB::batch_commit() throw0(DB_ERROR("batch transaction not in progress")); if (m_write_batch_txn == nullptr) throw0(DB_ERROR("batch transaction not in progress")); + if (m_writer != boost::this_thread::get_id()) + return; // batch txn owned by other thread + check_open(); LOG_PRINT_L3("batch transaction: committing..."); @@ -2311,6 +2327,8 @@ void BlockchainLMDB::batch_stop() throw0(DB_ERROR("batch transaction not in progress")); if (m_write_batch_txn == nullptr) throw0(DB_ERROR("batch transaction not in progress")); + if (m_writer != boost::this_thread::get_id()) + return; // batch txn owned by other thread check_open(); LOG_PRINT_L3("batch transaction: committing..."); TIME_MEASURE_START(time1); @@ -2333,6 +2351,8 @@ void BlockchainLMDB::batch_abort() throw0(DB_ERROR("batch transactions not enabled")); if (! m_batch_active) throw0(DB_ERROR("batch transaction not in progress")); + if (m_writer != boost::this_thread::get_id()) + return; // batch txn owned by other thread check_open(); // for destruction of batch transaction m_write_txn = nullptr; @@ -2505,6 +2525,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, c { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t m_height = height(); if (m_height % 1000 == 0) { @@ -2558,8 +2579,6 @@ void BlockchainLMDB::pop_block(block& blk, std::vector<transaction>& txs) block_txn_abort(); throw; } - - --m_height; } void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices, @@ -2850,7 +2869,7 @@ void BlockchainLMDB::fixup() void BlockchainLMDB::migrate_0_1() { LOG_PRINT_L3("BlockchainLMDB::" << __func__); - uint64_t i, z; + uint64_t i, z, m_height; int result; mdb_txn_safe txn(false); MDB_val k, v; @@ -2859,17 +2878,22 @@ void BlockchainLMDB::migrate_0_1() LOG_PRINT_YELLOW("Migrating blockchain from DB version 0 to 1 - this may take a while:", LOG_LEVEL_0); LOG_PRINT_L0("updating blocks, hf_versions, outputs, txs, and spent_keys tables..."); - LOG_PRINT_L0("Total number of blocks: " << m_height); - LOG_PRINT_L1("block migration will update block_heights, block_info, and hf_versions..."); - do { + result = mdb_txn_begin(m_env, NULL, 0, txn); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); + + MDB_stat db_stats; + if ((result = mdb_stat(txn, m_blocks, &db_stats))) + throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str())); + m_height = db_stats.ms_entries; + LOG_PRINT_L0("Total number of blocks: " << m_height); + LOG_PRINT_L1("block migration will update block_heights, block_info, and hf_versions..."); + LOG_PRINT_L1("migrating block_heights:"); MDB_dbi o_heights; unsigned int flags; - result = mdb_txn_begin(m_env, NULL, 0, txn); - if (result) - throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); result = mdb_dbi_flags(txn, m_block_heights, &flags); if (result) throw0(DB_ERROR(lmdb_error("Failed to retrieve block_heights flags: ", result).c_str())); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index b0d8d9d0a..e7faf8cdc 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -247,7 +247,7 @@ public: ); virtual void set_batch_transactions(bool batch_transactions); - virtual void batch_start(uint64_t batch_num_blocks=0); + virtual bool batch_start(uint64_t batch_num_blocks=0); virtual void batch_commit(); virtual void batch_stop(); virtual void batch_abort(); @@ -369,7 +369,6 @@ private: MDB_dbi m_properties; - uint64_t m_height; uint64_t m_num_txs; uint64_t m_num_outputs; mutable uint64_t m_cum_size; // used in batch size estimation diff --git a/src/blockchain_utilities/fake_core.h b/src/blockchain_utilities/fake_core.h index ba1c2ed72..814139602 100644 --- a/src/blockchain_utilities/fake_core.h +++ b/src/blockchain_utilities/fake_core.h @@ -119,9 +119,9 @@ struct fake_core_db return m_storage.get_db().add_block(blk, block_size, cumulative_difficulty, coins_generated, txs); } - void batch_start(uint64_t batch_num_blocks = 0) + bool batch_start(uint64_t batch_num_blocks = 0) { - m_storage.get_db().batch_start(batch_num_blocks); + return m_storage.get_db().batch_start(batch_num_blocks); } void batch_stop() diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index 602561489..bd703eee2 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -82,7 +82,9 @@ DISABLE_VS_WARNINGS(4244 4345) if (recover) { - m_creation_timestamp = std::max(mktime(×tamp), (long)0); + m_creation_timestamp = mktime(×tamp); + if (m_creation_timestamp == (uint64_t)-1) // failure + m_creation_timestamp = 0; // lowest value } else { @@ -105,7 +107,9 @@ DISABLE_VS_WARNINGS(4244 4345) timestamp.tm_min = 0; timestamp.tm_sec = 0; - m_creation_timestamp = std::max(mktime(×tamp), (long)0); + m_creation_timestamp = mktime(×tamp); + if (m_creation_timestamp == (uint64_t)-1) // failure + m_creation_timestamp = 0; // lowest value } //----------------------------------------------------------------- void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index de3af8e02..f0779dad0 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3381,9 +3381,10 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce) { const auto& pts = points.get_points(); + bool stop_batch; CRITICAL_REGION_LOCAL(m_blockchain_lock); - m_db->batch_start(); + stop_batch = m_db->batch_start(); for (const auto& pt : pts) { // if the checkpoint is for a block we don't have yet, move on @@ -3407,7 +3408,8 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor } } } - m_db->batch_stop(); + if (stop_batch) + m_db->batch_stop(); } //------------------------------------------------------------------ // returns false if any of the checkpoints loading returns false. @@ -3481,6 +3483,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) CRITICAL_REGION_LOCAL(m_blockchain_lock); TIME_MEASURE_START(t1); + m_db->batch_stop(); if (m_sync_counter > 0) { if (force_sync) @@ -3545,11 +3548,18 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e { LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3); TIME_MEASURE_START(prepare); + bool stop_batch; CRITICAL_REGION_LOCAL(m_blockchain_lock); if(blocks_entry.size() == 0) return false; + while (!(stop_batch = m_db->batch_start(blocks_entry.size()))) { + m_blockchain_lock.unlock(); + epee::misc_utils::sleep_no_w(1000); + m_blockchain_lock.lock(); + } + if ((m_db->height() + blocks_entry.size()) < m_blocks_hash_check.size()) return true; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index c63a08ee4..c2da7aaea 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -312,9 +312,9 @@ namespace cryptonote LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ..."); const std::string filename = folder.string(); - // temporarily default to fastest:async:1000 + // default to fast:async:1 blockchain_db_sync_mode sync_mode = db_async; - uint64_t blocks_per_sync = 1000; + uint64_t blocks_per_sync = 1; try { @@ -327,12 +327,12 @@ namespace cryptonote for(const auto &option : options) LOG_PRINT_L0("option: " << option); - // default to fast:async:1000 + // default to fast:async:1 uint64_t DEFAULT_FLAGS = DBS_FAST_MODE; if(options.size() == 0) { - // temporarily default to fastest:async:1000 + // default to fast:async:1 db_flags = DEFAULT_FLAGS; } @@ -348,7 +348,10 @@ namespace cryptonote else if(options[0] == "fast") db_flags = DBS_FAST_MODE; else if(options[0] == "fastest") + { db_flags = DBS_FASTEST_MODE; + blocks_per_sync = 1000; // default to fastest:async:1000 + } else db_flags = DEFAULT_FLAGS; } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 59ac534fe..028585741 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -177,6 +177,8 @@ namespace cryptonote return false; } + time_t receive_time = time(nullptr); + crypto::hash max_used_block_id = null_hash; uint64_t max_used_block_height = 0; tx_details txd; @@ -198,7 +200,7 @@ namespace cryptonote txd_p.first->second.last_failed_height = 0; txd_p.first->second.last_failed_id = null_hash; txd_p.first->second.kept_by_block = kept_by_block; - txd_p.first->second.receive_time = time(nullptr); + txd_p.first->second.receive_time = receive_time; txd_p.first->second.last_relayed_time = time(NULL); txd_p.first->second.relayed = relayed; tvc.m_verifivation_impossible = true; @@ -221,7 +223,7 @@ namespace cryptonote txd_p.first->second.max_used_block_height = max_used_block_height; txd_p.first->second.last_failed_height = 0; txd_p.first->second.last_failed_id = null_hash; - txd_p.first->second.receive_time = time(nullptr); + txd_p.first->second.receive_time = receive_time; txd_p.first->second.last_relayed_time = time(NULL); txd_p.first->second.relayed = relayed; tvc.m_added_to_pool = true; @@ -246,7 +248,7 @@ namespace cryptonote tvc.m_verifivation_failed = false; - m_txs_by_fee.emplace((double)blob_size / fee, id); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>((double)blob_size / fee, receive_time), id); return true; } @@ -301,7 +303,7 @@ namespace cryptonote auto sorted_it = find_tx_in_sorted_container(id); - if (sorted_it == m_txs_by_fee.end()) + if (sorted_it == m_txs_by_fee_and_receive_time.end()) return false; tx = it->second.tx; @@ -310,7 +312,7 @@ namespace cryptonote relayed = it->second.relayed; remove_transaction_keyimages(it->second.tx); m_transactions.erase(it); - m_txs_by_fee.erase(sorted_it); + m_txs_by_fee_and_receive_time.erase(sorted_it); return true; } //--------------------------------------------------------------------------------- @@ -321,7 +323,7 @@ namespace cryptonote //--------------------------------------------------------------------------------- sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id) const { - return std::find_if( m_txs_by_fee.begin(), m_txs_by_fee.end() + return std::find_if( m_txs_by_fee_and_receive_time.begin(), m_txs_by_fee_and_receive_time.end() , [&](const sorted_tx_container::value_type& a){ return a.second == id; } @@ -342,13 +344,13 @@ namespace cryptonote LOG_PRINT_L1("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age ); remove_transaction_keyimages(it->second.tx); auto sorted_it = find_tx_in_sorted_container(it->first); - if (sorted_it == m_txs_by_fee.end()) + if (sorted_it == m_txs_by_fee_and_receive_time.end()) { LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!"); } else { - m_txs_by_fee.erase(sorted_it); + m_txs_by_fee_and_receive_time.erase(sorted_it); } m_timed_out_transactions.insert(it->first); auto pit = it++; @@ -608,9 +610,9 @@ namespace cryptonote size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; std::unordered_set<crypto::key_image> k_images; - LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee.size() << " txes in the pool"); - auto sorted_it = m_txs_by_fee.begin(); - while (sorted_it != m_txs_by_fee.end()) + LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool"); + auto sorted_it = m_txs_by_fee_and_receive_time.begin(); + while (sorted_it != m_txs_by_fee_and_receive_time.end()) { auto tx_it = m_transactions.find(sorted_it->second); LOG_PRINT_L2("Considering " << tx_it->first << ", size " << tx_it->second.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase)); @@ -675,13 +677,13 @@ namespace cryptonote LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool"); remove_transaction_keyimages(it->second.tx); auto sorted_it = find_tx_in_sorted_container(it->first); - if (sorted_it == m_txs_by_fee.end()) + if (sorted_it == m_txs_by_fee_and_receive_time.end()) { LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!"); } else { - m_txs_by_fee.erase(sorted_it); + m_txs_by_fee_and_receive_time.erase(sorted_it); } auto pit = it++; m_transactions.erase(pit); @@ -712,14 +714,14 @@ namespace cryptonote LOG_ERROR("Failed to load memory pool from file " << state_file_path); m_transactions.clear(); - m_txs_by_fee.clear(); + m_txs_by_fee_and_receive_time.clear(); m_spent_key_images.clear(); } // no need to store queue of sorted transactions, as it's easy to generate. for (const auto& tx : m_transactions) { - m_txs_by_fee.emplace((double)tx.second.blob_size / tx.second.fee, tx.first); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>((double)tx.second.blob_size / tx.second.fee, tx.second.receive_time), tx.first); } // Ignore deserialization error diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 32a05b0f4..9258a0c38 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -54,23 +54,25 @@ namespace cryptonote /************************************************************************/ //! pair of <transaction fee, transaction hash> for organization - typedef std::pair<double, crypto::hash> tx_by_fee_entry; + typedef std::pair<std::pair<double, std::time_t>, crypto::hash> tx_by_fee_and_receive_time_entry; class txCompare { public: - bool operator()(const tx_by_fee_entry& a, const tx_by_fee_entry& b) + bool operator()(const tx_by_fee_and_receive_time_entry& a, const tx_by_fee_and_receive_time_entry& b) { // sort by greatest first, not least - if (a.first > b.first) return true; - else if (a.first < b.first) return false; + if (a.first.first > b.first.first) return true; + else if (a.first.first < b.first.first) return false; + else if (a.first.second < b.first.second) return true; + else if (a.first.second > b.first.second) return false; else if (a.second != b.second) return true; else return false; } }; //! container for sorting transactions by fee per unit size - typedef std::set<tx_by_fee_entry, txCompare> sorted_tx_container; + typedef std::set<tx_by_fee_and_receive_time_entry, txCompare> sorted_tx_container; /** * @brief Transaction pool, handles transactions which are not part of a block @@ -473,7 +475,8 @@ private: epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval; //TODO: look into doing this better - sorted_tx_container m_txs_by_fee; //!< container for transactions organized by fee per size + //!< container for transactions organized by fee per size and receive time + sorted_tx_container m_txs_by_fee_and_receive_time; /** * @brief get an iterator to a transaction in the sorted container diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index b878491ce..e397dac04 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.cpp @@ -33,6 +33,7 @@ #include "wallet.h" #include "crypto/hash.h" #include "wallet/wallet2.h" +#include "common_defines.h" #include <vector> @@ -43,30 +44,50 @@ AddressBook::~AddressBook() {} AddressBookImpl::AddressBookImpl(WalletImpl *wallet) : m_wallet(wallet) {} -bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) +bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &payment_id_str, const std::string &description) { - LOG_PRINT_L2("Adding row"); - clearStatus(); cryptonote::account_public_address addr; - bool has_payment_id; + bool has_short_pid; crypto::hash8 payment_id_short; - if(!cryptonote::get_account_integrated_address_from_str(addr, has_payment_id, payment_id_short, m_wallet->m_wallet->testnet(), dst_addr)) { - m_errorString = "Invalid destination address"; + if(!cryptonote::get_account_integrated_address_from_str(addr, has_short_pid, payment_id_short, m_wallet->m_wallet->testnet(), dst_addr)) { + m_errorString = tr("Invalid destination address"); m_errorCode = Invalid_Address; return false; } - crypto::hash pid32 = cryptonote::null_hash; - bool long_pid = (payment_id.empty())? false : tools::wallet2::parse_long_payment_id(payment_id, pid32); - if(!payment_id.empty() && !long_pid) { - m_errorString = "Invalid payment ID"; + crypto::hash payment_id = cryptonote::null_hash; + bool has_long_pid = (payment_id_str.empty())? false : tools::wallet2::parse_long_payment_id(payment_id_str, payment_id); + + // Short payment id provided + if(payment_id_str.length() == 16) { + m_errorString = tr("Invalid payment ID. Short payment ID should only be used in an integrated address"); + m_errorCode = Invalid_Payment_Id; + return false; + } + + // long payment id provided but not valid + if(!payment_id_str.empty() && !has_long_pid) { + m_errorString = tr("Invalid payment ID"); + m_errorCode = Invalid_Payment_Id; + return false; + } + + // integrated + long payment id provided + if(has_long_pid && has_short_pid) { + m_errorString = tr("Integrated address and long payment id can't be used at the same time"); m_errorCode = Invalid_Payment_Id; return false; } - bool r = m_wallet->m_wallet->add_address_book_row(addr,pid32,description); + // Pad short pid with zeros + if (has_short_pid) + { + memcpy(payment_id.data, payment_id_short.data, 8); + } + + bool r = m_wallet->m_wallet->add_address_book_row(addr,payment_id,description); if (r) refresh(); else @@ -87,7 +108,16 @@ void AddressBookImpl::refresh() std::string payment_id = (row->m_payment_id == cryptonote::null_hash)? "" : epee::string_tools::pod_to_hex(row->m_payment_id); std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->testnet(),row->m_address); - + // convert the zero padded short payment id to integrated address + if (payment_id.length() > 16 && payment_id.substr(16).find_first_not_of('0') == std::string::npos) { + payment_id = payment_id.substr(0,16); + crypto::hash8 payment_id_short; + if(tools::wallet2::parse_short_payment_id(payment_id, payment_id_short)) { + address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->testnet(), row->m_address, payment_id_short); + // Don't show payment id when integrated address is used + payment_id = ""; + } + } AddressBookRow * abr = new AddressBookRow(i, address, payment_id, row->m_description); m_rows.push_back(abr); } diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 849ecf651..353737d6b 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1260,6 +1260,24 @@ bool WalletImpl::parse_uri(const std::string &uri, std::string &address, std::st return m_wallet->parse_uri(uri, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error); } +bool WalletImpl::rescanSpent() +{ + clearStatus(); + if (!trustedDaemon()) { + m_status = Status_Error; + m_errorString = tr("Rescan spent can only be used with a trusted daemon"); + return false; + } + try { + m_wallet->rescan_spent(); + } catch (const std::exception &e) { + LOG_ERROR(__FUNCTION__ << " error: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + return false; + } + return true; +} } // namespace namespace Bitmonero = Monero; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index ea8c864ac..e26f30d70 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -93,7 +93,7 @@ public: void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); void setRecoveringFromSeed(bool recoveringFromSeed); bool watchOnly() const; - + bool rescanSpent(); PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 7ae8eb9c3..5a13205c5 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -573,6 +573,11 @@ struct Wallet virtual bool verifySignedMessage(const std::string &message, const std::string &addres, const std::string &signature) const = 0; virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) = 0; + /* + * \brief rescanSpent - Rescan spent outputs - Can only be used with trusted daemon + * \return true on success + */ + virtual bool rescanSpent() = 0; }; /** diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index ca72f5e0e..be17f01ad 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -51,7 +51,7 @@ public: virtual std::string get_db_name() const { return std::string(); } virtual bool lock() { return true; } virtual void unlock() { } - virtual void batch_start(uint64_t batch_num_blocks=0) {} + virtual bool batch_start(uint64_t batch_num_blocks=0) {} virtual void batch_stop() {} virtual void set_batch_transactions(bool) {} virtual void block_txn_start(bool readonly=false) {} |