|
6 | 6 | #include "secp256k1_mpt.h" |
7 | 7 | #include "test_utils.h" |
8 | 8 |
|
9 | | -/* ---- Aggregation parameters ---- */ |
10 | | -#define M 2 |
11 | 9 | #define BP_VALUE_BITS 64 |
12 | 10 | #define BP_TOTAL_BITS(m) ((size_t)(BP_VALUE_BITS * (m))) |
13 | | - |
14 | | -/* ---- Benchmark parameters ---- */ |
15 | 11 | #define VERIFY_RUNS 5 |
16 | 12 |
|
17 | | - |
18 | 13 | /* ---- Helpers ---- */ |
19 | | - |
20 | 14 | static inline double elapsed_ms(struct timespec a, struct timespec b) { |
21 | 15 | return (b.tv_sec - a.tv_sec) * 1000.0 + |
22 | 16 | (b.tv_nsec - a.tv_nsec) / 1e6; |
23 | 17 | } |
24 | 18 |
|
25 | | -/* ---- Main ---- */ |
26 | | -int main(void) { |
27 | | - printf("[TEST] Aggregated Bulletproof test (m = %d)\n", M); |
| 19 | +/* ---- Core Test Logic ---- */ |
| 20 | +void run_test_case(secp256k1_context* ctx, const char* name, uint64_t* values, size_t m, int run_benchmarks) { |
| 21 | + printf("\n[TEST] %s (m = %zu)\n", name, m); |
28 | 22 |
|
29 | | - /* ---- Context ---- */ |
30 | | - secp256k1_context* ctx = |
31 | | - secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); |
32 | | - EXPECT(ctx != NULL); |
33 | | - |
34 | | - /* ---- Values ---- */ |
35 | | - uint64_t values[M] = { 5000, 123456 }; |
36 | | - unsigned char blindings[M][32]; |
37 | | - secp256k1_pubkey commitments[M]; |
38 | | - |
39 | | - /* ---- Context Binding ---- */ |
| 23 | + unsigned char blindings[m][32]; |
| 24 | + secp256k1_pubkey commitments[m]; |
40 | 25 | unsigned char context_id[32]; |
41 | 26 | EXPECT(RAND_bytes(context_id, 32) == 1); |
42 | 27 |
|
43 | 28 | secp256k1_pubkey pk_base; |
44 | | - /* Use the standard H generator from the library */ |
45 | 29 | EXPECT(secp256k1_mpt_get_h_generator(ctx, &pk_base)); |
46 | 30 |
|
47 | 31 | /* ---- Commitments ---- */ |
48 | | - for (size_t i = 0; i < M; i++) { |
| 32 | + for (size_t i = 0; i < m; i++) { |
49 | 33 | random_scalar(ctx, blindings[i]); |
50 | 34 | EXPECT(secp256k1_bulletproof_create_commitment( |
51 | | - ctx, |
52 | | - &commitments[i], |
53 | | - values[i], |
54 | | - blindings[i], |
55 | | - &pk_base)); |
| 35 | + ctx, &commitments[i], values[i], blindings[i], &pk_base)); |
56 | 36 | } |
57 | 37 |
|
58 | 38 | /* ---- Generator vectors ---- */ |
59 | | - const size_t n = BP_TOTAL_BITS(M); |
| 39 | + const size_t n = BP_TOTAL_BITS(m); |
60 | 40 | secp256k1_pubkey* G_vec = malloc(n * sizeof(secp256k1_pubkey)); |
61 | 41 | secp256k1_pubkey* H_vec = malloc(n * sizeof(secp256k1_pubkey)); |
62 | 42 | EXPECT(G_vec && H_vec); |
63 | 43 |
|
64 | | - EXPECT(secp256k1_mpt_get_generator_vector( |
65 | | - ctx, G_vec, n, (const unsigned char*)"G", 1)); |
66 | | - EXPECT(secp256k1_mpt_get_generator_vector( |
67 | | - ctx, H_vec, n, (const unsigned char*)"H", 1)); |
| 44 | + EXPECT(secp256k1_mpt_get_generator_vector(ctx, G_vec, n, (const unsigned char*)"G", 1)); |
| 45 | + EXPECT(secp256k1_mpt_get_generator_vector(ctx, H_vec, n, (const unsigned char*)"H", 1)); |
68 | 46 |
|
69 | | - /* ---- Prove (timed) ---- */ |
| 47 | + /* ---- Prove ---- */ |
70 | 48 | unsigned char proof[4096]; |
71 | 49 | size_t proof_len = sizeof(proof); |
72 | 50 |
|
73 | | - printf("[TEST] Proving aggregated range proof...\n"); |
74 | | - |
75 | 51 | struct timespec t_p_start, t_p_end; |
76 | 52 | clock_gettime(CLOCK_MONOTONIC, &t_p_start); |
77 | 53 |
|
78 | | - /* Note: We cast the 2D array 'blindings' to flat pointer */ |
79 | 54 | EXPECT(secp256k1_bulletproof_prove_agg( |
80 | | - ctx, |
81 | | - proof, |
82 | | - &proof_len, |
83 | | - values, |
84 | | - (const unsigned char*)blindings, |
85 | | - M, |
86 | | - &pk_base, |
87 | | - context_id)); |
| 55 | + ctx, proof, &proof_len, values, (const unsigned char*)blindings, m, &pk_base, context_id)); |
88 | 56 |
|
89 | 57 | clock_gettime(CLOCK_MONOTONIC, &t_p_end); |
| 58 | + printf(" Proof size: %zu bytes\n", proof_len); |
| 59 | + if (run_benchmarks) printf(" [BENCH] Proving time: %.3f ms\n", elapsed_ms(t_p_start, t_p_end)); |
90 | 60 |
|
91 | | - printf("[TEST] Proof size = %zu bytes\n", proof_len); |
92 | | - printf("[BENCH] Proving time: %.3f ms\n", |
93 | | - elapsed_ms(t_p_start, t_p_end)); |
94 | | - |
95 | | - /* ---- Verify (single run, timed) ---- */ |
96 | | - printf("[TEST] Verifying aggregated proof...\n"); |
97 | | - |
| 61 | + /* ---- Verify ---- */ |
98 | 62 | struct timespec t_v_start, t_v_end; |
99 | 63 | clock_gettime(CLOCK_MONOTONIC, &t_v_start); |
100 | 64 |
|
101 | 65 | int ok = secp256k1_bulletproof_verify_agg( |
102 | | - ctx, |
103 | | - G_vec, |
104 | | - H_vec, |
105 | | - proof, |
106 | | - proof_len, |
107 | | - commitments, |
108 | | - M, |
109 | | - &pk_base, |
110 | | - context_id); |
| 66 | + ctx, G_vec, H_vec, proof, proof_len, commitments, m, &pk_base, context_id); |
111 | 67 |
|
112 | 68 | clock_gettime(CLOCK_MONOTONIC, &t_v_end); |
113 | | - |
114 | 69 | EXPECT(ok); |
115 | | - |
116 | | - printf("PASSED\n"); |
117 | | - printf("[BENCH] Verification time (single): %.3f ms\n", |
118 | | - elapsed_ms(t_v_start, t_v_end)); |
119 | | - |
120 | | - /* ---- Verify benchmark (average) ---- */ |
121 | | - double total_ms = 0.0; |
122 | | - |
123 | | - for (int i = 0; i < VERIFY_RUNS; i++) { |
124 | | - struct timespec ts, te; |
125 | | - clock_gettime(CLOCK_MONOTONIC, &ts); |
126 | | - |
127 | | - ok = secp256k1_bulletproof_verify_agg( |
128 | | - ctx, |
129 | | - G_vec, |
130 | | - H_vec, |
131 | | - proof, |
132 | | - proof_len, |
133 | | - commitments, |
134 | | - M, |
135 | | - &pk_base, |
136 | | - context_id); |
137 | | - |
138 | | - clock_gettime(CLOCK_MONOTONIC, &te); |
139 | | - |
140 | | - EXPECT(ok); |
141 | | - total_ms += elapsed_ms(ts, te); |
| 70 | + printf(" PASSED (Verification)\n"); |
| 71 | + if (run_benchmarks) printf(" [BENCH] Verification time: %.3f ms\n", elapsed_ms(t_v_start, t_v_end)); |
| 72 | + |
| 73 | + /* ---- Benchmark Verify ---- */ |
| 74 | + if (run_benchmarks) { |
| 75 | + double total_ms = 0.0; |
| 76 | + for (int i = 0; i < VERIFY_RUNS; i++) { |
| 77 | + struct timespec ts, te; |
| 78 | + clock_gettime(CLOCK_MONOTONIC, &ts); |
| 79 | + ok = secp256k1_bulletproof_verify_agg( |
| 80 | + ctx, G_vec, H_vec, proof, proof_len, commitments, m, &pk_base, context_id); |
| 81 | + clock_gettime(CLOCK_MONOTONIC, &te); |
| 82 | + EXPECT(ok); |
| 83 | + total_ms += elapsed_ms(ts, te); |
| 84 | + } |
| 85 | + printf(" [BENCH] Verification avg over %d runs: %.3f ms\n", VERIFY_RUNS, total_ms / VERIFY_RUNS); |
142 | 86 | } |
143 | 87 |
|
144 | | - printf("[BENCH] Verification avg over %d runs: %.3f ms\n", |
145 | | - VERIFY_RUNS, total_ms / VERIFY_RUNS); |
146 | | - |
147 | | - /* ---- Negative test ---- */ |
148 | | - printf("[TEST] Tamper test... "); |
149 | | - |
150 | | - secp256k1_pubkey bad_commitments[M]; |
151 | | - memcpy(bad_commitments, commitments, sizeof(commitments)); |
152 | | - |
| 88 | + /* ---- Negative Test (Tamper) ---- */ |
| 89 | + secp256k1_pubkey bad_commitments[m]; |
| 90 | + memcpy(bad_commitments, commitments, sizeof(secp256k1_pubkey) * m); |
153 | 91 | unsigned char bad_blinding[32]; |
154 | 92 | random_scalar(ctx, bad_blinding); |
155 | 93 |
|
156 | | - /* Create a fake commitment to (value + 1) to break the sum */ |
| 94 | + /* Create fake commitment to (value + 1) */ |
157 | 95 | EXPECT(secp256k1_bulletproof_create_commitment( |
158 | | - ctx, |
159 | | - &bad_commitments[1], |
160 | | - values[M - 1] + 1, |
161 | | - bad_blinding, |
162 | | - &pk_base)); |
| 96 | + ctx, &bad_commitments[m - 1], values[m - 1] + 1, bad_blinding, &pk_base)); |
163 | 97 |
|
164 | 98 | ok = secp256k1_bulletproof_verify_agg( |
165 | | - ctx, |
166 | | - G_vec, |
167 | | - H_vec, |
168 | | - proof, |
169 | | - proof_len, |
170 | | - bad_commitments, |
171 | | - M, |
172 | | - &pk_base, |
173 | | - context_id); |
| 99 | + ctx, G_vec, H_vec, proof, proof_len, bad_commitments, m, &pk_base, context_id); |
174 | 100 |
|
175 | 101 | if (ok) { |
176 | 102 | fprintf(stderr, "FAILED: Accepted invalid proof!\n"); |
177 | 103 | exit(EXIT_FAILURE); |
178 | 104 | } |
| 105 | + printf(" PASSED (Rejected invalid proof)\n"); |
179 | 106 |
|
180 | | - printf("PASSED (rejected invalid proof)\n"); |
181 | | - |
182 | | - /* ---- Cleanup ---- */ |
183 | 107 | free(G_vec); |
184 | 108 | free(H_vec); |
185 | | - secp256k1_context_destroy(ctx); |
| 109 | +} |
186 | 110 |
|
187 | | - printf("[TEST] Aggregated Bulletproof test completed successfully\n"); |
| 111 | +/* ---- Main ---- */ |
| 112 | +int main(void) { |
| 113 | + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); |
| 114 | + EXPECT(ctx != NULL); |
| 115 | + |
| 116 | + /* 1. Single proof, value 0 (The Bug Fix) */ |
| 117 | + uint64_t v1[] = {0}; |
| 118 | + run_test_case(ctx, "Single Proof (Value 0)", v1, 1, 0); |
| 119 | + |
| 120 | + /* 2. Single proof, value 1 */ |
| 121 | + uint64_t v2[] = {1}; |
| 122 | + run_test_case(ctx, "Single Proof (Value 1)", v2, 1, 0); |
| 123 | + |
| 124 | + /* 3. Single proof, MAX VALUE (Tests opposite vector edge case) */ |
| 125 | + uint64_t v3[] = {0xFFFFFFFFFFFFFFFF}; // 2^64 - 1 |
| 126 | + run_test_case(ctx, "Single Proof (MAX Value)", v3, 1, 0); |
| 127 | + |
| 128 | + /* 4. Aggregated proof, {0, 1} */ |
| 129 | + uint64_t v4[] = {0, 1}; |
| 130 | + run_test_case(ctx, "Aggregated Proof (0, 1)", v4, 2, 0); |
| 131 | + |
| 132 | + /* 5. Aggregated proof, {0, 0} with Benchmarks */ |
| 133 | + uint64_t v5[] = {0, 0}; |
| 134 | + run_test_case(ctx, "Aggregated Proof (0, 0)", v5, 2, 1); |
| 135 | + |
| 136 | + secp256k1_context_destroy(ctx); |
| 137 | + printf("\n[TEST] All Bulletproof tests completed successfully\n"); |
188 | 138 | return 0; |
189 | 139 | } |
0 commit comments