mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
lightningd: introduce peer_state enum.
The actual state names are place holders for now, really. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
93849b1e02
commit
34e6e56471
@ -84,6 +84,7 @@ LIGHTNINGD_HEADERS_NOGEN = \
|
||||
lightningd/lightningd.h \
|
||||
lightningd/pay.h \
|
||||
lightningd/peer_control.h \
|
||||
lightningd/peer_state.h \
|
||||
lightningd/subd.h \
|
||||
$(LIGHTNINGD_OLD_LIB_HEADERS) \
|
||||
$(LIGHTNINGD_LIB_HEADERS) \
|
||||
@ -95,6 +96,7 @@ LIGHTNINGD_HEADERS_NOGEN = \
|
||||
|
||||
# Generated headers
|
||||
LIGHTNINGD_HEADERS_GEN = \
|
||||
lightningd/gen_peer_state_names.h \
|
||||
$(WIRE_GEN_HEADERS) \
|
||||
$(GEN_HEADERS)
|
||||
|
||||
@ -118,6 +120,9 @@ include lightningd/channel/Makefile
|
||||
|
||||
$(LIGHTNINGD_OBJS) $(LIGHTNINGD_LIB_OBJS): $(LIGHTNINGD_HEADERS)
|
||||
|
||||
lightningd/gen_peer_state_names.h: lightningd/peer_state.h ccan/ccan/cdump/tools/cdump-enumstr
|
||||
ccan/ccan/cdump/tools/cdump-enumstr lightningd/peer_state.h > $@
|
||||
|
||||
check-source: $(LIGHTNINGD_SRC:%=check-src-include-order/%)
|
||||
check-source: $(LIGHTNINGD_LIB_SRC:%=check-src-include-order/%)
|
||||
check-source: $(LIGHTNINGD_CLI_SRC:%=check-src-include-order/%)
|
||||
|
@ -88,8 +88,9 @@ static void json_dev_newhtlc(struct command *cmd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!streq(peer->condition, "Normal operation")) {
|
||||
command_fail(cmd, "Peer in condition %s", peer->condition);
|
||||
if (!peer_can_add_htlc(peer)) {
|
||||
command_fail(cmd, "Peer in state %s",
|
||||
peer_state_name(peer->state));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -89,8 +89,8 @@ static void peer_nongossip(struct subd *gossip, const u8 *msg,
|
||||
peer->fd = peer_fd;
|
||||
peer->gossip_client_fd = gossip_fd;
|
||||
|
||||
peer_set_condition(peer, "Gossip ended up receipt of %s",
|
||||
wire_type_name(fromwire_peektype(inner)));
|
||||
log_info(peer->log, "Gossip ended up receipt of %s",
|
||||
wire_type_name(fromwire_peektype(inner)));
|
||||
|
||||
peer_accept_open(peer, &cs, inner);
|
||||
}
|
||||
@ -123,7 +123,7 @@ static void peer_ready(struct subd *gossip, const u8 *msg)
|
||||
peer->connect_cmd = NULL;
|
||||
}
|
||||
|
||||
peer_set_condition(peer, "Exchanging gossip");
|
||||
peer_set_condition(peer, GOSSIPING);
|
||||
}
|
||||
|
||||
static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <lightningd/channel.h>
|
||||
#include <lightningd/channel/gen_channel_wire.h>
|
||||
#include <lightningd/funding_tx.h>
|
||||
#include <lightningd/gen_peer_state_names.h>
|
||||
#include <lightningd/gossip/gen_gossip_wire.h>
|
||||
#include <lightningd/handshake/gen_handshake_wire.h>
|
||||
#include <lightningd/hsm/gen_hsm_wire.h>
|
||||
@ -39,8 +40,8 @@ static void destroy_peer(struct peer *peer)
|
||||
if (peer->fd >= 0)
|
||||
close(peer->fd);
|
||||
if (peer->connect_cmd)
|
||||
command_fail(peer->connect_cmd, "Failed after %s",
|
||||
peer->condition);
|
||||
command_fail(peer->connect_cmd, "Failed in state %s",
|
||||
peer_state_name(peer->state));
|
||||
}
|
||||
|
||||
void peer_fail(struct peer *peer, const char *fmt, ...)
|
||||
@ -55,20 +56,15 @@ void peer_fail(struct peer *peer, const char *fmt, ...)
|
||||
tal_free(peer);
|
||||
}
|
||||
|
||||
void peer_set_condition(struct peer *peer, const char *fmt, ...)
|
||||
void peer_set_condition(struct peer *peer, enum peer_state state)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
tal_free(peer->condition);
|
||||
peer->condition = tal_vfmt(peer, fmt, ap);
|
||||
va_end(ap);
|
||||
log_info(peer->log, "condition: %s", peer->condition);
|
||||
log_info(peer->log, "state: %s -> %s",
|
||||
peer_state_name(peer->state), peer_state_name(state));
|
||||
peer->state = state;
|
||||
}
|
||||
|
||||
static struct peer *new_peer(struct lightningd *ld,
|
||||
struct io_conn *conn,
|
||||
const char *in_or_out,
|
||||
struct command *cmd)
|
||||
{
|
||||
static u64 id_counter;
|
||||
@ -85,6 +81,7 @@ static struct peer *new_peer(struct lightningd *ld,
|
||||
peer->funding_txid = NULL;
|
||||
peer->seed = NULL;
|
||||
peer->balance = NULL;
|
||||
peer->state = HANDSHAKING;
|
||||
|
||||
/* Max 128k per peer. */
|
||||
peer->log_book = new_log_book(peer, 128*1024,
|
||||
@ -100,7 +97,6 @@ static struct peer *new_peer(struct lightningd *ld,
|
||||
return tal_free(peer);
|
||||
}
|
||||
netname = netaddr_name(peer, &peer->netaddr);
|
||||
peer->condition = tal_fmt(peer, "%s %s", in_or_out, netname);
|
||||
tal_free(netname);
|
||||
list_add_tail(&ld->peers, &peer->list);
|
||||
tal_add_destructor(peer, destroy_peer);
|
||||
@ -153,7 +149,7 @@ static bool handshake_succeeded(struct subd *hs, const u8 *msg, const int *fds,
|
||||
|
||||
peer->owner = peer->ld->gossip;
|
||||
tal_steal(peer->owner, peer);
|
||||
peer_set_condition(peer, "Beginning gossip");
|
||||
peer_set_condition(peer, INITIALIZING);
|
||||
|
||||
/* Tell gossip to handle it now. */
|
||||
msg = towire_gossipctl_new_peer(peer, peer->unique_id, &cs);
|
||||
@ -205,11 +201,10 @@ static bool peer_got_handshake_hsmfd(struct subd *hsm, const u8 *msg,
|
||||
if (peer->id) {
|
||||
req = towire_handshake_initiator(peer, &peer->ld->dstate.id,
|
||||
peer->id);
|
||||
peer_set_condition(peer, "Starting handshake as initiator");
|
||||
} else {
|
||||
req = towire_handshake_responder(peer, &peer->ld->dstate.id);
|
||||
peer_set_condition(peer, "Starting handshake as responder");
|
||||
}
|
||||
peer_set_condition(peer, HANDSHAKING);
|
||||
|
||||
/* Now hand peer request to the handshake daemon: hands it
|
||||
* back on success */
|
||||
@ -224,7 +219,7 @@ error:
|
||||
/* FIXME: timeout handshake if taking too long? */
|
||||
static struct io_plan *peer_in(struct io_conn *conn, struct lightningd *ld)
|
||||
{
|
||||
struct peer *peer = new_peer(ld, conn, "Incoming from", NULL);
|
||||
struct peer *peer = new_peer(ld, conn, NULL);
|
||||
|
||||
if (!peer)
|
||||
return io_close(conn);
|
||||
@ -352,7 +347,7 @@ static struct io_plan *peer_out(struct io_conn *conn,
|
||||
struct json_connecting *jc)
|
||||
{
|
||||
struct lightningd *ld = ld_from_dstate(jc->cmd->dstate);
|
||||
struct peer *peer = new_peer(ld, conn, "Outgoing to", jc->cmd);
|
||||
struct peer *peer = new_peer(ld, conn, jc->cmd);
|
||||
|
||||
if (!peer)
|
||||
return io_close(conn);
|
||||
@ -476,7 +471,7 @@ static void json_getpeers(struct command *cmd,
|
||||
list_for_each(&ld->peers, p, list) {
|
||||
json_object_start(response, NULL);
|
||||
json_add_u64(response, "unique_id", p->unique_id);
|
||||
json_add_string(response, "condition", p->condition);
|
||||
json_add_string(response, "state", peer_state_name(p->state));
|
||||
json_add_string(response, "netaddr",
|
||||
netaddr_name(response, &p->netaddr));
|
||||
if (p->id)
|
||||
@ -585,7 +580,7 @@ static enum watch_result funding_depth_cb(struct peer *peer,
|
||||
peer->scid->outnum = peer->funding_outnum;
|
||||
tal_free(loc);
|
||||
|
||||
peer_set_condition(peer, "Funding tx reached depth %u", depth);
|
||||
peer_set_condition(peer, OPENING_SENT_LOCKED);
|
||||
subd_send_msg(peer->owner,
|
||||
take(towire_channel_funding_locked(peer, peer->scid)));
|
||||
}
|
||||
@ -615,7 +610,7 @@ static bool opening_got_hsm_funding_sig(struct subd *hsm, const u8 *resp,
|
||||
fatal("HSM gave %zu sigs, needed %zu",
|
||||
tal_count(sigs), tal_count(tx->input));
|
||||
|
||||
peer_set_condition(fc->peer, "Waiting for our funding tx");
|
||||
peer_set_condition(fc->peer, OPENING_AWAITING_LOCKIN);
|
||||
|
||||
/* Create input parts from signatures. */
|
||||
for (i = 0; i < tal_count(tx->input); i++) {
|
||||
@ -976,10 +971,9 @@ static void forward_htlc(struct htlc_end *hend,
|
||||
err = towire_unknown_next_peer(hend);
|
||||
goto fail;
|
||||
}
|
||||
/* FIXME: These checks are horrible, use a peer flag to say it's
|
||||
* ready to forward! */
|
||||
if (!next->owner || !streq(next->owner->name, "lightningd_channel")
|
||||
|| !streq(next->condition, "Normal operation")) {
|
||||
|
||||
if (!peer_can_add_htlc(next)) {
|
||||
log_info(next->log, "Attempt to forward HTLC but not ready");
|
||||
err = towire_unknown_next_peer(hend);
|
||||
goto fail;
|
||||
}
|
||||
@ -1340,10 +1334,10 @@ static int channel_msg(struct subd *sd, const u8 *msg, const int *unused)
|
||||
|
||||
switch (t) {
|
||||
case WIRE_CHANNEL_RECEIVED_FUNDING_LOCKED:
|
||||
peer_set_condition(sd->peer, "Received funding locked");
|
||||
peer_set_condition(sd->peer, OPENING_RCVD_LOCKED);
|
||||
break;
|
||||
case WIRE_CHANNEL_NORMAL_OPERATION:
|
||||
peer_set_condition(sd->peer, "Normal operation");
|
||||
peer_set_condition(sd->peer, NORMAL);
|
||||
break;
|
||||
case WIRE_CHANNEL_ACCEPTED_HTLC:
|
||||
return peer_accepted_htlc(sd->peer, msg);
|
||||
@ -1406,7 +1400,7 @@ static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp,
|
||||
}
|
||||
cds->peer->fd = -1;
|
||||
|
||||
peer_set_condition(cds->peer, "Waiting for funding confirmations");
|
||||
log_debug(cds->peer->log, "Waiting for funding confirmations");
|
||||
/* We don't expect a response: we are triggered by funding_depth_cb. */
|
||||
subd_send_msg(cds->peer->owner, take(cds->initmsg));
|
||||
tal_free(cds);
|
||||
@ -1428,7 +1422,7 @@ static void peer_start_channeld(struct peer *peer,
|
||||
peer->owner = NULL;
|
||||
tal_steal(peer->ld, peer);
|
||||
|
||||
peer_set_condition(peer, "Waiting for HSM file descriptor");
|
||||
log_debug(peer->log, "Waiting for HSM file descriptor");
|
||||
|
||||
/* Now we can consider balance set. */
|
||||
peer->balance = tal_arr(peer, u64, NUM_SIDES);
|
||||
@ -1498,7 +1492,7 @@ static bool opening_release_tx(struct subd *opening, const u8 *resp,
|
||||
tal_free(fc->peer);
|
||||
return false;
|
||||
}
|
||||
peer_set_condition(fc->peer, "Getting HSM to sign funding tx");
|
||||
log_debug(fc->peer->log, "Getting HSM to sign funding tx");
|
||||
|
||||
/* Get HSM to sign the funding tx. */
|
||||
for (i = 0; i < tal_count(fc->utxomap); i++)
|
||||
@ -1529,7 +1523,7 @@ static bool opening_gen_funding(struct subd *opening, const u8 *reply,
|
||||
u8 *msg;
|
||||
struct pubkey changekey;
|
||||
|
||||
peer_set_condition(fc->peer, "Created funding transaction for channel");
|
||||
log_debug(fc->peer->log, "Created funding transaction for channel");
|
||||
if (!fromwire_opening_open_reply(reply, NULL,
|
||||
&fc->local_fundingkey,
|
||||
&fc->remote_fundingkey)) {
|
||||
@ -1611,6 +1605,7 @@ static bool opening_accept_reply(struct subd *opening, const u8 *reply,
|
||||
return false;
|
||||
}
|
||||
|
||||
peer_set_condition(peer, OPENING_AWAITING_LOCKIN);
|
||||
log_debug(peer->log, "Watching funding tx %s",
|
||||
type_to_string(reply, struct sha256_double,
|
||||
peer->funding_txid));
|
||||
@ -1686,7 +1681,7 @@ void peer_accept_open(struct peer *peer,
|
||||
return;
|
||||
}
|
||||
|
||||
peer_set_condition(peer, "Starting opening daemon");
|
||||
peer_set_condition(peer, OPENING_NOT_LOCKED);
|
||||
peer->owner = new_subd(ld, ld, "lightningd_opening", peer,
|
||||
opening_wire_type_name,
|
||||
NULL, NULL,
|
||||
@ -1758,7 +1753,7 @@ static bool gossip_peer_released(struct subd *gossip,
|
||||
fatal("Gossup daemon release gave %"PRIu64" not %"PRIu64,
|
||||
id, fc->peer->unique_id);
|
||||
|
||||
peer_set_condition(fc->peer, "Starting opening daemon");
|
||||
peer_set_condition(fc->peer, OPENING_NOT_LOCKED);
|
||||
opening = new_subd(fc->peer->ld, ld,
|
||||
"lightningd_opening", fc->peer,
|
||||
opening_wire_type_name,
|
||||
@ -1856,3 +1851,13 @@ static const struct json_command fund_channel_command = {
|
||||
"Returns once channel established"
|
||||
};
|
||||
AUTODATA(json_command, &fund_channel_command);
|
||||
|
||||
const char *peer_state_name(enum peer_state state)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; enum_peer_state_names[i].name; i++)
|
||||
if (enum_peer_state_names[i].v == state)
|
||||
return enum_peer_state_names[i].name;
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <daemon/json.h>
|
||||
#include <daemon/netaddr.h>
|
||||
#include <lightningd/channel_config.h>
|
||||
#include <lightningd/peer_state.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define ANNOUNCE_MIN_DEPTH 6
|
||||
@ -19,6 +20,9 @@ struct peer {
|
||||
/* Unique ID (works before we know their pubkey) */
|
||||
u64 unique_id;
|
||||
|
||||
/* What's happening. */
|
||||
enum peer_state state;
|
||||
|
||||
/* Which side offered channel? */
|
||||
enum side funder;
|
||||
|
||||
@ -28,9 +32,6 @@ struct peer {
|
||||
/* What stage is this in? NULL during first creation. */
|
||||
struct subd *owner;
|
||||
|
||||
/* What's happening (doubles as error return for connect_cmd) */
|
||||
const char *condition;
|
||||
|
||||
/* History */
|
||||
struct log_book *log_book;
|
||||
struct log *log;
|
||||
@ -71,6 +72,34 @@ struct peer {
|
||||
int gossip_client_fd;
|
||||
};
|
||||
|
||||
static inline bool peer_can_add_htlc(const struct peer *peer)
|
||||
{
|
||||
return peer->state == NORMAL;
|
||||
}
|
||||
|
||||
static inline bool peer_can_remove_htlc(const struct peer *peer)
|
||||
{
|
||||
return peer->state == NORMAL
|
||||
|| peer->state == SHUTDOWN_SENT
|
||||
|| peer->state == SHUTDOWN_RCVD
|
||||
|| peer->state == ONCHAIN_THEIR_UNILATERAL
|
||||
|| peer->state == ONCHAIN_OUR_UNILATERAL;
|
||||
}
|
||||
|
||||
static inline bool peer_on_chain(const struct peer *peer)
|
||||
{
|
||||
return peer->state == ONCHAIN_CHEATED
|
||||
|| peer->state == ONCHAIN_THEIR_UNILATERAL
|
||||
|| peer->state == ONCHAIN_OUR_UNILATERAL
|
||||
|| peer->state == ONCHAIN_MUTUAL;
|
||||
}
|
||||
|
||||
/* Do we need to remember anything about this peer? */
|
||||
static inline bool peer_persists(const struct peer *peer)
|
||||
{
|
||||
return peer->state > OPENING_NOT_LOCKED;
|
||||
}
|
||||
|
||||
struct peer *peer_by_unique_id(struct lightningd *ld, u64 unique_id);
|
||||
struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id);
|
||||
struct peer *peer_from_json(struct lightningd *ld,
|
||||
@ -83,6 +112,7 @@ void peer_accept_open(struct peer *peer,
|
||||
/* Peer has failed. */
|
||||
PRINTF_FMT(2,3) void peer_fail(struct peer *peer, const char *fmt, ...);
|
||||
|
||||
PRINTF_FMT(2,3) void peer_set_condition(struct peer *peer, const char *fmt, ...);
|
||||
const char *peer_state_name(enum peer_state state);
|
||||
void peer_set_condition(struct peer *peer, enum peer_state state);
|
||||
void setup_listeners(struct lightningd *ld);
|
||||
#endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */
|
||||
|
38
lightningd/peer_state.h
Normal file
38
lightningd/peer_state.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef LIGHTNING_LIGHTNINGD_PEER_STATE_H
|
||||
#define LIGHTNING_LIGHTNINGD_PEER_STATE_H
|
||||
#include "config.h"
|
||||
|
||||
enum peer_state {
|
||||
/* Not important: we can forget about peers in these states. */
|
||||
HANDSHAKING,
|
||||
INITIALIZING,
|
||||
GOSSIPING,
|
||||
|
||||
/* Negotiating channel opening */
|
||||
OPENING_NOT_LOCKED,
|
||||
/* Waiting for funding tx to lock in. */
|
||||
OPENING_AWAITING_LOCKIN,
|
||||
/* Opening, have received funding_locked (not sent). */
|
||||
OPENING_RCVD_LOCKED,
|
||||
/* Opening, have sent funding_locked (not received). */
|
||||
OPENING_SENT_LOCKED,
|
||||
|
||||
/* Normal operating state. */
|
||||
NORMAL,
|
||||
|
||||
/* We are closing, pending HTLC resolution. */
|
||||
SHUTDOWN_SENT,
|
||||
/* Both are closing, pending HTLC resolution. */
|
||||
SHUTDOWN_RCVD,
|
||||
|
||||
/* Exchanging signatures on closing tx. */
|
||||
CLOSING_SIGEXCHANGE,
|
||||
|
||||
/* Various onchain states. */
|
||||
ONCHAIN_CHEATED,
|
||||
ONCHAIN_THEIR_UNILATERAL,
|
||||
ONCHAIN_OUR_UNILATERAL,
|
||||
ONCHAIN_MUTUAL
|
||||
};
|
||||
|
||||
#endif /* LIGHTNING_LIGHTNINGD_PEER_STATE_H */
|
@ -180,8 +180,8 @@ class LightningDTests(BaseLightningDTests):
|
||||
|
||||
l1.bitcoin.rpc.generate(6)
|
||||
|
||||
l1.daemon.wait_for_log('Normal operation')
|
||||
l2.daemon.wait_for_log('Normal operation')
|
||||
l1.daemon.wait_for_log('-> NORMAL')
|
||||
l2.daemon.wait_for_log('-> NORMAL')
|
||||
|
||||
def test_connect(self):
|
||||
l1,l2 = self.connect()
|
||||
@ -189,13 +189,13 @@ class LightningDTests(BaseLightningDTests):
|
||||
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
|
||||
p2 = l2.rpc.getpeer(l1.info['id'], 'info')
|
||||
|
||||
assert p1['condition'] == 'Exchanging gossip'
|
||||
assert p2['condition'] == 'Exchanging gossip'
|
||||
assert p1['state'] == 'GOSSIPING'
|
||||
assert p2['state'] == 'GOSSIPING'
|
||||
|
||||
# It should have gone through these steps
|
||||
assert 'condition: Starting handshake as initiator' in p1['log']
|
||||
assert 'condition: Beginning gossip' in p1['log']
|
||||
assert 'condition: Exchanging gossip' in p1['log']
|
||||
print(p1['log'])
|
||||
assert 'state: HANDSHAKING -> INITIALIZING' in p1['log']
|
||||
assert 'state: INITIALIZING -> GOSSIPING' in p1['log']
|
||||
|
||||
# Both should still be owned by gossip
|
||||
assert p1['owner'] == 'lightningd_gossip'
|
||||
@ -205,8 +205,8 @@ class LightningDTests(BaseLightningDTests):
|
||||
l1,l2 = self.connect()
|
||||
|
||||
self.fund_channel(l1, l2, 10**6)
|
||||
l1.daemon.wait_for_log('Normal operation')
|
||||
l2.daemon.wait_for_log('Normal operation')
|
||||
l1.daemon.wait_for_log('-> NORMAL')
|
||||
l2.daemon.wait_for_log('-> NORMAL')
|
||||
|
||||
secret = '1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd'
|
||||
rhash = l1.rpc.dev_rhash(secret)['rhash']
|
||||
|
@ -282,5 +282,5 @@ class LightningNode(object):
|
||||
self.daemon.wait_for_log('sendrawtx exit 0, gave')
|
||||
time.sleep(1)
|
||||
self.bitcoin.rpc.generate(6)
|
||||
self.daemon.wait_for_log('Normal operation')
|
||||
self.daemon.wait_for_log('-> NORMAL')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user