Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLS precompile native benchmarking & improvements #7544

Merged
merged 16 commits into from
Oct 9, 2024
Merged
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsConst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace Nethermind.Evm.Precompiles.Bls;

public static class BlsConst
{
public const bool DisableConcurrency = false;
public const bool DisableSubgroupChecks = false;
public const int LenFr = 32;
public const int LenFp = 64;
public const int LenFpTrimmed = 48;
Expand Down
57 changes: 42 additions & 15 deletions src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MSMPrecompile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,30 @@ public long DataGasCost(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec
}

bool fail = false;
Parallel.ForEach(pointDestinations, (dest, state, i) =>

#pragma warning disable CS0162 // Unreachable code detected
if (BlsConst.DisableConcurrency)
{
if (dest != -1)
for (int i = 0; i < pointDestinations.Count; i++)
{
int offset = (int)i * ItemSize;
ReadOnlySpan<byte> rawPoint = inputData[offset..(offset + BlsConst.LenG1)].Span;
ReadOnlySpan<byte> rawScalar = inputData[(offset + BlsConst.LenG1)..(offset + ItemSize)].Span;

G1 p = new(rawPoints.AsSpan()[(dest * 18)..]);

if (!p.TryDecodeRaw(rawPoint) || !p.InGroup())
if (!TryDecodePoint(inputData, rawPoints.AsSpan(), rawScalars.AsSpan(), pointDestinations[i], i))
{
fail = true;
state.Break();
break;
}

int destOffset = dest * 32;
rawScalar.CopyTo(rawScalars.AsSpan()[destOffset..]);
rawScalars.AsSpan()[destOffset..(destOffset + 32)].Reverse();
}
});
}
else
{
Parallel.ForEach(pointDestinations, (dest, state, i) => {
if (!TryDecodePoint(inputData, rawPoints.AsSpan(), rawScalars.AsSpan(), dest, (int)i))
{
fail = true;
state.Break();
}
});
}
#pragma warning restore CS0162 // Unreachable code detected

if (fail)
{
Expand All @@ -96,4 +99,28 @@ public long DataGasCost(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec
G1 res = new G1().MultiMult(rawPoints.AsSpan(), rawScalars.AsSpan(), npoints);
return (res.EncodeRaw(), true);
}

private static bool TryDecodePoint(ReadOnlyMemory<byte> inputData, Span<long> rawPoints, Span<byte> rawScalars, int dest, int i)
Marchhill marked this conversation as resolved.
Show resolved Hide resolved
{
if (dest == -1)
{
return true;
}

int offset = i * ItemSize;
ReadOnlySpan<byte> rawPoint = inputData[offset..(offset + BlsConst.LenG1)].Span;
ReadOnlySpan<byte> rawScalar = inputData[(offset + BlsConst.LenG1)..(offset + ItemSize)].Span;

G1 p = new(rawPoints[(dest * 18)..]);

if (!p.TryDecodeRaw(rawPoint) || !(BlsConst.DisableSubgroupChecks || p.InGroup()))
{
return false;
}

int destOffset = dest * 32;
rawScalar.CopyTo(rawScalars[destOffset..]);
rawScalars[destOffset..(destOffset + 32)].Reverse();
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private G1MulPrecompile()
}

G1 x = new(stackalloc long[G1.Sz]);
if (!x.TryDecodeRaw(inputData[..BlsConst.LenG1].Span) || !x.InGroup())
if (!x.TryDecodeRaw(inputData[..BlsConst.LenG1].Span) || !(BlsConst.DisableSubgroupChecks || x.InGroup()))
{
return IPrecompile.Failure;
}
Expand Down
57 changes: 42 additions & 15 deletions src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MSMPrecompile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,30 @@ public long DataGasCost(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec
}

bool fail = false;
Parallel.ForEach(pointDestinations, (dest, state, i) =>

#pragma warning disable CS0162 // Unreachable code detected
if (BlsConst.DisableConcurrency)
{
if (dest != -1)
for (int i = 0; i < pointDestinations.Count; i++)
{
int offset = (int)i * ItemSize;
ReadOnlySpan<byte> rawPoint = inputData[offset..(offset + BlsConst.LenG2)].Span;
ReadOnlySpan<byte> rawScalar = inputData[(offset + BlsConst.LenG2)..(offset + ItemSize)].Span;

G2 p = new(rawPoints.AsSpan()[(dest * 36)..]);

if (!p.TryDecodeRaw(rawPoint) || !p.InGroup())
if (!TryDecodePoint(inputData, rawPoints.AsSpan(), rawScalars.AsSpan(), pointDestinations[i], i))
{
fail = true;
state.Break();
break;
}

int destOffset = dest * 32;
rawScalar.CopyTo(rawScalars.AsSpan()[destOffset..]);
rawScalars.AsSpan()[destOffset..(destOffset + 32)].Reverse();
}
});
}
else
{
Parallel.ForEach(pointDestinations, (dest, state, i) => {
if (!TryDecodePoint(inputData, rawPoints.AsSpan(), rawScalars.AsSpan(), dest, (int)i))
{
fail = true;
state.Break();
}
});
}
#pragma warning restore CS0162 // Unreachable code detected

if (fail)
{
Expand All @@ -97,4 +100,28 @@ public long DataGasCost(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec

return (res.EncodeRaw(), true);
}

private static bool TryDecodePoint(ReadOnlyMemory<byte> inputData, Span<long> rawPoints, Span<byte> rawScalars, int dest, int i)
Marchhill marked this conversation as resolved.
Show resolved Hide resolved
{
if (dest == -1)
{
return true;
}

int offset = i * ItemSize;
ReadOnlySpan<byte> rawPoint = inputData[offset..(offset + BlsConst.LenG2)].Span;
ReadOnlySpan<byte> rawScalar = inputData[(offset + BlsConst.LenG2)..(offset + ItemSize)].Span;

G2 p = new(rawPoints[(dest * 36)..]);

if (!p.TryDecodeRaw(rawPoint) || !(BlsConst.DisableSubgroupChecks || p.InGroup()))
{
return false;
}

int destOffset = dest * 32;
rawScalar.CopyTo(rawScalars[destOffset..]);
rawScalars[destOffset..(destOffset + 32)].Reverse();
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private G2MulPrecompile()
}

G2 x = new(stackalloc long[G2.Sz]);
if (!x.TryDecodeRaw(inputData[..BlsConst.LenG2].Span) || !x.InGroup())
if (!x.TryDecodeRaw(inputData[..BlsConst.LenG2].Span) || !(BlsConst.DisableSubgroupChecks || x.InGroup()))
{
return IPrecompile.Failure;
}
Expand Down