forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
run-bench-find_route.c
291 lines (258 loc) · 12.1 KB
/
run-bench-find_route.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
#include <assert.h>
#include <bitcoin/pubkey.h>
#include <ccan/err/err.h>
#include <ccan/opt/opt.h>
#include <ccan/tal/str/str.h>
#include <ccan/time/time.h>
#include <common/pseudorand.h>
#include <common/status.h>
#include <common/type_to_string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void status_fmt(enum log_level level UNUSED, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
printf("\n");
va_end(ap);
}
static bool in_bench = 0;
/* We use made-up pubkeys, so don't try to format them. */
static char *fake_type_to_string_(const tal_t *ctx, const char *typename,
union printable_types u)
{
/* We *do* call this at end of route setup. */
if (streq(typename, "struct pubkey")) {
size_t n;
memcpy(&n, u.pubkey, sizeof(n));
return tal_fmt(ctx, "pubkey-#%zu", n);
}
return type_to_string_(ctx, typename, u);
}
/* Only used on setup: if it was in benchmark run, we'd need the real one */
static int fake_pubkey_cmp(const struct pubkey *a, const struct pubkey *b)
{
assert(!in_bench);
return memcmp(a, b, sizeof(*a));
}
#define pubkey_cmp fake_pubkey_cmp
#define type_to_string_ fake_type_to_string_
#include "../routing.c"
#include "../gossip_store.c"
#undef type_to_string_
struct broadcast_state *new_broadcast_state(tal_t *ctx UNNEEDED)
{
return NULL;
}
/* AUTOGENERATED MOCKS START */
/* Generated stub for broadcast_del */
void broadcast_del(struct broadcast_state *bstate UNNEEDED, u64 index UNNEEDED, const u8 *payload UNNEEDED)
{ fprintf(stderr, "broadcast_del called!\n"); abort(); }
/* Generated stub for fromwire_channel_announcement */
bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *node_signature_1 UNNEEDED, secp256k1_ecdsa_signature *node_signature_2 UNNEEDED, secp256k1_ecdsa_signature *bitcoin_signature_1 UNNEEDED, secp256k1_ecdsa_signature *bitcoin_signature_2 UNNEEDED, u8 **features UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct pubkey *node_id_1 UNNEEDED, struct pubkey *node_id_2 UNNEEDED, struct pubkey *bitcoin_key_1 UNNEEDED, struct pubkey *bitcoin_key_2 UNNEEDED)
{ fprintf(stderr, "fromwire_channel_announcement called!\n"); abort(); }
/* Generated stub for fromwire_channel_update */
bool fromwire_channel_update(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED)
{ fprintf(stderr, "fromwire_channel_update called!\n"); abort(); }
/* Generated stub for fromwire_channel_update_option_channel_htlc_max */
bool fromwire_channel_update_option_channel_htlc_max(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, u64 *htlc_maximum_msat UNNEEDED)
{ fprintf(stderr, "fromwire_channel_update_option_channel_htlc_max called!\n"); abort(); }
/* Generated stub for fromwire_gossipd_local_add_channel */
bool fromwire_gossipd_local_add_channel(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct pubkey *remote_node_id UNNEEDED, u64 *satoshis UNNEEDED)
{ fprintf(stderr, "fromwire_gossipd_local_add_channel called!\n"); abort(); }
/* Generated stub for fromwire_gossip_store_channel_announcement */
bool fromwire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **announcement UNNEEDED, u64 *satoshis UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_store_channel_announcement called!\n"); abort(); }
/* Generated stub for fromwire_gossip_store_channel_delete */
bool fromwire_gossip_store_channel_delete(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_store_channel_delete called!\n"); abort(); }
/* Generated stub for fromwire_gossip_store_channel_update */
bool fromwire_gossip_store_channel_update(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **update UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_store_channel_update called!\n"); abort(); }
/* Generated stub for fromwire_gossip_store_local_add_channel */
bool fromwire_gossip_store_local_add_channel(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **local_add UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_store_local_add_channel called!\n"); abort(); }
/* Generated stub for fromwire_gossip_store_node_announcement */
bool fromwire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **announcement UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_store_node_announcement called!\n"); abort(); }
/* Generated stub for fromwire_node_announcement */
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
/* Generated stub for fromwire_peektype */
int fromwire_peektype(const u8 *cursor UNNEEDED)
{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); }
/* Generated stub for fromwire_wireaddr */
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
/* Generated stub for insert_broadcast */
u64 insert_broadcast(struct broadcast_state *bstate UNNEEDED, const u8 *msg UNNEEDED,
u32 timestamp UNNEEDED)
{ fprintf(stderr, "insert_broadcast called!\n"); abort(); }
/* Generated stub for next_broadcast */
const u8 *next_broadcast(struct broadcast_state *bstate UNNEEDED,
u32 timestamp_min UNNEEDED, u32 timestamp_max UNNEEDED,
u64 *last_index UNNEEDED)
{ fprintf(stderr, "next_broadcast called!\n"); abort(); }
/* Generated stub for onion_type_name */
const char *onion_type_name(int e UNNEEDED)
{ fprintf(stderr, "onion_type_name called!\n"); abort(); }
/* Generated stub for sanitize_error */
char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED,
struct channel_id *channel_id UNNEEDED)
{ fprintf(stderr, "sanitize_error called!\n"); abort(); }
/* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "status_failed called!\n"); abort(); }
/* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_announcement */
u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, u64 satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_delete */
u8 *towire_gossip_store_channel_delete(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_delete called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_update */
u8 *towire_gossip_store_channel_update(const tal_t *ctx UNNEEDED, const u8 *update UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_update called!\n"); abort(); }
/* Generated stub for towire_gossip_store_local_add_channel */
u8 *towire_gossip_store_local_add_channel(const tal_t *ctx UNNEEDED, const u8 *local_add UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_local_add_channel called!\n"); abort(); }
/* Generated stub for towire_gossip_store_node_announcement */
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
/* Generated stub for wire_type_name */
const char *wire_type_name(int e UNNEEDED)
{ fprintf(stderr, "wire_type_name called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
#if DEVELOPER
/* Generated stub for memleak_remove_htable */
void memleak_remove_htable(struct htable *memtable UNNEEDED, const struct htable *ht UNNEEDED)
{ fprintf(stderr, "memleak_remove_htable called!\n"); abort(); }
/* Generated stub for memleak_remove_intmap_ */
void memleak_remove_intmap_(struct htable *memtable UNNEEDED, const struct intmap *m UNNEEDED)
{ fprintf(stderr, "memleak_remove_intmap_ called!\n"); abort(); }
#endif
/* Updates existing route if required. */
static void add_connection(struct routing_state *rstate,
const struct pubkey *from,
const struct pubkey *to,
u32 base_fee, s32 proportional_fee,
u32 delay)
{
struct short_channel_id scid;
struct half_chan *c;
struct chan *chan;
memset(&scid, 0, sizeof(scid));
chan = get_channel(rstate, &scid);
if (!chan)
chan = new_chan(rstate, &scid, from, to, 1000000);
c = &chan->half[pubkey_idx(from, to)];
c->base_fee = base_fee;
c->proportional_fee = proportional_fee;
c->delay = delay;
c->channel_flags = get_channel_direction(from, to);
}
static struct pubkey nodeid(size_t n)
{
struct pubkey id;
memset(&id, 0, sizeof(id));
memcpy(&id, &n, sizeof(n));
return id;
}
static void populate_random_node(struct routing_state *rstate, u64 n)
{
struct pubkey id = nodeid(n);
/* Create 2 random channels. */
if (n < 1)
return;
for (size_t i = 0; i < 2; i++) {
struct pubkey randnode = nodeid(pseudorand(n));
add_connection(rstate, &id, &randnode,
pseudorand(100),
pseudorand(100),
pseudorand(144));
add_connection(rstate, &randnode, &id,
pseudorand(100),
pseudorand(100),
pseudorand(144));
}
}
static void run(const char *name)
{
int status;
switch (fork()) {
case 0:
execlp(name, name, NULL);
exit(127);
case -1:
err(1, "forking %s", name);
default:
wait(&status);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
errx(1, "%s failed", name);
}
}
int main(int argc, char *argv[])
{
setup_locale();
struct routing_state *rstate;
size_t num_nodes = 100, num_runs = 1;
struct timemono start, end;
size_t num_success;
struct pubkey me = nodeid(0);
bool perfme = false;
const double riskfactor = 0.01 / BLOCKS_PER_YEAR / 10000;
struct siphash_seed base_seed;
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);
setup_tmpctx();
rstate = new_routing_state(tmpctx, NULL, &me, 0);
opt_register_noarg("--perfme", opt_set_bool, &perfme,
"Run perfme-start and perfme-stop around benchmark");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc > 1)
num_nodes = atoi(argv[1]);
if (argc > 2)
num_runs = atoi(argv[2]);
if (argc > 3)
opt_usage_and_exit("[num_nodes [num_runs]]");
memset(&base_seed, 0, sizeof(base_seed));
for (size_t i = 0; i < num_nodes; i++)
populate_random_node(rstate, i);
in_bench = true;
if (perfme)
run("perfme-start");
start = time_mono();
num_success = 0;
for (size_t i = 0; i < num_runs; i++) {
struct pubkey from = nodeid(pseudorand(num_nodes));
struct pubkey to = nodeid(pseudorand(num_nodes));
u64 fee;
struct chan **route;
route = find_route(tmpctx, rstate, &from, &to,
pseudorand(100000),
riskfactor,
0.75, &base_seed,
&fee);
num_success += (route != NULL);
tal_free(route);
}
end = time_mono();
if (perfme)
run("perfme-stop");
printf("%zu (%zu succeeded) routes in %zu nodes in %"PRIu64" msec (%"PRIu64" nanoseconds per route)",
num_runs, num_success, num_nodes,
time_to_msec(timemono_between(end, start)),
time_to_nsec(time_divide(timemono_between(end, start), num_runs)));
tal_free(tmpctx);
secp256k1_context_destroy(secp256k1_ctx);
opt_free_table();
return 0;
}