/* * Copyright (c) [2016] [ <ether.camp> ] * This file is part of the ethereumJ library. * * The ethereumJ library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ethereumJ library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>. */ package org.ethereum.vm; import org.junit.Test; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class DataWordTest { @Test public void testAddPerformance() { boolean enabled = false; if (enabled) { byte[] one = new byte[]{0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41}; // Random value int ITERATIONS = 10000000; long now1 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { DataWord x = new DataWord(one); x.add(x); } System.out.println("Add1: " + (System.currentTimeMillis() - now1) + "ms"); long now2 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { DataWord x = new DataWord(one); x.add2(x); } System.out.println("Add2: " + (System.currentTimeMillis() - now2) + "ms"); } else { System.out.println("ADD performance test is disabled."); } } @Test public void testAdd2() { byte[] two = new byte[32]; two[31] = (byte) 0xff; // 0x000000000000000000000000000000000000000000000000000000000000ff DataWord x = new DataWord(two); x.add(new DataWord(two)); System.out.println(Hex.toHexString(x.getData())); DataWord y = new DataWord(two); y.add2(new DataWord(two)); System.out.println(Hex.toHexString(y.getData())); } @Test public void testAdd3() { byte[] three = new byte[32]; for (int i = 0; i < three.length; i++) { three[i] = (byte) 0xff; } DataWord x = new DataWord(three); x.add(new DataWord(three)); assertEquals(32, x.getData().length); System.out.println(Hex.toHexString(x.getData())); // FAIL // DataWord y = new DataWord(three); // y.add2(new DataWord(three)); // System.out.println(Hex.toHexString(y.getData())); } @Test public void testMod() { String expected = "000000000000000000000000000000000000000000000000000000000000001a"; byte[] one = new byte[32]; one[31] = 0x1e; // 0x000000000000000000000000000000000000000000000000000000000000001e byte[] two = new byte[32]; for (int i = 0; i < two.length; i++) { two[i] = (byte) 0xff; } two[31] = 0x56; // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56 DataWord x = new DataWord(one);// System.out.println(x.value()); DataWord y = new DataWord(two);// System.out.println(y.value()); y.mod(x); assertEquals(32, y.getData().length); assertEquals(expected, Hex.toHexString(y.getData())); } @Test public void testMul() { byte[] one = new byte[32]; one[31] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000001 byte[] two = new byte[32]; two[11] = 0x1; // 0x0000000000000000000000010000000000000000000000000000000000000000 DataWord x = new DataWord(one);// System.out.println(x.value()); DataWord y = new DataWord(two);// System.out.println(y.value()); x.mul(y); assertEquals(32, y.getData().length); assertEquals("0000000000000000000000010000000000000000000000000000000000000000", Hex.toHexString(y.getData())); } @Test public void testMulOverflow() { byte[] one = new byte[32]; one[30] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000100 byte[] two = new byte[32]; two[0] = 0x1; // 0x1000000000000000000000000000000000000000000000000000000000000000 DataWord x = new DataWord(one);// System.out.println(x.value()); DataWord y = new DataWord(two);// System.out.println(y.value()); x.mul(y); assertEquals(32, y.getData().length); assertEquals("0100000000000000000000000000000000000000000000000000000000000000", Hex.toHexString(y.getData())); } @Test public void testDiv() { byte[] one = new byte[32]; one[30] = 0x01; one[31] = 0x2c; // 0x000000000000000000000000000000000000000000000000000000000000012c byte[] two = new byte[32]; two[31] = 0x0f; // 0x000000000000000000000000000000000000000000000000000000000000000f DataWord x = new DataWord(one); DataWord y = new DataWord(two); x.div(y); assertEquals(32, x.getData().length); assertEquals("0000000000000000000000000000000000000000000000000000000000000014", Hex.toHexString(x.getData())); } @Test public void testDivZero() { byte[] one = new byte[32]; one[30] = 0x05; // 0x0000000000000000000000000000000000000000000000000000000000000500 byte[] two = new byte[32]; DataWord x = new DataWord(one); DataWord y = new DataWord(two); x.div(y); assertEquals(32, x.getData().length); assertTrue(x.isZero()); } @Test public void testSDivNegative() { // one is -300 as 256-bit signed integer: byte[] one = Hex.decode("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed4"); byte[] two = new byte[32]; two[31] = 0x0f; DataWord x = new DataWord(one); DataWord y = new DataWord(two); x.sDiv(y); assertEquals(32, x.getData().length); assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec", x.toString()); } @Test public void testPow() { BigInteger x = BigInteger.valueOf(Integer.MAX_VALUE); BigInteger y = BigInteger.valueOf(1000); BigInteger result1 = x.modPow(x, y); BigInteger result2 = pow(x, y); System.out.println(result1); System.out.println(result2); } @Test public void testSignExtend1() { DataWord x = new DataWord(Hex.decode("f2")); byte k = 0; String expected = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend2() { DataWord x = new DataWord(Hex.decode("f2")); byte k = 1; String expected = "00000000000000000000000000000000000000000000000000000000000000f2"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend3() { byte k = 1; DataWord x = new DataWord(Hex.decode("0f00ab")); String expected = "00000000000000000000000000000000000000000000000000000000000000ab"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend4() { byte k = 1; DataWord x = new DataWord(Hex.decode("ffff")); String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend5() { byte k = 3; DataWord x = new DataWord(Hex.decode("ffffffff")); String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend6() { byte k = 3; DataWord x = new DataWord(Hex.decode("ab02345678")); String expected = "0000000000000000000000000000000000000000000000000000000002345678"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend7() { byte k = 3; DataWord x = new DataWord(Hex.decode("ab82345678")); String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff82345678"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test public void testSignExtend8() { byte k = 30; DataWord x = new DataWord(Hex.decode("ff34567882345678823456788234567882345678823456788234567882345678")); String expected = "0034567882345678823456788234567882345678823456788234567882345678"; x.signExtend(k); System.out.println(x.toString()); assertEquals(expected, x.toString()); } @Test(expected = IndexOutOfBoundsException.class) public void testSignExtendException1() { byte k = -1; DataWord x = new DataWord(); x.signExtend(k); // should throw an exception } @Test(expected = IndexOutOfBoundsException.class) public void testSignExtendException2() { byte k = 32; DataWord x = new DataWord(); x.signExtend(k); // should throw an exception } @Test public void testAddModOverflow() { testAddMod("9999999999999999999999999999999999999999999999999999999999999999", "8888888888888888888888888888888888888888888888888888888888888888", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); testAddMod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); } void testAddMod(String v1, String v2, String v3) { DataWord dv1 = new DataWord(Hex.decode(v1)); DataWord dv2 = new DataWord(Hex.decode(v2)); DataWord dv3 = new DataWord(Hex.decode(v3)); BigInteger bv1 = new BigInteger(v1, 16); BigInteger bv2 = new BigInteger(v2, 16); BigInteger bv3 = new BigInteger(v3, 16); dv1.addmod(dv2, dv3); BigInteger br = bv1.add(bv2).mod(bv3); assertEquals(dv1.value(), br); } @Test public void testMulMod1() { DataWord wr = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); DataWord w1 = new DataWord(Hex.decode("01")); DataWord w2 = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999998")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertEquals("0000000000000000000000000000000000000000000000000000000000000001", Hex.toHexString(wr.getData())); } @Test public void testMulMod2() { DataWord wr = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); DataWord w1 = new DataWord(Hex.decode("01")); DataWord w2 = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertTrue(wr.isZero()); } @Test public void testMulModZero() { DataWord wr = new DataWord(Hex.decode("00")); DataWord w1 = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); DataWord w2 = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertTrue(wr.isZero()); } @Test public void testMulModZeroWord1() { DataWord wr = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); DataWord w1 = new DataWord(Hex.decode("00")); DataWord w2 = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertTrue(wr.isZero()); } @Test public void testMulModZeroWord2() { DataWord wr = new DataWord(Hex.decode("9999999999999999999999999999999999999999999999999999999999999999")); DataWord w1 = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); DataWord w2 = new DataWord(Hex.decode("00")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertTrue(wr.isZero()); } @Test public void testMulModOverflow() { DataWord wr = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); DataWord w1 = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); DataWord w2 = new DataWord(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); wr.mulmod(w1, w2); assertEquals(32, wr.getData().length); assertTrue(wr.isZero()); } public static BigInteger pow(BigInteger x, BigInteger y) { if (y.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException(); BigInteger z = x; // z will successively become x^2, x^4, x^8, x^16, // x^32... BigInteger result = BigInteger.ONE; byte[] bytes = y.toByteArray(); for (int i = bytes.length - 1; i >= 0; i--) { byte bits = bytes[i]; for (int j = 0; j < 8; j++) { if ((bits & 1) != 0) result = result.multiply(z); // short cut out if there are no more bits to handle: if ((bits >>= 1) == 0 && i == 0) return result; z = z.multiply(z); } } return result; } }