forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson_helpers.c
317 lines (281 loc) · 9.09 KB
/
json_helpers.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#include <arpa/inet.h>
#include <bitcoin/preimage.h>
#include <bitcoin/privkey.h>
#include <bitcoin/psbt.h>
#include <bitcoin/pubkey.h>
#include <ccan/ccan/str/hex/hex.h>
#include <common/amount.h>
#include <common/channel_id.h>
#include <common/json_helpers.h>
#include <common/json_stream.h>
#include <common/node_id.h>
#include <common/type_to_string.h>
#include <common/wireaddr.h>
#include <errno.h>
bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok,
uint64_t *satoshi)
{
char *end;
unsigned long btc, sat;
btc = strtoul(buffer + tok->start, &end, 10);
if (btc == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end) {
/* Expect always 8 decimal places. */
if (*end != '.' || buffer + tok->end - end != 9)
return false;
sat = strtoul(end+1, &end, 10);
if (sat == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end)
return false;
} else
sat = 0;
*satoshi = btc * (uint64_t)100000000 + sat;
if (*satoshi != btc * (uint64_t)100000000 + sat)
return false;
return true;
}
bool json_to_node_id(const char *buffer, const jsmntok_t *tok,
struct node_id *id)
{
return node_id_from_hexstr(buffer + tok->start,
tok->end - tok->start, id);
}
bool json_to_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey)
{
return pubkey_from_hexstr(buffer + tok->start,
tok->end - tok->start, pubkey);
}
bool json_to_msat(const char *buffer, const jsmntok_t *tok,
struct amount_msat *msat)
{
return parse_amount_msat(msat,
buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
return parse_amount_sat(sat, buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat_or_all(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
if (json_tok_streq(buffer, tok, "all")) {
*sat = AMOUNT_SAT(-1ULL);
return true;
}
return json_to_sat(buffer, tok, sat);
}
bool json_to_short_channel_id(const char *buffer, const jsmntok_t *tok,
struct short_channel_id *scid)
{
return (short_channel_id_from_str(buffer + tok->start,
tok->end - tok->start, scid));
}
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid)
{
return bitcoin_txid_from_hex(buffer + tok->start,
tok->end - tok->start, txid);
}
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
cid, sizeof(*cid));
}
bool split_tok(const char *buffer, const jsmntok_t *tok,
char split,
jsmntok_t *a,
jsmntok_t *b)
{
const char *p = memchr(buffer + tok->start, split, tok->end - tok->start);
if (!p)
return false;
*a = *b = *tok;
a->end = p - buffer;
b->start = p + 1 - buffer;
return true;
}
bool json_to_secret(const char *buffer, const jsmntok_t *tok, struct secret *dest)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
dest->data, sizeof(struct secret));
}
bool json_to_preimage(const char *buffer, const jsmntok_t *tok, struct preimage *preimage)
{
size_t hexlen = tok->end - tok->start;
return hex_decode(buffer + tok->start, hexlen, preimage->r, sizeof(preimage->r));
}
void json_add_node_id(struct json_stream *response,
const char *fieldname,
const struct node_id *id)
{
json_add_hex(response, fieldname, id->k, sizeof(id->k));
}
void json_add_pubkey(struct json_stream *response,
const char *fieldname,
const struct pubkey *key)
{
u8 der[PUBKEY_CMPR_LEN];
pubkey_to_der(der, key);
json_add_hex(response, fieldname, der, sizeof(der));
}
void json_add_txid(struct json_stream *result, const char *fieldname,
const struct bitcoin_txid *txid)
{
char hex[hex_str_size(sizeof(*txid))];
bitcoin_txid_to_hex(txid, hex, sizeof(hex));
json_add_string(result, fieldname, hex);
}
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *scid)
{
json_add_member(response, fieldname, true, "%dx%dx%d",
short_channel_id_blocknum(scid),
short_channel_id_txnum(scid),
short_channel_id_outnum(scid));
}
void json_add_short_channel_id_dir(struct json_stream *response,
const char *fieldname,
const struct short_channel_id_dir *scidd)
{
json_add_member(response, fieldname, true, "%dx%dx%d/%d",
short_channel_id_blocknum(&scidd->scid),
short_channel_id_txnum(&scidd->scid),
short_channel_id_outnum(&scidd->scid),
scidd->dir
);
}
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr)
{
json_object_start(response, fieldname);
char *addrstr = tal_arr(response, char, INET6_ADDRSTRLEN);
if (addr->type == ADDR_TYPE_IPV4) {
inet_ntop(AF_INET, addr->addr, addrstr, INET_ADDRSTRLEN);
json_add_string(response, "type", "ipv4");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_IPV6) {
inet_ntop(AF_INET6, addr->addr, addrstr, INET6_ADDRSTRLEN);
json_add_string(response, "type", "ipv6");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V2) {
json_add_string(response, "type", "torv2");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V3) {
json_add_string(response, "type", "torv3");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
}
json_object_end(response);
}
void json_add_address_internal(struct json_stream *response,
const char *fieldname,
const struct wireaddr_internal *addr)
{
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
json_object_start(response, fieldname);
json_add_string(response, "type", "local socket");
json_add_string(response, "socket", addr->u.sockname);
json_object_end(response);
return;
case ADDR_INTERNAL_ALLPROTO:
json_object_start(response, fieldname);
json_add_string(response, "type", "any protocol");
json_add_num(response, "port", addr->u.port);
json_object_end(response);
return;
case ADDR_INTERNAL_AUTOTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor generated address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_STATICTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor from blob generated static address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_FORPROXY:
json_object_start(response, fieldname);
json_add_string(response, "type", "unresolved");
json_add_string(response, "name", addr->u.unresolved.name);
json_add_num(response, "port", addr->u.unresolved.port);
json_object_end(response);
return;
case ADDR_INTERNAL_WIREADDR:
json_add_address(response, fieldname, &addr->u.wireaddr);
return;
}
abort();
}
void json_add_tx(struct json_stream *result,
const char *fieldname,
const struct bitcoin_tx *tx)
{
json_add_hex_talarr(result, fieldname, linearize_tx(tmpctx, tx));
}
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
struct wally_psbt *psbt)
{
const char *psbt_b64;
psbt_b64 = psbt_to_b64(NULL, psbt);
json_add_string(stream, fieldname, take(psbt_b64));
}
void json_add_amount_msat_compat(struct json_stream *result,
struct amount_msat msat,
const char *rawfieldname,
const char *msatfieldname)
{
json_add_u64(result, rawfieldname, msat.millisatoshis); /* Raw: low-level helper */
json_add_amount_msat_only(result, msatfieldname, msat);
}
void json_add_amount_msat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_msat msat)
{
json_add_string(result, msatfieldname,
type_to_string(tmpctx, struct amount_msat, &msat));
}
void json_add_amount_sat_compat(struct json_stream *result,
struct amount_sat sat,
const char *rawfieldname,
const char *msatfieldname)
{
json_add_u64(result, rawfieldname, sat.satoshis); /* Raw: low-level helper */
json_add_amount_sat_only(result, msatfieldname, sat);
}
void json_add_amount_sat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
{
struct amount_msat msat;
if (amount_sat_to_msat(&msat, sat))
json_add_string(result, msatfieldname,
type_to_string(tmpctx, struct amount_msat, &msat));
}
void json_add_secret(struct json_stream *response, const char *fieldname,
const struct secret *secret)
{
json_add_hex(response, fieldname, secret, sizeof(struct secret));
}
void json_add_sha256(struct json_stream *result, const char *fieldname,
const struct sha256 *hash)
{
json_add_hex(result, fieldname, hash, sizeof(*hash));
}
void json_add_preimage(struct json_stream *result, const char *fieldname,
const struct preimage *preimage)
{
json_add_hex(result, fieldname, preimage, sizeof(*preimage));
}