Skip to content

Commit c1c8442

Browse files
committed
pytest: add test for bcli concurrent load with getblockfrompeer retry
1 parent 17138ac commit c1c8442

1 file changed

Lines changed: 63 additions & 0 deletions

File tree

tests/test_plugin.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from bitcoin.rpc import RawProxy
12
from collections import OrderedDict
23
from datetime import datetime
34
from fixtures import * # noqa: F401,F403
@@ -1991,6 +1992,68 @@ def test_bcli(node_factory, bitcoind, chainparams):
19911992
assert not resp["success"] and "decode failed" in resp["errmsg"]
19921993

19931994

1995+
def test_bcli_concurrent(node_factory, bitcoind, executor):
1996+
"""Test bcli under a concurrent load with a retry path."""
1997+
retry_count = 5
1998+
getblockfrompeer_count = 0
1999+
2000+
def mock_getblock(r):
2001+
nonlocal getblockfrompeer_count
2002+
nonlocal retry_count
2003+
2004+
if getblockfrompeer_count >= retry_count:
2005+
conf_file = os.path.join(bitcoind.bitcoin_dir, "bitcoin.conf")
2006+
brpc = RawProxy(btc_conf_file=conf_file)
2007+
return {
2008+
"result": brpc._call(r["method"], *r["params"]),
2009+
"error": None,
2010+
"id": r["id"]
2011+
}
2012+
return {
2013+
"id": r["id"],
2014+
"result": None,
2015+
"error": {"code": -1, "message": "Block not available (pruned data)"}
2016+
}
2017+
2018+
def mock_getpeerinfo(r):
2019+
return {"id": r["id"], "result": [{"id": 1, "services": "000000000000040d"}]}
2020+
2021+
def mock_getblockfrompeer(r):
2022+
nonlocal getblockfrompeer_count
2023+
getblockfrompeer_count += 1
2024+
return {"id": r["id"], "result": {}}
2025+
2026+
l1 = node_factory.get_node(start=False)
2027+
l1.daemon.rpcproxy.mock_rpc("getblock", mock_getblock)
2028+
l1.daemon.rpcproxy.mock_rpc("getpeerinfo", mock_getpeerinfo)
2029+
l1.daemon.rpcproxy.mock_rpc("getblockfrompeer", mock_getblockfrompeer)
2030+
l1.start(wait_for_bitcoind_sync=False)
2031+
2032+
# Submit concurrent bcli requests, `getrawblockbyheight` hits a retry path
2033+
block_future = executor.submit(l1.rpc.call, "getrawblockbyheight", {"height": 1})
2034+
chaininfo_futures = []
2035+
fees_futures = []
2036+
for _ in range(5):
2037+
chaininfo_futures.append(executor.submit(l1.rpc.call, "getchaininfo", {"last_height": 0}))
2038+
fees_futures.append(executor.submit(l1.rpc.call, "estimatefees"))
2039+
2040+
block_result = block_future.result(TIMEOUT)
2041+
assert "blockhash" in block_result
2042+
assert "block" in block_result
2043+
2044+
for fut in chaininfo_futures:
2045+
result = fut.result(TIMEOUT)
2046+
assert "chain" in result
2047+
assert "blockcount" in result
2048+
2049+
for fut in fees_futures:
2050+
result = fut.result(TIMEOUT)
2051+
assert "feerates" in result
2052+
assert "feerate_floor" in result
2053+
2054+
assert getblockfrompeer_count == retry_count, "getblockfrompeer should have been called"
2055+
2056+
19942057
@unittest.skipIf(TEST_NETWORK != 'regtest', 'p2tr addresses not supported by elementsd')
19952058
def test_hook_crash(node_factory, executor, bitcoind):
19962059
"""Verify that we fail over if a plugin crashes while handling a hook.

0 commit comments

Comments
 (0)