Merge remote-tracking branch 'origin/master'

Conflicts:
	src/main/java/org/ethereum/util/ByteUtil.java
This commit is contained in:
romanman 2014-06-26 19:09:46 +01:00
commit f94862bc95
12 changed files with 304 additions and 152 deletions

View File

@ -150,13 +150,6 @@ mvn clean package -Dmaven.test.skip=true
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0.1</version>
</dependency>
</dependencies>
<build>

View File

@ -1,56 +1,48 @@
package org.ethereum.db;
import com.google.common.primitives.UnsignedBytes;
import java.util.Arrays;
import java.util.Comparator;
import org.ethereum.util.FastByteComparisons;
/**
* www.ethereumJ.com
*
* @author: Roman Mandeleil
* Created on: 11/06/2014 15:02
* @author: Roman Mandeleil Created on: 11/06/2014 15:02
*/
public class ByteArrayWrapper implements Comparable{
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
private final byte[] data;
public ByteArrayWrapper(byte[] data)
{
if (data == null)
{
public ByteArrayWrapper(byte[] data) {
if (data == null) {
throw new NullPointerException();
}
this.data = data;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof ByteArrayWrapper))
{
public boolean equals(Object other) {
if (!(other instanceof ByteArrayWrapper)) {
return false;
}
return Arrays.equals(data, ((ByteArrayWrapper)other).data);
byte[] otherData = ((ByteArrayWrapper) other).getData();
return FastByteComparisons.compareTo(
data, 0, data.length,
otherData, 0, otherData.length) == 0;
}
@Override
public int hashCode()
{
public int hashCode() {
return Arrays.hashCode(data);
}
@Override
public int compareTo(ByteArrayWrapper o) {
return FastByteComparisons.compareTo(
data, 0, data.length,
o.getData(), 0, o.getData().length);
}
public byte[] getData() {
return data;
}
@Override
public int compareTo(Object second) {
Comparator<byte[]> comparator = UnsignedBytes.lexicographicalComparator();
return comparator.compare(this.data, ((ByteArrayWrapper)second).getData());
}
}

View File

@ -2,11 +2,9 @@ package org.ethereum.json;
import org.ethereum.vm.DataWord;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.*;
/**
@ -18,14 +16,12 @@ import java.util.*;
public class JSONHelper {
public static String dumpLine(byte[] address, byte[] nonce, byte[] balance, byte[] stateRoot,
byte[] codeHash, byte[] code, Map<DataWord, DataWord> storageMap){
// {address: x, nonce: n1, balance: b1, stateRoot: s1, codeHash: c1, code: c2, sotrage: [key: k1, value: v1, key:k2, value: v2 ] }
ArrayList<DataWord> storageKeys = new ArrayList(storageMap.keySet());
List<DataWord> storageKeys = new ArrayList<DataWord>(storageMap.keySet());
Collections.sort((List)storageKeys);
Map outMap = new LinkedHashMap();

View File

@ -111,7 +111,7 @@ public class ClientPeer {
ByteBuf buffer = channel.alloc().buffer(payload.length + 8);
buffer.writeBytes(StaticMessages.MAGIC_PACKET);
buffer.writeBytes(ByteUtil.calcPacketSize(payload));
buffer.writeBytes(ByteUtil.calcPacketLength(payload));
buffer.writeBytes(payload);
logger.info("Send msg: [ " +

View File

@ -361,7 +361,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
ByteBuf buffer = ctx.alloc().buffer(chainMessage.getPayload().length + 8);
buffer.writeBytes(StaticMessages.MAGIC_PACKET);
buffer.writeBytes(ByteUtil.calcPacketSize(chainMessage.getPayload()));
buffer.writeBytes(ByteUtil.calcPacketLength(chainMessage.getPayload()));
buffer.writeBytes(chainMessage.getPayload());
ctx.writeAndFlush(buffer);

View File

@ -6,12 +6,9 @@ package org.ethereum.trie;
* @author: Roman Mandeleil
* Created on: 11/06/2014 19:44
*/
public interface TrieFacade {
public void update(byte[] key, byte[] value);
public byte[] get(byte[] key);
public void delete(byte[] key);
}

View File

@ -47,19 +47,6 @@ public class ByteUtil {
else return Hex.toHexString(data);
}
// The packet size should be 4 byte long
public static byte[] calcPacketSize(byte[] packet){
byte[] size = new byte[4];
size[0] = (byte)(packet.length >> 24 & 0xFF);
size[1] = (byte)(packet.length >> 16 & 0xFF);
size[2] = (byte)(packet.length >> 8 & 0xFF);
size[3] = (byte)(packet.length >> 0 & 0xFF);
return size;
}
/**
* Calculate packet length
* @param msg
@ -118,17 +105,13 @@ public class ByteUtil {
byte[] data;
// check if the string is numeric
if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?")) {
if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?"))
data = new BigInteger(arg.toString().trim()).toByteArray();
// check if it's hex number
} else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+")){
else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+"))
data = new BigInteger(arg.toString().trim().substring(2), 16).toByteArray();
} else {
else
data = arg.toString().trim().getBytes();
}
if (data.length > 32)
@ -160,30 +143,23 @@ public class ByteUtil {
return baos.toByteArray();
}
public static byte[] stripLeadingZeroes(byte[] data) {
public static byte[] stripLeadingZeroes(byte[] data){
if (data == null) return null;
if (data == null)
return null;
int firstNonZero = 0;
int i = 0;
for (i = 0; i < data.length; ++i)
if (data[i] != 0){
for (i = 0; i < data.length; ++i) {
if (data[i] != 0) {
firstNonZero = i;
break;
}
if (i == data.length) return new byte[1];
if (firstNonZero == 0) return data;
}
if (i == data.length)
return new byte[1];
if (firstNonZero == 0)
return data;
byte[] result = new byte[data.length - firstNonZero];
System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero);

View File

@ -3,7 +3,6 @@ package org.ethereum.core;
import java.math.BigInteger;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.message.StaticMessages;
import org.ethereum.util.ByteUtil;
import org.spongycastle.util.encoders.Hex;
import org.ethereum.core.Block;

View File

@ -3,13 +3,7 @@ package org.ethereum.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.FastByteComparisons;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
public class MinerTest {
@ -68,40 +62,4 @@ public class MinerTest {
newBlock.setStateRoot(Hex.decode("50188ab86bdf164ac90eb2835a04a8930aae5393c3a2ef1166fb95028f9456b8"));
return newBlock;
}
/**
* This test shows the difference between iterating over,
* and comparing byte[] vs BigInteger value.
*
* Results indicate that the former has ~15x better performance.
* Therefore this is used in the Miner.mine() method.
*/
@Test
public void testIncrementPerformance() {
boolean testEnabled = false;
if(testEnabled) {
byte[] counter1 = new byte[4];
byte[] max = ByteBuffer.allocate(4).putInt(Integer.MAX_VALUE).array();
long start1 = System.currentTimeMillis();
while(ByteUtil.increment(counter1)) {
if(FastByteComparisons.compareTo(counter1, 0, 4, max, 0, 4) == 0) {
break;
}
}
System.out.println(System.currentTimeMillis() - start1 + "ms to reach: " + Hex.toHexString(counter1));
BigInteger counter2 = BigInteger.ZERO;
long start2 = System.currentTimeMillis();
while(true) {
if(counter2.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 0) {
break;
}
counter2 = counter2.add(BigInteger.ONE);
}
System.out.println(System.currentTimeMillis() - start2 + "ms to reach: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(4, counter2)));
}
}
}

View File

@ -0,0 +1,141 @@
package org.ethereum.db;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Comparator;
import org.ethereum.util.FastByteComparisons;
import org.junit.BeforeClass;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import com.google.common.primitives.UnsignedBytes;
public class ByteArrayWrapperTest {
static ByteArrayWrapper wrapper1;
static ByteArrayWrapper wrapper2;
static ByteArrayWrapper wrapper3;
static ByteArrayWrapper wrapper4;
@BeforeClass
public static void loadByteArrays() {
String block = "f9072df8d3a077ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6c"
+ "d9225d285c89a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0"
+ "a142fd40d493479476f5eabe4b342ee56b8ceba6ab2a770c3e2198e7a0faa0ca"
+ "43105f667dceb168eb4e0cdc98ef28a9da5c381edef70d843207601719a06785"
+ "f3860460b2aa29122698e83a5151b270e82532c1663e89e3df8c5445b8ca833f"
+ "f000018609184e72a000830f3e6f8227d2845387c58f80a00000000000000000"
+ "0000000000000000000000000000000094148d7738f78c04f90654f8c6f8a080"
+ "8609184e72a00082271094000000000000000000000000000000000000000080"
+ "b83a33604557602a5160106000396000f200604556330e0f602a59366000530a"
+ "0f602a596020600053013560005335576040600053016000546009581ca033a6"
+ "bfa5eb2f4b63f1b98bed9a987d096d32e56deecb050367c84955508f5365a015"
+ "034e7574ec073f0c448aac1d9f844387610dfef5342834b6825fbc35df5913a0"
+ "ee258e73d41ada73d8d6071ba7d236fbbe24fcfb9627fbd4310e24ffd87b961a"
+ "8203e9f90194f9016d018609184e72a000822710940000000000000000000000"
+ "00000000000000000080b901067f4e616d655265670000000000000000000000"
+ "00000000000000000000000000003057307f4e616d6552656700000000000000"
+ "000000000000000000000000000000000000577f436f6e666967000000000000"
+ "000000000000000000000000000000000000000073ccdeac59d35627b7de0933"
+ "2e819d5159e7bb72505773ccdeac59d35627b7de09332e819d5159e7bb72507f"
+ "436f6e6669670000000000000000000000000000000000000000000000000000"
+ "57336045576041516100c56000396000f20036602259604556330e0f600f5933"
+ "ff33560f601e5960003356576000335700604158600035560f602b590033560f"
+ "603659600033565733600035576000353357001ca0f3c527e484ea5546189979"
+ "c767b69aa9f1ad5a6f4b6077d4bccf5142723a67c9a069a4a29a2a315102fcd0"
+ "822d39ad696a6d7988c993bb2b911cc2a78bb8902d91a01ebe4782ea3ed224cc"
+ "bb777f5de9ee7b5bbb282ac08f7fa0ef95d3d1c1c6d1a1820ef7f8ccf8a60286"
+ "09184e72a00082271094ccdeac59d35627b7de09332e819d5159e7bb725080b8"
+ "4000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000002d0aceee7e5ab874e22ccf8d1a649f59106d74"
+ "e81ba095ad45bf574c080e4d72da2cfd3dbe06cc814c1c662b5f74561f13e1e7"
+ "5058f2a057745a3db5482bccb5db462922b074f4b79244c4b1fa811ed094d728"
+ "e7b6da92a08599ea5d6cb6b9ad3311f0d82a3337125e05f4a82b9b0556cb3776"
+ "a6e1a02f8782132df8abf885038609184e72a000822710942d0aceee7e5ab874"
+ "e22ccf8d1a649f59106d74e880a0476176000000000000000000000000000000"
+ "00000000000000000000000000001ca09b5fdabd54ebc284249d2d2df6d43875"
+ "cb86c52bd2bac196d4f064c8ade054f2a07b33f5c8b277a408ec38d2457441d2"
+ "af32e55681c8ecb28eef3d2a152e8db5a9a0227a67fceb1bf4ddd31a7047e24b"
+ "e93c947ab3b539471555bb3509ed6e393c8e82178df90277f90250048609184e"
+ "72a0008246dd94000000000000000000000000000000000000000080b901e961"
+ "010033577f476176436f696e0000000000000000000000000000000000000000"
+ "000000000060005460006000600760006000732d0aceee7e5ab874e22ccf8d1a"
+ "649f59106d74e860645c03f150436000576000600157620f424060025761017d"
+ "5161006c6000396000f2006020360e0f61013f59602060006000374360205460"
+ "0056600054602056602054437f6e000000000000000000000000000000000000"
+ "00000000000000000000000000560e0f0f61008059437f6e0000000000000000"
+ "0000000000000000000000000000000000000000000000576000602054610400"
+ "60005304600053036000547f6400000000000000000000000000000000000000"
+ "0000000000000000000000005660016000030460406000200a0f61013e596001"
+ "60205301602054600a6020530b0f6100f45961040060005304600053017f6400"
+ "0000000000000000000000000000000000000000000000000000000000005760"
+ "20537f6900000000000000000000000000000000000000000000000000000000"
+ "000000576000537f640000000000000000000000000000000000000000000000"
+ "000000000000000057006040360e0f0f61014a59003356604054600035566060"
+ "546020356080546080536040530a0f6101695900608053604053033357608053"
+ "60605301600035571ba0190fc7ab634dc497fe1656fde523a4c26926d51a93db"
+ "2ba37af8e83c3741225da066ae0ec1217b0ca698a5369d4881e1c4cbde56af99"
+ "31ebf9281580a23b659c08a051f947cb2315d0259f55848c630caa10cd91d6e4"
+ "4ff8bad7758c65b25e2191308227d2c0";
byte[] test1 = Hex.decode(block);
byte[] test2 = Hex.decode(block);
byte[] test3 = Hex.decode("4ff8bad7758c65b25e2191308227d2c0");
byte[] test4 = Hex.decode("");
wrapper1 = new ByteArrayWrapper(test1);
wrapper2 = new ByteArrayWrapper(test2);
wrapper3 = new ByteArrayWrapper(test3);
wrapper4 = new ByteArrayWrapper(test4);
}
@Test
public void testEqualsObject() {
assertTrue(wrapper1.equals(wrapper2));
assertFalse(wrapper1.equals(wrapper3));
assertFalse(wrapper1.equals(wrapper4));
assertFalse(wrapper1.equals(null));
assertFalse(wrapper2.equals(wrapper3));
}
@Test
public void testCompareTo() {
assertTrue(wrapper1.compareTo(wrapper2) == 0);
assertTrue(wrapper1.compareTo(wrapper3) > 1);
assertTrue(wrapper1.compareTo(wrapper4) > 1);
assertTrue(wrapper2.compareTo(wrapper3) > 1);
}
@Test
public void testEqualsPerformance() {
boolean testEnabled = false;
if(testEnabled) {
final int ITERATIONS = 10000000;
long start1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
Comparator<byte[]> comparator = UnsignedBytes
.lexicographicalComparator();
comparator.compare(wrapper1.getData(),
wrapper2.getData());
}
System.out.println(System.currentTimeMillis() - start1 + "ms");
long start2 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
Arrays.equals(wrapper1.getData(), wrapper2.getData());
}
System.out.println(System.currentTimeMillis() - start2 + "ms");
long start3 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
FastByteComparisons.compareTo(wrapper1.getData(), 0, wrapper1.getData().length, wrapper2.getData(), 0, wrapper1.getData().length);
}
System.out.println(System.currentTimeMillis() - start3 + "ms");
}
}
}

