Calculate txTrieRoot from actual transactions in a block and move block header to separate class

This commit is contained in:
nicksavers 2014-06-06 15:30:24 +02:00
parent 72f7e18d7a
commit 6ec5dd9d12
11 changed files with 415 additions and 218 deletions

View File

@ -6,9 +6,7 @@ import org.ethereum.trie.Trie;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPElement;
import org.ethereum.util.RLPItem;
import org.ethereum.util.RLPList;
import org.ethereum.util.Utils;
import org.spongycastle.util.BigIntegers;
import java.math.BigInteger;
@ -27,81 +25,42 @@ public class Block {
/* A scalar value equal to the mininum limit of gas expenditure per block */
private static long MIN_GAS_LIMIT = BigInteger.valueOf(10).pow(4).longValue();
private BlockHeader header;
/* Transactions */
private List<TransactionReceipt> txReceiptList = new ArrayList<TransactionReceipt>();
private List<Transaction> transactionsList = new ArrayList<Transaction>();
/* Uncles */
private List<Block> uncleList = new ArrayList<Block>();
/* Private */
private byte[] rlpEncoded;
private boolean parsed = false;
private byte[] hash;
/* The SHA3 256-bit hash of the parent block, in its entirety */
private byte[] parentHash;
/* The SHA3 256-bit hash of the uncles list portion of this block */
private byte[] unclesHash;
/* The 160-bit address to which all fees collected from the
* successful mining of this block be transferred; formally */
private byte[] coinbase;
/* The SHA3 256-bit hash of the root node of the state trie,
* after all transactions are executed and finalisations applied */
private byte[] stateRoot;
/* The SHA3 256-bit hash of the root node of the trie structure
* populated with each transaction recipe in the transaction recipes
* list portion, the trie is populate by [key, val] --> [rlp(index), rlp(tx_reciepe)]
* of the block */
private byte[] txTrieRoot;
/* A scalar value corresponding to the difficulty level of this block.
* This can be calculated from the previous blocks difficulty level
* and the timestamp */
private byte[] difficulty;
/* A scalar value equal to the reasonable output of Unix's time()
* at this block's inception */
private long timestamp;
/* A scalar value equal to the number of ancestor blocks.
* The genesis block has a number of zero */
private long number;
/* A scalar value equal to the minimum price of gas a transaction
* must have provided in order to be sufficient for inclusion
* by this miner in this block */
private long minGasPrice;
/* A scalar value equal to the current limit of gas expenditure per block */
private long gasLimit;
/* A scalar value equal to the total gas used in transactions in this block */
private long gasUsed;
/* An arbitrary byte array containing data relevant to this block.
* With the exception of the genesis block, this must be 32 bytes or fewer */
private byte[] extraData;
/* A 256-bit hash which proves that a sufficient amount
* of computation has been carried out on this block */
private byte[] nonce;
private List<Transaction> transactionsList = new ArrayList<Transaction>();
private List<TransactionRecipe> txRecipeList = new ArrayList<TransactionRecipe>();
private List<Block> uncleList = new ArrayList<Block>();
private Trie state;
private Trie accountState;
private Trie txsState;
/* Constructors */
public Block(byte[] rawData) {
this.rlpEncoded = rawData;
this.parsed = false;
}
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
byte[] txTrieRoot, byte[] difficulty, long number,
long minGasPrice, long gasLimit, long gasUsed, long timestamp,
byte[] extraData, byte[] nonce, List<Transaction> transactionsList,
List<Block> uncleList) {
this.parentHash = parentHash;
this.unclesHash = unclesHash;
this.coinbase = coinbase;
this.state = new Trie(Config.STATE_DB.getDb());
this.stateRoot = state.getRootHash();
this.txTrieRoot = txTrieRoot;
this.difficulty = difficulty;
this.number = number;
this.minGasPrice = minGasPrice;
this.gasLimit = gasLimit;
this.gasUsed = gasUsed;
this.timestamp = timestamp;
this.extraData = extraData;
this.nonce = nonce;
byte[] difficulty, long number, long minGasPrice, long gasLimit,
long gasUsed, long timestamp, byte[] extraData, byte[] nonce,
List<Transaction> transactionsList, List<Block> uncleList) {
this.header = new BlockHeader(parentHash, unclesHash, coinbase,
difficulty, number, minGasPrice, gasLimit, gasUsed,
timestamp, extraData, nonce);
this.accountState = new Trie(Config.STATE_DB.getDb());
this.txsState = new Trie(null);
this.header.setStateRoot(accountState.getRootHash());
this.header.setTxTrieRoot(txsState.getRootHash());
this.transactionsList = transactionsList;
this.uncleList = uncleList;
this.parsed = true;
@ -117,46 +76,28 @@ public class Block {
// Parse Header
RLPList header = (RLPList) block.get(0);
this.parentHash = ((RLPItem) header.get(0)).getRLPData();
this.unclesHash = ((RLPItem) header.get(1)).getRLPData();
this.coinbase = ((RLPItem) header.get(2)).getRLPData();
this.stateRoot = ((RLPItem) header.get(3)).getRLPData();
this.txTrieRoot = ((RLPItem) header.get(4)).getRLPData();
this.difficulty = ((RLPItem) header.get(5)).getRLPData();
byte[] nrBytes = ((RLPItem) header.get(6)).getRLPData();
byte[] gpBytes = ((RLPItem) header.get(7)).getRLPData();
byte[] glBytes = ((RLPItem) header.get(8)).getRLPData();
byte[] guBytes = ((RLPItem) header.get(9)).getRLPData();
byte[] tsBytes = ((RLPItem) header.get(10)).getRLPData();
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
this.minGasPrice = gpBytes == null ? 0 : (new BigInteger(1, gpBytes)).longValue();
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
this.extraData = ((RLPItem) header.get(11)).getRLPData();
this.nonce = ((RLPItem) header.get(12)).getRLPData();
this.header = new BlockHeader(header);
// Parse Transactions
RLPList transactions = (RLPList) block.get(1);
for (RLPElement rlpTx : transactions){
RLPElement txData = ((RLPList)rlpTx).get(0);
this.txsState = new Trie(null);
RLPList txReceipts = (RLPList) block.get(1);
for (int i = 0; i < txReceipts.size(); i++) {
RLPElement rlpTxReceipt = txReceipts.get(i);
RLPElement txData = ((RLPList)rlpTxReceipt).get(0);
Transaction tx = new Transaction(txData.getRLPData());
this.transactionsList.add(tx);
this.txsState.update(RLP.encodeInt(i), tx.getEncoded());
// YP 4.3.1
RLPElement cummGas = ((RLPList)rlpTx).get(1);
RLPElement pstTxState = ((RLPList)rlpTx).get(2);
RLPElement cummGas = ((RLPList)rlpTxReceipt).get(1);
RLPElement pstTxState = ((RLPList)rlpTxReceipt).get(2);
TransactionRecipe txRecipe =
new TransactionRecipe(tx, cummGas.getRLPData(), pstTxState.getRLPData());
txRecipeList.add(txRecipe);
// TransactionReceipt txReceipt =
// new TransactionReceipt(tx, cummGas.getRLPData(), pstTxState.getRLPData());
// txReceiptList.add(txReceipt);
}
this.header.setTxTrieRoot(txsState.getRootHash());
// Parse Uncles
RLPList uncleBlocks = (RLPList) block.get(2);
@ -180,67 +121,67 @@ public class Block {
public byte[] getParentHash() {
if (!parsed) parseRLP();
return parentHash;
return this.header.getParentHash();
}
public byte[] getUnclesHash() {
if (!parsed) parseRLP();
return unclesHash;
return this.header.getUnclesHash();
}
public byte[] getCoinbase() {
if (!parsed) parseRLP();
return coinbase;
return this.header.getCoinbase();
}
public byte[] getStateRoot() {
if (!parsed) parseRLP();
return this.stateRoot;
return this.header.getStateRoot();
}
public byte[] getTxTrieRoot() {
if (!parsed) parseRLP();
return txTrieRoot;
return this.header.getTxTrieRoot();
}
public byte[] getDifficulty() {
if (!parsed) parseRLP();
return difficulty;
return this.header.getDifficulty();
}
public long getTimestamp() {
if (!parsed) parseRLP();
return timestamp;
return this.header.getTimestamp();
}
public long getNumber() {
if (!parsed) parseRLP();
return number;
return this.header.getNumber();
}
public long getMinGasPrice() {
if (!parsed) parseRLP();
return minGasPrice;
return this.header.getMinGasPrice();
}
public long getGasLimit() {
if (!parsed) parseRLP();
return gasLimit;
return this.header.getGasLimit();
}
public long getGasUsed() {
if (!parsed) parseRLP();
return gasUsed;
return this.header.getGasUsed();
}
public byte[] getExtraData() {
if (!parsed) parseRLP();
return extraData;
return this.header.getExtraData();
}
public byte[] getNonce() {
if (!parsed) parseRLP();
return nonce;
return this.header.getNonce();
}
public List<Transaction> getTransactionsList() {
@ -251,12 +192,12 @@ public class Block {
return transactionsList;
}
public List<TransactionRecipe> getTxRecipeList() {
public List<TransactionReceipt> getTxReceiptList() {
if (!parsed) parseRLP();
if (transactionsList == null) {
this.txRecipeList = new ArrayList<TransactionRecipe>();
this.txReceiptList = new ArrayList<TransactionReceipt>();
}
return txRecipeList;
return txReceiptList;
}
public List<Block> getUncleList() {
@ -279,27 +220,13 @@ public class Block {
toStringBuff.setLength(0);
toStringBuff.append("BlockData [\n");
toStringBuff.append(" hash=" + ByteUtil.toHexString(hash)).append("\n");
toStringBuff.append(" parentHash=" + ByteUtil.toHexString(parentHash)).append("\n");
toStringBuff.append(" unclesHash=" + ByteUtil.toHexString(unclesHash)).append("\n");
toStringBuff.append(" coinbase=" + ByteUtil.toHexString(coinbase)).append("\n");
toStringBuff.append(" stateHash=" + ByteUtil.toHexString(stateRoot)).append("\n");
toStringBuff.append(" txTrieHash=" + ByteUtil.toHexString(txTrieRoot)).append("\n");
toStringBuff.append(" difficulty=" + ByteUtil.toHexString(difficulty)).append("\n");
toStringBuff.append(" number=" + number).append("\n");
toStringBuff.append(" minGasPrice=" + minGasPrice).append("\n");
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
toStringBuff.append(" extraData=" + ByteUtil.toHexString(extraData)).append("\n");
toStringBuff.append(" nonce=" + ByteUtil.toHexString(nonce)).append("\n");
for (TransactionRecipe txRecipe : getTxRecipeList()){
toStringBuff.append(header.toString());
for (TransactionReceipt txReceipt : getTxReceiptList()) {
toStringBuff.append("\n");
toStringBuff.append(txRecipe.toString());
toStringBuff.append(txReceipt.toString());
}
toStringBuff.append("\n]");
toStringBuff.append("\n ]");
return toStringBuff.toString();
}
@ -309,20 +236,8 @@ public class Block {
toStringBuff.setLength(0);
toStringBuff.append("BlockData [");
toStringBuff.append(" hash=" + ByteUtil.toHexString(hash)).append("");
toStringBuff.append(" parentHash=" + ByteUtil.toHexString(parentHash)).append("");
toStringBuff.append(" unclesHash=" + ByteUtil.toHexString(unclesHash)).append("");
toStringBuff.append(" coinbase=" + ByteUtil.toHexString(coinbase)).append("");
toStringBuff.append(" stateHash=" + ByteUtil.toHexString(stateRoot)).append("");
toStringBuff.append(" txTrieHash=" + ByteUtil.toHexString(txTrieRoot)).append("");
toStringBuff.append(" difficulty=" + ByteUtil.toHexString(difficulty)).append("");
toStringBuff.append(" number=" + number).append("");
toStringBuff.append(" minGasPrice=" + minGasPrice).append("");
toStringBuff.append(" gasLimit=" + gasLimit).append("");
toStringBuff.append(" gasUsed=" + gasUsed).append("");
toStringBuff.append(" timestamp=" + timestamp).append("");
toStringBuff.append(" extraData=" + ByteUtil.toHexString(extraData)).append("");
toStringBuff.append(" nonce=" + ByteUtil.toHexString(nonce)).append("");
toStringBuff.append(header.toFlatString());
for (Transaction tx : getTransactionsList()){
toStringBuff.append("\n");
@ -334,8 +249,10 @@ public class Block {
}
public byte[] updateState(byte[] key, byte[] value) {
this.state.update(key, value);
return this.stateRoot = this.state.getRootHash();
this.accountState.update(key, value);
byte[] stateRoot = this.accountState.getRootHash();
this.header.setStateRoot(stateRoot);
return stateRoot;
}
/**
@ -365,21 +282,21 @@ public class Block {
* @return
*/
public long calcGasLimit() {
if (parentHash == null)
if (this.header.getParentHash() == null)
return 1000000L;
else {
Block parent = this.getParent();
return Math.max(MIN_GAS_LIMIT, (parent.gasLimit * (1024 - 1) + (parent.gasUsed * 6 / 5)) / 1024);
return Math.max(MIN_GAS_LIMIT, (parent.header.getGasLimit() * (1024 - 1) + (parent.header.getGasUsed() * 6 / 5)) / 1024);
}
}
public byte[] calcDifficulty() {
if (parentHash == null)
if (this.header.getParentHash() == null)
return Genesis.DIFFICULTY;
else {
Block parent = this.getParent();
long parentDifficulty = new BigInteger(1, parent.difficulty).longValue();
long newDifficulty = timestamp >= parent.timestamp + 42 ? parentDifficulty - (parentDifficulty >> 10) : (parentDifficulty + (parentDifficulty >> 10));
long parentDifficulty = new BigInteger(1, parent.header.getDifficulty()).longValue();
long newDifficulty = this.header.getTimestamp() >= parent.header.getTimestamp() + 42 ? parentDifficulty - (parentDifficulty >> 10) : (parentDifficulty + (parentDifficulty >> 10));
return BigIntegers.asUnsignedByteArray(BigInteger.valueOf(newDifficulty));
}
}
@ -395,24 +312,7 @@ public class Block {
// Object[] uncles = this.getUncleList().toArray();
// return RLP.encode(new Object[] { header, transactions, uncles });
byte[] parentHash = RLP.encodeElement(this.parentHash);
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
byte[] coinbase = RLP.encodeElement(this.coinbase);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
byte[] difficulty = RLP.encodeElement(this.difficulty);
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
byte[] minGasPrice = RLP.encodeBigInteger(BigInteger.valueOf(this.minGasPrice));
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
byte[] extraData = RLP.encodeElement(this.extraData);
byte[] nonce = RLP.encodeElement(this.nonce);
byte[] header = RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, difficulty, number,
minGasPrice, gasLimit, gasUsed, timestamp, extraData, nonce);
byte[] header = this.header.getEncoded();
byte[] transactions = RLP.encodeList();
byte[] uncles = RLP.encodeList();

View File

@ -0,0 +1,232 @@
package org.ethereum.core;
import java.math.BigInteger;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPItem;
import org.ethereum.util.RLPList;
import org.ethereum.util.Utils;
/**
* Block header is a value object containing
* the basic information of a block
*/
public class BlockHeader {
/* The SHA3 256-bit hash of the parent block, in its entirety */
private byte[] parentHash;
/* The SHA3 256-bit hash of the uncles list portion of this block */
private byte[] unclesHash;
/* The 160-bit address to which all fees collected from the
* successful mining of this block be transferred; formally */
private byte[] coinbase;
/* The SHA3 256-bit hash of the root node of the state trie,
* after all transactions are executed and finalisations applied */
private byte[] stateRoot;
/* The SHA3 256-bit hash of the root node of the trie structure
* populated with each transaction recipe in the transaction recipes
* list portion, the trie is populate by [key, val] --> [rlp(index), rlp(tx_reciepe)]
* of the block */
private byte[] txTrieRoot;
/* A scalar value corresponding to the difficulty level of this block.
* This can be calculated from the previous blocks difficulty level
* and the timestamp */
private byte[] difficulty;
/* A scalar value equal to the reasonable output of Unix's time()
* at this block's inception */
private long timestamp;
/* A scalar value equal to the number of ancestor blocks.
* The genesis block has a number of zero */
private long number;
/* A scalar value equal to the minimum price of gas a transaction
* must have provided in order to be sufficient for inclusion
* by this miner in this block */
private long minGasPrice;
/* A scalar value equal to the current limit of gas expenditure per block */
private long gasLimit;
/* A scalar value equal to the total gas used in transactions in this block */
private long gasUsed;
/* An arbitrary byte array containing data relevant to this block.
* With the exception of the genesis block, this must be 32 bytes or fewer */
private byte[] extraData;
/* A 256-bit hash which proves that a sufficient amount
* of computation has been carried out on this block */
private byte[] nonce;
public BlockHeader(RLPList rlpHeader) {
this.parentHash = ((RLPItem) rlpHeader.get(0)).getRLPData();
this.unclesHash = ((RLPItem) rlpHeader.get(1)).getRLPData();
this.coinbase = ((RLPItem) rlpHeader.get(2)).getRLPData();
this.stateRoot = ((RLPItem) rlpHeader.get(3)).getRLPData();
this.txTrieRoot = ((RLPItem) rlpHeader.get(4)).getRLPData();
this.difficulty = ((RLPItem) rlpHeader.get(5)).getRLPData();
byte[] nrBytes = ((RLPItem) rlpHeader.get(6)).getRLPData();
byte[] gpBytes = ((RLPItem) rlpHeader.get(7)).getRLPData();
byte[] glBytes = ((RLPItem) rlpHeader.get(8)).getRLPData();
byte[] guBytes = ((RLPItem) rlpHeader.get(9)).getRLPData();
byte[] tsBytes = ((RLPItem) rlpHeader.get(10)).getRLPData();
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
this.minGasPrice = gpBytes == null ? 0 : (new BigInteger(1, gpBytes)).longValue();
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
this.extraData = ((RLPItem) rlpHeader.get(11)).getRLPData();
this.nonce = ((RLPItem) rlpHeader.get(12)).getRLPData();
}
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
byte[] difficulty, long number, long minGasPrice, long gasLimit,
long gasUsed, long timestamp, byte[] extraData, byte[] nonce) {
this.parentHash = parentHash;
this.unclesHash = unclesHash;
this.coinbase = coinbase;
this.difficulty = difficulty;
this.number = number;
this.minGasPrice = minGasPrice;
this.gasLimit = gasLimit;
this.gasUsed = gasUsed;
this.timestamp = timestamp;
this.extraData = extraData;
this.nonce = nonce;
}
public byte[] getParentHash() {
return parentHash;
}
public void setParentHash(byte[] parentHash) {
this.parentHash = parentHash;
}
public byte[] getUnclesHash() {
return unclesHash;
}
public void setUnclesHash(byte[] unclesHash) {
this.unclesHash = unclesHash;
}
public byte[] getCoinbase() {
return coinbase;
}
public void setCoinbase(byte[] coinbase) {
this.coinbase = coinbase;
}
public byte[] getStateRoot() {
return stateRoot;
}
public void setStateRoot(byte[] stateRoot) {
this.stateRoot = stateRoot;
}
public byte[] getTxTrieRoot() {
return txTrieRoot;
}
public void setTxTrieRoot(byte[] txTrieRoot) {
this.txTrieRoot = txTrieRoot;
}
public byte[] getDifficulty() {
return difficulty;
}
public void setDifficulty(byte[] difficulty) {
this.difficulty = difficulty;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public long getMinGasPrice() {
return minGasPrice;
}
public void setMinGasPrice(long minGasPrice) {
this.minGasPrice = minGasPrice;
}
public long getGasLimit() {
return gasLimit;
}
public void setGasLimit(long gasLimit) {
this.gasLimit = gasLimit;
}
public long getGasUsed() {
return gasUsed;
}
public void setGasUsed(long gasUsed) {
this.gasUsed = gasUsed;
}
public byte[] getExtraData() {
return extraData;
}
public void setExtraData(byte[] extraData) {
this.extraData = extraData;
}
public byte[] getNonce() {
return nonce;
}
public void setNonce(byte[] nonce) {
this.nonce = nonce;
}
public byte[] getEncoded() {
byte[] parentHash = RLP.encodeElement(this.parentHash);
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
byte[] coinbase = RLP.encodeElement(this.coinbase);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
byte[] difficulty = RLP.encodeElement(this.difficulty);
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
byte[] minGasPrice = RLP.encodeBigInteger(BigInteger.valueOf(this.minGasPrice));
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
byte[] extraData = RLP.encodeElement(this.extraData);
byte[] nonce = RLP.encodeElement(this.nonce);
return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, difficulty, number,
minGasPrice, gasLimit, gasUsed, timestamp, extraData, nonce);
}
private StringBuffer toStringBuff = new StringBuffer();
public String toString() {
toStringBuff.append(" parentHash=" + ByteUtil.toHexString(parentHash)).append("\n");
toStringBuff.append(" unclesHash=" + ByteUtil.toHexString(unclesHash)).append("\n");
toStringBuff.append(" coinbase=" + ByteUtil.toHexString(coinbase)).append("\n");
toStringBuff.append(" stateHash=" + ByteUtil.toHexString(stateRoot)).append("\n");
toStringBuff.append(" txTrieHash=" + ByteUtil.toHexString(txTrieRoot)).append("\n");
toStringBuff.append(" difficulty=" + ByteUtil.toHexString(difficulty)).append("\n");
toStringBuff.append(" number=" + number).append("\n");
toStringBuff.append(" minGasPrice=" + minGasPrice).append("\n");
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
toStringBuff.append(" extraData=" + ByteUtil.toHexString(extraData)).append("\n");
toStringBuff.append(" nonce=" + ByteUtil.toHexString(nonce)).append("\n");
return toStringBuff.toString();
}
public String toFlatString() {
toStringBuff.append(" parentHash=" + ByteUtil.toHexString(parentHash)).append("");
toStringBuff.append(" unclesHash=" + ByteUtil.toHexString(unclesHash)).append("");
toStringBuff.append(" coinbase=" + ByteUtil.toHexString(coinbase)).append("");
toStringBuff.append(" stateHash=" + ByteUtil.toHexString(stateRoot)).append("");
toStringBuff.append(" txTrieHash=" + ByteUtil.toHexString(txTrieRoot)).append("");
toStringBuff.append(" difficulty=" + ByteUtil.toHexString(difficulty)).append("");
toStringBuff.append(" number=" + number).append("");
toStringBuff.append(" minGasPrice=" + minGasPrice).append("");
toStringBuff.append(" gasLimit=" + gasLimit).append("");
toStringBuff.append(" gasUsed=" + gasUsed).append("");
toStringBuff.append(" timestamp=" + timestamp).append("");
toStringBuff.append(" extraData=" + ByteUtil.toHexString(extraData)).append("");
toStringBuff.append(" nonce=" + ByteUtil.toHexString(nonce)).append("");
return toStringBuff.toString();
}
}

View File

@ -13,6 +13,17 @@ public class Genesis extends Block {
Logger logger = LoggerFactory.getLogger(this.getClass());
private AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
private String[] premine = new String[] {
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // # (M)
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // # (A)
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
"8a40bfaa73256b60764c1bf40675a99083efb075", // # (G)
"e4157b34ea9615cfbde6b4fda419828124b70c78", // # (CH)
"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // # (V)
"6c386a4b26f73c802f34673f7248bb118f97424a", // # (HH)
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826" }; // # (R)
private static byte[] zeroHash256 = new byte[32];
private static byte[] zeroHash160 = new byte[20];
private static byte[] sha3EmptyList = HashUtil.sha3(RLP.encodeList());
@ -20,7 +31,6 @@ public class Genesis extends Block {
public static byte[] PARENT_HASH = zeroHash256;
public static byte[] UNCLES_HASH = sha3EmptyList;
public static byte[] COINBASE = zeroHash160;
public static byte[] TX_TRIE_ROOT = new byte[0];
public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(22).toByteArray();
public static long NUMBER = 0;
public static long MIN_GAS_PRICE = 0;
@ -33,28 +43,14 @@ public class Genesis extends Block {
private static Block instance;
private Genesis() {
super(PARENT_HASH, UNCLES_HASH, COINBASE, TX_TRIE_ROOT, DIFFICULTY,
super(PARENT_HASH, UNCLES_HASH, COINBASE, DIFFICULTY,
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
EXTRA_DATA, NONCE, null, null);
// Premine state
AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
// # (M)
this.updateState(Hex.decode("2ef47100e0787b915105fd5e3f4ff6752079d5cb"), acct.getEncoded());
// # (A)
this.updateState(Hex.decode("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"), acct.getEncoded());
// # (J)
this.updateState(Hex.decode("e6716f9544a56c530d868e4bfbacb172315bdead"), acct.getEncoded());
// # (G)
this.updateState(Hex.decode("8a40bfaa73256b60764c1bf40675a99083efb075"), acct.getEncoded());
// # (CH)
this.updateState(Hex.decode("e4157b34ea9615cfbde6b4fda419828124b70c78"), acct.getEncoded());
// # (V)
this.updateState(Hex.decode("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"), acct.getEncoded());
// # (HH)
this.updateState(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct.getEncoded());
// # (R)
this.updateState(Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), acct.getEncoded());
for (String address : premine) {
this.updateState(Hex.decode(address), acct.getEncoded());
}
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));

View File

@ -214,7 +214,7 @@ public class Transaction {
", signatureV=" + signature.v +
", signatureR=" + ByteUtil.toHexString(BigIntegers.asUnsignedByteArray(signature.r)) +
", signatureS=" + ByteUtil.toHexString(BigIntegers.asUnsignedByteArray(signature.s)) +
"\n ]";
" ]";
}
/**

View File

@ -3,31 +3,28 @@ package org.ethereum.core;
import org.ethereum.util.RLP;
import org.spongycastle.util.encoders.Hex;
import java.util.Arrays;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/06/2014 04:03
* The transaction receipt is a tuple of three items
* comprising the transaction, together with the post-transaction state,
* and the cumulative gas used in the block containing the transaction receipt
* as of immediately after the transaction has happened,
*/
public class TransactionRecipe {
public class TransactionReceipt {
private Transaction transaction;
private byte[] postTxState;
private byte[] cumulativeGas;
/* Tx Recipe in encoded form */
/* Tx Receipt in encoded form */
private byte[] rlpEncoded;
public TransactionRecipe(Transaction transaction, byte[] postTxState, byte[] cumulativeGas) {
public TransactionReceipt(Transaction transaction, byte[] postTxState, byte[] cumulativeGas) {
this.transaction = transaction;
this.postTxState = postTxState;
this.cumulativeGas = cumulativeGas;
}
public byte[] getEncoded(){
public byte[] getEncoded() {
if(rlpEncoded != null) return rlpEncoded;
@ -42,7 +39,7 @@ public class TransactionRecipe {
@Override
public String toString() {
return "TransactionRecipe[" +
return "TransactionReceipt[" +
"\n " + transaction +
"\n , postTxState=" + Hex.toHexString(postTxState) +
"\n , cumulativeGas=" + Hex.toHexString(cumulativeGas) +

View File

@ -762,7 +762,7 @@ public class RLP {
} else if ((singleByte & 0xFF) < 0x7F) {
return new byte[] { singleByte };
} else {
return new byte[] { (byte) (OFFSET_SHORT_ITEM+1), singleByte };
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 1), singleByte };
}
}
@ -775,6 +775,25 @@ public class RLP {
(byte) (singleShort >> 0 & 0xFF) };
}
}
public static byte[] encodeInt(int singleInt) {
if (singleInt <= 0xFF)
return encodeByte((byte) singleInt);
else if (singleInt <= 0xFFFF)
return encodeShort((short) singleInt);
else if (singleInt <= 0xFFFFFF)
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 3),
(byte) (singleInt >>> 16),
(byte) (singleInt >>> 8),
(byte) singleInt};
else {
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 4),
(byte) (singleInt >>> 24),
(byte) (singleInt >>> 16),
(byte) (singleInt >>> 8),
(byte) singleInt};
}
}
public static byte[] encodeString(String srcString) {
return encodeElement(srcString.getBytes());

View File

@ -12,7 +12,7 @@ import java.nio.ByteBuffer;
*/
public class DataWord {
static DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
byte[] data = new byte[32];

View File

@ -69,4 +69,4 @@ samples.dir = samples
# the existing database will be
# destroyed and all the data will be
# downloaded from peers again
database.reset = false
database.reset = true

View File

@ -4,11 +4,9 @@ import static org.junit.Assert.*;
import java.math.BigInteger;
import org.abego.treelayout.internal.util.Contract;
import org.ethereum.trie.MockDB;
import org.ethereum.trie.Trie;
import org.ethereum.util.RLP;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
@ -55,7 +53,7 @@ public class StateTest {
@Test // right way to calc tx trie hash
public void test1(){
public void testCalculatePostTxState(){
/* txTrieHash=a77691cf47bec9021d3f027fc8ef2d51b758b600a79967154354b8e37108896f */
String expected = "a77691cf47bec9021d3f027fc8ef2d51b758b600a79967154354b8e37108896f";
@ -73,14 +71,13 @@ public class StateTest {
byte[] postTxState = Hex.decode("7fa5bd00f6e03b5a5718560f1e25179b227167585a3c3da06a48f554365fb527");
byte[] cumGas = Hex.decode("0272");
TransactionRecipe tr = new TransactionRecipe(tx, postTxState, cumGas);
TransactionReceipt tr = new TransactionReceipt(tx, postTxState, cumGas);
Trie trie = new Trie(new MockDB());
trie.update(RLP.encodeByte((byte)0), tr.getEncoded());
System.out.println(Hex.toHexString(trie.getRootHash()));
Assert.assertEquals(expected, Hex.toHexString(trie.getRootHash()));
trie.update(RLP.encodeInt(0), tr.getEncoded());
String txTrieRoot = Hex.toHexString(trie.getRootHash());
System.out.println(txTrieRoot);
assertEquals(expected, txTrieRoot);
/* *** GROSS DATA ***
@ -100,7 +97,7 @@ public class StateTest {
extraData=null
nonce=0000000000000000000000000000000000000000000000005d439960040e4505
TransactionRecipe[
TransactionReceipt[
TransactionData [ hash=1ee6fa3149a5e9c09b54009eb6e108aaa7ecd79483d57eedcf2dff93a1505588 nonce=null,
gasPrice=09184e72a000, gas=03e8, receiveAddress=0000000000000000000000000000000000000000, value=03e8,
data=60016000546006601160003960066000f261778e600054, signatureV=27,

View File

@ -150,6 +150,42 @@ public class RLPTest {
assertArrayEquals(expected5, data);
}
@Test /** encode int */
public void testEncodeInt(){
byte[] expected = {(byte)0x80};
byte[] data = RLP.encodeInt(0);
assertArrayEquals(expected, data);
byte[] expected2 = {(byte)0x78};
data = RLP.encodeInt(120);
assertArrayEquals(expected2, data);
byte[] expected3 = {(byte)0x81, (byte)0x7F};
data = RLP.encodeInt(127);
assertArrayEquals(expected3, data);
byte[] expected4 = {(byte)0x82, (byte)0x76, (byte)0x5F};
data = RLP.encodeInt(30303);
assertArrayEquals(expected4, data);
byte[] expected5 = {(byte)0x82, (byte)0x4E, (byte)0xEA};
data = RLP.encodeInt(20202);
assertArrayEquals(expected5, data);
byte[] expected6 = {(byte)0x83, 1, 0, 0};
data = RLP.encodeInt(65536);
assertArrayEquals(expected6, data);
byte[] expected7 = {(byte)0x80};
data = RLP.encodeInt(Integer.MIN_VALUE);
assertArrayEquals(expected7, data);
byte[] expected8 = {(byte)0x84, (byte)0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF};
data = RLP.encodeInt(Integer.MAX_VALUE);
assertArrayEquals(expected8, data);
}
@Test /** encode BigInteger */
public void test6(){

View File

@ -9,7 +9,7 @@ public class DataWordTest {
@Test
public void testAddPerformance() {
boolean enabled = true;
boolean enabled = false;
if(enabled) {
byte[] one = new byte[] { 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54,
@ -68,4 +68,24 @@ public class DataWordTest {
// y.add2(new DataWord(three));
// System.out.println(Hex.toHexString(y.data));
}
@Test
public void testMod() {
String expected = "000000000000000000000000000000000000000000000000000000000000001a";
byte[] one = new byte[32];
one[31] = 0x1e; // 0x000000000000000000000000000000000000000000000000000000000000001e
byte[] two = new byte[32];
for (int i = 0; i < two.length; i++) {
two[i] = (byte) 0xff;
}
two[31] = 0x56; // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
y.mod(x);
assertEquals(32, y.data.length);
assertEquals(expected, Hex.toHexString(y.data));
}
}