Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Commit

Permalink
Blake2b f precompile raw implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
iikirilov committed Jul 1, 2019
1 parent d6d2984 commit c32274d
Showing 1 changed file with 239 additions and 1 deletion.
Expand Up @@ -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);
Expand All @@ -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;
}
}

0 comments on commit c32274d

Please sign in to comment.