secp256k1ECmultConst static method

void secp256k1ECmultConst(
  1. Secp256k1Gej r,
  2. Secp256k1Ge a,
  3. Secp256k1Scalar q
)

Implementation

static void secp256k1ECmultConst(
    Secp256k1Gej r, Secp256k1Ge a, Secp256k1Scalar q) {
  /// The offset to add to s1 and s2 to make them non-negative. Equal to 2^128.
  Secp256k1Scalar s = Secp256k1Scalar(),
      v1 = Secp256k1Scalar(),
      v2 = Secp256k1Scalar();
  List<Secp256k1Ge> preA =
      List.generate(Secp256k1Const.constTableSize, (_) => Secp256k1Ge());
  List<Secp256k1Ge> preALam =
      List.generate(Secp256k1Const.constTableSize, (_) => Secp256k1Ge());
  Secp256k1Fe globalZ = Secp256k1Fe();
  int group, i;
  if (secp256k1GeIsInfinity(a).toBool) {
    secp256k1GejSetInfinity(r);
    return;
  }

  /// Compute v1 and v2.
  secp256k1ScalarAdd(s, q, Secp256k1Const.secp256k1ECmultConstK);
  secp256k1ScalarHalf(s, s);
  secp256k1ScalarSplitLambda(v1, v2, s);
  secp256k1ScalarAdd(v1, v1, Secp256k1Const.sOffset);
  secp256k1ScalarAdd(v2, v2, Secp256k1Const.sOffset);

  /// verify
  for (i = 129; i < 256; ++i) {
    _cond(
        secp256k1ScalarGetBitsLimb32(v1, i, 1) == 0, "secp256k1ECmultConst");
    _cond(
        secp256k1ScalarGetBitsLimb32(v2, i, 1) == 0, "secp256k1ECmultConst");
  }
  secp256k1GejSetGe(r, a);
  secp256k1ECmultConstOddMultiplesTableGlobalz(preA, globalZ, r);

  for (i = 0; i < Secp256k1Const.constTableSize; i++) {
    secp256k1GeMulLambda(preALam[i], preA[i]);
  }

  for (group = Secp256k1Const.constGroup - 1; group >= 0; --group) {
    /// Using the _var get_bits function is ok here, since it's only variable in offset and count, not in the scalar.
    int bits1 = secp256k1ScalarGetBitsVar(v1,
        group * Secp256k1Const.constGroupSize, Secp256k1Const.constGroupSize);
    int bits2 = secp256k1ScalarGetBitsVar(v2,
        group * Secp256k1Const.constGroupSize, Secp256k1Const.constGroupSize);
    Secp256k1Ge t = Secp256k1Ge();
    int j;
//
    ecmultConstTableGetGe(t, preA, bits1);
    if (group == Secp256k1Const.constGroup - 1) {
      /// Directly set r in the first iteration.
      secp256k1GejSetGe(r, t);
    } else {
      /// Shift the result so far up.
      for (j = 0; j < Secp256k1Const.constGroupSize; ++j) {
        secp256k1GejDouble(r, r);
      }
      secp256k1GejAddGe(r, r, t);
    }
    ecmultConstTableGetGe(t, preALam, bits2);
    secp256k1GejAddGe(r, r, t);
  }

  /// Map the result back to the secp256k1 curve from the isomorphic curve.
  secp256k1FeMul(r.z, r.z, globalZ);
}