Simplify -2^i * Gh generator
These values have no runtime dependencies and there are only 256
possible values so they can be made static.
MODIFY
WalletWasabi.Tests/UnitTests/Crypto/ProofSystemTests.cs
WalletWasabi.Tests/UnitTests/Crypto/ProofSystemTests.cs
@@ -207,7 +207,7 @@ namespace WalletWasabi.Tests.UnitTests.Crypto
var rangeProof = ProofSystemHelpers.Prove(knowledge, rnd);
- Assert.Equal(pass, ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, bitCommitments, 42), rangeProof));
+ Assert.Equal(pass, ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, bitCommitments, width), rangeProof));
if (!pass)
{

MODIFY
WalletWasabi/Crypto/Groups/Generators.cs
WalletWasabi/Crypto/Groups/Generators.cs
@@ -8,11 +8,6 @@ namespace WalletWasabi.Crypto.Groups
{
public static class Generators
{
- private static Dictionary<int, GroupElement[]> RangeProofWidthNegateGh2iPairs { get; } = new();
- private static object RangeProofWidthNegateGh2iPairsLock { get; } = new();
- private static Dictionary<int, Scalar[]> RangeProofWidthPowersOfTwoPairs { get; } = new();
- private static object RangeProofWidthPowersOfTwoPairsLock { get; } = new();
-
/// <summary>
/// Base point defined in the secp256k1 standard used in ECDSA public key derivation.
/// </summary>
@@ -63,32 +58,15 @@ namespace WalletWasabi.Crypto.Groups
/// </summary>
public static GroupElement Gs { get; } = FromText("Gs");
- public static GroupElement[] GetNegateGh2i(int rangeProofWidth)
- {
- lock (RangeProofWidthNegateGh2iPairsLock)
- {
- if (!RangeProofWidthNegateGh2iPairs.TryGetValue(rangeProofWidth, out var negateGh2i))
- {
- var negatedGh = Gh.Negate();
- negateGh2i = GetPowersOfTwo(rangeProofWidth).Select(b => b * negatedGh).ToArray();
- RangeProofWidthNegateGh2iPairs.Add(rangeProofWidth, negateGh2i);
- }
- return negateGh2i;
- }
- }
+ /// <summary>
+ /// Scalars corresponding to 2^i, used in range proofs.
+ /// </summary>
+ public static Scalar[] ScalarPowersOfTwo { get; } = Enumerable.Range(0, 255).Select(i => Scalar.Zero.CAddBit((uint)i, 1)).ToArray();
- public static Scalar[] GetPowersOfTwo(int rangeProofWidth)
- {
- lock (RangeProofWidthPowersOfTwoPairsLock)
- {
- if (!RangeProofWidthPowersOfTwoPairs.TryGetValue(rangeProofWidth, out var powerOfTwo))
- {
- powerOfTwo = Enumerable.Range(0, rangeProofWidth).Select(i => Scalar.Zero.CAddBit((uint)i, 1)).ToArray();
- RangeProofWidthPowersOfTwoPairs.Add(rangeProofWidth, powerOfTwo);
- }
- return powerOfTwo;
- }
- }
+ /// <summary>
+ /// Generators corresponding to -(2^i) * Gh, used in range proofs.
+ /// </summary>
+ public static GroupElement[] NegatedGhPowersOfTwo { get; } = ScalarPowersOfTwo.Select(b => b.Negate() * Gh).ToArray();
public static bool TryGetFriendlyGeneratorName(GroupElement? ge, out string name)
{

MODIFY
WalletWasabi/Crypto/ZeroKnowledge/ProofSystem.cs
WalletWasabi/Crypto/ZeroKnowledge/ProofSystem.cs
@@ -204,7 +204,7 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
// Ma, proven by showing that the public input is a commitment to 0 (only
// Gh term required to represent it). The per-bit witness terms of this
// equation are added in the loop below.
- var powersOfTwo = Generators.GetPowersOfTwo(rangeProofWidth).AsSpan(0, width);
+ var powersOfTwo = Generators.ScalarPowersOfTwo.AsSpan(0, width);
var bitsTotal = new GroupElement(ECMultContext.Instance.MultBatch(powersOfTwo, b.Select(x => x.Ge).ToArray()));
equations[0, 0] = ma - bitsTotal;
@@ -227,7 +227,7 @@ namespace WalletWasabi.Crypto.ZeroKnowledge
for (int i = 0; i < width; i++)
{
// Add [ -r_i * 2^i * Gh ] term to first equation.
- equations[0, RndColumn(i)] = Generators.GetNegateGh2i(rangeProofWidth)[i];
+ equations[0, RndColumn(i)] = Generators.NegatedGhPowersOfTwo[i];
// Add equation proving B is a Pedersen commitment to b:
// [ B = b*Gg + r*Gh ]

Simplify -2^i * Gh generator

These values have no runtime dependencies and there are only 256
possible values so they can be made static.