GithubHelp home page GithubHelp logo

lnprototest's Introduction

lnprototest

a Testsuite for the Lightning Network Protocol

GitHub Workflow Status (branch)

lnprototest is a set of test helpers written in Python3, designed to make it easy to write new tests when you propose changes to the lightning network protocol, as well as test existing implementations.

Install requirements

To install the necessary dependences

pip3 install poetry
poetry shell
poetry install

Well, now we can run the test

Running test

The simplest way to run is with the "dummy" runner:

make check

Here are some other useful pytest options:

  1. -n8 to run 8-way parallel.
  2. -x to stop on the first failure.
  3. --pdb to enter the debugger on first failure.
  4. --trace to enter the debugger on every test.
  5. -k foo to only run tests with 'foo' in their name.
  6. tests/test_bolt1-01-init.py to only run tests in that file.
  7. tests/test_bolt1-01-init.py::test_init to only run that test.
  8. --log-cli-level={LEVEL_NAME} to enable the logging during the test execution.

Running Against A Real Node.

The more useful way to run is to use an existing implementation. So far, core-lightning is supported. You will need:

  1. bitcoind installed, and in your path.
  2. lightningd compiled with --enable-developer. By default the source directory should be ../lightning relative to this directory, otherwise use export LIGHTNING_SRC=dirname.
  3. Install any python requirements by pip3 install -r lnprototest/clightning/requirements.txt.

Then you can run

make check PYTEST_ARGS='--runner=lnprototest.clightning.Runner'

or directly:

pytest --runner=lnprototest.clightning.Runner

Further Work

If you want to write new tests or new backends, see HACKING.md.

Let's keep the sats flowing!

Rusty.

lnprototest's People

Contributors

cdecker avatar ddustin avatar dependabot[bot] avatar endothermicdev avatar joelklabo avatar nassersaazi avatar niftynei avatar psycho-pirate avatar rustyrussell avatar vincenzopalazzo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

lnprototest's Issues

minimum_depth set to a static value

According to BOLT 2, for accept_message, the minimum_depth should be determined by the sender.

The sender:

    if channel_type includes option_zeroconf:
        MUST set minimum_depth to zero.
    otherwise:
        SHOULD set minimum_depth to a number of blocks it considers reasonable to avoid double-spending of the funding transaction.

Lnprototest sets it to 3. This causes tests to fail if minimum_depth required by an implementation is not equal to 3.

Feedback: Gather feedback on the usage of 'lnprototest' in the implementation

Through this issue, I am seeking feedback from individuals who have attempted to implement a runner using lnprototest within the Lightning framework, despite encountering challenges in the process.

The purpose behind this feedback collection effort is to support our ongoing review of the fundamental building blocks of lnprototest. As part of this review, I am actively soliciting input.

I have designated this issue as a centralized space where implementors who have experimented with incorporating lnprototest can share their insights, dreams, and the specific challenges they encountered during the implementation.

For those interested, you can observe the current design experimentation by following this link: lnprototest Design Experimentation

P.S: rewriting the implementation in Rust is not a viable option at the moment ๐Ÿ˜„. We will defer this decision until we have refined the framework's design to our satisfaction.

improve error printing

During the assertion, we have the message in hexadecimal, to have a clean way to have get the message content.

This is an example of stacktrace with an error message

tests/test_bolt2-01-close_channel.py:72: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

runner = <lnprototest.clightning.clightning.Runner object at 0x7fe3eab2f970>
test = [Block:spec_helper.py:41, Connect:spec_helper.py:42, ExpectMsg:spec_helper.py:43, Msg:spec_helper.py:44, Block:spec_helper.py:45, RawMsg:spec_helper.py:46, ...]

    def run_runner(runner: Runner, test: Union[Sequence, List[Event], Event]) -> None:
        """
        The pytest using the assertion as safe failure, and the exception it is only
        an event that must not happen.
    
        From design, lnprototest fails with an exception, and for this reason, if the
        lnprototest throws an exception, we catch it, and we fail with an assent.
        """
        try:
            runner.run(test)
        except Exception as ex:
            runner.stop()
            logging.error(get_traceback(ex))
>           assert False, ex
E           AssertionError: (ExpectMsg:test_bolt2-01-close_channel.py:70, 'Expected msgtype-shutdown, got msgtype-error: message was error channel_id=a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc77 data=556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e')

tests/helpers.py:169: AssertionError
----------------------------------------------------------------------------- Captured log call -----------------------------------------------------------------------------
ERROR    root:helpers.py:168 Traceback (most recent call last):
  File "/home/vincent/Github/lnprototest/tests/helpers.py", line 165, in run_runner
    runner.run(test)
  File "/home/vincent/Github/lnprototest/lnprototest/runner.py", line 103, in run
    all_done = sequence.action(self)
  File "/home/vincent/Github/lnprototest/lnprototest/structure.py", line 52, in action
    all_done &= e.action(runner)
  File "/home/vincent/Github/lnprototest/lnprototest/event.py", line 347, in action
    raise EventError(self, "{}: message was {}".format(err, msg.to_str()))
