@@ -21,6 +21,7 @@ struct routefail {
21
21
22
22
static struct command_result * update_gossip (struct routefail * r );
23
23
static struct command_result * handle_failure (struct routefail * r );
24
+ static void find_erring_node (struct route * route );
24
25
25
26
struct command_result * routefail_start (const tal_t * ctx , struct route * route ,
26
27
struct command * cmd )
@@ -40,9 +41,60 @@ struct command_result *routefail_start(const tal_t *ctx, struct route *route,
40
41
r -> route = route ;
41
42
r -> cmd = cmd ;
42
43
assert (route -> result );
44
+ find_erring_node (route );
43
45
return update_gossip (r );
44
46
}
45
47
48
+ /* The erring_node and erring_channel are necessary fields to handle the error.
49
+ * We might not know those values from listsendpays because the payment could
50
+ * have been paid with sendonion or similar RPCs, but if we know the route then
51
+ * we can deduce them just like lightningd's wallet would with a sendpay
52
+ * command. */
53
+ static void find_erring_node (struct route * route )
54
+ {
55
+ struct payment_result * result = route -> result ;
56
+ if (result -> erring_node && result -> erring_channel &&
57
+ result -> erring_direction )
58
+ return ;
59
+
60
+ /* we need the hops, othewise our assumptions are wrong */
61
+ assert (route -> hops );
62
+ assert (result -> erring_index );
63
+ unsigned int index = * result -> erring_index ;
64
+ unsigned int path_len = tal_count (route -> hops );
65
+
66
+ /* self-pay failure? */
67
+ assert (path_len > 0 );
68
+ assert (index >= 0 );
69
+ assert (path_len >= index );
70
+
71
+ if (index == path_len - 1 ) {
72
+ result -> erring_channel = tal_dup (
73
+ result , struct short_channel_id , & route -> hops [index ].scid );
74
+ result -> erring_direction =
75
+ tal_dup (result , int , & route -> hops [index ].direction );
76
+ result -> erring_node = tal_dup (result , struct node_id ,
77
+ & route -> hops [index ].node_id );
78
+ } else {
79
+ result -> erring_channel =
80
+ tal_dup (result , struct short_channel_id ,
81
+ & route -> hops [index + 1 ].scid );
82
+ result -> erring_direction =
83
+ tal_dup (result , int , & route -> hops [index + 1 ].direction );
84
+
85
+ /* If the error is a BADONION, then it's on behalf of the
86
+ * following node. */
87
+ if (result -> failcode & BADONION )
88
+ result -> erring_node =
89
+ tal_dup (result , struct node_id ,
90
+ & route -> hops [index + 1 ].node_id );
91
+ else
92
+ result -> erring_node =
93
+ tal_dup (result , struct node_id ,
94
+ & route -> hops [index ].node_id );
95
+ }
96
+ }
97
+
46
98
static struct command_result * routefail_end (struct routefail * r TAKES )
47
99
{
48
100
/* Notify the tracker that route has failed and routefail have completed
@@ -188,6 +240,7 @@ static void route_final_error(struct route *route, enum jsonrpc_errcode error,
188
240
route -> final_msg = tal_strdup (route , what );
189
241
}
190
242
243
+ /* FIXME: do proper error handling for BOLT12 */
191
244
static struct command_result * handle_failure (struct routefail * r )
192
245
{
193
246
/* BOLT #4:
0 commit comments