Skip to content

Commit

Permalink
EIP 152 - Blake2 implementation #816
Browse files Browse the repository at this point in the history
  • Loading branch information
spetz committed Aug 26, 2019
1 parent 198f962 commit 088dd82
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 21 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,3 @@
path = src/rocksdb-sharp
url = https://github.com/NethermindEth/rocksdb-sharp.git
branch = master
[submodule "src/Blake2Fast"]
path = src/Blake2Fast
url = git@github.com:saucecontrol/Blake2Fast.git
1 change: 0 additions & 1 deletion src/Blake2Fast
Submodule Blake2Fast deleted from 603a7b
40 changes: 40 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Blake2Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 Demerzel Solutions Limited
* This file is part of the Nethermind library.
*
* The Nethermind library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Nethermind library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
*/

using FluentAssertions;
using Nethermind.Core.Extensions;
using NUnit.Framework;

namespace Nethermind.Core.Test
{
public class Blake2Tests
{
[Test]
[TestCase("0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b")]
[TestCase("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")]
[TestCase("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000", "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735")]
[TestCase("0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421")]
// [TestCase("ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615")]
public void compression_function_should_return_valid_output(string input, string output)
{
var blake2 = new Blake2();
var result = blake2.Compress(Bytes.FromHexString(input)).ToHexString();
result.Should().BeEquivalentTo(output);
}
}
}
135 changes: 135 additions & 0 deletions src/Nethermind/Nethermind.Core/Blake2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2018 Demerzel Solutions Limited
* This file is part of the Nethermind library.
*
* The Nethermind library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Nethermind library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using Nethermind.Core.Extensions;

