diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 392660c7d..d0e19ab23 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -432,6 +432,187 @@ struct peer_connected_hook_response { enum peer_connected_hook_result result; }; +static void json_add_htlcs(struct lightningd *ld, + struct json_stream *response, + const struct channel *channel) +{ + /* FIXME: make per-channel htlc maps! */ + const struct htlc_in *hin; + struct htlc_in_map_iter ini; + const struct htlc_out *hout; + struct htlc_out_map_iter outi; + + /* FIXME: Add more fields. */ + json_array_start(response, "htlcs"); + for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); + hin; + hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { + if (hin->key.channel != channel) + continue; + + json_object_start(response, NULL); + json_add_string(response, "direction", "in"); + json_add_u64(response, "id", hin->key.id); + json_add_u64(response, "msatoshi", hin->msatoshi); + json_add_u64(response, "expiry", hin->cltv_expiry); + json_add_hex(response, "payment_hash", + &hin->payment_hash, sizeof(hin->payment_hash)); + json_add_string(response, "state", + htlc_state_name(hin->hstate)); + json_object_end(response); + } + + for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); + hout; + hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { + if (hout->key.channel != channel) + continue; + + json_object_start(response, NULL); + json_add_string(response, "direction", "out"); + json_add_u64(response, "id", hout->key.id); + json_add_u64(response, "msatoshi", hout->msatoshi); + json_add_u64(response, "expiry", hout->cltv_expiry); + json_add_hex(response, "payment_hash", + &hout->payment_hash, sizeof(hout->payment_hash)); + json_add_string(response, "state", + htlc_state_name(hout->hstate)); + json_object_end(response); + } + json_array_end(response); +} + +static void json_add_channel(struct lightningd *ld, + struct json_stream *response, const char *key, + const struct channel *channel) +{ + struct channel_id cid; + struct channel_stats channel_stats; + struct peer *p = channel->peer; + + u64 our_reserve_msat = + channel->channel_info.their_config.channel_reserve_satoshis * 1000; + json_object_start(response, key); + json_add_string(response, "state", channel_state_name(channel)); + if (channel->last_tx) { + struct bitcoin_txid txid; + bitcoin_txid(channel->last_tx, &txid); + + json_add_txid(response, "scratch_txid", &txid); + } + 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_num(response, "direction", + pubkey_idx(&ld->id, &channel->peer->id)); + } + + derive_channel_id(&cid, &channel->funding_txid, + channel->funding_outnum); + json_add_string(response, "channel_id", + type_to_string(tmpctx, struct channel_id, &cid)); + json_add_txid(response, "funding_txid", &channel->funding_txid); + json_add_bool( + response, "private", + !(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)); + + // FIXME @conscott : Modify this when dual-funded channels + // are implemented + json_object_start(response, "funding_allocation_msat"); + if (channel->funder == LOCAL) { + json_add_u64(response, pubkey_to_hexstr(tmpctx, &p->id), 0); + json_add_u64(response, pubkey_to_hexstr(tmpctx, &ld->id), + channel->funding_satoshi * 1000); + } else { + json_add_u64(response, pubkey_to_hexstr(tmpctx, &ld->id), 0); + json_add_u64(response, pubkey_to_hexstr(tmpctx, &p->id), + channel->funding_satoshi * 1000); + } + json_object_end(response); + + json_add_u64(response, "msatoshi_to_us", channel->our_msatoshi); + json_add_u64(response, "msatoshi_to_us_min", + channel->msatoshi_to_us_min); + json_add_u64(response, "msatoshi_to_us_max", + channel->msatoshi_to_us_max); + 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); + + /* The `channel_reserve_satoshis` is imposed on + * the *other* side (see `channel_reserve_msat` + * function in, it uses `!side` to flip sides). + * So our configuration `channel_reserve_satoshis` + * is imposed on their side, while their + * configuration `channel_reserve_satoshis` is + * imposed on ours. */ + json_add_u64(response, "their_channel_reserve_satoshis", + channel->our_config.channel_reserve_satoshis); + json_add_u64( + response, "our_channel_reserve_satoshis", + channel->channel_info.their_config.channel_reserve_satoshis); + /* Compute how much we can send via this channel. */ + if (channel->our_msatoshi <= our_reserve_msat) + json_add_u64(response, "spendable_msatoshi", 0); + else + json_add_u64(response, "spendable_msatoshi", + channel->our_msatoshi - our_reserve_msat); + json_add_u64(response, "htlc_minimum_msat", + channel->our_config.htlc_minimum_msat); + + /* The `to_self_delay` is imposed on the *other* + * side, so our configuration `to_self_delay` is + * imposed on their side, while their configuration + * `to_self_delay` is imposed on ours. */ + json_add_num(response, "their_to_self_delay", + channel->our_config.to_self_delay); + json_add_num(response, "our_to_self_delay", + channel->channel_info.their_config.to_self_delay); + json_add_num(response, "max_accepted_htlcs", + channel->our_config.max_accepted_htlcs); + + json_array_start(response, "status"); + for (size_t i = 0; i < ARRAY_SIZE(channel->billboard.permanent); i++) { + if (!channel->billboard.permanent[i]) + continue; + json_add_string(response, NULL, + channel->billboard.permanent[i]); + } + if (channel->billboard.transient) + json_add_string(response, NULL, channel->billboard.transient); + json_array_end(response); + + /* Provide channel statistics */ + wallet_channel_stats_load(ld->wallet, channel->dbid, &channel_stats); + json_add_u64(response, "in_payments_offered", + channel_stats.in_payments_offered); + json_add_u64(response, "in_msatoshi_offered", + channel_stats.in_msatoshi_offered); + json_add_u64(response, "in_payments_fulfilled", + channel_stats.in_payments_fulfilled); + json_add_u64(response, "in_msatoshi_fulfilled", + channel_stats.in_msatoshi_fulfilled); + json_add_u64(response, "out_payments_offered", + channel_stats.out_payments_offered); + json_add_u64(response, "out_msatoshi_offered", + channel_stats.out_msatoshi_offered); + json_add_u64(response, "out_payments_fulfilled", + channel_stats.out_payments_fulfilled); + json_add_u64(response, "out_msatoshi_fulfilled", + channel_stats.out_msatoshi_fulfilled); + + json_add_htlcs(ld, response, channel); + json_object_end(response); +} + static void peer_connected_serialize(struct peer_connected_hook_payload *payload, struct json_stream *stream) @@ -663,56 +844,6 @@ void channel_watch_funding(struct lightningd *ld, struct channel *channel) funding_spent); } -static void json_add_htlcs(struct lightningd *ld, - struct json_stream *response, - const struct channel *channel) -{ - /* FIXME: make per-channel htlc maps! */ - const struct htlc_in *hin; - struct htlc_in_map_iter ini; - const struct htlc_out *hout; - struct htlc_out_map_iter outi; - - /* FIXME: Add more fields. */ - json_array_start(response, "htlcs"); - for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); - hin; - hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { - if (hin->key.channel != channel) - continue; - - json_object_start(response, NULL); - json_add_string(response, "direction", "in"); - json_add_u64(response, "id", hin->key.id); - json_add_u64(response, "msatoshi", hin->msatoshi); - json_add_u64(response, "expiry", hin->cltv_expiry); - json_add_hex(response, "payment_hash", - &hin->payment_hash, sizeof(hin->payment_hash)); - json_add_string(response, "state", - htlc_state_name(hin->hstate)); - json_object_end(response); - } - - for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); - hout; - hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { - if (hout->key.channel != channel) - continue; - - json_object_start(response, NULL); - json_add_string(response, "direction", "out"); - json_add_u64(response, "id", hout->key.id); - json_add_u64(response, "msatoshi", hout->msatoshi); - json_add_u64(response, "expiry", hout->cltv_expiry); - json_add_hex(response, "payment_hash", - &hout->payment_hash, sizeof(hout->payment_hash)); - json_add_string(response, "state", - htlc_state_name(hout->hstate)); - json_object_end(response); - } - json_array_end(response); -} - static void json_add_peer(struct lightningd *ld, struct json_stream *response, struct peer *p, @@ -758,138 +889,8 @@ static void json_add_peer(struct lightningd *ld, json_array_start(response, "channels"); json_add_uncommitted_channel(response, p->uncommitted_channel); - list_for_each(&p->channels, channel, list) { - struct channel_id cid; - struct channel_stats channel_stats; - u64 our_reserve_msat = channel->channel_info.their_config.channel_reserve_satoshis * 1000; - json_object_start(response, NULL); - json_add_string(response, "state", - channel_state_name(channel)); - if (channel->last_tx) { - struct bitcoin_txid txid; - bitcoin_txid(channel->last_tx, &txid); - - json_add_txid(response, "scratch_txid", &txid); - } - 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_num(response, "direction", - pubkey_idx(&ld->id, &p->id)); - } - derive_channel_id(&cid, - &channel->funding_txid, - channel->funding_outnum); - json_add_string(response, "channel_id", - type_to_string(tmpctx, struct channel_id, &cid)); - json_add_txid(response, - "funding_txid", - &channel->funding_txid); - json_add_bool(response, "private", - !(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)); - - // FIXME @conscott : Modify this when dual-funded channels - // are implemented - json_object_start(response, "funding_allocation_msat"); - if (channel->funder == LOCAL) { - json_add_u64(response, pubkey_to_hexstr(tmpctx, &p->id), 0); - json_add_u64(response, pubkey_to_hexstr(tmpctx, &ld->id), - channel->funding_satoshi * 1000); - } else { - json_add_u64(response, pubkey_to_hexstr(tmpctx, &ld->id), 0); - json_add_u64(response, pubkey_to_hexstr(tmpctx, &p->id), - channel->funding_satoshi * 1000); - } - json_object_end(response); - - json_add_u64(response, "msatoshi_to_us", - channel->our_msatoshi); - json_add_u64(response, "msatoshi_to_us_min", - channel->msatoshi_to_us_min); - json_add_u64(response, "msatoshi_to_us_max", - channel->msatoshi_to_us_max); - 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); - - /* The `channel_reserve_satoshis` is imposed on - * the *other* side (see `channel_reserve_msat` - * function in, it uses `!side` to flip sides). - * So our configuration `channel_reserve_satoshis` - * is imposed on their side, while their - * configuration `channel_reserve_satoshis` is - * imposed on ours. */ - json_add_u64(response, "their_channel_reserve_satoshis", - channel->our_config.channel_reserve_satoshis); - json_add_u64(response, "our_channel_reserve_satoshis", - channel->channel_info.their_config.channel_reserve_satoshis); - /* Compute how much we can send via this channel. */ - if (channel->our_msatoshi <= our_reserve_msat) - json_add_u64(response, "spendable_msatoshi", 0); - else - json_add_u64(response, "spendable_msatoshi", - channel->our_msatoshi - our_reserve_msat); - json_add_u64(response, "htlc_minimum_msat", - channel->our_config.htlc_minimum_msat); - - /* The `to_self_delay` is imposed on the *other* - * side, so our configuration `to_self_delay` is - * imposed on their side, while their configuration - * `to_self_delay` is imposed on ours. */ - json_add_num(response, "their_to_self_delay", - channel->our_config.to_self_delay); - json_add_num(response, "our_to_self_delay", - channel->channel_info.their_config.to_self_delay); - json_add_num(response, "max_accepted_htlcs", - channel->our_config.max_accepted_htlcs); - - json_array_start(response, "status"); - for (size_t i = 0; - i < ARRAY_SIZE(channel->billboard.permanent); - i++) { - if (!channel->billboard.permanent[i]) - continue; - json_add_string(response, NULL, - channel->billboard.permanent[i]); - } - if (channel->billboard.transient) - json_add_string(response, NULL, - channel->billboard.transient); - json_array_end(response); - - /* Provide channel statistics */ - wallet_channel_stats_load(ld->wallet, - channel->dbid, - &channel_stats); - json_add_u64(response, "in_payments_offered", - channel_stats.in_payments_offered); - json_add_u64(response, "in_msatoshi_offered", - channel_stats.in_msatoshi_offered); - json_add_u64(response, "in_payments_fulfilled", - channel_stats.in_payments_fulfilled); - json_add_u64(response, "in_msatoshi_fulfilled", - channel_stats.in_msatoshi_fulfilled); - json_add_u64(response, "out_payments_offered", - channel_stats.out_payments_offered); - json_add_u64(response, "out_msatoshi_offered", - channel_stats.out_msatoshi_offered); - json_add_u64(response, "out_payments_fulfilled", - channel_stats.out_payments_fulfilled); - json_add_u64(response, "out_msatoshi_fulfilled", - channel_stats.out_msatoshi_fulfilled); - - json_add_htlcs(ld, response, channel); - json_object_end(response); - } + list_for_each(&p->channels, channel, list) + json_add_channel(ld, response, NULL, channel); json_array_end(response); if (ll)