Skip to content

Commit dfeff0d

Browse files
committed
bulletproofs: add benchmark
1 parent eb4047f commit dfeff0d

File tree

2 files changed

+343
-0
lines changed

2 files changed

+343
-0
lines changed

src/bench_bulletproof.c

+337
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
/**********************************************************************
2+
* Copyright (c) 2017 Andrew Poelstra *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5+
**********************************************************************/
6+
7+
#include <stdint.h>
8+
9+
#include "include/secp256k1_generator.h"
10+
#include "include/secp256k1_commitment.h"
11+
#include "include/secp256k1_bulletproofs.h"
12+
#include "util.h"
13+
#include "bench.h"
14+
15+
#define MAX_PROOF_SIZE 2000
16+
#define CIRCUIT_DIR "src/modules/bulletproofs/bin_circuits/"
17+
18+
typedef struct {
19+
secp256k1_context *ctx;
20+
secp256k1_scratch_space *scratch;
21+
unsigned char nonce[32];
22+
unsigned char **proof;
23+
secp256k1_bulletproof_generators *generators;
24+
secp256k1_generator *value_gen;
25+
secp256k1_generator blind_gen;
26+
size_t n_proofs;
27+
size_t plen;
28+
size_t iters;
29+
} bench_bulletproof_t;
30+
31+
typedef struct {
32+
bench_bulletproof_t *common;
33+
secp256k1_pedersen_commitment **commit;
34+
const unsigned char **blind;
35+
size_t *value;
36+
size_t n_commits;
37+
size_t nbits;
38+
} bench_bulletproof_rangeproof_t;
39+
40+
typedef struct {
41+
bench_bulletproof_t *common;
42+
43+
secp256k1_bulletproof_circuit **circ;
44+
secp256k1_bulletproof_circuit_assignment *assn;
45+
} bench_bulletproof_circuit_t;
46+
47+
static void bench_bulletproof_common_setup(bench_bulletproof_t *data) {
48+
size_t i;
49+
const unsigned char nonce[32] = "my kingdom for some randomness!!";
50+
const unsigned char genbd[32] = "yet more blinding, for the asset";
51+
52+
memcpy(data->nonce, nonce, 32);
53+
data->proof = (unsigned char **)malloc(data->n_proofs * sizeof(*data->proof));
54+
data->value_gen = (secp256k1_generator *)malloc(data->n_proofs * sizeof(*data->value_gen));
55+
for (i = 0; i < data->n_proofs; i++) {
56+
data->proof[i] = (unsigned char *)malloc(MAX_PROOF_SIZE);
57+
CHECK(secp256k1_generator_generate(data->ctx, &data->value_gen[i], genbd));
58+
}
59+
data->plen = MAX_PROOF_SIZE;
60+
}
61+
62+
static void bench_bulletproof_rangeproof_setup(void* arg) {
63+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
64+
size_t i;
65+
size_t v;
66+
67+
unsigned char blind[32] = "and my kingdom too for a blinder";
68+
69+
bench_bulletproof_common_setup (data->common);
70+
71+
data->commit = (secp256k1_pedersen_commitment **)malloc(data->common->n_proofs * sizeof(*data->commit));
72+
data->blind = (const unsigned char **)malloc(data->n_commits * sizeof(*data->blind));
73+
data->value = (size_t *)malloc(data->n_commits * sizeof(*data->commit));
74+
75+
for (i = 0; i < data->common->n_proofs; i++) {
76+
data->commit[i] = (secp256k1_pedersen_commitment *)malloc(data->n_commits * sizeof(*data->commit[i]));
77+
}
78+
79+
for (i = 0; i < data->n_commits; i++) {
80+
data->blind[i] = malloc(32);
81+
blind[0] = i;
82+
blind[1] = i >> 8;
83+
memcpy((unsigned char*) data->blind[i], blind, 32);
84+
data->value[i] = i * 17;
85+
CHECK(secp256k1_pedersen_commit(data->common->ctx, &data->commit[0][i], data->blind[i], data->value[i], &data->common->value_gen[0], &data->common->blind_gen));
86+
}
87+
for (i = 1; i < data->common->n_proofs; i++) {
88+
memcpy(data->commit[i], data->commit[0], data->n_commits * sizeof(*data->commit[0]));
89+
}
90+
91+
CHECK(secp256k1_bulletproof_rangeproof_prove(data->common->ctx, data->common->scratch, data->common->generators, data->common->proof[0], &data->common->plen, data->value, NULL, data->blind, data->n_commits, data->common->value_gen, data->nbits, data->common->nonce, NULL, 0) == 1);
92+
for (i = 1; i < data->common->n_proofs; i++) {
93+
memcpy(data->common->proof[i], data->common->proof[0], data->common->plen);
94+
CHECK(secp256k1_bulletproof_rangeproof_verify(data->common->ctx, data->common->scratch, data->common->generators, data->common->proof[i], data->common->plen, NULL, data->commit[i], data->n_commits, data->nbits, &data->common->value_gen[0], NULL, 0) == 1);
95+
}
96+
CHECK(secp256k1_bulletproof_rangeproof_verify(data->common->ctx, data->common->scratch, data->common->generators, data->common->proof[0], data->common->plen, NULL, data->commit[0], data->n_commits, data->nbits, data->common->value_gen, NULL, 0) == 1);
97+
CHECK(secp256k1_bulletproof_rangeproof_verify_multi(data->common->ctx, data->common->scratch, data->common->generators, (const unsigned char **) data->common->proof, data->common->n_proofs, data->common->plen, NULL, (const secp256k1_pedersen_commitment **) data->commit, data->n_commits, data->nbits, data->common->value_gen, NULL, 0) == 1);
98+
if (data->n_commits == 1) {
99+
CHECK(secp256k1_bulletproof_rangeproof_rewind(data->common->ctx, data->common->generators, &v, blind, data->common->proof[0], data->common->plen, 0, data->commit[0], &data->common->value_gen[0], data->common->nonce, NULL, 0) == 1);
100+
}
101+
}
102+
103+
static void bench_bulletproof_circuit_setup(void* arg) {
104+
bench_bulletproof_circuit_t *data = (bench_bulletproof_circuit_t *) arg;
105+
size_t i;
106+
107+
bench_bulletproof_common_setup (data->common);
108+
109+
CHECK(secp256k1_bulletproof_circuit_prove(data->common->ctx, data->common->scratch, data->common->generators, data->circ[0], data->common->proof[0], &data->common->plen, data->assn, NULL, 0, data->common->nonce, &data->common->value_gen[0], NULL, 0) == 1);
110+
for (i = 1; i < data->common->n_proofs; i++) {
111+
data->circ[i] = data->circ[0];
112+
memcpy(data->common->proof[i], data->common->proof[0], data->common->plen);
113+
}
114+
CHECK(secp256k1_bulletproof_circuit_verify(data->common->ctx, data->common->scratch, data->common->generators, data->circ[0], data->common->proof[0], data->common->plen, NULL, 0, data->common->value_gen, NULL, 0) == 1);
115+
CHECK(secp256k1_bulletproof_circuit_verify_multi(data->common->ctx, data->common->scratch, data->common->generators, (const secp256k1_bulletproof_circuit* const*) data->circ, (const unsigned char **) data->common->proof, data->common->n_proofs, data->common->plen, NULL, NULL, data->common->value_gen, NULL, 0) == 1);
116+
}
117+
118+
static void bench_bulletproof_common_teardown(bench_bulletproof_t *data) {
119+
size_t i;
120+
121+
for (i = 0; i < data->n_proofs; i++) {
122+
free(data->proof[i]);
123+
}
124+
free(data->proof);
125+
free(data->value_gen);
126+
}
127+
128+
static void bench_bulletproof_rangeproof_teardown(void* arg) {
129+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
130+
size_t i;
131+
132+
if (data->blind != NULL) {
133+
for (i = 0; i < data->n_commits; i++) {
134+
free((unsigned char*) data->blind[i]);
135+
}
136+
}
137+
if (data->commit != NULL) {
138+
for (i = 0; i < data->common->n_proofs; i++) {
139+
free(data->commit[i]);
140+
}
141+
free(data->commit);
142+
}
143+
free(data->blind);
144+
free(data->value);
145+
146+
bench_bulletproof_common_teardown(data->common);
147+
}
148+
149+
static void bench_bulletproof_circuit_teardown(void* arg) {
150+
bench_bulletproof_circuit_t *data = (bench_bulletproof_circuit_t *) arg;
151+
bench_bulletproof_common_teardown(data->common);
152+
}
153+
154+
static void bench_bulletproof_rangeproof_prove(void* arg) {
155+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
156+
size_t i;
157+
for (i = 0; i < 25; i++) {
158+
CHECK(secp256k1_bulletproof_rangeproof_prove(data->common->ctx, data->common->scratch, data->common->generators, data->common->proof[0], &data->common->plen, data->value, NULL, data->blind, data->n_commits, data->common->value_gen, data->nbits, data->common->nonce, NULL, 0) == 1);
159+
}
160+
}
161+
162+
static void bench_bulletproof_rangeproof_verify(void* arg) {
163+
size_t i;
164+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
165+
166+
for (i = 0; i < data->common->iters; i++) {
167+
CHECK(secp256k1_bulletproof_rangeproof_verify_multi(data->common->ctx, data->common->scratch, data->common->generators, (const unsigned char **) data->common->proof, data->common->n_proofs, data->common->plen, NULL, (const secp256k1_pedersen_commitment **) data->commit, data->n_commits, data->nbits, data->common->value_gen, NULL, 0) == 1);
168+
}
169+
}
170+
171+
static void bench_bulletproof_rangeproof_rewind_succeed(void* arg) {
172+
size_t i;
173+
size_t v;
174+
unsigned char blind[32];
175+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
176+
177+
for (i = 0; i < data->common->iters; i++) {
178+
CHECK(secp256k1_bulletproof_rangeproof_rewind(data->common->ctx, data->common->generators, &v, blind, data->common->proof[0], data->common->plen, 0, data->commit[0], &data->common->value_gen[0], data->common->nonce, NULL, 0) == 1);
179+
}
180+
}
181+
182+
static void bench_bulletproof_rangeproof_rewind_fail(void* arg) {
183+
size_t i;
184+
size_t v;
185+
unsigned char blind[32];
186+
bench_bulletproof_rangeproof_t *data = (bench_bulletproof_rangeproof_t*)arg;
187+
188+
data->common->nonce[0] ^= 1;
189+
for (i = 0; i < data->common->iters; i++) {
190+
CHECK(secp256k1_bulletproof_rangeproof_rewind(data->common->ctx, data->common->generators, &v, blind, data->common->proof[0], data->common->plen, 0, data->commit[0], &data->common->value_gen[0], data->common->nonce, NULL, 0) == 0);
191+
}
192+
data->common->nonce[0] ^= 1;
193+
}
194+
195+
static void bench_bulletproof_circuit_prove(void* arg) {
196+
bench_bulletproof_circuit_t *data = (bench_bulletproof_circuit_t *) arg;
197+
CHECK(secp256k1_bulletproof_circuit_prove(data->common->ctx, data->common->scratch, data->common->generators, data->circ[0], data->common->proof[0], &data->common->plen, data->assn, NULL, 0, data->common->nonce, data->common->value_gen, NULL, 0) == 1);
198+
}
199+
200+
static void bench_bulletproof_circuit_verify(void* arg) {
201+
bench_bulletproof_circuit_t *data = (bench_bulletproof_circuit_t *) arg;
202+
size_t i;
203+
for (i = 0; i < 10; i++) {
204+
CHECK(secp256k1_bulletproof_circuit_verify_multi(data->common->ctx, data->common->scratch, data->common->generators, (const secp256k1_bulletproof_circuit* const*) data->circ, (const unsigned char **) data->common->proof, data->common->n_proofs, data->common->plen, NULL, NULL, data->common->value_gen, NULL, 0) == 1);
205+
}
206+
}
207+
208+
static void run_rangeproof_test(bench_bulletproof_rangeproof_t *data, size_t nbits, size_t n_commits) {
209+
char str[64];
210+
211+
data->nbits = nbits;
212+
data->n_commits = n_commits;
213+
data->common->iters = 100;
214+
215+
data->common->n_proofs = 1;
216+
sprintf(str, "bulletproof_prove, %i, %i, 0, ", (int)nbits, (int) n_commits);
217+
run_benchmark(str, bench_bulletproof_rangeproof_prove, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, 25);
218+
219+
data->common->n_proofs = 1;
220+
sprintf(str, "bulletproof_verify, %i, %i, 1, ", (int)nbits, (int) n_commits);
221+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
222+
223+
if (n_commits == 1) {
224+
sprintf(str, "bulletproof_rewind_succeed, %i, ", (int)nbits);
225+
run_benchmark(str, bench_bulletproof_rangeproof_rewind_succeed, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
226+
sprintf(str, "bulletproof_rewind_fail, %i, ", (int)nbits);
227+
run_benchmark(str, bench_bulletproof_rangeproof_rewind_fail, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
228+
}
229+
230+
data->common->n_proofs = 2;
231+
sprintf(str, "bulletproof_verify, %i, %i, 2, ", (int)nbits, (int) n_commits);
232+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
233+
234+
data->common->iters = 10;
235+
data->common->n_proofs = 50;
236+
sprintf(str, "bulletproof_verify, %i, %i, 50, ", (int)nbits, (int) n_commits);
237+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
238+
239+
data->common->iters = 1;
240+
data->common->n_proofs = 100;
241+
sprintf(str, "bulletproof_verify, %i, %i, 100, ", (int)nbits, (int) n_commits);
242+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
243+
244+
data->common->n_proofs = 500;
245+
sprintf(str, "bulletproof_verify, %i, %i, 500, ", (int)nbits, (int) n_commits);
246+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
247+
248+
data->common->n_proofs = 1000;
249+
sprintf(str, "bulletproof_verify, %i, %i, 1000, ", (int)nbits, (int) n_commits);
250+
run_benchmark(str, bench_bulletproof_rangeproof_verify, bench_bulletproof_rangeproof_setup, bench_bulletproof_rangeproof_teardown, (void *)data, 5, data->common->iters);
251+
}
252+
253+
void run_circuit_test(bench_bulletproof_circuit_t *data, const char *name) {
254+
char fname[128];
255+
size_t i;
256+
257+
data->circ = (secp256k1_bulletproof_circuit **)malloc(500 * sizeof(*data->circ));
258+
259+
sprintf(fname, CIRCUIT_DIR "%s.circ", name);
260+
data->circ[0] = secp256k1_bulletproof_circuit_decode(data->common->ctx, fname);
261+
CHECK(data->circ[0] != NULL);
262+
263+
for (i = 1; i < 500; i++) {
264+
data->circ[i] = data->circ[0];
265+
}
266+
267+
sprintf(fname, CIRCUIT_DIR "%s.assn", name);
268+
data->assn = secp256k1_bulletproof_circuit_assignment_decode(data->common->ctx, fname);
269+
CHECK(data->assn != NULL);
270+
271+
data->common->n_proofs = 1;
272+
sprintf(fname, "bulletproof_prove_%s, ", name);
273+
run_benchmark(fname, bench_bulletproof_circuit_prove, bench_bulletproof_circuit_setup, bench_bulletproof_circuit_teardown, (void *)data, 1, 1);
274+
275+
data->common->n_proofs = 1;
276+
sprintf(fname, "bulletproof_verify_%s, %i, ", name, 1);
277+
run_benchmark(fname, bench_bulletproof_circuit_verify, bench_bulletproof_circuit_setup, bench_bulletproof_circuit_teardown, (void *)data, 2, 10);
278+
279+
data->common->n_proofs = 2;
280+
sprintf(fname, "bulletproof_verify_%s, %i, ", name, 2);
281+
run_benchmark(fname, bench_bulletproof_circuit_verify, bench_bulletproof_circuit_setup, bench_bulletproof_circuit_teardown, (void *)data, 2, 10);
282+
283+
data->common->n_proofs = 100;
284+
sprintf(fname, "bulletproof_verify_%s, %i, ", name, 100);
285+
run_benchmark(fname, bench_bulletproof_circuit_verify, bench_bulletproof_circuit_setup, bench_bulletproof_circuit_teardown, (void *)data, 2, 10);
286+
287+
secp256k1_bulletproof_circuit_destroy(data->common->ctx, data->circ[0]);
288+
secp256k1_bulletproof_circuit_assignment_destroy(data->common->ctx, data->assn);
289+
}
290+
291+
int main(void) {
292+
bench_bulletproof_t data;
293+
bench_bulletproof_rangeproof_t rp_data;
294+
bench_bulletproof_circuit_t c_data;
295+
296+
data.blind_gen = secp256k1_generator_const_g;
297+
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
298+
data.scratch = secp256k1_scratch_space_create(data.ctx, 1024 * 1024 * 1024);
299+
data.generators = secp256k1_bulletproof_generators_create(data.ctx, &data.blind_gen, 64 * 1024, 1);
300+
301+
rp_data.common = &data;
302+
c_data.common = &data;
303+
304+
run_circuit_test(&c_data, "pedersen-3");
305+
run_circuit_test(&c_data, "pedersen-6");
306+
run_circuit_test(&c_data, "pedersen-12");
307+
run_circuit_test(&c_data, "pedersen-24");
308+
run_circuit_test(&c_data, "pedersen-48");
309+
run_circuit_test(&c_data, "pedersen-96");
310+
run_circuit_test(&c_data, "pedersen-192");
311+
run_circuit_test(&c_data, "pedersen-384");
312+
run_circuit_test(&c_data, "pedersen-768");
313+
run_circuit_test(&c_data, "pedersen-1536");
314+
run_circuit_test(&c_data, "pedersen-3072");
315+
run_circuit_test(&c_data, "SHA2");
316+
317+
run_rangeproof_test(&rp_data, 8, 1);
318+
run_rangeproof_test(&rp_data, 16, 1);
319+
run_rangeproof_test(&rp_data, 32, 1);
320+
321+
run_rangeproof_test(&rp_data, 64, 1);
322+
run_rangeproof_test(&rp_data, 64, 2);
323+
run_rangeproof_test(&rp_data, 64, 4);
324+
run_rangeproof_test(&rp_data, 64, 8);
325+
run_rangeproof_test(&rp_data, 64, 16);
326+
run_rangeproof_test(&rp_data, 64, 32);
327+
run_rangeproof_test(&rp_data, 64, 64);
328+
run_rangeproof_test(&rp_data, 64, 128);
329+
run_rangeproof_test(&rp_data, 64, 256);
330+
run_rangeproof_test(&rp_data, 64, 512);
331+
/* to add more, increase the number of generators above in `data.generators = ...` */
332+
333+
secp256k1_bulletproof_generators_destroy(data.ctx, data.generators);
334+
secp256k1_scratch_space_destroy(data.scratch);
335+
secp256k1_context_destroy(data.ctx);
336+
return 0;
337+
}

src/modules/bulletproofs/Makefile.am.include

+6
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@ noinst_HEADERS += src/modules/bulletproofs/rangeproof_impl.h
44
noinst_HEADERS += src/modules/bulletproofs/main_impl.h
55
noinst_HEADERS += src/modules/bulletproofs/tests_impl.h
66
noinst_HEADERS += src/modules/bulletproofs/util.h
7+
if USE_BENCHMARK
8+
noinst_PROGRAMS += bench_bulletproof
9+
bench_bulletproof_SOURCES = src/bench_bulletproof.c
10+
bench_bulletproof_LDADD = libsecp256k1.la $(SECP_LIBS)
11+
bench_bulletproof_LDFLAGS = -static
12+
endif

0 commit comments

Comments
 (0)