Skip to content

Update emergency.recover after every 'commitment_revocation' so that user can sweep funds by penalty transaction. #7772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 44 additions & 15 deletions common/scb_wire.csv
Original file line number Diff line number Diff line change
@@ -1,23 +1,52 @@
#include <common/node_id.h>
#include <bitcoin/tx.h>
#include <ccan/crypto/shachain/shachain.h>
#include <common/amount.h>
#include <common/channel_id.h>
#include <common/wireaddr.h>
#include <common/channel_type.h>
#include <common/amount.h>
#include <bitcoin/tx.h>
#include <common/derive_basepoints.h>
#include <common/htlc_wire.h>
#include <common/node_id.h>
#include <common/wireaddr.h>

tlvtype,scb_tlvs,shachain,1,
tlvdata,scb_tlvs,shachain,their_shachain,shachain,
tlvtype,scb_tlvs,basepoints,3,
tlvdata,scb_tlvs,basepoints,their_basepoint,basepoints,
tlvtype,scb_tlvs,opener,5,
tlvdata,scb_tlvs,opener,opener,enum side,
tlvtype,scb_tlvs,remote_to_self_delay,7,
tlvdata,scb_tlvs,remote_to_self_delay,remote_to_self_delay,u16,

# scb_chan stores min. info required to sweep the peer's force close.
subtype,scb_chan
subtypedata,scb_chan,id,u64,
subtypedata,scb_chan,cid,channel_id,
subtypedata,scb_chan,node_id,node_id,
subtypedata,scb_chan,unused,u8,
subtypedata,scb_chan,addr,wireaddr,
subtypedata,scb_chan,funding,bitcoin_outpoint,
subtypedata,scb_chan,funding_sats,amount_sat,
subtypedata,scb_chan,type,channel_type,
# legacy_scb_chan stores min. info required to sweep the peer's force close.
subtype,legacy_scb_chan
subtypedata,legacy_scb_chan,id,u64,
subtypedata,legacy_scb_chan,cid,channel_id,
subtypedata,legacy_scb_chan,node_id,node_id,
subtypedata,legacy_scb_chan,unused,u8,
subtypedata,legacy_scb_chan,addr,wireaddr,
subtypedata,legacy_scb_chan,funding,bitcoin_outpoint,
subtypedata,legacy_scb_chan,funding_sats,amount_sat,
subtypedata,legacy_scb_chan,type,channel_type,

msgtype,static_chan_backup,6135,
msgdata,static_chan_backup,version,u64,
msgdata,static_chan_backup,timestamp,u32,
msgdata,static_chan_backup,num,u16,
msgdata,static_chan_backup,channels,scb_chan,num
msgdata,static_chan_backup,channels,legacy_scb_chan,num

subtype,modern_scb_chan
subtypedata,modern_scb_chan,id,u64,
subtypedata,modern_scb_chan,cid,channel_id,
subtypedata,modern_scb_chan,node_id,node_id,
subtypedata,modern_scb_chan,addr,wireaddr,
subtypedata,modern_scb_chan,funding,bitcoin_outpoint,
subtypedata,modern_scb_chan,funding_sats,amount_sat,
subtypedata,modern_scb_chan,type,channel_type,
subtypedata,modern_scb_chan,len_tlv,u32,
subtypedata,modern_scb_chan,tlvs,scb_tlvs,len_tlv

msgtype,static_chan_backup_with_tlvs,6137,
msgdata,static_chan_backup_with_tlvs,version,u64,
msgdata,static_chan_backup_with_tlvs,timestamp,u32,
msgdata,static_chan_backup_with_tlvs,num,u16,
msgdata,static_chan_backup_with_tlvs,channels,modern_scb_chan,num
13 changes: 10 additions & 3 deletions lightningd/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,12 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->owner = NULL;
memset(&channel->billboard, 0, sizeof(channel->billboard));
channel->billboard.transient = tal_strdup(channel, transient_billboard);
channel->channel_info = *channel_info;

/* If it's a unix domain socket connection, we don't save it */
if (peer->addr.itype == ADDR_INTERNAL_WIREADDR) {
channel->scb = tal(channel, struct scb_chan);
channel->scb = tal(channel, struct modern_scb_chan);
channel->scb->id = dbid;
channel->scb->unused = 0;
/* More useful to have last_known_addr, if avail */
if (peer->last_known_addr)
channel->scb->addr = *peer->last_known_addr;
Expand All @@ -497,6 +497,14 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->scb->cid = *cid;
channel->scb->funding_sats = funding_sats;
channel->scb->type = channel_type_dup(channel->scb, type);

struct tlv_scb_tlvs *scb_tlvs = tlv_scb_tlvs_new(channel);
scb_tlvs->shachain = &channel->their_shachain.chain;
scb_tlvs->basepoints = &channel->channel_info.theirbase;
scb_tlvs->opener = &channel->opener;
scb_tlvs->remote_to_self_delay = &channel->channel_info.their_config.to_self_delay;

channel->scb->tlvs = scb_tlvs;
} else
channel->scb = NULL;

