onchaind: use lightningd to sign and broadcast htlc_success transactions.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2023-04-06 09:03:24 +09:30
parent 2f6be4e6bb
commit a9dfec0e71
8 changed files with 253 additions and 98 deletions

View File

@@ -99,6 +99,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/hsm_encryption.o \ common/hsm_encryption.o \
common/htlc_state.o \ common/htlc_state.o \
common/htlc_trim.o \ common/htlc_trim.o \
common/htlc_tx.o \
common/htlc_wire.o \ common/htlc_wire.o \
common/invoice_path_id.o \ common/invoice_path_id.o \
common/key_derive.o \ common/key_derive.o \

View File

@@ -3,6 +3,7 @@
#include <bitcoin/script.h> #include <bitcoin/script.h>
#include <ccan/cast/cast.h> #include <ccan/cast/cast.h>
#include <ccan/tal/str/str.h> #include <ccan/tal/str/str.h>
#include <common/htlc_tx.h>
#include <common/key_derive.h> #include <common/key_derive.h>
#include <common/psbt_keypath.h> #include <common/psbt_keypath.h>
#include <common/type_to_string.h> #include <common/type_to_string.h>
@@ -550,6 +551,12 @@ struct onchain_signing_info {
struct { struct {
struct secret remote_per_commitment_secret; struct secret remote_per_commitment_secret;
} spend_penalty; } spend_penalty;
/* WIRE_ONCHAIND_SPEND_HTLC_SUCCESS */
struct {
u64 commit_num;
struct bitcoin_signature remote_htlc_sig;
struct preimage preimage;
} htlc_success;
} u; } u;
}; };
@@ -595,6 +602,22 @@ static u8 *sign_penalty(const tal_t *ctx,
info->channel->dbid); info->channel->dbid);
} }
static u8 *sign_htlc_success(const tal_t *ctx,
const struct bitcoin_tx *tx,
const struct onchain_signing_info *info)
{
const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS);
assert(info->msgtype == WIRE_ONCHAIND_SPEND_HTLC_SUCCESS);
return towire_hsmd_sign_any_local_htlc_tx(ctx,
info->u.htlc_success.commit_num,
tx, info->wscript,
anchor_outputs,
0,
&info->channel->peer->id,
info->channel->dbid);
}
/* Matches bitcoin_witness_sig_and_element! */ /* Matches bitcoin_witness_sig_and_element! */
static const struct onchain_witness_element ** static const struct onchain_witness_element **
onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness) onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness)
@@ -613,6 +636,24 @@ onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness)
return cast_const2(const struct onchain_witness_element **, welements); return cast_const2(const struct onchain_witness_element **, welements);
} }
/* Matches bitcoin_witness_htlc_success_tx & bitcoin_witness_htlc_timeout_tx! */
static const struct onchain_witness_element **
onchain_witness_htlc_tx(const tal_t *ctx, u8 **witness)
{
struct onchain_witness_element **welements;
welements = tal_arr(ctx, struct onchain_witness_element *,
tal_count(witness));
for (size_t i = 0; i < tal_count(welements); i++) {
welements[i] = tal(welements, struct onchain_witness_element);
/* See bitcoin_witness_htlc_success_tx / bitcoin_witness_htlc_timeout_tx */
welements[i]->is_signature = (i == 1 || i == 2);
welements[i]->witness = tal_dup_talarr(welements[i], u8,
witness[i]);
}
return cast_const2(const struct onchain_witness_element **, welements);
}
/* Always sets *welements, returns tx. Sets *worthwhile to false if /* Always sets *welements, returns tx. Sets *worthwhile to false if
* it wasn't worthwhile at the given feerate (and it had to drop feerate). * it wasn't worthwhile at the given feerate (and it had to drop feerate).
* Returns NULL iff it called channel_internal_error(). * Returns NULL iff it called channel_internal_error().
@@ -717,6 +758,29 @@ static bool consider_onchain_rebroadcast(struct channel *channel,
return true; return true;
} }
static bool consider_onchain_htlc_tx_rebroadcast(struct channel *channel,
const struct bitcoin_tx **tx,
struct onchain_signing_info *info)
{
/* FIXME: Implement rbf! */
return true;
}
/* We want to mine a success tx before they can timeout */
static u32 htlc_incoming_deadline(const struct channel *channel, u64 htlc_id)
{
struct htlc_in *hin;
hin = find_htlc_in(channel->peer->ld->htlcs_in, channel, htlc_id);
if (!hin) {
log_broken(channel->log, "No htlc IN %"PRIu64", using infinite deadline",
htlc_id);
return infinite_block_deadline(channel->peer->ld->topology);
}
return hin->cltv_expiry - 1;
}
/* Create the onchain tx and tell onchaind about it */ /* Create the onchain tx and tell onchaind about it */
static void create_onchain_tx(struct channel *channel, static void create_onchain_tx(struct channel *channel,
const struct bitcoin_outpoint *out, const struct bitcoin_outpoint *out,
@@ -849,6 +913,80 @@ static void handle_onchaind_spend_penalty(struct channel *channel,
__func__); __func__);
} }
static void handle_onchaind_spend_htlc_success(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, fee;
u64 htlc_id;
u8 *htlc_wscript;
struct bitcoin_tx *tx;
u8 **witness;
struct bitcoin_signature sig;
const struct onchain_witness_element **welements;
const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_HTLC_SUCCESS);
info->minblock = 0;
if (!fromwire_onchaind_spend_htlc_success(info, msg,
&out, &out_sats, &fee,
&htlc_id,
&info->u.htlc_success.commit_num,
&info->u.htlc_success.remote_htlc_sig,
&info->u.htlc_success.preimage,
&info->wscript,
&htlc_wscript)) {
channel_internal_error(channel, "Invalid onchaind_spend_htlc_success %s",
tal_hex(tmpctx, msg));
return;
}
/* BOLT #3:
* * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout
*/
tx = htlc_tx(NULL, chainparams, &out, info->wscript, out_sats, htlc_wscript, fee,
0, anchor_outputs);
tal_free(htlc_wscript);
if (!tx) {
/* Can only happen if fee > out_sats */
channel_internal_error(channel, "Invalid onchaind_spend_htlc_success %s",
tal_hex(tmpctx, msg));
return;
}
/* FIXME: tell onchaind if HTLC is too small for current
* feerate! */
info->deadline_block = htlc_incoming_deadline(channel, htlc_id);
/* Now sign, and set witness */
msg = sign_htlc_success(NULL, tx, info);
if (!wire_sync_write(ld->hsm_fd, take(msg)))
fatal("Writing sign request to hsm");
msg = wire_sync_read(tmpctx, ld->hsm_fd);
if (!msg || !fromwire_hsmd_sign_tx_reply(msg, &sig))
fatal("Reading sign_tx_reply: %s", tal_hex(tmpctx, msg));
witness = bitcoin_witness_htlc_success_tx(NULL, &sig,
&info->u.htlc_success.remote_htlc_sig,
&info->u.htlc_success.preimage,
info->wscript);
welements = onchain_witness_htlc_tx(tmpctx, witness);
bitcoin_tx_input_set_witness(tx, 0, take(witness));
log_debug(channel->log, "Broadcast for onchaind tx %s",
type_to_string(tmpctx, struct bitcoin_tx, tx));
broadcast_tx(channel->peer->ld->topology,
channel, take(tx), NULL, false,
info->minblock, NULL,
consider_onchain_htlc_tx_rebroadcast, take(info));
msg = towire_onchaind_spend_created(NULL, true, welements);
subd_send_msg(channel->owner, take(msg));
}
static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED) static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED)
{ {
enum onchaind_wire t = fromwire_peektype(msg); enum onchaind_wire t = fromwire_peektype(msg);
@@ -906,6 +1044,10 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U
handle_onchaind_spend_penalty(sd->channel, msg); handle_onchaind_spend_penalty(sd->channel, msg);
break; break;
case WIRE_ONCHAIND_SPEND_HTLC_SUCCESS:
handle_onchaind_spend_htlc_success(sd->channel, msg);
break;
/* We send these, not receive them */ /* We send these, not receive them */
case WIRE_ONCHAIND_INIT: case WIRE_ONCHAIND_INIT:
case WIRE_ONCHAIND_SPENT: case WIRE_ONCHAIND_SPENT:

View File

@@ -550,14 +550,30 @@ static bool set_htlc_timeout_fee(struct bitcoin_tx *tx,
&keyset->other_htlc_key, remotesig); &keyset->other_htlc_key, remotesig);
} }
static void set_htlc_success_fee(struct bitcoin_tx *tx, static struct amount_sat get_htlc_success_fee(struct tracked_output *out)
const struct bitcoin_signature *remotesig,
const u8 *wscript)
{ {
static struct amount_sat fee = AMOUNT_SAT_INIT(UINT64_MAX); static struct amount_sat fee = AMOUNT_SAT_INIT(UINT64_MAX);
struct amount_sat amt;
struct amount_asset asset;
size_t weight; size_t weight;
struct amount_msat htlc_amount;
struct bitcoin_tx *tx;
/* We only grind once, since they're all equiv. */
if (!amount_sat_eq(fee, AMOUNT_SAT(UINT64_MAX)))
return fee;
if (!amount_sat_to_msat(&htlc_amount, out->sat))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Overflow in get_htlc_success_fee %s",
type_to_string(tmpctx,
struct amount_sat,
&out->sat));
tx = htlc_success_tx(tmpctx, chainparams,
&out->outpoint,
out->wscript,
htlc_amount,
to_self_delay[LOCAL],
0,
keyset, option_anchor_outputs);
/* BOLT #3: /* BOLT #3:
* *
@@ -574,45 +590,21 @@ static void set_htlc_success_fee(struct bitcoin_tx *tx,
weight = 703; weight = 703;
weight += elements_tx_overhead(chainparams, 1, 1); weight += elements_tx_overhead(chainparams, 1, 1);
if (amount_sat_eq(fee, AMOUNT_SAT(UINT64_MAX))) { if (!grind_htlc_tx_fee(&fee, tx, out->remote_htlc_sig,
if (!grind_htlc_tx_fee(&fee, tx, remotesig, wscript, weight)) out->wscript, weight)) {
status_failed(STATUS_FAIL_INTERNAL_ERROR, status_failed(STATUS_FAIL_INTERNAL_ERROR,
"htlc_success_fee can't be found " "htlc_success_fee can't be found "
"for tx %s (weight %zu, feerate %u-%u), signature %s, wscript %s", "for tx %s (weight %zu, feerate %u-%u), signature %s, wscript %s",
type_to_string(tmpctx, struct bitcoin_tx, type_to_string(tmpctx, struct bitcoin_tx, tx),
tx),
weight, weight,
min_possible_feerate, max_possible_feerate, min_possible_feerate, max_possible_feerate,
type_to_string(tmpctx, type_to_string(tmpctx,
struct bitcoin_signature, struct bitcoin_signature,
remotesig), out->remote_htlc_sig),
tal_hex(tmpctx, wscript)); tal_hex(tmpctx, out->wscript));
return;
} }
asset = bitcoin_tx_output_get_amount(tx, 0); return fee;
assert(amount_asset_is_main(&asset));
amt = amount_asset_to_sat(&asset);
if (!amount_sat_sub(&amt, amt, fee))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Cannot deduct htlc-success fee %s from tx %s",
type_to_string(tmpctx, struct amount_sat, &fee),
type_to_string(tmpctx, struct bitcoin_tx, tx));
bitcoin_tx_output_set_amount(tx, 0, amt);
bitcoin_tx_finalize(tx);
if (check_tx_sig(tx, 0, NULL, wscript,
&keyset->other_htlc_key, remotesig))
return;
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"htlc_success_fee %s failed sigcheck "
" for tx %s, signature %s, wscript %s",
type_to_string(tmpctx, struct amount_sat, &fee),
type_to_string(tmpctx, struct bitcoin_tx, tx),
type_to_string(tmpctx, struct bitcoin_signature, remotesig),
tal_hex(tmpctx, wscript));
} }
static u8 *remote_htlc_to_us(const tal_t *ctx, static u8 *remote_htlc_to_us(const tal_t *ctx,
@@ -1745,14 +1737,12 @@ static void handle_preimage(struct tracked_output **outs,
size_t i; size_t i;
struct sha256 sha; struct sha256 sha;
struct ripemd160 ripemd; struct ripemd160 ripemd;
u8 **witness;
sha256(&sha, preimage, sizeof(*preimage)); sha256(&sha, preimage, sizeof(*preimage));
ripemd160(&ripemd, &sha, sizeof(sha)); ripemd160(&ripemd, &sha, sizeof(sha));
for (i = 0; i < tal_count(outs); i++) { for (i = 0; i < tal_count(outs); i++) {
struct bitcoin_tx *tx; struct bitcoin_tx *tx;
struct bitcoin_signature sig;
if (outs[i]->output_type != THEIR_HTLC) if (outs[i]->output_type != THEIR_HTLC)
continue; continue;
@@ -1788,29 +1778,29 @@ static void handle_preimage(struct tracked_output **outs,
* HTLC-success transaction. * HTLC-success transaction.
*/ */
if (outs[i]->remote_htlc_sig) { if (outs[i]->remote_htlc_sig) {
struct amount_msat htlc_amount; struct amount_sat fee;
if (!amount_sat_to_msat(&htlc_amount, outs[i]->sat)) const u8 *msg;
status_failed(STATUS_FAIL_INTERNAL_ERROR, const u8 *htlc_wscript;
"Overflow in output %zu %s",
i, /* FIXME: lightningd could derive this itself? */
type_to_string(tmpctx, htlc_wscript = bitcoin_wscript_htlc_tx(tmpctx,
struct amount_sat,
&outs[i]->sat));
tx = htlc_success_tx(outs[i], chainparams,
&outs[i]->outpoint,
outs[i]->wscript,
htlc_amount,
to_self_delay[LOCAL], to_self_delay[LOCAL],
0, &keyset->self_revocation_key,
keyset, option_anchor_outputs); &keyset->self_delayed_payment_key);
set_htlc_success_fee(tx, outs[i]->remote_htlc_sig,
outs[i]->wscript); fee = get_htlc_success_fee(outs[i]);
hsm_sign_local_htlc_tx(tx, outs[i]->wscript, &sig); msg = towire_onchaind_spend_htlc_success(NULL,
witness = bitcoin_witness_htlc_success_tx( &outs[i]->outpoint,
tx, &sig, outs[i]->remote_htlc_sig, preimage, outs[i]->sat,
outs[i]->wscript); fee,
bitcoin_tx_input_set_witness(tx, 0, take(witness)); outs[i]->htlc.id,
propose_resolution(outs[i], tx, 0, OUR_HTLC_SUCCESS_TX); commit_num,
outs[i]->remote_htlc_sig,
preimage,
outs[i]->wscript,
htlc_wscript);
propose_immediate_resolution(outs[i], take(msg),
OUR_HTLC_SUCCESS_TX);
} else { } else {
enum tx_type tx_type = THEIR_HTLC_FULFILL_TO_US; enum tx_type tx_type = THEIR_HTLC_FULFILL_TO_US;
@@ -1969,6 +1959,7 @@ static void wait_for_resolved(struct tracked_output **outs)
case WIRE_ONCHAIND_NOTIFY_COIN_MVT: case WIRE_ONCHAIND_NOTIFY_COIN_MVT:
case WIRE_ONCHAIND_SPEND_TO_US: case WIRE_ONCHAIND_SPEND_TO_US:
case WIRE_ONCHAIND_SPEND_PENALTY: case WIRE_ONCHAIND_SPEND_PENALTY:
case WIRE_ONCHAIND_SPEND_HTLC_SUCCESS:
break; break;
} }
master_badmsg(-1, msg); master_badmsg(-1, msg);

View File

@@ -159,6 +159,20 @@ msgdata,onchaind_spend_penalty,stack_elem,u8,stack_elem_len
msgdata,onchaind_spend_penalty,wscript_len,u32, msgdata,onchaind_spend_penalty,wscript_len,u32,
msgdata,onchaind_spend_penalty,wscript,u8,wscript_len msgdata,onchaind_spend_penalty,wscript,u8,wscript_len
# We tell lightningd to create, sign and broadcast this htlc_success tx:
msgtype,onchaind_spend_htlc_success,5042
msgdata,onchaind_spend_htlc_success,outpoint,bitcoin_outpoint,
msgdata,onchaind_spend_htlc_success,outpoint_amount,amount_sat,
msgdata,onchaind_spend_htlc_success,fee,amount_sat,
msgdata,onchaind_spend_htlc_success,htlc_id,u64,
msgdata,onchaind_spend_htlc_success,commit_num,u64,
msgdata,onchaind_spend_htlc_success,remote_htlc_sig,bitcoin_signature,
msgdata,onchaind_spend_htlc_success,preimage,preimage,
msgdata,onchaind_spend_htlc_success,wscript_len,u32,
msgdata,onchaind_spend_htlc_success,wscript,u8,wscript_len
msgdata,onchaind_spend_htlc_success,htlc_wscript_len,u32,
msgdata,onchaind_spend_htlc_success,htlc_wscript,u8,htlc_wscript_len
subtype,onchain_witness_element subtype,onchain_witness_element
subtypedata,onchain_witness_element,is_signature,bool, subtypedata,onchain_witness_element,is_signature,bool,
subtypedata,onchain_witness_element,len,u32, subtypedata,onchain_witness_element,len,u32,
1 #include <bitcoin/tx_parts.h>
159 # so it doesn't wait forever!
160 msgtype,onchaind_spend_created,5140
161 msgdata,onchaind_spend_created,expect_to_succeed,bool,
162 msgdata,onchaind_spend_created,num_witnesses,u32,
163 msgdata,onchaind_spend_created,witness,onchain_witness_element,num_witnesses
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

View File

@@ -282,6 +282,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
/* Generated stub for towire_onchaind_notify_coin_mvt */ /* 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) 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(); } { fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
/* Generated stub for towire_onchaind_spend_htlc_success */
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
/* Generated stub for towire_onchaind_spend_penalty */ /* 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) 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(); } { fprintf(stderr, "towire_onchaind_spend_penalty called!\n"); abort(); }

View File

@@ -314,6 +314,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
/* Generated stub for towire_onchaind_notify_coin_mvt */ /* 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) 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(); } { fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
/* Generated stub for towire_onchaind_spend_htlc_success */
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
/* Generated stub for towire_onchaind_spend_penalty */ /* 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) 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(); } { fprintf(stderr, "towire_onchaind_spend_penalty called!\n"); abort(); }

View File

@@ -1299,17 +1299,16 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams):
# l2 moves on for closed l3 # l2 moves on for closed l3
bitcoind.generate_block(1) bitcoind.generate_block(1)
l2.daemon.wait_for_log('to ONCHAIN') l2.daemon.wait_for_log('to ONCHAIN')
needle = l2.daemon.logsearch_start
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks')
l2.wait_for_onchaind_broadcast('OUR_HTLC_SUCCESS_TX',
'OUR_UNILATERAL/THEIR_HTLC')
l2.daemon.logsearch_start = needle
((_, _, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', ((_, txid1, blocks1), (_, _, blocks2)) = \
l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
'OUR_UNILATERAL/THEIR_HTLC',
'OUR_DELAYED_RETURN_TO_WALLET',
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US') 'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks1 == 0
assert blocks2 == 4
bitcoind.generate_block(1) bitcoind.generate_block(1, wait_for_mempool=txid1)
((_, _, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', ((_, _, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') 'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks == 4
@@ -1501,13 +1500,13 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams):
# l2 moves on for closed l3 # l2 moves on for closed l3
bitcoind.generate_block(1, wait_for_mempool=1) bitcoind.generate_block(1, wait_for_mempool=1)
l2.daemon.wait_for_log('to ONCHAIN') l2.daemon.wait_for_log('to ONCHAIN')
l2.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX .* after 16 blocks', l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX .* after 16 blocks')
'Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks'])
l2.wait_for_onchaind_broadcast('OUR_HTLC_SUCCESS_TX', ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
'OUR_UNILATERAL/THEIR_HTLC') 'OUR_UNILATERAL/THEIR_HTLC')
assert blocks == 0
bitcoind.generate_block(1, wait_for_mempool=1) bitcoind.generate_block(1, wait_for_mempool=txid)
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') 'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks == 4
@@ -2253,17 +2252,17 @@ def test_onchain_middleman_simple(node_factory, bitcoind):
l1.daemon.wait_for_log(' to ONCHAIN') l1.daemon.wait_for_log(' to ONCHAIN')
l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC') l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC')
needle = l2.daemon.logsearch_start
# l2 should fulfill HTLC onchain, and spend to-us (any order) # l2 should fulfill HTLC onchain, and spend to-us (any order)
l2.wait_for_onchaind_broadcast('OUR_HTLC_SUCCESS_TX', ((_, txid1, blocks1), (_, txid2, blocks2)) = \
'OUR_UNILATERAL/THEIR_HTLC') l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
l2.daemon.logsearch_start = needle 'OUR_UNILATERAL/THEIR_HTLC',
((_, txid1, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', 'OUR_DELAYED_RETURN_TO_WALLET',
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US') 'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks1 == 0
assert blocks2 == 4
# Payment should succeed. # Payment should succeed.
l1.bitcoin.generate_block(1, wait_for_mempool=1) l1.bitcoin.generate_block(1, wait_for_mempool=txid1)
l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage') l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage')
err = q.get(timeout=10) err = q.get(timeout=10)
if err: if err:
@@ -2272,16 +2271,16 @@ def test_onchain_middleman_simple(node_factory, bitcoind):
t.join(timeout=1) t.join(timeout=1)
assert not t.is_alive() assert not t.is_alive()
((_, txid2, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', ((_, txid3, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') 'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks == 4
# Four more, l2 can spend to-us, and we can spend htlc tx. # Four more, l2 can spend to-us, and we can spend htlc tx.
bitcoind.generate_block(3) bitcoind.generate_block(3)
bitcoind.generate_block(1, wait_for_mempool=txid1) bitcoind.generate_block(1, wait_for_mempool=txid2)
# 100 blocks after last spend, l2 should be done. # 100 blocks after last spend, l2 should be done.
l1.bitcoin.generate_block(100, wait_for_mempool=txid2) l1.bitcoin.generate_block(100, wait_for_mempool=txid3)
l2.daemon.wait_for_log('onchaind complete, forgetting peer') l2.daemon.wait_for_log('onchaind complete, forgetting peer')
# Verify accounting for l1 & l2 # Verify accounting for l1 & l2
@@ -3115,9 +3114,10 @@ def test_permfail_htlc_in(node_factory, bitcoind, executor):
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks') l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks')
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) after 6 blocks') l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) after 6 blocks')
# l2 then gets preimage, uses it instead of ignoring # l2 then gets preimage, uses it instead of ignoring
l2.wait_for_onchaind_broadcast('OUR_HTLC_SUCCESS_TX', ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
'OUR_UNILATERAL/THEIR_HTLC') 'OUR_UNILATERAL/THEIR_HTLC')
bitcoind.generate_block(1) assert blocks == 0
bitcoind.generate_block(1, wait_for_mempool=txid)
# OK, l1 sees l2 fulfill htlc. # OK, l1 sees l2 fulfill htlc.
l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage') l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage')

View File

@@ -427,9 +427,10 @@ def test_htlc_in_timeout(node_factory, bitcoind, executor):
l1.daemon.wait_for_log(' to ONCHAIN') l1.daemon.wait_for_log(' to ONCHAIN')
# L2 will collect HTLC (iff no shadow route) # L2 will collect HTLC (iff no shadow route)
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks') ((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
l2.daemon.wait_for_log('sendrawtx exit 0') 'OUR_UNILATERAL/THEIR_HTLC')
bitcoind.generate_block(1, wait_for_mempool=1) assert blocks == 0
bitcoind.generate_block(1, wait_for_mempool=txid)
((rawtx, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET', ((rawtx, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') 'OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
assert blocks == 4 assert blocks == 4