Merge pull request #75 from nicksavers/master
Multiple performance fixes
This commit is contained in:
commit
a70761ad2b
|
@ -73,9 +73,6 @@ public class Block {
|
|||
timestamp, extraData, nonce);
|
||||
this.txsState = new Trie(null);
|
||||
|
||||
byte[] stateRoot = WorldManager.getInstance().getRepository().getRootHash();
|
||||
this.header.setStateRoot(stateRoot);
|
||||
|
||||
this.header.setTxTrieRoot(txsState.getRootHash());
|
||||
this.transactionsList = transactionsList;
|
||||
this.uncleList = uncleList;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.ethereum.core;
|
||||
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -64,17 +65,18 @@ public class Genesis extends Block {
|
|||
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
||||
EXTRA_DATA, NONCE, null, null);
|
||||
|
||||
Repository repository = WorldManager.getInstance().getRepository();
|
||||
// The proof-of-concept series include a development premine, making the state root hash
|
||||
// some value stateRoot. The latest documentation should be consulted for the value of the state root.
|
||||
for (String address : premine) {
|
||||
WorldManager.getInstance().getRepository().createAccount(Hex.decode(address));
|
||||
WorldManager.getInstance().getRepository().addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) );
|
||||
repository.createAccount(Hex.decode(address));
|
||||
repository.addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) );
|
||||
}
|
||||
this.setStateRoot(WorldManager.getInstance().getRepository().getRootHash());
|
||||
WorldManager.getInstance().getRepository().dumpState(0, 0, null);
|
||||
setStateRoot(repository.getWorldState().getRootHash());
|
||||
repository.dumpState(0, 0, null);
|
||||
|
||||
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
||||
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
||||
logger.info("Genesis-hash: {}", Hex.toHexString(this.getHash()));
|
||||
logger.info("Genesis-stateRoot: {}", Hex.toHexString(this.getStateRoot()));
|
||||
}
|
||||
|
||||
public static Block getInstance() {
|
||||
|
|
|
@ -7,18 +7,16 @@ import java.security.MessageDigest;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import org.ethereum.util.LRUMap;
|
||||
|
||||
public class HashUtil {
|
||||
|
||||
private static final int MAX_ENTRIES = 1000; // Should contain most commonly hashed values
|
||||
private static LRUMap<ByteArrayWrapper, byte[]> sha3Cache = new LRUMap<>(0, MAX_ENTRIES);
|
||||
public static final byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]);
|
||||
private static final int MAX_ENTRIES = 100; // Should contain most commonly hashed values
|
||||
private static LRUMap<ByteArrayWrapper, byte[]> sha3Cache = new LRUMap<>(0, MAX_ENTRIES);
|
||||
public static final byte[] EMPTY_DATA_HASH = Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||
|
||||
private static final MessageDigest sha256digest;
|
||||
|
||||
|
@ -35,14 +33,15 @@ public class HashUtil {
|
|||
}
|
||||
|
||||
public static byte[] sha3(byte[] input) {
|
||||
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
|
||||
if(sha3Cache.keySet().contains(inputByteArray))
|
||||
return sha3Cache.get(inputByteArray);
|
||||
byte[] result = SHA3Helper.sha3(input);
|
||||
sha3Cache.put(inputByteArray, result);
|
||||
return result;
|
||||
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
|
||||
byte[] result = sha3Cache.get(inputByteArray);
|
||||
if(result != null)
|
||||
return result;
|
||||
result = SHA3Helper.sha3(input);
|
||||
sha3Cache.put(inputByteArray, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates RIGTMOST160(SHA3(input)). This is used in address calculations.
|
||||
*/
|
||||
|
@ -62,7 +61,7 @@ public class HashUtil {
|
|||
|
||||
byte[] encSender = RLP.encodeElement(addr);
|
||||
byte[] encNonce = RLP.encodeElement(nonce);
|
||||
byte[] newAddress = HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
|
||||
byte[] newAddress = sha3omit12(RLP.encodeList(encSender, encNonce));
|
||||
|
||||
return newAddress;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ContractDetails {
|
|||
}
|
||||
} else{
|
||||
|
||||
storageTrie.update(key.getData(), RLP.encodeElement( value.getNoLeadZeroesData() ));
|
||||
storageTrie.update(key.getData(), RLP.encodeElement(value.getNoLeadZeroesData()));
|
||||
int index = storageKeys.indexOf(key);
|
||||
if (index != -1) {
|
||||
storageKeys.remove(index);
|
||||
|
@ -94,7 +94,11 @@ public class ContractDetails {
|
|||
|
||||
public byte[] getStorageHash() {
|
||||
|
||||
getEncoded();
|
||||
storageTrie = new Trie(null);
|
||||
// calc the trie for root hash
|
||||
for (int i = 0; i < storageKeys.size(); ++i){
|
||||
storageTrie.update(storageKeys.get(i).getData(), RLP.encodeElement( storageValues.get(i).getNoLeadZeroesData() ));
|
||||
}
|
||||
return storageTrie.getRootHash();
|
||||
}
|
||||
|
||||
|
@ -124,7 +128,7 @@ public class ContractDetails {
|
|||
for (int i = 0; i < keys.size(); ++i) {
|
||||
DataWord key = storageKeys.get(i);
|
||||
DataWord value = storageValues.get(i);
|
||||
storageTrie.update(key.getData(), RLP.encodeElement( value.getNoLeadZeroesData() ));
|
||||
storageTrie.update(key.getData(), RLP.encodeElement(value.getNoLeadZeroesData()));
|
||||
}
|
||||
|
||||
this.code = code.getRLPData();
|
||||
|
@ -149,12 +153,6 @@ public class ContractDetails {
|
|||
values[i] = RLP.encodeElement(value.getNoLeadZeroesData());
|
||||
}
|
||||
|
||||
storageTrie = new Trie(null);
|
||||
// calc the trie for root hash
|
||||
for (int i = 0; i < storageKeys.size(); ++i){
|
||||
storageTrie.update(storageKeys.get(i).getData(), values[i]);
|
||||
}
|
||||
|
||||
byte[] rlpKeysList = RLP.encodeList(keys);
|
||||
byte[] rlpValuesList = RLP.encodeList(values);
|
||||
byte[] rlpCode = RLP.encodeElement(code);
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.ethereum.core.Blockchain;
|
|||
import org.ethereum.core.Genesis;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.json.JSONHelper;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.trie.Trie;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
|
@ -181,9 +180,9 @@ public class Repository {
|
|||
|
||||
byte[] accountStateRLP = accountStateDB.get(addr);
|
||||
|
||||
if (accountStateRLP.length == 0) {
|
||||
if (accountStateRLP.length == 0)
|
||||
return null;
|
||||
}
|
||||
|
||||
AccountState state = new AccountState(accountStateRLP);
|
||||
return state;
|
||||
}
|
||||
|
@ -196,11 +195,10 @@ public class Repository {
|
|||
logger.debug("Get contract details for: [ {} ]", Hex.toHexString(addr));
|
||||
|
||||
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
|
||||
|
||||
if (accountDetailsRLP == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (accountDetailsRLP == null)
|
||||
return null;
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP));
|
||||
|
||||
|
@ -214,10 +212,9 @@ public class Repository {
|
|||
|
||||
AccountState state = getAccountState(addr);
|
||||
|
||||
if (state == null){
|
||||
if (state == null)
|
||||
state = createAccount(addr);
|
||||
}
|
||||
|
||||
|
||||
BigInteger newBalance = state.addToBalance(value);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
|
@ -347,10 +344,6 @@ public class Repository {
|
|||
contractDetailsDB.delete(addr);
|
||||
}
|
||||
|
||||
public byte[] getRootHash() {
|
||||
return this.worldState.getRootHash();
|
||||
}
|
||||
|
||||
public List<ByteArrayWrapper> dumpKeys(){
|
||||
return stateDB.dumpKeys();
|
||||
}
|
||||
|
@ -413,7 +406,7 @@ public class Repository {
|
|||
bw.write("\n");
|
||||
}
|
||||
|
||||
String rootHash = Hex.toHexString(WorldManager.getInstance().getRepository().getRootHash());
|
||||
String rootHash = Hex.toHexString(this.getWorldState().getRootHash());
|
||||
bw.write(
|
||||
String.format(" => Global State Root: [ %s ]", rootHash)
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.ethereum.trie;
|
|||
import static java.util.Arrays.copyOfRange;
|
||||
import static org.spongycastle.util.Arrays.concatenate;
|
||||
import static org.ethereum.util.CompactEncoder.*;
|
||||
import static org.ethereum.util.ByteUtil.matchingNibbleLength;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -399,15 +400,6 @@ public class Trie implements TrieFacade {
|
|||
* Utility functions *
|
||||
*******************************/
|
||||
|
||||
// Returns the amount of nibbles that match each other from 0 ...
|
||||
private int matchingNibbleLength(byte[] a, byte[] b) {
|
||||
int i = 0;
|
||||
while (Arrays.equals(copyOfRange(a, 0, i+1), copyOfRange(b, 0, i+1)) && i < b.length) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Created an array of empty elements of requred length
|
||||
private Object[] emptyStringSlice(int l) {
|
||||
Object[] slice = new Object[l];
|
||||
|
@ -418,7 +410,6 @@ public class Trie implements TrieFacade {
|
|||
}
|
||||
|
||||
public byte[] getRootHash() {
|
||||
Object root = this.getRoot();
|
||||
if (root == null
|
||||
|| (root instanceof byte[] && ((byte[]) root).length == 0)
|
||||
|| (root instanceof String && "".equals((String) root))) {
|
||||
|
|
|
@ -60,6 +60,24 @@ public class ByteUtil {
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of nibbles that match each other from 0 ...
|
||||
* amount will never be larger than smallest input
|
||||
*
|
||||
* @param a - first input
|
||||
* @param b second input
|
||||
* @return number of bytes that match
|
||||
*/
|
||||
public static int matchingNibbleLength(byte[] a, byte[] b) {
|
||||
int i = 0;
|
||||
int length = a.length < b.length ? a.length : b.length;
|
||||
while (i < length) {
|
||||
if (a[i] != b[i])
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static byte[] longToBytes(long l) {
|
||||
return ByteBuffer.allocate(8).putLong(l).array();
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package org.ethereum.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static java.util.Arrays.copyOfRange;
|
||||
import static java.util.Arrays.copyOf;
|
||||
import static java.util.Arrays.copyOfRange;
|
||||
|
||||
import static org.ethereum.util.ByteUtil.appendByte;
|
||||
import static org.spongycastle.util.Arrays.concatenate;
|
||||
import static org.spongycastle.util.encoders.Hex.toHexString;
|
||||
import static org.spongycastle.util.encoders.Hex.encode;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Compact encoding of hex sequence with optional terminator
|
||||
|
@ -85,11 +86,11 @@ public class CompactEncoder {
|
|||
*/
|
||||
public static byte[] unpackToNibbles(byte[] str) {
|
||||
byte[] base = binToNibbles(str);
|
||||
base = copyOf(base, base.length-1);
|
||||
base = copyOf(base, base.length - 1);
|
||||
if (base[0] >= 2) {
|
||||
base = appendByte(base, TERMINATOR);
|
||||
}
|
||||
if (base[0]%2 == 1) {
|
||||
if (base[0] % 2 == 1) {
|
||||
base = copyOfRange(base, 1, base.length);
|
||||
} else {
|
||||
base = copyOfRange(base, 2, base.length);
|
||||
|
@ -101,15 +102,14 @@ public class CompactEncoder {
|
|||
* Transforms a binary array to hexadecimal format + terminator
|
||||
*
|
||||
* @return array with each individual nibble adding a terminator at the end
|
||||
*/
|
||||
*/
|
||||
public static byte[] binToNibbles(byte[] str) {
|
||||
byte[] hexSlice = new byte[0];
|
||||
String hexEncoded = toHexString(str);
|
||||
for (char value : hexEncoded.toCharArray()) {
|
||||
hexSlice = appendByte(hexSlice, (byte) hexBase.indexOf(value));
|
||||
byte[] hexEncoded = encode(str);
|
||||
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length + 1);
|
||||
for (byte b : hexEncoded) {
|
||||
slice.put((byte)hexBase.indexOf(b));
|
||||
}
|
||||
hexSlice = appendByte(hexSlice, TERMINATOR);
|
||||
|
||||
return hexSlice;
|
||||
slice.put(TERMINATOR);
|
||||
return slice.array();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -306,7 +306,7 @@ public class Program {
|
|||
this.refundGas(refundGas, "remain gas from the internal call");
|
||||
if (logger.isInfoEnabled()){
|
||||
|
||||
logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ",
|
||||
logger.info("The remaining gas is refunded, account: [ {} ], gas: [ {} ] ",
|
||||
Hex.toHexString(this.getOwnerAddress().getLast20Bytes()),
|
||||
refundGas);
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ public class Program {
|
|||
* That method implement internal calls
|
||||
* and code invocations
|
||||
*
|
||||
* @param gas - gas to pay for the call, remain gas will be refunded to the caller
|
||||
* @param gas - gas to pay for the call, remaining gas will be refunded to the caller
|
||||
* @param toAddressDW - address to call
|
||||
* @param endowmentValue - the value that can be transfer along with the code execution
|
||||
* @param inDataOffs - start of memory to be input data to the call
|
||||
|
@ -431,13 +431,13 @@ public class Program {
|
|||
BigInteger refundGas = gas.value().subtract(BigInteger.valueOf(result.getGasUsed()));
|
||||
if (refundGas.compareTo(BigInteger.ZERO) == 1) {
|
||||
|
||||
this.refundGas(refundGas.intValue(), "remain gas from the internal call");
|
||||
logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ",
|
||||
refundGas.toString(), refundGas.toString());
|
||||
this.refundGas(refundGas.intValue(), "remaining gas from the internal call");
|
||||
logger.info("The remaining gas refunded, account: [ {} ], gas: [ {} ] ",
|
||||
Hex.toHexString(senderAddress), refundGas.toString());
|
||||
}
|
||||
} else {
|
||||
|
||||
this.refundGas(gas.intValue(), "remain gas from the internal call");
|
||||
this.refundGas(gas.intValue(), "remaining gas from the internal call");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ public class ProgramInvokeFactory {
|
|||
long gaslimit = block.getGasLimit();
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Program invocation: \n" +
|
||||
logger.info("Top level call: \n" +
|
||||
"address={}\n" +
|
||||
"origin={}\n" +
|
||||
"caller={}\n" +
|
||||
|
@ -144,7 +144,7 @@ public class ProgramInvokeFactory {
|
|||
|
||||
if (logger.isInfoEnabled()) {
|
||||
|
||||
logger.info("Program invocation: \n" +
|
||||
logger.info("Internal call: \n" +
|
||||
"address={}\n" +
|
||||
"origin={}\n" +
|
||||
"caller={}\n" +
|
||||
|
@ -152,27 +152,15 @@ public class ProgramInvokeFactory {
|
|||
"gasPrice={}\n" +
|
||||
"gas={}\n" +
|
||||
"callValue={}\n" +
|
||||
"data={}\n" +
|
||||
"lastHash={}\n" +
|
||||
"coinbase={}\n" +
|
||||
"timestamp={}\n" +
|
||||
"blockNumber={}\n" +
|
||||
"difficulty={}\n" +
|
||||
"gaslimit={}\n",
|
||||
Hex.toHexString(address.getData()),
|
||||
Hex.toHexString(origin.getData()),
|
||||
Hex.toHexString(caller.getData()),
|
||||
new BigInteger(balance.getData()).longValue(),
|
||||
new BigInteger(gasPrice.getData()).longValue(),
|
||||
new BigInteger(gas.getData()).longValue(),
|
||||
Hex.toHexString(callValue.getData()),
|
||||
data == null ? "null": Hex.toHexString(data),
|
||||
Hex.toHexString(lastHash.getData()),
|
||||
Hex.toHexString(coinbase.getData()),
|
||||
Hex.toHexString(timestamp.getData()),
|
||||
new BigInteger(number.getData()).longValue(),
|
||||
Hex.toHexString(difficulty.getData()),
|
||||
new BigInteger(gasLimit.getData()).longValue());
|
||||
"data={}\n",
|
||||
Hex.toHexString(address.getLast20Bytes()),
|
||||
Hex.toHexString(origin.getLast20Bytes()),
|
||||
Hex.toHexString(caller.getLast20Bytes()),
|
||||
balance.longValue(),
|
||||
gasPrice.longValue(),
|
||||
gas.longValue(),
|
||||
callValue.longValue(),
|
||||
data == null ? "null": Hex.toHexString(data));
|
||||
}
|
||||
|
||||
return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue,
|
||||
|
|
|
@ -55,6 +55,7 @@ public class VM {
|
|||
|
||||
private Logger logger = LoggerFactory.getLogger("VM");
|
||||
private static BigInteger _32_ = BigInteger.valueOf(32);
|
||||
private static String logString = "[ {} ]\t Op: [ {} ]\t Gas: [ {} ]\t Deep: [ {} ] Hint: [ {} ]";
|
||||
|
||||
public void step(Program program) {
|
||||
|
||||
|
@ -65,10 +66,14 @@ public class VM {
|
|||
|
||||
int oldMemSize = program.getMemSize();
|
||||
|
||||
String hint = "";
|
||||
long gasBefore = program.getGas().longValue();
|
||||
int stepBefore = program.getPC();
|
||||
|
||||
switch (OpCode.code(op)) {
|
||||
case SHA3:
|
||||
program.spendGas(GasCost.SHA3, OpCode.code(op).name());
|
||||
break;
|
||||
program.spendGas(GasCost.SHA3, OpCode.code(op).name());
|
||||
break;
|
||||
case SLOAD:
|
||||
program.spendGas(GasCost.SLOAD, OpCode.code(op).name());
|
||||
break;
|
||||
|
@ -89,8 +94,7 @@ public class VM {
|
|||
program.spendGas(GasCost.STEP, OpCode.code(op).name());
|
||||
break;
|
||||
}
|
||||
|
||||
String hint = "";
|
||||
|
||||
switch (OpCode.code(op)) {
|
||||
/**
|
||||
* Stop and Arithmetic Operations
|
||||
|
@ -271,7 +275,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " = " + word2.longValue();
|
||||
hint = word1.longValue() + " == " + word2.longValue();
|
||||
|
||||
if (word1.xor(word2).isZero()) {
|
||||
word1.and(DataWord.ZERO);
|
||||
|
@ -696,9 +700,10 @@ public class VM {
|
|||
DataWord inSize = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
||||
OpCode.code(op).name(), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||
.name(), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
program.createContract(value, inOffset, inSize);
|
||||
|
||||
program.step();
|
||||
|
@ -715,11 +720,11 @@ public class VM {
|
|||
DataWord outDataSize = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
||||
OpCode.code(op).name(), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||
.name(), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize,outDataOffs, outDataSize);
|
||||
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
|
||||
|
||||
program.step();
|
||||
} break;
|
||||
|
@ -744,14 +749,12 @@ public class VM {
|
|||
default:{
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
if (!OpCode.code(op).equals(CALL) && !OpCode.code(op).equals(CREATE))
|
||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
||||
OpCode.code(op).name(), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
if (!OpCode.code(op).equals(CALL) && !OpCode.code(op).equals(CREATE))
|
||||
logger.info(logString, stepBefore, OpCode.code(op).name(),
|
||||
gasBefore, program.invokeData.getCallDeep(), hint);
|
||||
|
||||
// memory gas calc
|
||||
int newMemSize = program.getMemSize();
|
||||
int memoryUsage = (newMemSize - oldMemSize) /32;
|
||||
|
|
|
@ -84,7 +84,7 @@ samples.dir = samples
|
|||
# the existing database will be
|
||||
# destroyed and all the data will be
|
||||
# downloaded from peers again
|
||||
database.reset = false
|
||||
database.reset = true
|
||||
|
||||
# place to save physical storage files
|
||||
database.dir = database
|
||||
|
@ -92,7 +92,7 @@ database.dir = database
|
|||
# this string is computed
|
||||
# to be eventually the address
|
||||
# that get the miner reward
|
||||
coinbase.secret = "monkey"
|
||||
coinbase.secret = monkey
|
||||
|
||||
# for testing purposes
|
||||
# all the state will be dumped
|
||||
|
|
|
@ -62,6 +62,66 @@ public class ByteUtilTest {
|
|||
assertArrayEquals(expected, ByteUtil.stripLeadingZeroes(test1));
|
||||
assertArrayEquals(expected, ByteUtil.stripLeadingZeroes(test2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchingNibbleLength1() {
|
||||
// a larger than b
|
||||
byte[] a = new byte[] { 0x00, 0x01 };
|
||||
byte[] b = new byte[] { 0x00 };
|
||||
int result = ByteUtil.matchingNibbleLength(a, b);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
@Test
|
||||
public void testMatchingNibbleLength2() {
|
||||
// b larger than a
|
||||
byte[] a = new byte[] { 0x00 };
|
||||
byte[] b = new byte[] { 0x00, 0x01 };
|
||||
int result = ByteUtil.matchingNibbleLength(a, b);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchingNibbleLength3() {
|
||||
// a and b the same length equal
|
||||
byte[] a = new byte[] { 0x00 };
|
||||
byte[] b = new byte[] { 0x00 };
|
||||
int result = ByteUtil.matchingNibbleLength(a, b);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchingNibbleLength4() {
|
||||
// a and b the same length not equal
|
||||
byte[] a = new byte[] { 0x01 };
|
||||
byte[] b = new byte[] { 0x00 };
|
||||
int result = ByteUtil.matchingNibbleLength(a, b);
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testMatchingNibbleLength5() {
|
||||
// a == null
|
||||
byte[] a = null;
|
||||
byte[] b = new byte[] { 0x00 };
|
||||
ByteUtil.matchingNibbleLength(a, b);
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testMatchingNibbleLength6() {
|
||||
// b == null
|
||||
byte[] a = new byte[] { 0x00 };
|
||||
byte[] b = null;
|
||||
ByteUtil.matchingNibbleLength(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchingNibbleLength7() {
|
||||
// a or b is empty
|
||||
byte[] a = new byte[0];
|
||||
byte[] b = new byte[] { 0x00 };
|
||||
int result = ByteUtil.matchingNibbleLength(a, b);
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test shows the difference between iterating over,
|
||||
|
|
|
@ -73,4 +73,4 @@ database.reset = true
|
|||
# this string is computed
|
||||
# to be eventually the address
|
||||
# that get the miner reward
|
||||
coinbase.secret = "monkey"
|
||||
coinbase.secret = monkey
|
Loading…
Reference in New Issue