diff --git a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32.cs b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32.cs
index b16d58a..81af446 100644
--- a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32.cs
+++ b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32.cs
@@ -74,7 +74,7 @@ private static int MulCmp30(in ModInv32Signed30 a, int alen, in ModInv32Signed30
// to it to bring it to range [0,modulus). If sign < 0, the input will also be negated in the
// process. The input must have limbs in range (-2^30,2^30). The output will have limbs in range
// [0,2^30).
- static ModInv32Signed30 secp256k1_modinv32_normalize_30(in ModInv32Signed30 r, int sign, in ModInv32ModInfo modinfo)
+ private static ModInv32Signed30 Normalize30(in ModInv32Signed30 r, int sign, in ModInv32ModInfo modinfo)
{
const int M30 = (int)(uint.MaxValue >> 2);
int r0 = r.v0, r1 = r.v1, r2 = r.v2, r3 = r.v3, r4 = r.v4, r5 = r.v5, r6 = r.v6, r7 = r.v7, r8 = r.v8;
@@ -83,7 +83,7 @@ static ModInv32Signed30 secp256k1_modinv32_normalize_30(in ModInv32Signed30 r, i
#if DEBUG
// Verify that all limbs are in range (-2^30,2^30).
int[] rv = r.GetArray();
- for (int i = 0; i < 9; ++i)
+ for (int i = 0; i < 9; i++)
{
Debug.Assert(rv[i] >= -M30);
Debug.Assert(rv[i] <= M30);
@@ -127,8 +127,8 @@ static ModInv32Signed30 secp256k1_modinv32_normalize_30(in ModInv32Signed30 r, i
r7 += r6 >> 30; r6 &= M30;
r8 += r7 >> 30; r7 &= M30;
- // In a second step add the modulus again if the result is still negative, bringing r to range
- // [0,modulus).
+ // In a second step add the modulus again if the result is still negative,
+ // bringing r to range [0,modulus).
cond_add = r8 >> 31;
r0 += modinfo.modulus.v0 & cond_add;
r1 += modinfo.modulus.v1 & cond_add;
@@ -160,8 +160,8 @@ static ModInv32Signed30 secp256k1_modinv32_normalize_30(in ModInv32Signed30 r, i
Debug.Assert(r6 >> 30 == 0);
Debug.Assert(r7 >> 30 == 0);
Debug.Assert(r8 >> 30 == 0);
- Debug.Assert(MulCmp30(result, 9, modinfo.modulus, 0) >= 0); /* r >= 0 */
- Debug.Assert(MulCmp30(result, 9, modinfo.modulus, 1) < 0); /* r < modulus */
+ Debug.Assert(MulCmp30(result, 9, modinfo.modulus, 0) >= 0); // r >= 0
+ Debug.Assert(MulCmp30(result, 9, modinfo.modulus, 1) < 0); // r < modulus
#endif
return result;
}
@@ -176,7 +176,7 @@ static ModInv32Signed30 secp256k1_modinv32_normalize_30(in ModInv32Signed30 r, i
// Return: final zeta
//
// Implements the divsteps_n_matrix function from the explanation.
- private static int DivSteps30(int zeta, uint f0, uint g0, out secp256k1_modinv32_trans2x2 t)
+ private static int DivSteps30(int zeta, uint f0, uint g0, out ModInv32Trans2x2 t)
{
// u,v,q,r are the elements of the transformation matrix being built up,
// starting with the identity matrix. Semantically they are signed integers
@@ -218,7 +218,7 @@ private static int DivSteps30(int zeta, uint f0, uint g0, out secp256k1_modinv32
Debug.Assert(zeta >= -601 && zeta <= 601);
}
// Return data in t and return value.
- t = new secp256k1_modinv32_trans2x2(u, v, q, r);
+ t = new ModInv32Trans2x2(u, v, q, r);
// The determinant of t must be a power of two. This guarantees that multiplication with t
// does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
@@ -229,7 +229,7 @@ private static int DivSteps30(int zeta, uint f0, uint g0, out secp256k1_modinv32
}
// secp256k1_modinv32_inv256[i] = -(2*i+1)^-1 (mod 256)
- private static readonly byte[] secp256k1_modinv32_inv256 = new byte[128]
+ private static readonly byte[] Inv256 = new byte[128]
{
0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59,
0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31,
@@ -245,8 +245,8 @@ private static int DivSteps30(int zeta, uint f0, uint g0, out secp256k1_modinv32
};
- //https://github.com/bitcoin-core/secp256k1/blob/b314cf28334a91db2fe144d04f86077e2bfd7a25/src/util.h#L310
- static readonly byte[] debruijn = new byte[32]
+ //https://github.com/bitcoin-core/secp256k1/blob/1a81df826e2a24a1656fc28fc3076b62562216d9/src/util.h#L305
+ static readonly byte[] DeBruijn = new byte[32]
{
0x00, 0x01, 0x02, 0x18, 0x03, 0x13, 0x06, 0x19, 0x16, 0x04, 0x14, 0x0A,
0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B,
@@ -254,11 +254,12 @@ private static int DivSteps30(int zeta, uint f0, uint g0, out secp256k1_modinv32
};
// Determine the number of trailing zero bits in a (non-zero) 32-bit x.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- static int secp256k1_ctz32_var(uint x)
+ static int Ctz32Var(uint x)
{
// TODO: dotnet 3.0+ have: BitOperations.TrailingZeroCount()
Debug.Assert(x != 0);
- return debruijn[(uint)((x & -x) * 0x04D7651FU) >> 27];
+ // Multi-cast below mitigates the redundant conv.u8
+ return DeBruijn[((x & (uint)-(int)x) * 0x04D7651FU) >> 27];
}
@@ -271,34 +272,37 @@ static int secp256k1_ctz32_var(uint x)
// Return: final eta
//
// Implements the divsteps_n_matrix_var function from the explanation.
- static int secp256k1_modinv32_divsteps_30_var(int eta, uint f0, uint g0, out secp256k1_modinv32_trans2x2 t)
+ static int DivSteps30Var(int eta, uint f0, uint g0, out ModInv32Trans2x2 t)
{
- // Transformation matrix; see comments in secp256k1_modinv32_divsteps_30.
+ // Transformation matrix; see comments in DivSteps30().
uint u = 1, v = 0, q = 0, r = 1;
uint f = f0, g = g0, m;
ushort w;
int i = 30, limit, zeros;
- for (; ; )
+ while (true)
{
// Use a sentinel bit to count zeros only up to i.
- zeros = secp256k1_ctz32_var(g | (uint.MaxValue << i));
- /* Perform zeros divsteps at once; they all just divide g by two. */
+ zeros = Ctz32Var(g | (uint.MaxValue << i));
+ // Perform zeros divsteps at once; they all just divide g by two.
g >>= zeros;
u <<= zeros;
v <<= zeros;
eta -= zeros;
i -= zeros;
- /* We're done once we've done 30 divsteps. */
+ // We're done once we've done 30 divsteps.
if (i == 0)
+ {
break;
+ }
+
Debug.Assert((f & 1) == 1);
Debug.Assert((g & 1) == 1);
Debug.Assert((u * f0 + v * g0) == f << (30 - i));
Debug.Assert((q * f0 + r * g0) == g << (30 - i));
- /* Bounds on eta that follow from the bounds on iteration count (max 25*30 divsteps). */
+ // Bounds on eta that follow from the bounds on iteration count (max 25*30 divsteps).
Debug.Assert(eta >= -751 && eta <= 751);
- /* If eta is negative, negate it and replace f,g with g,-f. */
+ // If eta is negative, negate it and replace f,g with g,-f.
if (eta < 0)
{
uint tmp;
@@ -307,23 +311,23 @@ static int secp256k1_modinv32_divsteps_30_var(int eta, uint f0, uint g0, out sec
tmp = u; u = q; q = (uint)-tmp;
tmp = v; v = r; r = (uint)-tmp;
}
- /* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more
- * than i can be cancelled out (as we'd be done before that point), and no more than eta+1
- * can be done as its sign will flip once that happens. */
+ // eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more
+ // than i can be cancelled out (as we'd be done before that point), and no more than eta+1
+ // can be done as its sign will flip once that happens.
limit = (eta + 1) > i ? i : (eta + 1);
- /* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */
+ // m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits).
Debug.Assert(limit > 0 && limit <= 30);
m = (uint.MaxValue >> (32 - limit)) & 255U;
- /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
- w = (ushort)((g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m);
- /* Do so. */
+ // Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits.
+ w = (ushort)((g * Inv256[(f >> 1) & 127]) & m);
+ // Do so
g += f * w;
q += u * w;
r += v * w;
Debug.Assert((g & m) == 0);
}
// Return data in t and return value.
- t = new secp256k1_modinv32_trans2x2(u, v, q, r);
+ t = new ModInv32Trans2x2(u, v, q, r);
// The determinant of t must be a power of two. This guarantees that multiplication with t
// does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
// will be divided out again). As each divstep's individual matrix has determinant 2, the
@@ -332,20 +336,24 @@ static int secp256k1_modinv32_divsteps_30_var(int eta, uint f0, uint g0, out sec
return eta;
}
- /* Compute the transition matrix and eta for 30 posdivsteps (variable time, eta=-delta), and keeps track
- * of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^32 rather than 2^30, because
- * Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2).
- *
- * Input: eta: initial eta
- * f0: bottom limb of initial f
- * g0: bottom limb of initial g
- * Output: t: transition matrix
- * Input/Output: (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign
- * by applying the returned transformation matrix to it. The other bits of *jacp may
- * change, but are meaningless.
- * Return: final eta
- */
- static int secp256k1_modinv32_posdivsteps_30_var(int eta, uint f0, uint g0, secp256k1_modinv32_trans2x2 t, ref int jacp)
+
+ ///
+ /// Compute the transition matrix and eta for 30 posdivsteps (variable time, eta=-delta), and keeps track
+ /// of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^32 rather than 2^30, because
+ /// Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2).
+ ///
+ ///
+ /// (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign
+ /// by applying the returned transformation matrix to it. The other bits of *jacp may
+ /// change, but are meaningless.
+ ///
+ /// initial eta
+ /// bottom limb of initial f
+ /// bottom limb of initial g
+ /// transition matrix
+ ///
+ /// final eta
+ static int PosDivSteps30Var(int eta, uint f0, uint g0, ModInv32Trans2x2 t, ref int jacp)
{
/* Transformation matrix. */
uint u = 1, v = 0, q = 0, r = 1;
@@ -354,10 +362,10 @@ static int secp256k1_modinv32_posdivsteps_30_var(int eta, uint f0, uint g0, secp
int i = 30, limit, zeros;
int jac = jacp;
- for (; ; )
+ while (true)
{
/* Use a sentinel bit to count zeros only up to i. */
- zeros = secp256k1_ctz32_var(g | (uint.MaxValue << i));
+ zeros = Ctz32Var(g | (uint.MaxValue << i));
/* Perform zeros divsteps at once; they all just divide g by two. */
g >>= zeros;
u <<= zeros;
@@ -393,7 +401,7 @@ static int secp256k1_modinv32_posdivsteps_30_var(int eta, uint f0, uint g0, secp
Debug.Assert(limit > 0 && limit <= 30);
m = (uint.MaxValue >> (32 - limit)) & 255U;
/* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
- w = (ushort)((g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m);
+ w = (ushort)((g * Inv256[(f >> 1) & 127]) & m);
/* Do so. */
g += f * w;
q += u * w;
@@ -416,22 +424,15 @@ static int secp256k1_modinv32_posdivsteps_30_var(int eta, uint f0, uint g0, secp
}
- ///
- /// Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps.
- ///
- /// On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be
- /// in range (-2^30,2^30).
- ///
- /// This implements the update_de function from the explanation.
- ///
- ///
- ///
- ///
- ///
- internal static void UpdateDE30(ref ModInv32Signed30 d, ref ModInv32Signed30 e, secp256k1_modinv32_trans2x2 t, in ModInv32ModInfo modinfo)
+ // Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps.
+ //
+ // On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be
+ // in range (-2^30,2^30).
+ //
+ // This implements the update_de function from the explanation.
+ internal static void UpdateDE30(ref ModInv32Signed30 d, ref ModInv32Signed30 e, ModInv32Trans2x2 t, in ModInv32ModInfo modinfo)
{
const int M30 = (int)(uint.MaxValue >> 2);
- int u = t.u, v = t.v, q = t.q, r = t.r;
int di, ei, md, me, sd, se;
long cd, ce;
#if DEBUG
@@ -439,19 +440,19 @@ internal static void UpdateDE30(ref ModInv32Signed30 d, ref ModInv32Signed30 e,
Debug.Assert(MulCmp30(d, 9, modinfo.modulus, 1) < 0); // d < modulus
Debug.Assert(MulCmp30(e, 9, modinfo.modulus, -2) > 0); // e > -2*modulus
Debug.Assert(MulCmp30(e, 9, modinfo.modulus, 1) < 0); // e < modulus
- Debug.Assert(Math.Abs(u) <= (M30 + 1 - Math.Abs(v))); // |u|+|v| <= 2^30
- Debug.Assert(Math.Abs(q) <= (M30 + 1 - Math.Abs(r))); // |q|+|r| <= 2^30
+ Debug.Assert(Math.Abs(t.u) <= (M30 + 1 - Math.Abs(t.v))); // |u|+|v| <= 2^30
+ Debug.Assert(Math.Abs(t.q) <= (M30 + 1 - Math.Abs(t.r))); // |q|+|r| <= 2^30
#endif
// [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative.
sd = d.v8 >> 31;
se = e.v8 >> 31;
- md = (u & sd) + (v & se);
- me = (q & sd) + (r & se);
+ md = (t.u & sd) + (t.v & se);
+ me = (t.q & sd) + (t.r & se);
// Begin computing t*[d,e]
di = d.v0;
ei = e.v0;
- cd = (long)u * di + (long)v * ei;
- ce = (long)q * di + (long)r * ei;
+ cd = (long)t.u * di + (long)t.v * ei;
+ ce = (long)t.q * di + (long)t.r * ei;
// Correct md,me so that t*[d,e]+modulus*[md,me] has 30 zero bottom bits.
md -= (int)((modinfo.modulus_inv30 * (uint)cd + md) & M30);
me -= (int)((modinfo.modulus_inv30 * (uint)ce + me) & M30);
@@ -466,65 +467,62 @@ internal static void UpdateDE30(ref ModInv32Signed30 d, ref ModInv32Signed30 e,
int[] dv = d.GetArray();
int[] ev = e.GetArray();
int[] modv = modinfo.modulus.GetArray();
- for (int i = 1; i < 9; ++i)
+ for (int i = 1; i < 9; i++)
{
di = dv[i];
ei = ev[i];
- cd += (long)u * di + (long)v * ei;
- ce += (long)q * di + (long)r * ei;
+ cd += (long)t.u * di + (long)t.v * ei;
+ ce += (long)t.q * di + (long)t.r * ei;
cd += (long)modv[i] * md;
ce += (long)modv[i] * me;
dv[i - 1] = (int)cd & M30; cd >>= 30;
ev[i - 1] = (int)ce & M30; ce >>= 30;
}
- /* What remains is limb 9 of t*[d,e]+modulus*[md,me]; store it as output limb 8. */
+ // What remains is limb 9 of t*[d,e]+modulus*[md,me]; store it as output limb 8.
dv[8] = (int)cd;
ev[8] = (int)ce;
d = new ModInv32Signed30(dv);
e = new ModInv32Signed30(ev);
#if DEBUG
- Debug.Assert(MulCmp30(d, 9, modinfo.modulus, -2) > 0); /* d > -2*modulus */
- Debug.Assert(MulCmp30(d, 9, modinfo.modulus, 1) < 0); /* d < modulus */
- Debug.Assert(MulCmp30(e, 9, modinfo.modulus, -2) > 0); /* e > -2*modulus */
- Debug.Assert(MulCmp30(e, 9, modinfo.modulus, 1) < 0); /* e < modulus */
+ Debug.Assert(MulCmp30(d, 9, modinfo.modulus, -2) > 0); // d > -2*modulus
+ Debug.Assert(MulCmp30(d, 9, modinfo.modulus, 1) < 0); // d < modulus
+ Debug.Assert(MulCmp30(e, 9, modinfo.modulus, -2) > 0); // e > -2*modulus
+ Debug.Assert(MulCmp30(e, 9, modinfo.modulus, 1) < 0); // e < modulus
#endif
}
- /* Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps.
- *
- * This implements the update_fg function from the explanation.
- */
- static void secp256k1_modinv32_update_fg_30(ref ModInv32Signed30 f, ref ModInv32Signed30 g, secp256k1_modinv32_trans2x2 t)
+ // Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps.
+ //
+ // This implements the update_fg function from the explanation.
+ static void UpdateFG30(ref ModInv32Signed30 f, ref ModInv32Signed30 g, ModInv32Trans2x2 t)
{
const int M30 = (int)(uint.MaxValue >> 2);
- int u = t.u, v = t.v, q = t.q, r = t.r;
int fi, gi;
long cf, cg;
- int i;
- /* Start computing t*[f,g]. */
+ // Start computing t*[f,g].
fi = f.v0;
gi = g.v0;
- cf = (long)u * fi + (long)v * gi;
- cg = (long)q * fi + (long)r * gi;
- /* Verify that the bottom 30 bits of the result are zero, and then throw them away. */
+ cf = (long)t.u * fi + (long)t.v * gi;
+ cg = (long)t.q * fi + (long)t.r * gi;
+ // Verify that the bottom 30 bits of the result are zero, and then throw them away.
Debug.Assert(((int)cf & M30) == 0); cf >>= 30;
Debug.Assert(((int)cg & M30) == 0); cg >>= 30;
- /* Now iteratively compute limb i=1..8 of t*[f,g], and store them in output limb i-1 (shifting
- * down by 30 bits). */
+ // Now iteratively compute limb i=1..8 of t*[f,g], and store them in output limb i-1 (shifting
+ // down by 30 bits).
int[] fv = f.GetArray();
int[] gv = g.GetArray();
- for (i = 1; i < 9; ++i)
+ for (int i = 1; i < 9; i++)
{
fi = fv[i];
gi = gv[i];
- cf += (long)u * fi + (long)v * gi;
- cg += (long)q * fi + (long)r * gi;
+ cf += (long)t.u * fi + (long)t.v * gi;
+ cg += (long)t.q * fi + (long)t.r * gi;
fv[i - 1] = (int)cf & M30; cf >>= 30;
gv[i - 1] = (int)cg & M30; cg >>= 30;
}
- /* What remains is limb 9 of t*[f,g]; store it as output limb 8. */
+ // What remains is limb 9 of t*[f,g]; store it as output limb 8.
fv[8] = (int)cf;
gv[8] = (int)cg;
@@ -532,42 +530,39 @@ static void secp256k1_modinv32_update_fg_30(ref ModInv32Signed30 f, ref ModInv32
g = new ModInv32Signed30(gv);
}
- /* Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps.
- *
- * Version that operates on a variable number of limbs in f and g.
- *
- * This implements the update_fg function from the explanation in modinv64_impl.h.
- */
- static void secp256k1_modinv32_update_fg_30_var(int len, ref ModInv32Signed30 f, ref ModInv32Signed30 g, secp256k1_modinv32_trans2x2 t)
+ // Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps.
+ //
+ // Version that operates on a variable number of limbs in f and g.
+ //
+ // This implements the update_fg function from the explanation in modinv64_impl.h.
+ static void UpdateFG30Var(int len, ref ModInv32Signed30 f, ref ModInv32Signed30 g, ModInv32Trans2x2 t)
{
const int M30 = (int)(uint.MaxValue >> 2);
- int u = t.u, v = t.v, q = t.q, r = t.r;
int fi, gi;
long cf, cg;
- int i;
Debug.Assert(len > 0);
- /* Start computing t*[f,g]. */
+ // Start computing t*[f,g].
fi = f.v0;
gi = g.v0;
- cf = (long)u * fi + (long)v * gi;
- cg = (long)q * fi + (long)r * gi;
- /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
+ cf = (long)t.u * fi + (long)t.v * gi;
+ cg = (long)t.q * fi + (long)t.r * gi;
+ // Verify that the bottom 62 bits of the result are zero, and then throw them away.
Debug.Assert(((int)cf & M30) == 0); cf >>= 30;
Debug.Assert(((int)cg & M30) == 0); cg >>= 30;
- /* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting
- * down by 30 bits). */
+ // Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting
+ // down by 30 bits).
int[] fv = f.GetArray();
int[] gv = g.GetArray();
- for (i = 1; i < len; ++i)
+ for (int i = 1; i < len; i++)
{
fi = fv[i];
gi = gv[i];
- cf += (long)u * fi + (long)v * gi;
- cg += (long)q * fi + (long)r * gi;
+ cf += (long)t.u * fi + (long)t.v * gi;
+ cg += (long)t.q * fi + (long)t.r * gi;
fv[i - 1] = (int)cf & M30; cf >>= 30;
gv[i - 1] = (int)cg & M30; cg >>= 30;
}
- /* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */
+ // What remains is limb (len) of t*[f,g]; store it as output limb (len-1).
fv[len - 1] = (int)cf;
gv[len - 1] = (int)cg;
@@ -599,32 +594,32 @@ public static void Compute(ref ModInv32Signed30 x, in ModInv32ModInfo modinfo)
for (int i = 0; i < 20; i++)
{
// Compute transition matrix and new zeta after 30 divsteps.
- zeta = DivSteps30(zeta, (uint)f.v0, (uint)g.v0, out secp256k1_modinv32_trans2x2 t);
+ zeta = DivSteps30(zeta, (uint)f.v0, (uint)g.v0, out ModInv32Trans2x2 t);
// Update d,e using that transition matrix.
UpdateDE30(ref d, ref e, t, modinfo);
- /* Update f,g using that transition matrix. */
+ // Update f,g using that transition matrix.
#if DEBUG
- Debug.Assert(MulCmp30(f, 9, modinfo.modulus, -1) > 0); /* f > -modulus */
- Debug.Assert(MulCmp30(f, 9, modinfo.modulus, 1) <= 0); /* f <= modulus */
- Debug.Assert(MulCmp30(g, 9, modinfo.modulus, -1) > 0); /* g > -modulus */
- Debug.Assert(MulCmp30(g, 9, modinfo.modulus, 1) < 0); /* g < modulus */
+ Debug.Assert(MulCmp30(f, 9, modinfo.modulus, -1) > 0); // f > -modulus
+ Debug.Assert(MulCmp30(f, 9, modinfo.modulus, 1) <= 0); // f <= modulus
+ Debug.Assert(MulCmp30(g, 9, modinfo.modulus, -1) > 0); // g > -modulus
+ Debug.Assert(MulCmp30(g, 9, modinfo.modulus, 1) < 0); // g < modulus
#endif
- secp256k1_modinv32_update_fg_30(ref f, ref g, t);
+ UpdateFG30(ref f, ref g, t);
#if DEBUG
- Debug.Assert(MulCmp30(f, 9, modinfo.modulus, -1) > 0); /* f > -modulus */
- Debug.Assert(MulCmp30(f, 9, modinfo.modulus, 1) <= 0); /* f <= modulus */
- Debug.Assert(MulCmp30(g, 9, modinfo.modulus, -1) > 0); /* g > -modulus */
- Debug.Assert(MulCmp30(g, 9, modinfo.modulus, 1) < 0); /* g < modulus */
+ Debug.Assert(MulCmp30(f, 9, modinfo.modulus, -1) > 0); // f > -modulus
+ Debug.Assert(MulCmp30(f, 9, modinfo.modulus, 1) <= 0); // f <= modulus
+ Debug.Assert(MulCmp30(g, 9, modinfo.modulus, -1) > 0); // g > -modulus
+ Debug.Assert(MulCmp30(g, 9, modinfo.modulus, 1) < 0); // g < modulus
#endif
}
- /* At this point sufficient iterations have been performed that g must have reached 0
- * and (if g was not originally 0) f must now equal +/- GCD of the initial f, g
- * values i.e. +/- 1, and d now contains +/- the modular inverse. */
+ // At this point sufficient iterations have been performed that g must have reached 0
+ // and (if g was not originally 0) f must now equal +/- GCD of the initial f, g
+ // values i.e. +/- 1, and d now contains +/- the modular inverse.
#if DEBUG
- /* g == 0 */
+ // g == 0
Debug.Assert(MulCmp30(g, 9, ModInv32Signed30.One, 0) == 0);
- /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */
+ // |f| == 1, or (x == 0 and d == 0 and |f|=modulus)
Debug.Assert(MulCmp30(f, 9, ModInv32Signed30.One, -1) == 0 ||
MulCmp30(f, 9, ModInv32Signed30.One, 1) == 0 ||
(MulCmp30(x, 9, ModInv32Signed30.One, 0) == 0 &&
@@ -633,9 +628,8 @@ public static void Compute(ref ModInv32Signed30 x, in ModInv32ModInfo modinfo)
MulCmp30(f, 9, modinfo.modulus, -1) == 0)));
#endif
- /* Optionally negate d, normalize to [0,modulus), and return it. */
- x = secp256k1_modinv32_normalize_30(d, f.v8, modinfo);
-
+ // Optionally negate d, normalize to [0,modulus), and return it.
+ x = Normalize30(d, f.v8, modinfo);
}
@@ -650,7 +644,7 @@ public static void Compute(ref ModInv32Signed30 x, in ModInv32ModInfo modinfo)
///
public static void ComputeVar(ref ModInv32Signed30 x, ModInv32ModInfo modinfo)
{
- /* Start with d=0, e=1, f=modulus, g=x, eta=-1. */
+ // Start with d=0, e=1, f=modulus, g=x, eta=-1.
ModInv32Signed30 d = ModInv32Signed30.Zero;
ModInv32Signed30 e = ModInv32Signed30.One;
ModInv32Signed30 f = modinfo.modulus;
@@ -659,48 +653,47 @@ public static void ComputeVar(ref ModInv32Signed30 x, ModInv32ModInfo modinfo)
int i = 0;
#endif
int j, len = 9;
- int eta = -1; /* eta = -delta; delta is initially 1 (faster for the variable-time code) */
+ int eta = -1; // eta = -delta; delta is initially 1 (faster for the variable-time code)
int cond, fn, gn;
- /* Do iterations of 30 divsteps each until g=0. */
+ // Do iterations of 30 divsteps each until g=0.
while (true)
{
- /* Compute transition matrix and new eta after 30 divsteps. */
- secp256k1_modinv32_trans2x2 t;
- eta = secp256k1_modinv32_divsteps_30_var(eta, (uint)f.v0, (uint)g.v0, out t);
- /* Update d,e using that transition matrix. */
+ // Compute transition matrix and new eta after 30 divsteps.
+ eta = DivSteps30Var(eta, (uint)f.v0, (uint)g.v0, out ModInv32Trans2x2 t);
+ // Update d,e using that transition matrix.
UpdateDE30(ref d, ref e, t, modinfo);
- /* Update f,g using that transition matrix. */
+ // Update f,g using that transition matrix.
# if DEBUG
Debug.Assert(MulCmp30(f, len, modinfo.modulus, -1) > 0); /* f > -modulus */
Debug.Assert(MulCmp30(f, len, modinfo.modulus, 1) <= 0); /* f <= modulus */
Debug.Assert(MulCmp30(g, len, modinfo.modulus, -1) > 0); /* g > -modulus */
Debug.Assert(MulCmp30(g, len, modinfo.modulus, 1) < 0); /* g < modulus */
#endif
- secp256k1_modinv32_update_fg_30_var(len, ref f, ref g, t);
+ UpdateFG30Var(len, ref f, ref g, t);
- /* If the bottom limb of g is 0, there is a chance g=0. */
+ // If the bottom limb of g is 0, there is a chance g=0.
int[] fv = f.GetArray();
int[] gv = g.GetArray();
if (gv[0] == 0)
{
cond = 0;
- /* Check if all other limbs are also 0. */
+ // Check if all other limbs are also 0.
for (j = 1; j < len; ++j)
{
cond |= gv[j];
}
- /* If so, we're done. */
+ // If so, we're done.
if (cond == 0) break;
}
- /* Determine if len>1 and limb (len-1) of both f and g is 0 or -1. */
+ // Determine if len>1 and limb (len-1) of both f and g is 0 or -1.
fn = fv[len - 1];
gn = gv[len - 1];
cond = (len - 2) >> 31;
cond |= fn ^ (fn >> 31);
cond |= gn ^ (gn >> 31);
- /* If so, reduce length, propagating the sign of f and g's top limb into the one below. */
+ // If so, reduce length, propagating the sign of f and g's top limb into the one below.
if (cond == 0)
{
fv[len - 2] |= fn << 30;
@@ -711,20 +704,20 @@ public static void ComputeVar(ref ModInv32Signed30 x, ModInv32ModInfo modinfo)
f = new ModInv32Signed30(fv);
g = new ModInv32Signed30(gv);
#if DEBUG
- Debug.Assert(++i < 25); /* We should never need more than 25*30 = 750 divsteps */
- Debug.Assert(MulCmp30(f, len, modinfo.modulus, -1) > 0); /* f > -modulus */
- Debug.Assert(MulCmp30(f, len, modinfo.modulus, 1) <= 0); /* f <= modulus */
- Debug.Assert(MulCmp30(g, len, modinfo.modulus, -1) > 0); /* g > -modulus */
- Debug.Assert(MulCmp30(g, len, modinfo.modulus, 1) < 0); /* g < modulus */
+ Debug.Assert(++i < 25); // We should never need more than 25*30 = 750 divsteps
+ Debug.Assert(MulCmp30(f, len, modinfo.modulus, -1) > 0); // f > -modulus
+ Debug.Assert(MulCmp30(f, len, modinfo.modulus, 1) <= 0); // f <= modulus
+ Debug.Assert(MulCmp30(g, len, modinfo.modulus, -1) > 0); // g > -modulus
+ Debug.Assert(MulCmp30(g, len, modinfo.modulus, 1) < 0); // g < modulus
#endif
}
- /* At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of
- * the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse. */
+ // At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of
+ // the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse.
#if DEBUG
- /* g == 0 */
+ // g == 0
Debug.Assert(MulCmp30(g, len, ModInv32Signed30.One, 0) == 0);
- /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */
+ // |f| == 1, or (x == 0 and d == 0 and |f|=modulus)
Debug.Assert(MulCmp30(f, len, ModInv32Signed30.One, -1) == 0 ||
MulCmp30(f, len, ModInv32Signed30.One, 1) == 0 ||
(MulCmp30(x, 9, ModInv32Signed30.One, 0) == 0 &&
@@ -733,9 +726,9 @@ public static void ComputeVar(ref ModInv32Signed30 x, ModInv32ModInfo modinfo)
MulCmp30(f, len, modinfo.modulus, -1) == 0)));
#endif
- /* Optionally negate d, normalize to [0,modulus), and return it. */
+ // Optionally negate d, normalize to [0,modulus), and return it.
int[] tempArr = f.GetArray();
- x = secp256k1_modinv32_normalize_30(d, tempArr[len - 1], modinfo);
+ x = Normalize30(d, tempArr[len - 1], modinfo);
}
}
}
diff --git a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32ModInfo.cs b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32ModInfo.cs
index e09b976..56d1b43 100644
--- a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32ModInfo.cs
+++ b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32ModInfo.cs
@@ -23,16 +23,16 @@ public ModInv32ModInfo(in ModInv32Signed30 mod, uint modinv30)
internal static ref readonly ModInv32ModInfo Constant => ref _const;
}
- internal class secp256k1_modinv32_trans2x2
+ internal class ModInv32Trans2x2
{
- internal secp256k1_modinv32_trans2x2(uint u, uint v, uint q, uint r)
+ internal ModInv32Trans2x2(uint u, uint v, uint q, uint r)
{
this.u = (int)u;
this.v = (int)v;
this.q = (int)q;
this.r = (int)r;
}
- internal secp256k1_modinv32_trans2x2(int u, int v, int q, int r)
+ internal ModInv32Trans2x2(int u, int v, int q, int r)
{
this.u = u;
this.v = v;
diff --git a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32Signed30.cs b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32Signed30.cs
index bc6840e..5168559 100644
--- a/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32Signed30.cs
+++ b/Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/ModInv32Signed30.cs
@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file LICENCE or http://www.opensource.org/licenses/mit-license.php.
+using System;
using System.Diagnostics;
namespace Autarkysoft.Bitcoin.Cryptography.EllipticCurve
@@ -30,7 +31,7 @@ public ModInv32Signed30(int a0, int a1, int a2, int a3, int a4, int a5, int a6,
v4 = a4; v5 = a5; v6 = a6; v7 = a7; v8 = a8;
}
- public ModInv32Signed30(int[] arr)
+ public ModInv32Signed30(ReadOnlySpan arr)
{
Debug.Assert(arr.Length == 9);
v0 = arr[0]; v1 = arr[1]; v2 = arr[2]; v3 = arr[3];