From af8d81edcccb80d947ca3f6e1a47539725846d90 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 19 Feb 2021 14:52:01 +1030 Subject: [PATCH 1/5] common/shutdown_scriptpubkey: extract shutdown scriptpubkey test. Signed-off-by: Rusty Russell --- common/Makefile | 1 + common/shutdown_scriptpubkey.c | 10 ++++++++++ common/shutdown_scriptpubkey.h | 21 +++++++++++++++++++++ lightningd/Makefile | 1 + lightningd/channel_control.c | 17 ++--------------- 5 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 common/shutdown_scriptpubkey.c create mode 100644 common/shutdown_scriptpubkey.h diff --git a/common/Makefile b/common/Makefile index b72c6695cbd6..dfc7ab9ccbc9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -71,6 +71,7 @@ COMMON_SRC_NOGEN := \ common/read_peer_msg.c \ common/route.c \ common/setup.c \ + common/shutdown_scriptpubkey.c \ common/socket_close.c \ common/sphinx.c \ common/status.c \ diff --git a/common/shutdown_scriptpubkey.c b/common/shutdown_scriptpubkey.c new file mode 100644 index 000000000000..8c7bcee24bc0 --- /dev/null +++ b/common/shutdown_scriptpubkey.c @@ -0,0 +1,10 @@ +#include +#include + +bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey) +{ + return is_p2pkh(scriptpubkey, NULL) + || is_p2sh(scriptpubkey, NULL) + || is_p2wpkh(scriptpubkey, NULL) + || is_p2wsh(scriptpubkey, NULL); +} diff --git a/common/shutdown_scriptpubkey.h b/common/shutdown_scriptpubkey.h new file mode 100644 index 000000000000..1e70e91fd0a3 --- /dev/null +++ b/common/shutdown_scriptpubkey.h @@ -0,0 +1,21 @@ +#ifndef LIGHTNING_COMMON_SHUTDOWN_SCRIPTPUBKEY_H +#define LIGHTNING_COMMON_SHUTDOWN_SCRIPTPUBKEY_H +#include "config.h" +#include + +/* BOLT #2: + * + * 1. `OP_DUP` `OP_HASH160` `20` 20-bytes `OP_EQUALVERIFY` `OP_CHECKSIG` + * (pay to pubkey hash), OR + * 2. `OP_HASH160` `20` 20-bytes `OP_EQUAL` (pay to script hash), OR + * 3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), OR + * 4. `OP_0` `32` 32-bytes (version 0 pay to witness script hash) + * + * A receiving node: + *... + * - if the `scriptpubkey` is not in one of the above forms: + * - SHOULD fail the connection. + */ +bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey); + +#endif /* LIGHTNING_COMMON_SHUTDOWN_SCRIPTPUBKEY_H */ diff --git a/lightningd/Makefile b/lightningd/Makefile index 497a01801d94..287ffb873ae9 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -120,6 +120,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/pseudorand.o \ common/random_select.o \ common/setup.o \ + common/shutdown_scriptpubkey.o \ common/sphinx.o \ common/status_wire.o \ common/timeout.o \ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index e871ef7d4bc8..325ba0031126 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -230,21 +231,7 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) tal_free(channel->shutdown_scriptpubkey[REMOTE]); channel->shutdown_scriptpubkey[REMOTE] = scriptpubkey; - /* BOLT #2: - * - * 1. `OP_DUP` `OP_HASH160` `20` 20-bytes `OP_EQUALVERIFY` `OP_CHECKSIG` - * (pay to pubkey hash), OR - * 2. `OP_HASH160` `20` 20-bytes `OP_EQUAL` (pay to script hash), OR - * 3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), OR - * 4. `OP_0` `32` 32-bytes (version 0 pay to witness script hash) - * - * A receiving node: - *... - * - if the `scriptpubkey` is not in one of the above forms: - * - SHOULD fail the connection. - */ - if (!is_p2pkh(scriptpubkey, NULL) && !is_p2sh(scriptpubkey, NULL) - && !is_p2wpkh(scriptpubkey, NULL) && !is_p2wsh(scriptpubkey, NULL)) { + if (!valid_shutdown_scriptpubkey(scriptpubkey)) { channel_fail_permanent(channel, REASON_PROTOCOL, "Bad shutdown scriptpubkey %s", From 1978b80f8bae19cd4b1c14e3b9db8dab4ec58fc2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 19 Feb 2021 14:52:02 +1030 Subject: [PATCH 2/5] openingd: check upfront shutdown script. The spec doesn't say to do this, but it makes sense, otherwise they'll never be able to mutually close the channel. Signed-off-by: Rusty Russell --- openingd/Makefile | 1 + openingd/openingd.c | 21 +++++++++++++++++---- tests/test_closing.py | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/openingd/Makefile b/openingd/Makefile index 0bb19556647b..f1dc699fe6e0 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -75,6 +75,7 @@ OPENINGD_COMMON_OBJS := \ common/pseudorand.o \ common/read_peer_msg.o \ common/setup.o \ + common/shutdown_scriptpubkey.o \ common/status.o \ common/status_wire.o \ common/subdaemon.o \ diff --git a/openingd/openingd.c b/openingd/openingd.c index 96ed7318615a..e06ce82cf204 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -321,6 +322,20 @@ static bool setup_channel_funder(struct state *state) return true; } +static void set_remote_upfront_shutdown(struct state *state, + u8 *shutdown_scriptpubkey STEALS) +{ + state->upfront_shutdown_script[REMOTE] + = tal_steal(state, shutdown_scriptpubkey); + + if (shutdown_scriptpubkey + && !valid_shutdown_scriptpubkey(shutdown_scriptpubkey)) + peer_failed_err(state->pps, + &state->channel_id, + "Unacceptable upfront_shutdown_script %s", + tal_hex(tmpctx, shutdown_scriptpubkey)); +} + /* We start the 'open a channel' negotation with the supplied peer, but * stop when we get to the part where we need the funding txid */ static u8 *funder_channel_start(struct state *state, u8 channel_flags) @@ -404,8 +419,7 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags) &state->channel_id, "Parsing accept_channel %s", tal_hex(msg, msg)); } - state->upfront_shutdown_script[REMOTE] - = tal_steal(state, accept_tlvs->upfront_shutdown_script); + set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); /* BOLT #2: * @@ -764,8 +778,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) peer_failed_err(state->pps, &state->channel_id, "Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg)); - state->upfront_shutdown_script[REMOTE] - = tal_steal(state, open_tlvs->upfront_shutdown_script); + set_remote_upfront_shutdown(state, open_tlvs->upfront_shutdown_script); /* BOLT #2: * diff --git a/tests/test_closing.py b/tests/test_closing.py index 7dc4727564bf..2a2a74a26fc8 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -2594,3 +2594,18 @@ def test_option_upfront_shutdown_script(node_factory, bitcoind, executor): l1.rpc.fundchannel(l2.info['id'], 1000000) l1.rpc.close(l2.info['id']) wait_for(lambda: sorted([c['state'] for c in only_one(l1.rpc.listpeers()['peers'])['channels']]) == ['CLOSINGD_COMPLETE', 'ONCHAIN', 'ONCHAIN']) + + +@unittest.skipIf(not DEVELOPER, "needs to set upfront_shutdown_script") +def test_invalid_upfront_shutdown_script(node_factory, bitcoind, executor): + l1, l2 = node_factory.line_graph(2, fundchannel=False) + + l1 = node_factory.get_node(start=False, allow_warning=True) + # Insist on upfront script we're not going to match. + l1.daemon.env["DEV_OPENINGD_UPFRONT_SHUTDOWN_SCRIPT"] = "76a91404b61f7dc1ea0dc99424464cc4064dc564d91e8988ac00" + l1.start() + + l2 = node_factory.get_node() + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + with pytest.raises(RpcError, match=r'Unacceptable upfront_shutdown_script'): + l1.fundchannel(l2, 1000000, False) From 25e5c651cc305468b32500d7e9f8f002c6d282eb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 19 Feb 2021 14:52:03 +1030 Subject: [PATCH 3/5] bitcoin/script: use script opcode constants from wally_script.h Signed-off-by: Rusty Russell --- bitcoin/script.c | 29 +---------------------------- bitcoin/script.h | 1 + 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index d69751c24578..2ca0e1da3b5b 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -11,35 +11,8 @@ #include #include -/* Some standard ops */ -#define OP_0 0x00 +/* To push 0-75 bytes onto stack. */ #define OP_PUSHBYTES(val) (val) -#define OP_PUSHDATA1 0x4C -#define OP_PUSHDATA2 0x4D -#define OP_PUSHDATA4 0x4E -#define OP_NOP 0x61 -#define OP_IF 0x63 -#define OP_NOTIF 0x64 -#define OP_ELSE 0x67 -#define OP_ENDIF 0x68 -#define OP_RETURN 0x6a -#define OP_2DROP 0x6d -#define OP_IFDUP 0x73 -#define OP_DEPTH 0x74 -#define OP_DROP 0x75 -#define OP_DUP 0x76 -#define OP_SWAP 0x7c -#define OP_EQUAL 0x87 -#define OP_EQUALVERIFY 0x88 -#define OP_SIZE 0x82 -#define OP_1SUB 0x8C -#define OP_ADD 0x93 -#define OP_CHECKSIG 0xAC -#define OP_CHECKSIGVERIFY 0xAD -#define OP_CHECKMULTISIG 0xAE -#define OP_HASH160 0xA9 -#define OP_CHECKSEQUENCEVERIFY 0xB2 -#define OP_CHECKLOCKTIMEVERIFY 0xB1 /* Bitcoin's OP_HASH160 is RIPEMD(SHA256()) */ static void hash160(struct ripemd160 *redeemhash, const void *mem, size_t len) diff --git a/bitcoin/script.h b/bitcoin/script.h index b424f45d7620..939ecdc9c332 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -5,6 +5,7 @@ #include "tx.h" #include #include +#include struct bitcoin_address; struct preimage; From bbe17fc21791a4c981b4322e9727f983ab83c7f3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 24 Feb 2021 13:23:12 +1030 Subject: [PATCH 4/5] common: support opt_shutdown_anysegwit checks (EXPERIMENTAL_FEATURES). Signed-off-by: Rusty Russell --- common/features.c | 9 +++- common/features.h | 6 +++ common/shutdown_scriptpubkey.c | 57 ++++++++++++++++++++++++- common/shutdown_scriptpubkey.h | 3 +- lightningd/channel_control.c | 5 ++- lightningd/lightningd.c | 1 + openingd/openingd.c | 6 ++- tests/test_closing.py | 78 ++++++++++++++++++++++++++++++++++ tests/test_misc.py | 1 + tests/utils.py | 4 ++ 10 files changed, 164 insertions(+), 6 deletions(-) diff --git a/common/features.c b/common/features.c index 9c1c73ea8e1b..fa8c20c8b881 100644 --- a/common/features.c +++ b/common/features.c @@ -78,6 +78,10 @@ static const struct feature_style feature_styles[] = { .copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT, [NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT, [CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } }, + { OPT_SHUTDOWN_ANYSEGWIT, + .copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT, + [NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT, + [CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } }, { OPT_DUAL_FUND, .copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT, [NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT, @@ -385,9 +389,12 @@ static const char *feature_name(const tal_t *ctx, size_t f) "option_basic_mpp", "option_support_large_channel", "option_anchor_outputs", + "option_anchors_zero_fee_htlc_tx", + NULL, + "option_shutdown_anysegwit", }; - if (f / 2 >= ARRAY_SIZE(fnames)) + if (f / 2 >= ARRAY_SIZE(fnames) || !fnames[f / 2]) return tal_fmt(ctx, "option_unknown_%zu/%s", COMPULSORY_FEATURE(f), (f & 1) ? "odd" : "even"); diff --git a/common/features.h b/common/features.h index e928a73c9133..a0ce2d2a7b74 100644 --- a/common/features.h +++ b/common/features.h @@ -113,6 +113,12 @@ u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES); #define OPT_LARGE_CHANNELS 18 #define OPT_ANCHOR_OUTPUTS 20 +/* BOLT-4e329271a358ee52bf43ddbd96776943c5d74508 #9: + * + * | 26/27 | `option_shutdown_anysegwit` |... IN ... + */ +#define OPT_SHUTDOWN_ANYSEGWIT 26 + /* BOLT-7b04b1461739c5036add61782d58ac490842d98b #9: * | 222/223 | `option_dual_fund` | ... IN9 ... */ diff --git a/common/shutdown_scriptpubkey.c b/common/shutdown_scriptpubkey.c index 8c7bcee24bc0..e875e60a9934 100644 --- a/common/shutdown_scriptpubkey.c +++ b/common/shutdown_scriptpubkey.c @@ -1,10 +1,63 @@ #include #include -bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey) +#include + +/* BOLT-4e329271a358ee52bf43ddbd96776943c5d74508 #2: + * 5. if (and only if) `option_shutdown_anysegwit` is negotiated: + * * `OP_1` through `OP_16` inclusive, followed by a single + * push of 2 to 40 bytes + * (witness program versions 1 through 16) + */ +static bool is_valid_witnessprog(const u8 *scriptpubkey) +{ + size_t pushlen; + + if (tal_bytelen(scriptpubkey) < 2) + return false; + + switch (scriptpubkey[0]) { + case OP_1: + case OP_2: + case OP_3: + case OP_4: + case OP_5: + case OP_6: + case OP_7: + case OP_8: + case OP_9: + case OP_10: + case OP_11: + case OP_12: + case OP_13: + case OP_14: + case OP_15: + case OP_16: + break; + default: + fprintf(stderr, "op = %u (invalid)\n", scriptpubkey[0]); + return false; + } + + pushlen = scriptpubkey[1]; + /* Must be all of the rest of scriptpubkey */ + if (2 + pushlen != tal_bytelen(scriptpubkey)) { + fprintf(stderr, "2 + %zu != %zu\n", pushlen, tal_bytelen(scriptpubkey)); + return false; + } + + if (!(pushlen >= 2 && pushlen <= 40)) + fprintf(stderr, "pushlen == %zu\n", pushlen); + + return pushlen >= 2 && pushlen <= 40; +} + +bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey, + bool anysegwit) { return is_p2pkh(scriptpubkey, NULL) || is_p2sh(scriptpubkey, NULL) || is_p2wpkh(scriptpubkey, NULL) - || is_p2wsh(scriptpubkey, NULL); + || is_p2wsh(scriptpubkey, NULL) + || (anysegwit && is_valid_witnessprog(scriptpubkey)); } diff --git a/common/shutdown_scriptpubkey.h b/common/shutdown_scriptpubkey.h index 1e70e91fd0a3..942a112eac8f 100644 --- a/common/shutdown_scriptpubkey.h +++ b/common/shutdown_scriptpubkey.h @@ -16,6 +16,7 @@ * - if the `scriptpubkey` is not in one of the above forms: * - SHOULD fail the connection. */ -bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey); +bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey, + bool anysegwit); #endif /* LIGHTNING_COMMON_SHUTDOWN_SCRIPTPUBKEY_H */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 325ba0031126..233227466e2a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -220,6 +220,9 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) { u8 *scriptpubkey; struct lightningd *ld = channel->peer->ld; + bool anysegwit = feature_negotiated(ld->our_features, + channel->peer->their_features, + OPT_SHUTDOWN_ANYSEGWIT); if (!fromwire_channeld_got_shutdown(channel, msg, &scriptpubkey)) { channel_internal_error(channel, "bad channel_got_shutdown %s", @@ -231,7 +234,7 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) tal_free(channel->shutdown_scriptpubkey[REMOTE]); channel->shutdown_scriptpubkey[REMOTE] = scriptpubkey; - if (!valid_shutdown_scriptpubkey(scriptpubkey)) { + if (!valid_shutdown_scriptpubkey(scriptpubkey, anysegwit)) { channel_fail_permanent(channel, REASON_PROTOCOL, "Bad shutdown scriptpubkey %s", diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index ff3df6bb354b..190e7301bb71 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -740,6 +740,7 @@ static struct feature_set *default_features(const tal_t *ctx) #if EXPERIMENTAL_FEATURES OPTIONAL_FEATURE(OPT_ANCHOR_OUTPUTS), OPTIONAL_FEATURE(OPT_ONION_MESSAGES), + OPTIONAL_FEATURE(OPT_SHUTDOWN_ANYSEGWIT), #endif }; diff --git a/openingd/openingd.c b/openingd/openingd.c index e06ce82cf204..07fe1aa395c0 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -325,11 +325,15 @@ static bool setup_channel_funder(struct state *state) static void set_remote_upfront_shutdown(struct state *state, u8 *shutdown_scriptpubkey STEALS) { + bool anysegwit = feature_negotiated(state->our_features, + state->their_features, + OPT_SHUTDOWN_ANYSEGWIT); + state->upfront_shutdown_script[REMOTE] = tal_steal(state, shutdown_scriptpubkey); if (shutdown_scriptpubkey - && !valid_shutdown_scriptpubkey(shutdown_scriptpubkey)) + && !valid_shutdown_scriptpubkey(shutdown_scriptpubkey, anysegwit)) peer_failed_err(state->pps, &state->channel_id, "Unacceptable upfront_shutdown_script %s", diff --git a/tests/test_closing.py b/tests/test_closing.py index 2a2a74a26fc8..2b35bfa00278 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -5,6 +5,7 @@ from utils import ( only_one, sync_blockheight, wait_for, DEVELOPER, TIMEOUT, account_balance, first_channel_id, basic_fee, TEST_NETWORK, + EXPERIMENTAL_FEATURES, ) import os @@ -2609,3 +2610,80 @@ def test_invalid_upfront_shutdown_script(node_factory, bitcoind, executor): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) with pytest.raises(RpcError, match=r'Unacceptable upfront_shutdown_script'): l1.fundchannel(l2, 1000000, False) + + +@unittest.skipIf(not DEVELOPER, "needs to set upfront_shutdown_script") +@pytest.mark.slow_test +def test_segwit_shutdown_script(node_factory, bitcoind, executor): + """ +Try a range of future segwit versions as shutdown scripts. We create many nodes, so this is quite slow under valgrind +""" + l1 = node_factory.get_node(allow_warning=True) + + # BOLT-4e329271a358ee52bf43ddbd96776943c5d74508 #2: + # 5. if (and only if) `option_shutdown_anysegwit` is negotiated: + # * `OP_1` through `OP_16` inclusive, followed by a single push of 2 to 40 bytes + # (witness program versions 1 through 16) + valid = ['51020000', '5128' + '00' * 0x28, + '52020000', '5228' + '00' * 0x28, + '53020000', '5328' + '00' * 0x28, + '54020000', '5428' + '00' * 0x28, + '55020000', '5528' + '00' * 0x28, + '56020000', '5628' + '00' * 0x28, + '57020000', '5728' + '00' * 0x28, + '58020000', '5828' + '00' * 0x28, + '59020000', '5928' + '00' * 0x28, + '5A020000', '5A28' + '00' * 0x28, + '5B020000', '5B28' + '00' * 0x28, + '5C020000', '5C28' + '00' * 0x28, + '5D020000', '5D28' + '00' * 0x28, + '5E020000', '5E28' + '00' * 0x28, + '5F020000', '5F28' + '00' * 0x28, + '60020000', '6028' + '00' * 0x28] + invalid = ['50020000', # Not OP_1-OP_16 + '61020000', # Not OP_1-OP_16 + '5102000000', # Extra bytes + '510100', # Too short + '5129' + '00' * 0x29] # Too long + + if EXPERIMENTAL_FEATURES: + xsuccess = valid + xfail = invalid + else: + xsuccess = [] + xfail = valid + invalid + + # More efficient to create them all up-front. + nodes = node_factory.get_nodes(len(xfail) + len(xsuccess)) + + # Give it one UTXO to spend for each node. + addresses = {} + for n in nodes: + addresses[l1.rpc.newaddr()['bech32']] = (10**6 + 100000) / 10**8 + bitcoind.rpc.sendmany("", addresses) + bitcoind.generate_block(1) + wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == len(addresses)) + + # FIXME: Since we don't support other non-v0 encodings, we need a protocol + # test for this (we're actually testing our upfront check, not the real + # shutdown one!), + for script in xsuccess: + # Insist on upfront script we're not going to match. + l1.stop() + l1.daemon.env["DEV_OPENINGD_UPFRONT_SHUTDOWN_SCRIPT"] = script + l1.start() + + l2 = nodes.pop() + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + l1.rpc.fundchannel(l2.info['id'], 10**6) + + for script in xfail: + # Insist on upfront script we're not going to match. + l1.stop() + l1.daemon.env["DEV_OPENINGD_UPFRONT_SHUTDOWN_SCRIPT"] = script + l1.start() + + l2 = nodes.pop() + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + with pytest.raises(RpcError, match=r'Unacceptable upfront_shutdown_script'): + l1.rpc.fundchannel(l2.info['id'], 10**6) diff --git a/tests/test_misc.py b/tests/test_misc.py index 1c35ff829758..ec88c19d73b9 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1894,6 +1894,7 @@ def test_list_features_only(node_factory): ] if EXPERIMENTAL_FEATURES: expected += ['option_anchor_outputs/odd'] + expected += ['option_shutdown_anysegwit/odd'] expected += ['option_unknown_102/odd'] assert features == expected diff --git a/tests/utils.py b/tests/utils.py index e91a92715e23..9f8cf046dda4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -26,6 +26,8 @@ def expected_peer_features(wumbo_channels=False, extra=[]): features += [103] # option_anchor_outputs features += [21] + # option_shutdown_anysegwit + features += [27] if wumbo_channels: features += [19] return hex_bits(features + extra) @@ -41,6 +43,8 @@ def expected_node_features(wumbo_channels=False, extra=[]): features += [103] # option_anchor_outputs features += [21] + # option_shutdown_anysegwit + features += [27] if wumbo_channels: features += [19] return hex_bits(features + extra) From 5905b530302c2c232811983b847464098885ce29 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 25 Feb 2021 13:22:27 +1030 Subject: [PATCH 5/5] pytest: reduce test to edgecases for CI. It's timing out, even though we disable valgrind. Signed-off-by: Rusty Russell --- tests/test_closing.py | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 2b35bfa00278..0a1c6130c02b 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -2,6 +2,7 @@ from flaky import flaky from pyln.client import RpcError from shutil import copyfile +from pyln.testing.utils import SLOW_MACHINE from utils import ( only_one, sync_blockheight, wait_for, DEVELOPER, TIMEOUT, account_balance, first_channel_id, basic_fee, TEST_NETWORK, @@ -2624,28 +2625,35 @@ def test_segwit_shutdown_script(node_factory, bitcoind, executor): # 5. if (and only if) `option_shutdown_anysegwit` is negotiated: # * `OP_1` through `OP_16` inclusive, followed by a single push of 2 to 40 bytes # (witness program versions 1 through 16) - valid = ['51020000', '5128' + '00' * 0x28, - '52020000', '5228' + '00' * 0x28, - '53020000', '5328' + '00' * 0x28, - '54020000', '5428' + '00' * 0x28, - '55020000', '5528' + '00' * 0x28, - '56020000', '5628' + '00' * 0x28, - '57020000', '5728' + '00' * 0x28, - '58020000', '5828' + '00' * 0x28, - '59020000', '5928' + '00' * 0x28, - '5A020000', '5A28' + '00' * 0x28, - '5B020000', '5B28' + '00' * 0x28, - '5C020000', '5C28' + '00' * 0x28, - '5D020000', '5D28' + '00' * 0x28, - '5E020000', '5E28' + '00' * 0x28, - '5F020000', '5F28' + '00' * 0x28, - '60020000', '6028' + '00' * 0x28] + edge_valid = ['51020000', '5128' + '00' * 0x28, + '60020000', '6028' + '00' * 0x28] + other_valid = ['52020000', '5228' + '00' * 0x28, + '53020000', '5328' + '00' * 0x28, + '54020000', '5428' + '00' * 0x28, + '55020000', '5528' + '00' * 0x28, + '56020000', '5628' + '00' * 0x28, + '57020000', '5728' + '00' * 0x28, + '58020000', '5828' + '00' * 0x28, + '59020000', '5928' + '00' * 0x28, + '5A020000', '5A28' + '00' * 0x28, + '5B020000', '5B28' + '00' * 0x28, + '5C020000', '5C28' + '00' * 0x28, + '5D020000', '5D28' + '00' * 0x28, + '5E020000', '5E28' + '00' * 0x28, + '5F020000', '5F28' + '00' * 0x28] + invalid = ['50020000', # Not OP_1-OP_16 '61020000', # Not OP_1-OP_16 '5102000000', # Extra bytes '510100', # Too short '5129' + '00' * 0x29] # Too long + # Don't stress CI; just test edge cases + if SLOW_MACHINE: + valid = edge_valid + else: + valid = edge_valid + other_valid + if EXPERIMENTAL_FEATURES: xsuccess = valid xfail = invalid