From f8abefa8c3177f80db4d0e29814f55f1e29af74b Mon Sep 17 00:00:00 2001 From: ivaylo Date: Thu, 27 Jun 2019 13:40:01 +0100 Subject: [PATCH 01/12] Blake2b f compression precompile test vectors --- .../BLAKE2fPrecompileContract.java | 40 ++++++++ .../BLAKE2fPrecompileContractTest.java | 93 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java create mode 100644 ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java new file mode 100644 index 0000000000..3a65bd4e69 --- /dev/null +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.ethereum.mainnet.precompiles; + +import tech.pegasys.pantheon.ethereum.core.Gas; +import tech.pegasys.pantheon.ethereum.mainnet.AbstractPrecompiledContract; +import tech.pegasys.pantheon.ethereum.vm.GasCalculator; +import tech.pegasys.pantheon.ethereum.vm.MessageFrame; +import tech.pegasys.pantheon.util.bytes.BytesValue; + +public class BLAKE2fPrecompileContract extends AbstractPrecompiledContract { + public BLAKE2fPrecompileContract(final GasCalculator gasCalculator) { + super("BLAKE2b", gasCalculator); + } + + @Override + public Gas gasRequirement(final BytesValue input) { + return null; + } + + @Override + public BytesValue compute(final BytesValue input, final MessageFrame messageFrame) { + if (input.size() != 213) { + throw new IllegalArgumentException( + "input length for Blake2 F precompile should be exactly 213 bytes"); + } + + return null; + } +} diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java new file mode 100644 index 0000000000..4b09ab8620 --- /dev/null +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.ethereum.mainnet.precompiles; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import tech.pegasys.pantheon.ethereum.mainnet.ConstantinopleFixGasCalculator; +import tech.pegasys.pantheon.ethereum.vm.MessageFrame; +import tech.pegasys.pantheon.util.bytes.BytesValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class BLAKE2fPrecompileContractTest { + private final BLAKE2fPrecompileContract contract = + new BLAKE2fPrecompileContract(new ConstantinopleFixGasCalculator()); + + public BLAKE2fPrecompileContractTest() {} + + private MessageFrame messageFrame = mock(MessageFrame.class); + + @Parameterized.Parameters + public static Object[][] parameters() { + return new Object[][] { + { + "6a09e667f2bd8948bb67ae8484caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c", + "63b3654623b9ca0757a1474a529433186257ba9deee206e9572365bbce31cea6d3e6d6901c014e1be3c5854bdbbef6de8ccfe917f2bb6643c72c02911aecadad" + }, + { + "6a09e627f3bcc909bb67ae8484caa73b3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179278400340e6b05c5752592c52c4f121292eafc51cc01a997b4aed13409298fad0d99ccc8f76453d9b3661e5c4d325d7751147db17489046d1682d50eefa4a1da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "d618d21e4ccdda64b147dcca5687459fbf24145ea9091c33416e45229d0972282ea8b80ff6ca078d180efb0a36b08042c068f0ae9ce69f4a7098c8215ee61773" + }, + { + "2b536b65aae1d6731671813c2841a6146b8927a455d1f805ed650cdc3d38b03decbeb55e397687eb59650053fa515f5c817b4cedb190759a7f24f6ba1fc97300808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000001000000000000000000010000000c", + "913105d263890354d07b7868b36d287c2391f54f2d43099882adae97a0345a253672600754921d844010f12d6e9455d383bb247343b1372dbb58369fbc9b2bdf" + }, + { + "6a09e667f2bd8948bb67aea184caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c", + "138f26ca8e8b5088415879a35a2c2d7dd95e0929ba0bfe9c8b0ce25db7bce94cdbf1e30c89a2c099ea0da3e8e9ff135368f769a0eaae54da630d9b2ce7272703" + }, + { + "456d45a3841d8a19f16ed318dc09cb4a225593e559ecd4e1c57032c0316e2f08239531a59702945cb52b3fba2f3aa61e55e133554d2f4fd4fc252af7327e80e3808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000001000000000000000000010000000c", + "164a65d708f5ee940fffc9ac7d1ca30083dbe67dfc6623e36b7d5ffd9aa8edca89e32143550f1d81b3297a7dba3ed6097d246f9e82ba2a93d5b908dbaef1384c" + }, + { + "6a09e627f3bcc901bb67aecc84caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179d817fa064689494877e43d757ab1285b4b2a1899cde490442a90071c439a224e7070d3be04b6370df09c77018cf9d989afe1e208a9a35ce951330f210d56364a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "089c3ff02e0c9e934a01d4631722ffbbb1f5d4cc508cdb5510ebbbab022e58b50e585dcd7dbfb1c7a9a01d51a9523d54ec60d2a1a96c1f6690b407054e4d00e3" + }, + { + "6a09e627f3bcc91fbb67aed284caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179a11a4843ebc5ebc5e402d0f0ecf997957a5a01b2bfa6715e67130c95562c6f4d84c64d4bd0fb03698fbb0103aa31c4c1daeb4d727b46074d23756f961141685a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "d38f3c045427b0ff87160b670ad983c7611cfe54558be69c7a8890fd94186323e43ce133de436abdea320274298acd2eef70be64c3277a60a902da3fd06af78e" + }, + { + "6a09e627f3bcc92dbb67aee084caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217928cdecc6e7e3f0e93591c75513aa862e44adae0a40ce7b8e6c72ea4b47b7c88b832a34cca4d8dbc6f112373f1e82e1d26a58498cfa1ed290e872149667cb2b9100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "f1639feeaad03b7ea99e85889b6f7407a26a4095687dbc027d3256ad0c481f1661564b3628ba5b0a8117ea73be040036921ce3b64849a70db05bbaec2ba82c15" + }, + { + "6a09e627f3bcc93bbb67aef684caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e21795f88c38e13dd036e0b6907218d2236f47bfc9ad7ad4478e69c11a4dd69109a5045de7154839b33f604c0f5907ab5e9a916abd7bedaba1dd6635f2850f42038b500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "4c0fa0b3fa95a5ef7eb0ee4c662f9aef6b96582d211917c640cba8d7a7009fcaccfbb7ba7664cf24b2e2f5c3e7d45fee8b459c6581a25a97af1d6e71fd67a709" + }, + { + "6a09e627f3bcc948bb67ae0484caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e21790bc009514bdad0c0331a29252f923da6137d6fd4ba14cb0e9c7cbb0bb1a666d5597d4d8c44612f5a2b12e8e39fa134d96b1d53fa08e48a1ad915bc44040c22ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", + "272539bb30107dea7bf9ef9e3ed75db2c8a0ddb9f37c39ea06c012ed70c8a917e00040c6684905cc1b627d7d9b4e87daa03e2412698679068fe944138ab3c796" + }, + }; + } + + @Parameterized.Parameter public String input; + + @Parameterized.Parameter(1) + public String expectedResult; + + @Test + public void shouldRecoverAddress() { + final BytesValue input = BytesValue.fromHexString(this.input); + final BytesValue expected = + expectedResult == null ? BytesValue.EMPTY : BytesValue.fromHexString(expectedResult); + assertThat(contract.compute(input, messageFrame)).isEqualTo(expected); + } +} From 933ab48ee9419896418b79518be2f01b9aafe63c Mon Sep 17 00:00:00 2001 From: Ivaylo Kirilov Date: Sun, 30 Jun 2019 14:32:59 +0100 Subject: [PATCH 02/12] Blake2b f precompile raw implementation --- .../BLAKE2fPrecompileContract.java | 240 +++++++++++++++++- 1 file changed, 239 insertions(+), 1 deletion(-) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java index 3a65bd4e69..08b713f52f 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java @@ -18,6 +18,12 @@ import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.util.bytes.BytesValue; +import java.util.Arrays; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import org.bouncycastle.util.Pack; + public class BLAKE2fPrecompileContract extends AbstractPrecompiledContract { public BLAKE2fPrecompileContract(final GasCalculator gasCalculator) { super("BLAKE2b", gasCalculator); @@ -30,11 +36,243 @@ public Gas gasRequirement(final BytesValue input) { @Override public BytesValue compute(final BytesValue input, final MessageFrame messageFrame) { + + byte[] in = input.extractArray(); + if (input.size() != 213) { throw new IllegalArgumentException( "input length for Blake2 F precompile should be exactly 213 bytes"); } + long[] h = new long[8]; - return null; + h[0] = Longs.fromByteArray(Arrays.copyOfRange(in, 0, 8)); + h[1] = Longs.fromByteArray(Arrays.copyOfRange(in, 8, 16)); + h[2] = Longs.fromByteArray(Arrays.copyOfRange(in, 16, 24)); + h[3] = Longs.fromByteArray(Arrays.copyOfRange(in, 24, 32)); + h[4] = Longs.fromByteArray(Arrays.copyOfRange(in, 32, 40)); + h[5] = Longs.fromByteArray(Arrays.copyOfRange(in, 40, 48)); + h[6] = Longs.fromByteArray(Arrays.copyOfRange(in, 48, 56)); + h[7] = Longs.fromByteArray(Arrays.copyOfRange(in, 56, 64)); + + byte[] m = Arrays.copyOfRange(in, 64, 192); + + long[] t = new long[2]; + t[0] = Longs.fromByteArray(Arrays.copyOfRange(in, 192, 200)); + t[1] = Longs.fromByteArray(Arrays.copyOfRange(in, 200, 208)); + + boolean f = in[208] != 0x00000000; + + int rounds = Ints.fromByteArray(Arrays.copyOfRange(in, 209, 213)); + + byte[] output = blake2f(h, m, t, f, rounds); + + return BytesValue.wrap(output); + } + + private int blockSize = 128; + + private static final long[] iv = { + 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL, + 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL, + 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L + }; + + private static final byte[][] precomputed = { + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0} + }; + + private byte[] blake2f( + final long[] h, final byte[] mb, final long[] t, final boolean f, final int rounds) { + + long[] m = new long[16]; + + long t0 = t[0]; + long t1 = t[1]; + + for (int i = 0; i < mb.length; ++i) { + t0 += blockSize; + if (t0 < blockSize) { + t1++; + } + + long v0 = h[0]; + long v1 = h[1]; + long v2 = h[2]; + long v3 = h[3]; + long v4 = h[4]; + long v5 = h[5]; + long v6 = h[6]; + long v7 = h[7]; + long v8 = iv[0]; + long v9 = iv[1]; + long v10 = iv[2]; + long v11 = iv[3]; + long v12 = iv[4]; + long v13 = iv[5]; + long v14 = iv[6]; + long v15 = iv[7]; + v12 ^= t0; + v13 ^= t1; + + if (f) { + v14 ^= 0xffffffffffffffffL; + } + + for (int j = 0; j < m.length; ++j) { + m[j] = Pack.littleEndianToLong(Arrays.copyOfRange(mb, i, i + 8), 0); + i += 8; + } + + for (int j = 0; j < rounds; ++j) { + byte[] s = precomputed[j % 10]; + + v0 += m[s[0]]; + v0 += v4; + v12 ^= v0; + v12 = Long.rotateLeft(v12, -32); + v8 += v12; + v4 ^= v8; + v4 = Long.rotateLeft(v4, -24); + v1 += m[s[1]]; + v1 += v5; + v13 ^= v1; + v13 = Long.rotateLeft(v13, -32); + v9 += v13; + v5 ^= v9; + v5 = Long.rotateLeft(v5, -24); + v2 += m[s[2]]; + v2 += v6; + v14 ^= v2; + v14 = Long.rotateLeft(v14, -32); + v10 += v14; + v6 ^= v10; + v6 = Long.rotateLeft(v6, -24); + v3 += m[s[3]]; + v3 += v7; + v15 ^= v3; + v15 = Long.rotateLeft(v15, -32); + v11 += v15; + v7 ^= v11; + v7 = Long.rotateLeft(v7, -24); + + v0 += m[s[4]]; + v0 += v4; + v12 ^= v0; + v12 = Long.rotateLeft(v12, -16); + v8 += v12; + v4 ^= v8; + v4 = Long.rotateLeft(v4, -63); + v1 += m[s[5]]; + v1 += v5; + v13 ^= v1; + v13 = Long.rotateLeft(v13, -16); + v9 += v13; + v5 ^= v9; + v5 = Long.rotateLeft(v5, -63); + v2 += m[s[6]]; + v2 += v6; + v14 ^= v2; + v14 = Long.rotateLeft(v14, -16); + v10 += v14; + v6 ^= v10; + v6 = Long.rotateLeft(v6, -63); + v3 += m[s[7]]; + v3 += v7; + v15 ^= v3; + v15 = Long.rotateLeft(v15, -16); + v11 += v15; + v7 ^= v11; + v7 = Long.rotateLeft(v7, -63); + + v0 += m[s[8]]; + v0 += v5; + v15 ^= v0; + v15 = Long.rotateLeft(v15, -32); + v10 += v15; + v5 ^= v10; + v5 = Long.rotateLeft(v5, -24); + v1 += m[s[9]]; + v1 += v6; + v12 ^= v1; + v12 = Long.rotateLeft(v12, -32); + v11 += v12; + v6 ^= v11; + v6 = Long.rotateLeft(v6, -24); + v2 += m[s[10]]; + v2 += v7; + v13 ^= v2; + v13 = Long.rotateLeft(v13, -32); + v8 += v13; + v7 ^= v8; + v7 = Long.rotateLeft(v7, -24); + v3 += m[s[11]]; + v3 += v4; + v14 ^= v3; + v14 = Long.rotateLeft(v14, -32); + v9 += v14; + v4 ^= v9; + v4 = Long.rotateLeft(v4, -24); + + v0 += m[s[12]]; + v0 += v5; + v15 ^= v0; + v15 = Long.rotateLeft(v15, -16); + v10 += v15; + v5 ^= v10; + v5 = Long.rotateLeft(v5, -63); + v1 += m[s[13]]; + v1 += v6; + v12 ^= v1; + v12 = Long.rotateLeft(v12, -16); + v11 += v12; + v6 ^= v11; + v6 = Long.rotateLeft(v6, -63); + v2 += m[s[14]]; + v2 += v7; + v13 ^= v2; + v13 = Long.rotateLeft(v13, -16); + v8 += v13; + v7 ^= v8; + v7 = Long.rotateLeft(v7, -63); + v3 += m[s[15]]; + v3 += v4; + v14 ^= v3; + v14 = Long.rotateLeft(v14, -16); + v9 += v14; + v4 ^= v9; + v4 = Long.rotateLeft(v4, -63); + } + + h[0] ^= v0 ^ v8; + h[1] ^= v1 ^ v9; + h[2] ^= v2 ^ v10; + h[3] ^= v3 ^ v11; + h[4] ^= v4 ^ v12; + h[5] ^= v5 ^ v13; + h[6] ^= v6 ^ v14; + h[7] ^= v7 ^ v15; + } + + byte[] output = new byte[64]; + + System.arraycopy(Longs.toByteArray(h[0]), 0, output, 0, 8); + System.arraycopy(Longs.toByteArray(h[1]), 0, output, 8, 8); + System.arraycopy(Longs.toByteArray(h[2]), 0, output, 16, 8); + System.arraycopy(Longs.toByteArray(h[3]), 0, output, 24, 8); + System.arraycopy(Longs.toByteArray(h[4]), 0, output, 32, 8); + System.arraycopy(Longs.toByteArray(h[5]), 0, output, 40, 8); + System.arraycopy(Longs.toByteArray(h[6]), 0, output, 48, 8); + System.arraycopy(Longs.toByteArray(h[7]), 0, output, 56, 8); + + return output; } } From a46832a927af67b01c271e77c2ad5e05836f20ae Mon Sep 17 00:00:00 2001 From: Ivaylo Kirilov Date: Tue, 2 Jul 2019 22:42:08 +0100 Subject: [PATCH 03/12] Blake2b f precompile refined implementation --- .../pantheon/crypto/Blake2fMessageDigest.java | 248 +++++++++++++++++ .../tech/pegasys/pantheon/crypto/Hash.java | 21 +- ...Factory.java => MessageDigestFactory.java} | 10 +- .../pantheon/crypto/PantheonProvider.java | 35 +++ .../mainnet/DirectAcyclicGraphSeed.java | 4 +- .../BLAKE2fPrecompileContract.java | 263 ++---------------- .../BLAKE2fPrecompileContractTest.java | 82 ++++-- 7 files changed, 385 insertions(+), 278 deletions(-) create mode 100644 crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java rename crypto/src/main/java/tech/pegasys/pantheon/crypto/{BouncyCastleMessageDigestFactory.java => MessageDigestFactory.java} (79%) create mode 100644 crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java new file mode 100644 index 0000000000..fcacfb6932 --- /dev/null +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java @@ -0,0 +1,248 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.crypto; + +import static java.util.Arrays.copyOfRange; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import com.google.common.primitives.UnsignedInts; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.jcajce.provider.digest.BCMessageDigest; +import org.bouncycastle.util.Arrays; + +public class Blake2fMessageDigest extends BCMessageDigest { + + public Blake2fMessageDigest() { + super(new Blake2fDigest()); + } + + /** + * Implementation of the `F` compression function of the Blake2b cryptographic hash function. + * + *

Adapted from - https://github.com/keep-network/blake2b/blob/master/compression/f.go + * + *

Optimized for 64-bit platforms + */ + public static class Blake2fDigest implements Digest { + + public static final int MESSAGE_LENGTH_BYTES = 213; + + private static final int BLOCK_LENGTH_BYTES = 128; + + private static final long[] IV = { + 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL, + 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL, + 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L + }; + + private static final byte[][] PRECOMPUTED = { + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0} + }; + + private static final int DIGEST_LENGTH = 64; + + // buffer which holds serialized input for this compression function + // [ 4 bytes for rounds ][ 64 bytes for h ][ 128 bytes for m ] + // [ 8 bytes for t_0 ][ 8 bytes for t_1 ][ 1 byte for f ] + private byte[] buffer; + + private int bufferPos; + + // deserialized inputs for f compression + private final long[] h; + private final long[] m; + private final long[] t; + private boolean f; + private int rounds; + + private final long[] v; + + Blake2fDigest() { + buffer = new byte[MESSAGE_LENGTH_BYTES]; + bufferPos = 0; + + h = new long[8]; + m = new long[16]; + t = new long[2]; + f = false; + rounds = 12; + + v = new long[16]; + } + + @Override + public String getAlgorithmName() { + return "BLAKE2f"; + } + + @Override + public int getDigestSize() { + return DIGEST_LENGTH; + } + + /** + * update the message digest with a single byte. + * + * @param in the input byte to be entered. + */ + @Override + public void update(final byte in) { + + if (MESSAGE_LENGTH_BYTES - bufferPos == 0) { // full buffer + throw new IllegalArgumentException(); + } else { + buffer[bufferPos] = in; + bufferPos++; + if (bufferPos == BLOCK_LENGTH_BYTES) { + initialize(); + } + } + } + + /** + * update the message digest with a block of bytes. + * + * @param in the byte array containing the data. + * @param offset the offset into the byte array where the data starts. + * @param len the length of the data. + */ + @Override + public void update(final byte[] in, final int offset, final int len) { + if (in == null || len == 0) { + return; + } + + if (in.length != MESSAGE_LENGTH_BYTES || len != 213 || offset != 0 || bufferPos != 0) { + throw new IllegalArgumentException(); + } + + System.arraycopy(in, offset, buffer, bufferPos, len); + + initialize(); + } + + /** + * close the digest, producing the final digest value. The doFinal call leaves the digest reset. + * + * @param out the array the digest is to be copied into. + * @param offset the offset into the out array the digest is to start at. + */ + @Override + public int doFinal(final byte[] out, final int offset) { + compress(); + + for (int i = 0; i < h.length; i++) { + System.arraycopy(Longs.toByteArray(h[i]), 0, out, i * 8, 8); + } + + reset(); + + return 0; + } + + private void initialize() { + rounds = Ints.fromByteArray(copyOfRange(buffer, 0, 4)); + + for (int i = 0; i < h.length; i++) { + final int offset = 4 + i * 8; + h[i] = Longs.fromByteArray(copyOfRange(buffer, offset, offset + 8)); + } + + for (int i = 0; i < 16; i++) { + final int offset = 68 + i * 8; + m[i] = Longs.fromByteArray(copyOfRange(buffer, offset, offset + 8)); + } + + t[0] = Longs.fromByteArray(copyOfRange(buffer, 196, 204)); + t[1] = Longs.fromByteArray(copyOfRange(buffer, 204, 212)); + + f = buffer[212] != 0; + } + + /** + * F is a compression function for BLAKE2b. It takes as an argument the state vector `h`, + * message block vector `m`, offset counter `t`, final block indicator flag `f`, and number of + * rounds `rounds`. The state vector provided as the first parameter is modified by the + * function. + */ + private void compress() { + + long t0 = t[0]; + long t1 = t[1]; + + System.arraycopy(h, 0, v, 0, 8); + System.arraycopy(IV, 0, v, 8, 8); + + v[12] ^= t0; + v[13] ^= t1; + + if (f) { + v[14] ^= 0xffffffffffffffffL; + } + + for (int j = 0; UnsignedInts.compare(j, rounds) < 0; ++j) { + byte[] s = PRECOMPUTED[j % 10]; + + mix(m[s[0]], m[s[4]], 0, 4, 8, 12); + mix(m[s[1]], m[s[5]], 1, 5, 9, 13); + mix(m[s[2]], m[s[6]], 2, 6, 10, 14); + mix(m[s[3]], m[s[7]], 3, 7, 11, 15); + mix(m[s[8]], m[s[12]], 0, 5, 10, 15); + mix(m[s[9]], m[s[13]], 1, 6, 11, 12); + mix(m[s[10]], m[s[14]], 2, 7, 8, 13); + mix(m[s[11]], m[s[15]], 3, 4, 9, 14); + } + + // update h: + for (int offset = 0; offset < h.length; offset++) { + h[offset] ^= v[offset] ^ v[offset + 8]; + } + } + + private void mix( + final long a, final long b, final int i, final int j, final int k, final int l) { + v[i] += a + v[j]; + v[l] = Long.rotateLeft(v[l] ^ v[i], -32); + v[k] += v[l]; + v[j] = Long.rotateLeft(v[j] ^ v[k], -24); + + v[i] += b + v[j]; + v[l] = Long.rotateLeft(v[l] ^ v[i], -16); + v[k] += v[l]; + v[j] = Long.rotateLeft(v[j] ^ v[k], -63); + } + + /** Reset the digest back to it's initial state. */ + @Override + public void reset() { + bufferPos = 0; + Arrays.fill(buffer, (byte) 0); + Arrays.fill(h, 0); + Arrays.fill(m, (byte) 0); + Arrays.fill(t, 0); + f = false; + rounds = 12; + Arrays.fill(v, 0); + } + } +} diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java index 182aaa1d41..906649a51b 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java @@ -17,22 +17,16 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.Security; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; /** Various utilities for providing hashes (digests) of arbitrary data. */ public abstract class Hash { private Hash() {} - static { - Security.addProvider(new BouncyCastleProvider()); - } - public static final String KECCAK256_ALG = "KECCAK-256"; private static final String SHA256_ALG = "SHA-256"; private static final String RIPEMD160 = "RIPEMD160"; + private static final String BLAKE2F_ALG = "BLAKE2f"; /** * Helper method to generate a digest using the provided algorithm. @@ -42,9 +36,8 @@ private Hash() {} * @return A digest. */ private static byte[] digestUsingAlgorithm(final BytesValue input, final String alg) { - final MessageDigest digest; try { - digest = BouncyCastleMessageDigestFactory.create(alg); + final MessageDigest digest = MessageDigestFactory.create(alg); input.update(digest); return digest.digest(); } catch (final NoSuchAlgorithmException e) { @@ -81,4 +74,14 @@ public static Bytes32 keccak256(final BytesValue input) { public static BytesValue ripemd160(final BytesValue input) { return BytesValue.wrap(digestUsingAlgorithm(input, RIPEMD160)); } + + /** + * Digest using Blake2f compression function. + * + * @param input The input bytes to produce the digest for. + * @return A digest. + */ + public static BytesValue blake2f(final BytesValue input) { + return BytesValue.wrap(digestUsingAlgorithm(input, BLAKE2F_ALG)); + } } diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/BouncyCastleMessageDigestFactory.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/MessageDigestFactory.java similarity index 79% rename from crypto/src/main/java/tech/pegasys/pantheon/crypto/BouncyCastleMessageDigestFactory.java rename to crypto/src/main/java/tech/pegasys/pantheon/crypto/MessageDigestFactory.java index ad14d56bfd..28efadec66 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/BouncyCastleMessageDigestFactory.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/MessageDigestFactory.java @@ -14,15 +14,19 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; -public class BouncyCastleMessageDigestFactory { +public class MessageDigestFactory { - private static final BouncyCastleProvider securityProvider = new BouncyCastleProvider(); + static { + Security.addProvider(new PantheonProvider()); + Security.addProvider(new BouncyCastleProvider()); + } @SuppressWarnings("DoNotInvokeMessageDigestDirectly") public static MessageDigest create(final String algorithm) throws NoSuchAlgorithmException { - return MessageDigest.getInstance(algorithm, securityProvider); + return MessageDigest.getInstance(algorithm); } } diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java new file mode 100644 index 0000000000..16b2bfa97b --- /dev/null +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.crypto; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Provider; + +public final class PantheonProvider extends Provider { + + private static final String info = "Pantheon Security Provider v1.0"; + + public static final String PROVIDER_NAME = "Pantheon"; + + @SuppressWarnings("unchecked") + public PantheonProvider() { + super(PROVIDER_NAME, 1.0, info); + AccessController.doPrivileged( + (PrivilegedAction) + () -> { + put("MessageDigest.Blake2f", "tech.pegasys.pantheon.crypto.Blake2fMessageDigest"); + return null; + }); + } +} diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/DirectAcyclicGraphSeed.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/DirectAcyclicGraphSeed.java index f205fed40f..959816e43a 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/DirectAcyclicGraphSeed.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/DirectAcyclicGraphSeed.java @@ -14,8 +14,8 @@ import static tech.pegasys.pantheon.ethereum.mainnet.EthHash.EPOCH_LENGTH; -import tech.pegasys.pantheon.crypto.BouncyCastleMessageDigestFactory; import tech.pegasys.pantheon.crypto.Hash; +import tech.pegasys.pantheon.crypto.MessageDigestFactory; import java.security.DigestException; import java.security.MessageDigest; @@ -27,7 +27,7 @@ public class DirectAcyclicGraphSeed { ThreadLocal.withInitial( () -> { try { - return BouncyCastleMessageDigestFactory.create(Hash.KECCAK256_ALG); + return MessageDigestFactory.create(Hash.KECCAK256_ALG); } catch (final NoSuchAlgorithmException ex) { throw new IllegalStateException(ex); } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java index 08b713f52f..fe6cf53d94 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java @@ -12,267 +12,42 @@ */ package tech.pegasys.pantheon.ethereum.mainnet.precompiles; +import static java.util.Arrays.copyOfRange; +import static tech.pegasys.pantheon.crypto.Blake2fMessageDigest.Blake2fDigest.MESSAGE_LENGTH_BYTES; + +import tech.pegasys.pantheon.crypto.Hash; import tech.pegasys.pantheon.ethereum.core.Gas; import tech.pegasys.pantheon.ethereum.mainnet.AbstractPrecompiledContract; import tech.pegasys.pantheon.ethereum.vm.GasCalculator; import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.util.bytes.BytesValue; -import java.util.Arrays; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import org.bouncycastle.util.Pack; +import java.math.BigInteger; +// https://github.com/keep-network/go-ethereum/pull/4 public class BLAKE2fPrecompileContract extends AbstractPrecompiledContract { public BLAKE2fPrecompileContract(final GasCalculator gasCalculator) { - super("BLAKE2b", gasCalculator); + super("BLAKE2f", gasCalculator); } @Override public Gas gasRequirement(final BytesValue input) { - return null; - } - - @Override - public BytesValue compute(final BytesValue input, final MessageFrame messageFrame) { - - byte[] in = input.extractArray(); - - if (input.size() != 213) { - throw new IllegalArgumentException( - "input length for Blake2 F precompile should be exactly 213 bytes"); + if (input.size() != MESSAGE_LENGTH_BYTES) { + // Input is malformed, we can't read the number of rounds. + // Precompile can't be executed so we set its price to 0. + return Gas.ZERO; } - long[] h = new long[8]; - - h[0] = Longs.fromByteArray(Arrays.copyOfRange(in, 0, 8)); - h[1] = Longs.fromByteArray(Arrays.copyOfRange(in, 8, 16)); - h[2] = Longs.fromByteArray(Arrays.copyOfRange(in, 16, 24)); - h[3] = Longs.fromByteArray(Arrays.copyOfRange(in, 24, 32)); - h[4] = Longs.fromByteArray(Arrays.copyOfRange(in, 32, 40)); - h[5] = Longs.fromByteArray(Arrays.copyOfRange(in, 40, 48)); - h[6] = Longs.fromByteArray(Arrays.copyOfRange(in, 48, 56)); - h[7] = Longs.fromByteArray(Arrays.copyOfRange(in, 56, 64)); - byte[] m = Arrays.copyOfRange(in, 64, 192); - - long[] t = new long[2]; - t[0] = Longs.fromByteArray(Arrays.copyOfRange(in, 192, 200)); - t[1] = Longs.fromByteArray(Arrays.copyOfRange(in, 200, 208)); - - boolean f = in[208] != 0x00000000; - - int rounds = Ints.fromByteArray(Arrays.copyOfRange(in, 209, 213)); - - byte[] output = blake2f(h, m, t, f, rounds); - - return BytesValue.wrap(output); + byte[] roundsBytes = copyOfRange(input.extractArray(), 0, 4); + BigInteger rounds = new BigInteger(1, roundsBytes); + return Gas.of(rounds); } - private int blockSize = 128; - - private static final long[] iv = { - 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL, - 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL, - 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L - }; - - private static final byte[][] precomputed = { - {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, - {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, - {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, - {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, - {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, - {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, - {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, - {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, - {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, - {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0} - }; - - private byte[] blake2f( - final long[] h, final byte[] mb, final long[] t, final boolean f, final int rounds) { - - long[] m = new long[16]; - - long t0 = t[0]; - long t1 = t[1]; - - for (int i = 0; i < mb.length; ++i) { - t0 += blockSize; - if (t0 < blockSize) { - t1++; - } - - long v0 = h[0]; - long v1 = h[1]; - long v2 = h[2]; - long v3 = h[3]; - long v4 = h[4]; - long v5 = h[5]; - long v6 = h[6]; - long v7 = h[7]; - long v8 = iv[0]; - long v9 = iv[1]; - long v10 = iv[2]; - long v11 = iv[3]; - long v12 = iv[4]; - long v13 = iv[5]; - long v14 = iv[6]; - long v15 = iv[7]; - v12 ^= t0; - v13 ^= t1; - - if (f) { - v14 ^= 0xffffffffffffffffL; - } - - for (int j = 0; j < m.length; ++j) { - m[j] = Pack.littleEndianToLong(Arrays.copyOfRange(mb, i, i + 8), 0); - i += 8; - } - - for (int j = 0; j < rounds; ++j) { - byte[] s = precomputed[j % 10]; - - v0 += m[s[0]]; - v0 += v4; - v12 ^= v0; - v12 = Long.rotateLeft(v12, -32); - v8 += v12; - v4 ^= v8; - v4 = Long.rotateLeft(v4, -24); - v1 += m[s[1]]; - v1 += v5; - v13 ^= v1; - v13 = Long.rotateLeft(v13, -32); - v9 += v13; - v5 ^= v9; - v5 = Long.rotateLeft(v5, -24); - v2 += m[s[2]]; - v2 += v6; - v14 ^= v2; - v14 = Long.rotateLeft(v14, -32); - v10 += v14; - v6 ^= v10; - v6 = Long.rotateLeft(v6, -24); - v3 += m[s[3]]; - v3 += v7; - v15 ^= v3; - v15 = Long.rotateLeft(v15, -32); - v11 += v15; - v7 ^= v11; - v7 = Long.rotateLeft(v7, -24); - - v0 += m[s[4]]; - v0 += v4; - v12 ^= v0; - v12 = Long.rotateLeft(v12, -16); - v8 += v12; - v4 ^= v8; - v4 = Long.rotateLeft(v4, -63); - v1 += m[s[5]]; - v1 += v5; - v13 ^= v1; - v13 = Long.rotateLeft(v13, -16); - v9 += v13; - v5 ^= v9; - v5 = Long.rotateLeft(v5, -63); - v2 += m[s[6]]; - v2 += v6; - v14 ^= v2; - v14 = Long.rotateLeft(v14, -16); - v10 += v14; - v6 ^= v10; - v6 = Long.rotateLeft(v6, -63); - v3 += m[s[7]]; - v3 += v7; - v15 ^= v3; - v15 = Long.rotateLeft(v15, -16); - v11 += v15; - v7 ^= v11; - v7 = Long.rotateLeft(v7, -63); - - v0 += m[s[8]]; - v0 += v5; - v15 ^= v0; - v15 = Long.rotateLeft(v15, -32); - v10 += v15; - v5 ^= v10; - v5 = Long.rotateLeft(v5, -24); - v1 += m[s[9]]; - v1 += v6; - v12 ^= v1; - v12 = Long.rotateLeft(v12, -32); - v11 += v12; - v6 ^= v11; - v6 = Long.rotateLeft(v6, -24); - v2 += m[s[10]]; - v2 += v7; - v13 ^= v2; - v13 = Long.rotateLeft(v13, -32); - v8 += v13; - v7 ^= v8; - v7 = Long.rotateLeft(v7, -24); - v3 += m[s[11]]; - v3 += v4; - v14 ^= v3; - v14 = Long.rotateLeft(v14, -32); - v9 += v14; - v4 ^= v9; - v4 = Long.rotateLeft(v4, -24); - - v0 += m[s[12]]; - v0 += v5; - v15 ^= v0; - v15 = Long.rotateLeft(v15, -16); - v10 += v15; - v5 ^= v10; - v5 = Long.rotateLeft(v5, -63); - v1 += m[s[13]]; - v1 += v6; - v12 ^= v1; - v12 = Long.rotateLeft(v12, -16); - v11 += v12; - v6 ^= v11; - v6 = Long.rotateLeft(v6, -63); - v2 += m[s[14]]; - v2 += v7; - v13 ^= v2; - v13 = Long.rotateLeft(v13, -16); - v8 += v13; - v7 ^= v8; - v7 = Long.rotateLeft(v7, -63); - v3 += m[s[15]]; - v3 += v4; - v14 ^= v3; - v14 = Long.rotateLeft(v14, -16); - v9 += v14; - v4 ^= v9; - v4 = Long.rotateLeft(v4, -63); - } - - h[0] ^= v0 ^ v8; - h[1] ^= v1 ^ v9; - h[2] ^= v2 ^ v10; - h[3] ^= v3 ^ v11; - h[4] ^= v4 ^ v12; - h[5] ^= v5 ^ v13; - h[6] ^= v6 ^ v14; - h[7] ^= v7 ^ v15; + @Override + public BytesValue compute(final BytesValue input, final MessageFrame messageFrame) { + if (input.size() != MESSAGE_LENGTH_BYTES) { + return BytesValue.EMPTY; } - - byte[] output = new byte[64]; - - System.arraycopy(Longs.toByteArray(h[0]), 0, output, 0, 8); - System.arraycopy(Longs.toByteArray(h[1]), 0, output, 8, 8); - System.arraycopy(Longs.toByteArray(h[2]), 0, output, 16, 8); - System.arraycopy(Longs.toByteArray(h[3]), 0, output, 24, 8); - System.arraycopy(Longs.toByteArray(h[4]), 0, output, 32, 8); - System.arraycopy(Longs.toByteArray(h[5]), 0, output, 40, 8); - System.arraycopy(Longs.toByteArray(h[6]), 0, output, 48, 8); - System.arraycopy(Longs.toByteArray(h[7]), 0, output, 56, 8); - - return output; + return Hash.blake2f(input); } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java index 4b09ab8620..583c64824b 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java @@ -32,48 +32,90 @@ public BLAKE2fPrecompileContractTest() {} private MessageFrame messageFrame = mock(MessageFrame.class); + // Test vectors from + // https://github.com/keep-network/go-ethereum/blob/f-precompile/core/vm/contracts_test.go#L350 @Parameterized.Parameters public static Object[][] parameters() { return new Object[][] { { - "6a09e667f2bd8948bb67ae8484caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c", - "63b3654623b9ca0757a1474a529433186257ba9deee206e9572365bbce31cea6d3e6d6901c014e1be3c5854bdbbef6de8ccfe917f2bb6643c72c02911aecadad" + "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001", + "62305ad4d48dade8269ef60a1bcb8b7bef6e479e643b5ac1f8017e6422ce89fb62d09ecaa81d095e855540dcbc07bd0feb3d4f5e5e50541260ed930f027cfd8d" }, { - "6a09e627f3bcc909bb67ae8484caa73b3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179278400340e6b05c5752592c52c4f121292eafc51cc01a997b4aed13409298fad0d99ccc8f76453d9b3661e5c4d325d7751147db17489046d1682d50eefa4a1da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "d618d21e4ccdda64b147dcca5687459fbf24145ea9091c33416e45229d0972282ea8b80ff6ca078d180efb0a36b08042c068f0ae9ce69f4a7098c8215ee61773" + "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", + "74aaa2510b5c66ea8a708bdea257192d9c9bc48d53c7f7e87a51bffd24d5d9e6ea0b4b2070fb3a3d211208e3f7bcb1a24dec971cecbb62faf1cd142745f8f4ee" }, { - "2b536b65aae1d6731671813c2841a6146b8927a455d1f805ed650cdc3d38b03decbeb55e397687eb59650053fa515f5c817b4cedb190759a7f24f6ba1fc97300808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000001000000000000000000010000000c", - "913105d263890354d07b7868b36d287c2391f54f2d43099882adae97a0345a253672600754921d844010f12d6e9455d383bb247343b1372dbb58369fbc9b2bdf" + "000000018736a85f01b0a31dd67dcbe79b220b9b9d93e5897bb8975766b47652443b1927b715da2203c2ca1d0d22b820a965ad9cf23bb0bd57a16fd56ed7a9c5dc67af0587868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", + "f0eea67995b5e71bd02c40edf19aadd131475949119813de4ea3072f8865bb1978037a72d2bb446d3deead8310b5fba548088c5a99689c51c6632f660a2a2a45" }, { - "6a09e667f2bd8948bb67aea184caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c", - "138f26ca8e8b5088415879a35a2c2d7dd95e0929ba0bfe9c8b0ce25db7bce94cdbf1e30c89a2c099ea0da3e8e9ff135368f769a0eaae54da630d9b2ce7272703" + "000000056a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001", + "f863686fe221e37fee57b5eb7a41266fe765d26d337fa9fe329af1ae378bae9bd61f06dd8ccceec229349cd341b19df399488a9ab05aec7ba3442268fd039ba4" }, { - "456d45a3841d8a19f16ed318dc09cb4a225593e559ecd4e1c57032c0316e2f08239531a59702945cb52b3fba2f3aa61e55e133554d2f4fd4fc252af7327e80e3808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000001000000000000000000010000000c", - "164a65d708f5ee940fffc9ac7d1ca30083dbe67dfc6623e36b7d5ffd9aa8edca89e32143550f1d81b3297a7dba3ed6097d246f9e82ba2a93d5b908dbaef1384c" + "000000056a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", + "3a6c5ac8d6606290708c08540cb5c425f72014c8b50c280b817a6ffb1b8b405f2001caca125182b562b8a407a249ca6e9755b62e4324caaf4578a660d8dd4876" }, { - "6a09e627f3bcc901bb67aecc84caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179d817fa064689494877e43d757ab1285b4b2a1899cde490442a90071c439a224e7070d3be04b6370df09c77018cf9d989afe1e208a9a35ce951330f210d56364a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "089c3ff02e0c9e934a01d4631722ffbbb1f5d4cc508cdb5510ebbbab022e58b50e585dcd7dbfb1c7a9a01d51a9523d54ec60d2a1a96c1f6690b407054e4d00e3" + "000000052a3c65f1dbd604cbc713d5ce8c0e5e6c3b22c76bdf73716e55525ba247a930f9e240763f1c01d22c514aa14d3f18722715405fbe7ecde36c77e565078839b7c987868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", + "7e7acc657731d1dfb4229114f545597b7fa4b3140217b470e86a8c27ab0b1ce8c103e219a3a2f77fa495b8c706b8016facf32b1cb5d83f2ae8d3248892d5d74c" }, { - "6a09e627f3bcc91fbb67aed284caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179a11a4843ebc5ebc5e402d0f0ecf997957a5a01b2bfa6715e67130c95562c6f4d84c64d4bd0fb03698fbb0103aa31c4c1daeb4d727b46074d23756f961141685a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "d38f3c045427b0ff87160b670ad983c7611cfe54558be69c7a8890fd94186323e43ce133de436abdea320274298acd2eef70be64c3277a60a902da3fd06af78e" + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde00000000030201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000001", + "7180f3083d5aaabe0569cd951d62cf431dc9f9ff9eb4d014a5ef0eec4192b524ba8b0407d49601f648b0bc8e8246218d6d4fbb56fd42888dacb8aa4d4b9ce1f8" }, { - "6a09e627f3bcc92dbb67aee084caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217928cdecc6e7e3f0e93591c75513aa862e44adae0a40ce7b8e6c72ea4b47b7c88b832a34cca4d8dbc6f112373f1e82e1d26a58498cfa1ed290e872149667cb2b9100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "f1639feeaad03b7ea99e85889b6f7407a26a4095687dbc027d3256ad0c481f1661564b3628ba5b0a8117ea73be040036921ce3b64849a70db05bbaec2ba82c15" + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a0908000000141312111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000095000000000000000001", + "099cb773e2cc379a8876af0e51773691d22f53d314339be845292a02de394c76ddf87a51130d71b51cec3be7246631c03620302852f17de6dd18d2b40cab30f3" }, { - "6a09e627f3bcc93bbb67aef684caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e21795f88c38e13dd036e0b6907218d2236f47bfc9ad7ad4478e69c11a4dd69109a5045de7154839b33f604c0f5907ab5e9a916abd7bedaba1dd6635f2850f42038b500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "4c0fa0b3fa95a5ef7eb0ee4c662f9aef6b96582d211917c640cba8d7a7009fcaccfbb7ba7664cf24b2e2f5c3e7d45fee8b459c6581a25a97af1d6e71fd67a709" + "0000000c6a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", + "ff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde" }, { - "6a09e627f3bcc948bb67ae0484caa73a3c6ef372fe94b82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e21790bc009514bdad0c0331a29252f923da6137d6fd4ba14cb0e9c7cbb0bb1a666d5597d4d8c44612f5a2b12e8e39fa134d96b1d53fa08e48a1ad915bc44040c22ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0ffffffffffffffff010000000c", - "272539bb30107dea7bf9ef9e3ed75db2c8a0ddb9f37c39ea06c012ed70c8a917e00040c6684905cc1b627d7d9b4e87daa03e2412698679068fe944138ab3c796" + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a0908171615141312111000000000001a1918000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009b000000000000000001", + "54777d6e31afa286ac6453272e941b20d7d85bab6289ea12f9c8fffbc56d27fb67df67484eae8ca22709162425b7d980b5e078605bda55c81dcab91ce391aa54" + }, + { + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a09081716151413121110000000001b1a1918000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c000000000000000001", + "052780a0caf0bd10793f8aaf9b3606e7a77506a8030a2cd764515ea4e30bb0bb6d6fb5ef88eed1246577e2e65a5477578930fc93e4f5a8c355eedfa133896315" + }, + { + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a2928000000000000313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2000000000000000001", + "fe47a4b9e2a1e7d01080ffe977223ee8aa7afa12ae75f3c26aa2687831a6a58c32cfc1fb690b7a3601630637eb345da575ba0e2310213d6f7cf5ac546fa52840" + }, + { + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a393847464544434241404f4e4d4c4b4a494857565554535251505f5e5d5c5b5a595867666564636261606f6e6d6c6b6a696877767574737271707f7e7d7c7b7a79780000000000000100000000000000000000", + "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e000000000000000e8000000000000000000000000000000000000000000000169000000000000000001", + "ca769859d42c76d4db449924feb8b27536b9da1f74ce7ad2eb0f4625e4c6cb160e1838ccade7d451567f4a02897cc47feae4fd8d87db1a19fe0e61a2f52322d6" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e800000000f3f2f1f000000000000000000000000000000174000000000000000001", + "8187dd8f261496b3d5b489bffe2c5e5134e626c210ab2b406c0dfb00e09a6b4eea800ec83e2fcb79168969f8d28019eb51653672749f2ebd37a823cad39c6416" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000000000000000f80000000000000179000000000000000001", + "f5b5dbc5e76321b3ef75c8ead211dc1f7e0a0999767ecbbb5daf9507d5a8f87fcdf83e5498ffd974872785043dc19af8567417c800efe05637758ee39fd5e161" + }, + { + "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a393847464544434241404f4e4d4c4b4a494857565554535251505f5e5d5c5b5a595867666564636261606f6e6d6c6b6a696877767574737271707f7e7d7c7b7a79780000000000000100000000000000000000", + "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000010", + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" + }, + { + "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000011", + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" }, }; } From 7a85cbe04186c9333e21616187af70f76a87988e Mon Sep 17 00:00:00 2001 From: ivaylo Date: Thu, 4 Jul 2019 10:50:03 +0100 Subject: [PATCH 04/12] Add rfc link for completeness --- .../java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java index fcacfb6932..d7b007277f 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java @@ -30,6 +30,8 @@ public Blake2fMessageDigest() { /** * Implementation of the `F` compression function of the Blake2b cryptographic hash function. * + *

RFC - https://tools.ietf.org/html/rfc7693 + * *

Adapted from - https://github.com/keep-network/blake2b/blob/master/compression/f.go * *

Optimized for 64-bit platforms From 4f1494a82f8780dd041dbf5ff9e06f55d7f74856 Mon Sep 17 00:00:00 2001 From: ivaylo Date: Thu, 4 Jul 2019 16:26:05 +0100 Subject: [PATCH 05/12] Remove google.common dependency *represent uint as long for safe mod and comparison operation. Using UnsignedInts.remainder(divedent, divisor) converts int to long for each round. *use BC Pack utils for long <-> bytes --- .../pantheon/crypto/Blake2fMessageDigest.java | 99 ++++++++++++------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java index d7b007277f..e7f5a50858 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java @@ -14,12 +14,10 @@ import static java.util.Arrays.copyOfRange; -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import com.google.common.primitives.UnsignedInts; import org.bouncycastle.crypto.Digest; import org.bouncycastle.jcajce.provider.digest.BCMessageDigest; import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Pack; public class Blake2fMessageDigest extends BCMessageDigest { @@ -40,8 +38,6 @@ public static class Blake2fDigest implements Digest { public static final int MESSAGE_LENGTH_BYTES = 213; - private static final int BLOCK_LENGTH_BYTES = 128; - private static final long[] IV = { 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL, 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL, @@ -66,7 +62,7 @@ public static class Blake2fDigest implements Digest { // buffer which holds serialized input for this compression function // [ 4 bytes for rounds ][ 64 bytes for h ][ 128 bytes for m ] // [ 8 bytes for t_0 ][ 8 bytes for t_1 ][ 1 byte for f ] - private byte[] buffer; + private final byte[] buffer; private int bufferPos; @@ -75,7 +71,7 @@ public static class Blake2fDigest implements Digest { private final long[] m; private final long[] t; private boolean f; - private int rounds; + private long rounds; // unsigned integer represented as long private final long[] v; @@ -92,6 +88,22 @@ public static class Blake2fDigest implements Digest { v = new long[16]; } + // for tests + Blake2fDigest( + final long[] h, final long[] m, final long[] t, final boolean f, final long rounds) { + assert rounds <= 4294967295L; // uint max value + buffer = new byte[MESSAGE_LENGTH_BYTES]; + bufferPos = 0; + + this.h = h; + this.m = m; + this.t = t; + this.f = f; + this.rounds = rounds; + + v = new long[16]; + } + @Override public String getAlgorithmName() { return "BLAKE2f"; @@ -110,12 +122,12 @@ public int getDigestSize() { @Override public void update(final byte in) { - if (MESSAGE_LENGTH_BYTES - bufferPos == 0) { // full buffer + if (bufferPos == MESSAGE_LENGTH_BYTES) { // full buffer throw new IllegalArgumentException(); } else { buffer[bufferPos] = in; bufferPos++; - if (bufferPos == BLOCK_LENGTH_BYTES) { + if (bufferPos == MESSAGE_LENGTH_BYTES) { initialize(); } } @@ -134,13 +146,22 @@ public void update(final byte[] in, final int offset, final int len) { return; } - if (in.length != MESSAGE_LENGTH_BYTES || len != 213 || offset != 0 || bufferPos != 0) { - throw new IllegalArgumentException(); + if (len > MESSAGE_LENGTH_BYTES - bufferPos) { + throw new IllegalArgumentException( + "Attempting to update buffer with " + + len + + " byte(s) but there is " + + (MESSAGE_LENGTH_BYTES - bufferPos) + + " byte(s) left to fill"); } System.arraycopy(in, offset, buffer, bufferPos, len); - initialize(); + bufferPos += len; + + if (bufferPos == MESSAGE_LENGTH_BYTES) { + initialize(); + } } /** @@ -151,10 +172,14 @@ public void update(final byte[] in, final int offset, final int len) { */ @Override public int doFinal(final byte[] out, final int offset) { + if (bufferPos != 213) { + throw new IllegalStateException("The buffer must be filled with 213 bytes"); + } + compress(); for (int i = 0; i < h.length; i++) { - System.arraycopy(Longs.toByteArray(h[i]), 0, out, i * 8, 8); + System.arraycopy(Pack.longToBigEndian(h[i]), 0, out, i * 8, 8); } reset(); @@ -162,25 +187,46 @@ public int doFinal(final byte[] out, final int offset) { return 0; } + /** Reset the digest back to it's initial state. */ + @Override + public void reset() { + bufferPos = 0; + Arrays.fill(buffer, (byte) 0); + Arrays.fill(h, 0); + Arrays.fill(m, (byte) 0); + Arrays.fill(t, 0); + f = false; + rounds = 12; + Arrays.fill(v, 0); + } + private void initialize() { - rounds = Ints.fromByteArray(copyOfRange(buffer, 0, 4)); + rounds = Integer.toUnsignedLong(bytesToInt(copyOfRange(buffer, 0, 4))); for (int i = 0; i < h.length; i++) { final int offset = 4 + i * 8; - h[i] = Longs.fromByteArray(copyOfRange(buffer, offset, offset + 8)); + h[i] = bytesToLong((copyOfRange(buffer, offset, offset + 8))); } for (int i = 0; i < 16; i++) { final int offset = 68 + i * 8; - m[i] = Longs.fromByteArray(copyOfRange(buffer, offset, offset + 8)); + m[i] = bytesToLong(copyOfRange(buffer, offset, offset + 8)); } - t[0] = Longs.fromByteArray(copyOfRange(buffer, 196, 204)); - t[1] = Longs.fromByteArray(copyOfRange(buffer, 204, 212)); + t[0] = bytesToLong(copyOfRange(buffer, 196, 204)); + t[1] = bytesToLong(copyOfRange(buffer, 204, 212)); f = buffer[212] != 0; } + private int bytesToInt(final byte[] bytes) { + return Pack.bigEndianToInt(bytes, 0); + } + + private long bytesToLong(final byte[] bytes) { + return Pack.bigEndianToLong(bytes, 0); + } + /** * F is a compression function for BLAKE2b. It takes as an argument the state vector `h`, * message block vector `m`, offset counter `t`, final block indicator flag `f`, and number of @@ -202,8 +248,8 @@ private void compress() { v[14] ^= 0xffffffffffffffffL; } - for (int j = 0; UnsignedInts.compare(j, rounds) < 0; ++j) { - byte[] s = PRECOMPUTED[j % 10]; + for (long j = 0; j < rounds; ++j) { + byte[] s = PRECOMPUTED[(int) (j % 10)]; mix(m[s[0]], m[s[4]], 0, 4, 8, 12); mix(m[s[1]], m[s[5]], 1, 5, 9, 13); @@ -233,18 +279,5 @@ private void mix( v[k] += v[l]; v[j] = Long.rotateLeft(v[j] ^ v[k], -63); } - - /** Reset the digest back to it's initial state. */ - @Override - public void reset() { - bufferPos = 0; - Arrays.fill(buffer, (byte) 0); - Arrays.fill(h, 0); - Arrays.fill(m, (byte) 0); - Arrays.fill(t, 0); - f = false; - rounds = 12; - Arrays.fill(v, 0); - } } } From b6c383d1dfb5c7c4f39cf0959ed4ab18a9a088a8 Mon Sep 17 00:00:00 2001 From: ivaylo Date: Thu, 4 Jul 2019 16:53:37 +0100 Subject: [PATCH 06/12] Add tests --- .../crypto/Blake2fMessageDigestTest.java | 112 ++++++++++++++++++ .../pegasys/pantheon/crypto/HashTest.java | 14 +++ 2 files changed, 126 insertions(+) create mode 100644 crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java diff --git a/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java b/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java new file mode 100644 index 0000000000..94685e80f0 --- /dev/null +++ b/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.crypto; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.bouncycastle.util.Pack; +import org.junit.Before; +import org.junit.Test; + +/** + * Test vectors adapted from + * https://github.com/keep-network/blake2b/blob/master/compression/f_test.go + */ +public class Blake2fMessageDigestTest { + + private Blake2fMessageDigest messageDigest; + + // output when input is all 0 + private byte[] blake2fAllZero = + new byte[] { + 106, 9, -26, 103, -13, -68, -55, 8, -69, 103, -82, -123, -124, -54, -89, 59, 60, 110, -13, + 114, -2, -108, -8, 43, -91, 79, -11, 58, 95, 29, 54, -15, 81, 14, 82, 127, -83, -26, -126, + -47, -101, 5, 104, -116, 43, 62, 108, 31, 31, -125, -39, -85, -5, 65, -67, 107, 91, -32, + -51, 25, 19, 126, 33, 121 + }; + + // output when input is all 0 for 2147483648 rounds + private byte[] blake2fAllZeroNegativeRounds = + new byte[] { + 118, 127, 109, 29, 115, -124, -99, -111, 81, 112, 35, 60, -89, 75, 21, 18, -97, -73, 19, + -102, 40, -8, 78, 110, -43, 124, 66, 83, -89, 69, 69, 57, -25, -105, 123, 117, 115, 115, 78, + -92, 123, 87, 14, -127, -94, -1, -74, 25, -125, 48, 54, -78, -82, -75, 84, -26, -38, -42, + -93, 120, -61, 7, -58, 38 + }; + + @Before + public void setUp() { + messageDigest = new Blake2fMessageDigest(); + } + + @Test + public void digestIfUpdatedCorrectlyWithBytes() { + for (int i = 0; i < 213; i++) { + messageDigest.update((byte) 0); + } + assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + } + + @Test + public void digestIfUpdatedCorrectlyWithByteArray() { + byte[] update = new byte[213]; + messageDigest.update(update, 0, 213); + assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + } + + @Test + public void digestIfUpdatedCorrectlyMixed() { + byte[] update = new byte[213]; + messageDigest.update((byte) 0); + messageDigest.update(update, 2, 211); + messageDigest.update((byte) 0); + assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + } + + @Test + public void digestWithNegativeRounds() { + // equal to Integer.MAX_VALUE + 1 (2147483648) as uint + byte[] rounds = Pack.intToBigEndian(Integer.MIN_VALUE); + messageDigest.update(rounds, 0, 4); + messageDigest.update(new byte[213], 0, 209); + assertThat(messageDigest.digest()).isEqualTo(blake2fAllZeroNegativeRounds); + } + + @Test(expected = IllegalStateException.class) + public void throwsIfBufferUpdatedWithLessThat213Bytes() { + for (int i = 0; i < 212; i++) { + messageDigest.update((byte) 0); + } + messageDigest.digest(); + } + + @Test(expected = IllegalArgumentException.class) + public void throwsIfBufferUpdatedWithMoreThat213Bytes() { + for (int i = 0; i < 214; i++) { + messageDigest.update((byte) 0); + } + } + + @Test(expected = IllegalArgumentException.class) + public void throwsIfBufferUpdatedLargeByteArray() { + byte[] update = new byte[213]; + messageDigest.update((byte) 0); + messageDigest.update(update, 0, 213); + } + + @Test(expected = IllegalArgumentException.class) + public void throwsIfEmptyBufferUpdatedLargeByteArray() { + byte[] update = new byte[214]; + messageDigest.update(update, 0, 214); + } +} diff --git a/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java b/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java index 12bed28bdd..50cf542137 100644 --- a/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java +++ b/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java @@ -17,6 +17,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; public class HashTest { @@ -26,6 +27,12 @@ public class HashTest { private static final String horseKeccak256 = "c87f65ff3f271bf5dc8643484f66b200109caffe4bf98c4cb393dc35740b28c0"; + private static final String inputBlake2f = + "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001"; + + private static final String outputBlake2f = + "62305ad4d48dade8269ef60a1bcb8b7bef6e479e643b5ac1f8017e6422ce89fb62d09ecaa81d095e855540dcbc07bd0feb3d4f5e5e50541260ed930f027cfd8d"; + /** Validate keccak256 hash. */ @Test public void keccak256Hash() { @@ -35,4 +42,11 @@ public void keccak256Hash() { final BytesValue resultCow = Hash.keccak256(BytesValue.wrap("cow".getBytes(UTF_8))); assertEquals(BytesValue.fromHexString(cowKeccak256), resultCow); } + + /** Validate blake2f compression digest. */ + @Test + public void blake2fCompression() { + final BytesValue result = Hash.blake2f(BytesValue.wrap(Hex.decode(inputBlake2f))); + assertEquals(BytesValue.fromHexString(outputBlake2f), result); + } } From 19df45e31bf28c429e24bb9e1e40fa97a217582a Mon Sep 17 00:00:00 2001 From: ivaylo Date: Tue, 30 Jul 2019 16:19:30 +0100 Subject: [PATCH 07/12] Test gas usage in parameterized test --- .../BLAKE2fPrecompileContractTest.java | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java index 583c64824b..2f7e0f1b52 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java @@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import tech.pegasys.pantheon.ethereum.core.Gas; import tech.pegasys.pantheon.ethereum.mainnet.ConstantinopleFixGasCalculator; import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.util.bytes.BytesValue; @@ -39,83 +40,103 @@ public static Object[][] parameters() { return new Object[][] { { "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001", - "62305ad4d48dade8269ef60a1bcb8b7bef6e479e643b5ac1f8017e6422ce89fb62d09ecaa81d095e855540dcbc07bd0feb3d4f5e5e50541260ed930f027cfd8d" + "62305ad4d48dade8269ef60a1bcb8b7bef6e479e643b5ac1f8017e6422ce89fb62d09ecaa81d095e855540dcbc07bd0feb3d4f5e5e50541260ed930f027cfd8d", + 1 }, { "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", - "74aaa2510b5c66ea8a708bdea257192d9c9bc48d53c7f7e87a51bffd24d5d9e6ea0b4b2070fb3a3d211208e3f7bcb1a24dec971cecbb62faf1cd142745f8f4ee" + "74aaa2510b5c66ea8a708bdea257192d9c9bc48d53c7f7e87a51bffd24d5d9e6ea0b4b2070fb3a3d211208e3f7bcb1a24dec971cecbb62faf1cd142745f8f4ee", + 1 }, { "000000018736a85f01b0a31dd67dcbe79b220b9b9d93e5897bb8975766b47652443b1927b715da2203c2ca1d0d22b820a965ad9cf23bb0bd57a16fd56ed7a9c5dc67af0587868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", - "f0eea67995b5e71bd02c40edf19aadd131475949119813de4ea3072f8865bb1978037a72d2bb446d3deead8310b5fba548088c5a99689c51c6632f660a2a2a45" + "f0eea67995b5e71bd02c40edf19aadd131475949119813de4ea3072f8865bb1978037a72d2bb446d3deead8310b5fba548088c5a99689c51c6632f660a2a2a45", + 1 }, { "000000056a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001", - "f863686fe221e37fee57b5eb7a41266fe765d26d337fa9fe329af1ae378bae9bd61f06dd8ccceec229349cd341b19df399488a9ab05aec7ba3442268fd039ba4" + "f863686fe221e37fee57b5eb7a41266fe765d26d337fa9fe329af1ae378bae9bd61f06dd8ccceec229349cd341b19df399488a9ab05aec7ba3442268fd039ba4", + 5 }, { "000000056a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", - "3a6c5ac8d6606290708c08540cb5c425f72014c8b50c280b817a6ffb1b8b405f2001caca125182b562b8a407a249ca6e9755b62e4324caaf4578a660d8dd4876" + "3a6c5ac8d6606290708c08540cb5c425f72014c8b50c280b817a6ffb1b8b405f2001caca125182b562b8a407a249ca6e9755b62e4324caaf4578a660d8dd4876", + 5 }, { "000000052a3c65f1dbd604cbc713d5ce8c0e5e6c3b22c76bdf73716e55525ba247a930f9e240763f1c01d22c514aa14d3f18722715405fbe7ecde36c77e565078839b7c987868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", - "7e7acc657731d1dfb4229114f545597b7fa4b3140217b470e86a8c27ab0b1ce8c103e219a3a2f77fa495b8c706b8016facf32b1cb5d83f2ae8d3248892d5d74c" + "7e7acc657731d1dfb4229114f545597b7fa4b3140217b470e86a8c27ab0b1ce8c103e219a3a2f77fa495b8c706b8016facf32b1cb5d83f2ae8d3248892d5d74c", + 5 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde00000000030201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000001", - "7180f3083d5aaabe0569cd951d62cf431dc9f9ff9eb4d014a5ef0eec4192b524ba8b0407d49601f648b0bc8e8246218d6d4fbb56fd42888dacb8aa4d4b9ce1f8" + "7180f3083d5aaabe0569cd951d62cf431dc9f9ff9eb4d014a5ef0eec4192b524ba8b0407d49601f648b0bc8e8246218d6d4fbb56fd42888dacb8aa4d4b9ce1f8", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a0908000000141312111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000095000000000000000001", - "099cb773e2cc379a8876af0e51773691d22f53d314339be845292a02de394c76ddf87a51130d71b51cec3be7246631c03620302852f17de6dd18d2b40cab30f3" + "099cb773e2cc379a8876af0e51773691d22f53d314339be845292a02de394c76ddf87a51130d71b51cec3be7246631c03620302852f17de6dd18d2b40cab30f3", + 12 }, { "0000000c6a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000", - "ff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde" + "ff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a0908171615141312111000000000001a1918000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009b000000000000000001", - "54777d6e31afa286ac6453272e941b20d7d85bab6289ea12f9c8fffbc56d27fb67df67484eae8ca22709162425b7d980b5e078605bda55c81dcab91ce391aa54" + "54777d6e31afa286ac6453272e941b20d7d85bab6289ea12f9c8fffbc56d27fb67df67484eae8ca22709162425b7d980b5e078605bda55c81dcab91ce391aa54", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a09081716151413121110000000001b1a1918000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c000000000000000001", - "052780a0caf0bd10793f8aaf9b3606e7a77506a8030a2cd764515ea4e30bb0bb6d6fb5ef88eed1246577e2e65a5477578930fc93e4f5a8c355eedfa133896315" + "052780a0caf0bd10793f8aaf9b3606e7a77506a8030a2cd764515ea4e30bb0bb6d6fb5ef88eed1246577e2e65a5477578930fc93e4f5a8c355eedfa133896315", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a2928000000000000313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2000000000000000001", - "fe47a4b9e2a1e7d01080ffe977223ee8aa7afa12ae75f3c26aa2687831a6a58c32cfc1fb690b7a3601630637eb345da575ba0e2310213d6f7cf5ac546fa52840" + "fe47a4b9e2a1e7d01080ffe977223ee8aa7afa12ae75f3c26aa2687831a6a58c32cfc1fb690b7a3601630637eb345da575ba0e2310213d6f7cf5ac546fa52840", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a393847464544434241404f4e4d4c4b4a494857565554535251505f5e5d5c5b5a595867666564636261606f6e6d6c6b6a696877767574737271707f7e7d7c7b7a79780000000000000100000000000000000000", - "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92" + "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e000000000000000e8000000000000000000000000000000000000000000000169000000000000000001", - "ca769859d42c76d4db449924feb8b27536b9da1f74ce7ad2eb0f4625e4c6cb160e1838ccade7d451567f4a02897cc47feae4fd8d87db1a19fe0e61a2f52322d6" + "ca769859d42c76d4db449924feb8b27536b9da1f74ce7ad2eb0f4625e4c6cb160e1838ccade7d451567f4a02897cc47feae4fd8d87db1a19fe0e61a2f52322d6", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e800000000f3f2f1f000000000000000000000000000000174000000000000000001", - "8187dd8f261496b3d5b489bffe2c5e5134e626c210ab2b406c0dfb00e09a6b4eea800ec83e2fcb79168969f8d28019eb51653672749f2ebd37a823cad39c6416" + "8187dd8f261496b3d5b489bffe2c5e5134e626c210ab2b406c0dfb00e09a6b4eea800ec83e2fcb79168969f8d28019eb51653672749f2ebd37a823cad39c6416", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000000000000000f80000000000000179000000000000000001", - "f5b5dbc5e76321b3ef75c8ead211dc1f7e0a0999767ecbbb5daf9507d5a8f87fcdf83e5498ffd974872785043dc19af8567417c800efe05637758ee39fd5e161" + "f5b5dbc5e76321b3ef75c8ead211dc1f7e0a0999767ecbbb5daf9507d5a8f87fcdf83e5498ffd974872785043dc19af8567417c800efe05637758ee39fd5e161", + 12 }, { "0000000cff3e48ac606d27242b6d0f03be548f10ff2d7f8bccfba4b872deac9005e263ebe6d620e38bba2bf133164736804d08f5dbf004f0c01f6df4bc02b6384c348cde07060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a393847464544434241404f4e4d4c4b4a494857565554535251505f5e5d5c5b5a595867666564636261606f6e6d6c6b6a696877767574737271707f7e7d7c7b7a79780000000000000100000000000000000000", - "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92" + "b02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d92", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000001", - "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000010", - "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee", + 12 }, { "0000000cb02406865b80cde9fec1e321559891be456158a6d71cf0eac1eb845c70d4a3d8948e82cc975dcbd6984780bab7e236382fb585df5bc4b043cb3e866544413d9287868584838281808f8e8d8c8b8a898897969594939291909f9e9d9c9b9a9998a7a6a5a4a3a2a1a0afaeadacabaaa9a8b7b6b5b4b3b2b1b0bfbebdbcbbbab9b8c7c6c5c4c3c2c1c0cfcecdcccbcac9c8d7d6d5d4d3d2d1d0dfdedddcdbdad9d8e7e6e5e4e3e2e1e0efeeedecebeae9e8f7f6f5f4f3f2f1f000fefdfcfbfaf9f8000000000000017f000000000000000011", - "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee" + "ccfc282ed60927145b46f8d0fa97afd07010c51d20821e9748923ea42a37a0fa0609a13be7c1e14b6e10a4b63d85d1d56d3d370d80f97b0a61a4f22ed6462dee", + 12 }, }; } @@ -125,11 +146,15 @@ public static Object[][] parameters() { @Parameterized.Parameter(1) public String expectedResult; + @Parameterized.Parameter(2) + public long expectedGasUsed; + @Test - public void shouldRecoverAddress() { + public void shouldRunFCompression() { final BytesValue input = BytesValue.fromHexString(this.input); - final BytesValue expected = + final BytesValue expectedComputation = expectedResult == null ? BytesValue.EMPTY : BytesValue.fromHexString(expectedResult); - assertThat(contract.compute(input, messageFrame)).isEqualTo(expected); + assertThat(contract.compute(input, messageFrame)).isEqualTo(expectedComputation); + assertThat(contract.gasRequirement(input)).isEqualTo(Gas.of(expectedGasUsed)); } } From b1542a3f4fe6084899b4a0fd1643d9e3eabbcc4a Mon Sep 17 00:00:00 2001 From: ivaylo Date: Tue, 30 Jul 2019 16:28:05 +0100 Subject: [PATCH 08/12] Integrate with precompile registry --- .../java/tech/pegasys/pantheon/ethereum/core/Address.java | 1 + .../mainnet/MainnetPrecompiledContractRegistries.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Address.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Address.java index cdff337d75..5ee21a05b2 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Address.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Address.java @@ -37,6 +37,7 @@ public class Address extends DelegatingBytesValue { public static final Address ALTBN128_ADD = Address.precompiled(6); public static final Address ALTBN128_MUL = Address.precompiled(7); public static final Address ALTBN128_PAIRING = Address.precompiled(8); + public static final Address BLAKE2B_F_COMPRESSION = Address.precompiled(9); // Last address that can be generated for a pre-compiled contract public static final Integer PRIVACY = Byte.MAX_VALUE - 1; diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index 98f3c0e44e..3fe6fa4583 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128AddPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128MulPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128PairingPrecompiledContract; +import tech.pegasys.pantheon.ethereum.mainnet.precompiles.BLAKE2fPrecompileContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.BigIntegerModularExponentiationPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.ECRECPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.IDPrecompiledContract; @@ -100,6 +101,10 @@ public static PrecompileContractRegistry istanbul( Account.DEFAULT_VERSION, AltBN128PairingPrecompiledContract.istanbul( precompiledContractConfiguration.getGasCalculator())); + registry.put( + Address.BLAKE2B_F_COMPRESSION, + ISTANBUL_ACCOUNT_VERSION, + new BLAKE2fPrecompileContract(precompiledContractConfiguration.getGasCalculator())); return registry; } From 4c02065f93a2535da162e84e1ae2a098a005f05c Mon Sep 17 00:00:00 2001 From: ivaylo Date: Tue, 30 Jul 2019 16:38:46 +0100 Subject: [PATCH 09/12] Rename blake2f to blake2bf --- ...eDigest.java => Blake2bfMessageDigest.java} | 12 ++++++------ .../tech/pegasys/pantheon/crypto/Hash.java | 6 +++--- .../pantheon/crypto/PantheonProvider.java | 2 +- ...est.java => Blake2bfMessageDigestTest.java} | 18 +++++++++--------- .../tech/pegasys/pantheon/crypto/HashTest.java | 10 +++++----- .../MainnetPrecompiledContractRegistries.java | 4 ++-- ...ct.java => BLAKE2BFPrecompileContract.java} | 8 ++++---- ...ava => BLAKE2BFPrecompileContractTest.java} | 8 ++++---- 8 files changed, 34 insertions(+), 34 deletions(-) rename crypto/src/main/java/tech/pegasys/pantheon/crypto/{Blake2fMessageDigest.java => Blake2bfMessageDigest.java} (97%) rename crypto/src/test/java/tech/pegasys/pantheon/crypto/{Blake2fMessageDigestTest.java => Blake2bfMessageDigestTest.java} (86%) rename ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/{BLAKE2fPrecompileContract.java => BLAKE2BFPrecompileContract.java} (86%) rename ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/{BLAKE2fPrecompileContractTest.java => BLAKE2BFPrecompileContractTest.java} (98%) diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigest.java similarity index 97% rename from crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java rename to crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigest.java index e7f5a50858..7ee8992a91 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigest.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigest.java @@ -19,10 +19,10 @@ import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; -public class Blake2fMessageDigest extends BCMessageDigest { +public class Blake2bfMessageDigest extends BCMessageDigest { - public Blake2fMessageDigest() { - super(new Blake2fDigest()); + public Blake2bfMessageDigest() { + super(new Blake2bfDigest()); } /** @@ -34,7 +34,7 @@ public Blake2fMessageDigest() { * *

Optimized for 64-bit platforms */ - public static class Blake2fDigest implements Digest { + public static class Blake2bfDigest implements Digest { public static final int MESSAGE_LENGTH_BYTES = 213; @@ -75,7 +75,7 @@ public static class Blake2fDigest implements Digest { private final long[] v; - Blake2fDigest() { + Blake2bfDigest() { buffer = new byte[MESSAGE_LENGTH_BYTES]; bufferPos = 0; @@ -89,7 +89,7 @@ public static class Blake2fDigest implements Digest { } // for tests - Blake2fDigest( + Blake2bfDigest( final long[] h, final long[] m, final long[] t, final boolean f, final long rounds) { assert rounds <= 4294967295L; // uint max value buffer = new byte[MESSAGE_LENGTH_BYTES]; diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java index 906649a51b..23fc0dab77 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/Hash.java @@ -26,7 +26,7 @@ private Hash() {} private static final String SHA256_ALG = "SHA-256"; private static final String RIPEMD160 = "RIPEMD160"; - private static final String BLAKE2F_ALG = "BLAKE2f"; + private static final String BLAKE2BF_ALG = "BLAKE2BF"; /** * Helper method to generate a digest using the provided algorithm. @@ -81,7 +81,7 @@ public static BytesValue ripemd160(final BytesValue input) { * @param input The input bytes to produce the digest for. * @return A digest. */ - public static BytesValue blake2f(final BytesValue input) { - return BytesValue.wrap(digestUsingAlgorithm(input, BLAKE2F_ALG)); + public static BytesValue blake2bf(final BytesValue input) { + return BytesValue.wrap(digestUsingAlgorithm(input, BLAKE2BF_ALG)); } } diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java index 16b2bfa97b..4f648fbc41 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java @@ -28,7 +28,7 @@ public PantheonProvider() { AccessController.doPrivileged( (PrivilegedAction) () -> { - put("MessageDigest.Blake2f", "tech.pegasys.pantheon.crypto.Blake2fMessageDigest"); + put("MessageDigest.Blake2bf", "tech.pegasys.pantheon.crypto.Blake2bfMessageDigest"); return null; }); } diff --git a/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java b/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigestTest.java similarity index 86% rename from crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java rename to crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigestTest.java index 94685e80f0..7c1a218cf5 100644 --- a/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2fMessageDigestTest.java +++ b/crypto/src/test/java/tech/pegasys/pantheon/crypto/Blake2bfMessageDigestTest.java @@ -22,12 +22,12 @@ * Test vectors adapted from * https://github.com/keep-network/blake2b/blob/master/compression/f_test.go */ -public class Blake2fMessageDigestTest { +public class Blake2bfMessageDigestTest { - private Blake2fMessageDigest messageDigest; + private Blake2bfMessageDigest messageDigest; // output when input is all 0 - private byte[] blake2fAllZero = + private byte[] blake2bfAllZero = new byte[] { 106, 9, -26, 103, -13, -68, -55, 8, -69, 103, -82, -123, -124, -54, -89, 59, 60, 110, -13, 114, -2, -108, -8, 43, -91, 79, -11, 58, 95, 29, 54, -15, 81, 14, 82, 127, -83, -26, -126, @@ -36,7 +36,7 @@ public class Blake2fMessageDigestTest { }; // output when input is all 0 for 2147483648 rounds - private byte[] blake2fAllZeroNegativeRounds = + private byte[] blake2bfAllZeroNegativeRounds = new byte[] { 118, 127, 109, 29, 115, -124, -99, -111, 81, 112, 35, 60, -89, 75, 21, 18, -97, -73, 19, -102, 40, -8, 78, 110, -43, 124, 66, 83, -89, 69, 69, 57, -25, -105, 123, 117, 115, 115, 78, @@ -46,7 +46,7 @@ public class Blake2fMessageDigestTest { @Before public void setUp() { - messageDigest = new Blake2fMessageDigest(); + messageDigest = new Blake2bfMessageDigest(); } @Test @@ -54,14 +54,14 @@ public void digestIfUpdatedCorrectlyWithBytes() { for (int i = 0; i < 213; i++) { messageDigest.update((byte) 0); } - assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + assertThat(messageDigest.digest()).isEqualTo(blake2bfAllZero); } @Test public void digestIfUpdatedCorrectlyWithByteArray() { byte[] update = new byte[213]; messageDigest.update(update, 0, 213); - assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + assertThat(messageDigest.digest()).isEqualTo(blake2bfAllZero); } @Test @@ -70,7 +70,7 @@ public void digestIfUpdatedCorrectlyMixed() { messageDigest.update((byte) 0); messageDigest.update(update, 2, 211); messageDigest.update((byte) 0); - assertThat(messageDigest.digest()).isEqualTo(blake2fAllZero); + assertThat(messageDigest.digest()).isEqualTo(blake2bfAllZero); } @Test @@ -79,7 +79,7 @@ public void digestWithNegativeRounds() { byte[] rounds = Pack.intToBigEndian(Integer.MIN_VALUE); messageDigest.update(rounds, 0, 4); messageDigest.update(new byte[213], 0, 209); - assertThat(messageDigest.digest()).isEqualTo(blake2fAllZeroNegativeRounds); + assertThat(messageDigest.digest()).isEqualTo(blake2bfAllZeroNegativeRounds); } @Test(expected = IllegalStateException.class) diff --git a/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java b/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java index 50cf542137..d6e31f6ee3 100644 --- a/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java +++ b/crypto/src/test/java/tech/pegasys/pantheon/crypto/HashTest.java @@ -27,10 +27,10 @@ public class HashTest { private static final String horseKeccak256 = "c87f65ff3f271bf5dc8643484f66b200109caffe4bf98c4cb393dc35740b28c0"; - private static final String inputBlake2f = + private static final String inputBlake2bf = "000000016a09e667f2bd8948bb67ae8584caa73b3c6ef372fe94f82ba54ff53a5f1d36f1510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e217907060504030201000f0e0d0c0b0a090817161514131211101f1e1d1c1b1a191827262524232221202f2e2d2c2b2a292837363534333231303f3e3d3c3b3a3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000001"; - private static final String outputBlake2f = + private static final String outputBlake2bf = "62305ad4d48dade8269ef60a1bcb8b7bef6e479e643b5ac1f8017e6422ce89fb62d09ecaa81d095e855540dcbc07bd0feb3d4f5e5e50541260ed930f027cfd8d"; /** Validate keccak256 hash. */ @@ -45,8 +45,8 @@ public void keccak256Hash() { /** Validate blake2f compression digest. */ @Test - public void blake2fCompression() { - final BytesValue result = Hash.blake2f(BytesValue.wrap(Hex.decode(inputBlake2f))); - assertEquals(BytesValue.fromHexString(outputBlake2f), result); + public void blake2bfCompression() { + final BytesValue result = Hash.blake2bf(BytesValue.wrap(Hex.decode(inputBlake2bf))); + assertEquals(BytesValue.fromHexString(outputBlake2bf), result); } } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index 3fe6fa4583..e157ef4975 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -17,7 +17,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128AddPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128MulPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128PairingPrecompiledContract; -import tech.pegasys.pantheon.ethereum.mainnet.precompiles.BLAKE2fPrecompileContract; +import tech.pegasys.pantheon.ethereum.mainnet.precompiles.BLAKE2BFPrecompileContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.BigIntegerModularExponentiationPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.ECRECPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.IDPrecompiledContract; @@ -104,7 +104,7 @@ public static PrecompileContractRegistry istanbul( registry.put( Address.BLAKE2B_F_COMPRESSION, ISTANBUL_ACCOUNT_VERSION, - new BLAKE2fPrecompileContract(precompiledContractConfiguration.getGasCalculator())); + new BLAKE2BFPrecompileContract(precompiledContractConfiguration.getGasCalculator())); return registry; } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContract.java similarity index 86% rename from ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java rename to ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContract.java index fe6cf53d94..51bd0037e8 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContract.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContract.java @@ -13,7 +13,7 @@ package tech.pegasys.pantheon.ethereum.mainnet.precompiles; import static java.util.Arrays.copyOfRange; -import static tech.pegasys.pantheon.crypto.Blake2fMessageDigest.Blake2fDigest.MESSAGE_LENGTH_BYTES; +import static tech.pegasys.pantheon.crypto.Blake2bfMessageDigest.Blake2bfDigest.MESSAGE_LENGTH_BYTES; import tech.pegasys.pantheon.crypto.Hash; import tech.pegasys.pantheon.ethereum.core.Gas; @@ -25,8 +25,8 @@ import java.math.BigInteger; // https://github.com/keep-network/go-ethereum/pull/4 -public class BLAKE2fPrecompileContract extends AbstractPrecompiledContract { - public BLAKE2fPrecompileContract(final GasCalculator gasCalculator) { +public class BLAKE2BFPrecompileContract extends AbstractPrecompiledContract { + public BLAKE2BFPrecompileContract(final GasCalculator gasCalculator) { super("BLAKE2f", gasCalculator); } @@ -48,6 +48,6 @@ public BytesValue compute(final BytesValue input, final MessageFrame messageFram if (input.size() != MESSAGE_LENGTH_BYTES) { return BytesValue.EMPTY; } - return Hash.blake2f(input); + return Hash.blake2bf(input); } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContractTest.java similarity index 98% rename from ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java rename to ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContractTest.java index 2f7e0f1b52..759dfa493b 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2fPrecompileContractTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/BLAKE2BFPrecompileContractTest.java @@ -25,11 +25,11 @@ import org.junit.runners.Parameterized; @RunWith(Parameterized.class) -public class BLAKE2fPrecompileContractTest { - private final BLAKE2fPrecompileContract contract = - new BLAKE2fPrecompileContract(new ConstantinopleFixGasCalculator()); +public class BLAKE2BFPrecompileContractTest { + private final BLAKE2BFPrecompileContract contract = + new BLAKE2BFPrecompileContract(new ConstantinopleFixGasCalculator()); - public BLAKE2fPrecompileContractTest() {} + public BLAKE2BFPrecompileContractTest() {} private MessageFrame messageFrame = mock(MessageFrame.class); From 330048c8ee10525cdb9339fc44eb01e1e811eaf9 Mon Sep 17 00:00:00 2001 From: Ivaylo Kirilov Date: Tue, 30 Jul 2019 22:05:57 +0100 Subject: [PATCH 10/12] Fix deprecated constructor --- .../java/tech/pegasys/pantheon/crypto/PantheonProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java index 4f648fbc41..d769083e43 100644 --- a/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java +++ b/crypto/src/main/java/tech/pegasys/pantheon/crypto/PantheonProvider.java @@ -24,7 +24,7 @@ public final class PantheonProvider extends Provider { @SuppressWarnings("unchecked") public PantheonProvider() { - super(PROVIDER_NAME, 1.0, info); + super(PROVIDER_NAME, "1.0", info); AccessController.doPrivileged( (PrivilegedAction) () -> { From cecadd3b17afaa5e8e36ed20f76de592f93e80a1 Mon Sep 17 00:00:00 2001 From: Ivaylo Kirilov Date: Tue, 30 Jul 2019 22:06:08 +0100 Subject: [PATCH 11/12] spotless --- .../mainnet/MainnetPrecompiledContractRegistries.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index e157ef4975..fc6c0d400e 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -102,9 +102,9 @@ public static PrecompileContractRegistry istanbul( AltBN128PairingPrecompiledContract.istanbul( precompiledContractConfiguration.getGasCalculator())); registry.put( - Address.BLAKE2B_F_COMPRESSION, - ISTANBUL_ACCOUNT_VERSION, - new BLAKE2BFPrecompileContract(precompiledContractConfiguration.getGasCalculator())); + Address.BLAKE2B_F_COMPRESSION, + ISTANBUL_ACCOUNT_VERSION, + new BLAKE2BFPrecompileContract(precompiledContractConfiguration.getGasCalculator())); return registry; } From 909519fb0176dfc13a54bdc7d3adaca099f0c61d Mon Sep 17 00:00:00 2001 From: ivaylo Date: Wed, 31 Jul 2019 13:24:06 +0100 Subject: [PATCH 12/12] Fix account version reference for blake2bf --- .../ethereum/mainnet/MainnetPrecompiledContractRegistries.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index fc6c0d400e..484c9ec645 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -103,7 +103,7 @@ public static PrecompileContractRegistry istanbul( precompiledContractConfiguration.getGasCalculator())); registry.put( Address.BLAKE2B_F_COMPRESSION, - ISTANBUL_ACCOUNT_VERSION, + Account.DEFAULT_VERSION, new BLAKE2BFPrecompileContract(precompiledContractConfiguration.getGasCalculator())); return registry;