Expand Down Expand Up @@ -542,7 +550,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
if (last_sig)
channel->last_sig = *last_sig;
channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs);
channel->channel_info = *channel_info;
channel->fee_states = dup_fee_states(channel, fee_states);
channel->shutdown_scriptpubkey[REMOTE]
= tal_steal(channel, remote_shutdown_scriptpubkey);
Expand Down
2 changes: 1 addition & 1 deletion lightningd/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ struct channel {

/* `Channel-shell` of this channel
* (Minimum information required to backup this channel). */
struct scb_chan *scb;
struct modern_scb_chan *scb;

/* Do we allow the peer to set any fee it wants? */
bool ignore_fee_limits;
Expand Down
11 changes: 9 additions & 2 deletions lightningd/dual_open_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,14 +1462,21 @@ wallet_commit_channel(struct lightningd *ld,
channel->min_possible_feerate = commitment_feerate;
channel->max_possible_feerate = commitment_feerate;
if (channel->peer->addr.itype == ADDR_INTERNAL_WIREADDR) {
channel->scb = tal(channel, struct scb_chan);
channel->scb = tal(channel, struct modern_scb_chan);
channel->scb->id = channel->dbid;
channel->scb->unused = 0;
channel->scb->addr = channel->peer->addr.u.wireaddr.wireaddr;
channel->scb->node_id = channel->peer->id;
channel->scb->funding = *funding;
channel->scb->cid = channel->cid;
channel->scb->funding_sats = total_funding;

struct tlv_scb_tlvs *scb_tlvs = tlv_scb_tlvs_new(channel);
scb_tlvs->shachain = &channel->their_shachain.chain;
scb_tlvs->basepoints = &channel_info->theirbase;
scb_tlvs->opener = &channel->opener;
scb_tlvs->remote_to_self_delay = &channel_info->their_config.to_self_delay;

channel->scb->tlvs = scb_tlvs;
} else
channel->scb = NULL;

Expand Down
71 changes: 61 additions & 10 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1452,7 +1452,11 @@ static struct channel *stub_chan(struct command *cmd,
struct bitcoin_outpoint funding,
struct wireaddr addr,
struct amount_sat funding_sats,
struct channel_type *type)
struct channel_type *type,
struct shachain shachain,
struct basepoints their_basepoint,
enum side opener,
u16 remote_to_self_delay)
{
struct basepoints basepoints;
struct bitcoin_signature *sig;
Expand All @@ -1468,6 +1472,10 @@ static struct channel *stub_chan(struct command *cmd,
u32 blockht;
u32 feerate;
struct channel_stats zero_channel_stats;
struct wallet_shachain *their_shachain = tal(cmd, struct wallet_shachain);
their_shachain->chain = shachain;
their_shachain->id = 0;

u8 *dummy_sig = tal_hexdata(cmd,
"30450221009b2e0eef267b94c3899fb0dc73750"
"12e2cee4c10348a068fe78d1b82b4b1403602207"
Expand Down Expand Up @@ -1528,8 +1536,11 @@ static struct channel *stub_chan(struct command *cmd,
/* FIXME: Makeake these a pointer, so they could be NULL */
memset(our_config, 0, sizeof(struct channel_config));
memset(their_config, 0, sizeof(struct channel_config));
memset(channel_info, 0, sizeof(struct channel_info));

our_config->to_self_delay = remote_to_self_delay;
channel_info->their_config = *their_config;
channel_info->theirbase = basepoints;
channel_info->theirbase = their_basepoint;
channel_info->remote_fundingkey = pk;
channel_info->remote_per_commit = pk;
channel_info->old_remote_per_commit = pk;
Expand All @@ -1545,9 +1556,9 @@ static struct channel *stub_chan(struct command *cmd,

/* Channel Shell with Dummy data(mostly) */
channel = new_channel(peer, id,
NULL, /* No shachain yet */
their_shachain,
CHANNELD_NORMAL,
LOCAL,
opener,
NULL,
"restored from static channel backup",
0, false, false,
Expand All @@ -1574,15 +1585,15 @@ static struct channel *stub_chan(struct command *cmd,
sig,
NULL, /* No HTLC sigs */
channel_info,
new_fee_states(cmd, LOCAL, &feerate),
new_fee_states(cmd, opener, &feerate),
NULL, /* No shutdown_scriptpubkey[REMOTE] */
NULL,
1, false,
NULL, /* No commit sent */
/* If we're fundee, could be a little before this
* in theory, but it's only used for timing out. */
get_network_blockheight(ld->topology),
FEERATE_FLOOR,
feerate,
funding_sats.satoshis / MINIMUM_TX_WEIGHT * 1000 /* Raw: convert to feerate */,
&basepoints,
&localFundingPubkey,
Expand All @@ -1596,7 +1607,7 @@ static struct channel *stub_chan(struct command *cmd,
0, /* no close_attempt_height */
REASON_REMOTE,
NULL,
take(new_height_states(ld->wallet, LOCAL,
take(new_height_states(ld->wallet, opener,
&blockht)),
0, NULL, 0, 0, /* No leases on v1s */
ld->config.htlc_minimum_msat,
Expand All @@ -1621,7 +1632,7 @@ static struct command_result *json_recoverchannel(struct command *cmd,
const jsmntok_t *scb, *t;
size_t i;
struct json_stream *response;
struct scb_chan *scb_chan = tal(cmd, struct scb_chan);
struct modern_scb_chan *scb_chan = tal(cmd, struct modern_scb_chan);

if (!param(cmd, buffer, params,
p_req("scb", param_array, &scb),
Expand All @@ -1636,14 +1647,50 @@ static struct command_result *json_recoverchannel(struct command *cmd,
char *token = json_strdup(tmpctx, buffer, t);
const u8 *scb_arr = tal_hexdata(cmd, token, strlen(token));
size_t scblen = tal_count(scb_arr);
struct shachain chain;
struct basepoints basepoints;
struct pubkey _localfundingpubkey;
enum side opener = LOCAL;
u16 remote_to_self_delay = 0;

scb_chan = fromwire_scb_chan(cmd ,&scb_arr, &scblen);
scb_chan = fromwire_modern_scb_chan(cmd, &scb_arr, &scblen);

if (scb_chan == NULL) {
log_broken(cmd->ld->log, "SCB is invalid!");
continue;
}

if (scb_chan->tlvs != NULL) {
if (scb_chan->tlvs->shachain == NULL) {
shachain_init(&chain);
} else {
chain = *scb_chan->tlvs->shachain;
}

if (scb_chan->tlvs->basepoints == NULL) {
get_channel_basepoints(cmd->ld,
&scb_chan->node_id,
scb_chan->id,
&basepoints,
&_localfundingpubkey);
} else {
basepoints = *scb_chan->tlvs->basepoints;
}

if (scb_chan->tlvs->opener != NULL)
opener = *scb_chan->tlvs->opener;

if (scb_chan->tlvs->remote_to_self_delay != NULL)
remote_to_self_delay = *scb_chan->tlvs->remote_to_self_delay;
} else {
shachain_init(&chain);
get_channel_basepoints(cmd->ld,
&scb_chan->node_id,
scb_chan->id,
&basepoints,
&_localfundingpubkey);
}

struct lightningd *ld = cmd->ld;
struct channel *channel= stub_chan(cmd,
scb_chan->id,
Expand All @@ -1652,7 +1699,11 @@ static struct command_result *json_recoverchannel(struct command *cmd,
scb_chan->funding,
scb_chan->addr,
scb_chan->funding_sats,
scb_chan->type);
scb_chan->type,
chain,
basepoints,
opener,
remote_to_self_delay);

/* Returns NULL only when channel already exists, so we skip over it. */
if (channel == NULL)
Expand Down
6 changes: 5 additions & 1 deletion lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -2368,7 +2368,11 @@ static void json_add_scb(struct command *cmd,
{
u8 *scb = tal_arr(cmd, u8, 0);

towire_scb_chan(&scb, c->scb);
/* Update shachain & basepoints in SCB. */
c->scb->tlvs->shachain = &c->their_shachain.chain;
c->scb->tlvs->basepoints = &c->channel_info.theirbase;
towire_modern_scb_chan(&scb, c->scb);

json_add_hex_talarr(response, fieldname,
scb);
}
Expand Down
6 changes: 3 additions & 3 deletions lightningd/test/run-invoice-select-inchan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,9 @@ u8 *towire_hsmd_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct node_
/* Generated stub for towire_hsmd_sign_invoice */
u8 *towire_hsmd_sign_invoice(const tal_t *ctx UNNEEDED, const u8 *u5bytes UNNEEDED, const u8 *hrp UNNEEDED)
{ fprintf(stderr, "towire_hsmd_sign_invoice called!\n"); abort(); }
/* Generated stub for towire_modern_scb_chan */
void towire_modern_scb_chan(u8 **p UNNEEDED, const struct modern_scb_chan *modern_scb_chan UNNEEDED)
{ fprintf(stderr, "towire_modern_scb_chan called!\n"); abort(); }
/* Generated stub for towire_node_id */
void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "towire_node_id called!\n"); abort(); }
Expand All @@ -1021,9 +1024,6 @@ u8 *towire_onchaind_dev_memleak(const tal_t *ctx UNNEEDED)
/* Generated stub for towire_openingd_dev_memleak */
u8 *towire_openingd_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_openingd_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_scb_chan */
void towire_scb_chan(u8 **p UNNEEDED, const struct scb_chan *scb_chan UNNEEDED)
{ fprintf(stderr, "towire_scb_chan called!\n"); abort(); }
/* Generated stub for towire_warningfmt */
u8 *towire_warningfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,
Expand Down
2 changes: 1 addition & 1 deletion plugins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ plugins/pay: $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUG

plugins/autoclean: $(PLUGIN_AUTOCLEAN_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)

plugins/chanbackup: $(PLUGIN_chanbackup_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/scb_wiregen.o wire/channel_type_wiregen.o
plugins/chanbackup: $(PLUGIN_chanbackup_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/scb_wiregen.o wire/channel_type_wiregen.o common/htlc_wire.o common/onionreply.o common/derive_basepoints.o

plugins/commando: $(PLUGIN_COMMANDO_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)

Expand Down
Loading