mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
onchaind: have lightningd create our penalty txs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "config.h"
|
||||
#include <bitcoin/feerate.h>
|
||||
#include <bitcoin/script.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
@@ -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 (`<local_delayedsig> 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
|
||||
* `<revocationsig> 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)
|
||||
* <revocation_sig> <revocationpubkey>
|
||||
*/
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
@@ -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(); }
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user