Skip to content

Commit 19bbda5

Browse files
committed
bulletproofs: finish the uncompressed verifier
1 parent 03ce5bb commit 19bbda5

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

src/modules/bulletproofs/main_impl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ int secp256k1_bulletproofs_rangeproof_uncompressed_verify(
254254
unsigned char pk_buf[33];
255255
const size_t n_bits = (plen - 194) / 64;
256256
secp256k1_ge commitp, asset_genp;
257+
secp256k1_ge ap, sp;
257258
secp256k1_ge t1p, t2p;
258259
secp256k1_scalar l_dot_r;
259260
size_t i;
@@ -273,6 +274,17 @@ int secp256k1_bulletproofs_rangeproof_uncompressed_verify(
273274
secp256k1_pedersen_commitment_load(&commitp, commit);
274275
secp256k1_generator_load(&asset_genp, asset_gen);
275276

277+
pk_buf[0] = 2 | (proof[0] >> 1);
278+
memcpy(&pk_buf[1], &proof[1], 32);
279+
if (!secp256k1_eckey_pubkey_parse(&ap, pk_buf, sizeof(pk_buf))) {
280+
return 0;
281+
}
282+
pk_buf[0] = 2 | (proof[0] & 1);
283+
memcpy(&pk_buf[1], &proof[33], 32);
284+
if (!secp256k1_eckey_pubkey_parse(&sp, pk_buf, sizeof(pk_buf))) {
285+
return 0;
286+
}
287+
276288
pk_buf[0] = 2 | (proof[65] >> 1);
277289
memcpy(&pk_buf[1], &proof[66], 32);
278290
if (!secp256k1_eckey_pubkey_parse(&t1p, pk_buf, sizeof(pk_buf))) {
@@ -309,6 +321,8 @@ int secp256k1_bulletproofs_rangeproof_uncompressed_verify(
309321
min_value,
310322
&commitp,
311323
&asset_genp,
324+
&ap,
325+
&sp,
312326
&t1p,
313327
&t2p,
314328
gens,

src/modules/bulletproofs/rangeproof_uncompressed_impl.h

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,55 @@ static int secp256k1_bulletproofs_eq65_cb(secp256k1_scalar *sc, secp256k1_ge *pt
432432
return 1;
433433
}
434434

435+
/** Equation (67) is the sum of these 2 scalar-point multiplications, minus mu*G, plus a
436+
* somewhat complicatied inner product computation.. */
437+
typedef struct {
438+
const secp256k1_bulletproofs_generators* gens;
439+
const unsigned char* proof;
440+
const secp256k1_ge* ap;
441+
const secp256k1_ge* sp;
442+
secp256k1_scalar x;
443+
secp256k1_scalar z;
444+
secp256k1_scalar z_sq_2i;
445+
secp256k1_scalar y_inv;
446+
secp256k1_scalar y_neg_i;
447+
} secp256k1_bulletproofs_eq67_data;
448+
449+
static int secp256k1_bulletproofs_eq67_cb(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) {
450+
secp256k1_bulletproofs_eq67_data* ctx = (secp256k1_bulletproofs_eq67_data*) data;
451+
secp256k1_scalar lr_i;
452+
int overflow;
453+
454+
switch(idx) {
455+
case 0: /* A */
456+
*pt = *ctx->ap;
457+
secp256k1_scalar_set_int(sc, 1);
458+
return 1;
459+
case 1: /* xS */
460+
*pt = *ctx->sp;
461+
*sc = ctx->x;
462+
return 1;
463+
}
464+
465+
*pt = ctx->gens->gens[idx - 2];
466+
secp256k1_scalar_set_b32(&lr_i, &ctx->proof[194 + 32 * (idx - 2)], &overflow);
467+
VERIFY_CHECK(overflow == 0); /* checked in main_impl.h */
468+
/* (-z - l_i) G_i */
469+
if (idx % 2 == 0) {
470+
secp256k1_scalar_add(sc, &ctx->z, &lr_i);
471+
secp256k1_scalar_negate(sc, sc);
472+
/* (z + (2^i*z^2 - r)/y^i) H_i */
473+
} else {
474+
secp256k1_scalar_negate(sc, &lr_i);
475+
secp256k1_scalar_add(sc, sc, &ctx->z_sq_2i);
476+
secp256k1_scalar_mul(sc, sc, &ctx->y_neg_i);
477+
secp256k1_scalar_add(sc, sc, &ctx->z);
478+
479+
secp256k1_scalar_mul(&ctx->y_neg_i, &ctx->y_neg_i, &ctx->y_inv);
480+
secp256k1_scalar_add(&ctx->z_sq_2i, &ctx->z_sq_2i, &ctx->z_sq_2i);
481+
}
482+
return 1;
483+
}
435484

436485
static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
437486
const secp256k1_context* ctx,
@@ -442,6 +491,8 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
442491
const uint64_t min_value,
443492
const secp256k1_ge* commitp,
444493
const secp256k1_ge* asset_genp,
494+
const secp256k1_ge* ap,
495+
const secp256k1_ge* sp,
445496
const secp256k1_ge* t1p,
446497
const secp256k1_ge* t2p,
447498
const secp256k1_bulletproofs_generators* gens,
@@ -528,8 +579,32 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
528579
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res_j, &neg_tau_x, secp256k1_bulletproofs_eq65_cb, (void*) &eq65, 4)) {
529580
return 0;
530581
}
531-
return secp256k1_gej_is_infinity(&res_j);
582+
if (!secp256k1_gej_is_infinity(&res_j)) {
583+
return 0;
584+
}
532585
}
586+
/* Then (66-67) */
587+
{
588+
secp256k1_gej res_j;
589+
secp256k1_bulletproofs_eq67_data eq67;
590+
eq67.gens = gens;
591+
eq67.proof = proof;
592+
eq67.ap = ap;
593+
eq67.sp = sp;
594+
eq67.x = x;
595+
eq67.z = z;
596+
secp256k1_scalar_sqr(&eq67.z_sq_2i, &z);
597+
secp256k1_scalar_inverse_var(&eq67.y_inv, &y);
598+
secp256k1_scalar_set_int(&eq67.y_neg_i, 1);
599+
600+
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res_j, &neg_mu, secp256k1_bulletproofs_eq67_cb, (void*) &eq67, 2 + 2 * n_bits)) {
601+
return 0;
602+
}
603+
if (!secp256k1_gej_is_infinity(&res_j)) {
604+
return 0;
605+
}
606+
}
607+
return 1;
533608
}
534609

535610
#endif

0 commit comments

Comments
 (0)