From 3e53c6e359223384ae56319c19cc48c914e375d6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 6 Apr 2023 09:03:24 +0930 Subject: [PATCH] onchaind: have lightningd create our penalty txs. Signed-off-by: Rusty Russell --- lightningd/onchain_control.c | 62 ++++++++++++++++++ onchaind/onchaind.c | 74 ++++++++++++--------- onchaind/onchaind_wire.csv | 10 +++ onchaind/test/run-grind_feerate-bug.c | 6 +- onchaind/test/run-grind_feerate.c | 6 +- tests/test_closing.py | 93 +++++++++++++++------------ tests/test_connection.py | 16 +++-- 7 files changed, 181 insertions(+), 86 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 1551a743d..beaba49e4 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -546,6 +546,10 @@ struct onchain_signing_info { struct { u64 commit_num; } htlc_timedout; + /* WIRE_ONCHAIND_SPEND_PENALTY */ + struct { + struct secret remote_per_commitment_secret; + } spend_penalty; } u; }; @@ -578,6 +582,19 @@ static u8 *sign_tx_to_us(const tal_t *ctx, info->channel->dbid); } +static u8 *sign_penalty(const tal_t *ctx, + const struct bitcoin_tx *tx, + const struct onchain_signing_info *info) +{ + assert(info->msgtype == WIRE_ONCHAIND_SPEND_PENALTY); + return towire_hsmd_sign_any_penalty_to_us(ctx, + &info->u.spend_penalty.remote_per_commitment_secret, + tx, info->wscript, + 0, + &info->channel->peer->id, + info->channel->dbid); +} + /* Matches bitcoin_witness_sig_and_element! */ static const struct onchain_witness_element ** onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness) @@ -791,6 +808,47 @@ static void handle_onchaind_spend_to_us(struct channel *channel, __func__); } +static void handle_onchaind_spend_penalty(struct channel *channel, + const u8 *msg) +{ + struct lightningd *ld = channel->peer->ld; + struct onchain_signing_info *info; + struct bitcoin_outpoint out; + struct amount_sat out_sats; + u32 initial_feerate; + u8 *stack_elem; + + info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_PENALTY); + /* We can always spend penalty txs immediately */ + info->minblock = 0; + if (!fromwire_onchaind_spend_penalty(info, msg, + &out, &out_sats, + &info->u.spend_penalty.remote_per_commitment_secret, + &stack_elem, + &info->wscript)) { + channel_internal_error(channel, "Invalid onchaind_spend_penalty %s", + tal_hex(tmpctx, msg)); + return; + } + /* info->stack_elem is const void * */ + info->stack_elem = stack_elem; + + /* FIXME: Be more sophisticated! */ + initial_feerate = penalty_feerate(ld->topology); + if (!initial_feerate) + initial_feerate = tx_feerate(channel->last_tx); + + /* FIXME: deadline for HTLCs is actually a bit longer, but for + * their output it's channel->our_config.to_self_delay after + * the commitment tx is mined. */ + info->deadline_block = *channel->close_blockheight + + channel->our_config.to_self_delay; + create_onchain_tx(channel, &out, out_sats, + 0, 0, + initial_feerate, sign_penalty, info, + __func__); +} + static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED) { enum onchaind_wire t = fromwire_peektype(msg); @@ -844,6 +902,10 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U handle_onchaind_spend_to_us(sd->channel, msg); break; + case WIRE_ONCHAIND_SPEND_PENALTY: + handle_onchaind_spend_penalty(sd->channel, msg); + break; + /* We send these, not receive them */ case WIRE_ONCHAIND_INIT: case WIRE_ONCHAIND_SPENT: diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index f767f5720..da9bcaa92 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -624,14 +625,6 @@ static u8 *remote_htlc_to_us(const tal_t *ctx, option_anchor_outputs); } -static u8 *penalty_to_us(const tal_t *ctx, - struct bitcoin_tx *tx, - const u8 *wscript) -{ - return towire_hsmd_sign_penalty_to_us(ctx, remote_per_commitment_secret, - tx, wscript); -} - /* * This covers: * 1. to-us output spend (` 0`) @@ -927,6 +920,17 @@ static void propose_resolution_to_master(struct tracked_output *out, queue_until_msg(tmpctx, WIRE_ONCHAIND_SPEND_CREATED)); } +/* Create and broadcast this tx now */ +static void propose_immediate_resolution(struct tracked_output *out, + const u8 *send_message TAKES, + enum tx_type tx_type) +{ + /* We add 1 to blockheight (meaning you can broadcast it now) to avoid + * having to check for < 0 in various places we print messages */ + propose_resolution_to_master(out, send_message, out->tx_blockheight+1, + tx_type); +} + static bool is_valid_sig(const u8 *e) { struct bitcoin_signature sig; @@ -1417,11 +1421,10 @@ static void steal_htlc_tx(struct tracked_output *out, enum tx_type htlc_tx_type, const struct bitcoin_outpoint *htlc_outpoint) { - struct bitcoin_tx *tx; - enum tx_type tx_type = OUR_PENALTY_TX; struct tracked_output *htlc_out; struct amount_asset asset; struct amount_sat htlc_out_amt; + const u8 *msg; u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[REMOTE], &keyset->self_revocation_key, @@ -1437,22 +1440,23 @@ static void steal_htlc_tx(struct tracked_output *out, htlc_out_amt, DELAYED_CHEAT_OUTPUT_TO_THEM, &out->htlc, wscript, NULL); + + /* mark commitment tx htlc output as 'resolved by them' */ + resolved_by_other(out, &htlc_tx->txid, htlc_tx_type); + /* BOLT #3: * * To spend this via penalty, the remote node uses a witness stack * ` 1` */ - tx = tx_to_us(htlc_out, penalty_to_us, htlc_out, - BITCOIN_TX_RBF_SEQUENCE, 0, - &ONE, sizeof(ONE), - htlc_out->wscript, - &tx_type, penalty_feerate); + msg = towire_onchaind_spend_penalty(NULL, + htlc_outpoint, htlc_out_amt, + remote_per_commitment_secret, + tal_dup(tmpctx, u8, &ONE), + htlc_out->wscript); - /* mark commitment tx htlc output as 'resolved by them' */ - resolved_by_other(out, &htlc_tx->txid, htlc_tx_type); - - /* annnd done! */ - propose_resolution(htlc_out, tx, 0, tx_type); + /* Spend this immediately. */ + propose_immediate_resolution(htlc_out, take(msg), OUR_PENALTY_TX); } static void onchain_annotate_txout(const struct bitcoin_outpoint *outpoint, @@ -1964,6 +1968,7 @@ static void wait_for_resolved(struct tracked_output **outs) case WIRE_ONCHAIND_ANNOTATE_TXIN: case WIRE_ONCHAIND_NOTIFY_COIN_MVT: case WIRE_ONCHAIND_SPEND_TO_US: + case WIRE_ONCHAIND_SPEND_PENALTY: break; } master_badmsg(-1, msg); @@ -2753,9 +2758,7 @@ static void handle_our_unilateral(const struct tx_parts *tx, * delay */ static void steal_to_them_output(struct tracked_output *out, u32 csv) { - u8 *wscript; - struct bitcoin_tx *tx; - enum tx_type tx_type = OUR_PENALTY_TX; + const u8 *wscript, *msg; /* BOLT #3: * @@ -2768,16 +2771,19 @@ static void steal_to_them_output(struct tracked_output *out, u32 csv) &keyset->self_revocation_key, &keyset->self_delayed_payment_key); - tx = tx_to_us(tmpctx, penalty_to_us, out, BITCOIN_TX_RBF_SEQUENCE, 0, - &ONE, sizeof(ONE), wscript, &tx_type, penalty_feerate); + msg = towire_onchaind_spend_penalty(NULL, + &out->outpoint, out->sat, + remote_per_commitment_secret, + tal_dup(tmpctx, u8, &ONE), + wscript); - propose_resolution(out, tx, 0, tx_type); + /* Spend this immediately. */ + propose_immediate_resolution(out, take(msg), OUR_PENALTY_TX); } static void steal_htlc(struct tracked_output *out) { - struct bitcoin_tx *tx; - enum tx_type tx_type = OUR_PENALTY_TX; + const u8 *msg; u8 der[PUBKEY_CMPR_LEN]; /* BOLT #3: @@ -2788,11 +2794,15 @@ static void steal_htlc(struct tracked_output *out) * */ pubkey_to_der(der, &keyset->self_revocation_key); - tx = tx_to_us(out, penalty_to_us, out, BITCOIN_TX_RBF_SEQUENCE, 0, - der, sizeof(der), out->wscript, &tx_type, - penalty_feerate); - propose_resolution(out, tx, 0, tx_type); + msg = towire_onchaind_spend_penalty(NULL, + &out->outpoint, out->sat, + remote_per_commitment_secret, + tal_dup_arr(tmpctx, u8, der, ARRAY_SIZE(der), 0), + out->wscript); + + /* Spend this immediately. */ + propose_immediate_resolution(out, take(msg), OUR_PENALTY_TX); } /* Tell wallet that we have discovered a UTXO from a to-remote output, diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 3c4048742..949dba431 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -149,6 +149,16 @@ msgdata,onchaind_spend_to_us,commit_num,u64, msgdata,onchaind_spend_to_us,wscript_len,u32, msgdata,onchaind_spend_to_us,wscript,u8,wscript_len +# We tell lightningd to create, sign and broadcast this penalty tx: +msgtype,onchaind_spend_penalty,5041 +msgdata,onchaind_spend_penalty,outpoint,bitcoin_outpoint, +msgdata,onchaind_spend_penalty,outpoint_amount,amount_sat, +msgdata,onchaind_spend_penalty,remote_per_commitment_secret,secret, +msgdata,onchaind_spend_penalty,stack_elem_len,u16, +msgdata,onchaind_spend_penalty,stack_elem,u8,stack_elem_len +msgdata,onchaind_spend_penalty,wscript_len,u32, +msgdata,onchaind_spend_penalty,wscript,u8,wscript_len + subtype,onchain_witness_element subtypedata,onchain_witness_element,is_signature,bool, subtypedata,onchain_witness_element,len,u32, diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index 460583c79..563de5830 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -243,9 +243,6 @@ void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) /* Generated stub for towire_hsmd_get_per_commitment_point */ u8 *towire_hsmd_get_per_commitment_point(const tal_t *ctx UNNEEDED, u64 n UNNEEDED) { fprintf(stderr, "towire_hsmd_get_per_commitment_point called!\n"); abort(); } -/* Generated stub for towire_hsmd_sign_delayed_payment_to_us */ -u8 *towire_hsmd_sign_delayed_payment_to_us(const tal_t *ctx UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const u8 *wscript UNNEEDED) -{ fprintf(stderr, "towire_hsmd_sign_delayed_payment_to_us called!\n"); abort(); } /* Generated stub for towire_hsmd_sign_penalty_to_us */ u8 *towire_hsmd_sign_penalty_to_us(const tal_t *ctx UNNEEDED, const struct secret *revocation_secret UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const u8 *wscript UNNEEDED) { fprintf(stderr, "towire_hsmd_sign_penalty_to_us called!\n"); abort(); } @@ -285,6 +282,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct /* Generated stub for towire_onchaind_notify_coin_mvt */ u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) { fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); } +/* Generated stub for towire_onchaind_spend_penalty */ +u8 *towire_onchaind_spend_penalty(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, const struct secret *remote_per_commitment_secret UNNEEDED, const u8 *stack_elem UNNEEDED, const u8 *wscript UNNEEDED) +{ fprintf(stderr, "towire_onchaind_spend_penalty called!\n"); abort(); } /* Generated stub for towire_onchaind_spend_to_us */ u8 *towire_onchaind_spend_to_us(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u32 minblock UNNEEDED, u64 commit_num UNNEEDED, const u8 *wscript UNNEEDED) { fprintf(stderr, "towire_onchaind_spend_to_us called!\n"); abort(); } diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index a1aa26fee..4ffdb889e 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -272,9 +272,6 @@ void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) /* Generated stub for towire_hsmd_get_per_commitment_point */ u8 *towire_hsmd_get_per_commitment_point(const tal_t *ctx UNNEEDED, u64 n UNNEEDED) { fprintf(stderr, "towire_hsmd_get_per_commitment_point called!\n"); abort(); } -/* Generated stub for towire_hsmd_sign_delayed_payment_to_us */ -u8 *towire_hsmd_sign_delayed_payment_to_us(const tal_t *ctx UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const u8 *wscript UNNEEDED) -{ fprintf(stderr, "towire_hsmd_sign_delayed_payment_to_us called!\n"); abort(); } /* Generated stub for towire_hsmd_sign_local_htlc_tx */ u8 *towire_hsmd_sign_local_htlc_tx(const tal_t *ctx UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const u8 *wscript UNNEEDED, bool option_anchor_outputs UNNEEDED) { fprintf(stderr, "towire_hsmd_sign_local_htlc_tx called!\n"); abort(); } @@ -317,6 +314,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct /* Generated stub for towire_onchaind_notify_coin_mvt */ u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) { fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); } +/* Generated stub for towire_onchaind_spend_penalty */ +u8 *towire_onchaind_spend_penalty(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, const struct secret *remote_per_commitment_secret UNNEEDED, const u8 *stack_elem UNNEEDED, const u8 *wscript UNNEEDED) +{ fprintf(stderr, "towire_onchaind_spend_penalty called!\n"); abort(); } /* Generated stub for towire_onchaind_spend_to_us */ u8 *towire_onchaind_spend_to_us(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u32 minblock UNNEEDED, u64 commit_num UNNEEDED, const u8 *wscript UNNEEDED) { fprintf(stderr, "towire_onchaind_spend_to_us called!\n"); abort(); } diff --git a/tests/test_closing.py b/tests/test_closing.py index 259ff7987..41c0ec3fd 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -582,22 +582,22 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): # l2 should spend all of the outputs (except to-us). # Could happen in any order, depending on commitment tx. - needle = l2.daemon.logsearch_start - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') - l2.daemon.logsearch_start = needle - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/THEIR_HTLC') + ((_, txid1, blocks1), (_, txid2, blocks2)) = \ + l2.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM', + 'OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/THEIR_HTLC') + assert blocks1 == 0 + assert blocks2 == 0 # FIXME: test HTLC tx race! - bitcoind.generate_block(100) + bitcoind.generate_block(100, wait_for_mempool=[txid1, txid2]) sync_blockheight(bitcoind, [l1, l2]) wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == []) # Do one last pass over the logs to extract the reactions l2 sent - l2.daemon.logsearch_start = needle needles = [ # The first needle will match, but since we don't have a direct output # for l2 it won't result in an output, hence the comment: @@ -708,11 +708,13 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): # l2 should spend all of the outputs (except to-us). # Could happen in any order, depending on commitment tx. needle = l2.daemon.logsearch_start - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') - l2.daemon.logsearch_start = needle - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/OUR_HTLC') + ((_, txid1, blocks1), (_, txid2, blocks2)) = \ + l2.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM', + 'OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/OUR_HTLC') + assert blocks1 == 0 + assert blocks2 == 0 l2.daemon.logsearch_start = needle l2.daemon.wait_for_log('Ignoring output.*: THEIR_REVOKED_UNILATERAL/OUTPUT_TO_US') @@ -720,7 +722,7 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): # FIXME: test HTLC tx race! # 100 blocks later, all resolved. - bitcoind.generate_block(100) + bitcoind.generate_block(100, wait_for_mempool=[txid1, txid2]) sync_blockheight(bitcoind, [l1, l2]) peer = only_one(l2.rpc.listpeers()["peers"]) @@ -1316,15 +1318,19 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams): # notes that they've successfully claimed to_local and the fulfilled htlc) l3.start() sync_blockheight(bitcoind, [l3]) - l3.daemon.wait_for_logs(['Propose handling THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_PENALTY_TX', - 'Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM ' - 'by OUR_PENALTY_TX', - 'Resolved THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_HTLC_FULFILL_TO_THEM', - 'Propose handling OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM' - ' by OUR_PENALTY_TX']) - l3.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM') - bitcoind.generate_block(1) + + txids = [] + for (_, txid, blocks) in l3.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/OUR_HTLC', + 'OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM', + 'OUR_PENALTY_TX', + 'OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM'): + assert blocks == 0 + txids.append(txid) + + # First one is already spent by their fulfill attempt + bitcoind.generate_block(1, wait_for_mempool=txids[1:]) l3.daemon.wait_for_log('Resolved OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM ' 'by our proposal OUR_PENALTY_TX') l2.daemon.wait_for_log('Unknown spend of OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') @@ -1518,31 +1524,34 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams): # notes that they've successfully claimed to_local and the fulfilled htlc) l3.start() sync_blockheight(bitcoind, [l3]) - l3.daemon.wait_for_logs(['Propose handling THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_PENALTY_TX', - 'Propose handling THEIR_REVOKED_UNILATERAL/THEIR_HTLC by OUR_PENALTY_TX', - 'Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM ' - 'by OUR_PENALTY_TX', + + txids = [] + for (_, txid, blocks) in l3.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/OUR_HTLC', + 'OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/THEIR_HTLC', + 'OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM', + 'OUR_PENALTY_TX', + 'OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM', + 'OUR_PENALTY_TX', + 'THEIR_HTLC_TIMEOUT_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM'): + assert blocks == 0 + txids.append(txid) + + # Unfortunately, only the last one succeeds, since they already took the rest! + bitcoind.generate_block(1, wait_for_mempool=txids[-1]) + # And they resolve (intermingled with the above in some cases) + l3.daemon.logsearch_start = 0 + l3.daemon.wait_for_logs(['Resolved THEIR_HTLC_TIMEOUT_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM ' + 'by our proposal OUR_PENALTY_TX', 'Resolved THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_HTLC_FULFILL_TO_THEM', - 'Propose handling OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM' - ' by OUR_PENALTY_TX', 'Resolved OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM ' 'by THEIR_DELAYED_CHEAT', 'Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM ' 'by THEIR_DELAYED_CHEAT', - 'Resolved THEIR_REVOKED_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM', - 'Propose handling THEIR_HTLC_TIMEOUT_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM by OUR_PENALTY_TX']) + 'Resolved THEIR_REVOKED_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM']) - # Make sure we've broadcast the tx we expect (other channels shutting down can create - # unrelated txs!) - - # In theory this could have occurred before all the previous loglines appeared. - l3.daemon.logsearch_start = 0 - line = l3.daemon.wait_for_log(r'Broadcasting OUR_PENALTY_TX \([0-9a-f]*\) to resolve THEIR_HTLC_TIMEOUT_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM') - tx = re.search(r'\(([0-9a-f]*)\)', line).group(1) - txid = bitcoind.rpc.decoderawtransaction(tx)['txid'] - bitcoind.generate_block(1, wait_for_mempool=[txid]) - l3.daemon.wait_for_log('Resolved THEIR_HTLC_TIMEOUT_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM ' - 'by our proposal OUR_PENALTY_TX') l2.daemon.wait_for_log('Unknown spend of OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US') # 100 blocks later, l3+l2 are both done diff --git a/tests/test_connection.py b/tests/test_connection.py index 8578429c8..5b9591a0a 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3782,9 +3782,11 @@ def test_upgrade_statickey_onchaind(node_factory, executor, bitcoind): bitcoind.rpc.sendrawtransaction(tx) bitcoind.generate_block(1) - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') - bitcoind.generate_block(100) + ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') + assert blocks == 0 + + bitcoind.generate_block(100, wait_for_mempool=txid) # This works even if they disconnect and listpeerchannels() is empty: wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == []) @@ -3807,9 +3809,11 @@ def test_upgrade_statickey_onchaind(node_factory, executor, bitcoind): bitcoind.rpc.sendrawtransaction(tx) bitcoind.generate_block(1) - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') - bitcoind.generate_block(100) + ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') + assert blocks == 0 + + bitcoind.generate_block(100, wait_for_mempool=txid) # This works even if they disconnect and listpeers() is empty: wait_for(lambda: len(l2.rpc.listpeerchannels()['channels']) == 0)