lnprototest.errors.EventError: (ExpectMsg:test_bolt2-01-close_channel.py:70, 'Expected msgtype-shutdown, got msgtype-error: message was error channel_id=a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc77 data=556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e')
========================================================================== short test summary info ==========================================================================
FAILED tests/test_bolt2-01-close_channel.py::test_close_channel_shutdown_msg - AssertionError: (ExpectMsg:test_bolt2-01-close_channel.py:70, 'Expected msgtype-shutdown, g...
===================================================================== 1 failed, 27 deselected in 9.28s ======================================================================
make: *** [Makefile:14: check] Error 1

Where the data in this case is Unknown channel for WIRE_SHUTDOWN that is contained inside the data=556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e in the following error message

E AssertionError: (ExpectMsg:test_bolt2-01-close_channel.py:70, 'Expected msgtype-shutdown, got msgtype-error: message was error channel_id=a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc77 ')

Failed test: open_channel_accepter.py - BrokenPipeError: [Errno 32] Broken pipe

Built clightning from source with --enable-developer
What can I try to debug this connection issue?

Here's the log:

========================================================= test session starts ==========================================================
platform linux -- Python 3.9.5, pytest-6.1.2, py-1.10.0, pluggy-0.13.1
rootdir: /home/user/Documents/lightning/lnprototest
plugins: forked-1.3.0, rerunfailures-9.1.1, timeout-1.4.2, flaky-3.7.0, xdist-2.2.1
collected 26 items                                                                                                                     

tests/test_bolt1-01-init.py ..                                                                                                   [  7%]
tests/test_bolt1-02-unknown-messages.py .                                                                                        [ 11%]
tests/test_bolt2-01-open_channel.py .                                                                                            [ 15%]
tests/test_bolt2-02-reestablish.py .                                                                                             [ 19%]
tests/test_bolt2-10-add-htlc.py .                                                                                                [ 23%]
tests/test_bolt2-20-open_channel_accepter.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> captured stdout >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Port is 38609, dir is /tmp/lnprototest-clightning-lb7_uijc/bitcoind
2021-08-31T19:00:17.262Z UNUSUAL lightningd: Creating configuration directory /tmp/lnprototest-clightning-lb7_uijc/lightningd/regtest
signing our input for tx 02000000012f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360100000000fdffffff0178410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000
finalized funding 02000000012f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360100000000fdffffff0178410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000
Signing 1 redeemscript keys 03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 and 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a: 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae amount = 999800
tx: 0200000001a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc770000000000f436a980024a0100000000000022002047d040ee05dd47a80038faf7fa42e8559bfc8b60bd981410ad1d67d02dbe65e9c83d0f0000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01ac4cff0020
witness is ...  CTxInWitness(CScriptWitness(x('30450221009e8236b5eef62bab47f96ee3d37e4beb0d0561d1057483971a620f3299e98e8302204fe9f34b47e8f4b5afb188f3641e97407684a30da7bb2ca4f8879745daabc12501'),x('02d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b')))
witnesses are [{witness_element=[{witness=30450221009e8236b5eef62bab47f96ee3d37e4beb0d0561d1057483971a620f3299e98e8302204fe9f34b47e8f4b5afb188f3641e97407684a30da7bb2ca4f8879745daabc12501},{witness=02d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b}]}]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

self = <lnprototest.clightning.clightning.Runner object at 0x7f1894c35af0>, event = Msg:test_bolt2-20-open_channel_accepter.py:306
conn = <lnprototest.clightning.clightning.CLightningConn object at 0x7f1895ce3940>
outbuf = b'\x00$\xaa\x96\xb1\x18\x9fp6\xd4$\xdf\x00\x81\xcc\xa3\xf0\x19\x18\x10\x13\xf9+Gf\x8d\xfc\xa1\xf6\x01@7\rX\x02~\xed\x83\x89\xcf\x8e\xb7\x15\xd71\x11\xb7=\x94\xd2\xc2\xd0K\xf9m\xc4=\xfd[\tp\xd8\x0b6\x17\x00\x9d'

    def recv(self, event: Event, conn: Conn, outbuf: bytes) -> None:
        try:
>           cast(CLightningConn, conn).connection.send_message(outbuf)

lnprototest/clightning/clightning.py:182: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyln.proto.wire.LightningConnection object at 0x7f1895ce0e50>
m = b'\x00$\xaa\x96\xb1\x18\x9fp6\xd4$\xdf\x00\x81\xcc\xa3\xf0\x19\x18\x10\x13\xf9+Gf\x8d\xfc\xa1\xf6\x01@7\rX\x02~\xed\x83\x89\xcf\x8e\xb7\x15\xd71\x11\xb7=\x94\xd2\xc2\xd0K\xf9m\xc4=\xfd[\tp\xd8\x0b6\x17\x00\x9d'

    def send_message(self, m):
        length = struct.pack("!H", len(m))
        with self.send_lock:
            lc = encryptWithAD(self.sk, self.nonce(self.sn), b'', length)
            mc = encryptWithAD(self.sk, self.nonce(self.sn + 1), b'', m)
            self.sn += 2
            self.connection.send(lc)
>           self.connection.send(mc)
E           BrokenPipeError: [Errno 32] Broken pipe

/home/r/.local/lib/python3.9/site-packages/pyln/proto/wire.py:314: BrokenPipeError

During handling of the above exception, another exception occurred:

runner = <lnprototest.clightning.clightning.Runner object at 0x7f1894c35af0>
with_proposal = <function with_proposal.<locals>._setter at 0x7f1894c40af0>

>   ???

/home/r/Documents/lnprototest/tests/test_bolt2-20-open_channel_accepter.py:318: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
lnprototest/runner.py:83: in run
    all_done = sequence.action(self)
lnprototest/structure.py:48: in action
    all_done &= e.action(runner)
lnprototest/event.py:158: in action
    runner.recv(self, self.find_conn(runner), binmsg.getvalue())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <lnprototest.clightning.clightning.Runner object at 0x7f1894c35af0>, event = Msg:test_bolt2-20-open_channel_accepter.py:306
conn = <lnprototest.clightning.clightning.CLightningConn object at 0x7f1895ce3940>
outbuf = b'\x00$\xaa\x96\xb1\x18\x9fp6\xd4$\xdf\x00\x81\xcc\xa3\xf0\x19\x18\x10\x13\xf9+Gf\x8d\xfc\xa1\xf6\x01@7\rX\x02~\xed\x83\x89\xcf\x8e\xb7\x15\xd71\x11\xb7=\x94\xd2\xc2\xd0K\xf9m\xc4=\xfd[\tp\xd8\x0b6\x17\x00\x9d'

    def recv(self, event: Event, conn: Conn, outbuf: bytes) -> None:
        try:
            cast(CLightningConn, conn).connection.send_message(outbuf)
        except BrokenPipeError:
            # This happens when they've sent an error and closed; try
            # reading it to figure out what went wrong.
            fut = self.executor.submit(cast(CLightningConn, conn).connection.read_message)
            try:
                msg = fut.result(1)
            except futures.TimeoutError:
                msg = None
            if msg:
>               raise EventError(event, "Connection closed after sending {}".format(msg.hex()))
E               lnprototest.errors.EventError: (Msg:test_bolt2-20-open_channel_accepter.py:306, 'Connection closed after sending 0011aa96b1189f7036d424df0081cca3f019181013f92b47668dfca1f60140370d58016c4261642074785f7369676e6174757265732030303437616139366231313839663730333664343234646630303831636361336630313931383130313366393262343736363864666361316636303134303337306435386133373336323833396231336636316366653832643335626433393762313236346333383962323435383437636662363131316233383839323534366463373730303031333034353032323130303965383233366235656566363262616234376639366565336433376534626562306430353631643130353734383339373161363230663332393965393865383330323230346665396633346234376538663462356166623138386633363431653937343037363834613330646137626232636134663838373937343564616162633132353031303264366133633264306366373930346162366166353464376339353934333561343532623234613633313934653163346537633333376433656262623330313762')

lnprototest/clightning/clightning.py:192: EventError

flaky test ran on lightningd

This is an issue maybe it is in the wrong place but during the protocol testing we have an exception related to lnprototest https://github.com/ElementsProject/lightning/runs/4502628625?check_suite_focus=true#step:5:2775, we have a duplicate transaction in the bitcoin blockchain.

Click to expand the stacktrace!
================================== FAILURES ===================================
_________________________ test_open_opener_with_inputs _________________________
[gw0] linux -- Python 3.6.15 /opt/hostedtoolcache/Python/3.6.15/x64/bin/python3

runner = <lnprototest.clightning.clightning.Runner object at 0x7feb2c8cd390>
with_proposal = <function with_proposal.<locals>._setter at 0x7feb2c4a40d0>

    def test_open_opener_with_inputs(runner: Runner, with_proposal: Any) -> None:
        with_proposal(dual_fund_csv)
        runner.add_startup_flag('experimental-dual-fund')
    
        local_funding_privkey = '20'
    
        local_keyset = KeySet(revocation_base_secret='21',
                              payment_base_secret='22',
                              htlc_base_secret='24',
                              delayed_payment_base_secret='23',
                              shachain_seed='00' * 32)
    
        # Index 5 is special, only the test runner can spend it
        ii = 5
        test = [Block(blockheight=102, txs=[tx_spendable]),
                Connect(connprivkey='02'),
                ExpectMsg('init'),
    
                # BOLT-f53ca2301232db780843e894f55d95d512f297f9 #9:
                # | 28/29 | `option_dual_fund`             | Use v2 of channel open, enables dual funding              | IN9      | `option_anchor_outputs`, `option_static_remotekey`   | [BOLT #2](02-peer-protocol.md)        |
                Msg('init', globalfeatures='', features=bitfield(12, 20, 29)),
    
                FundChannel(amount=999877),
    
                ExpectMsg('open_channel2',
                          channel_id=channel_id_tmp(local_keyset, Side.remote),
                          chain_hash=regtest_hash,
                          funding_satoshis=999877,
                          dust_limit_satoshis=546,
                          htlc_minimum_msat=0,
                          to_self_delay=6,
                          funding_pubkey=remote_funding_pubkey(),
                          revocation_basepoint=remote_revocation_basepoint(),
                          payment_basepoint=remote_payment_basepoint(),
                          delayed_payment_basepoint=remote_delayed_payment_basepoint(),
                          htlc_basepoint=remote_htlc_basepoint(),
                          first_per_commitment_point=remote_per_commitment_point(0),
                          channel_flags='01'),
    
                Msg('accept_channel2',
                    channel_id=rcvd('open_channel2.channel_id'),
                    dust_limit_satoshis=550,
                    funding_satoshis=400000,
                    max_htlc_value_in_flight_msat=4294967295,
                    htlc_minimum_msat=0,
                    minimum_depth=3,
                    max_accepted_htlcs=483,
                    # We use 5, to be different from c-lightning runner who uses 6
                    to_self_delay=5,
                    funding_pubkey=pubkey_of(local_funding_privkey),
                    revocation_basepoint=local_keyset.revocation_basepoint(),
                    payment_basepoint=local_keyset.payment_basepoint(),
                    delayed_payment_basepoint=local_keyset.delayed_payment_basepoint(),
                    htlc_basepoint=local_keyset.htlc_basepoint(),
                    first_per_commitment_point=local_keyset.per_commit_point(0)),
    
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
    
                # Create and stash Funding object and FundingTx
                CreateDualFunding(fee=200,
                                  funding_sats=agreed_funding(Side.remote),
                                  locktime=rcvd('open_channel2.locktime', int),
                                  local_node_privkey='02',
                                  local_funding_privkey=local_funding_privkey,
                                  remote_node_privkey=runner.get_node_privkey(),
                                  remote_funding_privkey=remote_funding_privkey()),
    
                ExpectMsg('tx_add_input',
                          channel_id=channel_id_v2(local_keyset),
                          if_match=even_serial,
                          prevtx=tx_spendable,
                          sequence=0xfffffffd,
                          script_sig=''),
    
                AddInput(funding=funding(),
                         serial_id=rcvd('tx_add_input.serial_id', int),
                         prevtx=rcvd('tx_add_input.prevtx'),
                         prevtx_vout=rcvd('tx_add_input.prevtx_vout', int),
                         script_sig=rcvd('tx_add_input.script_sig')),
    
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
    
                Msg('tx_add_input',
                    channel_id=channel_id_v2(local_keyset),
                    serial_id=1,
                    sequence=0xfffffffd,
                    prevtx=tx_spendable,
                    prevtx_vout=tx_out_for_index(ii),
                    script_sig=''),
    
                AddInput(funding=funding(),
                         privkey=privkey_for_index(ii),
                         serial_id=sent('tx_add_input.serial_id', int),
                         prevtx=sent(),
                         prevtx_vout=sent('tx_add_input.prevtx_vout', int),
                         script_sig=sent()),
    
                # The funding output
                ExpectMsg('tx_add_output',
                          channel_id=channel_id_v2(local_keyset),
                          sats=agreed_funding(Side.remote),
                          if_match=even_serial),
    
    
                Msg('tx_add_output',
                    channel_id=channel_id_v2(local_keyset),
                    serial_id=101,
                    sats=change_amount(Side.remote, False,
                                       '001473daa75958d5b2ddca87a6c279bb7cb307167037',
                                       funding_amount_for_utxo(ii)),
                    script='001473daa75958d5b2ddca87a6c279bb7cb307167037'),
    
                # FIXME: They may send us the funding output second,
                # if there's also a change output
                AddOutput(funding=funding(),
                          serial_id=rcvd('tx_add_output.serial_id', int),
                          sats=rcvd('tx_add_output.sats', int),
                          script=rcvd('tx_add_output.script')),
    
                AddOutput(funding=funding(),
                          serial_id=sent('tx_add_output.serial_id', int),
                          script=sent(),
                          sats=sent('tx_add_output.sats', int)),
    
                # Their change if they have one!
                OneOf([ExpectMsg('tx_add_output',
                                 if_match=even_serial,
                                 channel_id=channel_id_v2(local_keyset)),
                       Msg('tx_complete',
                           channel_id=channel_id_v2(local_keyset)),
                       ExpectMsg('tx_complete',
                                 channel_id=channel_id_v2(local_keyset)),
                       AddOutput(funding=funding(),
                                 serial_id=rcvd('tx_add_output.serial_id', int),
                                 sats=rcvd('tx_add_output.sats', int),
                                 script=rcvd('tx_add_output.script'))],
                      [ExpectMsg('tx_complete',
                                 channel_id=channel_id_v2(local_keyset)),
                       Msg('tx_complete',
                           channel_id=channel_id_v2(local_keyset)),
                       ]),
    
                FinalizeFunding(funding=funding()),
    
                Commit(funding=funding(),
                       opener=Side.remote,
                       local_keyset=local_keyset,
                       local_to_self_delay=rcvd('open_channel2.to_self_delay', int),
                       remote_to_self_delay=sent('accept_channel2.to_self_delay', int),
                       local_amount=msat(sent('accept_channel2.funding_satoshis', int)),
                       remote_amount=msat(rcvd('open_channel2.funding_satoshis', int)),
                       local_dust_limit=550,
                       remote_dust_limit=546,
                       feerate=rcvd('open_channel2.commitment_feerate_perkw', int),
                       local_features=sent('init.features'),
                       remote_features=rcvd('init.features')),
    
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
    
                ExpectMsg('commitment_signed',
                          channel_id=channel_id_v2(local_keyset),
                          signature=commitsig_to_recv()),
    
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
    
                Msg('commitment_signed',
                    channel_id=channel_id_v2(local_keyset),
                    signature=commitsig_to_send(),
                    htlc_signature='[]'),
    
                Msg('tx_signatures',
                    channel_id=channel_id_v2(local_keyset),
                    txid=funding_txid(),
                    witness_stack=witnesses()),
    
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
    
                ExpectMsg('tx_signatures',
                          channel_id=channel_id_v2(local_keyset),
                          txid=funding_txid()),
    
                AddWitnesses(funding=funding(),
                             witness_stack=rcvd('witness_stack')),
    
                # Mine the block!
                Block(blockheight=103, number=3, txs=[funding_tx()]),
                ExpectMsg('funding_locked',
                          channel_id=channel_id_v2(local_keyset),
                          next_per_commitment_point=remote_per_commitment_point(1)),
                # Ignore unknown odd messages
                TryAll([], RawMsg(bytes.fromhex('270F'))),
                ]
    
>       runner.run(test)

tests/test_bolt2-20-open_channel_accepter.py:895: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
lnprototest/runner.py:86: in run
    self.stop()
lnprototest/clightning/clightning.py:133: in stop
    cb()
lnprototest/clightning/clightning.py:123: in kill_fundchannel
    fut.result(0)
/opt/hostedtoolcache/Python/3.6.15/x64/lib/python3.6/concurrent/futures/_base.py:425: in result
    return self.__get_result()
/opt/hostedtoolcache/Python/3.6.15/x64/lib/python3.6/concurrent/futures/_base.py:384: in __get_result
    raise self._exception
/opt/hostedtoolcache/Python/3.6.15/x64/lib/python3.6/concurrent/futures/_base.py:324: in _invoke_callbacks
    callback(self)
lnprototest/clightning/clightning.py:223: in _done
    raise(exception)
/opt/hostedtoolcache/Python/3.6.15/x64/lib/python3.6/concurrent/futures/thread.py:56: in run
    result = self.fn(*self.args, **self.kwargs)
lnprototest/clightning/clightning.py:218: in _fundchannel
    return runner.rpc.fundchannel(peer_id, amount, feerate='{}perkw'.format(feerate))
../../contrib/pyln-client/pyln/client/lightning.py:730: in fundchannel
    return self.call("fundchannel", payload)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyln.client.lightning.LightningRpc object at 0x7feb2c5e5518>
method = 'fundchannel'
payload = {'amount': 999877, 'announce': True, 'feerate': '253perkw', 'id': '02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5'}

    def call(self, method, payload=None):
        self.logger.debug("Calling %s with payload %r", method, payload)
    
        if payload is None:
            payload = {}
        # Filter out arguments that are None
        if isinstance(payload, dict):
            payload = {k: v for k, v in payload.items() if v is not None}
    
        # FIXME: we open a new socket for every readobj call...
        sock = UnixSocket(self.socket_path)
        this_id = self.next_id
        self.next_id += 0
        buf = b''
    
        if self._notify is not None:
            # Opt into the notifications support
            self._writeobj(sock, {
                "jsonrpc": "2.0",
                "method": "notifications",
                "id": 0,
                "params": {
                    "enable": True
                },
            })
            # FIXME: Notification schema support?
            _, buf = self._readobj(sock, buf)
    
        request = {
            "jsonrpc": "2.0",
            "method": method,
            "params": payload,
            "id": this_id,
        }
    
        self._writeobj(sock, request)
        while True:
            resp, buf = self._readobj(sock, buf)
            id = resp.get("id", None)
            meth = resp.get("method", None)
    
            if meth == 'message' and self._notify is not None:
                n = resp['params']
                self._notify(
                    message=n.get('message', None),
                    progress=n.get('progress', None),
                    request=request
                )
                continue
    
            if meth is None or id is None:
                break
    
        self.logger.debug("Received response for %s call: %r", method, resp)
        if 'id' in resp and resp['id'] != this_id:
            raise ValueError("Malformed response, id is not {}: {}.".format(this_id, resp))
        sock.close()
    
        if not isinstance(resp, dict):
            raise ValueError("Malformed response, response is not a dictionary %s." % resp)
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: fundchannel, payload: {'id': '02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5', 'amount': 999877, 'feerate': '253perkw', 'announce': True}, error: {'code': 303, 'message': 'Error broadcasting funding tx: error code: -27\\\\nerror message:\\\\nTransaction already in block chain. Unsent tx discarded 020000000001022f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360500000000fdffffff2f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360400000000fdffffff036e8501000000000016001473daa75958d5b2ddca87a6c279bb7cb307167037a1c62d0000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5455c150000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d81871173820247304402200939a3f094dbf21f3d6b36dca578601f31e1b61e86d3783f4ebd64b4b1ebe78202206429702a2e7c57ef0f2868d17744ddcf63334e8f9aa90454b9f97855490be072012102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee50247304402205fb99a0b718e201deb264bff0f93ffb7a74e24c8589679b18dba6453a1d1662102200ce4f83ff4bbc7a010b4c1d5c57ea29b23ca4c8cef2aca1e23e6b30203dd8f3a0121026957e53b46df017bd6460681d068e1d23a7b027de398272d0b15f59b78d060a966000000.', 'data': {'id': '02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5', 'method': 'openchannel_signed'}}

../../contrib/pyln-client/pyln/client/lightning.py:387: RpcError

I'm attaching this issue here because I want to look into it, but maybe this is an unrelated problem.

BTW, it requires more analysis

Code style to help the mantains the elegance of the code

Any time that I jump inside a repository I don't know if my editor has the correct configuration to write a code that respects the code style of the repository.

I open this issue to ask if a PR with an introduction of these tools is welcome. If yes, do you have any suggestions of what tools use?

I use in my small project a formatter called balck, it could be support all feature of python.

Thanks.

Add a method teardown

I noted during the testing of lnprototes that it create a work directory in the /tmp dir and it never delete it. I would like to propose to add a teardown method in the runner to delete all data produced at the end of the tests.

In addition, in case of failure bitcoin core is not stopped and I need to kill the process by hand.

If you would like, I like to work on this issue.

Thanks ๐Ÿ˜„

bolt2: failure to connect with the node, the runner did not receive `open_channel2`

With the patch https://github.com/ElementsProject/lightning/pull/5367/files the issue #31 is gone ๐Ÿ’ฏ

But sometime I receive the following error

self = ExpectMsg:test_bolt2-20-open_channel_accepter.py:2406
runner = <lnprototest.clightning.clightning.Runner object at 0x7f7e8354bee0>

    def action(self, runner: "Runner") -> bool:
        super().action(runner)
        conn = self.find_conn(runner)
        while True:
            binmsg = runner.get_output_message(conn, self)
            if binmsg is None:
>               raise EventError(
                    self, f"Did not receive a message {self.msgtype} from runner"
                )
E               lnprototest.errors.EventError: (ExpectMsg:test_bolt2-20-open_channel_accepter.py:2406, 'Did not receive a message msgtype-open_channel2 from runner')

lnprototest/event.py:318: EventError
---------------------------------------------- Captured stdout call -----------------------------------------------
signing our input for tx 02000000022f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360500000000fdffffff2f144a38afb7c3886d18f5283a8da92e79c7f6a24a64a5c7f9d5187ac2753f360000000000fdffffff03908201000000000016001473daa75958d5b2ddca87a6c279bb7cb30716703760df160000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5d8ba0d0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738266000000
Signing 1 redeemscript keys 03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 and 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a: 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae amount = 899800
tx: 0200000001acf33cb15a77827f6f7cfdc4d4a2d0bf8b06708f09a92b631b12f8edb1824e8102000000006d669280044a0100000000000022002047d040ee05dd47a80038faf7fa42e8559bfc8b60bd981410ad1d67d02dbe65e94a01000000000000220020c2c8616728753143bed607ea0b17e5ef615d05ada442dcd1613098597cb1ad09801a060000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01acfc94070000000000220020673a559ef5a5f20daa54be8b9b140457e12ae37f2f507b6f4a50aea6822eaf8850e05c20
witness is ...  CTxInWitness(CScriptWitness(x('304402202141ffe3d20751b2fb2978b5ab3340086b0b9547c4cf797ec51ed1dbad4b605f02206c83c26aaa3490aa21a68f4120fddff241aebf66fee095b7e78a564c286fe39301'),x('02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5')))
witnesses are [{witness_element=[{witness=304402202141ffe3d20751b2fb2978b5ab3340086b0b9547c4cf797ec51ed1dbad4b605f02206c83c26aaa3490aa21a68f4120fddff241aebf66fee095b7e78a564c286fe39301},{witness=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5}]}]
------------------------------------------------ Captured log call ------------------------------------------------
ERROR    concurrent.futures:_base.py:330 exception calling callback for <Future at 0x7f7e8354dd90 state=finished raised RpcError>
Traceback (most recent call last):
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 328, in _invoke_callbacks
    callback(self)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 359, in _done
    raise (exception)
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 345, in _run_rbf
    bump = runner.rpc.openchannel_bump(
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 1051, in openchannel_bump
    return self.call("openchannel_bump", payload)
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 387, in call
    raise RpcError(method, payload, resp['error'])
pyln.client.lightning.RpcError: RPC call failed: method: openchannel_bump, payload: {'channel_id': 'aa96b1189f7036d424df0081cca3f019181013f92b47668dfca1f60140370d58', 'amount': 498800, 'initialpsbt': 'cHNidP8BAFICAAAAAS8USjivt8OIbRj1KDqNqS55x/aiSmSlx/nVGHrCdT82AAAAAAD9////ATbjFgAAAAAAFgAUCdhZaR8I0hwzwR0e44WWaXkRiDsAAAAAAAEA/YUBAgAAAAABAYRZGlZyCqvIAjzs9xgBxeD50EnQxVCrQkEq0Spn2J86AAAAAAD+////B4CEHgAAAAAAFgAU/ZZY+9R20xjzuCWxUrFSqvpJvJJAQg8AAAAAABYAFINEBZYmgTLmyZ1E2uLRUdq9misjLBgKKQEAAAAWABTSlfdtojGXkfNt9XWeRbFdXhBSIcDGLQAAAAAAFgAUVNFK6RB5PpMNjjPT3gsMvwWqUzMACT0AAAAAABYAFBtC4fx7HNk6Rp+mftXqvzbONU3WIKEHAAAAAAAWABQGr9Rrzf0i75SsEiqhHyQSRKN+zICNWwAAAAAAIgAgALBo324OBULnds6l6+j18am0C1Md3Y6Usaf/mCm1u6oCRzBEAiA2e5v+0FZbrSE3Ek9zY3Nib6MTXlmyCntcHY8rjxsmuwIgL2ZN45eHCCo3bSIkh/Au8Z5FaWwEEESm1Xnuyrto6UUBIQNWYJqQSnAmxzkdP79xrZKgDgS0zS+2qNHmnLwJmPZpCmUAAAABAR+AhB4AAAAAABYAFP2WWPvUdtMY87glsVKxUqr6SbySAAA=', 'funding_feerate': '2031perkw'}, error: {'code': -1, 'message': 'Unexpected wire message 0048aa96b1189f7036d424df0081cca3f019181013f92b47668dfca1f60140370d580000000000079c7000000064000007ef'}
ERROR    concurrent.futures:_base.py:330 exception calling callback for <Future at 0x7f7e835682e0 state=finished raised RpcError>
Traceback (most recent call last):
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 328, in _invoke_callbacks
    callback(self)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 359, in _done
    raise (exception)
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 345, in _run_rbf
    bump = runner.rpc.openchannel_bump(
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 1051, in openchannel_bump
    return self.call("openchannel_bump", payload)
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 387, in call
    raise RpcError(method, payload, resp['error'])
pyln.client.lightning.RpcError: RPC call failed: method: openchannel_bump, payload: {'channel_id': 'aa96b1189f7036d424df0081cca3f019181013f92b47668dfca1f60140370d58', 'amount': 498800, 'initialpsbt': 'cHNidP8BAFICAAAAAS8USjivt8OIbRj1KDqNqS55x/aiSmSlx/nVGHrCdT82AAAAAAD9////ATbjFgAAAAAAFgAUUne/UQVzB3DqV23ok9TGrDCm23MAAAAAAAEA/YUBAgAAAAABAYRZGlZyCqvIAjzs9xgBxeD50EnQxVCrQkEq0Spn2J86AAAAAAD+////B4CEHgAAAAAAFgAU/ZZY+9R20xjzuCWxUrFSqvpJvJJAQg8AAAAAABYAFINEBZYmgTLmyZ1E2uLRUdq9misjLBgKKQEAAAAWABTSlfdtojGXkfNt9XWeRbFdXhBSIcDGLQAAAAAAFgAUVNFK6RB5PpMNjjPT3gsMvwWqUzMACT0AAAAAABYAFBtC4fx7HNk6Rp+mftXqvzbONU3WIKEHAAAAAAAWABQGr9Rrzf0i75SsEiqhHyQSRKN+zICNWwAAAAAAIgAgALBo324OBULnds6l6+j18am0C1Md3Y6Usaf/mCm1u6oCRzBEAiA2e5v+0FZbrSE3Ek9zY3Nib6MTXlmyCntcHY8rjxsmuwIgL2ZN45eHCCo3bSIkh/Au8Z5FaWwEEESm1Xnuyrto6UUBIQNWYJqQSnAmxzkdP79xrZKgDgS0zS+2qNHmnLwJmPZpCmUAAAABAR+AhB4AAAAAABYAFP2WWPvUdtMY87glsVKxUqr6SbySAAA=', 'funding_feerate': '2031perkw'}, error: {'code': -1, 'message': 'Owning subdaemon dualopend died (62208)'}
ERROR    concurrent.futures:_base.py:330 exception calling callback for <Future at 0x7f7e880247f0 state=finished raised RpcError>
Traceback (most recent call last):
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 328, in _invoke_callbacks
    callback(self)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 303, in _done
    raise exception
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/vincent/Github/lnprototest/lnprototest/clightning/clightning.py", line 296, in _fundchannel
    return runner.rpc.fundchannel(
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 730, in fundchannel
    return self.call("fundchannel", payload)
  File "/home/vincent/.cache/pypoetry/virtualenvs/lnprototest-AvqpilGs-py3.8/lib/python3.8/site-packages/pyln/client/lightning.py", line 387, in call
    raise RpcError(method, payload, resp['error'])
pyln.client.lightning.RpcError: RPC call failed: method: fundchannel, payload: {'id': '02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5', 'amount': 499800, 'feerate': '2000perkw', 'announce': True}, error: {'code': 400, 'message': 'Unable to connect, no address known for peer', 'data': {'id': '02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5', 'method': 'connect'}}
============================================= short test summary info =============================================
FAILED tests/test_bolt2-20-open_channel_accepter.py::test_rbf_opener_forgets - lnprototest.errors.EventError: (E...

Some tests are failing?

I wanted to give lnprototest a try to evaluate what changes would be needed on the eclair RPC to implement a runner, but I'm running into seemingly basic issues.

Is it expected that some tests are failing even with the dummy runner?

lnprototest

They're also all failing (but more slowly) with the clightning runner (using the latest commit on master), so I suspect that something's wrong with my installation (python is such a mess to get right for newbies...).

lnprototest2

I see these errors scattered in the output:

ValueError: ('Error waiting for {}', <function Runner.start.<locals>.<lambda> at 0x7fc82ec02b70>)
lnprototest.errors.SpecFileError: (Msg:test_bolt2-20-open_channel_accepter.py:71, 'Unknown msgtype open_channel2')
lnprototest.errors.SpecFileError: (ExpectMsg:test_bolt2-20-open_channel_accepter.py:216, 'Unknown msgtype tx_add_input')
AttributeError: 'PublicKey' object has no attribute 'secret'

test failure when closing with a wrong pub key

When we was going to close the channel with the wrong pub key, sometime we receive a spec violation from the tests

This are some logs


ERROR    root:helpers.py:170 Traceback (most recent call last):
  File "/work/lnprototest/tests/helpers.py", line 167, in run_runner
    runner.run(test)
  File "/work/lnprototest/lnprototest/runner.py", line 99, in run
    all_done = sequence.action(self)
  File "/work/lnprototest/lnprototest/structure.py", line 55, in action
    all_done &= e.action(runner)
  File "/work/lnprototest/lnprototest/event.py", line 342, in action
    raise EventError(
lnprototest.errors.EventError: `Got msg banned by {"event": "MustNotMsg", "file": "test_bolt2-01-close_channel.py", "pos": "156"}: 0026a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc7700160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5` on event [{"event": "ExpectMsg", "file": "test_bolt2-01-close_channel.py", "pos": "157"},]
=========================== short test summary info ============================
FAILED tests/test_bolt2-01-close_channel.py::test_close_channel_shutdown_msg_wrong_script_pubkey_receiver_side
================== 1 failed, 26 passed, 18 skipped in 50.88s ===================
make: *** [Makefile:14: check] Error 1

But core lightning log the correct message

2023-03-01T18:22:45.786Z DEBUG   lightningd: io_loop_with_timers: main
2023-03-01T18:22:45.787Z INFO    02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-chan#1: Peer transient failure in CHANNELD_NORMAL: Bad shutdown scriptpubkey 2102653a63d591390de0ff80830c1ec8c83b89a556d1e8e172c0181ff7ff807eae6eac
2023-03-01T18:22:45.787Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: Status closed, but not exited. Killing
2023-03-01T18:22:45.787Z DEBUG   0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798-hsmd: Got WIRE_HSMD_CUPDATE_SIG_REQ
2023-03-01T18:22:45.787Z DEBUG   connectd: REPLY WIRE_CONNECTD_START_SHUTDOWN_REPLY with 0 fds

failure test with `test_close_channel_shutdown_msg_wrong_script_pubkey_receiver_side`

23-04-26T20:52:00.703Z DEBUG   plugin-sql: Killing plugin: exited during normal operation
2023-04-26T20:52:00.703Z DEBUG   lightningd: io_break: destroy_plugin
2023-04-26T20:52:00.703Z DEBUG   lightningd: Command returned result after jcon close
2023-04-26T20:52:00.703Z DEBUG   connectd: Shutting down
2023-04-26T20:52:00.703Z DEBUG   gossipd: Shutting down
2023-04-26T20:52:00.703Z DEBUG   hsmd: Shutting down

ERROR    root:helpers.py:170 Traceback (most recent call last):
  File "/work/lnprototest/tests/helpers.py", line 167, in run_runner
    runner.run(test)
  File "/work/lnprototest/lnprototest/runner.py", line 99, in run
    all_done = sequence.action(self)
  File "/work/lnprototest/lnprototest/structure.py", line 55, in action
    all_done &= e.action(runner)
  File "/work/lnprototest/lnprototest/event.py", line 342, in action
    raise EventError(
lnprototest.errors.EventError: `Got msg banned by {"event": "MustNotMsg", "file": "test_bolt2-01-close_channel.py", "pos": "156"}: 0026a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc7700160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5` on event [{"event": "ExpectMsg", "file": "test_bolt2-01-close_channel.py", "pos": "157"},]
=========================== short test summary info ============================
FAILED tests/test_bolt2-01-close_channel.py::test_close_channel_shutdown_msg_wrong_script_pubkey_receiver_side

Some node logs

2023-04-26T20:51:59.889Z lightningd: "cln:getrawblockbyheight#78"[OUT] 
2023-04-26T20:51:59.916Z plugin-bcli: [IN] 7b226a736f6e727063223a22322e30222c226964223a22636c6e3a676574726177626c6f636b6279686569676874233738222c22726573756c74223a7b22626c6f636b68617368223a2236316138643738366238643332343532633061333963616264643533633866616634363636306538333834343234353338313839333861343531373331656132222c22626c6f636b223a223030303030303230663134306364653266343064326461373536623637306437333033666461323634613965373437306337613538656264363934383461333061663965663033316261346239623938356633323734356132613361613935383534383965363564313933666236643866623936646231353839333738316365333733323961646566643865343936346666666637663230303030303030303030313032303030303030303030313031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030306666666666666666303430313663303130316666666666666666303230306632303532613031303030303030313630303134346161303131376364633834333966636139653039363065386465353630386235633063643064363030303030303030303030303030303032363661323461613231613965646532663631633366373164316465666433666139393964666133363935333735356336393036383937393939363262343862656264383336393734653863663930313230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030227d7d0a0a
2023-04-26T20:51:59.916Z DEBUG   lightningd: Adding block 108: 61a8d786b8d32452c0a39cabdd53c8faf46660e838442453818938a451731ea2
2023-04-26T20:51:59.917Z lightningd: "cln:getrawblockbyheight#79"[OUT] 
2023-04-26T20:51:59.932Z plugin-bcli: [IN] 7b226a736f6e727063223a22322e30222c226964223a22636c6e3a676574726177626c6f636b6279686569676874233739222c22726573756c74223a7b22626c6f636b68617368223a6e756c6c2c22626c6f636b223a6e756c6c7d7d0a0a
2023-04-26T20:51:59.932Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-chan#1: Got depth change 0->6 for 77dc462589381b11b6cf4758249b384c26b197d35bd382fe1cf6139b836273a3
2023-04-26T20:51:59.932Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-chan#1: Funding tx 77dc462589381b11b6cf4758249b384c26b197d35bd382fe1cf6139b836273a3 depth 6 of 3
2023-04-26T20:51:59.932Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-chan#1: attempting update blockheight a37362839b13f61cfe82d35bd397b1264c389b24[5847](https://github.com/rustyrussell/lnprototest/actions/runs/4813210873/jobs/8569443494#step:3:5848)cfb6111b38892546dc77
2023-04-26T20:51:59.934Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-hsmd: Got WIRE_HSMD_CANNOUNCEMENT_SIG_REQ
2023-04-26T20:51:59.934Z DEBUG   gossipd: REPLY WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY with 0 fds
2023-04-26T20:51:59.934Z DEBUG   hsmd: Client: Received message 2 from client
2023-04-26T20:51:59.934Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: Exchanging announcement signatures.
2023-04-26T20:51:59.934Z 02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: [OUT] 0103a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc7700006700000100005ffb05bfb1ef2941cd26e02eea9bfcd6862a08dcfd58473cd1e7da879c2127d6650159c731ae07cd07ff00f4fe7d344aef7997384465f34d7c57add4795a7b09138c93afb2013c39f959e70a163c3d6d8128cf72f8ae143f87b9d1fd6bb0ad30321116b9c58d69fca9fb33c214f681b664e53d5640abc2fdb972dc62a5571053
2023-04-26T20:51:59.934Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: billboard: Channel ready for use. Waiting for their announcement signatures.
2023-04-26T20:51:59.935Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: billboard: Channel ready for use. Waiting for their announcement signatures.
2023-04-26T20:51:59.935Z DEBUG   gossipd: received private channel announcement from channeld for 103x1x0
2023-04-26T20:52:00.053Z lightningd: "cln:estimatefees#80"[OUT] 
2023-04-26T20:52:00.127Z plugin-bcli: [IN] 7b226a736f6e727063223a22322e30222c226d6574686f64223a226c6f67222c22706172616d73223a7b226c6576656c223a226465627567222c226d657373616765223a2246656572617465206d696e5f61636365707461626c65207261697365642066726f6d20353030207065726b6220746f20666c6f6f72206f662031303030227d7d0a0a7b226a736f6e727063223a22322e30222c226964223a22636c6e3a657374696d61746566656573233830222c22726573756c74223a7b226f70656e696e67223a313030302c226d757475616c5f636c6f7365223a313030302c22756e696c61746572616c5f636c6f7365223a313030302c2264656c617965645f746f5f7573223a313030302c2268746c635f7265736f6c7574696f6e223a313030302c2270656e616c7479223a313030302c226d696e5f61636365707461626c65223a313030302c226d61785f61636365707461626c65223a31303030302c226665657261746573223a5b7b22626c6f636b73223a322c2266656572617465223a313030307d2c7b22626c6f636b73223a362c2266656572617465223a313030307d2c7b22626c6f636b73223a31322c2266656572617465223a313030307d2c7b22626c6f636b73223a3130302c2266656572617465223a313030307d5d2c22666565726174655f666c6f6f72223a313030307d7d0a0a
2023-04-26T20:52:00.128Z DEBUG   plugin-bcli: Feerate min_acceptable raised from 500 perkb to floor of 1000
2023-04-26T20:52:00.665Z jsonrpc#17: [IN] 7b226a736f6e727063223a2022322e30222c20226d6574686f64223a2022676574696e666f222c2022706172616d73223a207b7d2c20226964223a20222d633a
2023-04-26T20:52:00.665Z jsonrpc#17: [IN] 676574696e666f233138227d
2023-04-26T20:52:00.665Z jsonrpc#17: "-c:getinfo#18"[IN] 
2023-04-26T20:52:00.665Z jsonrpc#17: [OUT] 7b226a736f6e727063223a22322e30222c226964223a222d633a676574696e666f233138222c22726573756c74223a7b226964223a22303237396265363637656639646362626163353561303632393563653837306230373032396266636462326463653238643935396632383135623136663831373938222c22616c696173223a2253494c454e54535041574e2d63312d322d67373832633137392d6d6f64646564222c22636f6c6f72223a22303237396265222c226e756d5f7065657273223a312c226e756d5f70656e64696e675f6368616e6e656c73223a302c226e756d5f6163746976655f6368616e6e656c73223a312c226e756d5f696e6163746976655f6368616e6e656c73223a302c2261646472657373223a5b5d2c2262696e64696e67223a5b7b2274797065223a2269707634222c2261646472657373223a223132372e302e302e31222c22706f7274223a34343736357d5d2c2276657273696f6e223a227632332e30357263312d322d67373832633137392d6d6f64646564222c22626c6f636b686569676874223a3130382c226e6574776f726b223a2272656774657374222c22666565735f636f6c6c65637465645f6d736174223a302c226c696768746e696e672d646972223a222f746d702f6c6e70742d636c2d6c5f683230706a5f2f6c696768746e696e67642f72656774657374222c226f75725f6665617475726573223a7b22696e6974223a223038613030303061303236396132222c226e6f6465223a223838613030303061303236396132222c226368616e6e656c223a22222c22696e766f696365223a223032303030303032303234313030227d7d7d0a0a
2023-04-26T20:52:00.672Z 02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: [IN] 0103a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc7700006700000100005ffb05bfb1ef2941cd26e02eea9bfcd6862a08dcfd58473cd1e7da879c2127d6650159c731ae07cd07ff00f4fe7d344aef7997384465f34d7c57add4795a7b09138c93afb2013c39f959e70a163c3d6d8128cf72f8ae143f87b9d1fd6bb0ad30321116b9c58d69fca9fb33c214f681b664e53d5640abc2fdb972dc62a5571053
2023-04-26T20:52:00.672Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: billboard: Channel ready for use. Channel announced.
2023-04-26T20:52:00.699Z 02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-chan#1: [IN] 0026a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc7700232102653a63d[5913](https://github.com/rustyrussell/lnprototest/actions/runs/4813210873/jobs/8569443494#step:3:5914)90de0ff80830c1ec8c83b89a556d1e8e172c0181ff7ff807eae6eac
2023-04-26T20:52:00.699Z jsonrpc#17: [IN] 7b226a736f6e727063223a2022322e30222c20226d6574686f64223a202273746f70222c2022706172616d73223a207b7d2c20226964223a20222d633a73746f
2023-04-26T20:52:00.699Z jsonrpc#17: [IN] 70233139227d
2023-04-26T20:52:00.699Z jsonrpc#17: "-c:stop#19"[IN] 
2023-04-26T20:52:00.700Z UNUSUAL lightningd: JSON-RPC shutdown
2023-04-26T20:52:00.700Z DEBUG   lightningd: io_break: start_json_stream
2023-04-26T20:52:00.700Z DEBUG   lightningd: io_loop_with_timers: main
2023-04-26T20:52:00.700Z INFO    02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-chan#1: Peer transient failure in CHANNELD_NORMAL: Bad shutdown scriptpubkey 2102653a63d591390de0ff80830c1ec8c83b89a556d1e8e172c0181ff7ff807eae6eac
2023-04-26T20:52:00.700Z DEBUG   02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9-channeld-

ExpectError Should check that connection is closed or not

I am making a LDK runner class to integrate LDK with Lnprototest. While running the BOLT#1 tests, I found out that the tests are failing because LDK is not sending an error message when the connection is closed because of protocol violations.

[RawMsg(bytes.fromhex("2710")), ExpectError()],

Here LDK, closes the connection when it receives unknown even message but it fails the test because it does not send any error message.

On checking BOLT#1, I found out that sending a message after protocol violation is something a node SHOULD do and its not a MUST.

A sending node:

    SHOULD send error for protocol violations or internal errors that make channels unusable or that make further communication unusable.

https://github.com/lightning/bolts/blob/master/01-messaging.md#requirements-2

While I will be working on adding the error msg in LDK, I think Lnprototest should check for all the MUSTs in BOLTs instead of SHOULDs to accommodate more lightning implementations.
Instead of checking for error messages it should check that the connection is closed and made unusable by the node.

The `has_option` method is really specific to C-Lightning

In the C-Lightning runner, the options dictionary contains strings that are really specific to how C-Lightning displays its features. This makes it difficult for other runners to use this as they have to format it in the same way C-Lightning does it.
The has_option method used inside the tests also checks for these specific C-Lightning strings.

bolt1: connection reset by peer

CI: https://github.com/rustyrussell/lnprototest/runs/7169458806?check_suite_focus=true

Stacktrace:

>       runner.run(test)
tests/test_bolt1-01-init.py:214: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
lnprototest/runner.py:104: in run
    self.post_check(sequence)
lnprototest/runner.py:91: in post_check
    self.disconnect(sequence, next(iter(self.conns.values())))
lnprototest/runner.py:82: in disconnect
    self.check_final_error(event, conn, conn.expected_error, conn.must_not_events)
lnprototest/clightning/clightning.py:424: in check_final_error
    binmsg = self.get_output_message(conn, event)
lnprototest/clightning/clightning.py:400: in get_output_message
    return fut.result(timeout)
/usr/lib/python3.8/concurrent/futures/_base.py:444: in result
    return self.__get_result()
/usr/lib/python3.8/concurrent/futures/_base.py:389: in __get_result
    raise self._exception
/usr/lib/python3.8/concurrent/futures/thread.py:57: in run
    result = self.fn(*self.args, **self.kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <pyln.proto.wire.LightningConnection object at 0x7f55a0f638b0>
    def read_message(self):
        with self.recv_lock:
>           lc = self.connection.recv(18)
E           ConnectionResetError: [Errno 104] Connection reset by peer
/usr/local/lib/python3.8/dist-packages/pyln/proto/wire.py:229: ConnectionResetError

bitcoin 23.x incompatibility

A summer of bitcoin guys that are working on ldk integration reported a wired error that I was able to reproduce with bitcoin core 23.x

self = Block:test_bolt7-20-query_channel_range.py:237, runner = <lnprototest.clightning.clightning.Runner object at 0x7fccff4dd060>

    def action(self, runner: "Runner") -> bool:
        super().action(runner)
        # Oops, did they ask us to produce a block with no predecessor?
        if runner.getblockheight() + 1 < self.blockheight:
>           raise SpecFileError(
                self,
                "Cannot generate block #{} at height {}".format(
                    self.blockheight, runner.getblockheight()
                ),
            )
E           lnprototest.errors.SpecFileError: (Block:test_bolt7-20-query_channel_range.py:237, 'Cannot generate block #102 at height 0')


gossip failure on cln with the new version of the protocol

This issue required more love in the description, but in the PR we receive the following failure ElementsProject/lightning#5592

DEBUG:lnprototest.runner:RUN c-lightning
___ external/lnprototest/tests/test_bolt7-01-channel_announcement-success.py ___
[gw0] linux -- Python 3.10.4 /usr/bin/python3
worker 'gw0' crashed while running 'external/lnprototest/tests/test_bolt7-01-channel_announcement-success.py::test_gossip'
__________ external/lnprototest/tests/test_bolt7-10-gossip-filter.py ___________
[gw1] linux -- Python 3.10.4 /usr/bin/python3
worker 'gw1' crashed while running 'external/lnprototest/tests/test_bolt7-10-gossip-filter.py::test_gossip_timestamp_filter'
=========================== short test summary info ============================
FAILED tests/test_bolt7-20-query_channel_range.py::test_query_channel_range
FAILED tests/test_bolt7-01-channel_announcement-success.py::test_gossip
FAILED tests/test_bolt7-10-gossip-filter.py::test_gossip_timestamp_filter
=================== 3 failed, 24 passed in 388.70s (0:06:28) ===================
make: *** [Makefile:458: check-protos] Error 1

Something to look inside it

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.