Skip to content

Commit 5fba72f

Browse files
committed
BP++ prover round 3
Commit to S. Compute l's adaptive to create a zero polynomial
1 parent 73ceb45 commit 5fba72f

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed

src/modules/bppp/bppp_rangeproof_impl.h

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,225 @@ static void secp256k1_bppp_rangeproof_prove_round2_impl(
224224
}
225225
}
226226

227+
/* Choose of the co-effs of poly and len of co-effs w = s + mT + dT^2 + rT^3 */
228+
static const secp256k1_scalar* secp256k1_bppp_w_coeff(
229+
unsigned int *len,
230+
size_t idx,
231+
const secp256k1_scalar *s,
232+
const secp256k1_scalar *m,
233+
const secp256k1_scalar *d,
234+
const secp256k1_scalar *r,
235+
const secp256k1_scalar *alpha_m,
236+
size_t digit_base,
237+
size_t num_digits
238+
) {
239+
switch (idx) {
240+
case 0:
241+
*len = num_digits > digit_base ? num_digits : digit_base;
242+
return s;
243+
case 1:
244+
*len = digit_base;
245+
return m;
246+
case 2:
247+
*len = num_digits;
248+
return d;
249+
case 3:
250+
*len = num_digits;
251+
return r;
252+
case 4:
253+
*len = digit_base;
254+
return alpha_m;
255+
default:
256+
VERIFY_CHECK(0);
257+
}
258+
return NULL;
259+
}
260+
261+
/* Compute the q-norm square of w = s + mT + dT^2 + rT^3 + alpha_mT^4.
262+
Since this is a degree 4 polynomial, we can hard code the expansion
263+
to get improve performance.
264+
|w|^2 =
265+
alpha_m**2*t**8 +
266+
2*alpha_m*r*t**7 +
267+
t**6*(2*alpha_m*d + r**2) +
268+
t**5*(2*alpha_m*m + 2*d*r) +
269+
t**4*(2*alpha_m*s + d**2 + 2*m*r) +
270+
t**3*(2*d*m + 2*r*s) +
271+
t**2*(2*d*s + m**2) +
272+
2*m*s*t +
273+
s**2
274+
*/
275+
static void secp256k1_bppp_rangeproof_w_w_q(
276+
secp256k1_scalar *w, /* size G_len = max(digits_base, num_digits)*/
277+
const secp256k1_scalar *s, /* size G_len */
278+
const secp256k1_scalar *m, /* size digits_base */
279+
const secp256k1_scalar *d, /* size num_digits */
280+
const secp256k1_scalar *r, /* size num_digits */
281+
const secp256k1_scalar *alpha_m, /* size digits_base */
282+
const secp256k1_scalar* q_pows, /* size G_len */
283+
size_t digit_base,
284+
size_t num_digits
285+
) {
286+
size_t i, j, k;
287+
for (i = 0; i < 9; i++) {
288+
secp256k1_scalar_clear(&w[i]);
289+
}
290+
291+
for (i = 0; i < 5; i++) {
292+
for (j = 0; j < 5; j++) {
293+
/* Can add an optimization to skip the last term if i + j >= 8 */
294+
unsigned int a_len, b_len;
295+
const secp256k1_scalar* a_coeffs =
296+
secp256k1_bppp_w_coeff(&a_len, i, s, m, d, r, alpha_m, digit_base, num_digits);
297+
const secp256k1_scalar* b_coeffs =
298+
secp256k1_bppp_w_coeff(&b_len, j, s, m, d, r, alpha_m, digit_base, num_digits);
299+
/* Compute w[i + j] += Sum(a[k] * b[k] * q_pows[k]) */
300+
unsigned int len = a_len < b_len ? a_len : b_len;
301+
for (k = 0; k < len; k++) {
302+
secp256k1_scalar tmp;
303+
secp256k1_scalar_mul(&tmp, &a_coeffs[k], &b_coeffs[k]);
304+
secp256k1_scalar_mul(&tmp, &tmp, &q_pows[k]);
305+
secp256k1_scalar_add(&w[i + j], &w[i + j], &tmp);
306+
}
307+
}
308+
}
309+
}
310+
311+
/* Round 3 of the proof. Computes the S value.
312+
* Serialized as 33 byte compressed point.
313+
* Always succeeds.
314+
*/
315+
static void secp256k1_bppp_rangeproof_prove_round3_impl(
316+
secp256k1_bppp_rangeproof_prover_context* prover_ctx,
317+
const secp256k1_bppp_generators* gens,
318+
const secp256k1_ge* asset_genp,
319+
unsigned char* output,
320+
secp256k1_sha256* transcript,
321+
const size_t num_digits,
322+
const size_t digit_base,
323+
const secp256k1_scalar* gamma,
324+
const unsigned char* nonce
325+
) {
326+
size_t i;
327+
size_t g_offset = digit_base > num_digits ? digit_base : num_digits;
328+
secp256k1_gej s_commj;
329+
330+
/* We don't need only one value in this round, ignore the second value. */
331+
for (i = 0; i < g_offset/2; i++) {
332+
secp256k1_scalar_chacha20(&prover_ctx->s[2*i], &prover_ctx->s[2*i + 1], nonce, i + 4);
333+
}
334+
335+
/* The l values must be computed adaptively in order to satisfy the following relation for all Ts. */
336+
{
337+
/* Add public values alpha_r=(-x*q^-(i + 1) + e) to to d */
338+
secp256k1_scalar tmp, b_pow_i, base;
339+
for (i = 0; i < num_digits; i++) {
340+
secp256k1_scalar_negate(&tmp, &prover_ctx->x);
341+
secp256k1_scalar_mul(&tmp, &tmp, &prover_ctx->q_inv_pows[i]);
342+
secp256k1_scalar_add(&tmp, &tmp, &prover_ctx->e);
343+
secp256k1_scalar_add(&prover_ctx->d[i], &prover_ctx->d[i], &tmp);
344+
}
345+
346+
/* Add public values alpha_d=(b^i*q_inv^(i+1)) to to r */
347+
secp256k1_scalar_set_int(&b_pow_i, 1);
348+
secp256k1_scalar_set_int(&base, digit_base);
349+
for (i = 0; i < num_digits; i++) {
350+
secp256k1_scalar_mul(&tmp, &b_pow_i, &prover_ctx->q_inv_pows[i]);
351+
secp256k1_scalar_add(&prover_ctx->r[i], &prover_ctx->r[i], &tmp);
352+
secp256k1_scalar_mul(&b_pow_i, &b_pow_i, &base);
353+
}
354+
}
355+
356+
/* Adaptively compute l_s to balance out the w_w_q + Y*<l, c> is zero is
357+
in all powers of T where c = (T, T^2, T^3, T^4, T^6, T^7).
358+
Note the absence of T**5 in this equation. T^0 is balanced by b_s.
359+
T^5 is balanced only if all the constraints in the rangeproof are correctly satisfied.
360+
l = l_s + l_m*T + l_d*T^2 + l_r*T^3 + 2*gamma*T^5. Only the values l_m_i are sampled randomly.
361+
All other values but ld4 = -lm5 and lm2 = -lm3 are zero. Therefore, the resultant
362+
<l-l_s, c> = T**8*(ld4 + lm5) + T**7*lm4 + T**6(2*gamma) + T**5*(ld2 + lm3) + T**4*lm2 + T**3*lm1 + T**2*lm0
363+
= T**7*lm4 + T**6(2*gamma) + T**4*lm2 + T**3*lm1 + T**2*lm0
364+
We add these terms times challenge X to respective coeffs in w_w_q. l_s is the obtained by
365+
w_w_q + y*<l - l_s, c> + y*<l_s, c> = 0
366+
*/
367+
{
368+
secp256k1_scalar w_w_q[9];
369+
secp256k1_scalar y_inv, two_gamma;
370+
secp256k1_bppp_rangeproof_w_w_q(
371+
w_w_q,
372+
prover_ctx->s,
373+
prover_ctx->m,
374+
prover_ctx->d,
375+
prover_ctx->r,
376+
prover_ctx->alpha_m,
377+
prover_ctx->q_pows,
378+
digit_base,
379+
num_digits
380+
);
381+
382+
/* Add b_i values to w_w_q. b_m*T + b_d*T^2 + b_r*T^3 */
383+
secp256k1_scalar_negate(&prover_ctx->b_m, &prover_ctx->b_m);
384+
secp256k1_scalar_negate(&prover_ctx->b_d, &prover_ctx->b_d);
385+
secp256k1_scalar_negate(&prover_ctx->b_r, &prover_ctx->b_r);
386+
387+
secp256k1_scalar_add(&w_w_q[1], &w_w_q[1], &prover_ctx->b_m);
388+
secp256k1_scalar_add(&w_w_q[2], &w_w_q[2], &prover_ctx->b_d);
389+
secp256k1_scalar_add(&w_w_q[3], &w_w_q[3], &prover_ctx->b_r);
390+
391+
secp256k1_scalar_inverse_var(&y_inv, &prover_ctx->y);
392+
393+
/* Balance out b_s = q^(i+1)*s[i]*s[i] = w_w_q[0] */
394+
prover_ctx->b_s = w_w_q[0];
395+
/* Note the limits on i from 1 to 8.*/
396+
for (i = 1; i < 8; i++) {
397+
secp256k1_scalar_mul(&w_w_q[i], &w_w_q[i], &y_inv);
398+
}
399+
secp256k1_scalar_add(&w_w_q[7], &w_w_q[7], &prover_ctx->l_m[4]);
400+
secp256k1_scalar_add(&w_w_q[4], &w_w_q[4], &prover_ctx->l_m[2]);
401+
secp256k1_scalar_add(&w_w_q[3], &w_w_q[3], &prover_ctx->l_m[1]);
402+
secp256k1_scalar_add(&w_w_q[2], &w_w_q[2], &prover_ctx->l_m[0]);
403+
404+
secp256k1_scalar_set_int(&two_gamma, 2);
405+
secp256k1_scalar_mul(&two_gamma, &two_gamma, gamma);
406+
secp256k1_scalar_add(&w_w_q[6], &w_w_q[6], &two_gamma);
407+
408+
/* Set all l_s values as negation of w_w_q */
409+
secp256k1_scalar_negate(&prover_ctx->l_s[0], &w_w_q[1]);
410+
secp256k1_scalar_negate(&prover_ctx->l_s[1], &w_w_q[2]);
411+
secp256k1_scalar_negate(&prover_ctx->l_s[2], &w_w_q[3]);
412+
secp256k1_scalar_negate(&prover_ctx->l_s[3], &w_w_q[4]);
413+
secp256k1_scalar_negate(&prover_ctx->l_s[4], &w_w_q[6]);
414+
secp256k1_scalar_negate(&prover_ctx->l_s[5], &w_w_q[7]);
415+
}
416+
/* Commit to the vector s in gens, with b_s along asset and l in H_vec */
417+
secp256k1_ecmult_const(&s_commj, asset_genp, &prover_ctx->b_s, 256);
418+
for (i = 0; i < g_offset; i++) {
419+
secp256k1_gej resj;
420+
secp256k1_ge s_comm;
421+
secp256k1_ecmult_const(&resj, &gens->gens[i], &prover_ctx->s[i], 256);
422+
secp256k1_ge_set_gej(&s_comm, &s_commj);
423+
secp256k1_gej_add_ge(&s_commj, &resj, &s_comm); /* s_comm cannot be 0 */
424+
}
425+
426+
for (i = 0; i < 6; i++) {
427+
secp256k1_gej resj;
428+
secp256k1_ge s_comm;
429+
secp256k1_ecmult_const(&resj, &gens->gens[g_offset + i], &prover_ctx->l_s[i], 256);
430+
secp256k1_ge_set_gej(&s_comm, &s_commj);
431+
secp256k1_gej_add_ge(&s_commj, &resj, &s_comm); /* s_comm cannot be 0 */
432+
}
433+
434+
{
435+
secp256k1_ge s_comm;
436+
/* All s values are non-zero(computed by inverse), scommj must be non-zero */
437+
VERIFY_CHECK(secp256k1_gej_is_infinity(&s_commj) == 0);
438+
secp256k1_ge_set_gej_var(&s_comm, &s_commj);
439+
secp256k1_fe_normalize_var(&s_comm.x);
440+
secp256k1_fe_normalize_var(&s_comm.y);
441+
secp256k1_bppp_serialize_pt(&output[0], &s_comm);
442+
443+
secp256k1_sha256_write(transcript, output, 33);
444+
secp256k1_bppp_challenge_scalar(&prover_ctx->t, transcript, 0);
445+
}
446+
}
447+
227448
#endif

0 commit comments

Comments
 (0)