mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
pytest: test Bitcoin plugin registration and the bcli plugin
This commit is contained in:
@@ -80,6 +80,9 @@ void bitcoind_check_commands(struct bitcoind *bitcoind)
|
|||||||
for (i = 0; i < ARRAY_SIZE(methods); i++) {
|
for (i = 0; i < ARRAY_SIZE(methods); i++) {
|
||||||
p = find_plugin_for_command(bitcoind->ld, methods[i]);
|
p = find_plugin_for_command(bitcoind->ld, methods[i]);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
/* For testing .. */
|
||||||
|
log_debug(bitcoind->ld->log, "Missing a Bitcoin plugin"
|
||||||
|
" command");
|
||||||
fatal("Could not access the plugin for %s, is a "
|
fatal("Could not access the plugin for %s, is a "
|
||||||
"Bitcoin plugin (by default plugins/bcli) "
|
"Bitcoin plugin (by default plugins/bcli) "
|
||||||
"registered ?", methods[i]);
|
"registered ?", methods[i]);
|
||||||
|
|||||||
@@ -1001,6 +1001,9 @@ void setup_topology(struct chain_topology *topo,
|
|||||||
/* This waits for bitcoind. */
|
/* This waits for bitcoind. */
|
||||||
bitcoind_check_commands(topo->bitcoind);
|
bitcoind_check_commands(topo->bitcoind);
|
||||||
|
|
||||||
|
/* For testing.. */
|
||||||
|
log_debug(topo->ld->log, "All Bitcoin plugin commands registered");
|
||||||
|
|
||||||
/* Sanity checks, then topology initialization. */
|
/* Sanity checks, then topology initialization. */
|
||||||
bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo);
|
bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo);
|
||||||
|
|
||||||
|
|||||||
37
tests/plugins/bitcoin/part1.py
Executable file
37
tests/plugins/bitcoin/part1.py
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
This registers part of the Bitcoin backend methods.
|
||||||
|
We only use it for testing startup and we don't care about the actual values.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
|
||||||
|
from pyln.client import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
plugin = Plugin()
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.method("getfeerate")
|
||||||
|
def getfeerate(plugin, **kwargs):
|
||||||
|
time.sleep(1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.method("getrawblockbyheight")
|
||||||
|
def getblock(plugin, **kwargs):
|
||||||
|
time.sleep(1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.method("getchaininfo")
|
||||||
|
def getchaininfo(plugin, **kwargs):
|
||||||
|
time.sleep(1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
# We don't use these options, but it allows us to get to the expected failure.
|
||||||
|
plugin.add_option("bitcoin-rpcuser", "", "")
|
||||||
|
plugin.add_option("bitcoin-rpcpassword", "", "")
|
||||||
|
plugin.add_option("bitcoin-rpcport", "", "")
|
||||||
|
|
||||||
|
plugin.run()
|
||||||
26
tests/plugins/bitcoin/part2.py
Executable file
26
tests/plugins/bitcoin/part2.py
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
This registers part of the Bitcoin backend methods.
|
||||||
|
We only use it for testing startup and we don't care about the actual values.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
|
||||||
|
from pyln.client import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
plugin = Plugin()
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.method("sendrawtransaction")
|
||||||
|
def sendtx(plugin, **kwargs):
|
||||||
|
time.sleep(1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.method("getutxout")
|
||||||
|
def gettxout(plugin, **kwargs):
|
||||||
|
time.sleep(1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
plugin.run()
|
||||||
@@ -931,3 +931,84 @@ def test_hook_chaining(node_factory):
|
|||||||
assert(l2.daemon.is_in_log(
|
assert(l2.daemon.is_in_log(
|
||||||
r'plugin-hook-chain-even.py: htlc_accepted called for payment_hash {}'.format(hash3)
|
r'plugin-hook-chain-even.py: htlc_accepted called for payment_hash {}'.format(hash3)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def test_bitcoin_backend(node_factory, bitcoind):
|
||||||
|
"""
|
||||||
|
This tests interaction with the Bitcoin backend, but not specifically bcli
|
||||||
|
"""
|
||||||
|
l1 = node_factory.get_node(start=False, options={"disable-plugin": "bcli"},
|
||||||
|
may_fail=True, allow_broken_log=True)
|
||||||
|
|
||||||
|
# We don't start if we haven't all the required methods registered.
|
||||||
|
plugin = os.path.join(os.getcwd(), "tests/plugins/bitcoin/part1.py")
|
||||||
|
l1.daemon.opts["plugin"] = plugin
|
||||||
|
try:
|
||||||
|
l1.daemon.start()
|
||||||
|
except ValueError:
|
||||||
|
assert l1.daemon.is_in_log("Missing a Bitcoin plugin command")
|
||||||
|
# Now we should start if all the commands are registered, even if they
|
||||||
|
# are registered by two distincts plugins.
|
||||||
|
del l1.daemon.opts["plugin"]
|
||||||
|
l1.daemon.opts["plugin-dir"] = os.path.join(os.getcwd(),
|
||||||
|
"tests/plugins/bitcoin/")
|
||||||
|
try:
|
||||||
|
l1.daemon.start()
|
||||||
|
except ValueError:
|
||||||
|
msg = "All Bitcoin plugin commands registered"
|
||||||
|
assert l1.daemon.is_in_log(msg)
|
||||||
|
else:
|
||||||
|
raise Exception("We registered all commands but couldn't start!")
|
||||||
|
else:
|
||||||
|
raise Exception("We could start without all commands registered !!")
|
||||||
|
|
||||||
|
# But restarting with just bcli is ok
|
||||||
|
del l1.daemon.opts["plugin-dir"]
|
||||||
|
del l1.daemon.opts["disable-plugin"]
|
||||||
|
l1.start()
|
||||||
|
assert l1.daemon.is_in_log("bitcoin-cli initialized and connected to"
|
||||||
|
" bitcoind")
|
||||||
|
|
||||||
|
|
||||||
|
def test_bcli(node_factory, bitcoind, chainparams):
|
||||||
|
"""
|
||||||
|
This tests the bcli plugin, used to gather Bitcoin data from a local
|
||||||
|
bitcoind.
|
||||||
|
Mostly sanity checks of the interface..
|
||||||
|
"""
|
||||||
|
l1, l2 = node_factory.get_nodes(2)
|
||||||
|
|
||||||
|
# We cant stop it dynamically
|
||||||
|
with pytest.raises(RpcError):
|
||||||
|
l1.rpc.plugin_stop("bcli")
|
||||||
|
|
||||||
|
# Failure case of feerate is tested in test_misc.py
|
||||||
|
assert "feerate" in l1.rpc.call("getfeerate", {"blocks": 3,
|
||||||
|
"mode": "CONSERVATIVE"})
|
||||||
|
|
||||||
|
resp = l1.rpc.call("getchaininfo")
|
||||||
|
assert resp["chain"] == chainparams['name']
|
||||||
|
for field in ["headercount", "blockcount", "ibd"]:
|
||||||
|
assert field in resp
|
||||||
|
|
||||||
|
# We shouldn't get upset if we ask for an unknown-yet block
|
||||||
|
resp = l1.rpc.call("getrawblockbyheight", {"height": 500})
|
||||||
|
assert resp["blockhash"] is resp["block"] is None
|
||||||
|
resp = l1.rpc.call("getrawblockbyheight", {"height": 50})
|
||||||
|
assert resp["blockhash"] is not None and resp["blockhash"] is not None
|
||||||
|
# Some other bitcoind-failure cases for this call are covered in
|
||||||
|
# tests/test_misc.py
|
||||||
|
|
||||||
|
l1.fundwallet(10**5)
|
||||||
|
l1.connect(l2)
|
||||||
|
txid = l1.rpc.fundchannel(l2.info["id"], 10**4)["txid"]
|
||||||
|
txo = l1.rpc.call("getutxout", {"txid": txid, "vout": 0})
|
||||||
|
assert (Millisatoshi(txo["amount"]) == Millisatoshi(10**4 * 10**3)
|
||||||
|
and txo["script"].startswith("0020"))
|
||||||
|
l1.rpc.close(l2.info["id"])
|
||||||
|
# When output is spent, it should give us null !
|
||||||
|
txo = l1.rpc.call("getutxout", {"txid": txid, "vout": 0})
|
||||||
|
assert txo["amount"] is txo["script"] is None
|
||||||
|
|
||||||
|
resp = l1.rpc.call("sendrawtransaction", {"tx": "dummy"})
|
||||||
|
assert not resp["success"] and "decode failed" in resp["errmsg"]
|
||||||
|
|||||||
Reference in New Issue
Block a user