Merge pull request #62 from nicksavers/master

Refactoring uncle reward and wallet processing
This commit is contained in:
romanman 2014-07-11 16:51:03 +03:00
commit eb382199cc
4 changed files with 53 additions and 57 deletions

View File

@ -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++) {

View File

@ -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, <block_number, block_hash>
private Map<Long, byte[]> index = new HashMap<>();
// This map of transaction designed
// to approve the tx by external trusted peer
private Map<String, WalletTransaction> walletTransactions =
Collections.synchronizedMap(new HashMap<String, WalletTransaction>());
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();

View File

@ -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<String, Transaction> pendingTransactions = Collections
.synchronizedMap(new HashMap<String, Transaction>());
// 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 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<Transaction> 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;

View File

@ -35,7 +35,7 @@ public class TransactionTask implements Callable<Transaction> {
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<Transaction> {
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;
}