Skip to content

Commit

Permalink
EIP 152 - Blake2 implementation fix #816
Browse files Browse the repository at this point in the history
  • Loading branch information
spetz committed Aug 27, 2019
1 parent 447f1ae commit 521d7bc
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 25 deletions.
38 changes: 21 additions & 17 deletions src/Nethermind/Nethermind.Core/Blake2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

namespace Nethermind.Core
{
/// <summary>
/// Code adapted from pantheon (https://github.com/PegaSysEng/pantheon)
/// </summary>
public class Blake2
{
private static readonly byte[][] Precomputed =
Expand All @@ -39,37 +42,34 @@ public class Blake2

private static readonly ulong[] IV =
{
0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL,
0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL,
0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L
0x6a09e667f3bcc908ul, 0xbb67ae8584caa73bul, 0x3c6ef372fe94f82bul,
0xa54ff53a5f1d36f1ul, 0x510e527fade682d1ul, 0x9b05688c2b3e6c1ful,
0x1f83d9abfb41bd6bul, 0x5be0cd19137e2179ul
};

private ulong[] _h = new ulong[8];
private ulong[] _m = new ulong[16];
private ulong[] _t = new ulong[2];
private ulong[] _v = new ulong[16];
private bool _f;
private uint _rounds;
private uint _rounds = 12;

public byte[] Compress(byte[] input)
{
Init(input);

var t0 = _t[0];
var t1 = _t[1];


Array.Copy(_h, 0, _v, 0, 8);
Array.Copy(IV, 0, _v, 8, 8);

_v[12] ^= t0;
_v[13] ^= t1;
_v[12] ^= _t[0];
_v[13] ^= _t[1];

if (_f)
{
_v[14] ^= 0xffffffffffffffffL;
_v[14] ^= 0xfffffffffffffffful;
}

for (ulong i = 0; i < _rounds; ++i)
for (var i = 0; i < _rounds; ++i)
{
var s = Precomputed[i % 10];
Compute(_m[s[0]], _m[s[4]], 0, 4, 8, 12);
Expand All @@ -87,7 +87,6 @@ public byte[] Compress(byte[] input)
_h[offset] ^= _v[offset] ^ _v[offset + 8];
}


var result = new byte[_h.Length * 8];
for (var i = 0; i < _h.Length; i++)
{
Expand Down Expand Up @@ -122,14 +121,19 @@ private void Init(byte[] input)
private void Compute(ulong a, ulong b, int i, int j, int k, int l)
{
_v[i] += a + _v[j];
_v[l] = _v[l] >> 32 ^ _v[i] << 32;
_v[l] = RotateLeft(_v[l] ^ _v[i], -32);
_v[k] += _v[l];
_v[j] = _v[j] >> 24 ^ _v[k] << 24;
_v[j] = RotateLeft(_v[j] ^ _v[k], -24);

_v[i] += b + _v[j];
_v[l] = _v[l] >> 16 ^ _v[i] << 16;
_v[l] = RotateLeft(_v[l] ^ _v[i], -16);
_v[k] += _v[l];
_v[j] = _v[j] >> 63 ^ _v[k] << 63;
_v[j] = RotateLeft(_v[j] ^ _v[k], -63);
}

private static ulong RotateLeft(ulong value, int count)
{
return (value << count) | (value >> (64 - count));
}
}
}
12 changes: 11 additions & 1 deletion src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
*/

using Nethermind.Core.Specs;
using Nethermind.Evm.Precompiles;
using NUnit.Framework;

namespace Nethermind.Evm.Test
{
public class Eip152Tests : VirtualMachineTestsBase
{
private const int InputLength = 213;
protected override long BlockNumber => MainNetSpecProvider.IstanbulBlockNumber + _blockNumberAdjustment;

private int _blockNumberAdjustment;
Expand All @@ -32,15 +34,23 @@ public void TearDown()
{
_blockNumberAdjustment = 0;
}

[Test]
public void before_istanbul()
{
_blockNumberAdjustment = -1;
var precompileAddress = Blake2BPrecompiledContract.Instance.Address;
Assert.False(precompileAddress.IsPrecompiled(Spec));
}

[Test]
public void after_istanbul()
{
var code = Prepare.EvmCode
.CallWithInput(Blake2BPrecompiledContract.Instance.Address, 1000L, new byte[InputLength])
.Done;
var result = Execute(code);
Assert.AreEqual(StatusCode.Success, result.StatusCode);
}
}
}
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Evm/GasCostOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public static class GasCostOf
public const long CodeDeposit = 200;
public const long Call = 40;
public const long CallEip150 = 700;
public const long CallEip152 = 12;
public const long CallValue = 9000;
public const long CallStipend = 2300;
public const long NewAccount = 25000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static bool IsPrecompiled(this Address address, IReleaseSpec releaseSpec)
}

BigInteger asInt = address.Bytes.ToUnsignedBigInteger();
if (asInt == 0 || asInt > 8)
if (asInt == 0 || asInt > 9)
{
return false;
}
Expand All @@ -52,8 +52,13 @@ public static bool IsPrecompiled(this Address address, IReleaseSpec releaseSpec)
{
return releaseSpec.IsEip196Enabled;
}

if (asInt == 8)
{
return releaseSpec.IsEip197Enabled;
}

return asInt == 8 && releaseSpec.IsEip197Enabled;
return asInt == 9 && releaseSpec.IsEip152Enabled;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,42 @@ namespace Nethermind.Evm.Precompiles
{
public class Blake2BPrecompiledContract : IPrecompiledContract
{
private const int RequiredInputLength = 213;
public static readonly IPrecompiledContract Instance = new Blake2BPrecompiledContract();

public Address Address { get; } = Address.FromNumber(9);

public long BaseGasCost(IReleaseSpec releaseSpec) => 0;

public long DataGasCost(byte[] inputData, IReleaseSpec releaseSpec) => 12;
public long DataGasCost(byte[] inputData, IReleaseSpec releaseSpec)
{
if (inputData.Length != RequiredInputLength)
{
return 0;
}

var finalByte = inputData[212];
if (finalByte != 0 && finalByte != 1)
{
return 0;
}

var rounds = inputData.Slice(0, 4).ToUInt32();

return rounds;
}

public (byte[], bool) Run(byte[] inputData)
{
if (inputData.Length != 213)
if (inputData.Length != RequiredInputLength)
{
return (Bytes.Empty, true);
return (Bytes.Empty, false);
}

var finalByte = inputData[212];
if (finalByte != 0 && finalByte != 1)
{
return (Bytes.Empty, true);
return (Bytes.Empty, false);
}

var blake = new Blake2();
Expand Down

0 comments on commit 521d7bc

Please sign in to comment.