Skip to content

Commit 28d8c3c

Browse files
committed
bulletproofs: finish the uncompressed verifier
1 parent 264924c commit 28d8c3c

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
@@ -255,6 +255,7 @@ int secp256k1_bulletproofs_rangeproof_uncompressed_verify(
255255
unsigned char pk_buf[33];
256256
const size_t n_bits = (plen - 194) / 64;
257257
secp256k1_ge commitp, asset_genp;
258+
secp256k1_ge ap, sp;
258259
secp256k1_ge t1p, t2p;
259260
secp256k1_scalar l_dot_r;
260261
size_t i;
@@ -274,6 +275,17 @@ int secp256k1_bulletproofs_rangeproof_uncompressed_verify(
274275
secp256k1_pedersen_commitment_load(&commitp, commit);
275276
secp256k1_generator_load(&asset_genp, asset_gen);
276277

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

src/modules/bulletproofs/rangeproof_uncompressed_impl.h

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,55 @@ static int secp256k1_bulletproofs_eq65_cb(secp256k1_scalar *sc, secp256k1_ge *pt
439439
return 1;
440440
}
441441

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

443492
static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
444493
const secp256k1_context* ctx,
@@ -449,6 +498,8 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
449498
const uint64_t min_value,
450499
const secp256k1_ge* commitp,
451500
const secp256k1_ge* asset_genp,
501+
const secp256k1_ge* ap,
502+
const secp256k1_ge* sp,
452503
const secp256k1_ge* t1p,
453504
const secp256k1_ge* t2p,
454505
const secp256k1_bulletproofs_generators* gens,
@@ -534,8 +585,32 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
534585
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res_j, &neg_tau_x, secp256k1_bulletproofs_eq65_cb, (void*) &eq65, 4)) {
535586
return 0;
536587
}
537-
return secp256k1_gej_is_infinity(&res_j);
588+
if (!secp256k1_gej_is_infinity(&res_j)) {
589+
return 0;
590+
}
538591
}
592+
/* Then (66-67) */
593+
{
594+
secp256k1_gej res_j;
595+
secp256k1_bulletproofs_eq67_data eq67;
596+
eq67.gens = gens;
597+
eq67.proof = proof;
598+
eq67.ap = ap;
599+
eq67.sp = sp;
600+
eq67.x = x;
601+
eq67.z = z;
602+
secp256k1_scalar_sqr(&eq67.z_sq_2i, &z);
603+
secp256k1_scalar_inverse_var(&eq67.y_inv, &y);
604+
secp256k1_scalar_set_int(&eq67.y_neg_i, 1);
605+
606+
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res_j, &neg_mu, secp256k1_bulletproofs_eq67_cb, (void*) &eq67, 2 + 2 * n_bits)) {
607+
return 0;
608+
}
609+
if (!secp256k1_gej_is_infinity(&res_j)) {
610+
return 0;
611+
}
612+
}
613+
return 1;
539614
}
540615

541616
#endif

0 commit comments

Comments
 (0)