namespace Nethermind.Core
{
public class Blake2
{
private static readonly byte[][] Precomputed =
{
new byte[] {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
new byte[] {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
new byte[] {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
new byte[] {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
new byte[] {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
new byte[] {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
new byte[] {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
new byte[] {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
new byte[] {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
new byte[] {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}
};

private static readonly ulong[] IV =
{
0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL,
0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL,
0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L
};

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;

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;

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

for (ulong i = 0; i < _rounds; ++i)
{
var s = Precomputed[i % 10];
Compute(_m[s[0]], _m[s[4]], 0, 4, 8, 12);
Compute(_m[s[1]], _m[s[5]], 1, 5, 9, 13);
Compute(_m[s[2]], _m[s[6]], 2, 6, 10, 14);
Compute(_m[s[3]], _m[s[7]], 3, 7, 11, 15);
Compute(_m[s[8]], _m[s[12]], 0, 5, 10, 15);
Compute(_m[s[9]], _m[s[13]], 1, 6, 11, 12);
Compute(_m[s[10]], _m[s[14]], 2, 7, 8, 13);
Compute(_m[s[11]], _m[s[15]], 3, 4, 9, 14);
}

for (var offset = 0; offset < _h.Length; offset++)
{
_h[offset] ^= _v[offset] ^ _v[offset + 8];
}


var result = new byte[_h.Length * 8];
for (var i = 0; i < _h.Length; i++)
{
Array.Copy(_h[i].ToByteArray(Bytes.Endianness.Little), 0, result, i * 8, 8);
}

return result;
}

private void Init(byte[] input)
{
_rounds = input.Slice(0, 4).ToUInt32();
var h = input.Slice(4, 64);
var m = input.Slice(68, 128);
for (var i = 0; i < _h.Length; i++)
{
var offset = i * 8;
_h[i] = h.Slice(offset, 8).ToUInt64(Bytes.Endianness.Little);
}

for (var i = 0; i < _m.Length; i++)
{
var offset = i * 8;
_m[i] = m.Slice(offset, 8).ToUInt64(Bytes.Endianness.Little);
}

_t[0] = input.Slice(196, 8).ToUInt64(Bytes.Endianness.Little);
_t[1] = input.Slice(204, 8).ToUInt64(Bytes.Endianness.Little);
_f = input[212] != 0;
}

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[k] += _v[l];
_v[j] = _v[j] >> 24 ^ _v[k] << 24;

_v[i] += b + _v[j];
_v[l] = _v[l] >> 16 ^ _v[i] << 16;
_v[k] += _v[l];
_v[j] = _v[j] >> 63 ^ _v[k] << 63;
}
}
}
46 changes: 46 additions & 0 deletions src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018 Demerzel Solutions Limited
* This file is part of the Nethermind library.
*
* The Nethermind library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Nethermind library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
*/

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

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

private int _blockNumberAdjustment;

[TearDown]
public void TearDown()
{
_blockNumberAdjustment = 0;
}

[Test]
public void before_istanbul()
{
}

[Test]
public void after_istanbul()
{
}
}
}
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Evm/GasCostOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ 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
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Evm/Nethermind.Evm.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Blake2Fast\src\Blake2Fast\Blake2Fast.csproj" />
<ProjectReference Include="..\..\Dirichlet\Nethermind.Dirichlet.Numerics\Nethermind.Dirichlet.Numerics.csproj" />
<ProjectReference Include="..\Nethermind.Core\Nethermind.Core.csproj" />
<ProjectReference Include="..\Nethermind.Store\Nethermind.Store.csproj">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
*/

using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using SauceControl.Blake2Fast;

namespace Nethermind.Evm.Precompiles
{
Expand All @@ -34,12 +34,19 @@ public class Blake2BPrecompiledContract : IPrecompiledContract

public (byte[], bool) Run(byte[] inputData)
{
Metrics.Blake2BPrecompile++;
var context = default(Blake2bContext);
//TODO: compression function
// context.Init(digestLength, key);
// context.compress();
var result = context.Finish();
if (inputData.Length != 213)
{
return (Bytes.Empty, true);
}

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

var blake = new Blake2();
var result = blake.Compress(inputData);

return (result, true);
}
Expand Down
9 changes: 0 additions & 9 deletions src/Nethermind/Nethermind.sln
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nethermind.DataMarketplace.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Runner.Test", "Nethermind.Runner.Test\Nethermind.Runner.Test.csproj", "{47B19E0D-5DED-436D-9BFB-17EF887634D3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cryptography", "Cryptography", "{B5079215-2D69-4345-8B57-0057F3806D32}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blake2Fast", "..\Blake2Fast\src\Blake2Fast\Blake2Fast.csproj", "{28A17F0D-B148-4185-9DE5-74DD5A2589F3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -454,10 +450,6 @@ Global
{47B19E0D-5DED-436D-9BFB-17EF887634D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47B19E0D-5DED-436D-9BFB-17EF887634D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47B19E0D-5DED-436D-9BFB-17EF887634D3}.Release|Any CPU.Build.0 = Release|Any CPU
{28A17F0D-B148-4185-9DE5-74DD5A2589F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28A17F0D-B148-4185-9DE5-74DD5A2589F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28A17F0D-B148-4185-9DE5-74DD5A2589F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28A17F0D-B148-4185-9DE5-74DD5A2589F3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -507,7 +499,6 @@ Global
{6708432B-C547-44B0-ADCB-8396B916B26F} = {568F4A96-2AA2-4B80-A58A-36950E13A242}
{5A0D6198-E28A-4B19-AA61-9F983B6031D3} = {568F4A96-2AA2-4B80-A58A-36950E13A242}
{47B19E0D-5DED-436D-9BFB-17EF887634D3} = {1564814A-27F8-40A3-943E-8E950D5EE17D}
{28A17F0D-B148-4185-9DE5-74DD5A2589F3} = {B5079215-2D69-4345-8B57-0057F3806D32}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {092CA5E3-6180-4ED7-A3CB-9B57FAC2AA85}
Expand Down

0 comments on commit 088dd82

Please sign in to comment.