Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lnprototest/backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .backend import Backend
from .bitcoind import Bitcoind

__all__ = [
"Backend",
"Bitcoind"
]
25 changes: 25 additions & 0 deletions lnprototest/backend/backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#! /usr/bin/python3
# This script exercises the backend implementation

# Released by Rusty Russell under CC0:
# https://creativecommons.org/publicdomain/zero/1.0/
from abc import ABC, abstractmethod

class Backend(ABC):
"""
Generic implementation of Bitcoin backend
This is useful when the LN node use different type
of bitcoin backend.
"""

@abstractmethod
def start(self) -> None:
pass

@abstractmethod
def stop(self) -> None:
pass

@abstractmethod
def restart(self) -> None:
pass
85 changes: 85 additions & 0 deletions lnprototest/backend/bitcoind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#! /usr/bin/python3
# This script exercises the c-lightning implementation

# Released by Rusty Russell under CC0:
# https://creativecommons.org/publicdomain/zero/1.0/

import os
import shutil
import subprocess
import logging

from ephemeral_port_reserve import reserve
from pyln.testing.utils import wait_for, SimpleBitcoinProxy
from .backend import Backend


class Bitcoind(Backend):
"""Starts regtest bitcoind on an ephemeral port, and returns the RPC proxy"""
def __init__(self, basedir: str):
self.bitcoin_dir = os.path.join(basedir, "bitcoind")
if not os.path.exists(self.bitcoin_dir):
os.makedirs(self.bitcoin_dir)
self.bitcoin_conf = os.path.join(self.bitcoin_dir, 'bitcoin.conf')
self.cmd_line = [
'bitcoind',
'-datadir={}'.format(self.bitcoin_dir),
'-server',
'-regtest',
'-logtimestamps',
'-nolisten']
self.port = reserve()
self.btc_version = None
print("Port is {}, dir is {}".format(self.port, self.bitcoin_dir))
# For after 0.16.1 (eg. 3f398d7a17f136cd4a67998406ca41a124ae2966), this
# needs its own [regtest] section.
with open(self.bitcoin_conf, 'w') as f:
f.write("regtest=1\n")
f.write("rpcuser=rpcuser\n")
f.write("rpcpassword=rpcpass\n")
f.write("[regtest]\n")
f.write("rpcport={}\n".format(self.port))
self.rpc = SimpleBitcoinProxy(btc_conf_file=self.bitcoin_conf)

def version_compatibility(self):
"""
This method try to manage the compatibility between
different version of Bitcoin Core implementation.

This method could be useful sometimes when is necessary
run the test with different version of Bitcoin core.
"""
if self.rpc is None:
# Sanity check
raise Error("bitcoind not initialized")

self.btc_version = self.rpc.getnetworkinfo()['version']
logging.info("Bitcoin Core version {}".format(self.btc_version))
if self.btc_version >= 210000:
# Maintains the compatibility between wallet
# different ln implementation can use the main wallet (?)
self.rpc.createwallet("main") # Automatically loads


def start(self) -> None:
self.proc = subprocess.Popen(self.cmd_line, stdout=subprocess.PIPE)

# Wait for it to startup.
while b'Done loading' not in self.proc.stdout.readline():
pass

self.version_compatibility()
# Block #1.
self.rpc.submitblock('0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f69d715fba6edece89b2dee71f4fed52c7accd6cd62c328536e6233b72b14c5f5c8ba465fffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a0100000016001419c70534cd905244cff88a594f0c16d4bbedc5e60000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000')
self.rpc.generatetoaddress(100, self.rpc.getnewaddress())

def stop(self) -> None:
self.proc.kill()

def restart(self) -> None:
# Only restart if we have to.
if self.rpc.getblockcount() != 102 or self.rpc.getrawmempool() == []:
self.stop()
shutil.rmtree(os.path.join(self.bitcoin_dir, 'regtest'))
self.start()

57 changes: 2 additions & 55 deletions lnprototest/clightning/clightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import pyln.client
import pyln.proto.wire
import os
import shutil
import subprocess
import tempfile
import lnprototest
Expand All @@ -17,67 +16,15 @@

from concurrent import futures
from ephemeral_port_reserve import reserve
from pyln.testing.utils import wait_for, SimpleBitcoinProxy
from lnprototest.backend import Bitcoind
from lnprototest import Event, EventError, SpecFileError, KeySet, Conn, namespace, MustNotMsg
from typing import Dict, Any, Callable, List, Optional, cast
from pyln.testing.utils import wait_for

TIMEOUT = int(os.getenv("TIMEOUT", "30"))
LIGHTNING_SRC = os.path.join(os.getcwd(), os.getenv("LIGHTNING_SRC", '../lightning/'))


class Bitcoind(object):
"""Starts regtest bitcoind on an ephemeral port, and returns the RPC proxy"""
def __init__(self, basedir: str):
self.bitcoin_dir = os.path.join(basedir, "bitcoind")
if not os.path.exists(self.bitcoin_dir):
os.makedirs(self.bitcoin_dir)
self.bitcoin_conf = os.path.join(self.bitcoin_dir, 'bitcoin.conf')
self.cmd_line = [
'bitcoind',
'-datadir={}'.format(self.bitcoin_dir),
'-server',
'-regtest',
'-logtimestamps',
'-nolisten']
self.port = reserve()
print("Port is {}, dir is {}".format(self.port, self.bitcoin_dir))
# For after 0.16.1 (eg. 3f398d7a17f136cd4a67998406ca41a124ae2966), this
# needs its own [regtest] section.
with open(self.bitcoin_conf, 'w') as f:
f.write("regtest=1\n")
f.write("rpcuser=rpcuser\n")
f.write("rpcpassword=rpcpass\n")
f.write("[regtest]\n")
f.write("rpcport={}\n".format(self.port))
self.rpc = SimpleBitcoinProxy(btc_conf_file=self.bitcoin_conf)

def start(self) -> None:
self.proc = subprocess.Popen(self.cmd_line, stdout=subprocess.PIPE)

# Wait for it to startup.
while b'Done loading' not in self.proc.stdout.readline():
pass

if 'lnprototest' not in self.rpc.listwallets():
self.rpc.createwallet("lnprototest") # Automatically loads
else:
self.rpc.loadwallet("lnprototest")

# Block #1.
self.rpc.submitblock('0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f69d715fba6edece89b2dee71f4fed52c7accd6cd62c328536e6233b72b14c5f5c8ba465fffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a0100000016001419c70534cd905244cff88a594f0c16d4bbedc5e60000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000')
self.rpc.generatetoaddress(100, self.rpc.getnewaddress())

def stop(self) -> None:
self.proc.kill()

def restart(self) -> None:
# Only restart if we have to.
if self.rpc.getblockcount() != 102 or self.rpc.getrawmempool() == []:
self.stop()
shutil.rmtree(os.path.join(self.bitcoin_dir, 'regtest'))
self.start()


class CLightningConn(lnprototest.Conn):
def __init__(self, connprivkey: str, port: int):
super().__init__(connprivkey)
Expand Down