Browse Source

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>
ppa-0.6.1
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
43156643b4
  1. 1
      channeld/channel.c
  2. 5
      channeld/channel_wire.csv
  3. 1
      lightningd/channel.c
  4. 4
      lightningd/channel.h
  5. 30
      lightningd/channel_control.c
  6. 25
      lightningd/peer_control.c

1
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);

5
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

Can't render this file because it has a wrong number of fields in line 6.

1
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);

4
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,

30
lightningd/channel_control.c

@ -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:

25
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);
resolve_close_command(ld, channel, cooperative);
remove_sig(channel->last_tx);
}
remove_sig(channel->last_tx);
resolve_close_command(ld, channel, cooperative);
}
void channel_errmsg(struct channel *channel,

Loading…
Cancel
Save