lightningd: message for channeld to tell us that channel risks penalty.

For option_data_loss_protect, the peer can prove to us that it's ahead;
it gives us the (hopefully honest!) per_commitment_point it will use,
and we make sure we don't broadcast the commitment transaction we have.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-08-17 14:36:35 +09:30 committed by Christian Decker
parent 18297a173c
commit 43156643b4
6 changed files with 60 additions and 6 deletions

View File

@ -2309,6 +2309,7 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNEL_GOT_SHUTDOWN:
case WIRE_CHANNEL_SHUTDOWN_COMPLETE:
case WIRE_CHANNEL_DEV_REENABLE_COMMIT_REPLY:
case WIRE_CHANNEL_FAIL_FALLEN_BEHIND:
break;
}
master_badmsg(-1, msg);

View File

@ -165,3 +165,8 @@ channel_feerates,1027
channel_feerates,,feerate,u32
channel_feerates,,min_feerate,u32
channel_feerates,,max_feerate,u32
# Peer presented proof it was from the future.
channel_fail_fallen_behind,1028
channel_fail_fallen_behind,,remote_per_commitment_point,struct pubkey

1 #include <common/cryptomsg.h>
165
166
167
168
169
170
171
172

View File

@ -231,6 +231,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->connected = connected;
channel->local_basepoints = *local_basepoints;
channel->local_funding_pubkey = *local_funding_pubkey;
channel->future_per_commitment_point = NULL;
list_add_tail(&peer->channels, &channel->list);
tal_add_destructor(channel, destroy_channel);

View File

@ -105,6 +105,10 @@ struct channel {
/* Does gossipd need to know if the owner dies? (ie. not onchaind) */
bool connected;
/* Do we have an "impossible" future per_commitment_point from
* peer via option_data_loss_protect? */
struct pubkey *future_per_commitment_point;
};
struct channel *new_channel(struct peer *peer, u64 dbid,

View File

@ -4,6 +4,7 @@
#include <common/memleak.h>
#include <common/timeout.h>
#include <common/utils.h>
#include <common/wire_error.h>
#include <errno.h>
#include <gossipd/gossip_constants.h>
#include <hsmd/gen_hsm_client_wire.h>
@ -101,6 +102,32 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg)
wallet_channel_save(ld->wallet, channel);
}
static void channel_fail_fallen_behind(struct channel *channel, const u8 *msg)
{
struct pubkey per_commitment_point;
struct channel_id cid;
if (!fromwire_channel_fail_fallen_behind(msg, &per_commitment_point)) {
channel_internal_error(channel,
"bad channel_fail_fallen_behind %s",
tal_hex(tmpctx, msg));
return;
}
/* FIXME: Save in db! */
channel->future_per_commitment_point
= tal_dup(channel, struct pubkey, &per_commitment_point);
/* We don't fail yet, since we want daemon to send them an error
* to trigger rebroadcasting. But make sure we set error now in
* case something else goes wrong! */
derive_channel_id(&cid,
&channel->funding_txid,
channel->funding_outnum);
channel->error = towire_errorfmt(channel, &cid,
"Catastrophic failure: please close channel");
}
static void peer_start_closingd_after_shutdown(struct channel *channel,
const u8 *msg,
const int *fds)
@ -147,6 +174,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
return 2;
peer_start_closingd_after_shutdown(sd->channel, msg, fds);
break;
case WIRE_CHANNEL_FAIL_FALLEN_BEHIND:
channel_fail_fallen_behind(sd->channel, msg);
break;
/* And we never get these from channeld. */
case WIRE_CHANNEL_INIT:

View File

@ -370,15 +370,28 @@ register_close_command(struct lightningd *ld,
void drop_to_chain(struct lightningd *ld, struct channel *channel,
bool cooperative)
{
sign_last_tx(channel);
/* BOLT #2:
*
* - if `next_remote_revocation_number` is greater than expected
* above, AND `your_last_per_commitment_secret` is correct for that
* `next_remote_revocation_number` minus 1:
* - MUST NOT broadcast its commitment transaction.
*/
if (channel->future_per_commitment_point && !cooperative) {
log_broken(channel->log,
"Cannot broadcast our commitment tx:"
" they have a future one");
} else {
sign_last_tx(channel);
/* Keep broadcasting until we say stop (can fail due to dup,
* if they beat us to the broadcast). */
broadcast_tx(ld->topology, channel, channel->last_tx, NULL);
/* Keep broadcasting until we say stop (can fail due to dup,
* if they beat us to the broadcast). */
broadcast_tx(ld->topology, channel, channel->last_tx, NULL);
remove_sig(channel->last_tx);
}
resolve_close_command(ld, channel, cooperative);
remove_sig(channel->last_tx);
}
void channel_errmsg(struct channel *channel,