lightningd: struct uncommitted_channel for opening channels.

Each peer can have one 'uncommitted' channel, which is in the process
of opening.  This is used for openingd, and then on return we convert
it into a full-fledged struct channel and commit it into the database.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-02-19 11:36:02 +10:30
parent d2f691b288
commit 8db8c51201
7 changed files with 544 additions and 304 deletions

View File

@ -53,19 +53,15 @@ static void destroy_channel(struct channel *channel)
list_del_from(&channel->peer->channels, &channel->list);
}
/* This lets us give a more detailed error than just a destructor. */
/* FIXME: remove why */
void delete_channel(struct channel *channel, const char *why)
{
struct peer *peer = channel->peer;
if (channel->opening_cmd) {
command_fail(channel->opening_cmd, "%s", why);
channel->opening_cmd = NULL;
}
wallet_channel_delete(channel->peer->ld->wallet, channel->dbid);
tal_free(channel);
/* Last one out frees the peer */
if (list_empty(&peer->channels))
if (list_empty(&peer->channels) && !peer->uncommitted_channel)
delete_peer(peer);
}
@ -84,9 +80,9 @@ void delete_channel(struct channel *channel, const char *why)
* reconnection. We use the DB channel ID to guarantee unique secrets
* per channel.
*/
static void derive_channel_seed(struct lightningd *ld, struct privkey *seed,
const struct pubkey *peer_id,
const u64 dbid)
void derive_channel_seed(struct lightningd *ld, struct privkey *seed,
const struct pubkey *peer_id,
const u64 dbid)
{
u8 input[PUBKEY_DER_LEN + sizeof(dbid)];
char *info = "per-peer seed";
@ -143,11 +139,18 @@ struct channel *peer_active_channel(struct peer *peer)
}
struct channel *active_channel_by_id(struct lightningd *ld,
const struct pubkey *id)
const struct pubkey *id,
struct uncommitted_channel **uc)
{
struct peer *peer = peer_by_id(ld, id);
if (!peer)
if (!peer) {
if (uc)
*uc = NULL;
return NULL;
}
if (uc)
*uc = peer->uncommitted_channel;
return peer_active_channel(peer);
}

View File

@ -5,6 +5,8 @@
#include <lightningd/peer_state.h>
#include <wallet/wallet.h>
struct uncommitted_channel;
struct channel {
/* Inside peer->channels. */
struct list_node list;
@ -27,9 +29,6 @@ struct channel {
/* Which side offered channel? */
enum side funder;
/* Command which ordered us to open channel, if any. */
struct command *opening_cmd;
/* Is there a single subdaemon responsible for us? */
struct subd *owner;
@ -110,8 +109,10 @@ void channel_set_state(struct channel *channel,
/* Find a channel which is not onchain, if any */
struct channel *peer_active_channel(struct peer *peer);
/* Get active channel for peer, optionally any uncommitted_channel. */
struct channel *active_channel_by_id(struct lightningd *ld,
const struct pubkey *id);
const struct pubkey *id,
struct uncommitted_channel **uc);
void channel_set_last_tx(struct channel *channel,
struct bitcoin_tx *tx,
@ -176,4 +177,8 @@ static inline bool channel_persists(const struct channel *channel)
{
return channel->state >= CHANNELD_AWAITING_LOCKIN;
}
void derive_channel_seed(struct lightningd *ld, struct privkey *seed,
const struct pubkey *peer_id,
const u64 dbid);
#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_H */

View File

@ -547,7 +547,7 @@ bool send_payment(const tal_t *ctx,
* context, not our temporary context. */
new_sendpay_command(ctx, rhash, ld, cb, cbarg);
channel = active_channel_by_id(ld, &ids[0]);
channel = active_channel_by_id(ld, &ids[0], NULL);
if (!channel) {
/* Report routing failure to gossipd */
fail = immediate_routing_failure(tmpctx, ld,

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,9 @@ struct peer {
/* Our channels */
struct list_head channels;
/* Our (only) uncommitted channel, still opening. */
struct uncommitted_channel *uncommitted_channel;
/* History */
struct log_book *log_book;

View File

@ -422,7 +422,7 @@ static void forward_htlc(struct htlc_in *hin,
enum onion_type failcode;
u64 fee;
struct lightningd *ld = hin->key.channel->peer->ld;
struct channel *next = active_channel_by_id(ld, next_hop);
struct channel *next = active_channel_by_id(ld, next_hop, NULL);
/* Unknown peer, or peer not ready. */
if (!next || !next->scid) {

View File

@ -2406,7 +2406,7 @@ class LightningDTests(BaseLightningDTests):
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
# We should get a message about reconnecting.
l2.daemon.wait_for_log('Peer has reconnected, state OPENINGD')
l2.daemon.wait_for_log('Peer reconnected, killing openingd')
# Should work fine.
l1.rpc.fundchannel(l2.info['id'], 20000)