Skip to content

Commit

Permalink
rpc: Expose g_is_mempool_loaded via getmempoolinfo and /rest/mempool/…
Browse files Browse the repository at this point in the history
…info.json

And use it to fix a race condition in mempool_persist.py:
https://travis-ci.org/Empact/bitcoin/jobs/487577243

Since e.g. getrawmempool returns errors based on this status, this
enables users to test it for readiness.
  • Loading branch information
Empact committed Mar 22, 2019
1 parent 3515612 commit bb8ae2c
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 8 deletions.
1 change: 1 addition & 0 deletions doc/REST-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76

Returns various information about the TX mempool.
Only supports JSON as output format.
* loaded : (boolean) if the mempool is fully loaded
* size : (numeric) the number of transactions in the TX mempool
* bytes : (numeric) size of the TX mempool in bytes
* usage : (numeric) total TX mempool memory usage
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
UniValue MempoolInfoToJSON(const CTxMemPool& pool)
{
UniValue ret(UniValue::VOBJ);
ret.pushKV("loaded", g_is_mempool_loaded);
ret.pushKV("size", (int64_t)pool.size());
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
Expand All @@ -1504,6 +1505,7 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
{},
RPCResult{
"{\n"
" \"loaded\": true|false (boolean) True if the mempool is fully loaded\n"
" \"size\": xxxxx, (numeric) Current tx count\n"
" \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n"
" \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n"
Expand Down
17 changes: 9 additions & 8 deletions test/functional/mempool_persist.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"""
from decimal import Decimal
import os
import time

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, wait_until
Expand Down Expand Up @@ -83,9 +82,10 @@ def run_test(self):
self.start_node(1, extra_args=["-persistmempool=0"])
self.start_node(0)
self.start_node(2)
# Give bitcoind a second to reload the mempool
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1)
wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1)
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"], timeout=1)
wait_until(lambda: self.nodes[2].getmempoolinfo()["loaded"], timeout=1)
assert_equal(len(self.nodes[0].getrawmempool()), 5)
assert_equal(len(self.nodes[2].getrawmempool()), 5)
# The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
assert_equal(len(self.nodes[1].getrawmempool()), 0)

Expand All @@ -100,14 +100,14 @@ def run_test(self):
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
self.stop_nodes()
self.start_node(0, extra_args=["-persistmempool=0"])
# Give bitcoind a second to reload the mempool
time.sleep(1)
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"])
assert_equal(len(self.nodes[0].getrawmempool()), 0)

self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.")
self.stop_nodes()
self.start_node(0)
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"])
assert_equal(len(self.nodes[0].getrawmempool()), 5)

mempooldat0 = os.path.join(self.nodes[0].datadir, 'regtest', 'mempool.dat')
mempooldat1 = os.path.join(self.nodes[1].datadir, 'regtest', 'mempool.dat')
Expand All @@ -120,7 +120,8 @@ def run_test(self):
os.rename(mempooldat0, mempooldat1)
self.stop_nodes()
self.start_node(1, extra_args=[])
wait_until(lambda: len(self.nodes[1].getrawmempool()) == 5)
wait_until(lambda: self.nodes[1].getmempoolinfo()["loaded"])
assert_equal(len(self.nodes[1].getrawmempool()), 5)

self.log.debug("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails")
# to test the exception we are creating a tmp folder called mempool.dat.new
Expand Down

0 comments on commit bb8ae2c

Please sign in to comment.