diff --git a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java index 278d5165..dde54985 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java @@ -1,6 +1,7 @@ package org.ethereum.core; -import org.ethereum.crypto.HashUtil; +import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; +import static org.ethereum.crypto.HashUtil.EMPTY_DATA_HASH; import org.ethereum.util.RLP; import org.ethereum.util.RLPList; @@ -28,7 +29,7 @@ public class AccountState { * I define a convenient equivalence TRIE (σ[a] s ) ≡ σ[a] s . * It shall be understood that σ[a] s is not a ‘physical’ member * of the account and does not contribute to its later serialisation */ - private byte[] stateRoot = new byte[0]; + private byte[] stateRoot = EMPTY_BYTE_ARRAY; /* The hash of the EVM code of this contract—this is the code * that gets executed should this address receive a message call; @@ -36,7 +37,7 @@ public class AccountState { * after construction. All such code fragments are contained in * the state database under their corresponding hashes for later * retrieval */ - private byte[] codeHash = HashUtil.sha3(new byte[0]); + private byte[] codeHash = EMPTY_DATA_HASH; public AccountState() { this(BigInteger.ZERO, BigInteger.ZERO); diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java index 8ced22bf..c28223e2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java @@ -5,7 +5,10 @@ import static java.util.Arrays.copyOfRange; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; import org.ethereum.util.Utils; @@ -13,7 +16,8 @@ import org.spongycastle.util.encoders.Hex; public class HashUtil { - public static byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]); + public static Map hashes = new HashMap<>(); + public static final byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]); private static final MessageDigest sha256digest; @@ -30,13 +34,14 @@ public class HashUtil { } public static byte[] sha3(byte[] input) { - return SHA3Helper.sha3(input); + ByteArrayWrapper byteArray = new ByteArrayWrapper(input); + if(hashes.keySet().contains(byteArray)) + return hashes.get(byteArray); + byte[] result = SHA3Helper.sha3(input); + hashes.put(byteArray, result); + return result; } - public static String sha3String(String input) { - return SHA3Helper.sha3String(input); - } - /** * Calculates RIGTMOST160(SHA3(input)). This is used in address calculations. */ diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java b/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java index 2ad5dea9..2bba8741 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java @@ -7,72 +7,74 @@ import org.spongycastle.util.encoders.Hex; public class SHA3Helper { - public static String sha3String(String message) { - return sha3String(message, new SHA3Digest(256), true); - } + private static int DEFAULT_SIZE = 256; - public static String sha3String(byte[] message) { - return sha3String(message, new SHA3Digest(256), true); - } + public static String sha3String(String message) { + return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true); + } - public static byte[] sha3(String message) { - return sha3(Hex.decode(message), new SHA3Digest(256), true); - } - - public static byte[] sha3(byte[] message) { - return sha3(message, new SHA3Digest(256), true); - } - - protected static String sha3String(String message, Size bitSize) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, true); - } - - protected static String sha3String(byte[] message, Size bitSize) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, true); - } - - protected static String sha3String(String message, Size bitSize, boolean bouncyencoder) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, bouncyencoder); - } - - protected static String sha3string(byte[] message, Size bitSize, boolean bouncyencoder) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, bouncyencoder); - } - - private static String sha3String(String message, SHA3Digest digest, boolean bouncyencoder) { - if (message != null) { - return sha3String(Hex.decode(message), digest, bouncyencoder); - } - throw new NullPointerException("Can't hash a NULL value"); - } + public static String sha3String(byte[] message) { + return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true); + } - private static String sha3String(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - byte[] hash = doSha3(message, digest, bouncyencoder); - if (bouncyencoder) { - return Hex.toHexString(hash); - } else { - BigInteger bigInt = new BigInteger(1, hash); - return bigInt.toString(16); - } - } - - private static byte[] sha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - return doSha3(message, digest, bouncyencoder); - } - - private static byte[] doSha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - byte[] hash = new byte[digest.getDigestSize()]; + public static byte[] sha3(String message) { + return sha3(Hex.decode(message), new SHA3Digest(DEFAULT_SIZE), true); + } - if (message.length != 0) { - digest.update(message, 0, message.length); - } - digest.doFinal(hash, 0); - return hash; - } + public static byte[] sha3(byte[] message) { + return sha3(message, new SHA3Digest(DEFAULT_SIZE), true); + } + + protected static String sha3String(String message, Size bitSize) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, true); + } + + protected static String sha3String(byte[] message, Size bitSize) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, true); + } + + protected static String sha3String(String message, Size bitSize, boolean bouncyencoder) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, bouncyencoder); + } + + protected static String sha3string(byte[] message, Size bitSize, boolean bouncyencoder) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, bouncyencoder); + } + + private static String sha3String(String message, SHA3Digest digest, boolean bouncyencoder) { + if (message != null) { + return sha3String(Hex.decode(message), digest, bouncyencoder); + } + throw new NullPointerException("Can't hash a NULL value"); + } + + private static String sha3String(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + byte[] hash = doSha3(message, digest, bouncyencoder); + if (bouncyencoder) { + return Hex.toHexString(hash); + } else { + BigInteger bigInt = new BigInteger(1, hash); + return bigInt.toString(16); + } + } + + private static byte[] sha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + return doSha3(message, digest, bouncyencoder); + } + + private static byte[] doSha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + byte[] hash = new byte[digest.getDigestSize()]; + + if (message.length != 0) { + digest.update(message, 0, message.length); + } + digest.doFinal(hash, 0); + return hash; + } public enum Size { @@ -91,4 +93,5 @@ public class SHA3Helper { return this.bits; } } + } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java index 94a3b104..503a7e89 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java @@ -10,6 +10,8 @@ import org.spongycastle.util.encoders.Hex; public class ByteUtil { + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + /** * Creates a copy of bytes and appends b to the end of it */