lightningd/peer_control: reorder, move more functions out.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-02-21 07:29:09 +10:30 committed by Christian Decker
parent 372040bbd5
commit 36652a3df3
6 changed files with 289 additions and 297 deletions

View File

@ -89,6 +89,19 @@ void peer_connection_failed(struct lightningd *ld, const u8 *msg)
connect_failed(ld, &id, error);
}
/* Gossipd tells us peer was already connected. */
void peer_already_connected(struct lightningd *ld, const u8 *msg)
{
struct pubkey id;
if (!fromwire_gossip_peer_already_connected(msg, NULL, &id))
fatal("Gossip gave bad GOSSIP_PEER_ALREADY_CONNECTED message %s",
tal_hex(msg, msg));
/* If we were waiting for connection, we succeeded. */
connect_succeeded(ld, &id);
}
static void json_connect(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{

View File

@ -12,4 +12,7 @@ void connect_failed(struct lightningd *ld, const struct pubkey *id,
/* Gossipd was unable to connect to the peer */
void peer_connection_failed(struct lightningd *ld, const u8 *msg);
/* This simply means we asked to reach a peer, but we already have it */
void peer_already_connected(struct lightningd *ld, const u8 *msg);
#endif /* LIGHTNING_LIGHTNINGD_CONNECT_CONTROL_H */

View File

@ -44,18 +44,26 @@
#include <wire/peer_wire.h>
#include <wire/wire_sync.h>
/* FIXME: Reorder */
static void destroy_peer(struct peer *peer)
{
list_del_from(&peer->ld->peers, &peer->list);
}
/* We copy per-peer entries above --log-level into the main log. */
static void copy_to_parent_log(const char *prefix,
enum log_level level,
bool continued,
const struct timeabs *time,
const char *str,
const u8 *io,
struct log *parent_log);
static void destroy_peer(struct peer *peer)
struct log *parent_log)
{
list_del_from(&peer->ld->peers, &peer->list);
if (level == LOG_IO_IN || level == LOG_IO_OUT)
log_io(parent_log, level, prefix, io, tal_len(io));
else if (continued)
log_add(parent_log, "%s ... %s", prefix, str);
else
log_(parent_log, level, "%s %s", prefix, str);
}
struct peer *new_peer(struct lightningd *ld, u64 dbid,
@ -105,6 +113,61 @@ struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid)
return NULL;
}
struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id)
{
struct peer *p;
list_for_each(&ld->peers, p, list)
if (pubkey_eq(&p->id, id))
return p;
return NULL;
}
struct peer *peer_from_json(struct lightningd *ld,
const char *buffer,
jsmntok_t *peeridtok)
{
struct pubkey peerid;
if (!json_tok_pubkey(buffer, peeridtok, &peerid))
return NULL;
return peer_by_id(ld, &peerid);
}
u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx)
{
struct pubkey shutdownkey;
if (!bip32_pubkey(ld->wallet->bip32_base, &shutdownkey, keyidx))
return NULL;
return scriptpubkey_p2wpkh(ctx, &shutdownkey);
}
u32 feerate_min(struct lightningd *ld)
{
if (ld->config.ignore_fee_limits)
return 1;
/* Set this to average of slow and normal.*/
return (get_feerate(ld->topology, FEERATE_SLOW)
+ get_feerate(ld->topology, FEERATE_NORMAL)) / 2;
}
/* BOLT #2:
*
* Given the variance in fees, and the fact that the transaction may
* be spent in the future, it's a good idea for the fee payer to keep
* a good margin, say 5x the expected fee requirement */
u32 feerate_max(struct lightningd *ld)
{
if (ld->config.ignore_fee_limits)
return UINT_MAX;
return get_feerate(ld->topology, FEERATE_IMMEDIATE) * 5;
}
static void sign_last_tx(struct channel *channel)
{
const tal_t *tmpctx = tal_tmpctx(channel);
@ -340,19 +403,6 @@ send_error:
subd_send_fd(ld->gossip, gossip_fd);
}
/* Gossipd tells us peer was already connected. */
void peer_already_connected(struct lightningd *ld, const u8 *msg)
{
struct pubkey id;
if (!fromwire_gossip_peer_already_connected(msg, NULL, &id))
fatal("Gossip gave bad GOSSIP_PEER_ALREADY_CONNECTED message %s",
tal_hex(msg, msg));
/* If we were waiting for connection, we succeeded. */
connect_succeeded(ld, &id);
}
static struct channel *channel_by_channel_id(struct peer *peer,
const struct channel_id *channel_id)
{
@ -429,213 +479,6 @@ send_error:
tal_free(error);
}
/* We copy per-peer entries above --log-level into the main log. */
static void copy_to_parent_log(const char *prefix,
enum log_level level,
bool continued,
const struct timeabs *time,
const char *str,
const u8 *io,
struct log *parent_log)
{
if (level == LOG_IO_IN || level == LOG_IO_OUT)
log_io(parent_log, level, prefix, io, tal_len(io));
else if (continued)
log_add(parent_log, "%s ... %s", prefix, str);
else
log_(parent_log, level, "%s %s", prefix, str);
}
struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id)
{
struct peer *p;
list_for_each(&ld->peers, p, list)
if (pubkey_eq(&p->id, id))
return p;
return NULL;
}
struct getpeers_args {
struct command *cmd;
/* If non-NULL, they want logs too */
enum log_level *ll;
/* If set, only report on a specific id. */
struct pubkey *specific_id;
};
static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg,
const int *fds,
struct getpeers_args *gpa)
{
/* This is a little sneaky... */
struct pubkey *ids;
struct wireaddr *addrs;
struct json_result *response = new_json_result(gpa->cmd);
struct peer *p;
if (!fromwire_gossip_getpeers_reply(msg, msg, NULL, &ids, &addrs)) {
command_fail(gpa->cmd, "Bad response from gossipd");
return;
}
/* First the peers not just gossiping. */
json_object_start(response, NULL);
json_array_start(response, "peers");
list_for_each(&gpa->cmd->ld->peers, p, list) {
bool connected;
struct channel *channel;
if (gpa->specific_id && !pubkey_eq(gpa->specific_id, &p->id))
continue;
json_object_start(response, NULL);
json_add_pubkey(response, "id", &p->id);
channel = peer_active_channel(p);
connected = (channel && channel->owner != NULL);
json_add_bool(response, "connected", connected);
if (connected) {
json_array_start(response, "netaddr");
if (p->addr.type != ADDR_TYPE_PADDING)
json_add_string(response, NULL,
type_to_string(response,
struct wireaddr,
&p->addr));
json_array_end(response);
}
json_array_start(response, "channels");
json_add_uncommitted_channel(response, p->uncommitted_channel);
list_for_each(&p->channels, channel, list) {
json_object_start(response, NULL);
json_add_string(response, "state",
channel_state_name(channel));
if (channel->owner)
json_add_string(response, "owner",
channel->owner->name);
if (channel->scid)
json_add_short_channel_id(response,
"short_channel_id",
channel->scid);
json_add_txid(response,
"funding_txid",
&channel->funding_txid);
json_add_u64(response, "msatoshi_to_us",
channel->our_msatoshi);
json_add_u64(response, "msatoshi_total",
channel->funding_satoshi * 1000);
/* channel config */
json_add_u64(response, "dust_limit_satoshis",
channel->our_config.dust_limit_satoshis);
json_add_u64(response, "max_htlc_value_in_flight_msat",
channel->our_config.max_htlc_value_in_flight_msat);
json_add_u64(response, "channel_reserve_satoshis",
channel->our_config.channel_reserve_satoshis);
json_add_u64(response, "htlc_minimum_msat",
channel->our_config.htlc_minimum_msat);
json_add_num(response, "to_self_delay",
channel->our_config.to_self_delay);
json_add_num(response, "max_accepted_htlcs",
channel->our_config.max_accepted_htlcs);
json_object_end(response);
}
json_array_end(response);
if (gpa->ll)
json_add_log(response, "log", p->log_book, *gpa->ll);
json_object_end(response);
}
for (size_t i = 0; i < tal_count(ids); i++) {
/* Don't report peers in both, which can happen if they're
* reconnecting */
if (peer_by_id(gpa->cmd->ld, ids + i))
continue;
json_object_start(response, NULL);
/* Fake state. */
json_add_string(response, "state", "GOSSIPING");
json_add_pubkey(response, "id", ids+i);
json_array_start(response, "netaddr");
if (addrs[i].type != ADDR_TYPE_PADDING)
json_add_string(response, NULL,
type_to_string(response, struct wireaddr,
addrs + i));
json_array_end(response);
json_add_bool(response, "connected", true);
json_add_string(response, "owner", gossip->name);
json_object_end(response);
}
json_array_end(response);
json_object_end(response);
command_success(gpa->cmd, response);
}
static void json_listpeers(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
jsmntok_t *leveltok;
struct getpeers_args *gpa = tal(cmd, struct getpeers_args);
jsmntok_t *idtok;
gpa->cmd = cmd;
gpa->specific_id = NULL;
if (!json_get_params(cmd, buffer, params,
"?id", &idtok,
"?level", &leveltok,
NULL)) {
return;
}
if (idtok) {
gpa->specific_id = tal_arr(cmd, struct pubkey, 1);
if (!json_tok_pubkey(buffer, idtok, gpa->specific_id)) {
command_fail(cmd, "id %.*s not valid",
idtok->end - idtok->start,
buffer + idtok->start);
return;
}
}
if (leveltok) {
gpa->ll = tal(gpa, enum log_level);
if (!json_tok_loglevel(buffer, leveltok, gpa->ll)) {
command_fail(cmd, "Invalid level param");
return;
}
} else
gpa->ll = NULL;
/* Get peers from gossipd. */
subd_req(cmd, cmd->ld->gossip,
take(towire_gossip_getpeers_request(cmd, gpa->specific_id)),
-1, 0, gossipd_getpeers_complete, gpa);
command_still_pending(cmd);
}
static const struct json_command listpeers_command = {
"listpeers",
json_listpeers,
"Show current peers, if {level} is set, include logs for {id}"
};
AUTODATA(json_command, &listpeers_command);
struct peer *peer_from_json(struct lightningd *ld,
const char *buffer,
jsmntok_t *peeridtok)
{
struct pubkey peerid;
if (!json_tok_pubkey(buffer, peeridtok, &peerid))
return NULL;
return peer_by_id(ld, &peerid);
}
static enum watch_result funding_announce_cb(struct channel *channel,
const struct bitcoin_tx *tx,
unsigned int depth,
@ -659,50 +502,6 @@ static enum watch_result funding_announce_cb(struct channel *channel,
return DELETE_WATCH;
}
/* If channel is NULL, free them all (for shutdown) */
void free_htlcs(struct lightningd *ld, const struct channel *channel)
{
struct htlc_out_map_iter outi;
struct htlc_out *hout;
struct htlc_in_map_iter ini;
struct htlc_in *hin;
bool deleted;
/* FIXME: Implement check_htlcs to ensure no dangling hout->in ptrs! */
do {
deleted = false;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (channel && hout->key.channel != channel)
continue;
tal_free(hout);
deleted = true;
}
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (channel && hin->key.channel != channel)
continue;
tal_free(hin);
deleted = true;
}
/* Can skip over elements due to iterating while deleting. */
} while (deleted);
}
u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx)
{
struct pubkey shutdownkey;
if (!bip32_pubkey(ld->wallet->bip32_base, &shutdownkey, keyidx))
return NULL;
return scriptpubkey_p2wpkh(ctx, &shutdownkey);
}
static enum watch_result funding_lockin_cb(struct channel *channel,
const struct bitcoin_tx *tx,
unsigned int depth,
@ -964,29 +763,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
return 0;
}
u32 feerate_min(struct lightningd *ld)
{
if (ld->config.ignore_fee_limits)
return 1;
/* Set this to average of slow and normal.*/
return (get_feerate(ld->topology, FEERATE_SLOW)
+ get_feerate(ld->topology, FEERATE_NORMAL)) / 2;
}
/* BOLT #2:
*
* Given the variance in fees, and the fact that the transaction may
* be spent in the future, it's a good idea for the fee payer to keep
* a good margin, say 5x the expected fee requirement */
u32 feerate_max(struct lightningd *ld)
{
if (ld->config.ignore_fee_limits)
return UINT_MAX;
return get_feerate(ld->topology, FEERATE_IMMEDIATE) * 5;
}
bool peer_start_channeld(struct channel *channel,
const struct crypto_state *cs,
u64 gossip_index,
@ -1116,6 +892,174 @@ bool peer_start_channeld(struct channel *channel,
return true;
}
struct getpeers_args {
struct command *cmd;
/* If non-NULL, they want logs too */
enum log_level *ll;
/* If set, only report on a specific id. */
struct pubkey *specific_id;
};
static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg,
const int *fds,
struct getpeers_args *gpa)
{
/* This is a little sneaky... */
struct pubkey *ids;
struct wireaddr *addrs;
struct json_result *response = new_json_result(gpa->cmd);
struct peer *p;
if (!fromwire_gossip_getpeers_reply(msg, msg, NULL, &ids, &addrs)) {
command_fail(gpa->cmd, "Bad response from gossipd");
return;
}
/* First the peers not just gossiping. */
json_object_start(response, NULL);
json_array_start(response, "peers");
list_for_each(&gpa->cmd->ld->peers, p, list) {
bool connected;
struct channel *channel;
if (gpa->specific_id && !pubkey_eq(gpa->specific_id, &p->id))
continue;
json_object_start(response, NULL);
json_add_pubkey(response, "id", &p->id);
channel = peer_active_channel(p);
connected = (channel && channel->owner != NULL);
json_add_bool(response, "connected", connected);
if (connected) {
json_array_start(response, "netaddr");
if (p->addr.type != ADDR_TYPE_PADDING)
json_add_string(response, NULL,
type_to_string(response,
struct wireaddr,
&p->addr));
json_array_end(response);
}
json_array_start(response, "channels");
json_add_uncommitted_channel(response, p->uncommitted_channel);
list_for_each(&p->channels, channel, list) {
json_object_start(response, NULL);
json_add_string(response, "state",
channel_state_name(channel));
if (channel->owner)
json_add_string(response, "owner",
channel->owner->name);
if (channel->scid)
json_add_short_channel_id(response,
"short_channel_id",
channel->scid);
json_add_txid(response,
"funding_txid",
&channel->funding_txid);
json_add_u64(response, "msatoshi_to_us",
channel->our_msatoshi);
json_add_u64(response, "msatoshi_total",
channel->funding_satoshi * 1000);
/* channel config */
json_add_u64(response, "dust_limit_satoshis",
channel->our_config.dust_limit_satoshis);
json_add_u64(response, "max_htlc_value_in_flight_msat",
channel->our_config.max_htlc_value_in_flight_msat);
json_add_u64(response, "channel_reserve_satoshis",
channel->our_config.channel_reserve_satoshis);
json_add_u64(response, "htlc_minimum_msat",
channel->our_config.htlc_minimum_msat);
json_add_num(response, "to_self_delay",
channel->our_config.to_self_delay);
json_add_num(response, "max_accepted_htlcs",
channel->our_config.max_accepted_htlcs);
json_object_end(response);
}
json_array_end(response);
if (gpa->ll)
json_add_log(response, "log", p->log_book, *gpa->ll);
json_object_end(response);
}
for (size_t i = 0; i < tal_count(ids); i++) {
/* Don't report peers in both, which can happen if they're
* reconnecting */
if (peer_by_id(gpa->cmd->ld, ids + i))
continue;
json_object_start(response, NULL);
/* Fake state. */
json_add_string(response, "state", "GOSSIPING");
json_add_pubkey(response, "id", ids+i);
json_array_start(response, "netaddr");
if (addrs[i].type != ADDR_TYPE_PADDING)
json_add_string(response, NULL,
type_to_string(response, struct wireaddr,
addrs + i));
json_array_end(response);
json_add_bool(response, "connected", true);
json_add_string(response, "owner", gossip->name);
json_object_end(response);
}
json_array_end(response);
json_object_end(response);
command_success(gpa->cmd, response);
}
static void json_listpeers(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
jsmntok_t *leveltok;
struct getpeers_args *gpa = tal(cmd, struct getpeers_args);
jsmntok_t *idtok;
gpa->cmd = cmd;
gpa->specific_id = NULL;
if (!json_get_params(cmd, buffer, params,
"?id", &idtok,
"?level", &leveltok,
NULL)) {
return;
}
if (idtok) {
gpa->specific_id = tal_arr(cmd, struct pubkey, 1);
if (!json_tok_pubkey(buffer, idtok, gpa->specific_id)) {
command_fail(cmd, "id %.*s not valid",
idtok->end - idtok->start,
buffer + idtok->start);
return;
}
}
if (leveltok) {
gpa->ll = tal(gpa, enum log_level);
if (!json_tok_loglevel(buffer, leveltok, gpa->ll)) {
command_fail(cmd, "Invalid level param");
return;
}
} else
gpa->ll = NULL;
/* Get peers from gossipd. */
subd_req(cmd, cmd->ld->gossip,
take(towire_gossip_getpeers_request(cmd, gpa->specific_id)),
-1, 0, gossipd_getpeers_complete, gpa);
command_still_pending(cmd);
}
static const struct json_command listpeers_command = {
"listpeers",
json_listpeers,
"Show current peers, if {level} is set, include logs for {id}"
};
AUTODATA(json_command, &listpeers_command);
static void json_close(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{

View File

@ -71,9 +71,6 @@ struct peer *peer_from_json(struct lightningd *ld,
void peer_connected(struct lightningd *ld, const u8 *msg,
int peer_fd, int gossip_fd);
/* This simply means we asked to reach a peer, but we already have it */
void peer_already_connected(struct lightningd *ld, const u8 *msg);
void peer_sent_nongossip(struct lightningd *ld,
const struct pubkey *id,
const struct wireaddr *addr,
@ -107,8 +104,6 @@ void activate_peers(struct lightningd *ld);
void drop_to_chain(struct lightningd *ld, struct channel *channel);
void free_htlcs(struct lightningd *ld, const struct channel *channel);
/* Get range of feerates to insist other side abide by for normal channels. */
u32 feerate_min(struct lightningd *ld);
u32 feerate_max(struct lightningd *ld);

View File

@ -1414,6 +1414,40 @@ void peer_htlcs(const tal_t *ctx,
}
}
/* If channel is NULL, free them all (for shutdown) */
void free_htlcs(struct lightningd *ld, const struct channel *channel)
{
struct htlc_out_map_iter outi;
struct htlc_out *hout;
struct htlc_in_map_iter ini;
struct htlc_in *hin;
bool deleted;
/* FIXME: Implement check_htlcs to ensure no dangling hout->in ptrs! */
do {
deleted = false;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (channel && hout->key.channel != channel)
continue;
tal_free(hout);
deleted = true;
}
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (channel && hin->key.channel != channel)
continue;
tal_free(hin);
deleted = true;
}
/* Can skip over elements due to iterating while deleting. */
} while (deleted);
}
/* BOLT #2:
*
* For HTLCs we offer: the timeout deadline when we have to fail the channel

View File

@ -11,6 +11,7 @@ struct channel;
struct htlc_in;
struct htlc_out;
struct htlc_stub;
struct lightningd;
/* FIXME: Define serialization primitive for this? */
struct channel_info {
@ -34,6 +35,8 @@ void peer_htlcs(const tal_t *ctx,
const struct failed_htlc ***failed_htlcs,
enum side **failed_sides);
void free_htlcs(struct lightningd *ld, const struct channel *channel);
void peer_sending_commitsig(struct channel *channel, const u8 *msg);
void peer_got_commitsig(struct channel *channel, const u8 *msg);
void peer_got_revoke(struct channel *channel, const u8 *msg);