mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +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 {
|
struct {
|
||||||
u64 commit_num;
|
u64 commit_num;
|
||||||
} htlc_timedout;
|
} htlc_timedout;
|
||||||
|
/* WIRE_ONCHAIND_SPEND_PENALTY */
|
||||||
|
struct {
|
||||||
|
struct secret remote_per_commitment_secret;
|
||||||
|
} spend_penalty;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -578,6 +582,19 @@ static u8 *sign_tx_to_us(const tal_t *ctx,
|
|||||||
info->channel->dbid);
|
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! */
|
/* 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)
|
||||||
@@ -791,6 +808,47 @@ static void handle_onchaind_spend_to_us(struct channel *channel,
|
|||||||
__func__);
|
__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)
|
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);
|
||||||
@@ -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);
|
handle_onchaind_spend_to_us(sd->channel, msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WIRE_ONCHAIND_SPEND_PENALTY:
|
||||||
|
handle_onchaind_spend_penalty(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:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <bitcoin/feerate.h>
|
#include <bitcoin/feerate.h>
|
||||||
#include <bitcoin/script.h>
|
#include <bitcoin/script.h>
|
||||||
|
#include <ccan/array_size/array_size.h>
|
||||||
#include <ccan/asort/asort.h>
|
#include <ccan/asort/asort.h>
|
||||||
#include <ccan/cast/cast.h>
|
#include <ccan/cast/cast.h>
|
||||||
#include <ccan/mem/mem.h>
|
#include <ccan/mem/mem.h>
|
||||||
@@ -624,14 +625,6 @@ static u8 *remote_htlc_to_us(const tal_t *ctx,
|
|||||||
option_anchor_outputs);
|
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:
|
* This covers:
|
||||||
* 1. to-us output spend (`<local_delayedsig> 0`)
|
* 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));
|
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)
|
static bool is_valid_sig(const u8 *e)
|
||||||
{
|
{
|
||||||
struct bitcoin_signature sig;
|
struct bitcoin_signature sig;
|
||||||
@@ -1417,11 +1421,10 @@ static void steal_htlc_tx(struct tracked_output *out,
|
|||||||
enum tx_type htlc_tx_type,
|
enum tx_type htlc_tx_type,
|
||||||
const struct bitcoin_outpoint *htlc_outpoint)
|
const struct bitcoin_outpoint *htlc_outpoint)
|
||||||
{
|
{
|
||||||
struct bitcoin_tx *tx;
|
|
||||||
enum tx_type tx_type = OUR_PENALTY_TX;
|
|
||||||
struct tracked_output *htlc_out;
|
struct tracked_output *htlc_out;
|
||||||
struct amount_asset asset;
|
struct amount_asset asset;
|
||||||
struct amount_sat htlc_out_amt;
|
struct amount_sat htlc_out_amt;
|
||||||
|
const u8 *msg;
|
||||||
|
|
||||||
u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[REMOTE],
|
u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[REMOTE],
|
||||||
&keyset->self_revocation_key,
|
&keyset->self_revocation_key,
|
||||||
@@ -1437,22 +1440,23 @@ static void steal_htlc_tx(struct tracked_output *out,
|
|||||||
htlc_out_amt,
|
htlc_out_amt,
|
||||||
DELAYED_CHEAT_OUTPUT_TO_THEM,
|
DELAYED_CHEAT_OUTPUT_TO_THEM,
|
||||||
&out->htlc, wscript, NULL);
|
&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:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
* To spend this via penalty, the remote node uses a witness stack
|
* To spend this via penalty, the remote node uses a witness stack
|
||||||
* `<revocationsig> 1`
|
* `<revocationsig> 1`
|
||||||
*/
|
*/
|
||||||
tx = tx_to_us(htlc_out, penalty_to_us, htlc_out,
|
msg = towire_onchaind_spend_penalty(NULL,
|
||||||
BITCOIN_TX_RBF_SEQUENCE, 0,
|
htlc_outpoint, htlc_out_amt,
|
||||||
&ONE, sizeof(ONE),
|
remote_per_commitment_secret,
|
||||||
htlc_out->wscript,
|
tal_dup(tmpctx, u8, &ONE),
|
||||||
&tx_type, penalty_feerate);
|
htlc_out->wscript);
|
||||||
|
|
||||||
/* mark commitment tx htlc output as 'resolved by them' */
|
/* Spend this immediately. */
|
||||||
resolved_by_other(out, &htlc_tx->txid, htlc_tx_type);
|
propose_immediate_resolution(htlc_out, take(msg), OUR_PENALTY_TX);
|
||||||
|
|
||||||
/* annnd done! */
|
|
||||||
propose_resolution(htlc_out, tx, 0, tx_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onchain_annotate_txout(const struct bitcoin_outpoint *outpoint,
|
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_ANNOTATE_TXIN:
|
||||||
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:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
master_badmsg(-1, msg);
|
master_badmsg(-1, msg);
|
||||||
@@ -2753,9 +2758,7 @@ static void handle_our_unilateral(const struct tx_parts *tx,
|
|||||||
* delay */
|
* delay */
|
||||||
static void steal_to_them_output(struct tracked_output *out, u32 csv)
|
static void steal_to_them_output(struct tracked_output *out, u32 csv)
|
||||||
{
|
{
|
||||||
u8 *wscript;
|
const u8 *wscript, *msg;
|
||||||
struct bitcoin_tx *tx;
|
|
||||||
enum tx_type tx_type = OUR_PENALTY_TX;
|
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
@@ -2768,16 +2771,19 @@ static void steal_to_them_output(struct tracked_output *out, u32 csv)
|
|||||||
&keyset->self_revocation_key,
|
&keyset->self_revocation_key,
|
||||||
&keyset->self_delayed_payment_key);
|
&keyset->self_delayed_payment_key);
|
||||||
|
|
||||||
tx = tx_to_us(tmpctx, penalty_to_us, out, BITCOIN_TX_RBF_SEQUENCE, 0,
|
msg = towire_onchaind_spend_penalty(NULL,
|
||||||
&ONE, sizeof(ONE), wscript, &tx_type, penalty_feerate);
|
&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)
|
static void steal_htlc(struct tracked_output *out)
|
||||||
{
|
{
|
||||||
struct bitcoin_tx *tx;
|
const u8 *msg;
|
||||||
enum tx_type tx_type = OUR_PENALTY_TX;
|
|
||||||
u8 der[PUBKEY_CMPR_LEN];
|
u8 der[PUBKEY_CMPR_LEN];
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
@@ -2788,11 +2794,15 @@ static void steal_htlc(struct tracked_output *out)
|
|||||||
* <revocation_sig> <revocationpubkey>
|
* <revocation_sig> <revocationpubkey>
|
||||||
*/
|
*/
|
||||||
pubkey_to_der(der, &keyset->self_revocation_key);
|
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,
|
/* 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_len,u32,
|
||||||
msgdata,onchaind_spend_to_us,wscript,u8,wscript_len
|
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
|
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,
|
||||||
|
|||||||
|
@@ -243,9 +243,6 @@ void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED)
|
|||||||
/* Generated stub for towire_hsmd_get_per_commitment_point */
|
/* Generated stub for towire_hsmd_get_per_commitment_point */
|
||||||
u8 *towire_hsmd_get_per_commitment_point(const tal_t *ctx UNNEEDED, u64 n UNNEEDED)
|
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(); }
|
{ 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 */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* 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_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 */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* Generated stub for towire_hsmd_get_per_commitment_point */
|
||||||
u8 *towire_hsmd_get_per_commitment_point(const tal_t *ctx UNNEEDED, u64 n UNNEEDED)
|
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(); }
|
{ 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 */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* 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_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 */
|
/* 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)
|
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(); }
|
{ 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).
|
# l2 should spend all of the outputs (except to-us).
|
||||||
# Could happen in any order, depending on commitment tx.
|
# Could happen in any order, depending on commitment tx.
|
||||||
needle = l2.daemon.logsearch_start
|
((_, txid1, blocks1), (_, txid2, blocks2)) = \
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
l2.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM',
|
||||||
l2.daemon.logsearch_start = needle
|
'OUR_PENALTY_TX',
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
|
||||||
'THEIR_REVOKED_UNILATERAL/THEIR_HTLC')
|
'THEIR_REVOKED_UNILATERAL/THEIR_HTLC')
|
||||||
|
assert blocks1 == 0
|
||||||
|
assert blocks2 == 0
|
||||||
|
|
||||||
# FIXME: test HTLC tx race!
|
# FIXME: test HTLC tx race!
|
||||||
|
|
||||||
bitcoind.generate_block(100)
|
bitcoind.generate_block(100, wait_for_mempool=[txid1, txid2])
|
||||||
|
|
||||||
sync_blockheight(bitcoind, [l1, l2])
|
sync_blockheight(bitcoind, [l1, l2])
|
||||||
wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == [])
|
wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == [])
|
||||||
|
|
||||||
# Do one last pass over the logs to extract the reactions l2 sent
|
# Do one last pass over the logs to extract the reactions l2 sent
|
||||||
l2.daemon.logsearch_start = needle
|
|
||||||
needles = [
|
needles = [
|
||||||
# The first needle will match, but since we don't have a direct output
|
# 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:
|
# 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).
|
# l2 should spend all of the outputs (except to-us).
|
||||||
# Could happen in any order, depending on commitment tx.
|
# Could happen in any order, depending on commitment tx.
|
||||||
needle = l2.daemon.logsearch_start
|
needle = l2.daemon.logsearch_start
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
((_, txid1, blocks1), (_, txid2, blocks2)) = \
|
||||||
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
l2.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
l2.daemon.logsearch_start = needle
|
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM',
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
'OUR_PENALTY_TX',
|
||||||
'THEIR_REVOKED_UNILATERAL/OUR_HTLC')
|
'THEIR_REVOKED_UNILATERAL/OUR_HTLC')
|
||||||
|
assert blocks1 == 0
|
||||||
|
assert blocks2 == 0
|
||||||
|
|
||||||
l2.daemon.logsearch_start = needle
|
l2.daemon.logsearch_start = needle
|
||||||
l2.daemon.wait_for_log('Ignoring output.*: THEIR_REVOKED_UNILATERAL/OUTPUT_TO_US')
|
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!
|
# FIXME: test HTLC tx race!
|
||||||
|
|
||||||
# 100 blocks later, all resolved.
|
# 100 blocks later, all resolved.
|
||||||
bitcoind.generate_block(100)
|
bitcoind.generate_block(100, wait_for_mempool=[txid1, txid2])
|
||||||
|
|
||||||
sync_blockheight(bitcoind, [l1, l2])
|
sync_blockheight(bitcoind, [l1, l2])
|
||||||
peer = only_one(l2.rpc.listpeers()["peers"])
|
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)
|
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
||||||
l3.start()
|
l3.start()
|
||||||
sync_blockheight(bitcoind, [l3])
|
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 '
|
txids = []
|
||||||
'by OUR_PENALTY_TX',
|
for (_, txid, blocks) in l3.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
'Resolved THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_HTLC_FULFILL_TO_THEM',
|
'THEIR_REVOKED_UNILATERAL/OUR_HTLC',
|
||||||
'Propose handling OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM'
|
'OUR_PENALTY_TX',
|
||||||
' by OUR_PENALTY_TX'])
|
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM',
|
||||||
l3.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
'OUR_PENALTY_TX',
|
||||||
'OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
'OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM'):
|
||||||
bitcoind.generate_block(1)
|
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 '
|
l3.daemon.wait_for_log('Resolved OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM '
|
||||||
'by our proposal OUR_PENALTY_TX')
|
'by our proposal OUR_PENALTY_TX')
|
||||||
l2.daemon.wait_for_log('Unknown spend of OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US')
|
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)
|
# notes that they've successfully claimed to_local and the fulfilled htlc)
|
||||||
l3.start()
|
l3.start()
|
||||||
sync_blockheight(bitcoind, [l3])
|
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',
|
txids = []
|
||||||
'Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM '
|
for (_, txid, blocks) in l3.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
'by 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',
|
'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 '
|
'Resolved OUR_HTLC_FULFILL_TO_THEM/DELAYED_CHEAT_OUTPUT_TO_THEM '
|
||||||
'by THEIR_DELAYED_CHEAT',
|
'by THEIR_DELAYED_CHEAT',
|
||||||
'Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM '
|
'Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM '
|
||||||
'by THEIR_DELAYED_CHEAT',
|
'by THEIR_DELAYED_CHEAT',
|
||||||
'Resolved THEIR_REVOKED_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM',
|
'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'])
|
|
||||||
|
|
||||||
# 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')
|
l2.daemon.wait_for_log('Unknown spend of OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US')
|
||||||
|
|
||||||
# 100 blocks later, l3+l2 are both done
|
# 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.rpc.sendrawtransaction(tx)
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1)
|
||||||
|
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
||||||
bitcoind.generate_block(100)
|
assert blocks == 0
|
||||||
|
|
||||||
|
bitcoind.generate_block(100, wait_for_mempool=txid)
|
||||||
# This works even if they disconnect and listpeerchannels() is empty:
|
# This works even if they disconnect and listpeerchannels() is empty:
|
||||||
wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == [])
|
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.rpc.sendrawtransaction(tx)
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1)
|
||||||
|
|
||||||
l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX',
|
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_PENALTY_TX',
|
||||||
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM')
|
||||||
bitcoind.generate_block(100)
|
assert blocks == 0
|
||||||
|
|
||||||
|
bitcoind.generate_block(100, wait_for_mempool=txid)
|
||||||
# This works even if they disconnect and listpeers() is empty:
|
# This works even if they disconnect and listpeers() is empty:
|
||||||
wait_for(lambda: len(l2.rpc.listpeerchannels()['channels']) == 0)
|
wait_for(lambda: len(l2.rpc.listpeerchannels()['channels']) == 0)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user