From 43156643b46a052e68d05e85dbd7ac555eac8599 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 17 Aug 2018 14:36:35 +0930 Subject: [PATCH] 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 --- channeld/channel.c | 1 + channeld/channel_wire.csv | 5 +++++ lightningd/channel.c | 1 + lightningd/channel.h | 4 ++++ lightningd/channel_control.c | 30 ++++++++++++++++++++++++++++++ lightningd/peer_control.c | 25 +++++++++++++++++++------ 6 files changed, 60 insertions(+), 6 deletions(-) diff --git a/channeld/channel.c b/channeld/channel.c index c0ae24644..75452bd99 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -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); diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 866f5c264..a6c2b2a53 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -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 + diff --git a/lightningd/channel.c b/lightningd/channel.c index 2c0afec0e..a3861a35c 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -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); diff --git a/lightningd/channel.h b/lightningd/channel.h index e0dd98ba5..80e1709fe 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -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, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 87917f10c..7b11ed62b 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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: diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7ac334101..7960c951a 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -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,