Add VM dumptrace in pretty format

This commit is contained in:
nicksavers 2014-09-01 20:59:06 +02:00
parent 45925d0791
commit e106d2fdc7
16 changed files with 388 additions and 310 deletions

View File

@ -29,6 +29,7 @@ public class SystemProperties {
private static Boolean DEFAULT_DB_RESET = false;
private static Boolean DEFAULT_DUMP_FULL = false;
private static String DEFAULT_DUMP_DIR = "dmp";
private static String DEFAULT_DUMP_STYLE = "standard+";
private static Integer DEFAULT_VMTRACE_BLOCK = 0;
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
@ -152,11 +153,17 @@ public class SystemProperties {
return prop.getProperty("dump.dir");
}
public String dumpStyle() {
if(prop.isEmpty()) return DEFAULT_DUMP_STYLE;
return prop.getProperty("dump.style");
}
public Integer dumpBlock() {
if(prop.isEmpty()) return DEFAULT_VMTRACE_BLOCK;
return Integer.parseInt(prop.getProperty("dump.block"));
}
public String databaseDir() {
if(prop.isEmpty()) return DEFAULT_DATABASE_DIR;
return prop.getProperty("database.dir");

View File

@ -32,7 +32,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public class Block {
private static Logger logger = LoggerFactory.getLogger("block");
private static final Logger logger = LoggerFactory.getLogger("block");
/* A scalar value equal to the mininum limit of gas expenditure per block */
private static long MIN_GAS_LIMIT = 125000L;

View File

@ -96,8 +96,8 @@ public class Blockchain {
if (block == null)
return;
if (block.getNumber() == 12301)
logger.debug("Block #12301");
if (block.getNumber() == 12390)
logger.debug("Block #12390");
// if it is the first block to add
// make sure the parent is genesis
@ -153,11 +153,14 @@ public class Blockchain {
for (TransactionReceipt txr : block.getTxReceiptList()) {
stateLogger.debug("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i);
totalGasUsed += applyTransaction(block, txr.getTransaction());
if(!Arrays.equals(this.repository.getWorldState().getRootHash(), txr.getPostTxState()))
stateLogger.warn("TX: STATE CONFLICT {}..: {}", Hex.toHexString(txr.getTransaction().getHash()).substring(0, 8),
Hex.toHexString(this.repository.getWorldState().getRootHash()));
if(block.getNumber() >= CONFIG.traceStartBlock())
repository.dumpState(block, totalGasUsed, i++, txr.getTransaction().getHash());
if(!Arrays.equals(this.repository.getWorldState().getRootHash(), txr.getPostTxState())) {
stateLogger.warn("TX: STATE CONFLICT {}..: {}", Hex.toHexString(txr.getTransaction().getHash()).substring(0, 8),
Hex.toHexString(this.repository.getWorldState().getRootHash()));
// repository.close();
// System.exit(-1); // Don't continue
}
}
this.addReward(block);

View File

@ -1,12 +1,13 @@
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 static org.ethereum.util.CompactEncoder.binToNibbles;
import static org.ethereum.util.CompactEncoder.packNibbles;
import static org.ethereum.util.CompactEncoder.unpackToNibbles;
import static org.spongycastle.util.Arrays.concatenate;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.ByteArrayWrapper;
@ -253,11 +254,9 @@ public class Trie implements TrieFacade {
}
if (matchingLength == 0) {
// End of the chain, return
return newHash;
} else {
Object[] newNode = new Object[] { packNibbles(copyOfRange(key, 0, matchingLength)), newHash};
return this.putToCache(newNode);
}
@ -300,7 +299,6 @@ public class Trie implements TrieFacade {
} else {
newNode = new Object[] {currentNode.get(0).asString(), hash};
}
return this.putToCache(newNode);
} else {
return node;
@ -337,7 +335,6 @@ public class Trie implements TrieFacade {
} else {
newNode = itemList;
}
return this.putToCache(newNode);
}
}
@ -449,7 +446,7 @@ public class Trie implements TrieFacade {
* safe, the tree should not be modified during the
* cleaning process.
*/
public void cleanCacheGarbage(){
public void cleanCacheGarbage() {
CollectFullSetOfNodes collectAction = new CollectFullSetOfNodes();
long startTime = System.currentTimeMillis();
@ -460,15 +457,13 @@ public class Trie implements TrieFacade {
Map<ByteArrayWrapper, Node> nodes = this.getCache().getNodes();
Set<ByteArrayWrapper> toRemoveSet = new HashSet<>();
for (ByteArrayWrapper key : nodes.keySet()){
if (!hashSet.contains(key.getData())){
for (ByteArrayWrapper key : nodes.keySet()) {
if (!hashSet.contains(key.getData())) {
toRemoveSet.add(key);
}
}
for (ByteArrayWrapper key : toRemoveSet){
for (ByteArrayWrapper key : toRemoveSet) {
this.getCache().delete(key.getData());
@ -476,29 +471,23 @@ public class Trie implements TrieFacade {
logger.trace("Garbage collected node: [ {} ]",
Hex.toHexString( key.getData() ));
}
logger.info("Garbage collected node list, size: [ {} ]", toRemoveSet.size());
logger.info("Garbage collection time: [ {}ms ]", System.currentTimeMillis() - startTime);
}
public void scanTree(byte[] hash , ScanAction scanAction){
public void scanTree(byte[] hash, ScanAction scanAction) {
Value node = this.getCache().get(hash);
if (node == null) return ;
if (node.isList()){
if (node == null) return;
if (node.isList()) {
List<Object> siblings = node.asList();
if (siblings.size() == 2){
if (siblings.size() == PAIR_SIZE) {
Value val = new Value(siblings.get(1));
if (val.isHashCode())
scanTree(val.asBytes(), scanAction);
} else {
for (int j = 0; j < 17; ++j){
for (int j = 0; j < LIST_SIZE; ++j) {
Value val = new Value(siblings.get(j));
if (val.isHashCode())
scanTree(val.asBytes(), scanAction);
@ -508,26 +497,21 @@ public class Trie implements TrieFacade {
}
}
public String getTrieDump(){
public String getTrieDump() {
String root = "";
TraceAllNodes traceAction = new TraceAllNodes();
this.scanTree(this.getRootHash(), traceAction);
if (this.getRoot() instanceof Value){
if (this.getRoot() instanceof Value) {
root = "root: " + Hex.toHexString(getRootHash()) + " => " + this.getRoot() + "\n";
} else{
} else {
root = "root: " + Hex.toHexString(getRootHash()) + "\n";
}
return root + traceAction.getOutput();
}
public interface ScanAction{
public interface ScanAction {
public void doOnNode(byte[] hash, Value node);
}
}

View File

@ -116,6 +116,24 @@ public class ByteUtil {
return 0;
return new BigInteger(1, b).intValue();
}
/**
* Turn nibbles to a pretty looking output string
*
* Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45'
*
* @param nibbles - getting byte of data [ 04 ] and turning
* it to a '\x04' representation
* @return pretty string of nibbles
*/
public static String nibblesToPrettyString(byte[] nibbles){
StringBuffer buffer = new StringBuffer();
for (byte nibble : nibbles) {
String nibleString = Utils.oneByteToHexString(nibble);
buffer.append("\\x" + nibleString);
}
return buffer.toString();
}
/**
* Calculate the number of bytes need

View File

@ -51,25 +51,24 @@ public class CompactEncoder {
private final static byte TERMINATOR = 16;
private final static Map<Character, Byte> hexMap = new HashMap<>();
static {
hexMap.put('0', (byte)0);
hexMap.put('1', (byte)1);
hexMap.put('2', (byte)2);
hexMap.put('3', (byte)3);
hexMap.put('4', (byte)4);
hexMap.put('5', (byte)5);
hexMap.put('6', (byte)6);
hexMap.put('7', (byte)7);
hexMap.put('8', (byte)8);
hexMap.put('9', (byte)9);
hexMap.put('a', (byte)10);
hexMap.put('b', (byte)11);
hexMap.put('c', (byte)12);
hexMap.put('d', (byte)13);
hexMap.put('e', (byte)14);
hexMap.put('f', (byte)15);
hexMap.put('0', (byte)0x0);
hexMap.put('1', (byte)0x1);
hexMap.put('2', (byte)0x2);
hexMap.put('3', (byte)0x3);
hexMap.put('4', (byte)0x4);
hexMap.put('5', (byte)0x5);
hexMap.put('6', (byte)0x6);
hexMap.put('7', (byte)0x7);
hexMap.put('8', (byte)0x8);
hexMap.put('9', (byte)0x9);
hexMap.put('a', (byte)0xa);
hexMap.put('b', (byte)0xb);
hexMap.put('c', (byte)0xc);
hexMap.put('d', (byte)0xd);
hexMap.put('e', (byte)0xe);
hexMap.put('f', (byte)0xf);
}
/**
* Pack nibbles to binary
*
@ -94,7 +93,7 @@ public class CompactEncoder {
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < nibbles.length; i += 2) {
buffer.write( 16*nibbles[i] + nibbles[i+1] );
buffer.write(16*nibbles[i] + nibbles[i+1]);
}
return buffer.toByteArray();
}
@ -140,27 +139,6 @@ public class CompactEncoder {
for (byte b : hexEncoded) {
slice.put(hexMap.get((char)b));
}
return slice.array();
}
/**
* turn nibbles to a nice good looking output string
*
* @param nibbles - getting byte of data [ 04 ] and turning
* it to a '\x04' representation
* @return
*/
public static String nibblesToPrettyString(byte[] nibbles){
StringBuffer buffer = new StringBuffer();
for (byte nibble : nibbles){
String nibleString = Utils.oneByteToHexString(nibble);
buffer.append("\\x" + nibleString);
}
return buffer.toString();
}
}

View File

@ -1,6 +1,5 @@
package org.ethereum.util;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
@ -155,7 +154,6 @@ public class Value {
}
for (int i = 0; i < data.length; ++i){
if (data[i] > 32 && data[i] < 126) ++readableChars;
}
@ -171,14 +169,14 @@ public class Value {
int hexChars = 0;
byte[] data = (byte[])value;
for (int i = 0; i < data.length; ++i){
for (int i = 0; i < data.length; ++i) {
if ((data[i] >= 48 && data[i] <= 57) ||
(data[i] >= 97 && data[i] <= 102)
) ++hexChars;
}
if ((data[i] >= 48 && data[i] <= 57)
|| (data[i] >= 97 && data[i] <= 102))
++hexChars;
}
if ((double)hexChars / (double)data.length > 0.9)
if ((double) hexChars / (double) data.length > 0.9)
return true;
else
return false;
@ -212,23 +210,23 @@ public class Value {
return 0;
}
public String toString(){
public String toString() {
StringBuffer buffer = new StringBuffer();
if (isList()){
if (isList()) {
Object[] list = (Object[])value;
Object[] list = (Object[]) value;
// special case - key/value node
if (list.length == 2){
if (list.length == 2) {
buffer.append("[ ");
Value key = new Value(list[0]);
byte[] keyNibbles = CompactEncoder.binToNibblesNoTerminator(key.asBytes());
String keyString = CompactEncoder.nibblesToPrettyString(keyNibbles);
String keyString = ByteUtil.nibblesToPrettyString(keyNibbles);
buffer.append(keyString);
buffer.append(",");
@ -239,83 +237,60 @@ public class Value {
buffer.append(" ]");
return buffer.toString();
}
buffer.append(" [");
for (int i = 0; i < list.length; ++i){
Value val = new Value(list[i]);
if (val.isString() || val.isEmpty()){
buffer.append("'").
append(val.toString())
.append("'");
buffer.append("'").append(val.toString()).append("'");
} else {
buffer.append(val.toString());
}
if (i < list.length - 1)
buffer.append(", ");
}
buffer.append("] ");
return buffer.toString();
} else if (isEmpty()){
} else if (isEmpty()) {
return "";
} else if (isBytes()){
} else if (isBytes()) {
StringBuffer output = new StringBuffer();
if (isHashCode()) {
output.append(Hex.toHexString(asBytes()));
}else if (isReadbleString()){
} else if (isReadbleString()) {
output.append("'");
for (byte oneByte : asBytes()){
if (oneByte < 16){
for (byte oneByte : asBytes()) {
if (oneByte < 16) {
output.append("\\x").append(Utils.oneByteToHexString(oneByte));
} else {
output.append( Character.valueOf((char)oneByte) );
}
}
output.append("'");
return output.toString();
}
return Hex.toHexString(this.asBytes());
} else if (isString()){
return asString();
}
return "what the fuck";
return "Unexpected type";
}
public int countYourBranchNodes(){
if (this.isList()){
List<Object> objList = this.asList();
int i = 0;
for (Object obj : objList){
i += (new Value(obj)).countYourBranchNodes();
}
return i;
} else if (this.isBytes()){
this.asBytes();
}
return 0;
}
}

View File

@ -265,6 +265,11 @@ public class DataWord implements Comparable<DataWord> {
public String toString() {
return Hex.toHexString(data);
}
public String shortHex() {
String hexValue = Hex.toHexString(getNoLeadZeroesData()).toUpperCase();
return "0x" + hexValue.replaceFirst("^0+(?!$)", "");
}
public DataWord clone() {
return new DataWord(Arrays.clone(data));

View File

@ -11,7 +11,10 @@ import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
/**
@ -185,7 +188,7 @@ public class Program {
int offset = offsetData.intValue();
int size = sizeData.intValue();
byte[] chunk = new byte[size];
allocateMemory(offset, chunk);
allocateMemory(offset, new byte[size]);
if (memory != null) {
if (memory.limit() < offset + size) size = memory.limit() - offset;
@ -424,8 +427,12 @@ public class Program {
if (retSize > allocSize) {
byte[] outArray = Arrays.copyOf(buffer.array(), allocSize);
this.memorySave(outArray, buffer.array());
} else {
} else if (retSize == 0 || retSize == allocSize){
this.memorySave(outDataOffs.getData(), buffer.array());
} else {
byte[] outArray = new byte[allocSize];
System.arraycopy(buffer.array(), 0, outArray, 0, retSize);
this.memorySave(outDataOffs.getData(), outArray);
}
}
}
@ -562,6 +569,34 @@ public class Program {
public void setRuntimeFailure(RuntimeException e) {
result.setException(e);
}
public String memoryToString() {
StringBuilder memoryData = new StringBuilder();
StringBuilder firstLine = new StringBuilder();
StringBuilder secondLine = new StringBuilder();
for (int i = 0; memory != null && i < memory.limit(); ++i) {
byte value = memory.get(i);
// Check if value is ASCII
// (should be until 0x7e - but using 0x7f
// to be compatible with cpp-ethereum)
// See: https://github.com/ethereum/cpp-ethereum/issues/299
String character = ((byte)0x20 <= value && value <= (byte)0x7f) ? new String(new byte[]{value}) : "?";
firstLine.append(character).append("");
secondLine.append(Utils.oneByteToHexString(value)).append(" ");
if ((i + 1) % 8 == 0) {
String tmp = String.format("%4s", Integer.toString(i - 7, 16)).replace(" ", "0");
memoryData.append("").append(tmp).append(" ");
memoryData.append(firstLine).append(" ");
memoryData.append(secondLine);
if (i+1 < memory.limit()) memoryData.append("\n");
firstLine.setLength(0);
secondLine.setLength(0);
}
}
return memoryData.toString();
}
public void fullTrace() {
@ -577,7 +612,9 @@ public class Program {
ContractDetails contractDetails = this.result.getRepository().
getContractDetails(this.programAddress.getLast20Bytes());
StringBuilder storageData = new StringBuilder();
for (DataWord key : contractDetails.getStorage().keySet()) {
List<DataWord> storageKeys = new ArrayList<>(contractDetails.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
for (DataWord key : storageKeys) {
storageData.append(" ").append(key).append(" -> ").
append(contractDetails.getStorage().get(key)).append("\n");
}
@ -625,8 +662,6 @@ public class Program {
invokeData.getGas().longValue(),
getGas().longValue());
StringBuilder globalOutput = new StringBuilder("\n");
if (stackData.length() > 0) stackData.append("\n");

View File

@ -64,12 +64,17 @@ public class VM {
private Logger logger = LoggerFactory.getLogger("VM");
private Logger dumpLogger = LoggerFactory.getLogger("dump");
private static BigInteger _32_ = BigInteger.valueOf(32);
private static String logString = "[{}]\t Op: [{}] Gas: [{}]\t Deep: [{}] Hint: [{}]";
private static String logString = "[{}]\t Op: [{}] Gas: [{}] Deep: [{}] Hint: [{}]";
private static BigInteger MAX_GAS = BigInteger.valueOf(Long.MAX_VALUE);
/* Keeps track of the number of steps performed in this VM */
private int vmCounter = 0;
public void step(Program program) {
program.fullTrace();
try {
OpCode op = OpCode.code(program.getCurrentOp());
program.setLastOp(op.val());
@ -79,92 +84,96 @@ public class VM {
Stack<DataWord> stack = program.getStack();
String hint = "";
long callGas = 0, memWords = 0; // parameters for logging
long gasCost = GasCost.STEP;
long gasBefore = program.getGas().longValue();
int stepBefore = program.getPC();
// Log debugging line for VM
if(program.getNumber().intValue() == CONFIG.dumpBlock())
this.dumpLine(op.val(), program);
// Calculate fees and spend gas
switch (op) {
case STOP: case SUICIDE:
// The ops that doesn't charged by step, or
// charged in the following section
// The ops that don't charge by step
gasCost = GasCost.STOP;
break;
case SSTORE:
// for gas calculations [YP 9.2]
DataWord newValue = stack.get(stack.size()-2);
DataWord oldValue = program.storageLoad(stack.peek());
if (oldValue == null && !newValue.isZero()) {
program.spendGas(GasCost.SSTORE * 2, op.name());
gasCost = GasCost.SSTORE * 2;
} else if (oldValue != null && newValue.isZero()) {
program.spendGas(GasCost.SSTORE * 0, op.name());
gasCost = GasCost.SSTORE * 0;
} else
program.spendGas(GasCost.SSTORE, op.name());
gasCost = GasCost.SSTORE;
break;
case SLOAD:
program.spendGas(GasCost.SLOAD, op.name());
gasCost = GasCost.SLOAD;
break;
case BALANCE:
program.spendGas(GasCost.BALANCE, op.name());
gasCost = GasCost.BALANCE;
break;
// These all operate on memory and therefore potentially expand it:
case MSTORE:
newMemSize = stack.peek().value().add(BigInteger.valueOf(32));
program.spendGas(GasCost.STEP, op.name());
break;
case MSTORE8:
newMemSize = stack.peek().value().add(BigInteger.ONE);
program.spendGas(GasCost.STEP, op.name());
break;
case MLOAD:
newMemSize = stack.peek().value().add(BigInteger.valueOf(32));
program.spendGas(GasCost.STEP, op.name());
break;
case RETURN:
newMemSize = stack.peek().value().add(stack.get(stack.size()-2).value());
program.spendGas(GasCost.STEP, op.name());
break;
case SHA3:
program.spendGas(GasCost.SHA3, op.name());
gasCost = GasCost.SHA3;
newMemSize = stack.peek().value().add(stack.get(stack.size()-2).value());
break;
case CALLDATACOPY:
newMemSize = stack.peek().value().add(stack.get(stack.size()-3).value());
program.spendGas(GasCost.STEP, op.name());
break;
case CODECOPY:
newMemSize = stack.peek().value().add(stack.get(stack.size()-3).value());
program.spendGas(GasCost.STEP, op.name());
break;
case CALL:
program.spendGas(GasCost.CALL, op.name());
BigInteger callGas = stack.get(stack.size()-1).value();
if(callGas.compareTo(program.getGas().value()) == 1) {
gasCost = GasCost.CALL;
BigInteger callGasWord = stack.get(stack.size()-1).value();
if(callGasWord.compareTo(program.getGas().value()) == 1) {
throw program.new OutOfGasException();
}
callGas = callGasWord.longValue();
// Casting to long (causing overflow) as workaround for PoC5 - should be removed for PoC6
long x = stack.get(stack.size()-6).value().add(stack.get(stack.size()-7).value()).longValue();
long y = stack.get(stack.size()-4).value().add(stack.get(stack.size()-5).value()).longValue();
newMemSize = BigInteger.valueOf(Math.max(x, y));
break;
case CREATE:
program.spendGas(GasCost.CREATE, op.name());
gasCost = GasCost.CREATE;
newMemSize = stack.get(stack.size()-2).value().add(stack.get(stack.size()-3).value());
break;
default:
program.spendGas(GasCost.STEP, op.name());
break;
}
program.spendGas(gasCost, op.name());
if(newMemSize.compareTo(MAX_GAS) == 1) {
throw program.new OutOfGasException();
}
// memory gas calc
long memoryUsage = (newMemSize.longValue() + 31) / 32 * 32;
if (memoryUsage > oldMemSize)
program.spendGas(GasCost.MEMORY * ((memoryUsage - oldMemSize) / 32), op.name() + " (memory usage)");
// memory gas calc
long memoryUsage = (newMemSize.longValue() + 31) / 32 * 32;
if (memoryUsage > oldMemSize) {
memWords = (memoryUsage - oldMemSize) / 32;
long memGas = GasCost.MEMORY * memWords;
program.spendGas(memGas, op.name() + " (memory usage)");
gasCost += memGas;
}
// Log debugging line for VM
if(program.getNumber().intValue() == CONFIG.dumpBlock())
this.dumpLine(op, gasBefore, gasCost+callGas, memWords, program);
// Execute operation
switch (op) {
/**
@ -492,7 +501,7 @@ public class VM {
DataWord callValue = program.getCallValue();
if (logger.isInfoEnabled())
hint = "value: " + callValue.toString();
hint = "value: " + callValue;
program.stackPush(callValue);
program.step();
@ -502,7 +511,7 @@ public class VM {
DataWord value = program.getDataValue(dataOffs);
if (logger.isInfoEnabled())
hint = "data: " + value.toString();
hint = "data: " + value;
program.stackPush(value);
program.step();
@ -677,7 +686,7 @@ public class VM {
DataWord val = program.storageLoad(key);
if (logger.isInfoEnabled())
hint = "key: " + key + " value: " + val;
hint = "key: " + key + " value: " + val;
if (val == null) {
val = key.and(DataWord.ZERO);
@ -784,12 +793,17 @@ public class VM {
DataWord outDataOffs = program.stackPop();
DataWord outDataSize = program.stackPop();
if (logger.isInfoEnabled())
if (logger.isInfoEnabled()) {
hint = "addr: " + Hex.toHexString(toAddress.getLast20Bytes())
+ " gas: " + gas.shortHex()
+ " inOff: " + inDataOffs.shortHex()
+ " inSize: " + inDataSize.shortHex();
logger.info(logString, program.getPC(),
String.format("%-12s", op.name()),
program.getGas().value(),
program.invokeData.getCallDeep(), hint);
}
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
@ -803,7 +817,9 @@ public class VM {
program.setHReturn(hReturn);
if (logger.isInfoEnabled())
hint = "data: " + Hex.toHexString(hReturn.array());
hint = "data: " + Hex.toHexString(hReturn.array())
+ " offset: " + offset.value()
+ " size: " + size.value();
program.step();
program.stop();
@ -818,18 +834,17 @@ public class VM {
program.stop();
} break;
default:{
throw new IllegalOperationException();
}
}
if (logger.isInfoEnabled() && !op.equals(CALL)
&& !op.equals(CREATE))
logger.info(logString, stepBefore, String.format("%-12s", op.name()), program.getGas().longValue(),
logger.info(logString, stepBefore, String.format("%-12s",
op.name()), program.getGas().longValue(),
program.invokeData.getCallDeep(), hint);
program.fullTrace();
// program.fullTrace();
vmCounter++;
} catch (RuntimeException e) {
if(e instanceof OutOfGasException)
logger.warn("OutOfGasException occurred", e);
@ -858,28 +873,69 @@ public class VM {
}
}
private void dumpLine(byte op, Program program) {
switch (OpCode.code(op)) {
case STOP: case RETURN: case SUICIDE:
ContractDetails details = program.getResult().getRepository()
/*
* Dumping the VM state at the current operation in various styles
* - standard Not Yet Implemented
* - standard+ (owner address, program counter, operation, gas left)
* - pretty (stack, memory, storage, level, contract,
* vmCounter, internalSteps, operation
gasBefore, gasCost, memWords)
*/
private void dumpLine(OpCode op, long gasBefore, long gasCost, long memWords, Program program) {
if(CONFIG.dumpStyle().equals("standard+")) {
switch (op) {
case STOP: case RETURN: case SUICIDE:
ContractDetails details = program.getResult().getRepository()
.getContractDetails(program.getOwnerAddress().getLast20Bytes());
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
for (DataWord key : storageKeys) {
dumpLogger.trace("{} {}",
Hex.toHexString(key.getNoLeadZeroesData()),
Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
}
default:
break;
}
String addressString = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
String pcString = Hex.toHexString(new DataWord(program.getPC()).getNoLeadZeroesData());
String opString = Hex.toHexString(new byte[]{op.val()});
String gasString = Hex.toHexString(program.getGas().getNoLeadZeroesData());
dumpLogger.trace("{} {} {} {}", addressString, pcString, opString, gasString);
} else if(CONFIG.dumpStyle().equals("pretty")) {
dumpLogger.trace(" STACK");
for (DataWord item : program.getStack()) {
dumpLogger.trace("{}", item);
}
dumpLogger.trace(" MEMORY");
String memoryString = program.memoryToString();
if(!"".equals(memoryString))
dumpLogger.trace("{}", memoryString);
dumpLogger.trace(" STORAGE");
ContractDetails details = program.getResult().getRepository()
.getContractDetails(program.getOwnerAddress().getLast20Bytes());
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
for (DataWord key : storageKeys) {
dumpLogger.info("{} {}",
Hex.toHexString(key.getNoLeadZeroesData()),
Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
}
default:
break;
}
String addressString = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
String pcString = Hex.toHexString(new DataWord(program.getPC()).getNoLeadZeroesData());
String opString = Hex.toHexString(new byte[]{op});
String gasString = Hex.toHexString(program.getGas().getNoLeadZeroesData());
dumpLogger.info("{} {} {} {}", addressString, pcString, opString, gasString);
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
for (DataWord key : storageKeys) {
dumpLogger.trace("{}: {}",
key.shortHex(),
details.getStorage().get(key).shortHex());
}
int level = program.invokeData.getCallDeep();
String contract = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
String internalSteps = String.format("%4s", Integer.toHexString(program.getPC())).replace(' ', '0').toUpperCase();
dumpLogger.trace("{} | {} | #{} | {} : {} | {} | -{} | {}x32",
level, contract, vmCounter, internalSteps, op,
gasBefore, gasCost, memWords);
}
}
@SuppressWarnings("serial")
private class IllegalOperationException extends RuntimeException {}
}

View File

@ -22,7 +22,7 @@ log4j.logger.java.nio = ERROR
log4j.logger.io.netty = ERROR
log4j.logger.wire = ERROR
log4j.logger.wallet = ERROR
log4j.logger.VM = DEBUG
log4j.logger.VM = TRACE
log4j.logger.dump = OFF
log4j.logger.main = INFO
log4j.logger.trie = ERROR

View File

@ -1,11 +1,18 @@
# Root logger option
log4j.rootLogger=DEBUG, stdout, file
log4j.logger.dump=TRACE, DUMP
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss} [%c{1}] %m%n
log4j.appender.stdout.Threshold=DEBUG
# Direct log messages to stdout
log4j.appender.DUMP=org.apache.log4j.ConsoleAppender
log4j.appender.DUMP.Target=System.out
log4j.appender.DUMP.layout=org.apache.log4j.PatternLayout
log4j.appender.file=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
@ -14,7 +21,7 @@ log4j.appender.file.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolic
log4j.appender.file.RollingPolicy.FileNamePattern=./logs/ethereum_%d{yyyy-MM-dd}_h%d{HH}.log
# filter noisy classes
log4j.logger.org.ethereum.core = ERROR
log4j.logger.block = ERROR
log4j.logger.wallet = ERROR
log4j.logger.net = ERROR
log4j.logger.db = ERROR

View File

@ -11,7 +11,7 @@ peer.discovery.ip.list = 185.43.109.23:30303, \
54.72.69.180:30303, \
54.201.28.117:30303, \
70.29.74.8:7
#peer.discovery.ip.list = 127.0.0.1:30303
# active peer ip and port
# that is the peer through
@ -32,6 +32,10 @@ peer.discovery.ip.list = 185.43.109.23:30303, \
peer.active.ip = 185.43.109.23
peer.active.port = 30303
# Localhost
#peer.active.ip = 127.0.0.1
#peer.active.port = 30303
#peer.active.ip = 54.72.69.180
#peer.active.port = 30303
@ -96,10 +100,16 @@ coinbase.secret = monkey
# all the state will be dumped
# in JSON form to [dump.dir]
# if [dump.full] = true
# posible values [true/false]
# possible values [true/false]
dump.full = false
dump.dir = dmp
# This defines the vmtrace dump
# to the console and the style
# -1 for no block trace
# styles: [pretty/standard+] (default: standard+)
dump.block = -1
dump.style = pretty
# clean the dump dir each start
dump.clean.on.restart = true

View File

@ -6,22 +6,20 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.ethereum.core.AccountState;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.db.DatabaseImpl;
import org.ethereum.util.CompactEncoder;
import org.ethereum.util.Value;
import org.iq80.leveldb.DBIterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -520,53 +518,57 @@ public class TrieTest {
trie.update("te", "testy");
assertEquals("8452568af70d8d140f58d941338542f645fcca50094b20f3c3d8c3df49337928", Hex.toHexString(trie.getRootHash()));
}
private final String randomDictionary = "spinneries, archipenko, prepotency, herniotomy, preexpress, relaxative, insolvably, debonnaire, apophysate, virtuality, cavalryman, utilizable, diagenesis, vitascopic, governessy, abranchial, cyanogenic, gratulated, signalment, predicable, subquality, crystalize, prosaicism, oenologist, repressive, impanelled, cockneyism, bordelaise, compigne, konstantin, predicated, unsublimed, hydrophane, phycomyces, capitalise, slippingly, untithable, unburnable, deoxidizer, misteacher, precorrect, disclaimer, solidified, neuraxitis, caravaning, betelgeuse, underprice, uninclosed, acrogynous, reirrigate, dazzlingly, chaffiness, corybantes, intumesced, intentness, superexert, abstrusely, astounding, pilgrimage, posttarsal, prayerless, nomologist, semibelted, frithstool, unstinging, ecalcarate, amputating, megascopic, graphalloy, platteland, adjacently, mingrelian, valentinus, appendical, unaccurate, coriaceous, waterworks, sympathize, doorkeeper, overguilty, flaggingly, admonitory, aeriferous, normocytic, parnellism, catafalque, odontiasis, apprentice, adulterous, mechanisma, wilderness, undivorced, reinterred, effleurage, pretrochal, phytogenic, swirlingly, herbarized, unresolved, classifier, diosmosing, microphage, consecrate, astarboard, predefying, predriving, lettergram, ungranular, overdozing, conferring, unfavorite, peacockish, coinciding, erythraeum, freeholder, zygophoric, imbitterer, centroidal, appendixes, grayfishes, enological, indiscreet, broadcloth, divulgated, anglophobe, stoopingly, bibliophil, laryngitis, separatist, estivating, bellarmine, greasiness, typhlology, xanthation, mortifying, endeavorer, aviatrices, unequalise, metastatic, leftwinger, apologizer, quatrefoil, nonfouling, bitartrate, outchiding, undeported, poussetted, haemolysis, asantehene, montgomery, unjoinable, cedarhurst, unfastener, nonvacuums, beauregard, animalized, polyphides, cannizzaro, gelatinoid, apologised, unscripted, tracheidal, subdiscoid, gravelling, variegated, interabang, inoperable, immortelle, laestrygon, duplicatus, proscience, deoxidised, manfulness, channelize, nondefense, ectomorphy, unimpelled, headwaiter, hexaemeric, derivation, prelexical, limitarian, nonionized, prorefugee, invariably, patronizer, paraplegia, redivision, occupative, unfaceable, hypomnesia, psalterium, doctorfish, gentlefolk, overrefine, heptastich, desirously, clarabelle, uneuphonic, autotelism, firewarden, timberjack, fumigation, drainpipes, spathulate, novelvelle, bicorporal, grisliness, unhesitant, supergiant, unpatented, womanpower, toastiness, multichord, paramnesia, undertrick, contrarily, neurogenic, gunmanship, settlement, brookville, gradualism, unossified, villanovan, ecospecies, organising, buckhannon, prefulfill, johnsonese, unforegone, unwrathful, dunderhead, erceldoune, unwadeable, refunction, understuff, swaggering, freckliest, telemachus, groundsill, outslidden, bolsheviks, recognizer, hemangioma, tarantella, muhammedan, talebearer, relocation, preemption, chachalaca, septuagint, ubiquitous, plexiglass, humoresque, biliverdin, tetraploid, capitoline, summerwood, undilating, undetested, meningitic, petrolatum, phytotoxic, adiphenine, flashlight, protectory, inwreathed, rawishness, tendrillar, hastefully, bananaquit, anarthrous, unbedimmed, herborized, decenniums, deprecated, karyotypic, squalidity, pomiferous, petroglyph, actinomere, peninsular, trigonally, androgenic, resistance, unassuming, frithstool, documental, eunuchised, interphone, thymbraeus, confirmand, expurgated, vegetation, myographic, plasmagene, spindrying, unlackeyed, foreknower, mythically, albescence, rebudgeted, implicitly, unmonastic, torricelli, mortarless, labialized, phenacaine, radiometry, sluggishly, understood, wiretapper, jacobitely, unbetrayed, stadholder, directress, emissaries, corelation, sensualize, uncurbable, permillage, tentacular, thriftless, demoralize, preimagine, iconoclast, acrobatism, firewarden, transpired, bluethroat, wanderjahr, groundable, pedestrian, unulcerous, preearthly, freelanced, sculleries, avengingly, visigothic, preharmony, bressummer, acceptable, unfoolable, predivider, overseeing, arcosolium, piriformis, needlecord, homebodies, sulphation, phantasmic, unsensible, unpackaged, isopiestic, cytophagic, butterlike, frizzliest, winklehawk, necrophile, mesothorax, cuchulainn, unrentable, untangible, unshifting, unfeasible, poetastric, extermined, gaillardia, nonpendent, harborside, pigsticker, infanthood, underrower, easterling, jockeyship, housebreak, horologium, undepicted, dysacousma, incurrable, editorship, unrelented, peritricha, interchaff, frothiness, underplant, proafrican, squareness, enigmatise, reconciled, nonnumeral, nonevident, hamantasch, victualing, watercolor, schrdinger, understand, butlerlike, hemiglobin, yankeeland";
@Test
public void testMasiveUpdate(){
String randomDictionary = "spinneries, archipenko, prepotency, herniotomy, preexpress, relaxative, insolvably, debonnaire, apophysate, virtuality, cavalryman, utilizable, diagenesis, vitascopic, governessy, abranchial, cyanogenic, gratulated, signalment, predicable, subquality, crystalize, prosaicism, oenologist, repressive, impanelled, cockneyism, bordelaise, compigne, konstantin, predicated, unsublimed, hydrophane, phycomyces, capitalise, slippingly, untithable, unburnable, deoxidizer, misteacher, precorrect, disclaimer, solidified, neuraxitis, caravaning, betelgeuse, underprice, uninclosed, acrogynous, reirrigate, dazzlingly, chaffiness, corybantes, intumesced, intentness, superexert, abstrusely, astounding, pilgrimage, posttarsal, prayerless, nomologist, semibelted, frithstool, unstinging, ecalcarate, amputating, megascopic, graphalloy, platteland, adjacently, mingrelian, valentinus, appendical, unaccurate, coriaceous, waterworks, sympathize, doorkeeper, overguilty, flaggingly, admonitory, aeriferous, normocytic, parnellism, catafalque, odontiasis, apprentice, adulterous, mechanisma, wilderness, undivorced, reinterred, effleurage, pretrochal, phytogenic, swirlingly, herbarized, unresolved, classifier, diosmosing, microphage, consecrate, astarboard, predefying, predriving, lettergram, ungranular, overdozing, conferring, unfavorite, peacockish, coinciding, erythraeum, freeholder, zygophoric, imbitterer, centroidal, appendixes, grayfishes, enological, indiscreet, broadcloth, divulgated, anglophobe, stoopingly, bibliophil, laryngitis, separatist, estivating, bellarmine, greasiness, typhlology, xanthation, mortifying, endeavorer, aviatrices, unequalise, metastatic, leftwinger, apologizer, quatrefoil, nonfouling, bitartrate, outchiding, undeported, poussetted, haemolysis, asantehene, montgomery, unjoinable, cedarhurst, unfastener, nonvacuums, beauregard, animalized, polyphides, cannizzaro, gelatinoid, apologised, unscripted, tracheidal, subdiscoid, gravelling, variegated, interabang, inoperable, immortelle, laestrygon, duplicatus, proscience, deoxidised, manfulness, channelize, nondefense, ectomorphy, unimpelled, headwaiter, hexaemeric, derivation, prelexical, limitarian, nonionized, prorefugee, invariably, patronizer, paraplegia, redivision, occupative, unfaceable, hypomnesia, psalterium, doctorfish, gentlefolk, overrefine, heptastich, desirously, clarabelle, uneuphonic, autotelism, firewarden, timberjack, fumigation, drainpipes, spathulate, novelvelle, bicorporal, grisliness, unhesitant, supergiant, unpatented, womanpower, toastiness, multichord, paramnesia, undertrick, contrarily, neurogenic, gunmanship, settlement, brookville, gradualism, unossified, villanovan, ecospecies, organising, buckhannon, prefulfill, johnsonese, unforegone, unwrathful, dunderhead, erceldoune, unwadeable, refunction, understuff, swaggering, freckliest, telemachus, groundsill, outslidden, bolsheviks, recognizer, hemangioma, tarantella, muhammedan, talebearer, relocation, preemption, chachalaca, septuagint, ubiquitous, plexiglass, humoresque, biliverdin, tetraploid, capitoline, summerwood, undilating, undetested, meningitic, petrolatum, phytotoxic, adiphenine, flashlight, protectory, inwreathed, rawishness, tendrillar, hastefully, bananaquit, anarthrous, unbedimmed, herborized, decenniums, deprecated, karyotypic, squalidity, pomiferous, petroglyph, actinomere, peninsular, trigonally, androgenic, resistance, unassuming, frithstool, documental, eunuchised, interphone, thymbraeus, confirmand, expurgated, vegetation, myographic, plasmagene, spindrying, unlackeyed, foreknower, mythically, albescence, rebudgeted, implicitly, unmonastic, torricelli, mortarless, labialized, phenacaine, radiometry, sluggishly, understood, wiretapper, jacobitely, unbetrayed, stadholder, directress, emissaries, corelation, sensualize, uncurbable, permillage, tentacular, thriftless, demoralize, preimagine, iconoclast, acrobatism, firewarden, transpired, bluethroat, wanderjahr, groundable, pedestrian, unulcerous, preearthly, freelanced, sculleries, avengingly, visigothic, preharmony, bressummer, acceptable, unfoolable, predivider, overseeing, arcosolium, piriformis, needlecord, homebodies, sulphation, phantasmic, unsensible, unpackaged, isopiestic, cytophagic, butterlike, frizzliest, winklehawk, necrophile, mesothorax, cuchulainn, unrentable, untangible, unshifting, unfeasible, poetastric, extermined, gaillardia, nonpendent, harborside, pigsticker, infanthood, underrower, easterling, jockeyship, housebreak, horologium, undepicted, dysacousma, incurrable, editorship, unrelented, peritricha, interchaff, frothiness, underplant, proafrican, squareness, enigmatise, reconciled, nonnumeral, nonevident, hamantasch, victualing, watercolor, schrdinger, understand, butlerlike, hemiglobin, yankeeland";
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
HashMap<String, String> testerMap = new HashMap<>();
Trie trie = new Trie(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 100000; ++i ){
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
int half = testerMap.size() / 2;
for (int r = 0; r < half; ++r){
int randomIndex = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex).trim();
testerMap.remove(word1);
trie.delete(word1);
}
trie.cleanCacheGarbage();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
boolean massiveUpdateTestEnabled = false;
if(massiveUpdateTestEnabled) {
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
HashMap<String, String> testerMap = new HashMap<>();
Trie trie = new Trie(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 100000; ++i ){
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
int half = testerMap.size() / 2;
for (int r = 0; r < half; ++r){
int randomIndex = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex).trim();
testerMap.remove(word1);
trie.delete(word1);
}
trie.cleanCacheGarbage();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
}
}
@ -636,56 +638,58 @@ public class TrieTest {
assertEquals(trieSingle.getRootHash(), trie2.getRootHash());
}
@Test // tests saving keys to the file //
public void testMasiveUpdateFromDB(){
String randomDictionary = "spinneries, archipenko, prepotency, herniotomy, preexpress, relaxative, insolvably, debonnaire, apophysate, virtuality, cavalryman, utilizable, diagenesis, vitascopic, governessy, abranchial, cyanogenic, gratulated, signalment, predicable, subquality, crystalize, prosaicism, oenologist, repressive, impanelled, cockneyism, bordelaise, compigne, konstantin, predicated, unsublimed, hydrophane, phycomyces, capitalise, slippingly, untithable, unburnable, deoxidizer, misteacher, precorrect, disclaimer, solidified, neuraxitis, caravaning, betelgeuse, underprice, uninclosed, acrogynous, reirrigate, dazzlingly, chaffiness, corybantes, intumesced, intentness, superexert, abstrusely, astounding, pilgrimage, posttarsal, prayerless, nomologist, semibelted, frithstool, unstinging, ecalcarate, amputating, megascopic, graphalloy, platteland, adjacently, mingrelian, valentinus, appendical, unaccurate, coriaceous, waterworks, sympathize, doorkeeper, overguilty, flaggingly, admonitory, aeriferous, normocytic, parnellism, catafalque, odontiasis, apprentice, adulterous, mechanisma, wilderness, undivorced, reinterred, effleurage, pretrochal, phytogenic, swirlingly, herbarized, unresolved, classifier, diosmosing, microphage, consecrate, astarboard, predefying, predriving, lettergram, ungranular, overdozing, conferring, unfavorite, peacockish, coinciding, erythraeum, freeholder, zygophoric, imbitterer, centroidal, appendixes, grayfishes, enological, indiscreet, broadcloth, divulgated, anglophobe, stoopingly, bibliophil, laryngitis, separatist, estivating, bellarmine, greasiness, typhlology, xanthation, mortifying, endeavorer, aviatrices, unequalise, metastatic, leftwinger, apologizer, quatrefoil, nonfouling, bitartrate, outchiding, undeported, poussetted, haemolysis, asantehene, montgomery, unjoinable, cedarhurst, unfastener, nonvacuums, beauregard, animalized, polyphides, cannizzaro, gelatinoid, apologised, unscripted, tracheidal, subdiscoid, gravelling, variegated, interabang, inoperable, immortelle, laestrygon, duplicatus, proscience, deoxidised, manfulness, channelize, nondefense, ectomorphy, unimpelled, headwaiter, hexaemeric, derivation, prelexical, limitarian, nonionized, prorefugee, invariably, patronizer, paraplegia, redivision, occupative, unfaceable, hypomnesia, psalterium, doctorfish, gentlefolk, overrefine, heptastich, desirously, clarabelle, uneuphonic, autotelism, firewarden, timberjack, fumigation, drainpipes, spathulate, novelvelle, bicorporal, grisliness, unhesitant, supergiant, unpatented, womanpower, toastiness, multichord, paramnesia, undertrick, contrarily, neurogenic, gunmanship, settlement, brookville, gradualism, unossified, villanovan, ecospecies, organising, buckhannon, prefulfill, johnsonese, unforegone, unwrathful, dunderhead, erceldoune, unwadeable, refunction, understuff, swaggering, freckliest, telemachus, groundsill, outslidden, bolsheviks, recognizer, hemangioma, tarantella, muhammedan, talebearer, relocation, preemption, chachalaca, septuagint, ubiquitous, plexiglass, humoresque, biliverdin, tetraploid, capitoline, summerwood, undilating, undetested, meningitic, petrolatum, phytotoxic, adiphenine, flashlight, protectory, inwreathed, rawishness, tendrillar, hastefully, bananaquit, anarthrous, unbedimmed, herborized, decenniums, deprecated, karyotypic, squalidity, pomiferous, petroglyph, actinomere, peninsular, trigonally, androgenic, resistance, unassuming, frithstool, documental, eunuchised, interphone, thymbraeus, confirmand, expurgated, vegetation, myographic, plasmagene, spindrying, unlackeyed, foreknower, mythically, albescence, rebudgeted, implicitly, unmonastic, torricelli, mortarless, labialized, phenacaine, radiometry, sluggishly, understood, wiretapper, jacobitely, unbetrayed, stadholder, directress, emissaries, corelation, sensualize, uncurbable, permillage, tentacular, thriftless, demoralize, preimagine, iconoclast, acrobatism, firewarden, transpired, bluethroat, wanderjahr, groundable, pedestrian, unulcerous, preearthly, freelanced, sculleries, avengingly, visigothic, preharmony, bressummer, acceptable, unfoolable, predivider, overseeing, arcosolium, piriformis, needlecord, homebodies, sulphation, phantasmic, unsensible, unpackaged, isopiestic, cytophagic, butterlike, frizzliest, winklehawk, necrophile, mesothorax, cuchulainn, unrentable, untangible, unshifting, unfeasible, poetastric, extermined, gaillardia, nonpendent, harborside, pigsticker, infanthood, underrower, easterling, jockeyship, housebreak, horologium, undepicted, dysacousma, incurrable, editorship, unrelented, peritricha, interchaff, frothiness, underplant, proafrican, squareness, enigmatise, reconciled, nonnumeral, nonevident, hamantasch, victualing, watercolor, schrdinger, understand, butlerlike, hemiglobin, yankeeland";
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
HashMap<String, String> testerMap = new HashMap<>();
Trie trie = new Trie(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 50000; ++i ){
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
trie.cleanCacheGarbage();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
Trie trie2 = new Trie(mockDb, trie.getRootHash());
// Assert the result now
keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie2.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
boolean massiveUpdateFromDBEnabled = false;
if(massiveUpdateFromDBEnabled) {
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
HashMap<String, String> testerMap = new HashMap<>();
Trie trie = new Trie(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 50000; ++i ){
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
trie.cleanCacheGarbage();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
Trie trie2 = new Trie(mockDb, trie.getRootHash());
// Assert the result now
keys = testerMap.keySet().iterator();
while (keys.hasNext()){
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie2.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
}
}

View File

@ -98,6 +98,20 @@ public class ByteUtilTest {
assertEquals(0, result);
}
@Test
public void testNiceNiblesOutput_1(){
byte[] test = {7, 0, 7, 5, 7, 0, 7, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x05\\x07\\x00\\x07\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test
public void testNiceNiblesOutput_2(){
byte[] test = {7, 0, 7, 0xf, 7, 0, 0xa, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x0f\\x07\\x00\\x0a\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test(expected=NullPointerException.class)
public void testMatchingNibbleLength5() {
// a == null

View File

@ -85,22 +85,4 @@ public class CompactEncoderTest {
byte[] result = new byte[] { 7, 0, 7, 5, 7, 0, 7, 0, 7, 9, T };
assertArrayEquals(result, CompactEncoder.binToNibbles(test));
}
@Test
public void testNiceNiblesOutput_1(){
byte[] test = {7, 0, 7, 5, 7, 0, 7, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x05\\x07\\x00\\x07\\x00\\x07\\x09";
assertEquals(result, CompactEncoder.nibblesToPrettyString(test));
}
@Test
public void testNiceNiblesOutput_2(){
byte[] test = {7, 0, 7, 0xf, 7, 0, 0xa, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x0f\\x07\\x00\\x0a\\x00\\x07\\x09";
assertEquals(result, CompactEncoder.nibblesToPrettyString(test));
}
}