View File

@ -436,7 +436,7 @@ public class MessagesTest {
assertEquals(expected, Hex.toHexString(getChainMessage.getPayload()).toUpperCase());
byte[] size = ByteUtil.calcPacketSize( getChainMessage.getPayload());
byte[] size = ByteUtil.calcPacketLength( getChainMessage.getPayload());
assertEquals("00000067", Hex.toHexString(size));
}

View File

@ -0,0 +1,100 @@
package org.ethereum.util;
import static org.junit.Assert.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
public class ByteUtilTest {
@Test
public void testAppendByte() {
byte[] bytes = "tes".getBytes();
byte b = 0x74;
assertArrayEquals("test".getBytes(), ByteUtil.appendByte(bytes, b));
}
// @Test
// public void testBigIntegerToBytes() {
// fail("Not yet implemented");
// }
@Test
public void testToHexString() {
assertEquals("null", ByteUtil.toHexString(null));
}
@Test
public void testCalcPacketLength() {
byte[] test = new byte[] { 0x0f, 0x10, 0x43 };
byte[] expected = new byte[] { 0x00, 0x00, 0x00, 0x03 };
assertArrayEquals(expected, ByteUtil.calcPacketLength(test));
}
@Test
public void testByteArrayToInt() {
assertEquals(0, ByteUtil.byteArrayToInt(null));
assertEquals(0, ByteUtil.byteArrayToInt(new byte[0]));
}
@Test
public void testNumBytes() {
String test1 = "0";
String test2 = "1";
String test3 = "1000000000"; //3B9ACA00
int expected1 = 1;
int expected2 = 1;
int expected3 = 4;
assertEquals(expected1, ByteUtil.numBytes(test1));
assertEquals(expected2, ByteUtil.numBytes(test2));
assertEquals(expected3, ByteUtil.numBytes(test3));
}
@Test
public void testStripLeadingZeroes() {
byte[] test1 = new byte[] { 0x00, 0x01 };
byte[] test2 = new byte[] { 0x00, 0x00, 0x01 };
byte[] expected = new byte[] { 0x01 };
assertArrayEquals(expected, ByteUtil.stripLeadingZeroes(test1));
assertArrayEquals(expected, ByteUtil.stripLeadingZeroes(test2));
}
/**
* This test shows the difference between iterating over,
* and comparing byte[] vs BigInteger value.
*
* Results indicate that the former has ~15x better performance.
* Therefore this is used in the Miner.mine() method.
*/
@Test
public void testIncrementPerformance() {
boolean testEnabled = false;
if(testEnabled) {
byte[] counter1 = new byte[4];
byte[] max = ByteBuffer.allocate(4).putInt(Integer.MAX_VALUE).array();
long start1 = System.currentTimeMillis();
while(ByteUtil.increment(counter1)) {
if(FastByteComparisons.compareTo(counter1, 0, 4, max, 0, 4) == 0) {
break;
}
}
System.out.println(System.currentTimeMillis() - start1 + "ms to reach: " + Hex.toHexString(counter1));
BigInteger counter2 = BigInteger.ZERO;
long start2 = System.currentTimeMillis();
while(true) {
if(counter2.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 0) {
break;
}
counter2 = counter2.add(BigInteger.ONE);
}
System.out.println(System.currentTimeMillis() - start2 + "ms to reach: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(4, counter2)));
}
}
}