Skip to content

Commit

Permalink
Add sauron tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sip-21 authored and ca-ruz committed Oct 8, 2024
1 parent 7402d7d commit 18f6e23
Show file tree
Hide file tree
Showing 7 changed files with 393 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .ci/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()}")
Expand Down
2 changes: 1 addition & 1 deletion poncho
11 changes: 6 additions & 5 deletions sauron/sauron.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)


Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.",
)


Expand Down
152 changes: 152 additions & 0 deletions sauron/tests/test_sauron_esplora.py
Original file line number Diff line number Diff line change
@@ -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
45 changes: 45 additions & 0 deletions sauron/tests/test_sauron_esplora_tor_proxy.py
Original file line number Diff line number Diff line change
@@ -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")
Loading

0 comments on commit 18f6e23

Please sign in to comment.