From 18f6e23c3a34ef0feac709fd251114e3a0ef5300 Mon Sep 17 00:00:00 2001 From: sip21 Date: Sat, 28 Sep 2024 02:13:27 -0600 Subject: [PATCH 01/22] Add sauron tests --- .ci/test.py | 3 +- poncho | 2 +- sauron/sauron.py | 11 +- sauron/tests/test_sauron_esplora.py | 152 +++++++++++++++++ sauron/tests/test_sauron_esplora_tor_proxy.py | 45 ++++++ sauron/tests/test_sauron_mempoolspace.py | 153 ++++++++++++++++++ sauron/tests/util.py | 34 ++++ 7 files changed, 393 insertions(+), 7 deletions(-) create mode 100644 sauron/tests/test_sauron_esplora.py create mode 100644 sauron/tests/test_sauron_esplora_tor_proxy.py create mode 100644 sauron/tests/test_sauron_mempoolspace.py create mode 100644 sauron/tests/util.py diff --git a/.ci/test.py b/.ci/test.py index a4f5ee742..7239d4594 100644 --- a/.ci/test.py +++ b/.ci/test.py @@ -241,13 +241,14 @@ def run_one(p: Plugin, workflow: str) -> bool: logging.info(f"Virtualenv at {vpath}") + num_workers = 1 if p.name == "sauron" else 5 cmd = [ str(pytest_path), "-vvv", "--timeout=600", "--timeout-method=thread", "--color=yes", - "-n=5", + f"-n={num_workers}", ] logging.info(f"Running `{' '.join(cmd)}` in directory {p.path.resolve()}") diff --git a/poncho b/poncho index e7795d763..a94da96ff 160000 --- a/poncho +++ b/poncho @@ -1 +1 @@ -Subproject commit e7795d763168d81435e7430105a7ef4c6985c45a +Subproject commit a94da96ff257cd10edda74ac897fc15a4344a08e diff --git a/sauron/sauron.py b/sauron/sauron.py index 0ac6b9375..4165ef100 100755 --- a/sauron/sauron.py +++ b/sauron/sauron.py @@ -51,9 +51,9 @@ def init(plugin, options, **kwargs): # Esplora API feerate_url = "{}/fee-estimates".format(plugin.api_endpoint) feerate_req = fetch(feerate_url) - assert feerate_req.status_code == 200 + assert feerate_req.status_code == 200 and feerate_req.content != b'{}' plugin.is_mempoolspace = False - except AssertionError as e0: + except AssertionError: try: # MutinyNet API feerate_url = "{}/v1/fees/recommended".format(plugin.api_endpoint) @@ -72,7 +72,8 @@ def init(plugin, options, **kwargs): } plugin.log("Using proxy {} for requests".format(socks5_proxy)) - plugin.log("Sauron plugin initialized") + api = "mempool.space" if plugin.is_mempoolspace else "Esplora" + plugin.log(f"Sauron plugin initialized using {api} API") plugin.log(sauron_eye) @@ -215,7 +216,7 @@ def estimatefees(plugin, **kwargs): feerate_req = fetch(feerate_url) assert feerate_req.status_code == 200 feerates = feerate_req.json() - if plugin.sauron_network == "test" or plugin.sauron_network == "signet": + if plugin.sauron_network in ["test", "signet"]: # FIXME: remove the hack if the test API is "fixed" feerate = feerates.get("144", 1) slow = normal = urgent = very_urgent = int(feerate * 10**3) @@ -259,7 +260,7 @@ def estimatefees(plugin, **kwargs): "", "Tor's SocksPort address in the form address:port, don't specify the" " protocol. If you didn't modify your torrc you want to put" - "'localhost:9050' here.", + " 'localhost:9050' here.", ) diff --git a/sauron/tests/test_sauron_esplora.py b/sauron/tests/test_sauron_esplora.py new file mode 100644 index 000000000..233f00965 --- /dev/null +++ b/sauron/tests/test_sauron_esplora.py @@ -0,0 +1,152 @@ +#!/usr/bin/python + +import os + +os.environ["TEST_NETWORK"] = "bitcoin" +import pyln +import pytest +from pyln.testing import utils +from util import * # noqa: F403 + +pyln.testing.fixtures.network_daemons["bitcoin"] = utils.BitcoinD + + +class LightningNode(utils.LightningNode): + def __init__(self, *args, **kwargs): + utils.LightningNode.__init__(self, *args, **kwargs) + lightning_dir = args[1] + + self.daemon = LightningD(lightning_dir, None) # noqa: F405 + options = { + "disable-plugin": "bcli", + "network": "bitcoin", + "plugin": os.path.join(os.path.dirname(__file__), "../sauron.py"), + "sauron-api-endpoint": "https://blockstream.info/api", + } + self.daemon.opts.update(options) + + # Monkey patch + def set_feerates(self, feerates, wait_for_effect=True): + return None + + +@pytest.fixture +def node_cls(): + yield LightningNode + + +def test_rpc_getchaininfo(ln_node): + """ + Test getchaininfo + """ + + response = ln_node.rpc.call("getchaininfo") + + assert ln_node.daemon.is_in_log("Sauron plugin initialized using Esplora API") + + expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] + assert list(response.keys()) == expected_response_keys + assert response["chain"] == "main" + assert not response["ibd"] + + +def test_rpc_getrawblockbyheight(ln_node): + """ + Test getrawblockbyheight + """ + + response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) + + expected_response = { + "block": "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000", + "blockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", + } + assert response == expected_response + + +def test_rpc_sendrawtransaction_invalid(ln_node): + """ + Test sendrawtransaction + """ + + expected_response = { + "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', + "success": False, + } + response = ln_node.rpc.call( + "sendrawtransaction", + {"tx": "invalid-raw-tx"}, + ) + + assert response == expected_response + + +def test_rpc_getutxout(ln_node): + """ + Test getutxout + """ + + expected_response = { + "amount": 1000000000, + "script": "4104b5abd412d4341b45056d3e376cd446eca43fa871b51961330deebd84423e740daa520690e1d9e074654c59ff87b408db903649623e86f1ca5412786f61ade2bfac", + } + response = ln_node.rpc.call( + "getutxout", + { + # block 181 + "txid": "a16f3ce4dd5deb92d98ef5cf8afeaf0775ebca408f708b2146c4fb42b41e14be", + "vout": 0, + }, + ) + assert response == expected_response + + +def test_rpc_estimatefees(ln_node): + """ + Test estimatefees + """ + + # Sample response + # { + # "opening": 4477, + # "mutual_close": 4477, + # "unilateral_close": 11929, + # "delayed_to_us": 4477, + # "htlc_resolution": 5652, + # "penalty": 5652, + # "min_acceptable": 1060, + # "max_acceptable": 119290, + # "feerate_floor": 1520, + # "feerates": [ + # {"blocks": 2, "feerate": 11929}, + # {"blocks": 6, "feerate": 5652}, + # {"blocks": 12, "feerate": 4477}, + # {"blocks": 144, "feerate": 2120} + # ] + # } + response = ln_node.rpc.call("estimatefees") + + expected_response_keys = [ + "opening", + "mutual_close", + "unilateral_close", + "delayed_to_us", + "htlc_resolution", + "penalty", + "min_acceptable", + "max_acceptable", + "feerate_floor", + "feerates", + ] + assert list(response.keys()) == expected_response_keys + + expected_feerates_keys = ("blocks", "feerate") + assert ( + list(set([tuple(entry.keys()) for entry in response["feerates"]]))[0] + == expected_feerates_keys + ) + + expected_feerates_blocks = [2, 6, 12, 144] + assert [ + entry["blocks"] for entry in response["feerates"] + ] == expected_feerates_blocks diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py new file mode 100644 index 000000000..434335a9c --- /dev/null +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -0,0 +1,45 @@ +#!/usr/bin/python + +import os + +os.environ["TEST_NETWORK"] = "bitcoin" +import pyln +import pytest +from pyln.testing import utils +from util import * # noqa: F403 + +pyln.testing.fixtures.network_daemons["bitcoin"] = utils.BitcoinD + + +class LightningNode(utils.LightningNode): + def __init__(self, *args, **kwargs): + utils.LightningNode.__init__(self, *args, **kwargs) + lightning_dir = args[1] + + self.daemon = LightningD(lightning_dir, None) # noqa: F405 + options = { + "disable-plugin": "bcli", + "network": "bitcoin", + "plugin": os.path.join(os.path.dirname(__file__), "../sauron.py"), + "sauron-api-endpoint": "https://blockstream.info/api", + "sauron-tor-proxy": "localhost:9050", + } + self.daemon.opts.update(options) + + # Monkey patch + def set_feerates(self, feerates, wait_for_effect=True): + return None + + +@pytest.fixture +def node_cls(): + yield LightningNode + + +def test_tor_proxy(ln_node): + """ + Test for tor proxy + """ + + assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" + assert ln_node.daemon.is_in_log("Using proxy socks5h://localhost:9050 for requests") diff --git a/sauron/tests/test_sauron_mempoolspace.py b/sauron/tests/test_sauron_mempoolspace.py new file mode 100644 index 000000000..c07b970b4 --- /dev/null +++ b/sauron/tests/test_sauron_mempoolspace.py @@ -0,0 +1,153 @@ +#!/usr/bin/python + +import os + +os.environ["TEST_NETWORK"] = "signet" +import pyln +import pytest +from pyln.testing import utils +from util import * # noqa: F403 + +pyln.testing.fixtures.network_daemons["signet"] = utils.BitcoinD + + +class LightningNode(utils.LightningNode): + def __init__(self, *args, **kwargs): + utils.LightningNode.__init__(self, *args, **kwargs) + lightning_dir = args[1] + + self.daemon = LightningD(lightning_dir, None) # noqa: F405 + options = { + "disable-plugin": "bcli", + "network": "signet", + "plugin": os.path.join(os.path.dirname(__file__), "../sauron.py"), + "sauron-api-endpoint": "https://mutinynet.com/api", + } + self.daemon.opts.update(options) + + # Monkey patch + def set_feerates(self, feerates, wait_for_effect=True): + return None + + +@pytest.fixture +def node_cls(): + yield LightningNode + + +def test_rpc_getchaininfo(ln_node): + """ + Test getchaininfo + """ + + response = ln_node.rpc.call("getchaininfo") + + assert ln_node.daemon.is_in_log("Sauron plugin initialized using mempool.space API") + + expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] + assert list(response.keys()) == expected_response_keys + assert response["chain"] == "signet" + assert not response["ibd"] + + +def test_rpc_getrawblockbyheight(ln_node): + """ + Test getrawblockbyheight + """ + + response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) + + expected_response = { + "block": "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a008f4d5fae77031e8ad222030101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000", + "blockhash": "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6", + } + assert response == expected_response + + +def test_rpc_sendrawtransaction_invalid(ln_node): + """ + Test sendrawtransaction + """ + + expected_response = { + "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', + "success": False, + } + response = ln_node.rpc.call( + "sendrawtransaction", + {"tx": "invalid-raw-tx"}, + ) + + assert response == expected_response + + +def test_rpc_getutxout(ln_node): + """ + Test getutxout + """ + + expected_response = { + "amount": 5000000000, + "script": "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac", + } + response = ln_node.rpc.call( + "getutxout", + { + # coinbase tx block 0 + "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + "vout": 0, + }, + ) + assert response == expected_response + + +def test_rpc_estimatefees(ln_node): + """ + Test estimatefees + """ + + # Sample response + # { + # "opening": 1000, + # "mutual_close": 1000, + # "unilateral_close": 1000, + # "delayed_to_us": 1000, + # "htlc_resolution": 1000, + # "penalty": 1000, + # "min_acceptable": 500, + # "max_acceptable": 10000, + # "feerate_floor": 1000000, + # "feerates": [ + # {"blocks": 2, "feerate": 1000}, + # {"blocks": 6, "feerate": 1000}, + # {"blocks": 12, "feerate": 1000}, + # {"blocks": 144, "feerate": 1000} + # ] + # } + + response = ln_node.rpc.call("estimatefees") + + expected_response_keys = [ + "opening", + "mutual_close", + "unilateral_close", + "delayed_to_us", + "htlc_resolution", + "penalty", + "min_acceptable", + "max_acceptable", + "feerate_floor", + "feerates", + ] + assert list(response.keys()) == expected_response_keys + + expected_feerates_keys = ("blocks", "feerate") + assert ( + list(set([tuple(entry.keys()) for entry in response["feerates"]]))[0] + == expected_feerates_keys + ) + + expected_feerates_blocks = [2, 6, 12, 144] + assert [ + entry["blocks"] for entry in response["feerates"] + ] == expected_feerates_blocks diff --git a/sauron/tests/util.py b/sauron/tests/util.py new file mode 100644 index 000000000..c0e01d2d1 --- /dev/null +++ b/sauron/tests/util.py @@ -0,0 +1,34 @@ +import logging + +import pytest +from pyln.testing import utils +from pyln.testing.fixtures import * # noqa: F403 + + +class LightningD(utils.LightningD): + def __init__(self, lightning_dir, *args, **kwargs): + super().__init__(lightning_dir, *args, **kwargs) + + opts_to_disable = [ + "bitcoin-datadir", + "bitcoin-rpcpassword", + "bitcoin-rpcuser", + "dev-bitcoind-poll", + ] + for opt in opts_to_disable: + self.opts.pop(opt) + + # Monkey patch + def start(self, stdin=None, wait_for_initialized=True, stderr_redir=False): + utils.TailableProc.start( + self, stdin, stdout_redir=False, stderr_redir=stderr_redir + ) + + if wait_for_initialized: + self.wait_for_log("Server started with public key") + logging.info("LightningD started") + + +@pytest.fixture +def ln_node(node_factory): # noqa: F811 + yield node_factory.get_node() From f0729c68ce0a9b8a6c8ec1ca353d10716f337b3d Mon Sep 17 00:00:00 2001 From: sip21 Date: Wed, 9 Oct 2024 14:56:15 -0600 Subject: [PATCH 02/22] Use node factory --- sauron/tests/test_sauron_esplora.py | 15 ++++++++++----- sauron/tests/test_sauron_esplora_tor_proxy.py | 3 ++- sauron/tests/test_sauron_mempoolspace.py | 15 ++++++++++----- sauron/tests/util.py | 5 ----- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/sauron/tests/test_sauron_esplora.py b/sauron/tests/test_sauron_esplora.py index 952fb7feb..9e30c5801 100644 --- a/sauron/tests/test_sauron_esplora.py +++ b/sauron/tests/test_sauron_esplora.py @@ -36,10 +36,11 @@ def node_cls(monkeypatch): yield LightningNode -def test_rpc_getchaininfo(ln_node): +def test_rpc_getchaininfo(node_factory): """ Test getchaininfo """ + ln_node = node_factory.get_node() response = ln_node.rpc.call("getchaininfo") @@ -51,10 +52,11 @@ def test_rpc_getchaininfo(ln_node): assert not response["ibd"] -def test_rpc_getrawblockbyheight(ln_node): +def test_rpc_getrawblockbyheight(node_factory): """ Test getrawblockbyheight """ + ln_node = node_factory.get_node() response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) @@ -65,10 +67,11 @@ def test_rpc_getrawblockbyheight(ln_node): assert response == expected_response -def test_rpc_sendrawtransaction_invalid(ln_node): +def test_rpc_sendrawtransaction_invalid(node_factory): """ Test sendrawtransaction """ + ln_node = node_factory.get_node() expected_response = { "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', @@ -82,10 +85,11 @@ def test_rpc_sendrawtransaction_invalid(ln_node): assert response == expected_response -def test_rpc_getutxout(ln_node): +def test_rpc_getutxout(node_factory): """ Test getutxout """ + ln_node = node_factory.get_node() expected_response = { "amount": 1000000000, @@ -102,10 +106,11 @@ def test_rpc_getutxout(ln_node): assert response == expected_response -def test_rpc_estimatefees(ln_node): +def test_rpc_estimatefees(node_factory): """ Test estimatefees """ + ln_node = node_factory.get_node() # Sample response # { diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index 1ffd41d2d..b254923f5 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -37,10 +37,11 @@ def node_cls(monkeypatch): yield LightningNode @pytest.mark.skip(reason="TODO: Mock tor") -def test_tor_proxy(ln_node): +def test_tor_proxy(node_factory): """ Test for tor proxy """ + ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" assert ln_node.daemon.is_in_log("Using proxy socks5h://localhost:9050 for requests") diff --git a/sauron/tests/test_sauron_mempoolspace.py b/sauron/tests/test_sauron_mempoolspace.py index c3e93b287..91487d396 100644 --- a/sauron/tests/test_sauron_mempoolspace.py +++ b/sauron/tests/test_sauron_mempoolspace.py @@ -36,10 +36,11 @@ def node_cls(monkeypatch): yield LightningNode -def test_rpc_getchaininfo(ln_node): +def test_rpc_getchaininfo(node_factory): """ Test getchaininfo """ + ln_node = node_factory.get_node() response = ln_node.rpc.call("getchaininfo") @@ -51,10 +52,11 @@ def test_rpc_getchaininfo(ln_node): assert not response["ibd"] -def test_rpc_getrawblockbyheight(ln_node): +def test_rpc_getrawblockbyheight(node_factory): """ Test getrawblockbyheight """ + ln_node = node_factory.get_node() response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) @@ -65,10 +67,11 @@ def test_rpc_getrawblockbyheight(ln_node): assert response == expected_response -def test_rpc_sendrawtransaction_invalid(ln_node): +def test_rpc_sendrawtransaction_invalid(node_factory): """ Test sendrawtransaction """ + ln_node = node_factory.get_node() expected_response = { "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', @@ -82,10 +85,11 @@ def test_rpc_sendrawtransaction_invalid(ln_node): assert response == expected_response -def test_rpc_getutxout(ln_node): +def test_rpc_getutxout(node_factory): """ Test getutxout """ + ln_node = node_factory.get_node() expected_response = { "amount": 5000000000, @@ -102,10 +106,11 @@ def test_rpc_getutxout(ln_node): assert response == expected_response -def test_rpc_estimatefees(ln_node): +def test_rpc_estimatefees(node_factory): """ Test estimatefees """ + ln_node = node_factory.get_node() # Sample response # { diff --git a/sauron/tests/util.py b/sauron/tests/util.py index c0e01d2d1..e70f5bf46 100644 --- a/sauron/tests/util.py +++ b/sauron/tests/util.py @@ -27,8 +27,3 @@ def start(self, stdin=None, wait_for_initialized=True, stderr_redir=False): if wait_for_initialized: self.wait_for_log("Server started with public key") logging.info("LightningD started") - - -@pytest.fixture -def ln_node(node_factory): # noqa: F811 - yield node_factory.get_node() From 2ef269bc38833aaa0a508a48295aacc8389a77b3 Mon Sep 17 00:00:00 2001 From: sip21 Date: Wed, 9 Oct 2024 15:16:37 -0600 Subject: [PATCH 03/22] Refactor imports --- sauron/tests/test_sauron_esplora.py | 3 ++- sauron/tests/test_sauron_esplora_tor_proxy.py | 1 + sauron/tests/test_sauron_mempoolspace.py | 3 ++- sauron/tests/util.py | 2 -- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sauron/tests/test_sauron_esplora.py b/sauron/tests/test_sauron_esplora.py index 9e30c5801..88e474095 100644 --- a/sauron/tests/test_sauron_esplora.py +++ b/sauron/tests/test_sauron_esplora.py @@ -5,7 +5,8 @@ import pyln import pytest from pyln.testing import utils -from util import * # noqa: F403 +from pyln.testing.fixtures import * # noqa: F403 +from util import LightningD pyln.testing.fixtures.network_daemons["bitcoin"] = utils.BitcoinD diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index b254923f5..06989ec75 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -36,6 +36,7 @@ def node_cls(monkeypatch): monkeypatch.setenv("TEST_NETWORK", "bitcoin") yield LightningNode + @pytest.mark.skip(reason="TODO: Mock tor") def test_tor_proxy(node_factory): """ diff --git a/sauron/tests/test_sauron_mempoolspace.py b/sauron/tests/test_sauron_mempoolspace.py index 91487d396..5b0bcbe04 100644 --- a/sauron/tests/test_sauron_mempoolspace.py +++ b/sauron/tests/test_sauron_mempoolspace.py @@ -5,7 +5,8 @@ import pyln import pytest from pyln.testing import utils -from util import * # noqa: F403 +from pyln.testing.fixtures import * # noqa: F403 +from util import LightningD pyln.testing.fixtures.network_daemons["signet"] = utils.BitcoinD diff --git a/sauron/tests/util.py b/sauron/tests/util.py index e70f5bf46..f060aa844 100644 --- a/sauron/tests/util.py +++ b/sauron/tests/util.py @@ -1,8 +1,6 @@ import logging -import pytest from pyln.testing import utils -from pyln.testing.fixtures import * # noqa: F403 class LightningD(utils.LightningD): From 5bbb8c473b913a03b71ca8777fc0d0ed2c74c984 Mon Sep 17 00:00:00 2001 From: sip21 Date: Fri, 11 Oct 2024 21:53:19 -0600 Subject: [PATCH 04/22] Add setup.sh --- sauron/tests/setup.sh | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 sauron/tests/setup.sh diff --git a/sauron/tests/setup.sh b/sauron/tests/setup.sh new file mode 100644 index 000000000..62aad0679 --- /dev/null +++ b/sauron/tests/setup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +sudo apt update -y +sudo apt -y install tor \ No newline at end of file From 3f6928870f863da821764c4c239da5a6017faa1b Mon Sep 17 00:00:00 2001 From: sip21 Date: Fri, 11 Oct 2024 22:17:19 -0600 Subject: [PATCH 05/22] Unskip test --- sauron/tests/test_sauron_esplora_tor_proxy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index 06989ec75..7daa121da 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -37,7 +37,6 @@ def node_cls(monkeypatch): yield LightningNode -@pytest.mark.skip(reason="TODO: Mock tor") def test_tor_proxy(node_factory): """ Test for tor proxy From 8123b51655d0bb9c512c64d0e87502c1e49407bc Mon Sep 17 00:00:00 2001 From: sip21 Date: Fri, 11 Oct 2024 22:25:57 -0600 Subject: [PATCH 06/22] Fix imports --- sauron/tests/test_sauron_esplora_tor_proxy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index 7daa121da..c544c0f0e 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -5,7 +5,8 @@ import pyln import pytest from pyln.testing import utils -from util import * # noqa: F403 +from pyln.testing.fixtures import * # noqa: F403 +from util import LightningD pyln.testing.fixtures.network_daemons["bitcoin"] = utils.BitcoinD From 888800ff5637039d00c2be35771b31909c183814 Mon Sep 17 00:00:00 2001 From: sip21 Date: Fri, 11 Oct 2024 22:43:52 -0600 Subject: [PATCH 07/22] Test CI --- sauron/.github/workflows/ci.yml | 253 ++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 sauron/.github/workflows/ci.yml diff --git a/sauron/.github/workflows/ci.yml b/sauron/.github/workflows/ci.yml new file mode 100644 index 000000000..19c6ca70a --- /dev/null +++ b/sauron/.github/workflows/ci.yml @@ -0,0 +1,253 @@ +name: CI + +# Cancel duplicate jobs +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +on: + push: + branches: [ master ] + pull_request: + +jobs: + build-and-test: + name: Test CLN=${{ matrix.cln-version }}, PY=${{ matrix.python-version }}, BCD=${{ matrix.bitcoind-version }}, EXP=${{ matrix.experimental }}, DEP=${{ matrix.deprecated }} + runs-on: ubuntu-latest + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.11"] + bitcoind-version: ["27.1"] + cln-version: ["24.08.1", "24.05", "24.02.2"] + experimental: [1] + deprecated: [0] + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Get changed files + id: get_changed_files + if: ${{ github.event_name == 'pull_request' }} + uses: tj-actions/changed-files@v44 + with: + files: '**/*' + files_ignore: | + *.md + *.toml + *.yml + *.lock + Dockerfile + .gitignore + LICENSE + archived/** + + - name: Set plugin_dirs + id: set_plugin_dirs + if: ${{ github.event_name == 'pull_request' }} + run: | + changed_files=$(echo "${{ steps.get_changed_files.outputs.all_changed_files }}" | tr ',' '\n') + plugin_dirs="" + for file in $changed_files; do + dir=$(dirname "$file" | cut -d'/' -f1) + if [[ "$dir" != "." && "${dir:0:1}" != "." && ! " ${plugin_dirs[@]} " =~ " ${dir} " ]]; then + plugin_dirs="${plugin_dirs} ${dir}" + fi + done + echo "plugin_dirs=${plugin_dirs}" >> "$GITHUB_OUTPUT" + + if [[ -n "${{ steps.get_changed_files.outputs.all_changed_files }}" ]]; then + echo "run_ci=true" >> "$GITHUB_OUTPUT" + else + echo "run_ci=false" >> "$GITHUB_OUTPUT" + fi + + - name: Set up Python ${{ matrix.python-version }} + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Extract exact python and os version + id: exact_versions + run: | + PYTHON_VERSION=$(python --version 2>&1 | grep -oP '(?<=Python )\d+\.\d+(\.\d+)?') + echo "Python version: $PYTHON_VERSION" + echo "python_version=$PYTHON_VERSION" >> "$GITHUB_OUTPUT" + OS_VERSION=$(lsb_release -rs) + echo "OS version: $OS_VERSION" + echo "os_version=$OS_VERSION" >> $GITHUB_OUTPUT + + - name: Create cache paths + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + run: | + sudo mkdir /usr/local/libexec + sudo mkdir /usr/local/libexec/c-lightning + sudo mkdir /usr/local/libexec/c-lightning/plugins + sudo chown -R $USER /usr/local/libexec + + - name: Restore bitcoind cache + id: cache-bitcoind + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + uses: actions/cache@v4 + with: + path: /usr/local/bin/bitcoin* + key: cache-bitcoind-${{ matrix.bitcoind-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Download Bitcoin ${{ matrix.bitcoind-version }} & install binaries + if: ${{ steps.cache-bitcoind.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} + run: | + export BITCOIND_VERSION=${{ matrix.bitcoind-version }} + wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VERSION}/bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz + tar -xzf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz + sudo mv bitcoin-${BITCOIND_VERSION}/bin/* /usr/local/bin + rm -rf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz bitcoin-${BITCOIND_VERSION} + + - name: Save bitcoind cache + uses: actions/cache/save@v4 + if: ${{ steps.cache-bitcoind.outputs.cache-hit != 'true' && github.event_name == 'push' }} + with: + path: /usr/local/bin/bitcoin* + key: cache-bitcoind-${{ matrix.bitcoind-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Restore CLN cache + id: cache-cln + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + uses: actions/cache@v4 + with: + path: | + /usr/local/bin/lightning* + /usr/local/libexec/c-lightning + ./lightning + key: cache-cln-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Download Core Lightning ${{ matrix.cln-version }} & install binaries + if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} + id: cln-install + run: | + url=$(curl -s https://api.github.com/repos/ElementsProject/lightning/releases/tags/v${{ matrix.cln-version }} \ + | jq '.assets[] | select(.name | contains("22.04")) | .browser_download_url' \ + | tr -d '\"') + wget $url + sudo tar -xvf ${url##*/} -C /usr/local --strip-components=2 + + - name: Checkout Core Lightning ${{ matrix.cln-version }} + if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} + uses: actions/checkout@v4 + with: + repository: 'ElementsProject/lightning' + path: 'lightning' + ref: 'v${{ matrix.cln-version }}' + fetch-depth: 0 # Fetch all history for all branches and tags + submodules: 'recursive' + + - name: Save CLN cache + uses: actions/cache/save@v4 + if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && github.event_name == 'push' }} + with: + path: | + /usr/local/bin/lightning* + /usr/local/libexec/c-lightning + ./lightning + key: cache-cln-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Restore python dependencies cache + id: cache-python-deps + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + uses: actions/cache@v4 + with: + path: ~/.local/lib/python${{ matrix.python-version }}/site-packages + key: cache-python-deps-${{ steps.exact_versions.outputs.python_version }}-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Install Core Lightning Python package dependencies + if: ${{ steps.cache-python-deps.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} + run: | + cd lightning + pip3 install --user -U \ + pip \ + poetry \ + wheel \ + blinker \ + pytest-custom-exit-code==0.3.0 \ + pytest-json-report + + poetry install + poetry update + poetry export --without-hashes -f requirements.txt --output requirements.txt + pip install --user -U -r requirements.txt + pip install --user contrib/pyln-client contrib/pyln-testing flaky + + pip3 install --upgrade pip + pip3 install --user -U virtualenv pip > /dev/null + + sudo apt install tor + + - name: Save python dependencies cache + uses: actions/cache/save@v4 + if: ${{ steps.cache-python-deps.outputs.cache-hit != 'true' && github.event_name == 'push' }} + with: + path: ~/.local/lib/python${{ matrix.python-version }}/site-packages + key: cache-python-deps-${{ steps.exact_versions.outputs.python_version }}-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} + + - name: Run pytest tests + id: pytest_tests + if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} + run: | + export CLN_PATH=${{ github.workspace }}/lightning + export COMPAT=${{ matrix.deprecated }} + export EXPERIMENTAL_FEATURES=${{ matrix.experimental }} + export SLOW_MACHINE=1 + export TEST_DEBUG=1 + export TRAVIS=1 + export VALGRIND=0 + + if [[ "${{ github.event_name }}" == 'pull_request' ]]; then + plugin_dirs="${{ steps.set_plugin_dirs.outputs.plugin_dirs }}" + else + plugin_dirs="" + fi + + # Run the tests: In the case of a 'pull_request' event only the plugins in `plugin_dirs` + # are going to be tested; otherwise ('push' event) we test all plugins. + + update_badges='' + if [[ "${{ github.event_name }}" == 'push' && "${{ github.ref }}" == 'refs/heads/master' ]] || [[ "${{ github.event_name }}" == 'schedule' ]] + then + update_badges='--update-badges' + fi + + if [[ -z "$plugin_dirs" ]]; then + # Test all plugins if no specific plugins were changed + python3 .ci/test.py ${{ matrix.cln-version }} ${{ matrix.python-version }} $update_badges + else + python3 .ci/test.py ${{ matrix.cln-version }} ${{ matrix.python-version }} $update_badges $(echo "$plugin_dirs") + fi + + gather: + # A dummy task that depends on the full matrix of tests, and signals completion. + name: CI completion + runs-on: ubuntu-latest + if: ${{ always() && github.event_name == 'push' }} + needs: + - build-and-test + strategy: + fail-fast: false + matrix: + cln-version: ["24.08.1", "24.05", "24.02.2"] + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Complete + run: | + python_versions='3.8 3.11' + echo "Updating badges data for ${{ matrix.cln-version }} workflow..." + python3 .ci/update_badges.py ${{ matrix.cln-version }} $(echo "$python_versions") + echo "CI completed." From 3a705f8d8e4c0b7089e179e333246e99e7390f60 Mon Sep 17 00:00:00 2001 From: sip21 Date: Fri, 11 Oct 2024 22:46:43 -0600 Subject: [PATCH 08/22] Test CI --- sauron/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sauron/.github/workflows/ci.yml b/sauron/.github/workflows/ci.yml index 19c6ca70a..8cb5dadb6 100644 --- a/sauron/.github/workflows/ci.yml +++ b/sauron/.github/workflows/ci.yml @@ -89,6 +89,8 @@ jobs: sudo mkdir /usr/local/libexec/c-lightning/plugins sudo chown -R $USER /usr/local/libexec + sudo apt install tor + - name: Restore bitcoind cache id: cache-bitcoind if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} @@ -183,8 +185,6 @@ jobs: pip3 install --upgrade pip pip3 install --user -U virtualenv pip > /dev/null - sudo apt install tor - - name: Save python dependencies cache uses: actions/cache/save@v4 if: ${{ steps.cache-python-deps.outputs.cache-hit != 'true' && github.event_name == 'push' }} From a7989ddc3f5ddc375d10af05da98ece5fb445ae7 Mon Sep 17 00:00:00 2001 From: sip21 Date: Sat, 12 Oct 2024 00:20:26 -0600 Subject: [PATCH 09/22] Test CI --- sauron/tests/test_sauron_esplora_tor_proxy.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index c544c0f0e..194704546 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -42,6 +42,11 @@ def test_tor_proxy(node_factory): """ Test for tor proxy """ + import subprocess + from subprocess import STDOUT + proc = subprocess.Popen('sudo apt install -y tor', shell=True, stdin=None, stdout=open(os.devnull,"wb"), stderr=STDOUT, executable="/bin/bash") + proc.wait() + ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" From 31d1f33e587e83b42191ba9b9f79a738a1aa4963 Mon Sep 17 00:00:00 2001 From: sip21 Date: Sat, 12 Oct 2024 00:37:04 -0600 Subject: [PATCH 10/22] Test CI --- sauron/tests/test_sauron_esplora_tor_proxy.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index 194704546..fd1866c68 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -43,11 +43,25 @@ def test_tor_proxy(node_factory): Test for tor proxy """ import subprocess - from subprocess import STDOUT - proc = subprocess.Popen('sudo apt install -y tor', shell=True, stdin=None, stdout=open(os.devnull,"wb"), stderr=STDOUT, executable="/bin/bash") + + proc = subprocess.Popen( + "sudo apt install -y tor", + shell=True, + stdin=None, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + executable="/bin/bash", + ) proc.wait() ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" assert ln_node.daemon.is_in_log("Using proxy socks5h://localhost:9050 for requests") + + response = ln_node.rpc.call("getchaininfo") + + expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] + assert list(response.keys()) == expected_response_keys + assert response["chain"] == "main" + assert not response["ibd"] \ No newline at end of file From c60ef636da19e54a8ded5ed3a08ad112218b6707 Mon Sep 17 00:00:00 2001 From: sip21 Date: Sun, 13 Oct 2024 00:38:21 -0600 Subject: [PATCH 11/22] Use subprocess.call and sleep --- sauron/tests/test_sauron_esplora_tor_proxy.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index fd1866c68..fdc6f9cba 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -43,16 +43,12 @@ def test_tor_proxy(node_factory): Test for tor proxy """ import subprocess + import time - proc = subprocess.Popen( - "sudo apt install -y tor", - shell=True, - stdin=None, - stdout=open(os.devnull, "wb"), - stderr=subprocess.STDOUT, - executable="/bin/bash", + subprocess.call( + ["sudo", "apt", "install", "tor"] ) - proc.wait() + time.sleep(10) ln_node = node_factory.get_node() From 11b3880edd2811d2881bd76629fe47885f7e3834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sip=C2=B2=C2=B9?= <157324775+sip-21@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:18:18 -0600 Subject: [PATCH 12/22] Update main.yml --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99eecfa92..2c2ce4eb7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,6 +89,8 @@ jobs: sudo mkdir /usr/local/libexec/c-lightning/plugins sudo chown -R $USER /usr/local/libexec + sudo apt install tor + - name: Restore bitcoind cache id: cache-bitcoind if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} From f696681889c5cf8ab6776843b39d0dc065fbf4d6 Mon Sep 17 00:00:00 2001 From: sip21 Date: Sun, 13 Oct 2024 14:20:48 -0600 Subject: [PATCH 13/22] Test CI --- sauron/tests/test_sauron_esplora_tor_proxy.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index fdc6f9cba..a8eb007b7 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -42,14 +42,6 @@ def test_tor_proxy(node_factory): """ Test for tor proxy """ - import subprocess - import time - - subprocess.call( - ["sudo", "apt", "install", "tor"] - ) - time.sleep(10) - ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" From 578ac1273d5243ed51813e04783d4d1dcb82aaec Mon Sep 17 00:00:00 2001 From: sip21 Date: Sun, 13 Oct 2024 14:30:19 -0600 Subject: [PATCH 14/22] Test CI --- sauron/.github/workflows/ci.yml | 253 -------------------------------- sauron/tests/setup.sh | 4 +- 2 files changed, 2 insertions(+), 255 deletions(-) delete mode 100644 sauron/.github/workflows/ci.yml diff --git a/sauron/.github/workflows/ci.yml b/sauron/.github/workflows/ci.yml deleted file mode 100644 index 8cb5dadb6..000000000 --- a/sauron/.github/workflows/ci.yml +++ /dev/null @@ -1,253 +0,0 @@ -name: CI - -# Cancel duplicate jobs -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -on: - push: - branches: [ master ] - pull_request: - -jobs: - build-and-test: - name: Test CLN=${{ matrix.cln-version }}, PY=${{ matrix.python-version }}, BCD=${{ matrix.bitcoind-version }}, EXP=${{ matrix.experimental }}, DEP=${{ matrix.deprecated }} - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - python-version: ["3.8", "3.11"] - bitcoind-version: ["27.1"] - cln-version: ["24.08.1", "24.05", "24.02.2"] - experimental: [1] - deprecated: [0] - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Get changed files - id: get_changed_files - if: ${{ github.event_name == 'pull_request' }} - uses: tj-actions/changed-files@v44 - with: - files: '**/*' - files_ignore: | - *.md - *.toml - *.yml - *.lock - Dockerfile - .gitignore - LICENSE - archived/** - - - name: Set plugin_dirs - id: set_plugin_dirs - if: ${{ github.event_name == 'pull_request' }} - run: | - changed_files=$(echo "${{ steps.get_changed_files.outputs.all_changed_files }}" | tr ',' '\n') - plugin_dirs="" - for file in $changed_files; do - dir=$(dirname "$file" | cut -d'/' -f1) - if [[ "$dir" != "." && "${dir:0:1}" != "." && ! " ${plugin_dirs[@]} " =~ " ${dir} " ]]; then - plugin_dirs="${plugin_dirs} ${dir}" - fi - done - echo "plugin_dirs=${plugin_dirs}" >> "$GITHUB_OUTPUT" - - if [[ -n "${{ steps.get_changed_files.outputs.all_changed_files }}" ]]; then - echo "run_ci=true" >> "$GITHUB_OUTPUT" - else - echo "run_ci=false" >> "$GITHUB_OUTPUT" - fi - - - name: Set up Python ${{ matrix.python-version }} - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Extract exact python and os version - id: exact_versions - run: | - PYTHON_VERSION=$(python --version 2>&1 | grep -oP '(?<=Python )\d+\.\d+(\.\d+)?') - echo "Python version: $PYTHON_VERSION" - echo "python_version=$PYTHON_VERSION" >> "$GITHUB_OUTPUT" - OS_VERSION=$(lsb_release -rs) - echo "OS version: $OS_VERSION" - echo "os_version=$OS_VERSION" >> $GITHUB_OUTPUT - - - name: Create cache paths - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - run: | - sudo mkdir /usr/local/libexec - sudo mkdir /usr/local/libexec/c-lightning - sudo mkdir /usr/local/libexec/c-lightning/plugins - sudo chown -R $USER /usr/local/libexec - - sudo apt install tor - - - name: Restore bitcoind cache - id: cache-bitcoind - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - uses: actions/cache@v4 - with: - path: /usr/local/bin/bitcoin* - key: cache-bitcoind-${{ matrix.bitcoind-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Download Bitcoin ${{ matrix.bitcoind-version }} & install binaries - if: ${{ steps.cache-bitcoind.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} - run: | - export BITCOIND_VERSION=${{ matrix.bitcoind-version }} - wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VERSION}/bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz - tar -xzf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz - sudo mv bitcoin-${BITCOIND_VERSION}/bin/* /usr/local/bin - rm -rf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz bitcoin-${BITCOIND_VERSION} - - - name: Save bitcoind cache - uses: actions/cache/save@v4 - if: ${{ steps.cache-bitcoind.outputs.cache-hit != 'true' && github.event_name == 'push' }} - with: - path: /usr/local/bin/bitcoin* - key: cache-bitcoind-${{ matrix.bitcoind-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Restore CLN cache - id: cache-cln - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - uses: actions/cache@v4 - with: - path: | - /usr/local/bin/lightning* - /usr/local/libexec/c-lightning - ./lightning - key: cache-cln-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Download Core Lightning ${{ matrix.cln-version }} & install binaries - if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} - id: cln-install - run: | - url=$(curl -s https://api.github.com/repos/ElementsProject/lightning/releases/tags/v${{ matrix.cln-version }} \ - | jq '.assets[] | select(.name | contains("22.04")) | .browser_download_url' \ - | tr -d '\"') - wget $url - sudo tar -xvf ${url##*/} -C /usr/local --strip-components=2 - - - name: Checkout Core Lightning ${{ matrix.cln-version }} - if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} - uses: actions/checkout@v4 - with: - repository: 'ElementsProject/lightning' - path: 'lightning' - ref: 'v${{ matrix.cln-version }}' - fetch-depth: 0 # Fetch all history for all branches and tags - submodules: 'recursive' - - - name: Save CLN cache - uses: actions/cache/save@v4 - if: ${{ steps.cache-cln.outputs.cache-hit != 'true' && github.event_name == 'push' }} - with: - path: | - /usr/local/bin/lightning* - /usr/local/libexec/c-lightning - ./lightning - key: cache-cln-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Restore python dependencies cache - id: cache-python-deps - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - uses: actions/cache@v4 - with: - path: ~/.local/lib/python${{ matrix.python-version }}/site-packages - key: cache-python-deps-${{ steps.exact_versions.outputs.python_version }}-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Install Core Lightning Python package dependencies - if: ${{ steps.cache-python-deps.outputs.cache-hit != 'true' && (github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true') }} - run: | - cd lightning - pip3 install --user -U \ - pip \ - poetry \ - wheel \ - blinker \ - pytest-custom-exit-code==0.3.0 \ - pytest-json-report - - poetry install - poetry update - poetry export --without-hashes -f requirements.txt --output requirements.txt - pip install --user -U -r requirements.txt - pip install --user contrib/pyln-client contrib/pyln-testing flaky - - pip3 install --upgrade pip - pip3 install --user -U virtualenv pip > /dev/null - - - name: Save python dependencies cache - uses: actions/cache/save@v4 - if: ${{ steps.cache-python-deps.outputs.cache-hit != 'true' && github.event_name == 'push' }} - with: - path: ~/.local/lib/python${{ matrix.python-version }}/site-packages - key: cache-python-deps-${{ steps.exact_versions.outputs.python_version }}-${{ matrix.cln-version }}-${{ steps.exact_versions.outputs.os_version }} - - - name: Run pytest tests - id: pytest_tests - if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} - run: | - export CLN_PATH=${{ github.workspace }}/lightning - export COMPAT=${{ matrix.deprecated }} - export EXPERIMENTAL_FEATURES=${{ matrix.experimental }} - export SLOW_MACHINE=1 - export TEST_DEBUG=1 - export TRAVIS=1 - export VALGRIND=0 - - if [[ "${{ github.event_name }}" == 'pull_request' ]]; then - plugin_dirs="${{ steps.set_plugin_dirs.outputs.plugin_dirs }}" - else - plugin_dirs="" - fi - - # Run the tests: In the case of a 'pull_request' event only the plugins in `plugin_dirs` - # are going to be tested; otherwise ('push' event) we test all plugins. - - update_badges='' - if [[ "${{ github.event_name }}" == 'push' && "${{ github.ref }}" == 'refs/heads/master' ]] || [[ "${{ github.event_name }}" == 'schedule' ]] - then - update_badges='--update-badges' - fi - - if [[ -z "$plugin_dirs" ]]; then - # Test all plugins if no specific plugins were changed - python3 .ci/test.py ${{ matrix.cln-version }} ${{ matrix.python-version }} $update_badges - else - python3 .ci/test.py ${{ matrix.cln-version }} ${{ matrix.python-version }} $update_badges $(echo "$plugin_dirs") - fi - - gather: - # A dummy task that depends on the full matrix of tests, and signals completion. - name: CI completion - runs-on: ubuntu-latest - if: ${{ always() && github.event_name == 'push' }} - needs: - - build-and-test - strategy: - fail-fast: false - matrix: - cln-version: ["24.08.1", "24.05", "24.02.2"] - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Complete - run: | - python_versions='3.8 3.11' - echo "Updating badges data for ${{ matrix.cln-version }} workflow..." - python3 .ci/update_badges.py ${{ matrix.cln-version }} $(echo "$python_versions") - echo "CI completed." diff --git a/sauron/tests/setup.sh b/sauron/tests/setup.sh index 62aad0679..36866c854 100644 --- a/sauron/tests/setup.sh +++ b/sauron/tests/setup.sh @@ -1,4 +1,4 @@ #!/bin/bash -sudo apt update -y -sudo apt -y install tor \ No newline at end of file +sudo apt update +sudo apt install tor \ No newline at end of file From a189bb200e0b9f91fe9a56c6eb443299db680acd Mon Sep 17 00:00:00 2001 From: sip21 Date: Sun, 13 Oct 2024 14:40:34 -0600 Subject: [PATCH 15/22] Test CI --- sauron/tests/test_sauron_esplora_tor_proxy.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index a8eb007b7..c544c0f0e 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -46,10 +46,3 @@ def test_tor_proxy(node_factory): assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" assert ln_node.daemon.is_in_log("Using proxy socks5h://localhost:9050 for requests") - - response = ln_node.rpc.call("getchaininfo") - - expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] - assert list(response.keys()) == expected_response_keys - assert response["chain"] == "main" - assert not response["ibd"] \ No newline at end of file From 283c636095a6428ba0603c4a5c49fea1829a5eba Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 13:48:36 -0600 Subject: [PATCH 16/22] Cleanup --- .github/workflows/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2c2ce4eb7..99eecfa92 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,8 +89,6 @@ jobs: sudo mkdir /usr/local/libexec/c-lightning/plugins sudo chown -R $USER /usr/local/libexec - sudo apt install tor - - name: Restore bitcoind cache id: cache-bitcoind if: ${{ github.event_name == 'push' || steps.set_plugin_dirs.outputs.run_ci == 'true' }} From 0e359a38f9acf6c607fce0a2c822428be031c7d4 Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 13:50:27 -0600 Subject: [PATCH 17/22] Install to in test --- sauron/tests/test_sauron_esplora_tor_proxy.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index c544c0f0e..a309ca2c1 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -42,6 +42,14 @@ def test_tor_proxy(node_factory): """ Test for tor proxy """ + import subprocess + import time + + subprocess.call( + ["sudo", "apt", "install", "tor"] + ) + time.sleep(10) + ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" From 453a57f013619927c56c93fd65e242a851848e3f Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 14:23:50 -0600 Subject: [PATCH 18/22] Use wait_for_log --- sauron/tests/test_sauron_esplora.py | 2 +- sauron/tests/test_sauron_mempoolspace.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sauron/tests/test_sauron_esplora.py b/sauron/tests/test_sauron_esplora.py index 88e474095..f6e9bdd88 100644 --- a/sauron/tests/test_sauron_esplora.py +++ b/sauron/tests/test_sauron_esplora.py @@ -45,7 +45,7 @@ def test_rpc_getchaininfo(node_factory): response = ln_node.rpc.call("getchaininfo") - assert ln_node.daemon.is_in_log("Sauron plugin initialized using Esplora API") + assert ln_node.daemon.wait_for_log("Sauron plugin initialized using Esplora API") expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] assert list(response.keys()) == expected_response_keys diff --git a/sauron/tests/test_sauron_mempoolspace.py b/sauron/tests/test_sauron_mempoolspace.py index 5b0bcbe04..4a2f2c921 100644 --- a/sauron/tests/test_sauron_mempoolspace.py +++ b/sauron/tests/test_sauron_mempoolspace.py @@ -45,7 +45,7 @@ def test_rpc_getchaininfo(node_factory): response = ln_node.rpc.call("getchaininfo") - assert ln_node.daemon.is_in_log("Sauron plugin initialized using mempool.space API") + assert ln_node.daemon.wait_for_log("Sauron plugin initialized using mempool.space API") expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] assert list(response.keys()) == expected_response_keys From 892055f3c5ddddcc580e6c1f7b9b02850a353dc7 Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 18:17:32 -0600 Subject: [PATCH 19/22] Add test for Esplora signet and testnet --- ...lora.py => test_sauron_esplora_bitcoin.py} | 2 +- sauron/tests/test_sauron_esplora_signet.py | 159 ++++++++++++++++++ sauron/tests/test_sauron_esplora_testnet.py | 159 ++++++++++++++++++ sauron/tests/test_sauron_esplora_tor_proxy.py | 9 +- ....py => test_sauron_mempoolspace_signet.py} | 2 +- 5 files changed, 321 insertions(+), 10 deletions(-) rename sauron/tests/{test_sauron_esplora.py => test_sauron_esplora_bitcoin.py} (98%) create mode 100644 sauron/tests/test_sauron_esplora_signet.py create mode 100644 sauron/tests/test_sauron_esplora_testnet.py rename sauron/tests/{test_sauron_mempoolspace.py => test_sauron_mempoolspace_signet.py} (98%) diff --git a/sauron/tests/test_sauron_esplora.py b/sauron/tests/test_sauron_esplora_bitcoin.py similarity index 98% rename from sauron/tests/test_sauron_esplora.py rename to sauron/tests/test_sauron_esplora_bitcoin.py index f6e9bdd88..88e474095 100644 --- a/sauron/tests/test_sauron_esplora.py +++ b/sauron/tests/test_sauron_esplora_bitcoin.py @@ -45,7 +45,7 @@ def test_rpc_getchaininfo(node_factory): response = ln_node.rpc.call("getchaininfo") - assert ln_node.daemon.wait_for_log("Sauron plugin initialized using Esplora API") + assert ln_node.daemon.is_in_log("Sauron plugin initialized using Esplora API") expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] assert list(response.keys()) == expected_response_keys diff --git a/sauron/tests/test_sauron_esplora_signet.py b/sauron/tests/test_sauron_esplora_signet.py new file mode 100644 index 000000000..8ab376178 --- /dev/null +++ b/sauron/tests/test_sauron_esplora_signet.py @@ -0,0 +1,159 @@ +#!/usr/bin/python + +import os + +import pyln +import pytest +from pyln.testing import utils +from pyln.testing.fixtures import * # noqa: F403 +from util import LightningD + +pyln.testing.fixtures.network_daemons["signet"] = utils.BitcoinD + + +class LightningNode(utils.LightningNode): + def __init__(self, *args, **kwargs): + pyln.testing.utils.TEST_NETWORK = "signet" + utils.LightningNode.__init__(self, *args, **kwargs) + lightning_dir = args[1] + + self.daemon = LightningD(lightning_dir, None) # noqa: F405 + options = { + "disable-plugin": "bcli", + "network": "signet", + "plugin": os.path.join(os.path.dirname(__file__), "../sauron.py"), + "sauron-api-endpoint": "https://blockstream.info/signet/api", + } + self.daemon.opts.update(options) + + # Monkey patch + def set_feerates(self, feerates, wait_for_effect=True): + return None + + +@pytest.fixture +def node_cls(monkeypatch): + monkeypatch.setenv("TEST_NETWORK", "signet") + yield LightningNode + + +def test_rpc_getchaininfo(node_factory): + """ + Test getchaininfo + """ + ln_node = node_factory.get_node() + + response = ln_node.rpc.call("getchaininfo") + + assert ln_node.daemon.is_in_log("Sauron plugin initialized using Esplora API") + + expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] + assert list(response.keys()) == expected_response_keys + assert response["chain"] == "signet" + assert not response["ibd"] + + +def test_rpc_getrawblockbyheight(node_factory): + """ + Test getrawblockbyheight + """ + ln_node = node_factory.get_node() + + response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) + + expected_response = { + "block": "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a008f4d5fae77031e8ad222030101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000", + "blockhash": "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6", + } + assert response == expected_response + + +def test_rpc_sendrawtransaction_invalid(node_factory): + """ + Test sendrawtransaction + """ + ln_node = node_factory.get_node() + + expected_response = { + "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', + "success": False, + } + response = ln_node.rpc.call( + "sendrawtransaction", + {"tx": "invalid-raw-tx"}, + ) + + assert response == expected_response + + +def test_rpc_getutxout(node_factory): + """ + Test getutxout + """ + ln_node = node_factory.get_node() + + expected_response = { + "amount": 5000000000, + "script": "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac", + } + response = ln_node.rpc.call( + "getutxout", + { + # block 217883 + "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + "vout": 0, + }, + ) + assert response == expected_response + + +def test_rpc_estimatefees(node_factory): + """ + Test estimatefees + """ + ln_node = node_factory.get_node() + + # Sample response + # { + # "opening": 4477, + # "mutual_close": 4477, + # "unilateral_close": 11929, + # "delayed_to_us": 4477, + # "htlc_resolution": 5652, + # "penalty": 5652, + # "min_acceptable": 1060, + # "max_acceptable": 119290, + # "feerate_floor": 1520, + # "feerates": [ + # {"blocks": 2, "feerate": 11929}, + # {"blocks": 6, "feerate": 5652}, + # {"blocks": 12, "feerate": 4477}, + # {"blocks": 144, "feerate": 2120} + # ] + # } + response = ln_node.rpc.call("estimatefees") + + expected_response_keys = [ + "opening", + "mutual_close", + "unilateral_close", + "delayed_to_us", + "htlc_resolution", + "penalty", + "min_acceptable", + "max_acceptable", + "feerate_floor", + "feerates", + ] + assert list(response.keys()) == expected_response_keys + + expected_feerates_keys = ("blocks", "feerate") + assert ( + list(set([tuple(entry.keys()) for entry in response["feerates"]]))[0] + == expected_feerates_keys + ) + + expected_feerates_blocks = [2, 6, 12, 144] + assert [ + entry["blocks"] for entry in response["feerates"] + ] == expected_feerates_blocks diff --git a/sauron/tests/test_sauron_esplora_testnet.py b/sauron/tests/test_sauron_esplora_testnet.py new file mode 100644 index 000000000..e135967de --- /dev/null +++ b/sauron/tests/test_sauron_esplora_testnet.py @@ -0,0 +1,159 @@ +#!/usr/bin/python + +import os + +import pyln +import pytest +from pyln.testing import utils +from pyln.testing.fixtures import * # noqa: F403 +from util import LightningD + +pyln.testing.fixtures.network_daemons["testnet"] = utils.BitcoinD + + +class LightningNode(utils.LightningNode): + def __init__(self, *args, **kwargs): + pyln.testing.utils.TEST_NETWORK = "testnet" + utils.LightningNode.__init__(self, *args, **kwargs) + lightning_dir = args[1] + + self.daemon = LightningD(lightning_dir, None) # noqa: F405 + options = { + "disable-plugin": "bcli", + "network": "testnet", + "plugin": os.path.join(os.path.dirname(__file__), "../sauron.py"), + "sauron-api-endpoint": "https://blockstream.info/testnet/api", + } + self.daemon.opts.update(options) + + # Monkey patch + def set_feerates(self, feerates, wait_for_effect=True): + return None + + +@pytest.fixture +def node_cls(monkeypatch): + monkeypatch.setenv("TEST_NETWORK", "testnet4") + yield LightningNode + + +def test_rpc_getchaininfo(node_factory): + """ + Test getchaininfo + """ + ln_node = node_factory.get_node() + + response = ln_node.rpc.call("getchaininfo") + + assert ln_node.daemon.is_in_log("Sauron plugin initialized using Esplora API") + + expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] + assert list(response.keys()) == expected_response_keys + assert response["chain"] == "test" + assert not response["ibd"] + + +def test_rpc_getrawblockbyheight(node_factory): + """ + Test getrawblockbyheight + """ + ln_node = node_factory.get_node() + + response = ln_node.rpc.call("getrawblockbyheight", {"height": 0}) + + expected_response = { + "block": "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000", + "blockhash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943", + } + assert response == expected_response + + +def test_rpc_sendrawtransaction_invalid(node_factory): + """ + Test sendrawtransaction + """ + ln_node = node_factory.get_node() + + expected_response = { + "errmsg": 'sendrawtransaction RPC error: {"code":-22,"message":"TX decode failed. Make sure the tx has at least one input."}', + "success": False, + } + response = ln_node.rpc.call( + "sendrawtransaction", + {"tx": "invalid-raw-tx"}, + ) + + assert response == expected_response + + +def test_rpc_getutxout(node_factory): + """ + Test getutxout + """ + ln_node = node_factory.get_node() + + expected_response = { + "amount": 5000000000, + "script": "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac", + } + response = ln_node.rpc.call( + "getutxout", + { + # block 0 + "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + "vout": 0, + }, + ) + assert response == expected_response + + +def test_rpc_estimatefees(node_factory): + """ + Test estimatefees + """ + ln_node = node_factory.get_node() + + # Sample response + # { + # "opening": 4477, + # "mutual_close": 4477, + # "unilateral_close": 11929, + # "delayed_to_us": 4477, + # "htlc_resolution": 5652, + # "penalty": 5652, + # "min_acceptable": 1060, + # "max_acceptable": 119290, + # "feerate_floor": 1520, + # "feerates": [ + # {"blocks": 2, "feerate": 11929}, + # {"blocks": 6, "feerate": 5652}, + # {"blocks": 12, "feerate": 4477}, + # {"blocks": 144, "feerate": 2120} + # ] + # } + response = ln_node.rpc.call("estimatefees") + + expected_response_keys = [ + "opening", + "mutual_close", + "unilateral_close", + "delayed_to_us", + "htlc_resolution", + "penalty", + "min_acceptable", + "max_acceptable", + "feerate_floor", + "feerates", + ] + assert list(response.keys()) == expected_response_keys + + expected_feerates_keys = ("blocks", "feerate") + assert ( + list(set([tuple(entry.keys()) for entry in response["feerates"]]))[0] + == expected_feerates_keys + ) + + expected_feerates_blocks = [2, 6, 12, 144] + assert [ + entry["blocks"] for entry in response["feerates"] + ] == expected_feerates_blocks diff --git a/sauron/tests/test_sauron_esplora_tor_proxy.py b/sauron/tests/test_sauron_esplora_tor_proxy.py index a309ca2c1..26321cf1e 100644 --- a/sauron/tests/test_sauron_esplora_tor_proxy.py +++ b/sauron/tests/test_sauron_esplora_tor_proxy.py @@ -38,18 +38,11 @@ def node_cls(monkeypatch): yield LightningNode +@pytest.mark.skip(reason="TODO: Add mock for tor proxy") def test_tor_proxy(node_factory): """ Test for tor proxy """ - import subprocess - import time - - subprocess.call( - ["sudo", "apt", "install", "tor"] - ) - time.sleep(10) - ln_node = node_factory.get_node() assert ln_node.daemon.opts["sauron-tor-proxy"] == "localhost:9050" diff --git a/sauron/tests/test_sauron_mempoolspace.py b/sauron/tests/test_sauron_mempoolspace_signet.py similarity index 98% rename from sauron/tests/test_sauron_mempoolspace.py rename to sauron/tests/test_sauron_mempoolspace_signet.py index 4a2f2c921..5b0bcbe04 100644 --- a/sauron/tests/test_sauron_mempoolspace.py +++ b/sauron/tests/test_sauron_mempoolspace_signet.py @@ -45,7 +45,7 @@ def test_rpc_getchaininfo(node_factory): response = ln_node.rpc.call("getchaininfo") - assert ln_node.daemon.wait_for_log("Sauron plugin initialized using mempool.space API") + assert ln_node.daemon.is_in_log("Sauron plugin initialized using mempool.space API") expected_response_keys = ["chain", "blockcount", "headercount", "ibd"] assert list(response.keys()) == expected_response_keys From 211122c453311f2e958571ac53e9b80716eb689a Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 18:19:31 -0600 Subject: [PATCH 20/22] Update sauron --- sauron/sauron.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/sauron/sauron.py b/sauron/sauron.py index 4165ef100..c57d5cc5e 100755 --- a/sauron/sauron.py +++ b/sauron/sauron.py @@ -46,22 +46,16 @@ def init(plugin, options, **kwargs): raise SauronError("You need to specify the sauron-api-endpoint option.") sys.exit(1) - # Test for Esplora or mempoolspace + # Testing for Esplora or mempool.space API try: - # Esplora API - feerate_url = "{}/fee-estimates".format(plugin.api_endpoint) + # MutinyNet API + feerate_url = "{}/v1/fees/recommended".format(plugin.api_endpoint) feerate_req = fetch(feerate_url) - assert feerate_req.status_code == 200 and feerate_req.content != b'{}' - plugin.is_mempoolspace = False + assert feerate_req.status_code == 200 + plugin.is_mempoolspace = True except AssertionError: - try: - # MutinyNet API - feerate_url = "{}/v1/fees/recommended".format(plugin.api_endpoint) - feerate_req = fetch(feerate_url) - assert feerate_req.status_code == 200 - plugin.is_mempoolspace = True - except AssertionError as e1: - raise Exception("Sauron API cannot be reached") from e1 + # Esplora API + plugin.is_mempoolspace = False if options["sauron-tor-proxy"]: address, port = options["sauron-tor-proxy"].split(":") @@ -72,7 +66,7 @@ def init(plugin, options, **kwargs): } plugin.log("Using proxy {} for requests".format(socks5_proxy)) - api = "mempool.space" if plugin.is_mempoolspace else "Esplora" + api = "mempool.space" if plugin.is_mempoolspace in plugin.api_endpoint else "Esplora" plugin.log(f"Sauron plugin initialized using {api} API") plugin.log(sauron_eye) From 681717daea997ea47da9ed35c262c4ca9ba1a0a8 Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 18:21:24 -0600 Subject: [PATCH 21/22] Remove tests/setup.sh --- sauron/tests/setup.sh | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 sauron/tests/setup.sh diff --git a/sauron/tests/setup.sh b/sauron/tests/setup.sh deleted file mode 100644 index 36866c854..000000000 --- a/sauron/tests/setup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -sudo apt update -sudo apt install tor \ No newline at end of file From 84f6d804b7787ca12e454266fe10f3022de2ea34 Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 17 Oct 2024 18:23:13 -0600 Subject: [PATCH 22/22] Bugfix --- sauron/sauron.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sauron/sauron.py b/sauron/sauron.py index c57d5cc5e..cb0d1b58c 100755 --- a/sauron/sauron.py +++ b/sauron/sauron.py @@ -66,7 +66,7 @@ def init(plugin, options, **kwargs): } plugin.log("Using proxy {} for requests".format(socks5_proxy)) - api = "mempool.space" if plugin.is_mempoolspace in plugin.api_endpoint else "Esplora" + api = "mempool.space" if plugin.is_mempoolspace else "Esplora" plugin.log(f"Sauron plugin initialized using {api} API") plugin.log(sauron_eye)