secp256k1ECmultGen static method
Implementation
static void secp256k1ECmultGen(
Secp256k1ECmultGenContext ctx, Secp256k1Gej r, Secp256k1Scalar gn) {
int combOff;
Secp256k1Ge add = Secp256k1Ge();
Secp256k1Fe neg = Secp256k1Fe();
Secp256k1GeStorage adds = Secp256k1GeStorage();
Secp256k1Scalar d = Secp256k1Scalar();
List<int> recoded = List.filled((Secp256k1Const.combBits + 31) >> 5, 0);
int first = 1, i;
/// Compute the scalar d = (gn + ctx->scalarOffset).
secp256k1ScalarAdd(d, ctx.scalarOffset, gn);
/// Convert to recoded array.
for (i = 0; i < 8 && i < (Secp256k1Const.combBits + 31) >> 5; ++i) {
recoded[i] = secp256k1ScalarGetBitsLimb32(d, 32 * i, 32);
}
/// Outer loop: iterate over combOff from combSpacing - 1 down to 0.
const int combSpacing = 1;
const int combPoints = 32;
combOff = combSpacing - 1;
const int combBlocks = 43;
const int combTeeth = 6;
List<List<Secp256k1GeStorage>> secp256k1ECmultGenPrecTable = tables
.map((e) => e
.map((e) => Secp256k1GeStorage.constants(
BigInt.from(e[0]),
BigInt.from(e[1]),
BigInt.from(e[2]),
BigInt.from(e[3]),
BigInt.from(e[4]),
BigInt.from(e[5]),
BigInt.from(e[6]),
BigInt.from(e[7]),
BigInt.from(e[8]),
BigInt.from(e[9]),
BigInt.from(e[10]),
BigInt.from(e[11]),
BigInt.from(e[12]),
BigInt.from(e[13]),
BigInt.from(e[14]),
BigInt.from(e[15])))
.toList())
.toList();
while (true) {
int block;
int bitPos = combOff;
/// Inner loop: for each block, add table entries to the result.
for (block = 0; block < combBlocks; ++block) {
int bits = 0, sign, abs, index, tooth;
for (tooth = 0; tooth < combTeeth; ++tooth) {
int bitdata = secp256k1Rotr32(recoded[bitPos >> 5], bitPos & 0x1f);
/// Clear the bit at position tooth, but sssh, don't tell clang.
int vmask = (~(1 << tooth)).toUnsigned(32);
bits = (bits & vmask).toUnsigned(32);
/// Write the bit into position tooth (and junk into higher bits).
bits = (bits ^ bitdata << tooth).toUnsigned(32);
bitPos = (bitPos + combSpacing).toUnsigned(32);
}
sign = ((bits >> (combTeeth - 1)) & 1).toUnsigned(32);
abs = (bits ^ -sign) & (combPoints - 1);
_cond(sign == 0 || sign == 1, "secp256k1ECmultGen");
_cond(abs < combPoints, "secp256k1ECmultGen");
for (index = 0; index < combPoints; ++index) {
secp256k1GeStorageCmov(adds,
secp256k1ECmultGenPrecTable[block][index], (index == abs).toInt);
}
/// Set add=adds or add=-adds, in constant time, based on sign.
secp256k1GeFromStorage(add, adds);
secp256k1FeNegate(neg, add.y, 1);
secp256k1FeCmov(add.y, neg, sign);
/// Add the looked up and conditionally negated value to r.
if (first != 0) {
/// If this is the first table lookup, we can skip addition.
secp256k1GejSetGe(r, add);
/// Give the entry a random Z coordinate to blind intermediary results.
secp256k1GejRescale(r, ctx.projBlind);
first = 0;
} else {
secp256k1GejAddGe(r, r, add);
}
}
/// Double the result, except in the last iteration.
if (combOff-- == 0) break;
secp256k1GejDouble(r, r);
}
secp256k1GejAddGe(r, r, ctx.geOffset);
}