diff --git a/bitcoin/short_channel_id.h b/bitcoin/short_channel_id.h index bac77d8d8..4465da462 100644 --- a/bitcoin/short_channel_id.h +++ b/bitcoin/short_channel_id.h @@ -37,6 +37,13 @@ static inline u32 short_channel_id_blocknum(const struct short_channel_id *scid) return scid->u64 >> 40; } +static inline bool is_stub_scid(const struct short_channel_id *scid) +{ + return scid ? scid->u64 >> 40 == 1 && + ((scid->u64 >> 16) & 0x00FFFFFF) == 1 && + (scid->u64 & 0xFFFF) == 1 : false; +} + static inline u32 short_channel_id_txnum(const struct short_channel_id *scid) { return (scid->u64 >> 16) & 0x00FFFFFF; diff --git a/lightningd/channel.c b/lightningd/channel.c index 035af0895..06a7c6361 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -534,6 +534,12 @@ struct channel *new_channel(struct peer *peer, u64 dbid, txfilter_add_scriptpubkey(peer->ld->owned_txfilter, take(p2wpkh_for_keyidx(NULL, peer->ld, channel->final_key_idx))); + /* scid is NULL when opening a new channel so we don't + * need to set error in that case as well */ + if (is_stub_scid(scid)) + channel->error = towire_errorfmt(peer->ld, + &channel->cid, + "We can't be together anymore."); return channel; } @@ -779,6 +785,11 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...) { + /* Don't do anything if it's an stub channel because + * peer has already closed it unilatelrally. */ + if (is_stub_scid(channel->scid)) + return; + struct lightningd *ld = channel->peer->ld; va_list ap; char *why; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 1c22cc1b9..2e8919751 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -669,8 +669,17 @@ enum watch_result onchaind_funding_spent(struct channel *channel, channel->final_key_idx); return KEEP_WATCHING; } - /* This could be a mutual close, but it doesn't matter. */ - bitcoin_txid(channel->last_tx, &our_last_txid); + + /* This could be a mutual close, but it doesn't matter. + * We don't need this for stub channels as well */ + if (!is_stub_scid(channel->scid)) + bitcoin_txid(channel->last_tx, &our_last_txid); + else + /* Dummy txid for stub channel to make valgrind happy. */ + bitcoin_txid_from_hex("80cea306607b708a03a1854520729d" + "a884e4317b7b51f3d4a622f88176f5e034", + 64, + &our_last_txid); /* We try to get the feerate for each transaction type, 0 if estimation * failed. */ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index a6b8d7532..c2f02819f 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1229,6 +1230,208 @@ static struct command_result *json_fundchannel_start(struct command *cmd, return command_still_pending(cmd); } +static struct channel *stub_chan(struct command *cmd, + u64 id, + struct node_id nodeid, + struct channel_id cid, + struct bitcoin_outpoint funding, + struct wireaddr_internal addr, + struct amount_sat funding_sats, + struct channel_type *type) +{ + struct basepoints basepoints; + struct bitcoin_signature *sig; + struct channel *channel; + struct channel_config *our_config; + struct channel_config *their_config; + struct channel_info *channel_info; + struct lightningd *ld; + struct peer *peer; + struct pubkey localFundingPubkey; + struct pubkey pk; + struct short_channel_id *scid; + u32 blockht; + u32 feerate; + u8 *dummy_sig = tal_hexdata(cmd, + "30450221009b2e0eef267b94c3899fb0dc73750" + "12e2cee4c10348a068fe78d1b82b4b1403602207" + "7c3fad3adac2ddf33f415e45f0daf6658b7a0b09" + "647de4443938ae2dbafe2b9" "01", + 144); + + peer = new_peer(cmd->ld, + 0, + &nodeid, + &addr, + false); + + ld = cmd->ld; + feerate = FEERATE_FLOOR; + + sig = tal(cmd, struct bitcoin_signature); + signature_from_der(dummy_sig, + tal_bytelen(dummy_sig) + ,sig); + + if (!pubkey_from_der(tal_hexdata(cmd, + type_to_string(tmpctx, + struct node_id, + &nodeid), + 66), + 33, + &pk)) + { + fatal("Invalid node id!"); + } + + get_channel_basepoints(ld, + &nodeid, + id, + &basepoints, + &localFundingPubkey); + + channel_info = tal(cmd, + struct channel_info); + + our_config = tal(cmd, struct channel_config); + their_config = tal(cmd, struct channel_config); + + /* 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)); + channel_info->their_config = *their_config; + channel_info->theirbase = basepoints; + channel_info->remote_fundingkey = pk; + channel_info->remote_per_commit = pk; + channel_info->old_remote_per_commit = pk; + + blockht = 100; + scid = tal(cmd, struct short_channel_id); + + /*To indicate this is an stub channel we keep it's scid to 1x1x1.*/ + if (!mk_short_channel_id(scid, 1, 1, 1)) + fatal("Failed to make short channel 1x1x1!"); + + /* Channel Shell with Dummy data(mostly) */ + channel = new_channel(peer, id, + NULL, /* No shachain yet */ + CHANNELD_NORMAL, + LOCAL, + NULL, + "restored from static channel backup", + 0, our_config, + 0, + 1, 1, 1, + &funding, + funding_sats, + AMOUNT_MSAT(0), + AMOUNT_SAT(0), + true, /* !remote_funding_locked */ + scid, + scid, + scid, + &cid, + /* The three arguments below are msatoshi_to_us, + * msatoshi_to_us_min, and msatoshi_to_us_max. + * Because, this is a newly-funded channel, + * all three are same value. */ + AMOUNT_MSAT(0), + AMOUNT_MSAT(0), /* msat_to_us_min */ + AMOUNT_MSAT(0), /* msat_to_us_max */ + NULL, + sig, + NULL, /* No HTLC sigs */ + channel_info, + new_fee_states(cmd, LOCAL, &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, + funding_sats.satoshis / MINIMUM_TX_WEIGHT * 1000 /* Raw: convert to feerate */, + false, + &basepoints, + &localFundingPubkey, + NULL, + ld->config.fee_base, + ld->config.fee_per_satoshi, + NULL, + 0, 0, + type, + NUM_SIDES, /* closer not yet known */ + REASON_REMOTE, + NULL, + take(new_height_states(ld->wallet, LOCAL, + &blockht)), + 0, NULL, 0, 0, /* No leases on v1s */ + ld->config.htlc_minimum_msat, + ld->config.htlc_maximum_msat); + + return channel; +} + +static struct command_result *json_recoverchannel(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + const jsmntok_t *scb, *t; + size_t i; + struct json_stream *response; + struct scb_chan *scb_chan = tal(cmd, struct scb_chan); + + if (!param(cmd, buffer, params, + p_req("scb", param_array, &scb), + NULL)) + return command_param_failed(); + + response = json_stream_success(cmd); + + json_array_start(response, "stubs"); + json_for_each_arr(i,t,scb){ + + char *token = json_strdup(tmpctx, buffer, t); + const u8 *scb_arr = tal_hexdata(cmd, token, strlen(token)); + size_t scblen = tal_count(scb_arr); + + scb_chan = fromwire_scb_chan(cmd ,&scb_arr, &scblen); + + if (scb_chan == NULL) { + log_broken(cmd->ld->log, "SCB is invalid!"); + continue; + } + + struct lightningd *ld = cmd->ld; + struct channel *channel= stub_chan(cmd, + scb_chan->id, + scb_chan->node_id, + scb_chan->cid, + scb_chan->funding, + scb_chan->addr, + scb_chan->funding_sats, + scb_chan->type); + + /* Now we put this in the database. */ + wallet_channel_insert(ld->wallet, channel); + + /* Watch the Funding */ + channel_watch_funding(ld, channel); + + json_add_channel_id(response, NULL, &scb_chan->cid); + } + + /* This will try to reconnect to the peers and start + * initiating the process */ + setup_peers(cmd->ld); + + json_array_end(response); + + return command_success(cmd, response); +} + static const struct json_command fundchannel_start_command = { "fundchannel_start", "channels", @@ -1254,3 +1457,13 @@ static const struct json_command fundchannel_complete_command = { "with {psbt}. Returns true on success, false otherwise." }; AUTODATA(json_command, &fundchannel_complete_command); + +static const struct json_command json_commitchan_command = { + "recoverchannel", + "channels", + json_recoverchannel, + "Populate the DB with a channel and peer" + "Used for recovering the channel using DLP." + "This needs param in the form of an array [scb1,scb2,...]" +}; +AUTODATA(json_command, &json_commitchan_command); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 44bd8624b..4a0b4c8a0 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1536,8 +1536,9 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, const char *txidstr; struct short_channel_id scid; - /* Sanity check */ - if (!check_funding_tx(tx, channel)) { + /* Sanity check, but we'll have to make an exception + * for stub channels(1x1x1) */ + if (!check_funding_tx(tx, channel) && !is_stub_scid(channel->scid)) { channel_internal_error(channel, "Bad tx %s: %s", type_to_string(tmpctx, struct bitcoin_txid, txid), @@ -1592,13 +1593,15 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, return DELETE_WATCH; } - /* If we restart, we could already have peer->scid from database */ + /* If we restart, we could already have peer->scid from database, + * we don't need to update scid for stub channels(1x1x1) */ if (!channel->scid) { channel->scid = tal(channel, struct short_channel_id); *channel->scid = scid; wallet_channel_save(ld->wallet, channel); - } else if (!short_channel_id_eq(channel->scid, &scid)) { + } else if (!short_channel_id_eq(channel->scid, &scid) && + !is_stub_scid(channel->scid)) { /* This normally restarts channeld, initialized with updated scid * and also adds it (at least our halve_chan) to rtable. */ channel_fail_reconnect(channel, diff --git a/wallet/wallet.c b/wallet/wallet.c index 33694c9c4..6f6c6b699 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1930,7 +1930,10 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) db_bind_talarr(stmt, 17, chan->shutdown_scriptpubkey[REMOTE]); db_bind_u64(stmt, 18, chan->final_key_idx); db_bind_u64(stmt, 19, chan->our_config.id); - db_bind_psbt(stmt, 20, chan->last_tx->psbt); + if (chan->last_tx) + db_bind_psbt(stmt, 20, chan->last_tx->psbt); + else + db_bind_null(stmt, 20); db_bind_signature(stmt, 21, &chan->last_sig.s); db_bind_int(stmt, 22, chan->last_was_revoke); db_bind_int(stmt, 23, chan->min_possible_feerate);