mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-21 16:08:07 +00:00
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);
|
timestamp, extraData, nonce);
|
||||||
this.txsState = new Trie(null);
|
this.txsState = new Trie(null);
|
||||||
|
|
||||||
byte[] stateRoot = WorldManager.getInstance().getRepository().getRootHash();
|
|
||||||
this.header.setStateRoot(stateRoot);
|
|
||||||
|
|
||||||
this.header.setTxTrieRoot(txsState.getRootHash());
|
this.header.setTxTrieRoot(txsState.getRootHash());
|
||||||
this.transactionsList = transactionsList;
|
this.transactionsList = transactionsList;
|
||||||
this.uncleList = uncleList;
|
this.uncleList = uncleList;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
|
import org.ethereum.db.Repository;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.util.RLP;
|
import org.ethereum.util.RLP;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -64,17 +65,18 @@ public class Genesis extends Block {
|
|||||||
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
||||||
EXTRA_DATA, NONCE, null, null);
|
EXTRA_DATA, NONCE, null, null);
|
||||||
|
|
||||||
|
Repository repository = WorldManager.getInstance().getRepository();
|
||||||
// The proof-of-concept series include a development premine, making the state root hash
|
// 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.
|
// some value stateRoot. The latest documentation should be consulted for the value of the state root.
|
||||||
for (String address : premine) {
|
for (String address : premine) {
|
||||||
WorldManager.getInstance().getRepository().createAccount(Hex.decode(address));
|
repository.createAccount(Hex.decode(address));
|
||||||
WorldManager.getInstance().getRepository().addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) );
|
repository.addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) );
|
||||||
}
|
}
|
||||||
this.setStateRoot(WorldManager.getInstance().getRepository().getRootHash());
|
setStateRoot(repository.getWorldState().getRootHash());
|
||||||
WorldManager.getInstance().getRepository().dumpState(0, 0, null);
|
repository.dumpState(0, 0, null);
|
||||||
|
|
||||||
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
logger.info("Genesis-hash: {}", Hex.toHexString(this.getHash()));
|
||||||
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
logger.info("Genesis-stateRoot: {}", Hex.toHexString(this.getStateRoot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block getInstance() {
|
public static Block getInstance() {
|
||||||
|
@ -7,18 +7,16 @@ import java.security.MessageDigest;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import org.ethereum.db.ByteArrayWrapper;
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
import org.ethereum.util.ByteUtil;
|
|
||||||
import org.ethereum.util.RLP;
|
import org.ethereum.util.RLP;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import org.ethereum.util.LRUMap;
|
import org.ethereum.util.LRUMap;
|
||||||
|
|
||||||
public class HashUtil {
|
public class HashUtil {
|
||||||
|
|
||||||
private static final int MAX_ENTRIES = 1000; // Should contain most commonly hashed values
|
private static final int MAX_ENTRIES = 100; // Should contain most commonly hashed values
|
||||||
private static LRUMap<ByteArrayWrapper, byte[]> sha3Cache = new LRUMap<>(0, MAX_ENTRIES);
|
private static LRUMap<ByteArrayWrapper, byte[]> sha3Cache = new LRUMap<>(0, MAX_ENTRIES);
|
||||||
public static final byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]);
|
public static final byte[] EMPTY_DATA_HASH = Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||||
|
|
||||||
private static final MessageDigest sha256digest;
|
private static final MessageDigest sha256digest;
|
||||||
|
|
||||||
@ -36,9 +34,10 @@ public class HashUtil {
|
|||||||
|
|
||||||
public static byte[] sha3(byte[] input) {
|
public static byte[] sha3(byte[] input) {
|
||||||
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
|
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
|
||||||
if(sha3Cache.keySet().contains(inputByteArray))
|
byte[] result = sha3Cache.get(inputByteArray);
|
||||||
return sha3Cache.get(inputByteArray);
|
if(result != null)
|
||||||
byte[] result = SHA3Helper.sha3(input);
|
return result;
|
||||||
|
result = SHA3Helper.sha3(input);
|
||||||
sha3Cache.put(inputByteArray, result);
|
sha3Cache.put(inputByteArray, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -62,7 +61,7 @@ public class HashUtil {
|
|||||||
|
|
||||||
byte[] encSender = RLP.encodeElement(addr);
|
byte[] encSender = RLP.encodeElement(addr);
|
||||||
byte[] encNonce = RLP.encodeElement(nonce);
|
byte[] encNonce = RLP.encodeElement(nonce);
|
||||||
byte[] newAddress = HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
|
byte[] newAddress = sha3omit12(RLP.encodeList(encSender, encNonce));
|
||||||
|
|
||||||
return newAddress;
|
return newAddress;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,11 @@ public class ContractDetails {
|
|||||||
|
|
||||||
public byte[] getStorageHash() {
|
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();
|
return storageTrie.getRootHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,12 +153,6 @@ public class ContractDetails {
|
|||||||
values[i] = RLP.encodeElement(value.getNoLeadZeroesData());
|
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[] rlpKeysList = RLP.encodeList(keys);
|
||||||
byte[] rlpValuesList = RLP.encodeList(values);
|
byte[] rlpValuesList = RLP.encodeList(values);
|
||||||
byte[] rlpCode = RLP.encodeElement(code);
|
byte[] rlpCode = RLP.encodeElement(code);
|
||||||
|
@ -7,7 +7,6 @@ import org.ethereum.core.Blockchain;
|
|||||||
import org.ethereum.core.Genesis;
|
import org.ethereum.core.Genesis;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.json.JSONHelper;
|
import org.ethereum.json.JSONHelper;
|
||||||
import org.ethereum.manager.WorldManager;
|
|
||||||
import org.ethereum.trie.TrackTrie;
|
import org.ethereum.trie.TrackTrie;
|
||||||
import org.ethereum.trie.Trie;
|
import org.ethereum.trie.Trie;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
@ -181,9 +180,9 @@ public class Repository {
|
|||||||
|
|
||||||
byte[] accountStateRLP = accountStateDB.get(addr);
|
byte[] accountStateRLP = accountStateDB.get(addr);
|
||||||
|
|
||||||
if (accountStateRLP.length == 0) {
|
if (accountStateRLP.length == 0)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
AccountState state = new AccountState(accountStateRLP);
|
AccountState state = new AccountState(accountStateRLP);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -197,9 +196,8 @@ public class Repository {
|
|||||||
|
|
||||||
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
|
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
|
||||||
|
|
||||||
if (accountDetailsRLP == null) {
|
if (accountDetailsRLP == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP));
|
logger.debug("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP));
|
||||||
@ -214,9 +212,8 @@ public class Repository {
|
|||||||
|
|
||||||
AccountState state = getAccountState(addr);
|
AccountState state = getAccountState(addr);
|
||||||
|
|
||||||
if (state == null){
|
if (state == null)
|
||||||
state = createAccount(addr);
|
state = createAccount(addr);
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger newBalance = state.addToBalance(value);
|
BigInteger newBalance = state.addToBalance(value);
|
||||||
|
|
||||||
@ -347,10 +344,6 @@ public class Repository {
|
|||||||
contractDetailsDB.delete(addr);
|
contractDetailsDB.delete(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRootHash() {
|
|
||||||
return this.worldState.getRootHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ByteArrayWrapper> dumpKeys(){
|
public List<ByteArrayWrapper> dumpKeys(){
|
||||||
return stateDB.dumpKeys();
|
return stateDB.dumpKeys();
|
||||||
}
|
}
|
||||||
@ -413,7 +406,7 @@ public class Repository {
|
|||||||
bw.write("\n");
|
bw.write("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
String rootHash = Hex.toHexString(WorldManager.getInstance().getRepository().getRootHash());
|
String rootHash = Hex.toHexString(this.getWorldState().getRootHash());
|
||||||
bw.write(
|
bw.write(
|
||||||
String.format(" => Global State Root: [ %s ]", rootHash)
|
String.format(" => Global State Root: [ %s ]", rootHash)
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ package org.ethereum.trie;
|
|||||||
import static java.util.Arrays.copyOfRange;
|
import static java.util.Arrays.copyOfRange;
|
||||||
import static org.spongycastle.util.Arrays.concatenate;
|
import static org.spongycastle.util.Arrays.concatenate;
|
||||||
import static org.ethereum.util.CompactEncoder.*;
|
import static org.ethereum.util.CompactEncoder.*;
|
||||||
|
import static org.ethereum.util.ByteUtil.matchingNibbleLength;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -399,15 +400,6 @@ public class Trie implements TrieFacade {
|
|||||||
* Utility functions *
|
* 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
|
// Created an array of empty elements of requred length
|
||||||
private Object[] emptyStringSlice(int l) {
|
private Object[] emptyStringSlice(int l) {
|
||||||
Object[] slice = new Object[l];
|
Object[] slice = new Object[l];
|
||||||
@ -418,7 +410,6 @@ public class Trie implements TrieFacade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRootHash() {
|
public byte[] getRootHash() {
|
||||||
Object root = this.getRoot();
|
|
||||||
if (root == null
|
if (root == null
|
||||||
|| (root instanceof byte[] && ((byte[]) root).length == 0)
|
|| (root instanceof byte[] && ((byte[]) root).length == 0)
|
||||||
|| (root instanceof String && "".equals((String) root))) {
|
|| (root instanceof String && "".equals((String) root))) {
|
||||||
|
@ -60,6 +60,24 @@ public class ByteUtil {
|
|||||||
return data;
|
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) {
|
public static byte[] longToBytes(long l) {
|
||||||
return ByteBuffer.allocate(8).putLong(l).array();
|
return ByteBuffer.allocate(8).putLong(l).array();
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package org.ethereum.util;
|
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.copyOf;
|
||||||
|
import static java.util.Arrays.copyOfRange;
|
||||||
|
|
||||||
import static org.ethereum.util.ByteUtil.appendByte;
|
import static org.ethereum.util.ByteUtil.appendByte;
|
||||||
import static org.spongycastle.util.Arrays.concatenate;
|
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
|
* Compact encoding of hex sequence with optional terminator
|
||||||
@ -103,13 +104,12 @@ public class CompactEncoder {
|
|||||||
* @return array with each individual nibble adding a terminator at the end
|
* @return array with each individual nibble adding a terminator at the end
|
||||||
*/
|
*/
|
||||||
public static byte[] binToNibbles(byte[] str) {
|
public static byte[] binToNibbles(byte[] str) {
|
||||||
byte[] hexSlice = new byte[0];
|
byte[] hexEncoded = encode(str);
|
||||||
String hexEncoded = toHexString(str);
|
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length + 1);
|
||||||
for (char value : hexEncoded.toCharArray()) {
|
for (byte b : hexEncoded) {
|
||||||
hexSlice = appendByte(hexSlice, (byte) hexBase.indexOf(value));
|
slice.put((byte)hexBase.indexOf(b));
|
||||||
}
|
}
|
||||||
hexSlice = appendByte(hexSlice, TERMINATOR);
|
slice.put(TERMINATOR);
|
||||||
|
return slice.array();
|
||||||
return hexSlice;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,7 @@ public class Program {
|
|||||||
this.refundGas(refundGas, "remain gas from the internal call");
|
this.refundGas(refundGas, "remain gas from the internal call");
|
||||||
if (logger.isInfoEnabled()){
|
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()),
|
Hex.toHexString(this.getOwnerAddress().getLast20Bytes()),
|
||||||
refundGas);
|
refundGas);
|
||||||
}
|
}
|
||||||
@ -317,7 +317,7 @@ public class Program {
|
|||||||
* That method implement internal calls
|
* That method implement internal calls
|
||||||
* and code invocations
|
* 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 toAddressDW - address to call
|
||||||
* @param endowmentValue - the value that can be transfer along with the code execution
|
* @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
|
* @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()));
|
BigInteger refundGas = gas.value().subtract(BigInteger.valueOf(result.getGasUsed()));
|
||||||
if (refundGas.compareTo(BigInteger.ZERO) == 1) {
|
if (refundGas.compareTo(BigInteger.ZERO) == 1) {
|
||||||
|
|
||||||
this.refundGas(refundGas.intValue(), "remain gas from the internal call");
|
this.refundGas(refundGas.intValue(), "remaining gas from the internal call");
|
||||||
logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ",
|
logger.info("The remaining gas refunded, account: [ {} ], gas: [ {} ] ",
|
||||||
refundGas.toString(), refundGas.toString());
|
Hex.toHexString(senderAddress), refundGas.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} 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();
|
long gaslimit = block.getGasLimit();
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info("Program invocation: \n" +
|
logger.info("Top level call: \n" +
|
||||||
"address={}\n" +
|
"address={}\n" +
|
||||||
"origin={}\n" +
|
"origin={}\n" +
|
||||||
"caller={}\n" +
|
"caller={}\n" +
|
||||||
@ -144,7 +144,7 @@ public class ProgramInvokeFactory {
|
|||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
|
|
||||||
logger.info("Program invocation: \n" +
|
logger.info("Internal call: \n" +
|
||||||
"address={}\n" +
|
"address={}\n" +
|
||||||
"origin={}\n" +
|
"origin={}\n" +
|
||||||
"caller={}\n" +
|
"caller={}\n" +
|
||||||
@ -152,27 +152,15 @@ public class ProgramInvokeFactory {
|
|||||||
"gasPrice={}\n" +
|
"gasPrice={}\n" +
|
||||||
"gas={}\n" +
|
"gas={}\n" +
|
||||||
"callValue={}\n" +
|
"callValue={}\n" +
|
||||||
"data={}\n" +
|
"data={}\n",
|
||||||
"lastHash={}\n" +
|
Hex.toHexString(address.getLast20Bytes()),
|
||||||
"coinbase={}\n" +
|
Hex.toHexString(origin.getLast20Bytes()),
|
||||||
"timestamp={}\n" +
|
Hex.toHexString(caller.getLast20Bytes()),
|
||||||
"blockNumber={}\n" +
|
balance.longValue(),
|
||||||
"difficulty={}\n" +
|
gasPrice.longValue(),
|
||||||
"gaslimit={}\n",
|
gas.longValue(),
|
||||||
Hex.toHexString(address.getData()),
|
callValue.longValue(),
|
||||||
Hex.toHexString(origin.getData()),
|
data == null ? "null": Hex.toHexString(data));
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue,
|
return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue,
|
||||||
|
@ -55,6 +55,7 @@ public class VM {
|
|||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger("VM");
|
private Logger logger = LoggerFactory.getLogger("VM");
|
||||||
private static BigInteger _32_ = BigInteger.valueOf(32);
|
private static BigInteger _32_ = BigInteger.valueOf(32);
|
||||||
|
private static String logString = "[ {} ]\t Op: [ {} ]\t Gas: [ {} ]\t Deep: [ {} ] Hint: [ {} ]";
|
||||||
|
|
||||||
public void step(Program program) {
|
public void step(Program program) {
|
||||||
|
|
||||||
@ -65,6 +66,10 @@ public class VM {
|
|||||||
|
|
||||||
int oldMemSize = program.getMemSize();
|
int oldMemSize = program.getMemSize();
|
||||||
|
|
||||||
|
String hint = "";
|
||||||
|
long gasBefore = program.getGas().longValue();
|
||||||
|
int stepBefore = program.getPC();
|
||||||
|
|
||||||
switch (OpCode.code(op)) {
|
switch (OpCode.code(op)) {
|
||||||
case SHA3:
|
case SHA3:
|
||||||
program.spendGas(GasCost.SHA3, OpCode.code(op).name());
|
program.spendGas(GasCost.SHA3, OpCode.code(op).name());
|
||||||
@ -90,7 +95,6 @@ public class VM {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String hint = "";
|
|
||||||
switch (OpCode.code(op)) {
|
switch (OpCode.code(op)) {
|
||||||
/**
|
/**
|
||||||
* Stop and Arithmetic Operations
|
* Stop and Arithmetic Operations
|
||||||
@ -271,7 +275,7 @@ public class VM {
|
|||||||
DataWord word2 = program.stackPop();
|
DataWord word2 = program.stackPop();
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
hint = word1.longValue() + " = " + word2.longValue();
|
hint = word1.longValue() + " == " + word2.longValue();
|
||||||
|
|
||||||
if (word1.xor(word2).isZero()) {
|
if (word1.xor(word2).isZero()) {
|
||||||
word1.and(DataWord.ZERO);
|
word1.and(DataWord.ZERO);
|
||||||
@ -696,9 +700,10 @@ public class VM {
|
|||||||
DataWord inSize = program.stackPop();
|
DataWord inSize = program.stackPop();
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||||
OpCode.code(op).name(), program.getGas().longValue(),
|
.name(), program.getGas().longValue(),
|
||||||
program.invokeData.getCallDeep(), hint);
|
program.invokeData.getCallDeep(), hint);
|
||||||
|
|
||||||
program.createContract(value, inOffset, inSize);
|
program.createContract(value, inOffset, inSize);
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
@ -715,8 +720,8 @@ public class VM {
|
|||||||
DataWord outDataSize = program.stackPop();
|
DataWord outDataSize = program.stackPop();
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||||
OpCode.code(op).name(), program.getGas().longValue(),
|
.name(), program.getGas().longValue(),
|
||||||
program.invokeData.getCallDeep(), hint);
|
program.invokeData.getCallDeep(), hint);
|
||||||
|
|
||||||
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
|
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
|
||||||
@ -747,10 +752,8 @@ public class VM {
|
|||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
if (!OpCode.code(op).equals(CALL) && !OpCode.code(op).equals(CREATE))
|
if (!OpCode.code(op).equals(CALL) && !OpCode.code(op).equals(CREATE))
|
||||||
logger.info("[ {} ] Op: [ {} ] Gas: [ {} ] Deep: [ {} ] Hint: [ {} ]" ,program.getPC(),
|
logger.info(logString, stepBefore, OpCode.code(op).name(),
|
||||||
OpCode.code(op).name(), program.getGas().longValue(),
|
gasBefore, program.invokeData.getCallDeep(), hint);
|
||||||
program.invokeData.getCallDeep(), hint);
|
|
||||||
|
|
||||||
|
|
||||||
// memory gas calc
|
// memory gas calc
|
||||||
int newMemSize = program.getMemSize();
|
int newMemSize = program.getMemSize();
|
||||||
|
@ -84,7 +84,7 @@ samples.dir = samples
|
|||||||
# the existing database will be
|
# the existing database will be
|
||||||
# destroyed and all the data will be
|
# destroyed and all the data will be
|
||||||
# downloaded from peers again
|
# downloaded from peers again
|
||||||
database.reset = false
|
database.reset = true
|
||||||
|
|
||||||
# place to save physical storage files
|
# place to save physical storage files
|
||||||
database.dir = database
|
database.dir = database
|
||||||
@ -92,7 +92,7 @@ database.dir = database
|
|||||||
# this string is computed
|
# this string is computed
|
||||||
# to be eventually the address
|
# to be eventually the address
|
||||||
# that get the miner reward
|
# that get the miner reward
|
||||||
coinbase.secret = "monkey"
|
coinbase.secret = monkey
|
||||||
|
|
||||||
# for testing purposes
|
# for testing purposes
|
||||||
# all the state will be dumped
|
# all the state will be dumped
|
||||||
|
@ -63,6 +63,66 @@ public class ByteUtilTest {
|
|||||||
assertArrayEquals(expected, ByteUtil.stripLeadingZeroes(test2));
|
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,
|
* This test shows the difference between iterating over,
|
||||||
* and comparing byte[] vs BigInteger value.
|
* and comparing byte[] vs BigInteger value.
|
||||||
|
@ -73,4 +73,4 @@ database.reset = true
|
|||||||
# this string is computed
|
# this string is computed
|
||||||
# to be eventually the address
|
# to be eventually the address
|
||||||
# that get the miner reward
|
# that get the miner reward
|
||||||
coinbase.secret = "monkey"
|
coinbase.secret = monkey
|
Loading…
x
Reference in New Issue
Block a user