Browse Source

Merge #11839: don't attempt mempool entry for wallet transactions on startup if alr…

6697a70 add test for unconfirmed balance between restarts (Gregory Sanders)
6ba8f30 don't attempt mempool entry for wallet transactions on startup if already in mempool (Gregory Sanders)

Pull request description:

  …eady in mempool

  Mempool loads first, wallet second. Second attempt fails, marking that transaction !fInMempool. Those funds will disappear until confirmation is reached.

Tree-SHA512: 955f0565ec1dc1ba395e0b803a98c07b7cd00c8cac5ec618ed832fed259a856fb7bbbe41310cf6a4e43c0435e09b156109d2a4467d403811dc8379d2caebeede
0.16
Wladimir J. van der Laan 7 years ago
parent
commit
8ab6c0b09e
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D
  1. 5
      src/wallet/wallet.cpp
  2. 8
      test/functional/mempool_persist.py

5
src/wallet/wallet.cpp

@ -4114,6 +4114,11 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
{ {
// Quick check to avoid re-setting fInMempool to false
if (mempool.exists(tx->GetHash())) {
return false;
}
// We must set fInMempool here - while it will be re-set to true by the // We must set fInMempool here - while it will be re-set to true by the
// entered-mempool callback, if we did not there would be a race where a // entered-mempool callback, if we did not there would be a race where a
// user could call sendmoney in a loop and hit spurious out of funds errors // user could call sendmoney in a loop and hit spurious out of funds errors

8
test/functional/mempool_persist.py

@ -57,21 +57,27 @@ class MempoolPersistTest(BitcoinTestFramework):
self.log.debug("Send 5 transactions from node2 (to its own address)") self.log.debug("Send 5 transactions from node2 (to its own address)")
for i in range(5): for i in range(5):
self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10"))
node2_balance = self.nodes[2].getbalance()
self.sync_all() self.sync_all()
self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools") self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools")
assert_equal(len(self.nodes[0].getrawmempool()), 5) assert_equal(len(self.nodes[0].getrawmempool()), 5)
assert_equal(len(self.nodes[1].getrawmempool()), 5) assert_equal(len(self.nodes[1].getrawmempool()), 5)
self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
self.stop_nodes() self.stop_nodes()
self.start_node(0) self.start_node(0)
self.start_node(1) self.start_node(1)
self.start_node(2)
# Give bitcoind a second to reload the mempool # Give bitcoind a second to reload the mempool
time.sleep(1) time.sleep(1)
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5)
assert_equal(len(self.nodes[1].getrawmempool()), 0) assert_equal(len(self.nodes[1].getrawmempool()), 0)
# Verify accounting of mempool transactions after restart is correct
assert_equal(node2_balance, self.nodes[2].getbalance())
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
self.stop_nodes() self.stop_nodes()
self.start_node(0, extra_args=["-persistmempool=0"]) self.start_node(0, extra_args=["-persistmempool=0"])

Loading…
Cancel
Save