1
1
#include "config.h"
2
2
#include <common/json_stream.h>
3
+ #include <common/onionreply.h>
4
+ #include <common/sphinx.h>
3
5
#include <plugins/renepay/json.h>
4
6
5
7
/* See if this notification is about one of our flows. */
@@ -72,12 +74,103 @@ struct route *tal_route_from_json(const tal_t *ctx, const char *buf,
72
74
return tal_free (route );
73
75
}
74
76
77
+ static bool get_data_details_onionreply (struct payment_result * result ,
78
+ const char * buffer ,
79
+ const jsmntok_t * datatok ,
80
+ struct secret * shared_secrets )
81
+ {
82
+ const tal_t * this_ctx = tal (result , tal_t );
83
+ const jsmntok_t * onionreplytok ;
84
+ struct onionreply * onionreply , * wonionreply ;
85
+ const u8 * replymsg ;
86
+ int index ;
87
+
88
+ onionreplytok = json_get_member (buffer , datatok , "onionreply" );
89
+ if (!onionreplytok || !shared_secrets )
90
+ goto fail ;
91
+ onionreply = new_onionreply (
92
+ this_ctx ,
93
+ take (json_tok_bin_from_hex (this_ctx , buffer , onionreplytok )));
94
+ assert (onionreply );
95
+ /* FIXME: It seems that lightningd will unwrap top portion of the
96
+ * onionreply for us before serializing it, while unwrap_onionreply will
97
+ * try to do the entire unwraping. It would be a better API if either
98
+ * lightningd unwraps the entire thing or it doesn't do any unwraping.
99
+ * Also it wouldn't hurt if injectpaymentonion accepted the shared
100
+ * secrets to allow lightningd do the decoding for us. */
101
+ wonionreply = wrap_onionreply (this_ctx , & shared_secrets [0 ], onionreply );
102
+ replymsg = unwrap_onionreply (this_ctx , shared_secrets ,
103
+ tal_count (shared_secrets ),
104
+ wonionreply , & index );
105
+ if (replymsg ) {
106
+ result -> failcode = tal (result , enum onion_wire );
107
+ * result -> failcode = fromwire_peektype (replymsg );
108
+
109
+ result -> erring_index = tal (result , u32 );
110
+ * result -> erring_index = index ;
111
+ }
112
+ tal_free (this_ctx );
113
+ return true;
114
+ fail :
115
+ tal_free (this_ctx );
116
+ return false;
117
+ }
118
+
119
+ static bool get_data_details (struct payment_result * result ,
120
+ const char * buffer ,
121
+ const jsmntok_t * datatok )
122
+ {
123
+
124
+ const jsmntok_t * erridxtok , * failcodetok , * errnodetok , * errchantok ,
125
+ * errdirtok , * rawmsgtok , * failcodenametok ;
126
+ erridxtok = json_get_member (buffer , datatok , "erring_index" );
127
+ failcodetok = json_get_member (buffer , datatok , "failcode" );
128
+
129
+ if (!erridxtok || !failcodetok )
130
+ return false;
131
+ result -> failcode = tal (result , enum onion_wire );
132
+ json_to_u32 (buffer , failcodetok , result -> failcode );
133
+
134
+ result -> erring_index = tal (result , u32 );
135
+ json_to_u32 (buffer , erridxtok , result -> erring_index );
136
+
137
+ // search for other fields
138
+ errnodetok = json_get_member (buffer , datatok , "erring_node" );
139
+ errchantok = json_get_member (buffer , datatok , "erring_channel" );
140
+ errdirtok = json_get_member (buffer , datatok , "erring_direction" );
141
+ failcodenametok = json_get_member (buffer , datatok , "failcodename" );
142
+ rawmsgtok = json_get_member (buffer , datatok , "raw_message" );
143
+
144
+ if (errnodetok != NULL ) {
145
+ result -> erring_node = tal (result , struct node_id );
146
+ json_to_node_id (buffer , errnodetok , result -> erring_node );
147
+ }
148
+
149
+ if (errchantok != NULL ) {
150
+ result -> erring_channel = tal (result , struct short_channel_id );
151
+ json_to_short_channel_id (buffer , errchantok ,
152
+ result -> erring_channel );
153
+ }
154
+ if (errdirtok != NULL ) {
155
+ result -> erring_direction = tal (result , int );
156
+ json_to_int (buffer , errdirtok , result -> erring_direction );
157
+ }
158
+ if (rawmsgtok != NULL )
159
+ result -> raw_message =
160
+ json_tok_bin_from_hex (result , buffer , rawmsgtok );
161
+
162
+ if (failcodenametok != NULL )
163
+ result -> failcodename =
164
+ json_strdup (result , buffer , failcodenametok );
165
+
166
+ return true;
167
+ }
168
+
75
169
struct payment_result * tal_sendpay_result_from_json (const tal_t * ctx ,
76
170
const char * buffer ,
77
- const jsmntok_t * toks )
171
+ const jsmntok_t * toks ,
172
+ struct secret * shared_secrets )
78
173
{
79
- // FIXME: we will be getting onionreply try to decode these with
80
- // shared_secrets
81
174
const jsmntok_t * idtok = json_get_member (buffer , toks , "created_index" );
82
175
const jsmntok_t * hashtok =
83
176
json_get_member (buffer , toks , "payment_hash" );
@@ -89,8 +182,6 @@ struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx,
89
182
const jsmntok_t * codetok = json_get_member (buffer , toks , "code" );
90
183
const jsmntok_t * msgtok = json_get_member (buffer , toks , "message" );
91
184
const jsmntok_t * datatok = json_get_member (buffer , toks , "data" );
92
- const jsmntok_t * erridxtok , * failcodetok , * rawmsgtok ,
93
- * failcodenametok , * errchantok , * errnodetok , * errdirtok ;
94
185
struct payment_result * result ;
95
186
96
187
/* Check if we have an error and need to descend into data to get
@@ -110,6 +201,7 @@ struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx,
110
201
}
111
202
112
203
result = tal (ctx , struct payment_result );
204
+ memset (result , 0 , sizeof (struct payment_result ));
113
205
114
206
if (msgtok )
115
207
result -> message = json_strdup (result , buffer , msgtok );
@@ -147,77 +239,12 @@ struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx,
147
239
148
240
/* Now extract the error details if the error code is not 0 */
149
241
if (result -> code != 0 && datatok ) {
150
- erridxtok = json_get_member (buffer , datatok , "erring_index" );
151
- errnodetok = json_get_member (buffer , datatok , "erring_node" );
152
- errchantok = json_get_member (buffer , datatok , "erring_channel" );
153
- errdirtok =
154
- json_get_member (buffer , datatok , "erring_direction" );
155
- failcodetok = json_get_member (buffer , datatok , "failcode" );
156
- failcodenametok =
157
- json_get_member (buffer , datatok , "failcodename" );
158
- rawmsgtok = json_get_member (buffer , datatok , "raw_message" );
159
- /* check type for sanity */
160
- if ((failcodetok != NULL &&
161
- failcodetok -> type != JSMN_PRIMITIVE ) ||
162
- (failcodenametok != NULL &&
163
- failcodenametok -> type != JSMN_STRING ) ||
164
- (erridxtok != NULL && erridxtok -> type != JSMN_PRIMITIVE ) ||
165
- (errnodetok != NULL && errnodetok -> type != JSMN_STRING ) ||
166
- (errchantok != NULL && errchantok -> type != JSMN_STRING ) ||
167
- (errdirtok != NULL && errdirtok -> type != JSMN_PRIMITIVE ) ||
168
- (rawmsgtok != NULL && rawmsgtok -> type != JSMN_STRING ))
242
+ /* try one, then try the other, then fail */
243
+ if (!get_data_details (result , buffer , datatok ) &&
244
+ !get_data_details_onionreply (result , buffer , datatok ,
245
+ shared_secrets ))
169
246
goto fail ;
170
-
171
- if (rawmsgtok != NULL )
172
- result -> raw_message =
173
- json_tok_bin_from_hex (result , buffer , rawmsgtok );
174
- else
175
- result -> raw_message = NULL ;
176
-
177
- if (failcodenametok != NULL )
178
- result -> failcodename =
179
- json_strdup (result , buffer , failcodenametok );
180
- else
181
- result -> failcodename = NULL ;
182
-
183
- if (failcodetok ){
184
- result -> failcode = tal (result , enum onion_wire );
185
- json_to_u32 (buffer , failcodetok , result -> failcode );
186
- }else
187
- result -> failcode = NULL ;
188
- if (erridxtok != NULL ) {
189
- result -> erring_index = tal (result , u32 );
190
- json_to_u32 (buffer , erridxtok , result -> erring_index );
191
- } else {
192
- result -> erring_index = NULL ;
193
- }
194
-
195
- if (errdirtok != NULL ) {
196
- result -> erring_direction = tal (result , int );
197
- json_to_int (buffer , errdirtok ,
198
- result -> erring_direction );
199
- } else {
200
- result -> erring_direction = NULL ;
201
- }
202
-
203
- if (errnodetok != NULL ) {
204
- result -> erring_node = tal (result , struct node_id );
205
- json_to_node_id (buffer , errnodetok ,
206
- result -> erring_node );
207
- } else {
208
- result -> erring_node = NULL ;
209
- }
210
-
211
- if (errchantok != NULL ) {
212
- result -> erring_channel =
213
- tal (result , struct short_channel_id );
214
- json_to_short_channel_id (buffer , errchantok ,
215
- result -> erring_channel );
216
- } else {
217
- result -> erring_channel = NULL ;
218
- }
219
247
}
220
-
221
248
return result ;
222
249
fail :
223
250
return tal_free (result );
0 commit comments