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 ed09578d..0cfb9088 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -37,6 +37,8 @@ public class Block { /* A scalar value equal to the mininum limit of gas expenditure per block */ private static long MIN_GAS_LIMIT = 125000L; public static BigInteger BLOCK_REWARD = BigInteger.valueOf(1500000000000000000L); + public static BigInteger UNCLE_REWARD = BLOCK_REWARD.multiply( + BigInteger.valueOf(7)).divide(BigInteger.valueOf(8)); private BlockHeader header; @@ -91,7 +93,7 @@ public class Block { // Parse Transactions RLPList txReceipts = (RLPList) block.get(1); - this.processTxs(txReceipts); + this.parseTxs(txReceipts); // Parse Uncles RLPList uncleBlocks = (RLPList) block.get(2); @@ -259,7 +261,7 @@ public class Block { return toStringBuff.toString(); } - private void processTxs(RLPList txReceipts) { + private void parseTxs(RLPList txReceipts) { this.txsState = new Trie(null); for (int i = 0; i < txReceipts.size(); i++) { 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 01d76e57..88c077a9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -2,7 +2,6 @@ package org.ethereum.core; import org.ethereum.db.DatabaseImpl; import org.ethereum.manager.WorldManager; -import org.ethereum.net.submit.WalletTransaction; import org.ethereum.util.ByteUtil; import org.iq80.leveldb.DBIterator; import org.slf4j.Logger; @@ -54,7 +53,6 @@ public class Blockchain { private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue(); private DatabaseImpl chainDb; - private Wallet wallet; private long gasPrice = 1000; private Block lastBlock; @@ -63,11 +61,6 @@ public class Blockchain { // convenient usage, private Map index = new HashMap<>(); - // This map of transaction designed - // to approve the tx by external trusted peer - private Map walletTransactions = - Collections.synchronizedMap(new HashMap()); - public Blockchain() { this.chainDb = new DatabaseImpl("blockchain"); } @@ -108,7 +101,7 @@ public class Blockchain { String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash()); if (!hashLast.equals(blockParentHash)) return; } - for (int i = blocks.size() - 1; i >= 0 ; --i) { + for (int i = blocks.size() - 1; i >= 0 ; --i) { this.addBlock(blocks.get(i)); /* Debug check to see if the state is still as expected */ @@ -124,7 +117,7 @@ public class Blockchain { for (Transaction tx : block.getTransactionsList()) { if (logger.isDebugEnabled()) logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash())); - this.removeWalletTransaction(tx); + WorldManager.getInstance().removeWalletTransaction(tx); } } logger.info("*** Block chain size: [ {} ]", this.getSize()); @@ -133,13 +126,17 @@ public class Blockchain { public void addBlock(Block block) { if(block.isValid()) { - if (!block.isGenesis()) + if (!block.isGenesis()) { + for (Transaction tx : block.getTransactionsList()) + // TODO: refactor the wallet pending transactions to the world manager + WorldManager.getInstance().addWalletTransaction(tx); WorldManager.getInstance().applyBlock(block); + } this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); this.index.put(block.getNumber(), block.getEncoded()); - this.wallet.processBlock(block); + WorldManager.getInstance().getWallet().processBlock(block); this.updateGasPrice(block); this.setLastBlock(block); if (logger.isDebugEnabled()) @@ -158,37 +155,6 @@ public class Blockchain { return gasPrice; } - /*********************************************************************** - * 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 setWallet(Wallet wallet) { - this.wallet = wallet; - } - public byte[] getLatestBlockHash() { if (index.isEmpty()) return Genesis.getInstance().getHash(); 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 d4d8ea85..3c029f9e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -5,7 +5,6 @@ import static org.ethereum.config.SystemProperties.CONFIG; import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.ethereum.core.AccountState; @@ -16,6 +15,7 @@ import org.ethereum.core.Wallet; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.db.Repository; +import org.ethereum.net.submit.WalletTransaction; import org.ethereum.vm.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +40,11 @@ public class WorldManager { private Map pendingTransactions = Collections .synchronizedMap(new HashMap()); + + // This map of transaction designed + // to approve the tx by external trusted peer + private Map walletTransactions = + Collections.synchronizedMap(new HashMap()); private static WorldManager instance; @@ -59,8 +64,6 @@ public class WorldManager { String secret = CONFIG.coinbaseSecret(); byte[] cbAddr = HashUtil.sha3(secret.getBytes()); wallet.importKey(cbAddr); - - blockchain.setWallet(wallet); } public static WorldManager getInstance() { @@ -73,10 +76,6 @@ public class WorldManager { public void applyTransaction(Transaction tx, byte[] coinbase) { - // TODO: refactor the wallet pending transactions to the world manager - if (blockchain != null) - blockchain.addWalletTransaction(tx); - byte[] senderAddress = tx.getSender(); AccountState senderAccount = repository.getAccountState(senderAddress); @@ -276,12 +275,10 @@ public class WorldManager { } } - private static BigInteger UNCLE_RATIO = BigInteger.valueOf(7).divide(BigInteger.valueOf(8)); public void applyBlock(Block block) { int i = 0; - List txList = block.getTransactionsList(); - for (Transaction tx : txList) { + for (Transaction tx : block.getTransactionsList()) { applyTransaction(tx, block.getCoinbase()); repository.dumpState(block.getNumber(), i, Hex.toHexString(tx.getHash())); @@ -293,9 +290,40 @@ public class WorldManager { repository.createAccount(block.getCoinbase()); repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD); for (Block uncle : block.getUncleList()) { - repository.addBalance(uncle.getCoinbase(), Block.BLOCK_REWARD.multiply(UNCLE_RATIO)); + repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); } } + + /*********************************************************************** + * 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 setWallet(Wallet wallet) { + this.wallet = wallet; + } public Repository getRepository() { return repository; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java b/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java index 88eb4038..5d21c1fa 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java @@ -35,7 +35,7 @@ public class TransactionTask implements Callable { ClientPeer peer = MainData.instance.getActivePeer(); WalletTransaction walletTransaction = WorldManager.getInstance() - .getBlockChain().addWalletTransaction(tx); + .addWalletTransaction(tx); peer.sendTransaction(tx); while(walletTransaction.getApproved() < 1 ) { @@ -44,7 +44,7 @@ public class TransactionTask implements Callable { logger.info("return approved: {}", walletTransaction.getApproved()); } catch (Throwable th) { logger.info("exception caugh: {}", th); - WorldManager.getInstance().getBlockChain().removeWalletTransaction(tx); + WorldManager.getInstance().removeWalletTransaction(tx); } return null; }