Skip to content

Commit

Permalink
func test: allow to run using electrs backend
Browse files Browse the repository at this point in the history
  • Loading branch information
jp1ac4 committed Aug 22, 2024
1 parent 0304648 commit dac26c8
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 0 deletions.
11 changes: 11 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from bip380.descriptors import Descriptor
from concurrent import futures
from test_framework.bitcoind import Bitcoind
from test_framework.electrs import Electrs
from test_framework.lianad import Lianad
from test_framework.signer import SingleSigner, MultiSigner
from test_framework.utils import (
Expand Down Expand Up @@ -126,6 +127,16 @@ def bitcoin_backend(directory, bitcoind):
if BITCOIN_BACKEND_TYPE is BitcoinBackendType.Bitcoind:
yield bitcoind
bitcoind.cleanup()
elif BITCOIN_BACKEND_TYPE is BitcoinBackendType.Electrs:
electrs = Electrs(
electrs_dir=os.path.join(directory, "electrs"),
bitcoind_dir=bitcoind.bitcoin_dir,
bitcoind_rpcport=bitcoind.rpcport,
bitcoind_p2pport=bitcoind.p2pport,
)
electrs.startup()
yield electrs
electrs.cleanup()
else:
raise NotImplementedError

Expand Down
6 changes: 6 additions & 0 deletions tests/test_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ def test_reorg_status_recovery(lianad, bitcoind):
assert new_coin_b == coin_b


@pytest.mark.skipif(
not BITCOIN_BACKEND_TYPE.has_rescan(), reason="Rescan not applicable."
)
def test_rescan_edge_cases(lianad, bitcoind):
"""Test some specific cases that could arise when rescanning the chain."""
initial_tip = bitcoind.rpc.getblockheader(bitcoind.rpc.getbestblockhash())
Expand Down Expand Up @@ -329,6 +332,9 @@ def test_deposit_replacement(lianad, bitcoind):
wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 1)


@pytest.mark.skipif(
not BITCOIN_BACKEND_TYPE.has_rescan(), reason="Rescan not applicable."
)
def test_rescan_and_recovery(lianad, bitcoind):
"""Test user recovery flow"""
# Get initial_tip to use for rescan later
Expand Down
72 changes: 72 additions & 0 deletions tests/test_framework/electrs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging
import os

from ephemeral_port_reserve import reserve
from test_framework.utils import BitcoinBackend, TailableProc, ELECTRS_PATH


class Electrs(BitcoinBackend):
def __init__(
self,
bitcoind_dir,
bitcoind_rpcport,
bitcoind_p2pport,
electrs_dir,
rpcport=None,
):
TailableProc.__init__(self, electrs_dir, verbose=False)

if rpcport is None:
rpcport = reserve()

self.electrs_dir = electrs_dir
self.rpcport = rpcport

regtestdir = os.path.join(electrs_dir, "regtest")
if not os.path.exists(regtestdir):
os.makedirs(regtestdir)

self.cmd_line = [
ELECTRS_PATH,
"--conf",
"{}/electrs.toml".format(regtestdir),
]
electrs_conf = {
"daemon_dir": bitcoind_dir,
"cookie_file": os.path.join(bitcoind_dir, "regtest", ".cookie"),
"daemon_rpc_addr": f"127.0.0.1:{bitcoind_rpcport}",
"daemon_p2p_addr": f"127.0.0.1:{bitcoind_p2pport}",
"db_dir": electrs_dir,
"network": "regtest",
"electrum_rpc_addr": f"127.0.0.1:{self.rpcport}",
}
self.conf_file = os.path.join(regtestdir, "electrs.toml")
with open(self.conf_file, "w") as f:
for k, v in electrs_conf.items():
f.write(f'{k} = "{v}"\n')

def start(self):
TailableProc.start(self)
logging.info("Electrs started")

def startup(self):
try:
self.start()
except Exception:
self.stop()
raise

def stop(self):
return TailableProc.stop(self)

def cleanup(self):
try:
self.stop()
except Exception:
self.proc.kill()
self.proc.wait()

def append_to_lianad_conf(self, conf_file):
with open(conf_file, "a") as f:
f.write("[electrum_config]\n")
f.write(f"addr = '127.0.0.1:{self.rpcport}'\n")
10 changes: 10 additions & 0 deletions tests/test_framework/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@

class BitcoinBackendType(str, enum.Enum):
Bitcoind = "bitcoind"
Electrs = "electrs"

def has_rescan(self):
if self is BitcoinBackendType.Bitcoind:
return True
if self is BitcoinBackendType.Electrs:
return False
raise NotImplementedError


DEFAULT_BITCOIN_BACKEND_TYPE = "bitcoind"
Expand All @@ -34,6 +42,8 @@ class BitcoinBackendType(str, enum.Enum):
)
DEFAULT_BITCOIND_PATH = "bitcoind"
BITCOIND_PATH = os.getenv("BITCOIND_PATH", DEFAULT_BITCOIND_PATH)
DEFAULT_ELECTRS_PATH = "electrs"
ELECTRS_PATH = os.getenv("ELECTRS_PATH", DEFAULT_ELECTRS_PATH)
OLD_LIANAD_PATH = os.getenv("OLD_LIANAD_PATH", None)
IS_NOT_BITCOIND_24 = bool(int(os.getenv("IS_NOT_BITCOIND_24", True)))
USE_TAPROOT = bool(
Expand Down
6 changes: 6 additions & 0 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from test_framework.authproxy import JSONRPCException
from test_framework.serializations import PSBT
from test_framework.utils import (
BitcoinBackendType,
BITCOIN_BACKEND_TYPE,
wait_for,
RpcError,
OLD_LIANAD_PATH,
Expand Down Expand Up @@ -315,6 +317,10 @@ def bitcoind_wait_new_block(bitcoind):
@pytest.mark.skipif(
not IS_NOT_BITCOIND_24, reason="Need 'generateblock' with 'submit=False'"
)
# TODO: Should this test work for other backends?
@pytest.mark.skipif(
BITCOIN_BACKEND_TYPE is not BitcoinBackendType.Bitcoind, reason="FIXME"
)
def test_retry_on_workqueue_exceeded(lianad, bitcoind, executor):
"""Make sure we retry requests to bitcoind if it is temporarily overloaded."""
# Start by reducing the work queue to a single slot. Note we need to stop lianad
Expand Down
3 changes: 3 additions & 0 deletions tests/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ def test_broadcast_spend(lianad, bitcoind):
lianad.rpc.broadcastspend(txid)


@pytest.mark.skipif(
not BITCOIN_BACKEND_TYPE.has_rescan(), reason="Rescan not applicable."
)
def test_start_rescan(lianad, bitcoind):
"""Test we successfully retrieve all our transactions after losing state by rescanning."""
initial_timestamp = int(time.time())
Expand Down

0 comments on commit dac26c8

Please sign in to comment.