Optimization: move (2^COMB_BITS-1)/2 term into ctx->scalar_offset

It is unnecessary to recompute this term needed by the SDMC algorithm
for every multiplication; move it into the context scalar_offset value
instead.
This commit is contained in:
Pieter Wuille
2021-12-26 18:37:53 -05:00
parent ed2a056f3d
commit 7a33db35cd
2 changed files with 13 additions and 10 deletions

View File

@@ -103,7 +103,7 @@ typedef struct {
/* Values chosen such that
*
* n*G == comb(n + (2^COMB_BITS-1)/2 + scalar_offset, G/2) + ge_offset.
* n*G == comb(n + scalar_offset, G/2) + ge_offset.
*
* This expression lets us use scalar blinding and optimize the comb precomputation. See
* ecmult_gen_impl.h for more details. */

View File

@@ -91,19 +91,17 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
*
* Adding precomputation, our final equations become:
*
* ctx->scalar_offset = -b
* ctx->scalar_offset = (2^COMB_BITS - 1)/2 - b (mod order)
* ctx->ge_offset = b*G
* d = gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2 (mod order)
* d = gn + ctx->scalar_offset (mod order)
* R = comb(d, G/2) + ctx->ge_offset
*
* comb(d, G/2) function is then computed by summing + or - 2^(i-1)*G, for i=0..COMB_BITS-1,
* depending on the value of the bits d[i] of the binary representation of scalar d.
*/
/* Compute the scalar d = (gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2). */
secp256k1_ecmult_gen_scalar_diff(&d);
secp256k1_scalar_add(&d, &d, &ctx->scalar_offset);
secp256k1_scalar_add(&d, &d, gn);
/* Compute the scalar d = (gn + ctx->scalar_offset). */
secp256k1_scalar_add(&d, &ctx->scalar_offset, gn);
/* In secp256k1_ecmult_gen_prec_table we have precomputed sums of the
* (2*d[i]-1) * 2^(i-1) * G points, for various combinations of i positions.
@@ -245,14 +243,19 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
/* Setup blinding values for secp256k1_ecmult_gen. */
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) {
secp256k1_scalar b;
secp256k1_scalar diff;
secp256k1_gej gb;
unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256 rng;
unsigned char keydata[64];
/* Compute the (2^COMB_BITS - 1)/2 term once. */
secp256k1_ecmult_gen_scalar_diff(&diff);
if (seed32 == NULL) {
/* When seed is NULL, reset the final point and blinding value. */
secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g);
ctx->scalar_offset = secp256k1_scalar_one;
secp256k1_scalar_add(&ctx->scalar_offset, &secp256k1_scalar_one, &diff);
return;
}
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
@@ -268,7 +271,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
/* TODO: reintroduce projective blinding. */
/* For a random blinding value b, set ctx->scalar_offset=-b, ctx->ge_offset=bG. */
/* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
secp256k1_scalar_set_b32(&b, nonce32, NULL);
/* The blinding value cannot be zero, as that would mean ge_offset = infinity,
@@ -278,7 +281,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
memset(nonce32, 0, 32);
secp256k1_ecmult_gen(ctx, &gb, &b);
secp256k1_scalar_negate(&b, &b);
ctx->scalar_offset = b;
secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff);
secp256k1_ge_set_gej(&ctx->ge_offset, &gb);
/* Clean up. */