From e75d8e061b46f4c727de1ab772d2463a16e061c6 Mon Sep 17 00:00:00 2001 From: trueptolemy <823220586@qq.com> Date: Sat, 15 Jun 2019 21:09:09 +0800 Subject: [PATCH] Plugin: New notification type, forward_event `forward_event` A notification for topic `forward_event` is sent every time the status of a forward payment is set. The json format is same as the API `listforwards`. ```json { "forward_event": { "payment_hash": "f5a6a059a25d1e329d9b094aeeec8c2191ca037d3f5b0662e21ae850debe8ea2", "in_channel": "103x2x1", "out_channel": "103x1x1", "in_msatoshi": 100001001, "in_msat": "100001001msat", "out_msatoshi": 100000000, "out_msat": "100000000msat", "fee": 1001, "fee_msat": "1001msat", "status": "settled", "received_time": 1560696342.368, "resolved_time": 1560696342.556 } } ``` or ```json { "forward_event": { "payment_hash": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "in_channel": "103x2x1", "out_channel": "110x1x0", "in_msatoshi": 100001001, "in_msat": "100001001msat", "out_msatoshi": 100000000, "out_msat": "100000000msat", "fee": 1001, "fee_msat": "1001msat", "status": "local_failed", "failcode": 16392, "failreason": "WIRE_PERMANENT_CHANNEL_FAILURE", "received_time": 1560696343.052 } } ``` - The status includes `offered`, `settled`, `failed` and `local_failed`, and they are all string type in json. - When the forward payment is valid for us, we'll set `offered` and send the forward payment to next hop to resolve; - When the payment forwarded by us gets paid eventually, the forward payment will change the status from `offered` to `settled`; - If payment fails locally(like failing to resolve locally) or the corresponding htlc with next hop fails(like htlc timeout), we will set the status as `local_failed`. `local_failed` may be set before setting `offered` or after setting `offered`. In fact, from the time we receive the htlc of the previous hop, all we can know the cause of the failure is treated as `local_failed`. `local_failed` only occuors locally or happens in the htlc between us and next hop; - If `local_failed` is set before `offered`, this means we just received htlc from the previous hop and haven't generate htlc for next hop. In this case, the json of `forward_event` sets the fields of `out_msatoshi`, `out_msat`,`fee` and `out_channel` as 0; - Note: In fact, for this case we may be not sure if this incoming htlc represents a pay to us or a payment we need to forward. We just simply treat all incoming failed to resolve as `local_failed`. - Only in `local_failed` case, json includes `failcode` and `failreason` fields; - `failed` means the payment forwarded by us fails in the latter hops, and the failure isn't related to us, so we aren't accessed to the fail reason. `failed` must be set after `offered`. - `failed` case doesn't include `failcode` and `failreason` fields; - `received_time` means when we received the htlc of this payment from the previous peer. It will be contained into all status case; - `resolved_time` means when the htlc of this payment between us and the next peer was resolved. The resolved result may success or fail, so only `settled` and `failed` case contain `resolved_time`; - The `failcode` and `failreason` are defined in [BOLT 4][bolt4-failure-codes]. --- lightningd/notification.c | 41 ++++++++++++++++++++++++++++++++++++++- lightningd/notification.h | 8 ++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lightningd/notification.c b/lightningd/notification.c index 55de51e9c..ddc241512 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -1,13 +1,16 @@ #include +#include #include #include +#include const char *notification_topics[] = { "connect", "disconnect", "warning", "invoice_payment", - "channel_opened" + "channel_opened", + "forward_event" }; bool notifications_have_topic(const char *topic) @@ -93,3 +96,39 @@ void notify_channel_opened(struct lightningd *ld, struct node_id *node_id, jsonrpc_notification_end(n); plugins_notify(ld->plugins, take(n)); } + +void notify_forward_event(struct lightningd *ld, + const struct htlc_in *in, + const struct htlc_out *out, + enum forward_status state, + enum onion_type failcode, + struct timeabs *resolved_time) +{ + struct jsonrpc_notification *n = + jsonrpc_notification_start(NULL, "forward_event"); + /* Here is more neat to initial a forwarding structure than + * to pass in a bunch of parameters directly*/ + struct forwarding *cur = tal(tmpctx, struct forwarding); + cur->channel_in = *in->key.channel->scid; + cur->msat_in = in->msat; + if (out) { + cur->channel_out = *out->key.channel->scid; + cur->msat_out = out->msat; + assert(amount_msat_sub(&cur->fee, in->msat, out->msat)); + } else { + cur->channel_out.u64 = 0; + cur->msat_out = AMOUNT_MSAT(0); + cur->fee = AMOUNT_MSAT(0); + } + cur->payment_hash = tal(cur, struct sha256_double); + cur->payment_hash->sha = in->payment_hash; + cur->status = state; + cur->failcode = failcode; + cur->received_time = in->received_time; + cur->resolved_time = tal_steal(cur, resolved_time); + + json_format_forwarding_object(n->stream, "forward_event", cur); + + jsonrpc_notification_end(n); + plugins_notify(ld->plugins, take(n)); +} diff --git a/lightningd/notification.h b/lightningd/notification.h index 8d4c23870..7db53d46f 100644 --- a/lightningd/notification.h +++ b/lightningd/notification.h @@ -10,6 +10,7 @@ #include #include #include +#include bool notifications_have_topic(const char *topic); @@ -26,4 +27,11 @@ void notify_channel_opened(struct lightningd *ld, struct node_id *node_id, struct amount_sat *funding_sat, struct bitcoin_txid *funding_txid, bool *funding_locked); +void notify_forward_event(struct lightningd *ld, + const struct htlc_in *in, + const struct htlc_out *out, + enum forward_status state, + enum onion_type failcode, + struct timeabs *resolved_time); + #endif /* LIGHTNING_LIGHTNINGD_NOTIFICATION_H */