Merge pull request #62 from nicksavers/master
Refactoring uncle reward and wallet processing
This commit is contained in:
commit
eb382199cc
|
@ -37,6 +37,8 @@ public class Block {
|
||||||
/* A scalar value equal to the mininum limit of gas expenditure per block */
|
/* A scalar value equal to the mininum limit of gas expenditure per block */
|
||||||
private static long MIN_GAS_LIMIT = 125000L;
|
private static long MIN_GAS_LIMIT = 125000L;
|
||||||
public static BigInteger BLOCK_REWARD = BigInteger.valueOf(1500000000000000000L);
|
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;
|
private BlockHeader header;
|
||||||
|
|
||||||
|
@ -91,7 +93,7 @@ public class Block {
|
||||||
|
|
||||||
// Parse Transactions
|
// Parse Transactions
|
||||||
RLPList txReceipts = (RLPList) block.get(1);
|
RLPList txReceipts = (RLPList) block.get(1);
|
||||||
this.processTxs(txReceipts);
|
this.parseTxs(txReceipts);
|
||||||
|
|
||||||
// Parse Uncles
|
// Parse Uncles
|
||||||
RLPList uncleBlocks = (RLPList) block.get(2);
|
RLPList uncleBlocks = (RLPList) block.get(2);
|
||||||
|
@ -259,7 +261,7 @@ public class Block {
|
||||||
return toStringBuff.toString();
|
return toStringBuff.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processTxs(RLPList txReceipts) {
|
private void parseTxs(RLPList txReceipts) {
|
||||||
|
|
||||||
this.txsState = new Trie(null);
|
this.txsState = new Trie(null);
|
||||||
for (int i = 0; i < txReceipts.size(); i++) {
|
for (int i = 0; i < txReceipts.size(); i++) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.db.DatabaseImpl;
|
import org.ethereum.db.DatabaseImpl;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.net.submit.WalletTransaction;
|
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.iq80.leveldb.DBIterator;
|
import org.iq80.leveldb.DBIterator;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -54,7 +53,6 @@ public class Blockchain {
|
||||||
private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
|
private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
|
||||||
|
|
||||||
private DatabaseImpl chainDb;
|
private DatabaseImpl chainDb;
|
||||||
private Wallet wallet;
|
|
||||||
|
|
||||||
private long gasPrice = 1000;
|
private long gasPrice = 1000;
|
||||||
private Block lastBlock;
|
private Block lastBlock;
|
||||||
|
@ -63,11 +61,6 @@ public class Blockchain {
|
||||||
// convenient usage, <block_number, block_hash>
|
// convenient usage, <block_number, block_hash>
|
||||||
private Map<Long, byte[]> index = new HashMap<>();
|
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() {
|
public Blockchain() {
|
||||||
this.chainDb = new DatabaseImpl("blockchain");
|
this.chainDb = new DatabaseImpl("blockchain");
|
||||||
}
|
}
|
||||||
|
@ -124,7 +117,7 @@ public class Blockchain {
|
||||||
for (Transaction tx : block.getTransactionsList()) {
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
||||||
this.removeWalletTransaction(tx);
|
WorldManager.getInstance().removeWalletTransaction(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info("*** Block chain size: [ {} ]", this.getSize());
|
logger.info("*** Block chain size: [ {} ]", this.getSize());
|
||||||
|
@ -133,13 +126,17 @@ public class Blockchain {
|
||||||
public void addBlock(Block block) {
|
public void addBlock(Block block) {
|
||||||
if(block.isValid()) {
|
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);
|
WorldManager.getInstance().applyBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded());
|
this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded());
|
||||||
this.index.put(block.getNumber(), block.getEncoded());
|
this.index.put(block.getNumber(), block.getEncoded());
|
||||||
|
|
||||||
this.wallet.processBlock(block);
|
WorldManager.getInstance().getWallet().processBlock(block);
|
||||||
this.updateGasPrice(block);
|
this.updateGasPrice(block);
|
||||||
this.setLastBlock(block);
|
this.setLastBlock(block);
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
|
@ -158,37 +155,6 @@ public class Blockchain {
|
||||||
return gasPrice;
|
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() {
|
public byte[] getLatestBlockHash() {
|
||||||
if (index.isEmpty())
|
if (index.isEmpty())
|
||||||
return Genesis.getInstance().getHash();
|
return Genesis.getInstance().getHash();
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
|
@ -16,6 +15,7 @@ import org.ethereum.core.Wallet;
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.Repository;
|
||||||
|
import org.ethereum.net.submit.WalletTransaction;
|
||||||
import org.ethereum.vm.*;
|
import org.ethereum.vm.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -41,6 +41,11 @@ public class WorldManager {
|
||||||
private Map<String, Transaction> pendingTransactions = Collections
|
private Map<String, Transaction> pendingTransactions = Collections
|
||||||
.synchronizedMap(new HashMap<String, Transaction>());
|
.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;
|
private static WorldManager instance;
|
||||||
|
|
||||||
public WorldManager() {
|
public WorldManager() {
|
||||||
|
@ -59,8 +64,6 @@ public class WorldManager {
|
||||||
String secret = CONFIG.coinbaseSecret();
|
String secret = CONFIG.coinbaseSecret();
|
||||||
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
|
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
|
||||||
wallet.importKey(cbAddr);
|
wallet.importKey(cbAddr);
|
||||||
|
|
||||||
blockchain.setWallet(wallet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorldManager getInstance() {
|
public static WorldManager getInstance() {
|
||||||
|
@ -73,10 +76,6 @@ public class WorldManager {
|
||||||
|
|
||||||
public void applyTransaction(Transaction tx, byte[] coinbase) {
|
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();
|
byte[] senderAddress = tx.getSender();
|
||||||
AccountState senderAccount = repository.getAccountState(senderAddress);
|
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) {
|
public void applyBlock(Block block) {
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
List<Transaction> txList = block.getTransactionsList();
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
for (Transaction tx : txList) {
|
|
||||||
applyTransaction(tx, block.getCoinbase());
|
applyTransaction(tx, block.getCoinbase());
|
||||||
repository.dumpState(block.getNumber(), i,
|
repository.dumpState(block.getNumber(), i,
|
||||||
Hex.toHexString(tx.getHash()));
|
Hex.toHexString(tx.getHash()));
|
||||||
|
@ -293,10 +290,41 @@ public class WorldManager {
|
||||||
repository.createAccount(block.getCoinbase());
|
repository.createAccount(block.getCoinbase());
|
||||||
repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD);
|
repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD);
|
||||||
for (Block uncle : block.getUncleList()) {
|
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() {
|
public Repository getRepository() {
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class TransactionTask implements Callable<Transaction> {
|
||||||
ClientPeer peer = MainData.instance.getActivePeer();
|
ClientPeer peer = MainData.instance.getActivePeer();
|
||||||
|
|
||||||
WalletTransaction walletTransaction = WorldManager.getInstance()
|
WalletTransaction walletTransaction = WorldManager.getInstance()
|
||||||
.getBlockChain().addWalletTransaction(tx);
|
.addWalletTransaction(tx);
|
||||||
peer.sendTransaction(tx);
|
peer.sendTransaction(tx);
|
||||||
|
|
||||||
while(walletTransaction.getApproved() < 1 ) {
|
while(walletTransaction.getApproved() < 1 ) {
|
||||||
|
@ -44,7 +44,7 @@ public class TransactionTask implements Callable<Transaction> {
|
||||||
logger.info("return approved: {}", walletTransaction.getApproved());
|
logger.info("return approved: {}", walletTransaction.getApproved());
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
logger.info("exception caugh: {}", th);
|
logger.info("exception caugh: {}", th);
|
||||||
WorldManager.getInstance().getBlockChain().removeWalletTransaction(tx);
|
WorldManager.getInstance().removeWalletTransaction(tx);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue