From 2b42ebaac2cad23b570f04777844741e95bf7c33 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 13:48:38 +0200 Subject: [PATCH] Use Repository as abstraction layer for Blockchain --- .../main/java/org/ethereum/core/Block.java | 2 +- .../java/org/ethereum/core/Blockchain.java | 331 ++++++++++++++---- .../java/org/ethereum/db/ContractDetails.java | 10 +- .../main/java/org/ethereum/db/Repository.java | 121 +++++-- .../org/ethereum/facade/EthereumImpl.java | 4 +- .../org/ethereum/gui/BlockChainTable.java | 10 +- .../org/ethereum/gui/BlockTableModel.java | 4 +- .../org/ethereum/gui/ContractCallDialog.java | 2 +- .../ethereum/gui/ContractSubmitDialog.java | 4 +- .../java/org/ethereum/gui/PayOutDialog.java | 4 +- .../main/java/org/ethereum/gui/ToolBar.java | 3 +- .../org/ethereum/manager/WorldManager.java | 272 +------------- .../java/org/ethereum/net/BlockQueue.java | 10 +- .../net/client/EthereumFrameDecoder.java | 1 - .../net/client/EthereumProtocolHandler.java | 9 +- .../ethereum/net/message/GetChainMessage.java | 2 +- .../ethereum/net/message/GetPeersMessage.java | 2 +- .../org/ethereum/net/message/PingMessage.java | 10 +- .../main/java/org/ethereum/trie/Cache.java | 5 +- .../src/main/java/org/ethereum/trie/Trie.java | 4 + .../ethereum/util/AdvancedDeviceUtils.java | 3 - .../org/ethereum/vm/ProgramInvokeFactory.java | 2 +- .../main/resources/log4j-detailed.properties | 4 +- .../src/main/resources/log4j.properties | 4 +- .../src/main/resources/system.properties | 2 +- .../java/org/ethereum/core/BlockTest.java | 4 +- 26 files changed, 421 insertions(+), 408 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Block.java b/ethereumj-core/src/main/java/org/ethereum/core/Block.java index 0cfb9088..745f13c6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -110,7 +110,7 @@ public class Block { } public Block getParent() { - return WorldManager.getInstance().getBlockChain().getByNumber(this.getNumber() - 1); + return WorldManager.getInstance().getBlockchain().getByNumber(this.getNumber() - 1); } public byte[] getParentHash() { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java index 3afb32ae..34a532e0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -1,17 +1,18 @@ package org.ethereum.core; -import org.ethereum.db.DatabaseImpl; +import org.ethereum.db.Repository; import org.ethereum.listener.EthereumListener; import org.ethereum.manager.WorldManager; +import org.ethereum.net.BlockQueue; import org.ethereum.util.AdvancedDeviceUtils; -import org.ethereum.util.ByteUtil; -import org.iq80.leveldb.DBIterator; +import org.ethereum.vm.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; -import java.io.IOException; +import java.math.BigInteger; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -53,21 +54,39 @@ import static org.ethereum.core.Denomination.SZABO; public class Blockchain { private static Logger logger = LoggerFactory.getLogger("blockchain"); + private static Logger stateLogger = LoggerFactory.getLogger("state"); // to avoid using minGasPrice=0 from Genesis for the wallet private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue(); - - private DatabaseImpl chainDb; - + + private Repository repository; private Block lastBlock; // keep the index of the chain for // convenient usage, - private Map index = new HashMap<>(); + private Map blockCache = new HashMap<>(); + + private Map pendingTransactions = Collections + .synchronizedMap(new HashMap()); + + private BlockQueue blockQueue = new BlockQueue(); - public Blockchain() { - this.chainDb = new DatabaseImpl("blockchain"); + public Blockchain(Repository repository) { + this.repository = repository; } + + public BlockQueue getBlockQueue() { + return blockQueue; + } + + public Map getBlockCache() { + return this.blockCache; + } + + public long getGasPrice() { + // In case of the genesis block we don't want to rely on the min gas price + return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE; + } public Block getLastBlock() { return lastBlock; @@ -77,12 +96,19 @@ public class Blockchain { this.lastBlock = block; } + public byte[] getLatestBlockHash() { + if (blockCache.isEmpty()) + return Genesis.getInstance().getHash(); + else + return getLastBlock().getHash(); + } + public int getSize() { - return index.size(); + return blockCache.size(); } public Block getByNumber(long blockNr) { - return new Block(chainDb.get(ByteUtil.longToBytes(blockNr))); + return repository.getBlock(blockNr); } public void add(Block block) { @@ -92,13 +118,13 @@ public class Blockchain { // if it is the first block to add // make sure the parent is genesis - if (index.isEmpty() + if (blockCache.isEmpty() && !Arrays.equals(Genesis.getInstance().getHash(), block.getParentHash())) { return; } // if there is some blocks already keep chain continuity - if (!index.isEmpty()) { + if (!blockCache.isEmpty()) { String hashLast = Hex.toHexString(getLastBlock().getHash()); String blockParentHash = Hex.toHexString(block.getParentHash()); if (!hashLast.equals(blockParentHash)) return; @@ -120,16 +146,7 @@ public class Blockchain { EthereumListener listener = WorldManager.getInstance().getListener(); if (listener != null) listener.trace(String.format("Block chain size: [ %d ]", this.getSize())); - -/* - if (lastBlock.getNumber() >= 30) { - System.out.println("** checkpoint **"); - this.close(); - WorldManager.getInstance().getRepository().close(); - System.exit(1); - } -*/ } public void processBlock(Block block) { @@ -138,7 +155,7 @@ public class Blockchain { for (Transaction tx : block.getTransactionsList()) // TODO: refactor the wallet pending transactions to the world manager WorldManager.getInstance().addWalletTransaction(tx); - WorldManager.getInstance().applyBlock(block); + this.applyBlock(block); WorldManager.getInstance().getWallet().processBlock(block); } this.storeBlock(block); @@ -147,7 +164,7 @@ public class Blockchain { } } - private void storeBlock(Block block) { + public void storeBlock(Block block) { /* Debug check to see if the state is still as expected */ if(logger.isWarnEnabled()) { String blockStateRootHash = Hex.toHexString(block.getStateRoot()); @@ -155,12 +172,13 @@ public class Blockchain { if(!blockStateRootHash.equals(worldStateRootHash)){ logger.error("ERROR: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash); // Last conflict on block 1157 -> worldstate b1d9a978451ef04c1639011d9516473d51c608dbd25906c89be791707008d2de + repository.close(); System.exit(-1); // Don't add block } } - this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); - this.index.put(block.getNumber(), block.getHash()); + this.repository.saveBlock(block); + this.blockCache.put(block.getNumber(), block.getHash()); this.setLastBlock(block); if (logger.isDebugEnabled()) @@ -168,46 +186,233 @@ public class Blockchain { logger.info("*** Block chain size: [ {} ]", this.getSize()); } - public long getGasPrice() { - // In case of the genesis block we don't want to rely on the min gas price - return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE; - } + public void applyBlock(Block block) { + + int i = 0; + for (Transaction tx : block.getTransactionsList()) { + stateLogger.debug("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i); + applyTransaction(block, tx, block.getCoinbase()); + repository.dumpState(block.getNumber(), i, tx.getHash()); + ++i; - public byte[] getLatestBlockHash() { - if (index.isEmpty()) - return Genesis.getInstance().getHash(); - else - return getLastBlock().getHash(); - } + } + + // miner reward + if (repository.getAccountState(block.getCoinbase()) == null) + repository.createAccount(block.getCoinbase()); + repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD); + for (Block uncle : block.getUncleList()) { + repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); + } + + repository.dumpState(block.getNumber(), 0, + null); + } - public void load() { - DBIterator iterator = chainDb.iterator(); - try { - if (!iterator.hasNext()) { - logger.info("DB is empty - adding Genesis"); - this.lastBlock = Genesis.getInstance(); - this.storeBlock(lastBlock); - logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString()); - } else { - logger.debug("Displaying blocks stored in DB sorted on blocknumber"); - for (iterator.seekToFirst(); iterator.hasNext();) { - this.lastBlock = new Block(iterator.next().getValue()); - this.index.put(lastBlock.getNumber(), lastBlock.getHash()); - logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString()); - } - } - } finally { - // Make sure you close the iterator to avoid resource leaks. - try { - iterator.close(); - } catch (IOException e) { - logger.error(e.getMessage(), e); + public void applyTransaction(Block block, Transaction tx, byte[] coinbase) { + + byte[] senderAddress = tx.getSender(); + AccountState senderAccount = repository.getAccountState(senderAddress); + + if (senderAccount == null) { + if (stateLogger.isWarnEnabled()) + stateLogger.warn("No such address: {}", + Hex.toHexString(senderAddress)); + return; + } + + // 1. VALIDATE THE NONCE + BigInteger nonce = senderAccount.getNonce(); + BigInteger txNonce = new BigInteger(1, tx.getNonce()); + if (nonce.compareTo(txNonce) != 0) { + if (stateLogger.isWarnEnabled()) + stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}", + nonce, txNonce); + return; + } + + // 3. FIND OUT THE TRANSACTION TYPE + byte[] receiverAddress, code = null; + boolean isContractCreation = tx.isContractCreation(); + if (isContractCreation) { + receiverAddress = tx.getContractAddress(); + repository.createAccount(receiverAddress); + if(stateLogger.isDebugEnabled()) + stateLogger.debug("new contract created address={}", + Hex.toHexString(receiverAddress)); + code = tx.getData(); // init code + if (stateLogger.isDebugEnabled()) + stateLogger.debug("running the init for contract: address={}", + Hex.toHexString(receiverAddress)); + } else { + receiverAddress = tx.getReceiveAddress(); + AccountState receiverState = repository.getAccountState(receiverAddress); + if (receiverState == null) { + repository.createAccount(receiverAddress); + if (stateLogger.isDebugEnabled()) + stateLogger.debug("new receiver account created address={}", + Hex.toHexString(receiverAddress)); + } else { + code = repository.getCode(receiverAddress); + if (code != null) { + if (stateLogger.isDebugEnabled()) + stateLogger.debug("calling for existing contract: address={}", + Hex.toHexString(receiverAddress)); + } } } + + // 2.1 UPDATE THE NONCE + // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) + repository.increaseNonce(senderAddress); + + // 2.2 PERFORM THE GAS VALUE TX + // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) + BigInteger gasDebit = tx.getTotalGasValueDebit(); + + // Debit the actual total gas value from the sender + // the purchased gas will be available for + // the contract in the execution state, + // it can be retrieved using GAS op + if (gasDebit.signum() == 1) { + BigInteger balance = senderAccount.getBalance(); + if (balance.compareTo(gasDebit) == -1) { + logger.debug("No gas to start the execution: sender={}", + Hex.toHexString(senderAddress)); + return; + } + repository.addBalance(senderAddress, gasDebit.negate()); + + // The coinbase get the gas cost + if (coinbase != null) + repository.addBalance(coinbase, gasDebit); + + if (stateLogger.isDebugEnabled()) + stateLogger.debug( + "Before contract execution debit the sender address with gas total cost, " + + "\n sender={} \n gas_debit= {}", + 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={}", + Hex.toHexString(senderAddress), + Hex.toHexString(receiverAddress), + new BigInteger(tx.getValue())); + } + } + + // 5. CREATE OR EXECUTE PROGRAM + if (isContractCreation || code != null) { + Block currBlock = (block == null) ? this.getLastBlock() : block; + + ProgramInvoke programInvoke = ProgramInvokeFactory + .createProgramInvoke(tx, currBlock, trackRepository); + + VM vm = new VM(); + Program program = new Program(code, programInvoke); + + if (CONFIG.playVM()) + vm.play(program); + ProgramResult result = program.getResult(); + applyProgramResult(result, gasDebit, trackRepository, + senderAddress, receiverAddress, coinbase, isContractCreation); + } 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)); + if (refund.signum() > 0) { + // gas refund + repository.addBalance(senderAddress, refund); + repository.addBalance(coinbase, refund.negate()); + } + } + } catch (RuntimeException e) { + trackRepository.rollback(); + return; + } + trackRepository.commit(); + pendingTransactions.put(Hex.toHexString(tx.getHash()), tx); } - public void close() { - if (this.chainDb != null) - chainDb.close(); - } + /** + * After any contract code finish the run the certain result should take + * place, according the given circumstances + * + * @param result + * @param gasDebit + * @param senderAddress + * @param contractAddress + */ + private void applyProgramResult(ProgramResult result, BigInteger gasDebit, + Repository repository, byte[] senderAddress, + byte[] contractAddress, byte[] coinbase, boolean initResults) { + + if (result.getException() != null + && result.getException() instanceof Program.OutOfGasException) { + stateLogger.debug("contract run halted by OutOfGas: contract={}", + Hex.toHexString(contractAddress)); + throw result.getException(); + } + + BigInteger gasPrice = BigInteger.valueOf(this.getGasPrice()); + BigInteger refund = gasDebit.subtract(BigInteger.valueOf( + result.getGasUsed()).multiply(gasPrice)); + + if (refund.signum() > 0) { + if (stateLogger.isDebugEnabled()) + stateLogger + .debug("After contract execution the sender address refunded with gas leftover, " + + "\n sender={} \n contract={} \n gas_refund= {}", + Hex.toHexString(senderAddress), + Hex.toHexString(contractAddress), refund); + // gas refund + repository.addBalance(senderAddress, refund); + repository.addBalance(coinbase, refund.negate()); + } + + if (initResults) { + // Save the code created by init + byte[] bodyCode = null; + if (result.getHReturn() != null) { + bodyCode = result.getHReturn().array(); + } + + if (bodyCode != null) { + if (stateLogger.isDebugEnabled()) + stateLogger + .debug("saving code of the contract to the db:\n contract={} code={}", + Hex.toHexString(contractAddress), + Hex.toHexString(bodyCode)); + repository.saveCode(contractAddress, bodyCode); + } + } + + // delete the marked to die accounts + if (result.getDeleteAccounts() == null) return; + for (DataWord address : result.getDeleteAccounts()){ + repository.delete(address.getNoLeadZeroesData()); + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java b/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java index 706696ee..f2520039 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java @@ -23,15 +23,15 @@ public class ContractDetails { private byte[] rlpEncoded; - private List storageKeys = new ArrayList(); - private List storageValues = new ArrayList(); + private List storageKeys = new ArrayList<>(); + private List storageValues = new ArrayList<>(); private byte[] code; private Trie storageTrie = new Trie(null); - public ContractDetails() { - } + public ContractDetails() { + } public ContractDetails(byte[] rlpCode) { decode(rlpCode); @@ -165,7 +165,7 @@ public class ContractDetails { } public Map getStorage() { - Map storage = new HashMap(); + Map storage = new HashMap<>(); for (int i = 0; storageKeys != null && i < storageKeys.size(); ++i) { storage.put(storageKeys.get(i), storageValues.get(i)); } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java index 7f90df9d..1de3bc7b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java @@ -2,6 +2,9 @@ package org.ethereum.db; import org.codehaus.plexus.util.FileUtils; import org.ethereum.core.AccountState; +import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; import org.ethereum.crypto.HashUtil; import org.ethereum.json.JSONHelper; import org.ethereum.manager.WorldManager; @@ -9,6 +12,7 @@ import org.ethereum.trie.TrackTrie; import org.ethereum.trie.Trie; import org.ethereum.util.ByteUtil; import org.ethereum.vm.DataWord; +import org.iq80.leveldb.DBIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.BigIntegers; @@ -56,18 +60,25 @@ public class Repository { // TODO: Listeners listeners // TODO: cash impl - private DatabaseImpl detailsDB = null; - private DatabaseImpl stateDB = null; - + private DatabaseImpl chainDB = null; + private DatabaseImpl detailsDB = null; + private DatabaseImpl stateDB = null; + + /** + * Create a new Repository DAO + * assuming empty db and thus no stateRoot + * + * @See loadBlockchain() to update the stateRoot + */ public Repository() { - detailsDB = new DatabaseImpl("details"); - contractDetailsDB = new TrackDatabase(detailsDB); - stateDB = new DatabaseImpl("state"); - worldState = new Trie(stateDB.getDb()); - accountStateDB = new TrackTrie(worldState); + chainDB = new DatabaseImpl("blockchain"); + detailsDB = new DatabaseImpl("details"); + contractDetailsDB = new TrackDatabase(detailsDB); + stateDB = new DatabaseImpl("state"); + worldState = new Trie(stateDB.getDb()); + accountStateDB = new TrackTrie(worldState); } - private Repository(TrackTrie accountStateDB, TrackDatabase contractDetailsDB) { this.accountStateDB = accountStateDB; this.contractDetailsDB = contractDetailsDB; @@ -80,27 +91,72 @@ public class Repository { } public void startTracking() { - logger.info("start tracking"); + logger.debug("start tracking"); accountStateDB.startTrack(); contractDetailsDB.startTrack(); } public void commit() { - logger.info("commit changes"); + logger.debug("commit changes"); accountStateDB.commitTrack(); contractDetailsDB.commitTrack(); } public void rollback() { - logger.info("rollback changes"); + logger.debug("rollback changes"); accountStateDB.rollbackTrack(); contractDetailsDB.rollbackTrack(); } + + public Block getBlock(long blockNr) { + return new Block(chainDB.get(ByteUtil.longToBytes(blockNr))); + } + + public void saveBlock(Block block) { + this.chainDB.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); + } + + public Blockchain loadBlockchain() { + Blockchain blockchain = new Blockchain(this); + DBIterator iterator = chainDB.iterator(); + try { + if (!iterator.hasNext()) { + logger.info("DB is empty - adding Genesis"); + blockchain.storeBlock(Genesis.getInstance()); + logger.debug("Block #{} -> {}", Genesis.NUMBER, blockchain.getLastBlock().toFlatString()); + } else { + logger.debug("Displaying blocks stored in DB sorted on blocknumber"); + + for (iterator.seekToFirst(); iterator.hasNext();) { + Block block = new Block(iterator.next().getValue()); + blockchain.getBlockCache().put(block.getNumber(), block.getHash()); + blockchain.setLastBlock(block); + logger.debug("Block #{} -> {}", block.getNumber(), block.toFlatString()); + } + logger.info( + "*** Loaded up to block [ {} ] with stateRoot [ {} ]", + blockchain.getLastBlock().getNumber(), Hex + .toHexString(blockchain.getLastBlock() + .getStateRoot())); + } + } finally { + // Make sure you close the iterator to avoid resource leaks. + try { + iterator.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + // Update world state to latest loaded block from db + this.worldState.setRoot(blockchain.getLastBlock().getStateRoot()); + return blockchain; + } + public AccountState createAccount(byte[] addr) { this.validateAddress(addr); - + // 1. Save AccountState AccountState state = new AccountState(); accountStateDB.update(addr, state.getEncoded()); @@ -109,8 +165,8 @@ public class Repository { ContractDetails details = new ContractDetails(); contractDetailsDB.put(addr, details.getEncoded()); - if (logger.isInfoEnabled()) - logger.info("New account created: [ {} ]", Hex.toHexString(addr)); + if (logger.isDebugEnabled()) + logger.debug("New account created: [ {} ]", Hex.toHexString(addr)); return state; } @@ -122,12 +178,10 @@ public class Repository { public AccountState getAccountState(byte[] addr) { this.validateAddress(addr); - + byte[] accountStateRLP = accountStateDB.get(addr); if (accountStateRLP.length == 0) { - if (logger.isInfoEnabled()) - logger.info("No account: [ {} ]", Hex.toHexString(addr)); return null; } AccountState state = new AccountState(accountStateRLP); @@ -138,18 +192,17 @@ public class Repository { this.validateAddress(addr); - if (logger.isInfoEnabled()) - logger.info("Account: [ {} ]", Hex.toHexString(addr)); + if (logger.isDebugEnabled()) + logger.debug("Get contract details for: [ {} ]", Hex.toHexString(addr)); byte[] accountDetailsRLP = contractDetailsDB.get(addr); - if (accountDetailsRLP == null) { return null; } - if (logger.isInfoEnabled()) - logger.info("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP)); + if (logger.isDebugEnabled()) + logger.debug("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP)); ContractDetails details = new ContractDetails(accountDetailsRLP); return details; @@ -167,8 +220,8 @@ public class Repository { BigInteger newBalance = state.addToBalance(value); - if (logger.isInfoEnabled()) - logger.info("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]", Hex.toHexString(addr), newBalance.toString(), value); accountStateDB.update(addr, state.getEncoded()); @@ -197,8 +250,8 @@ public class Repository { if (state == null) return BigInteger.ZERO; state.incrementNonce(); - if (logger.isInfoEnabled()) - logger.info("Incerement nonce: account: [ {} ] new nonce: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Incerement nonce: account: [ {} ] new nonce: [ {} ]", Hex.toHexString(addr), state.getNonce().longValue()); accountStateDB.update(addr, state.getEncoded()); @@ -219,8 +272,8 @@ public class Repository { byte[] storageHash = details.getStorageHash(); state.setStateRoot(storageHash); - if (logger.isInfoEnabled()) - logger.info("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]", Hex.toHexString(addr), Hex.toHexString(key.getNoLeadZeroesData()), Hex.toHexString(value.getNoLeadZeroesData()), @@ -272,8 +325,8 @@ public class Repository { byte[] codeHash = HashUtil.sha3(code); state.setCodeHash(codeHash); - if (logger.isInfoEnabled()) - logger.info("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]", Hex.toHexString(addr), Hex.toHexString(codeHash), Hex.toHexString(code)); @@ -302,7 +355,7 @@ public class Repository { return stateDB.dumpKeys(); } - public void dumpState(long blockNumber, int txNumber, String txHash) { + public void dumpState(long blockNumber, int txNumber, byte[] txHash) { if (!CONFIG.dumpFull()) return; @@ -318,7 +371,7 @@ public class Repository { String fileName = ""; if (txHash != null) fileName = String.format("%d_%d_%s.dmp", - blockNumber, txNumber, txHash.substring(0, 8)); + blockNumber, txNumber, Hex.toHexString(txHash).substring(0, 8)); else fileName = String.format("%d_c.dmp", blockNumber); @@ -381,6 +434,8 @@ public class Repository { worldState.sync(); } + if (this.chainDB != null) + chainDB.close(); if (this.stateDB != null) stateDB.close(); if (this.detailsDB != null) diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index f7fb5754..7b6c4c1b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -85,13 +85,13 @@ public class EthereumImpl implements Ethereum { @Override public Block getBlockByIndex(long index){ - Block block = WorldManager.getInstance().getBlockChain().getByNumber(index); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(index); return block; } @Override public long getBlockChainSize(){ - return WorldManager.getInstance().getBlockChain().getSize(); + return WorldManager.getInstance().getBlockchain().getSize(); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java index 0a1d0fbf..9c008179 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java @@ -74,9 +74,9 @@ public class BlockChainTable extends JFrame { @Override public void actionPerformed(ActionEvent e) { - if (WorldManager.getInstance().getBlockChain().getSize() - 1 < lastFindIndex) return; + if (WorldManager.getInstance().getBlockchain().getSize() - 1 < lastFindIndex) return; - Block block = WorldManager.getInstance().getBlockChain().getByNumber(lastFindIndex); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(lastFindIndex); StringSelection stsel = new StringSelection(block.toString()); Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard(); system.setContents(stsel,stsel); @@ -96,10 +96,10 @@ public class BlockChainTable extends JFrame { return; } - for (int i = lastFindIndex + 1; i < WorldManager.getInstance().getBlockChain().getSize(); ++i) { + for (int i = lastFindIndex + 1; i < WorldManager.getInstance().getBlockchain().getSize(); ++i) { - if (WorldManager.getInstance().getBlockChain().getSize() - 1 < i) return; - Block block = WorldManager.getInstance().getBlockChain().getByNumber(i); + if (WorldManager.getInstance().getBlockchain().getSize() - 1 < i) return; + Block block = WorldManager.getInstance().getBlockchain().getByNumber(i); boolean found = block.toString().toLowerCase().contains(toFind.toLowerCase()); if (found) { // TODO: now we find the first occur diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java b/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java index d74685d8..b28fcfe7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java @@ -16,7 +16,7 @@ public class BlockTableModel extends AbstractTableModel { public int getRowCount() { fireTableDataChanged(); - int rowCount = WorldManager.getInstance().getBlockChain().getSize(); + int rowCount = WorldManager.getInstance().getBlockchain().getSize(); return rowCount; } @@ -31,7 +31,7 @@ public class BlockTableModel extends AbstractTableModel { // byte[] hash = MainData.instance.getAllBlocks().get(rowIndex).getHash(); // return Hex.toHexString(hash); - Block block = WorldManager.getInstance().getBlockChain().getByNumber(rowIndex); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(rowIndex); if (block == null) return ""; return block.toString(); diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java index 786d536d..a5884d1c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java @@ -315,7 +315,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog { Transaction tx = createTransaction(); if (tx == null) return; - ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.getInstance().getBlockChain().getLastBlock()); + ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.getInstance().getBlockchain().getLastBlock()); } protected JRootPane createRootPane() { diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java index 83c37c5c..c65efc06 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java @@ -107,7 +107,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog { contractAddrInput.setText(Hex.toHexString(tx.getContractAddress())); ProgramPlayDialog.createAndShowGUI(tx.getData(), tx, - WorldManager.getInstance().getBlockChain().getLastBlock()); + WorldManager.getInstance().getBlockchain().getLastBlock()); }} ); @@ -301,7 +301,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog { Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount(); BigInteger currentBalance = account.getBalance(); - BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice()); + BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockchain().getGasPrice()); BigInteger gasInput = new BigInteger( this.gasInput.getText()); boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0; diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java index c09a4a1c..c6c5c779 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java @@ -118,7 +118,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog { byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes(); byte[] nonce = accountState.getNonce() == BigInteger.ZERO ? null : accountState.getNonce().toByteArray(); - byte[] gasPrice = BigInteger.valueOf( WorldManager.getInstance().getBlockChain().getGasPrice()).toByteArray(); + byte[] gasPrice = BigInteger.valueOf( WorldManager.getInstance().getBlockchain().getGasPrice()).toByteArray(); Transaction tx = new Transaction(nonce, gasPrice, BigIntegers .asUnsignedByteArray(fee), address, BigIntegers @@ -193,7 +193,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog { // check if the tx is affordable BigInteger ammountValue = new BigInteger(amountText); BigInteger feeValue = new BigInteger(feeText); - BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice()); + BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockchain().getGasPrice()); BigInteger currentBalance = accountState.getBalance(); boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1; diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java index dc5b18be..5ef3d042 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; + import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -225,7 +226,7 @@ public class ToolBar extends JFrame { cp.add(chainToggle); cp.add(walletToggle); - WorldManager.getInstance(); + WorldManager.getInstance().loadBlockchain(); } public static void main(String args[]) { diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index 80e1e45d..66a709c8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -8,7 +8,6 @@ import java.net.UnknownHostException; import java.util.*; import org.ethereum.core.AccountState; -import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.Transaction; import org.ethereum.core.Wallet; @@ -16,12 +15,10 @@ import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.db.Repository; import org.ethereum.listener.EthereumListener; -import org.ethereum.net.BlockQueue; 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.ethereum.vm.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -37,7 +34,6 @@ import org.spongycastle.util.encoders.Hex; public class WorldManager { private Logger logger = LoggerFactory.getLogger("main"); - private Logger stateLogger = LoggerFactory.getLogger("state"); private Blockchain blockchain; private Repository repository; @@ -47,9 +43,6 @@ public class WorldManager { private List peers = Collections.synchronizedList(new ArrayList()); private ClientPeer activePeer; - private Map pendingTransactions = Collections - .synchronizedMap(new HashMap()); - // This map of transaction designed // to approve the tx by external trusted peer private Map walletTransactions = @@ -59,12 +52,10 @@ public class WorldManager { private static WorldManager instance; - private BlockQueue blockQueue = new BlockQueue(); - - public WorldManager() { - this.blockchain = new Blockchain(); + private WorldManager() { this.repository = new Repository(); - + this.blockchain = new Blockchain(repository); + // Initialize PeerData try { InetAddress ip = InetAddress.getByName(CONFIG.peerDiscoveryIP()); @@ -94,246 +85,9 @@ public class WorldManager { public static WorldManager getInstance() { if(instance == null) { instance = new WorldManager(); - instance.blockchain.load(); } return instance; } - - public void applyTransaction(Block block, Transaction tx, byte[] coinbase) { - - byte[] senderAddress = tx.getSender(); - AccountState senderAccount = repository.getAccountState(senderAddress); - - if (senderAccount == null) { - if (stateLogger.isWarnEnabled()) - stateLogger.warn("No such address: {}", - Hex.toHexString(senderAddress)); - return; - } - - // 1. VALIDATE THE NONCE - BigInteger nonce = senderAccount.getNonce(); - BigInteger txNonce = new BigInteger(1, tx.getNonce()); - if (nonce.compareTo(txNonce) != 0) { - if (stateLogger.isWarnEnabled()) - stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}", - nonce, txNonce); - return; - } - - // 3. FIND OUT THE TRANSACTION TYPE - byte[] receiverAddress, code = null; - boolean isContractCreation = tx.isContractCreation(); - if (isContractCreation) { - receiverAddress = tx.getContractAddress(); - repository.createAccount(receiverAddress); - stateLogger.info("New contract created address={}", - Hex.toHexString(receiverAddress)); - code = tx.getData(); // init code - if (logger.isInfoEnabled()) - logger.info("running the init for contract: address={}", - Hex.toHexString(receiverAddress)); - } else { - receiverAddress = tx.getReceiveAddress(); - AccountState receiverState = repository.getAccountState(receiverAddress); - if (receiverState == null) { - repository.createAccount(receiverAddress); - if (stateLogger.isInfoEnabled()) - stateLogger.info("New receiver account created address={}", - Hex.toHexString(receiverAddress)); - } else { - code = repository.getCode(receiverAddress); - if (code != null) { - if (logger.isInfoEnabled()) - logger.info("calling for existing contract: address={}", - Hex.toHexString(receiverAddress)); - } - } - } - - // 2.1 UPDATE THE NONCE - // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) - repository.increaseNonce(senderAddress); - - // 2.2 PERFORM THE GAS VALUE TX - // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) - BigInteger gasDebit = tx.getTotalGasValueDebit(); - - // Debit the actual total gas value from the sender - // the purchased gas will be available for - // the contract in the execution state, - // it can be retrieved using GAS op - if (gasDebit.signum() == 1) { - BigInteger balance = senderAccount.getBalance(); - if (balance.compareTo(gasDebit) == -1) { - logger.info("No gas to start the execution: sender={}", - Hex.toHexString(senderAddress)); - return; - } - repository.addBalance(senderAddress, gasDebit.negate()); - - // The coinbase get the gas cost - if (coinbase != null) - repository.addBalance(coinbase, gasDebit); - - - if (stateLogger.isInfoEnabled()) - stateLogger.info( - "Before contract execution debit the sender address with gas total cost, " - + "\n sender={} \n gas_debit= {}", - 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.isInfoEnabled()) - stateLogger.info("Update value balance \n " - + "sender={}, receiver={}, value={}", - Hex.toHexString(senderAddress), - Hex.toHexString(receiverAddress), - new BigInteger(tx.getValue())); - } - } - - // 5. CREATE OR EXECUTE PROGRAM - if (isContractCreation || code != null) { - Block currBlock = (block == null) ? blockchain.getLastBlock() : block; - - ProgramInvoke programInvoke = ProgramInvokeFactory - .createProgramInvoke(tx, currBlock, trackRepository); - - VM vm = new VM(); - Program program = new Program(code, programInvoke); - - if (CONFIG.playVM()) - vm.play(program); - ProgramResult result = program.getResult(); - applyProgramResult(result, gasDebit, trackRepository, - senderAddress, receiverAddress, coinbase, isContractCreation); - } 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)); - if (refund.signum() > 0) { - // gas refund - repository.addBalance(senderAddress, refund); - repository.addBalance(coinbase, refund.negate()); - } - } - } catch (RuntimeException e) { - trackRepository.rollback(); - return; - } - trackRepository.commit(); - pendingTransactions.put(Hex.toHexString(tx.getHash()), tx); - } - - /** - * After any contract code finish the run the certain result should take - * place, according the given circumstances - * - * @param result - * @param gasDebit - * @param senderAddress - * @param contractAddress - */ - private void applyProgramResult(ProgramResult result, BigInteger gasDebit, - Repository repository, byte[] senderAddress, - byte[] contractAddress, byte[] coinbase, boolean initResults) { - - if (result.getException() != null - && result.getException() instanceof Program.OutOfGasException) { - logger.info("contract run halted by OutOfGas: contract={}", - Hex.toHexString(contractAddress)); - throw result.getException(); - } - - BigInteger gasPrice = BigInteger.valueOf(blockchain.getGasPrice()); - BigInteger refund = gasDebit.subtract(BigInteger.valueOf( - result.getGasUsed()).multiply(gasPrice)); - - if (refund.signum() > 0) { - if (stateLogger.isInfoEnabled()) - stateLogger - .info("After contract execution the sender address refunded with gas leftover, " - + "\n sender={} \n contract={} \n gas_refund= {}", - Hex.toHexString(senderAddress), - Hex.toHexString(contractAddress), refund); - // gas refund - repository.addBalance(senderAddress, refund); - repository.addBalance(coinbase, refund.negate()); - } - - if (initResults) { - // Save the code created by init - byte[] bodyCode = null; - if (result.getHReturn() != null) { - bodyCode = result.getHReturn().array(); - } - - if (bodyCode != null) { - repository.saveCode(contractAddress, bodyCode); - if (stateLogger.isInfoEnabled()) - stateLogger - .info("saving code of the contract to the db:\n contract={} code={}", - Hex.toHexString(contractAddress), - Hex.toHexString(bodyCode)); - } - } - - // delete the marked to die accounts - if (result.getDeleteAccounts() == null) return; - for (DataWord address : result.getDeleteAccounts()){ - repository.delete(address.getNoLeadZeroesData()); - } - } - - public void applyBlock(Block block) { - - if(block.getNumber() == 1157) { - logger.debug("Block 1157"); - } - - int i = 0; - for (Transaction tx : block.getTransactionsList()) { - logger.info("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i); - applyTransaction(block, tx, block.getCoinbase()); - repository.dumpState(block.getNumber(), i, - Hex.toHexString(tx.getHash())); - ++i; - - } - - // miner reward - if (repository.getAccountState(block.getCoinbase()) == null) - repository.createAccount(block.getCoinbase()); - repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD); - for (Block uncle : block.getUncleList()) { - repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); - } - - repository.dumpState(block.getNumber(), 0, - null); - - } /*********************************************************************** * 1) the dialog put a pending transaction on the list @@ -361,6 +115,14 @@ public class WorldManager { logger.info("pending transaction removed with hash: {} ", hash); walletTransactions.remove(hash); } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setBlockchain(Blockchain blockchain) { + this.blockchain = blockchain; + } public void setWallet(Wallet wallet) { this.wallet = wallet; @@ -370,9 +132,13 @@ public class WorldManager { return repository; } - public Blockchain getBlockChain() { + public Blockchain getBlockchain() { return blockchain; } + + public void loadBlockchain() { + this.blockchain = repository.loadBlockchain(); + } public Wallet getWallet() { return wallet; @@ -394,7 +160,6 @@ public class WorldManager { this.listener = listener; } - public void addPeers(List newPeers) { for (PeerData peer : newPeers) { if (this.peers.indexOf(peer) == -1) { @@ -420,12 +185,7 @@ public class WorldManager { peerDiscovery.stop(); } - public BlockQueue getBlockQueue() { - return blockQueue; - } - public void close() { - blockchain.close(); repository.close(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java index 701ca8cb..0a0c416a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java @@ -20,10 +20,10 @@ public class BlockQueue { private static Logger logger = LoggerFactory.getLogger("blockchain"); - ConcurrentLinkedQueue blockQueue = new ConcurrentLinkedQueue(); - Block lastBlock; + private Queue blockQueue = new ConcurrentLinkedQueue<>(); + private Block lastBlock; - Timer timer = new Timer(); + private Timer timer = new Timer(); public BlockQueue() { @@ -40,7 +40,7 @@ public class BlockQueue { Block block = blockQueue.poll(); - WorldManager.getInstance().getBlockChain().add(block); + WorldManager.getInstance().getBlockchain().add(block); } public void addBlocks(List blockList) { @@ -64,7 +64,7 @@ public class BlockQueue { public Block getLast() { if (blockQueue.isEmpty()) - return WorldManager.getInstance().getBlockChain().getLastBlock(); + return WorldManager.getInstance().getBlockchain().getLastBlock(); return lastBlock; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java index 92c85591..1ec014d4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java @@ -3,7 +3,6 @@ package org.ethereum.net.client; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.CorruptedFrameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java index ad452626..50431bc3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java @@ -183,7 +183,8 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { List txList = transactionsMessage.getTransactions(); for(Transaction tx : txList) - WorldManager.getInstance().applyTransaction(null, tx, null); + WorldManager.getInstance().getBlockchain() + .applyTransaction(null, tx, null); logger.info(transactionsMessage.toString()); if (peerListener != null) peerListener.console(transactionsMessage.toString()); @@ -235,7 +236,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { } if (blockList.isEmpty()) return; - WorldManager.getInstance().getBlockQueue().addBlocks(blockList); + WorldManager.getInstance().getBlockchain().getBlockQueue().addBlocks(blockList); if (peerListener != null) peerListener.console(blocksMessage.toString()); } @@ -318,10 +319,10 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { private void sendGetChain() { - if (WorldManager.getInstance().getBlockQueue().size() > + if (WorldManager.getInstance().getBlockchain().getBlockQueue().size() > SystemProperties.CONFIG.maxBlocksQueued()) return; - Block lastBlock = WorldManager.getInstance().getBlockQueue().getLast(); + Block lastBlock = WorldManager.getInstance().getBlockchain().getBlockQueue().getLast(); byte[] hash = lastBlock.getHash(); GetChainMessage chainMessage = diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java index 6592320a..3af03fde 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java @@ -88,7 +88,7 @@ public class GetChainMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return BlocksMessage.class; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java index e2b988d1..8fb784fb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java @@ -27,7 +27,7 @@ public class GetPeersMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return PeersMessage.class; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java index 99600073..062bed12 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java @@ -1,15 +1,7 @@ package org.ethereum.net.message; -import org.ethereum.util.RLP; -import org.ethereum.util.RLPItem; -import org.ethereum.util.RLPList; import org.spongycastle.util.encoders.Hex; -import java.math.BigInteger; -import java.nio.ByteBuffer; - -import static org.ethereum.net.Command.HELLO; - /** * www.ethereumJ.com * @author: Roman Mandeleil @@ -35,7 +27,7 @@ public class PingMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return PongMessage.class; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java index 850ab630..04802e60 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java @@ -16,13 +16,12 @@ import org.iq80.leveldb.DB; */ public class Cache { - private Map nodes; + private Map nodes = new HashMap<>(); private DB db; private boolean isDirty; public Cache(DB db) { this.db = db; - nodes = new HashMap(); } /** @@ -88,7 +87,7 @@ public class Cache { // If the nodes grows beyond the 200 entries we simple empty it // FIXME come up with something better if (this.nodes.size() > 200) { - this.nodes = new HashMap(); + this.nodes = new HashMap<>(); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java index 81ea0dd6..b533fbba 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java @@ -72,6 +72,10 @@ public class Trie implements TrieFacade { return root; } + public void setRoot(Object root) { + this.root = root; + } + public void setCache(Cache cache) { this.cache = cache; } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java b/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java index ec7153c1..256268fa 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java @@ -1,10 +1,7 @@ package org.ethereum.util; -import com.maxmind.geoip.Location; import org.apache.log4j.PropertyConfigurator; -import org.ethereum.db.IpGeoDB; -import java.net.InetAddress; import java.net.URL; import static org.ethereum.config.SystemProperties.CONFIG; diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java index 869a7c47..e4f2c13f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java @@ -24,7 +24,7 @@ public class ProgramInvokeFactory { public static ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) { // https://ethereum.etherpad.mozilla.org/26 - Block lastBlock = WorldManager.getInstance().getBlockChain().getLastBlock(); + Block lastBlock = WorldManager.getInstance().getBlockchain().getLastBlock(); /*** ADDRESS op ***/ // YP: Get address of currently executing account. diff --git a/ethereumj-core/src/main/resources/log4j-detailed.properties b/ethereumj-core/src/main/resources/log4j-detailed.properties index 672cc173..15d8b9b4 100644 --- a/ethereumj-core/src/main/resources/log4j-detailed.properties +++ b/ethereumj-core/src/main/resources/log4j-detailed.properties @@ -23,9 +23,9 @@ log4j.logger.io.netty = ERROR log4j.logger.wire = ERROR log4j.logger.VM = DEBUG log4j.logger.main = INFO -log4j.logger.state = ERROR +log4j.logger.state = DEBUG log4j.logger.repository = DEBUG -log4j.logger.blockchain = DEBUG +log4j.logger.blockchain = INFO log4j.logger.ui = ERROR log4j.logger.gas = ERROR diff --git a/ethereumj-core/src/main/resources/log4j.properties b/ethereumj-core/src/main/resources/log4j.properties index 518657e3..bba5eecc 100644 --- a/ethereumj-core/src/main/resources/log4j.properties +++ b/ethereumj-core/src/main/resources/log4j.properties @@ -24,8 +24,8 @@ log4j.logger.wire = ERROR log4j.logger.VM = ERROR log4j.logger.main = ERROR log4j.logger.trie = ERROR -log4j.logger.state = ERROR -log4j.logger.repository = ERROR +log4j.logger.state = INFO +log4j.logger.repository = INFO log4j.logger.blockchain = INFO log4j.logger.txs = ERROR log4j.logger.ui = ERROR diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index c9468b34..0b3d94c6 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -99,7 +99,7 @@ coinbase.secret = "monkey" # in JSON form to [dump.dir] # if [dump.full] = true # posible values [true/false] -dump.full = true +dump.full = false dump.dir = dmp # clean the dump dir each start diff --git a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java index 654b2ad9..e60a8fed 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java @@ -115,7 +115,7 @@ public class BlockTest { assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().add(genesis); + WorldManager.getInstance().getBlockchain().add(genesis); Block block1 = new Block(Hex.decode(block_1)); BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty()); @@ -137,7 +137,7 @@ public class BlockTest { assertEquals(Genesis.GAS_LIMIT, gasLimit); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().add(genesis); + WorldManager.getInstance().getBlockchain().add(genesis); // Test with block Block block1 = new Block(Hex.decode(block_1));