From 3b1d7e03fcc1caa8898ced33e127f6ba09d66df8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 29 Jan 2016 15:09:17 +0000 Subject: [PATCH 1/3] Fix V1/V2 use of hard fork related parameters Some of it uses hardcoded height, which will need some thinking for next (voted upon) fork. --- .../blockchain_import.cpp | 8 ++- src/cryptonote_config.h | 6 +-- src/cryptonote_core/blockchain.cpp | 19 ++++--- src/cryptonote_core/blockchain_storage.cpp | 10 ++-- src/cryptonote_core/cryptonote_basic_impl.cpp | 6 +-- src/cryptonote_core/cryptonote_core.cpp | 7 ++- src/cryptonote_core/tx_pool.cpp | 50 +++++++++++++------ src/cryptonote_core/tx_pool.h | 5 +- .../cryptonote_protocol_handler.inl | 2 +- src/rpc/core_rpc_server.cpp | 4 +- src/simplewallet/simplewallet.h | 3 +- src/wallet/wallet2.cpp | 12 +++-- src/wallet/wallet2.h | 2 +- 13 files changed, 89 insertions(+), 45 deletions(-) diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 85ab883f4..30090bd78 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -399,9 +399,15 @@ int import_from_file(FakeCore& simple_core, const std::string& import_file_path, // crypto::hash hsh = null_hash; // size_t blob_size = 0; // get_transaction_hash(tx, hsh, blob_size); + + // we'd need to get the starting heights from the daemon + // to be correct once voting kicks in + uint64_t v2height = opt_testnet ? 624634 : 1009827; + + uint8_t version = h < v2height ? 1 : 2; tx_verification_context tvc = AUTO_VAL_INIT(tvc); bool r = true; - r = simple_core.m_pool.add_tx(tx, tvc, true, true); + r = simple_core.m_pool.add_tx(tx, tvc, true, true, version); if (!r) { LOG_PRINT_RED_L0("failed to add transaction to transaction pool, height=" << h <<", tx_num=" << tx_num); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index f89835ff2..1a093b501 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -55,7 +55,7 @@ #define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)300000000000) // 3 * pow(10, 11) #define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100 -#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE 60000 //size of block (bytes) after which reward for block calculated using block size +#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size #define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 20000 //size of block (bytes) after which reward for block calculated using block size - before first fork #define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600 #define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12 @@ -67,7 +67,7 @@ #define ORPHANED_BLOCKS_MAX_COUNT 100 -#define DIFFICULTY_TARGET 120 // seconds +#define DIFFICULTY_TARGET_V2 120 // seconds #define DIFFICULTY_TARGET_V1 60 // seconds - before first fork #define DIFFICULTY_WINDOW 720 // blocks #define DIFFICULTY_LAG 15 // !!! @@ -76,7 +76,7 @@ #define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS -#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS DIFFICULTY_TARGET * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS +#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS #define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 40e8609b8..b27927c0a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -478,12 +478,18 @@ block Blockchain::pop_block_from_blockchain() if (!is_coinbase(tx)) { cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); + + // This is not quite correct, as we really want to add the txes + // to the pool based on the version determined after all blocks + // are popped. + uint8_t version = get_current_hard_fork_version(); + // We assume that if they were in a block, the transactions are already // known to the network as a whole. However, if we had mined that block, // that might not be always true. Unlikely though, and always relaying // these again might cause a spike of traffic as many nodes re-relay // all the transactions in a popped block when a reorg happens. - bool r = m_tx_pool.add_tx(tx, tvc, true, true); + bool r = m_tx_pool.add_tx(tx, tvc, true, true, version); if (!r) { LOG_ERROR("Error returning transaction to tx_pool"); @@ -702,7 +708,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block() m_timestamps = timestamps; m_difficulties = difficulties; } - size_t target = get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; + size_t target = get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; return next_difficulty(timestamps, difficulties, target); } //------------------------------------------------------------------ @@ -900,7 +906,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: } // FIXME: This will fail if fork activation heights are subject to voting - size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; + size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; // calculate the difficulty target for the block and return it return next_difficulty(timestamps, cumulative_difficulties, target); @@ -2239,7 +2245,7 @@ bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const { //interpret as time uint64_t current_time = static_cast(time(NULL)); - if(current_time + (get_current_hard_fork_version() < 2 ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS) >= unlock_time) + if(current_time + (get_current_hard_fork_version() < 2 ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2) >= unlock_time) return true; else return false; @@ -2364,6 +2370,7 @@ bool Blockchain::check_block_timestamp(const block& b) const //------------------------------------------------------------------ void Blockchain::return_tx_to_pool(const std::vector &txs) { + uint8_t version = get_current_hard_fork_version(); for (auto& tx : txs) { cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); @@ -2372,7 +2379,7 @@ void Blockchain::return_tx_to_pool(const std::vector &txs) // that might not be always true. Unlikely though, and always relaying // these again might cause a spike of traffic as many nodes re-relay // all the transactions in a popped block when a reorg happens. - if (!m_tx_pool.add_tx(tx, tvc, true, true)) + if (!m_tx_pool.add_tx(tx, tvc, true, true, version)) { LOG_PRINT_L0("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool"); } @@ -2698,7 +2705,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& //------------------------------------------------------------------ bool Blockchain::update_next_cumulative_size_limit() { - uint64_t full_reward_zone = get_current_hard_fork_version() < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + uint64_t full_reward_zone = get_current_hard_fork_version() < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2; LOG_PRINT_L3("Blockchain::" << __func__); std::vector sz; diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp index 3034cf3f7..f656f938b 100644 --- a/src/cryptonote_core/blockchain_storage.cpp +++ b/src/cryptonote_core/blockchain_storage.cpp @@ -301,7 +301,7 @@ bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& t if(!is_coinbase(tx)) { cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - bool r = m_tx_pool->add_tx(tx, tvc, true, true); + bool r = m_tx_pool->add_tx(tx, tvc, true, true, 1); CHECK_AND_ASSERT_MES(r, false, "purge_block_data_from_blockchain: failed to add transaction to transaction pool"); } @@ -1699,7 +1699,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt { LOG_PRINT_L1("Block with id: " << id << "has at least one transaction (id: " << tx_id << ") with wrong inputs."); cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - bool add_res = m_tx_pool->add_tx(tx, tvc, true, relayed); + bool add_res = m_tx_pool->add_tx(tx, tvc, true, relayed, 1); CHECK_AND_ASSERT_MES2(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool"); purge_block_data_from_blockchain(bl, tx_processed_count); add_block_as_invalid(bl, id); @@ -1712,7 +1712,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt { LOG_PRINT_L1("Block with id: " << id << " failed to add transaction to blockchain storage"); cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - bool add_res = m_tx_pool->add_tx(tx, tvc, true, relayed); + bool add_res = m_tx_pool->add_tx(tx, tvc, true, relayed, 1); CHECK_AND_ASSERT_MES2(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool"); purge_block_data_from_blockchain(bl, tx_processed_count); bvc.m_verifivation_failed = true; @@ -1787,8 +1787,8 @@ bool blockchain_storage::update_next_comulative_size_limit() get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW); uint64_t median = epee::misc_utils::median(sz); - if(median <= CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) - median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + if(median <= CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1) + median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; m_current_block_cumul_sz_limit = median*2; return true; diff --git a/src/cryptonote_core/cryptonote_basic_impl.cpp b/src/cryptonote_core/cryptonote_basic_impl.cpp index da14d772b..74f44e2af 100644 --- a/src/cryptonote_core/cryptonote_basic_impl.cpp +++ b/src/cryptonote_core/cryptonote_basic_impl.cpp @@ -74,8 +74,8 @@ namespace cryptonote { } //----------------------------------------------------------------------------------------------- bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) { - static_assert(DIFFICULTY_TARGET%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60"); - const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; + static_assert(DIFFICULTY_TARGET_V2%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60"); + const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; const int target_minutes = target / 60; const int emission_speed_factor = EMISSION_SPEED_FACTOR_PER_MINUTE - (target_minutes-1); @@ -85,7 +85,7 @@ namespace cryptonote { base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes; } - uint64_t full_reward_zone = version < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + uint64_t full_reward_zone = version < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2; //make it soft if (median_size < full_reward_zone) { diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 608abea19..ac0be5a07 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -358,6 +358,10 @@ namespace cryptonote r = m_blockchain_storage.init(db, m_testnet, m_fakechain); + // now that we have a valid m_blockchain_storage, we can clean out any + // transactions in the pool that do not conform to the current fork + m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version()); + bool show_time_stats = command_line::get_arg(vm, command_line::arg_show_time_stats) != 0; m_blockchain_storage.set_show_time_stats(show_time_stats); #else @@ -607,7 +611,8 @@ namespace cryptonote return true; } - return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block, relayed); + uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); + return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block, relayed, version); } //----------------------------------------------------------------------------------------------- bool core::relay_txpool_transactions() diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 1be44172d..2c607fa88 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -54,7 +54,8 @@ namespace cryptonote { namespace { - size_t const TRANSACTION_SIZE_LIMIT = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); + size_t const TRANSACTION_SIZE_LIMIT_V1 = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); + size_t const TRANSACTION_SIZE_LIMIT_V2 = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); time_t const MIN_RELAY_TIME = (60 * 5); // only start re-relaying transactions after that many seconds time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends @@ -81,7 +82,7 @@ namespace cryptonote } #endif //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed) + bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed, uint8_t version) { @@ -118,9 +119,10 @@ namespace cryptonote return false; } - if (!kept_by_block && blob_size >= TRANSACTION_SIZE_LIMIT) + size_t tx_size_limit = (version < 2 ? TRANSACTION_SIZE_LIMIT_V1 : TRANSACTION_SIZE_LIMIT_V2); + if (!kept_by_block && blob_size >= tx_size_limit) { - LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << TRANSACTION_SIZE_LIMIT); + LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << tx_size_limit); tvc.m_verifivation_failed = true; return false; } @@ -217,12 +219,12 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed) + bool tx_memory_pool::add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, uint8_t version) { crypto::hash h = null_hash; size_t blob_size = 0; get_transaction_hash(tx, h, blob_size); - return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed); + return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed, version); } //--------------------------------------------------------------------------------- bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx) @@ -607,6 +609,33 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- + size_t tx_memory_pool::validate(uint8_t version) + { + size_t n_removed = 0; + size_t tx_size_limit = (version < 2 ? TRANSACTION_SIZE_LIMIT_V1 : TRANSACTION_SIZE_LIMIT_V2); + for (auto it = m_transactions.begin(); it != m_transactions.end(); ) { + if (it->second.blob_size >= tx_size_limit) { + 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()) + { + 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); + } + auto pit = it++; + m_transactions.erase(pit); + ++n_removed; + continue; + } + it++; + } + return n_removed; + } + //--------------------------------------------------------------------------------- bool tx_memory_pool::init(const std::string& config_folder) { CRITICAL_REGION_LOCAL(m_transactions_lock); @@ -629,15 +658,6 @@ namespace cryptonote m_spent_key_images.clear(); } - for (auto it = m_transactions.begin(); it != m_transactions.end(); ) { - if (it->second.blob_size >= TRANSACTION_SIZE_LIMIT) { - 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); - m_transactions.erase(it); - } - it++; - } - // no need to store queue of sorted transactions, as it's easy to generate. for (const auto& tx : m_transactions) { diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 5a3af1262..3832ccb64 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -81,8 +81,8 @@ namespace cryptonote #else tx_memory_pool(blockchain_storage& bchs); #endif - bool add_tx(const transaction &tx, const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block, bool relayed); - bool add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed); + bool add_tx(const transaction &tx, const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block, bool relayed, uint8_t version); + bool add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, uint8_t version); //gets tx and remove it from pool bool take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee, bool &relayed); @@ -105,6 +105,7 @@ namespace cryptonote void set_relayed(const std::list>& txs); size_t get_transactions_count() const; std::string print_pool(bool short_format) const; + size_t validate(uint8_t version); /*bool flush_pool(const std::strig& folder); bool inflate_pool(const std::strig& folder);*/ diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 88908d75f..f917f4c3f 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -278,7 +278,7 @@ namespace cryptonote int64_t diff = static_cast(hshd.current_height) - static_cast(m_core.get_current_blockchain_height()); LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height - << " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET) << " days) " + << " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET_V1) << " days) " << (0 <= diff ? std::string("behind") : std::string("ahead")) << "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1)); LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 0f9e2b3ab..adcaf036d 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -127,7 +127,7 @@ namespace cryptonote res.top_block_hash = string_tools::pod_to_hex(top_hash); res.target_height = m_core.get_target_blockchain_height(); res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block(); - res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; + res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase res.tx_pool_size = m_core.get_pool_transactions_count(); res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); @@ -902,7 +902,7 @@ namespace cryptonote res.height = m_core.get_current_blockchain_height(); res.target_height = m_core.get_target_blockchain_height(); res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block(); - res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; + res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase res.tx_pool_size = m_core.get_pool_transactions_count(); res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index c2a8d2296..05f42f8de 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -177,7 +177,8 @@ namespace cryptonote void update(uint64_t height, bool force = false) { auto current_time = std::chrono::system_clock::now(); - if (std::chrono::seconds(DIFFICULTY_TARGET / 2) < current_time - m_blockchain_height_update_time || m_blockchain_height <= height) + const auto node_update_threshold = std::chrono::seconds(DIFFICULTY_TARGET_V1 / 2); // use min of V1/V2 + if (node_update_threshold < current_time - m_blockchain_height_update_time || m_blockchain_height <= height) { update_blockchain_height(); m_blockchain_height = (std::max)(m_blockchain_height, height); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 55e290c0c..d636b0e4b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1450,7 +1450,7 @@ void wallet2::rescan_blockchain(bool refresh) //---------------------------------------------------------------------------------------------------- bool wallet2::is_transfer_unlocked(const transfer_details& td) const { - if(!is_tx_spendtime_unlocked(td.m_tx.unlock_time)) + if(!is_tx_spendtime_unlocked(td.m_tx.unlock_time, td.m_block_height)) return false; if(td.m_block_height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE > m_blockchain.size()) @@ -1459,7 +1459,7 @@ bool wallet2::is_transfer_unlocked(const transfer_details& td) const return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time) const +bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const { if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER) { @@ -1472,7 +1472,11 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time) const { //interpret as time uint64_t current_time = static_cast(time(NULL)); - if(current_time + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS >= unlock_time) + // XXX: this needs to be fast, so we'd need to get the starting heights + // from the daemon to be correct once voting kicks in + uint64_t v2height = m_testnet ? 624634 : 1009827; + uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2; + if(current_time + leeway >= unlock_time) return true; else return false; @@ -2417,7 +2421,7 @@ uint64_t wallet2::get_upper_tranaction_size_limit() { if (m_upper_transaction_size_limit > 0) return m_upper_transaction_size_limit; - uint64_t full_reward_zone = use_fork_rules(2) ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; + uint64_t full_reward_zone = use_fork_rules(2) ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; return ((full_reward_zone * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 9912226c6..e29619444 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -356,7 +356,7 @@ namespace tools void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height); void detach_blockchain(uint64_t height); void get_short_chain_history(std::list& ids) const; - bool is_tx_spendtime_unlocked(uint64_t unlock_time) const; + bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const; bool is_transfer_unlocked(const transfer_details& td) const; bool clear(); void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::list &blocks); From eadbdf354a3a3135fd235ce3cce47d8b89f7b279 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 29 Jan 2016 16:49:53 +0000 Subject: [PATCH 2/3] tx_pool: fix use of invalidated iterator --- src/cryptonote_core/tx_pool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 2c607fa88..2cef68a85 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -315,7 +315,8 @@ namespace cryptonote { m_txs_by_fee.erase(sorted_it); } - m_transactions.erase(it++); + auto pit = it++; + m_transactions.erase(pit); }else ++it; } From 94b98fb5fa98ca317664b96d6a564159945de95e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 29 Jan 2016 17:15:09 +0000 Subject: [PATCH 3/3] tx_pool: do not accept txes not in a block if they timed out before This is intended to avoid cases where a timed out tx will be re-relayed by another peer for which it has not timed out yet, which would cause the tx to stay in the network's pool for a long time (until all peers time it out before another one tries to relay it again). --- src/cryptonote_core/tx_pool.cpp | 11 ++++++++++- src/cryptonote_core/tx_pool.h | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 2cef68a85..5d67acdd2 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -84,7 +84,15 @@ namespace cryptonote //--------------------------------------------------------------------------------- bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed, uint8_t version) { - + // we do not accept transactions that timed out before, unless they're + // kept_by_block + if (!kept_by_block && m_timed_out_transactions.find(id) != m_timed_out_transactions.end()) + { + // not clear if we should set that, since verifivation (sic) did not fail before, since + // the tx was accepted before timing out. + tvc.m_verifivation_failed = true; + return false; + } if(!check_inputs_types_supported(tx)) { @@ -315,6 +323,7 @@ namespace cryptonote { m_txs_by_fee.erase(sorted_it); } + m_timed_out_transactions.insert(it->first); auto pit = it++; m_transactions.erase(pit); }else diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 3832ccb64..34dc1f72f 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -110,7 +110,7 @@ namespace cryptonote /*bool flush_pool(const std::strig& folder); bool inflate_pool(const std::strig& folder);*/ -#define CURRENT_MEMPOOL_ARCHIVE_VER 9 +#define CURRENT_MEMPOOL_ARCHIVE_VER 10 template void serialize(archive_t & a, const unsigned int version) @@ -120,6 +120,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); a & m_transactions; a & m_spent_key_images; + a & m_timed_out_transactions; } struct tx_details @@ -162,6 +163,8 @@ namespace cryptonote sorted_tx_container::iterator find_tx_in_sorted_container(const crypto::hash& id) const; + std::unordered_set m_timed_out_transactions; + //transactions_container m_alternative_transactions; std::string m_config_folder;