Merge branch 'master' of https://github.com/ethereum/ethereumj
This commit is contained in:
commit
24449cc77a
|
@ -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 Integer DEFAULT_VMTRACE_BLOCK = 0;
|
||||
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
|
||||
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
|
||||
private static Boolean DEFAULT_PLAY_VM = true;
|
||||
|
@ -151,6 +152,11 @@ public class SystemProperties {
|
|||
return prop.getProperty("dump.dir");
|
||||
}
|
||||
|
||||
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");
|
||||
|
|
|
@ -15,8 +15,6 @@ import org.spongycastle.util.BigIntegers;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
|
@ -45,7 +43,7 @@ public class Block {
|
|||
private BlockHeader header;
|
||||
|
||||
/* Transactions */
|
||||
private List<TransactionReceipt> txReceiptList = new CopyOnWriteArrayList <TransactionReceipt>() ;
|
||||
private List<TransactionReceipt> txReceiptList = new CopyOnWriteArrayList<TransactionReceipt>() ;
|
||||
private List<Transaction> transactionsList = new CopyOnWriteArrayList<Transaction>();
|
||||
|
||||
/* Uncles */
|
||||
|
@ -73,14 +71,14 @@ public class Block {
|
|||
this.header = new BlockHeader(parentHash, unclesHash, coinbase,
|
||||
difficulty, number, minGasPrice, gasLimit, gasUsed,
|
||||
timestamp, extraData, nonce);
|
||||
|
||||
this.transactionsList = transactionsList;
|
||||
if (this.transactionsList == null){
|
||||
this.transactionsList = new CopyOnWriteArrayList<Transaction>();
|
||||
}
|
||||
|
||||
this.uncleList = uncleList;
|
||||
if (this.uncleList == null){
|
||||
|
||||
if (this.uncleList == null) {
|
||||
this.uncleList = new CopyOnWriteArrayList<BlockHeader>();
|
||||
}
|
||||
|
||||
|
@ -268,7 +266,6 @@ public class Block {
|
|||
toStringBuff.append(header.toStylishString());
|
||||
|
||||
for (TransactionReceipt tx : getTxReceiptList()) {
|
||||
|
||||
toStringBuff.append("<br/>");
|
||||
toStringBuff.append( tx.toStylishString() );
|
||||
toStringBuff.append("<br/>");
|
||||
|
|
|
@ -137,11 +137,7 @@ public class Blockchain {
|
|||
this.processBlock(block);
|
||||
|
||||
// Remove all wallet transactions as they already approved by the net
|
||||
for (Transaction tx : block.getTransactionsList()) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
||||
WorldManager.getInstance().removeWalletTransaction(tx);
|
||||
}
|
||||
WorldManager.getInstance().getWallet().removeTransactions(block.getTransactionsList());
|
||||
|
||||
EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
if (listener != null)
|
||||
|
@ -150,35 +146,15 @@ public class Blockchain {
|
|||
EthereumListener ethereumListener = WorldManager.getInstance().getListener();
|
||||
if (ethereumListener != null)
|
||||
ethereumListener.onBlock(block);
|
||||
|
||||
/*
|
||||
if (lastBlock.getNumber() >= 30) {
|
||||
System.out.println("** checkpoint **");
|
||||
|
||||
this.close();
|
||||
WorldManager.getInstance().getRepository().close();
|
||||
System.exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
public void processBlock(Block block) {
|
||||
if(block.isValid()) {
|
||||
if (!block.isGenesis()) {
|
||||
|
||||
if (!CONFIG.blockChainOnly()) {
|
||||
|
||||
for (Transaction tx : block.getTransactionsList())
|
||||
// TODO: refactor the wallet pending transactions to the world manager
|
||||
WorldManager.getInstance().addWalletTransaction(tx);
|
||||
|
||||
this.applyBlock(block);
|
||||
|
||||
WorldManager.getInstance().getWallet().addTransactions(block.getTransactionsList());
|
||||
this.applyBlock(block);
|
||||
WorldManager.getInstance().getWallet().processBlock(block);
|
||||
|
||||
repository.dumpState(block.getNumber(), 0,
|
||||
null);
|
||||
}
|
||||
}
|
||||
this.storeBlock(block);
|
||||
|
@ -190,11 +166,15 @@ public class Blockchain {
|
|||
public void applyBlock(Block block) {
|
||||
|
||||
int i = 0;
|
||||
for (Transaction tx : block.getTransactionsList()) {
|
||||
long totalGasUsed = 0;
|
||||
for (TransactionReceipt txr : block.getTxReceiptList()) {
|
||||
stateLogger.debug("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i);
|
||||
applyTransaction(block, tx, block.getCoinbase());
|
||||
repository.dumpState(block.getNumber(), i, tx.getHash());
|
||||
++i;
|
||||
totalGasUsed += applyTransaction(block, txr.getTransaction());
|
||||
if(!Arrays.equals(this.repository.getWorldState().getRootHash(), txr.getPostTxState()))
|
||||
logger.warn("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());
|
||||
}
|
||||
|
||||
// miner reward
|
||||
|
@ -205,6 +185,9 @@ public class Blockchain {
|
|||
for (BlockHeader uncle : block.getUncleList()) {
|
||||
repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD);
|
||||
}
|
||||
|
||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||
repository.dumpState(block, totalGasUsed, 0, null);
|
||||
}
|
||||
|
||||
public void storeBlock(Block block) {
|
||||
|
@ -216,8 +199,8 @@ public class Blockchain {
|
|||
if(!blockStateRootHash.equals(worldStateRootHash)){
|
||||
logger.error("ERROR: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash);
|
||||
// Last conflict on block 1501 -> worldstate 27920c6c7acd42c8a7ac8a835d4c0e0a45590deb094d6b72a8493fac5d7a3654
|
||||
// repository.close();
|
||||
// System.exit(-1); // Don't add block
|
||||
repository.close();
|
||||
System.exit(-1); // Don't add block
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,8 +213,17 @@ public class Blockchain {
|
|||
logger.info("*** Last block added [ #{} ]", block.getNumber());
|
||||
}
|
||||
|
||||
public void applyTransaction(Block block, Transaction tx, byte[] coinbase) {
|
||||
|
||||
/**
|
||||
* Apply the transaction to the world state
|
||||
*
|
||||
* @param block - the block which contains the transactions
|
||||
* @param tx - the transaction to be applied
|
||||
* @return gasUsed
|
||||
*/
|
||||
public long applyTransaction(Block block, Transaction tx) {
|
||||
|
||||
byte[] coinbase = block.getCoinbase();
|
||||
byte[] senderAddress = tx.getSender();
|
||||
AccountState senderAccount = repository.getAccountState(senderAddress);
|
||||
|
||||
|
@ -239,7 +231,7 @@ public class Blockchain {
|
|||
if (stateLogger.isWarnEnabled())
|
||||
stateLogger.warn("No such address: {}",
|
||||
Hex.toHexString(senderAddress));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1. VALIDATE THE NONCE
|
||||
|
@ -249,7 +241,7 @@ public class Blockchain {
|
|||
if (stateLogger.isWarnEnabled())
|
||||
stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}",
|
||||
nonce, txNonce);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. FIND OUT THE TRANSACTION TYPE
|
||||
|
@ -300,7 +292,7 @@ public class Blockchain {
|
|||
if (balance.compareTo(gasDebit) == -1) {
|
||||
logger.debug("No gas to start the execution: sender={}",
|
||||
Hex.toHexString(senderAddress));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
repository.addBalance(senderAddress, gasDebit.negate());
|
||||
senderAccount.subFromBalance(gasDebit); // balance will be read again below
|
||||
|
@ -316,23 +308,18 @@ public class Blockchain {
|
|||
Hex.toHexString(senderAddress), gasDebit);
|
||||
}
|
||||
|
||||
// 3. START TRACKING FOR REVERT CHANGES OPTION !!!
|
||||
Repository trackRepository = repository.getTrack();
|
||||
trackRepository.startTracking();
|
||||
|
||||
try {
|
||||
|
||||
|
||||
// 4. THE SIMPLE VALUE/BALANCE CHANGE
|
||||
if (tx.getValue() != null) {
|
||||
|
||||
|
||||
BigInteger senderBalance = senderAccount.getBalance();
|
||||
|
||||
|
||||
if (senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0) {
|
||||
repository.addBalance(receiverAddress,
|
||||
new BigInteger(1, tx.getValue()));
|
||||
repository.addBalance(senderAddress,
|
||||
new BigInteger(1, tx.getValue()).negate());
|
||||
|
||||
|
||||
if (stateLogger.isDebugEnabled())
|
||||
stateLogger.debug("Update value balance \n "
|
||||
+ "sender={}, receiver={}, value={}",
|
||||
|
@ -342,7 +329,14 @@ public class Blockchain {
|
|||
}
|
||||
}
|
||||
|
||||
// 5. CREATE OR EXECUTE PROGRAM
|
||||
// 3. START TRACKING FOR REVERT CHANGES OPTION !!!
|
||||
Repository trackRepository = repository.getTrack();
|
||||
trackRepository.startTracking();
|
||||
long gasUsed = 0;
|
||||
try {
|
||||
|
||||
// 5. CREATE OR EXECUTE PROGRAM
|
||||
|
||||
if (isContractCreation || code != null) {
|
||||
Block currBlock = (block == null) ? this.getLastBlock() : block;
|
||||
|
||||
|
@ -357,13 +351,13 @@ public class Blockchain {
|
|||
ProgramResult result = program.getResult();
|
||||
applyProgramResult(result, gasDebit, trackRepository,
|
||||
senderAddress, receiverAddress, coinbase, isContractCreation);
|
||||
gasUsed = result.getGasUsed();
|
||||
} else {
|
||||
// refund everything except fee (500 + 5*txdata)
|
||||
BigInteger gasPrice = new BigInteger(1, tx.getGasPrice());
|
||||
long dataFee = tx.getData() == null ? 0: tx.getData().length * GasCost.TXDATA;
|
||||
long minTxFee = GasCost.TRANSACTION + dataFee;
|
||||
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(
|
||||
minTxFee).multiply(gasPrice));
|
||||
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(minTxFee).multiply(gasPrice));
|
||||
if (refund.signum() > 0) {
|
||||
// gas refund
|
||||
repository.addBalance(senderAddress, refund);
|
||||
|
@ -372,10 +366,11 @@ public class Blockchain {
|
|||
}
|
||||
} catch (RuntimeException e) {
|
||||
trackRepository.rollback();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
trackRepository.commit();
|
||||
pendingTransactions.put(Hex.toHexString(tx.getHash()), tx);
|
||||
return gasUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,14 @@ public class TransactionReceipt {
|
|||
this.postTxState = postTxState;
|
||||
this.cumulativeGas = cumulativeGas;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public byte[] getPostTxState() {
|
||||
return postTxState;
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.ethereum.core;
|
||||
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.net.submit.WalletTransaction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
|
@ -22,6 +26,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* The Wallet handles the management of accounts with addresses and private keys.
|
||||
|
@ -29,17 +34,23 @@ import java.util.Map;
|
|||
*/
|
||||
public class Wallet {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("wallet");
|
||||
|
||||
// TODO: a) the values I need to keep for address state is balance & nonce & ECKey
|
||||
// TODO: b) keep it to be easy accessed by the toAddress()
|
||||
// private HashMap<Address, BigInteger> rows = new HashMap<>();
|
||||
|
||||
// This map of transaction designed
|
||||
// to approve the tx by external trusted peer
|
||||
private Map<String, WalletTransaction> walletTransactions = new ConcurrentHashMap<>();
|
||||
|
||||
// <address, info> table for a wallet
|
||||
private Map<String, Account> rows = new HashMap<>();
|
||||
private long high;
|
||||
|
||||
private List<WalletListener> listeners = new ArrayList<>();
|
||||
|
||||
private Map<BigInteger, Transaction> transactionMap = new HashMap<>();
|
||||
private Map<ByteArrayWrapper, Transaction> transactionMap = new HashMap<>();
|
||||
|
||||
public void addNewAccount() {
|
||||
Account account = new Account();
|
||||
|
@ -80,10 +91,51 @@ public class Wallet {
|
|||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 1) the dialog put a pending transaction on the list
|
||||
* 2) the dialog send the transaction to a net
|
||||
* 3) wherever the transaction got in from the wire it will change to approve state
|
||||
* 4) only after the approve a) Wallet state changes
|
||||
* 5) After the block is received with that tx the pending been clean up
|
||||
*/
|
||||
public WalletTransaction addTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction placed hash: {}", hash );
|
||||
|
||||
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
|
||||
if (walletTransaction != null)
|
||||
walletTransaction.incApproved();
|
||||
else {
|
||||
walletTransaction = new WalletTransaction(transaction);
|
||||
this.walletTransactions.put(hash, walletTransaction);
|
||||
}
|
||||
return walletTransaction;
|
||||
}
|
||||
|
||||
public void addTransactions(List<Transaction> transactions) {
|
||||
for (Transaction transaction : transactions) {
|
||||
this.addTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTransactions(List<Transaction> transactions) {
|
||||
for (Transaction tx : transactions) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString(tx.getHash()));
|
||||
this.removeTransaction(tx);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction removed with hash: {} ", hash);
|
||||
walletTransactions.remove(hash);
|
||||
}
|
||||
|
||||
public void applyTransaction(Transaction transaction) {
|
||||
|
||||
transactionMap.put(new BigInteger(transaction.getHash()), transaction );
|
||||
transactionMap.put(new ByteArrayWrapper(transaction.getHash()), transaction );
|
||||
|
||||
byte[] senderAddress = transaction.getSender();
|
||||
Account sender = rows.get(Hex.toHexString(senderAddress));
|
||||
|
@ -113,7 +165,7 @@ public class Wallet {
|
|||
List<Transaction> transactions = block.getTransactionsList();
|
||||
|
||||
for (Transaction tx : transactions) {
|
||||
boolean txExist = transactionMap.get(new BigInteger(tx.getHash())) != null;
|
||||
boolean txExist = transactionMap.get(new ByteArrayWrapper(tx.getHash())) != null;
|
||||
if (txExist) break;
|
||||
else {
|
||||
this.applyTransaction(tx);
|
||||
|
|
|
@ -70,13 +70,7 @@ public class ContractDetails {
|
|||
if (storageKeys.size() == 0)
|
||||
return null;
|
||||
|
||||
int foundIndex = -1;
|
||||
for (int i = 0; i < storageKeys.size(); ++i) {
|
||||
if (storageKeys.get(i).equals(key)) {
|
||||
foundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int foundIndex = storageKeys.indexOf(key);
|
||||
if (foundIndex != -1)
|
||||
return storageValues.get(foundIndex);
|
||||
else
|
||||
|
@ -97,7 +91,8 @@ public class ContractDetails {
|
|||
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() ));
|
||||
storageTrie.update(storageKeys.get(i).getData(), RLP
|
||||
.encodeElement(storageValues.get(i).getNoLeadZeroesData()));
|
||||
}
|
||||
return storageTrie.getRootHash();
|
||||
}
|
||||
|
|
|
@ -16,16 +16,17 @@ import org.ethereum.vm.DataWord;
|
|||
import org.iq80.leveldb.DBIterator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
|
@ -136,7 +137,7 @@ public class Repository {
|
|||
}
|
||||
|
||||
logger.debug("Block #{} -> {}", Genesis.NUMBER, blockchain.getLastBlock().toFlatString());
|
||||
dumpState(0, 0, null);
|
||||
dumpState(Genesis.getInstance(), 0, 0, null);
|
||||
} else {
|
||||
logger.debug("Displaying blocks stored in DB sorted on blocknumber");
|
||||
|
||||
|
@ -368,13 +369,14 @@ public class Repository {
|
|||
return stateDB.dumpKeys();
|
||||
}
|
||||
|
||||
public void dumpState(long blockNumber, int txNumber, byte[] txHash) {
|
||||
public void dumpState(Block block, long gasUsed, int txNumber, byte[] txHash) {
|
||||
|
||||
if (!CONFIG.dumpFull()) return;
|
||||
if (!(CONFIG.dumpFull() || CONFIG.dumpBlock() == block.getNumber()))
|
||||
return;
|
||||
|
||||
// todo: dump block header and the relevant tx
|
||||
|
||||
if (blockNumber == 0 && txNumber == 0)
|
||||
if (block.getNumber() == 0 && txNumber == 0)
|
||||
if (CONFIG.dumpCleanOnRestart()) {
|
||||
try {FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {}
|
||||
}
|
||||
|
@ -383,10 +385,10 @@ public class Repository {
|
|||
|
||||
String fileName = "";
|
||||
if (txHash != null)
|
||||
fileName = String.format("%d_%d_%s.dmp",
|
||||
blockNumber, txNumber, Hex.toHexString(txHash).substring(0, 8));
|
||||
fileName = String.format("%d_%d_%s.dmp", block.getNumber(), txNumber,
|
||||
Hex.toHexString(txHash).substring(0, 8));
|
||||
else
|
||||
fileName = String.format("%d_c.dmp", blockNumber);
|
||||
fileName = String.format("%d_c.dmp", block.getNumber());
|
||||
|
||||
File dumpFile = new File(System.getProperty("user.dir") + "/" + dir + fileName);
|
||||
FileWriter fw = null;
|
||||
|
@ -400,35 +402,16 @@ public class Repository {
|
|||
bw = new BufferedWriter(fw);
|
||||
|
||||
List<ByteArrayWrapper> keys = this.detailsDB.dumpKeys();
|
||||
|
||||
// dump json file
|
||||
for (ByteArrayWrapper key : keys) {
|
||||
|
||||
byte[] keyBytes = key.getData();
|
||||
AccountState state = getAccountState(keyBytes);
|
||||
ContractDetails details = getContractDetails(keyBytes);
|
||||
|
||||
BigInteger nonce = (state != null)? state.getNonce():null;
|
||||
BigInteger balance = (state != null)? state.getBalance():null;
|
||||
|
||||
byte[] stateRoot = (state != null)? state.getStateRoot():null;
|
||||
byte[] codeHash = (state != null)? state.getCodeHash():null;
|
||||
|
||||
byte[] code = details.getCode();
|
||||
Map<DataWord, DataWord> storage = details.getStorage();
|
||||
|
||||
String accountLine = JSONHelper.dumpLine(key.getData(),
|
||||
(nonce != null)? BigIntegers.asUnsignedByteArray(nonce) : null,
|
||||
(nonce != null)? BigIntegers.asUnsignedByteArray(balance): null,
|
||||
stateRoot, codeHash, code, storage);
|
||||
|
||||
bw.write(accountLine);
|
||||
bw.write("\n");
|
||||
}
|
||||
|
||||
JsonNodeFactory jsonFactory = new JsonNodeFactory(false);
|
||||
ObjectNode blockNode = jsonFactory.objectNode();
|
||||
JSONHelper.dumpBlock(blockNode, block, gasUsed, this.getWorldState().getRootHash(), keys, this);
|
||||
|
||||
bw.write(blockNode.toString());
|
||||
bw.write("\n");
|
||||
|
||||
String rootHash = Hex.toHexString(this.getWorldState().getRootHash());
|
||||
bw.write(
|
||||
String.format(" => Global State Root: [ %s ]", rootHash)
|
||||
bw.write(String.format(" => Global State Root: [ %s ]", rootHash)
|
||||
);
|
||||
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -5,8 +5,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.ethereum.util.LRUMap;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
|
|
|
@ -1,15 +1,41 @@
|
|||
package org.ethereum.json;
|
||||
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* JSON Helper class to format data into ObjectNodes
|
||||
* to match PyEthereum blockstate output
|
||||
*
|
||||
* Dump format:
|
||||
* {
|
||||
* "address":
|
||||
* {
|
||||
* "nonce": "n1",
|
||||
* "balance": "b1",
|
||||
* "stateRoot": "s1",
|
||||
* "codeHash": "c1",
|
||||
* "code": "c2",
|
||||
* "storage":
|
||||
* {
|
||||
* "key1": "value1",
|
||||
* "key2": "value2"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
|
@ -17,46 +43,62 @@ import java.util.*;
|
|||
*/
|
||||
public class JSONHelper {
|
||||
|
||||
public static String dumpLine(byte[] address, byte[] nonce, byte[] balance, byte[] stateRoot,
|
||||
byte[] codeHash, byte[] code, Map<DataWord, DataWord> storageMap) {
|
||||
public static void dumpState(ObjectNode statesNode, String address, AccountState state, ContractDetails details) {
|
||||
|
||||
// {address: x, nonce: n1, balance: b1, stateRoot: s1, codeHash: c1, code: c2, sotrage: [key: k1, value: v1, key:k2, value: v2 ] }
|
||||
|
||||
List<DataWord> storageKeys = new ArrayList<DataWord>(storageMap.keySet());
|
||||
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
|
||||
Collections.sort((List<DataWord>) storageKeys);
|
||||
|
||||
Map<String, String> outMap = new LinkedHashMap<String, String>();
|
||||
|
||||
ObjectNode account = statesNode.objectNode();
|
||||
ObjectNode storage = statesNode.objectNode();
|
||||
|
||||
for (DataWord key : storageKeys) {
|
||||
outMap.put(Hex.toHexString(key.getData()),
|
||||
Hex.toHexString(
|
||||
RLP.encodeElement( storageMap.get(key).getNoLeadZeroesData() )
|
||||
));
|
||||
storage.put("0x" + Hex.toHexString(key.getData()),
|
||||
"0x" + Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
|
||||
}
|
||||
|
||||
String mapString = JSONValue.toJSONString(outMap);
|
||||
mapString = mapString.replace("\"", "");
|
||||
|
||||
JSONArray orderFields = new JSONArray();
|
||||
orderFields.add("address: " + Hex.toHexString(address));
|
||||
orderFields.add(" nonce: " + (nonce == null ? "00" : new BigInteger(1, nonce).toString()));
|
||||
orderFields.add(" balance: " + (balance == null ? "00" : new BigInteger(1, balance).toString()));
|
||||
orderFields.add(" stateRoot: " + (stateRoot == null ? "" : Hex.toHexString(stateRoot)));
|
||||
orderFields.add(" codeHash: " + (codeHash == null ? "" : Hex.toHexString(codeHash)));
|
||||
orderFields.add(" code: " + (code == null ? "" : Hex.toHexString(code)));
|
||||
orderFields.add(" storage: " + mapString);
|
||||
|
||||
String out = orderFields.toString();
|
||||
out = out.replace("\"", "");
|
||||
|
||||
return out;
|
||||
account.put("balance", state.getBalance() == null ? "0" : state.getBalance().toString());
|
||||
// account.put("codeHash", details.getCodeHash() == null ? "0x" : "0x" + Hex.toHexString(details.getCodeHash()));
|
||||
account.put("code", details.getCode() == null ? "0x" : "0x" + Hex.toHexString(details.getCode()));
|
||||
account.put("nonce", state.getNonce() == null ? "0" : state.getNonce().toString());
|
||||
account.put("storage", storage);
|
||||
account.put("storage_root", state.getStateRoot() == null ? "" : Hex.toHexString(state.getStateRoot()));
|
||||
|
||||
statesNode.put(address, account);
|
||||
}
|
||||
|
||||
public static void dumpBlock(ObjectNode blockNode, Block block,
|
||||
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
|
||||
Repository repository) {
|
||||
|
||||
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
|
||||
blockNode.put("difficulty", new BigInteger(1, block.calcDifficulty()).toString());
|
||||
blockNode.put("extra_data", "0x");
|
||||
blockNode.put("gas_limit", String.valueOf(block.calcGasLimit()));
|
||||
blockNode.put("gas_used", String.valueOf(gasUsed));
|
||||
blockNode.put("min_gas_price", String.valueOf(block.getMinGasPrice()));
|
||||
blockNode.put("nonce", "0x" + Hex.toHexString(block.getNonce()));
|
||||
blockNode.put("number", String.valueOf(block.getNumber()));
|
||||
blockNode.put("prevhash", "0x" + Hex.toHexString(block.getParentHash()));
|
||||
|
||||
ObjectNode statesNode = blockNode.objectNode();
|
||||
for (ByteArrayWrapper key : keys) {
|
||||
byte[] keyBytes = key.getData();
|
||||
AccountState accountState = repository.getAccountState(keyBytes);
|
||||
ContractDetails details = repository.getContractDetails(keyBytes);
|
||||
JSONHelper.dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details);
|
||||
}
|
||||
blockNode.put("state", statesNode);
|
||||
|
||||
blockNode.put("state_root", Hex.toHexString(state));
|
||||
blockNode.put("timestamp", String.valueOf(block.getTimestamp()));
|
||||
|
||||
ArrayNode transactionsNode = blockNode.arrayNode();
|
||||
blockNode.put("transactions", transactionsNode);
|
||||
|
||||
blockNode.put("tx_list_root", ByteUtil.toHexString(block.getTxTrieRoot()));
|
||||
blockNode.put("uncles_hash", "0x" + Hex.toHexString(block.getUnclesHash()));
|
||||
|
||||
// JSONHelper.dumpTransactions(blockNode,
|
||||
// stateRoot, codeHash, code, storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -10,7 +10,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Blockchain;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.core.Wallet;
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
|
@ -19,10 +18,6 @@ import org.ethereum.listener.EthereumListener;
|
|||
import org.ethereum.net.client.ClientPeer;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.peerdiscovery.PeerDiscovery;
|
||||
import org.ethereum.net.submit.WalletTransaction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* WorldManager is the main class to handle the processing of transactions and
|
||||
|
@ -34,8 +29,6 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class WorldManager {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("main");
|
||||
|
||||
private Blockchain blockchain;
|
||||
private Repository repository;
|
||||
private Wallet wallet;
|
||||
|
@ -44,11 +37,6 @@ public class WorldManager {
|
|||
private List<PeerData> peers = new CopyOnWriteArrayList<PeerData>();
|
||||
private ClientPeer activePeer;
|
||||
|
||||
// This map of transaction designed
|
||||
// to approve the tx by external trusted peer
|
||||
private Map<String, WalletTransaction> walletTransactions =
|
||||
Collections.synchronizedMap(new HashMap<String, WalletTransaction>());
|
||||
|
||||
private EthereumListener listener;
|
||||
|
||||
private static WorldManager instance;
|
||||
|
@ -83,34 +71,7 @@ public class WorldManager {
|
|||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 1) the dialog put a pending transaction on the list
|
||||
* 2) the dialog send the transaction to a net
|
||||
* 3) wherever the transaction got in from the wire it will change to approve state
|
||||
* 4) only after the approve a) Wallet state changes
|
||||
* 5) After the block is received with that tx the pending been clean up
|
||||
*/
|
||||
public WalletTransaction addWalletTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction placed hash: {}", hash );
|
||||
|
||||
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
|
||||
if (walletTransaction != null)
|
||||
walletTransaction.incApproved();
|
||||
else {
|
||||
walletTransaction = new WalletTransaction(transaction);
|
||||
this.walletTransactions.put(hash, walletTransaction);
|
||||
}
|
||||
return walletTransaction;
|
||||
}
|
||||
|
||||
public void removeWalletTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction removed with hash: {} ", hash);
|
||||
walletTransactions.remove(hash);
|
||||
}
|
||||
|
||||
|
||||
public void setRepository(Repository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
List<Transaction> txList = transactionsMessage.getTransactions();
|
||||
for(Transaction tx : txList)
|
||||
WorldManager.getInstance().getBlockchain()
|
||||
.applyTransaction(null, tx, null);
|
||||
.applyTransaction(null, tx);
|
||||
|
||||
logger.info(transactionsMessage.toString());
|
||||
if (peerListener != null) peerListener.console(transactionsMessage.toString());
|
||||
|
|
|
@ -36,11 +36,14 @@ public class StaticMessages {
|
|||
|
||||
String version = SystemProperties.CONFIG.projectVersion();
|
||||
String system = System.getProperty("os.name");
|
||||
if (System.getProperty("java.vm.vendor").contains("Android")) system = "Android";
|
||||
if (system.contains(" "))
|
||||
system = system.substring(0, system.indexOf(" "));
|
||||
if (System.getProperty("java.vm.vendor").contains("Android"))
|
||||
system = "Android";
|
||||
|
||||
String phrase = SystemProperties.CONFIG.helloPhrase();
|
||||
|
||||
String helloAnnouncement = String.format("Ethereum(J)/v%s/Release/%s/%s ", version, system, phrase);
|
||||
String helloAnnouncement = String.format("EthereumJ/v%s/%s/%s/Java", version, phrase, system);
|
||||
|
||||
return new HelloMessage((byte) 0x17, (byte) 0x00,
|
||||
helloAnnouncement, Byte.parseByte("00000111", 2),
|
||||
|
|
|
@ -17,7 +17,7 @@ import static java.lang.Thread.sleep;
|
|||
*/
|
||||
public class TransactionTask implements Callable<Transaction> {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("TransactionTask");
|
||||
private Logger logger = LoggerFactory.getLogger(TransactionTask.class);
|
||||
|
||||
private Transaction tx;
|
||||
|
||||
|
@ -33,17 +33,16 @@ public class TransactionTask implements Callable<Transaction> {
|
|||
|
||||
ClientPeer peer = WorldManager.getInstance().getActivePeer();
|
||||
|
||||
WalletTransaction walletTransaction = WorldManager.getInstance()
|
||||
.addWalletTransaction(tx);
|
||||
WalletTransaction walletTransaction = WorldManager.getInstance().getWallet().addTransaction(tx);
|
||||
peer.sendTransaction(tx);
|
||||
|
||||
while(walletTransaction.getApproved() < 1 ) {
|
||||
while(walletTransaction.getApproved() < 1) {
|
||||
sleep(10);
|
||||
}
|
||||
logger.info("return approved: {}", walletTransaction.getApproved());
|
||||
} catch (Throwable th) {
|
||||
logger.info("exception caugh: {}", th);
|
||||
WorldManager.getInstance().removeWalletTransaction(tx);
|
||||
WorldManager.getInstance().getWallet().removeTransaction(tx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -15,12 +15,10 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
|
||||
public class AdvancedDeviceUtils {
|
||||
|
||||
public static void adjustDetailedTracing(long blockNum){
|
||||
public static void adjustDetailedTracing(long blockNum) {
|
||||
// here we can turn on the detail tracing in the middle of the chain
|
||||
if (blockNum >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) {
|
||||
URL configFile = ClassLoader
|
||||
.getSystemResource("log4j-detailed.properties");
|
||||
|
||||
URL configFile = ClassLoader.getSystemResource("log4j-detailed.properties");
|
||||
PropertyConfigurator.configure(configFile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Stack;
|
|||
* Created on: 01/06/2014 10:45
|
||||
*/
|
||||
public class Program {
|
||||
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("VM");
|
||||
private Logger gasLogger = LoggerFactory.getLogger("gas");
|
||||
private int invokeHash;
|
||||
|
@ -302,7 +302,7 @@ public class Program {
|
|||
trackRepository.commit();
|
||||
|
||||
// 5. REFUND THE REMAIN GAS
|
||||
int refundGas = gas - result.getGasUsed();
|
||||
long refundGas = gas - result.getGasUsed();
|
||||
if (refundGas > 0) {
|
||||
this.refundGas(refundGas, "remain gas from the internal call");
|
||||
if (logger.isInfoEnabled()){
|
||||
|
@ -376,7 +376,6 @@ public class Program {
|
|||
// actual gas subtract
|
||||
this.spendGas(gas.intValue(), "internal call");
|
||||
|
||||
|
||||
Repository trackRepository = result.getRepository().getTrack();
|
||||
trackRepository.startTracking();
|
||||
trackRepository.addBalance(toAddress, endowmentValue.value());
|
||||
|
@ -390,7 +389,6 @@ public class Program {
|
|||
ProgramResult result = null;
|
||||
|
||||
if (programCode != null && programCode.length != 0) {
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
vm.play(program);
|
||||
|
@ -451,7 +449,7 @@ public class Program {
|
|||
result.spendGas(gasValue);
|
||||
}
|
||||
|
||||
public void refundGas(int gasValue, String cause) {
|
||||
public void refundGas(long gasValue, String cause) {
|
||||
gasLogger.info("[{}] Refund for cause: [ {} ], gas: [ {} ]", invokeHash, cause, gasValue);
|
||||
result.refundGas(gasValue);
|
||||
}
|
||||
|
@ -659,6 +657,7 @@ public class Program {
|
|||
public void output(String out);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class OutOfGasException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.List;
|
|||
*/
|
||||
public class ProgramResult {
|
||||
|
||||
private int gasUsed = 0;
|
||||
private long gasUsed = 0;
|
||||
private ByteBuffer hReturn = null;
|
||||
private RuntimeException exception;
|
||||
private List<DataWord> deleteAccounts;
|
||||
|
@ -30,7 +30,7 @@ public class ProgramResult {
|
|||
public void spendGas(int gas) {
|
||||
gasUsed += gas;
|
||||
}
|
||||
public void refundGas(int gas) {
|
||||
public void refundGas(long gas) {
|
||||
gasUsed -= gas;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ public class ProgramResult {
|
|||
return exception;
|
||||
}
|
||||
|
||||
public int getGasUsed() {
|
||||
public long getGasUsed() {
|
||||
return gasUsed;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.vm.Program.OutOfGasException;
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.ethereum.vm.OpCode.CALL;
|
||||
import static org.ethereum.vm.OpCode.CREATE;
|
||||
|
@ -54,9 +59,10 @@ import static org.ethereum.vm.OpCode.PUSH1;
|
|||
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: [ {} ]\t Gas: [ {} ]\t Deep: [ {} ] Hint: [ {} ]";
|
||||
|
||||
|
||||
public void step(Program program) {
|
||||
|
||||
try {
|
||||
|
@ -70,6 +76,34 @@ public class VM {
|
|||
long gasBefore = program.getGas().longValue();
|
||||
int stepBefore = program.getPC();
|
||||
|
||||
|
||||
if(program.getNumber().intValue() == CONFIG.dumpBlock()) {
|
||||
|
||||
switch (OpCode.code(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.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);
|
||||
}
|
||||
|
||||
|
||||
switch (OpCode.code(op)) {
|
||||
case SHA3:
|
||||
program.spendGas(GasCost.SHA3, OpCode.code(op).name());
|
||||
|
@ -108,7 +142,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " + " + word2.longValue();
|
||||
hint = word1.value() + " + " + word2.value();
|
||||
|
||||
word1.add(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -120,7 +154,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " * " + word2.longValue();
|
||||
hint = word1.value() + " * " + word2.value();
|
||||
|
||||
word1.mul(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -131,7 +165,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " - " + word2.longValue();
|
||||
hint = word1.value() + " - " + word2.value();
|
||||
|
||||
word1.sub(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -142,7 +176,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " / " + word2.longValue();
|
||||
hint = word1.value() + " / " + word2.value();
|
||||
|
||||
word1.div(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -164,7 +198,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " % " + word2.longValue();
|
||||
hint = word1.value() + " % " + word2.value();
|
||||
|
||||
word1.mod(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -186,7 +220,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " ** " + word2.longValue();
|
||||
hint = word1.value() + " ** " + word2.value();
|
||||
|
||||
word1.exp(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -197,7 +231,7 @@ public class VM {
|
|||
word1.negate();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "" + word1.longValue();
|
||||
hint = "" + word1.value();
|
||||
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -208,7 +242,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " < " + word2.longValue();
|
||||
hint = word1.value() + " < " + word2.value();
|
||||
|
||||
if (word1.value().compareTo(word2.value()) == -1) {
|
||||
word1.and(DataWord.ZERO);
|
||||
|
@ -259,7 +293,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " < " + word2.longValue();
|
||||
hint = word1.value() + " < " + word2.value();
|
||||
|
||||
if (word1.value().compareTo(word2.value()) == 1) {
|
||||
word1.and(DataWord.ZERO);
|
||||
|
@ -275,7 +309,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " == " + word2.longValue();
|
||||
hint = word1.value() + " == " + word2.value();
|
||||
|
||||
if (word1.xor(word2).isZero()) {
|
||||
word1.and(DataWord.ZERO);
|
||||
|
@ -295,7 +329,7 @@ public class VM {
|
|||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "" + word1.longValue();
|
||||
hint = "" + word1.value();
|
||||
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -309,7 +343,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " && " + word2.longValue();
|
||||
hint = word1.value() + " && " + word2.value();
|
||||
|
||||
word1.and(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -320,7 +354,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " || " + word2.longValue();
|
||||
hint = word1.value() + " || " + word2.value();
|
||||
|
||||
word1.or(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -331,7 +365,7 @@ public class VM {
|
|||
DataWord word2 = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = word1.longValue() + " ^ " + word2.longValue();
|
||||
hint = word1.value() + " ^ " + word2.value();
|
||||
|
||||
word1.xor(word2);
|
||||
program.stackPush(word1);
|
||||
|
@ -351,7 +385,7 @@ public class VM {
|
|||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "" + result.longValue();
|
||||
hint = "" + result.value();
|
||||
|
||||
program.stackPush(result);
|
||||
program.step();
|
||||
|
@ -440,7 +474,7 @@ public class VM {
|
|||
DataWord dataSize = program.getDataSize();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "size: " + dataSize.longValue();
|
||||
hint = "size: " + dataSize.value();
|
||||
|
||||
program.stackPush(dataSize);
|
||||
program.step();
|
||||
|
@ -462,7 +496,7 @@ public class VM {
|
|||
DataWord length = new DataWord(program.ops.length);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "size: " + length.longValue();
|
||||
hint = "size: " + length.value();
|
||||
|
||||
program.stackPush(length);
|
||||
program.step();
|
||||
|
@ -524,7 +558,7 @@ public class VM {
|
|||
DataWord timestamp = program.getTimestamp();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "timestamp: " + timestamp.longValue();
|
||||
hint = "timestamp: " + timestamp.value();
|
||||
|
||||
program.stackPush(timestamp);
|
||||
program.step();
|
||||
|
@ -533,7 +567,7 @@ public class VM {
|
|||
DataWord number = program.getNumber();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "number: " + number.longValue();
|
||||
hint = "number: " + number.value();
|
||||
|
||||
program.stackPush(number);
|
||||
program.step();
|
||||
|
@ -636,7 +670,7 @@ public class VM {
|
|||
DataWord pos = program.stackPop();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "~> " + pos.longValue();
|
||||
hint = "~> " + pos.value();
|
||||
|
||||
program.setPC(pos);
|
||||
} break;
|
||||
|
@ -703,7 +737,7 @@ public class VM {
|
|||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||
.name(), program.getGas().longValue(),
|
||||
.name(), program.getGas().value(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
program.createContract(value, inOffset, inSize);
|
||||
|
@ -723,7 +757,7 @@ public class VM {
|
|||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info(logString, program.getPC(), OpCode.code(op)
|
||||
.name(), program.getGas().longValue(),
|
||||
.name(), program.getGas().value(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
|
||||
|
@ -756,8 +790,8 @@ public class VM {
|
|||
}
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
if (!OpCode.code(op).equals(CALL) && !OpCode.code(op).equals(CREATE))
|
||||
if (logger.isInfoEnabled() && !OpCode.code(op).equals(CALL)
|
||||
&& !OpCode.code(op).equals(CREATE))
|
||||
logger.info(logString, stepBefore, OpCode.code(op).name(),
|
||||
gasBefore, program.invokeData.getCallDeep(), hint);
|
||||
|
||||
|
|
|
@ -21,11 +21,15 @@ log4j.logger.peerdiscovery = ERROR
|
|||
log4j.logger.java.nio = ERROR
|
||||
log4j.logger.io.netty = ERROR
|
||||
log4j.logger.wire = ERROR
|
||||
log4j.logger.wallet = ERROR
|
||||
log4j.logger.VM = DEBUG
|
||||
log4j.logger.dump = OFF
|
||||
log4j.logger.main = INFO
|
||||
log4j.logger.trie = ERROR
|
||||
log4j.logger.state = DEBUG
|
||||
log4j.logger.repository = DEBUG
|
||||
log4j.logger.repository = INFO
|
||||
log4j.logger.blockchain = INFO
|
||||
log4j.logger.ui = ERROR
|
||||
log4j.logger.txs = ERROR
|
||||
log4j.logger.gas = ERROR
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@ log4j.appender.file.RollingPolicy.FileNamePattern=./logs/ethereum_%d{yyyy-MM-dd}
|
|||
|
||||
# filter noisy classes
|
||||
log4j.logger.org.ethereum.core = ERROR
|
||||
log4j.logger.org.ethereum.net = ERROR
|
||||
log4j.logger.org.ethereum.db = ERROR
|
||||
log4j.logger.wallet = ERROR
|
||||
log4j.logger.net = ERROR
|
||||
log4j.logger.db = ERROR
|
||||
log4j.logger.peerdiscovery = ERROR
|
||||
log4j.logger.java.nio = ERROR
|
||||
log4j.logger.io.netty = ERROR
|
||||
|
|
|
@ -25,12 +25,12 @@ peer.discovery.ip.list = 185.43.109.23:30303, \
|
|||
#peer.active.port = 30303
|
||||
|
||||
# RomanJ
|
||||
peer.active.ip = 54.211.14.10
|
||||
peer.active.port = 30303
|
||||
#peer.active.ip = 54.211.14.10
|
||||
#peer.active.port = 30303
|
||||
|
||||
# PoC-5 testnet
|
||||
#peer.active.ip = 185.43.109.23
|
||||
#peer.active.port = 30303
|
||||
peer.active.ip = 185.43.109.23
|
||||
peer.active.port = 30303
|
||||
|
||||
#peer.active.ip = 54.72.69.180
|
||||
#peer.active.port = 30303
|
||||
|
@ -99,6 +99,7 @@ coinbase.secret = monkey
|
|||
# posible values [true/false]
|
||||
dump.full = false
|
||||
dump.dir = dmp
|
||||
dump.block = 1501
|
||||
|
||||
# clean the dump dir each start
|
||||
dump.clean.on.restart = true
|
||||
|
@ -130,7 +131,6 @@ max.blocks.ask = 100
|
|||
# recommended value: [100.300]
|
||||
max.blocks.queued = 300
|
||||
|
||||
|
||||
# project version auto copied during build phase
|
||||
project.version = PROJECT.VERSION
|
||||
|
||||
|
|
|
@ -9,17 +9,20 @@ log4j.appender.stdout.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n
|
|||
|
||||
# filter noisy classes
|
||||
log4j.logger.org.ethereum.core = ERROR
|
||||
log4j.logger.org.ethereum.net = ERROR
|
||||
log4j.logger.org.ethereum.db = ERROR
|
||||
log4j.logger.wallet = ERROR
|
||||
log4j.logger.net = ERROR
|
||||
log4j.logger.db = ERROR
|
||||
log4j.logger.peerdiscovery = ERROR
|
||||
log4j.logger.java.nio = ERROR
|
||||
log4j.logger.io.netty = ERROR
|
||||
log4j.logger.wire = ERROR
|
||||
log4j.logger.VM = OFF
|
||||
log4j.logger.main = INFO
|
||||
log4j.logger.trie = ERROR
|
||||
log4j.logger.state = ERROR
|
||||
log4j.logger.repository = ERROR
|
||||
log4j.logger.blockchain = DEBUG
|
||||
log4j.logger.txs = ERROR
|
||||
log4j.logger.ui = ERROR
|
||||
log4j.logger.gas = ERROR
|
||||
|
||||
|
|
|
@ -74,3 +74,49 @@ database.reset = true
|
|||
# to be eventually the address
|
||||
# that get the miner reward
|
||||
coinbase.secret = monkey
|
||||
|
||||
# for testing purposes
|
||||
# all the state will be dumped
|
||||
# in JSON form to [dump.dir]
|
||||
# if [dump.full] = true
|
||||
# posible values [true/false]
|
||||
dump.full = false
|
||||
dump.dir = dmp
|
||||
dump.block = 1501
|
||||
|
||||
# clean the dump dir each start
|
||||
dump.clean.on.restart = true
|
||||
|
||||
# make changes to tracing options
|
||||
# starting from certain block
|
||||
# -1 don't make any tracing changes
|
||||
trace.startblock = -1
|
||||
|
||||
# invoke vm program on
|
||||
# message received,
|
||||
# if the vm is not invoked
|
||||
# the balance transfer
|
||||
# occurs anyway [true/false]
|
||||
play.vm = true
|
||||
|
||||
# maximum blocks to ask,
|
||||
# when downloading the chain
|
||||
# sequenteally sending GET_CHAIN msg
|
||||
# we specify number of block we want
|
||||
# to get, recomendec value [1..100]
|
||||
max.blocks.ask = 100
|
||||
|
||||
# the network layer will ask for
|
||||
# more and more blocks independently
|
||||
# from how much of them been executed
|
||||
# how much block we will keep in buffer
|
||||
# until the execution is set by this param
|
||||
# recommended value: [100.300]
|
||||
max.blocks.queued = 300
|
||||
|
||||
# project version auto copied during build phase
|
||||
project.version = PROJECT.VERSION
|
||||
|
||||
# hello phrase will be included in
|
||||
# the hello message of the peer
|
||||
hello.phrase = RJ
|
Loading…
Reference in New Issue