Skip to content

Commit eed6839

Browse files
committed
Prover round 4: Norm proof argument
Run the run norm proof argument on the computed C
1 parent 5fba72f commit eed6839

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed

src/modules/bppp/bppp_rangeproof_impl.h

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,4 +445,264 @@ static void secp256k1_bppp_rangeproof_prove_round3_impl(
445445
}
446446
}
447447

448+
/* Round 4 of the proof. Computes the norm proof on the w and l values.
449+
* Can fail only when the norm proof fails.
450+
* This should not happen in our setting because w_vec and l_vec and uniformly
451+
* distributed and thus norm argument can only fail when the lengths are not a
452+
* power of two or if the allocated proof size is not enough.
453+
*
454+
* We check for both of these conditions beforehand, therefore in practice this
455+
* function should never fail because it returns point at infinity during some
456+
* interim calculations. However, since the overall API can fail, we also fail
457+
* if the norm proofs fails for any reason.
458+
*/
459+
static int secp256k1_bppp_rangeproof_prove_round4_impl(
460+
const secp256k1_context* ctx,
461+
secp256k1_scratch_space* scratch,
462+
const secp256k1_bppp_generators* gens,
463+
const secp256k1_ge* asset_genp,
464+
secp256k1_bppp_rangeproof_prover_context* prover_ctx,
465+
unsigned char* output,
466+
size_t *output_len,
467+
secp256k1_sha256* transcript,
468+
const secp256k1_scalar* gamma,
469+
const size_t num_digits,
470+
const size_t digit_base
471+
) {
472+
size_t i, scratch_checkpoint;
473+
size_t g_offset = digit_base > num_digits ? digit_base : num_digits;
474+
/* Compute w = s + t*m + t^2*d + t^3*r + t^4*alpha_m. Store w in s*/
475+
/* Has capacity 8 because we can re-use it as the c-poly. */
476+
secp256k1_scalar t_pows[8];
477+
secp256k1_ge *gs;
478+
secp256k1_bppp_rangeproof_powers_of_q(&t_pows[0], &prover_ctx->t, 7); /* Computes from t^1 to t^7 */
479+
480+
for (i = 0; i < g_offset; i++) {
481+
if (i < num_digits) {
482+
secp256k1_scalar_mul(&prover_ctx->r[i], &prover_ctx->r[i], &t_pows[2]);
483+
secp256k1_scalar_add(&prover_ctx->s[i], &prover_ctx->s[i], &prover_ctx->r[i]);
484+
485+
secp256k1_scalar_mul(&prover_ctx->d[i], &prover_ctx->d[i], &t_pows[1]);
486+
secp256k1_scalar_add(&prover_ctx->s[i], &prover_ctx->s[i], &prover_ctx->d[i]);
487+
}
488+
if (i < digit_base) {
489+
secp256k1_scalar_mul(&prover_ctx->m[i], &prover_ctx->m[i], &t_pows[0]);
490+
secp256k1_scalar_add(&prover_ctx->s[i], &prover_ctx->s[i], &prover_ctx->m[i]);
491+
492+
secp256k1_scalar_mul(&prover_ctx->alpha_m[i], &prover_ctx->alpha_m[i], &t_pows[3]);
493+
secp256k1_scalar_add(&prover_ctx->s[i], &prover_ctx->s[i], &prover_ctx->alpha_m[i]);
494+
}
495+
}
496+
/* Compute l = l_s + t*l_m + t^2*l_d + t^3*l_r. Store l in l_s*/
497+
for (i = 0; i < 6; i++) {
498+
secp256k1_scalar tmp;
499+
secp256k1_scalar_mul(&tmp, &prover_ctx->l_m[i], &t_pows[0]);
500+
secp256k1_scalar_add(&prover_ctx->l_s[i], &prover_ctx->l_s[i], &tmp);
501+
}
502+
/* Manually add l_d2 and l_d4 */
503+
{
504+
secp256k1_scalar tmp;
505+
secp256k1_scalar_mul(&tmp, &prover_ctx->l_m[3], &t_pows[1]);
506+
secp256k1_scalar_negate(&tmp, &tmp);/* l_d2 = -l_m3 */
507+
secp256k1_scalar_add(&prover_ctx->l_s[2], &prover_ctx->l_s[2], &tmp);
508+
509+
secp256k1_scalar_mul(&tmp, &prover_ctx->l_m[5], &t_pows[1]);
510+
secp256k1_scalar_negate(&tmp, &tmp);/* l_d4 = -l_m5 */
511+
secp256k1_scalar_add(&prover_ctx->l_s[4], &prover_ctx->l_s[4], &tmp);
512+
513+
/* Add two_gamma * t5 to l_s[0] */
514+
secp256k1_scalar_add(&tmp, &t_pows[4], &t_pows[4]);
515+
secp256k1_scalar_mul(&tmp, &tmp, gamma);
516+
secp256k1_scalar_add(&prover_ctx->l_s[0], &prover_ctx->l_s[0], &tmp);
517+
}
518+
/* Set non used 7th and 8th l_s to 0 */
519+
secp256k1_scalar_set_int(&prover_ctx->l_s[6], 0);
520+
secp256k1_scalar_set_int(&prover_ctx->l_s[7], 0);
521+
522+
/* Make c = y*(T, T^2, T^3, T^4, T^6, T^7, 0, 0) */
523+
t_pows[4] = t_pows[5];
524+
t_pows[5] = t_pows[6];
525+
for (i = 0; i < 6; i++) {
526+
secp256k1_scalar_mul(&t_pows[i], &t_pows[i], &prover_ctx->y);
527+
}
528+
secp256k1_scalar_set_int(&t_pows[6], 0);
529+
secp256k1_scalar_set_int(&t_pows[7], 0);
530+
/* Call the norm argument on w, l */
531+
/* We have completed the blinding, none of part that comes from this point on
532+
needs to constant time. We can safely early return
533+
*/
534+
scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
535+
gs = (secp256k1_ge*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, (gens->n) * sizeof(secp256k1_ge));
536+
if (gs == NULL) {
537+
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
538+
return 0;
539+
}
540+
memcpy(gs, gens->gens, (gens->n) * sizeof(secp256k1_ge));
541+
542+
return secp256k1_bppp_rangeproof_norm_product_prove(
543+
ctx,
544+
scratch,
545+
output,
546+
output_len,
547+
transcript,
548+
&prover_ctx->q_sqrt,
549+
gs,
550+
gens->n,
551+
asset_genp,
552+
prover_ctx->s,
553+
g_offset,
554+
prover_ctx->l_s,
555+
8,
556+
t_pows,
557+
8
558+
);
559+
}
560+
561+
static int secp256k1_bppp_rangeproof_prove_impl(
562+
const secp256k1_context* ctx,
563+
secp256k1_scratch_space* scratch,
564+
const secp256k1_bppp_generators* gens,
565+
const secp256k1_ge* asset_genp,
566+
unsigned char* proof,
567+
size_t* proof_len,
568+
const size_t n_bits,
569+
const size_t digit_base,
570+
const uint64_t value,
571+
const uint64_t min_value,
572+
const secp256k1_ge* commitp,
573+
const secp256k1_scalar* gamma,
574+
const unsigned char* nonce,
575+
const unsigned char* extra_commit,
576+
size_t extra_commit_len
577+
) {
578+
size_t scratch_checkpoint, n_proof_bytes_written, norm_proof_len;
579+
secp256k1_sha256 transcript;
580+
size_t num_digits = n_bits / secp256k1_bppp_log2(digit_base);
581+
size_t h_len = 8;
582+
size_t g_offset = num_digits > digit_base ? num_digits : digit_base;
583+
size_t log_n = secp256k1_bppp_log2(g_offset), log_m = secp256k1_bppp_log2(h_len);
584+
size_t n_rounds = log_n > log_m ? log_n : log_m;
585+
int res;
586+
secp256k1_bppp_rangeproof_prover_context prover_ctx;
587+
/* Check proof sizes*/
588+
if (*proof_len < 33 * 4 + (65 * n_rounds) + 64) {
589+
return 0;
590+
}
591+
if (gens->n != (g_offset + h_len)) {
592+
return 0;
593+
}
594+
if (!secp256k1_is_power_of_two(digit_base) || !secp256k1_is_power_of_two(num_digits)) {
595+
return 0;
596+
}
597+
if (n_bits > 64) {
598+
return 0;
599+
}
600+
if (value < min_value) {
601+
return 0;
602+
}
603+
if (n_bits < 64 && (value - min_value) >= (1ull << n_bits)) {
604+
return 0;
605+
}
606+
if (extra_commit_len > 0 && extra_commit == NULL) {
607+
return 0;
608+
}
609+
610+
/* Compute the base digits representation of the value */
611+
/* Alloc for prover->ctx */
612+
scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
613+
prover_ctx.s = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_offset * sizeof(secp256k1_scalar));
614+
prover_ctx.d = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, num_digits * sizeof(secp256k1_scalar));
615+
prover_ctx.m = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, digit_base * sizeof(secp256k1_scalar));
616+
prover_ctx.r = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, num_digits * sizeof(secp256k1_scalar));
617+
prover_ctx.alpha_m = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, digit_base * sizeof(secp256k1_scalar));
618+
619+
prover_ctx.l_m = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, 6 * sizeof(secp256k1_scalar));
620+
prover_ctx.l_s = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar));
621+
622+
prover_ctx.q_pows = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_offset * sizeof(secp256k1_scalar));
623+
prover_ctx.q_inv_pows = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_offset * sizeof(secp256k1_scalar));
624+
625+
if ( prover_ctx.s == NULL || prover_ctx.d == NULL || prover_ctx.m == NULL || prover_ctx.r == NULL
626+
|| prover_ctx.alpha_m == NULL || prover_ctx.l_m == NULL || prover_ctx.l_s == NULL
627+
|| prover_ctx.q_pows == NULL || prover_ctx.q_inv_pows == NULL )
628+
{
629+
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
630+
return 0;
631+
}
632+
633+
/* Initialze the transcript by committing to all the public data */
634+
secp256k1_bppp_commit_initial_data(
635+
&transcript,
636+
num_digits,
637+
digit_base,
638+
min_value,
639+
commitp,
640+
asset_genp,
641+
extra_commit,
642+
extra_commit_len
643+
);
644+
645+
n_proof_bytes_written = 0;
646+
secp256k1_bppp_rangeproof_prove_round1_impl(
647+
&prover_ctx,
648+
gens,
649+
asset_genp,
650+
&proof[n_proof_bytes_written],
651+
&transcript,
652+
num_digits,
653+
digit_base,
654+
value - min_value,
655+
nonce
656+
);
657+
n_proof_bytes_written += 33 *2;
658+
659+
secp256k1_bppp_rangeproof_prove_round2_impl(
660+
&prover_ctx,
661+
gens,
662+
asset_genp,
663+
&proof[n_proof_bytes_written],
664+
&transcript,
665+
num_digits,
666+
digit_base,
667+
nonce
668+
);
669+
n_proof_bytes_written += 33;
670+
671+
secp256k1_bppp_rangeproof_prove_round3_impl(
672+
&prover_ctx,
673+
gens,
674+
asset_genp,
675+
&proof[n_proof_bytes_written],
676+
&transcript,
677+
num_digits,
678+
digit_base,
679+
gamma,
680+
nonce
681+
);
682+
n_proof_bytes_written += 33;
683+
684+
/* Calculate the remaining buffer size. We have already checked that buffer is of correct size */
685+
norm_proof_len = *proof_len - n_proof_bytes_written;
686+
res = secp256k1_bppp_rangeproof_prove_round4_impl(
687+
ctx,
688+
scratch,
689+
gens,
690+
asset_genp,
691+
&prover_ctx,
692+
&proof[n_proof_bytes_written],
693+
&norm_proof_len,
694+
&transcript,
695+
gamma,
696+
num_digits,
697+
digit_base
698+
);
699+
/* No need to worry about constant time-ness from this point. All data is public */
700+
if (res) {
701+
*proof_len = n_proof_bytes_written + norm_proof_len;
702+
}
703+
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
704+
return res;
705+
}
706+
707+
448708
#endif

0 commit comments

Comments
 (0)