diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3086,8 +3086,8 @@ txid.ToString(), pfrom.GetId()); pfrom.fDisconnect = true; return; - } else if (!fAlreadyHave && !fImporting && !fReindex && - !::ChainstateActive().IsInitialBlockDownload()) { + } else if (!fAlreadyHave && !m_chainman.ActiveChainstate() + .IsInitialBlockDownload()) { RequestTx(State(pfrom.GetId()), txid, current_time); } } @@ -5524,11 +5524,23 @@ 1000000) .GetFeePerK(); int64_t timeNow = GetTimeMicros(); + static FeeFilterRounder g_filter_rounder{ + CFeeRate{DEFAULT_MIN_RELAY_TX_FEE_PER_KB}}; + if (m_chainman.ActiveChainstate().IsInitialBlockDownload()) { + // Received tx-inv messages are discarded when the active + // chainstate is in IBD, so tell the peer to not send them. + currentFilter = MAX_MONEY; + } else { + static const Amount MAX_FILTER{ + g_filter_rounder.round(MAX_MONEY)}; + if (pto->m_tx_relay->lastSentFeeFilter == MAX_FILTER) { + // Send the current filter if we sent MAX_FILTER previously + // and made it out of IBD. + pto->m_tx_relay->nextSendTimeFeeFilter = timeNow - 1; + } + } if (timeNow > pto->m_tx_relay->nextSendTimeFeeFilter) { - static CFeeRate default_feerate = - CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB); - static FeeFilterRounder filterRounder(default_feerate); - Amount filterToSend = filterRounder.round(currentFilter); + Amount filterToSend = g_filter_rounder.round(currentFilter); filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK()); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -175,6 +175,7 @@ netbase_tests.cpp op_reversebytes_tests.cpp pmt_tests.cpp + policy_fee_tests.cpp policyestimator_tests.cpp prevector_tests.cpp radix_tests.cpp diff --git a/src/test/policy_fee_tests.cpp b/src/test/policy_fee_tests.cpp new file mode 100644 --- /dev/null +++ b/src/test/policy_fee_tests.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include + +#include + +#include + +BOOST_FIXTURE_TEST_SUITE(policy_fee_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(FeeRounder) { + FeeFilterRounder fee_rounder{CFeeRate{1000 * SATOSHI}}; + + // check that 1000 rounds to 974 or 1071 + std::set results; + while (results.size() < 2) { + results.emplace(fee_rounder.round(1000 * SATOSHI)); + } + BOOST_CHECK_EQUAL(*results.begin(), 974 * SATOSHI); + BOOST_CHECK_EQUAL(*++results.begin(), 1071 * SATOSHI); + + // check that negative amounts rounds to 0 + BOOST_CHECK_EQUAL(fee_rounder.round(-0 * SATOSHI), Amount::zero()); + BOOST_CHECK_EQUAL(fee_rounder.round(-1 * SATOSHI), Amount::zero()); + + // check that MAX_MONEY rounds to 9170997 + BOOST_CHECK_EQUAL(fee_rounder.round(MAX_MONEY), 9170997 * SATOSHI); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -1115,7 +1115,8 @@ std::vector GetAll(); //! The most-work chain. - CChain &ActiveChain() const; + CChainState &ActiveChainstate() const; + CChain &ActiveChain() const { return ActiveChainstate().m_chain; } int ActiveHeight() const { return ActiveChain().Height(); } CBlockIndex *ActiveTip() const { return ActiveChain().Tip(); } @@ -1217,13 +1218,13 @@ */ extern ChainstateManager g_chainman GUARDED_BY(::cs_main); -/** @returns the most-work valid chainstate. */ +/** Please prefer the identical ChainstateManager::ActiveChainstate */ CChainState &ChainstateActive(); -/** @returns the most-work chain. */ +/** Please prefer the identical ChainstateManager::ActiveChain */ CChain &ChainActive(); -/** @returns the global block index map. */ +/** Please prefer the identical ChainstateManager::BlockIndex */ BlockMap &BlockIndex(); /** diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -6092,9 +6092,9 @@ return *to_modify; } -CChain &ChainstateManager::ActiveChain() const { +CChainState &ChainstateManager::ActiveChainstate() const { assert(m_active_chainstate); - return m_active_chainstate->m_chain; + return *m_active_chainstate; } bool ChainstateManager::IsSnapshotActive() const { diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -51,6 +51,8 @@ self.supports_cli = False def run_test(self): + self.log.info('Get out of IBD for the minfeefilter test') + self.nodes[0].generate(1) self.log.info('Connect nodes both way') connect_nodes(self.nodes[0], self.nodes[1]) connect_nodes(self.nodes[1], self.nodes[0])