Merge pull request #22 from nicksavers/master
Calculate txTrieRoot from txs in a block + minors
This commit is contained in:
commit
3e58497a6f
|
@ -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 block’s 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();
|
||||
|
||||
|
|
|
@ -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 block’s 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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 ]";
|
||||
" ]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) +
|
|
@ -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());
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(){
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue