Merge pull request #1 from nicksavers/master
Start with testing of genesis block
This commit is contained in:
commit
20740beac2
|
@ -5,6 +5,11 @@
|
|||
|
||||
*.xlsx
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.ethereum</groupId>
|
||||
<artifactId>EthereumJ</artifactId>
|
||||
<artifactId>ethereumj</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>EthereumJ</name>
|
||||
|
|
|
@ -61,10 +61,9 @@ public class ConnectionConsole extends JFrame implements PeerListener{
|
|||
public void componentShown(ComponentEvent e) {
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
// new ClientPeer(thisConsole).connect("54.201.28.117", 30303);
|
||||
// new ClientPeer(thisConsole).connect("82.217.72.169", 30303);
|
||||
new ClientPeer(thisConsole).connect("54.204.10.41", 30303);
|
||||
new ClientPeer(thisConsole).connect("54.201.28.117", 30303);
|
||||
// new ClientPeer(thisConsole).connect("82.217.72.169", 30303);
|
||||
// new ClientPeer(thisConsole).connect("54.204.10.41", 30303);
|
||||
}
|
||||
};
|
||||
t.start();
|
||||
|
|
|
@ -25,6 +25,7 @@ public class Block {
|
|||
private static int GAS_LIMIT = (int) Math.pow(10, 6);
|
||||
|
||||
private RLPList rawData;
|
||||
private byte[] encodedBlock;
|
||||
private boolean parsed = false;
|
||||
|
||||
private byte[] hash;
|
||||
|
@ -38,18 +39,34 @@ public class Block {
|
|||
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[] stateHash;
|
||||
private byte[] stateRoot;
|
||||
/* The SHA3 256-bit hash of the root node of the trie structure
|
||||
* populated with each transaction in the transactions list portion
|
||||
* of the block */
|
||||
private byte[] txTrieHash;
|
||||
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;
|
||||
|
||||
private long timestamp;
|
||||
/* 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>();
|
||||
|
@ -59,15 +76,27 @@ public class Block {
|
|||
this.rawData = rawData;
|
||||
this.parsed = false;
|
||||
}
|
||||
|
||||
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txTrieHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List<Transaction> transactionsList, List<Block> uncleList) {
|
||||
|
||||
public Block(byte[] encodedBlock) {
|
||||
this.encodedBlock = encodedBlock;
|
||||
}
|
||||
|
||||
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
|
||||
byte[] stateRoot, byte[] txTrieRoot, byte[] difficulty,
|
||||
long timestamp, long number, long minGasPrice, long gasLimit,
|
||||
long gasUsed, byte[] extraData, byte[] nonce,
|
||||
List<Transaction> transactionsList, List<Block> uncleList) {
|
||||
this.parentHash = parentHash;
|
||||
this.unclesHash = unclesHash;
|
||||
this.coinbase = coinbase;
|
||||
this.stateHash = stateHash;
|
||||
this.txTrieHash = txTrieHash;
|
||||
this.stateRoot = stateRoot;
|
||||
this.txTrieRoot = txTrieRoot;
|
||||
this.difficulty = difficulty;
|
||||
this.timestamp = timestamp;
|
||||
this.number = number;
|
||||
this.minGasPrice = minGasPrice;
|
||||
this.gasLimit = gasLimit;
|
||||
this.gasUsed = gasUsed;
|
||||
this.extraData = extraData;
|
||||
this.nonce = nonce;
|
||||
this.transactionsList = transactionsList;
|
||||
|
@ -75,24 +104,36 @@ public class Block {
|
|||
this.parsed = true;
|
||||
}
|
||||
|
||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_list_hash, difficulty, timestamp, extradata, nonce]
|
||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
|
||||
// difficulty, timestamp, number, minGasPrice, gasLimit, gasUsed,
|
||||
// extradata, nonce]
|
||||
private void parseRLP() {
|
||||
|
||||
this.hash = HashUtil.sha3(rawData.getRLPData());
|
||||
|
||||
List params = ((RLPList) rawData.getElement(0)).getList();
|
||||
|
||||
this.parentHash = ((RLPItem) params.get(0)).getData();
|
||||
this.unclesHash = ((RLPItem) params.get(1)).getData();
|
||||
this.coinbase = ((RLPItem) params.get(2)).getData();
|
||||
this.stateHash = ((RLPItem) params.get(3)).getData();
|
||||
this.txTrieHash = ((RLPItem) params.get(4)).getData();
|
||||
this.difficulty = ((RLPItem) params.get(5)).getData();
|
||||
this.parentHash = ((RLPItem) params.get(0)).getData();
|
||||
this.unclesHash = ((RLPItem) params.get(1)).getData();
|
||||
this.coinbase = ((RLPItem) params.get(2)).getData();
|
||||
this.stateRoot = ((RLPItem) params.get(3)).getData();
|
||||
this.txTrieRoot = ((RLPItem) params.get(4)).getData();
|
||||
this.difficulty = ((RLPItem) params.get(5)).getData();
|
||||
|
||||
byte[] tsBytes = ((RLPItem) params.get(6)).getData();
|
||||
this.timestamp = (new BigInteger(tsBytes)).longValue();
|
||||
this.extraData = ((RLPItem) params.get(7)).getData();
|
||||
this.nonce = ((RLPItem) params.get(8)).getData();
|
||||
byte[] tsBytes = ((RLPItem) params.get(6)).getData();
|
||||
byte[] nrBytes = ((RLPItem) params.get(7)).getData();
|
||||
byte[] gpBytes = ((RLPItem) params.get(8)).getData();
|
||||
byte[] glBytes = ((RLPItem) params.get(9)).getData();
|
||||
byte[] guBytes = ((RLPItem) params.get(10)).getData();
|
||||
|
||||
this.timestamp = (new BigInteger(tsBytes)).longValue();
|
||||
this.number = (new BigInteger(nrBytes)).longValue();
|
||||
this.minGasPrice = (new BigInteger(gpBytes)).longValue();
|
||||
this.gasLimit = (new BigInteger(glBytes)).longValue();
|
||||
this.gasUsed = (new BigInteger(guBytes)).longValue();
|
||||
|
||||
this.extraData = ((RLPItem) params.get(11)).getData();
|
||||
this.nonce = ((RLPItem) params.get(12)).getData();
|
||||
|
||||
// parse transactions
|
||||
List<RLPElement> transactions = ((RLPList) rawData.getElement(1)).getList();
|
||||
|
@ -134,14 +175,14 @@ public class Block {
|
|||
return coinbase;
|
||||
}
|
||||
|
||||
public byte[] getStateHash() {
|
||||
public byte[] getStateRoot() {
|
||||
if (!parsed) parseRLP();
|
||||
return stateHash;
|
||||
return stateRoot;
|
||||
}
|
||||
|
||||
public byte[] getTxTrieHash() {
|
||||
public byte[] getTxTrieRoot() {
|
||||
if (!parsed) parseRLP();
|
||||
return txTrieHash;
|
||||
return txTrieRoot;
|
||||
}
|
||||
|
||||
public byte[] getDifficulty() {
|
||||
|
@ -153,8 +194,24 @@ public class Block {
|
|||
if (!parsed) parseRLP();
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public byte[] getExtraData() {
|
||||
public long getMinGasPrice() {
|
||||
return minGasPrice;
|
||||
}
|
||||
|
||||
public long getGasLimit() {
|
||||
return gasLimit;
|
||||
}
|
||||
|
||||
public long getGasUsed() {
|
||||
return gasUsed;
|
||||
}
|
||||
|
||||
public byte[] getExtraData() {
|
||||
if (!parsed) parseRLP();
|
||||
return extraData;
|
||||
}
|
||||
|
@ -174,21 +231,28 @@ public class Block {
|
|||
return uncleList;
|
||||
}
|
||||
|
||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_list_hash, difficulty, timestamp, extradata, nonce]
|
||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
|
||||
// difficulty, timestamp, number, minGasPrice, gasLimit, gasUsed,
|
||||
// extradata, nonce]
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!parsed) parseRLP();
|
||||
|
||||
return "BlockData [" + " hash=" + Utils.toHexString(hash) +
|
||||
" parentHash=" + Utils.toHexString(parentHash) +
|
||||
", unclesHash=" + Utils.toHexString(unclesHash) +
|
||||
", coinbase=" + Utils.toHexString(coinbase) +
|
||||
", stateHash=" + Utils.toHexString(stateHash) +
|
||||
", txTrieHash=" + Utils.toHexString(txTrieHash) +
|
||||
", difficulty=" + Utils.toHexString(difficulty) +
|
||||
", timestamp=" + timestamp +
|
||||
", extraData=" + Utils.toHexString(extraData) +
|
||||
", nonce=" + Utils.toHexString(nonce) +
|
||||
return "BlockData [" +
|
||||
" hash=" + Utils.toHexString(hash) +
|
||||
" parentHash=" + Utils.toHexString(parentHash) +
|
||||
", unclesHash=" + Utils.toHexString(unclesHash) +
|
||||
", coinbase=" + Utils.toHexString(coinbase) +
|
||||
", stateHash=" + Utils.toHexString(stateRoot) +
|
||||
", txTrieHash=" + Utils.toHexString(txTrieRoot) +
|
||||
", difficulty=" + Utils.toHexString(difficulty) +
|
||||
", timestamp=" + timestamp +
|
||||
", number=" + number +
|
||||
", minGasPrice=" + minGasPrice +
|
||||
", gasLimit=" + gasLimit +
|
||||
", gasUsed=" + gasUsed +
|
||||
", extraData=" + Utils.toHexString(extraData) +
|
||||
", nonce=" + Utils.toHexString(nonce) +
|
||||
']';
|
||||
}
|
||||
|
||||
|
@ -217,4 +281,13 @@ public class Block {
|
|||
return Math.floor((this.getParent().getOplimit() * (EMA_FACTOR - 1)
|
||||
+ Math.floor(GAS_LIMIT * LIMIT_FACTOR)) / EMA_FACTOR);
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if (this.encodedBlock == null) parseRLP();
|
||||
return this.encodedBlock;
|
||||
}
|
||||
|
||||
public byte[] hash() {
|
||||
return HashUtil.sha3(this.getEncoded());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,20 @@ import org.ethereum.crypto.HashUtil;
|
|||
import org.ethereum.net.rlp.RLP;
|
||||
import org.ethereum.net.rlp.RLPList;
|
||||
import org.ethereum.net.vo.Block;
|
||||
import org.ethereum.util.RlpEncoder;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class BlockTest {
|
||||
|
||||
// https://ethereum.etherpad.mozilla.org/12
|
||||
private String CPP_PoC5_GENESIS_STATE_ROOT_HEX_HASH = "2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d";
|
||||
private String CPP_PoC5_GENESIS_HEX_RLP_ENCODED = "f8cbf8c7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817da00000000000000000000000000000000000000000000000000000000000000000834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
|
||||
private String CPP_PoC5_GENESIS_HEX_HASH = "69a7356a245f9dc5b865475ada5ee4e89b18f93c06503a9db3b3630e88e9fb4e";
|
||||
|
||||
@Test /* Creating genesis hash not ready yet */
|
||||
public void test1() throws IOException {
|
||||
|
@ -50,8 +58,6 @@ public class BlockTest {
|
|||
block.appendRaw(RLPEmptyList);
|
||||
|
||||
*/
|
||||
// gennesis hash
|
||||
//ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf
|
||||
|
||||
/* 1 */ byte[] prevHash =
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -108,23 +114,72 @@ public class BlockTest {
|
|||
System.out.println(Hex.toHexString(genesis));
|
||||
|
||||
byte[] hash = HashUtil.sha3(genesis);
|
||||
|
||||
System.out.println(Hex.toHexString(hash));
|
||||
|
||||
System.out.println("ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf");
|
||||
assertEquals(CPP_PoC5_GENESIS_HEX_HASH, Hex.toHexString(hash));
|
||||
}
|
||||
|
||||
@Test /* got from go guy */
|
||||
public void test2(){
|
||||
public void testGenesisFromRLP(){
|
||||
// from RLP encoding
|
||||
byte[] genesisBytes = Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
||||
Block genesis = new Block(genesisBytes);
|
||||
assertEquals(CPP_PoC5_GENESIS_HEX_HASH, Hex.toHexString(genesis.hash()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenesisFromNew() {
|
||||
|
||||
System.out.println(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
||||
Object genesisItems = RlpEncoder.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED.getBytes(), 0).getDecoded();
|
||||
// TODO: verify genesis items with expected values
|
||||
|
||||
byte[] goGenesisBytes = Hex.decode("f8a4f8a0a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000000080a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347834000008080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0");
|
||||
System.out.println( Hex.toHexString( HashUtil.sha3(goGenesisBytes) ) );
|
||||
/* From: https://ethereum.etherpad.mozilla.org/11
|
||||
Genesis block is:
|
||||
(
|
||||
B32(0, 0, ...),
|
||||
B32(sha3(B())),
|
||||
B20(0, 0, ...),
|
||||
B32(stateRoot),
|
||||
B32(0, 0, ...),
|
||||
P(2^22),
|
||||
P(0),
|
||||
P(0),
|
||||
P(1000000),
|
||||
P(0),
|
||||
P(0)
|
||||
B()
|
||||
B32(sha3(B(42)))
|
||||
)
|
||||
*/
|
||||
|
||||
byte[] parentHash = new byte[32]; System.out.println(Hex.toHexString(parentHash));
|
||||
byte[] unclesHash = HashUtil.sha3(new byte[0]); System.out.println(Hex.toHexString(unclesHash));
|
||||
byte[] coinbase = new byte[20]; System.out.println(Hex.toHexString(coinbase));
|
||||
byte[] stateRoot = Hex.decode(CPP_PoC5_GENESIS_STATE_ROOT_HEX_HASH); System.out.println(Hex.toHexString(stateRoot));
|
||||
byte[] txTrieRoot = new byte[32]; System.out.println(Hex.toHexString(txTrieRoot));
|
||||
byte[] difficulty = doubleToByteArray(Math.pow(2, 22)); System.out.println(Hex.toHexString(difficulty));
|
||||
long timestamp = 0; System.out.println(Long.toHexString(timestamp));
|
||||
long number = 0; System.out.println(Long.toHexString(number));
|
||||
long minGasPrice = 0; System.out.println(Long.toHexString(minGasPrice));
|
||||
long gasLimit = 1000000; System.out.println(Long.toHexString(gasLimit));
|
||||
long gasUsed = 0; System.out.println(Long.toHexString(gasUsed));
|
||||
byte[] extraData = new byte[0]; System.out.println(Hex.toHexString(extraData));
|
||||
byte[] nonce = HashUtil.sha3(new byte[]{42}); System.out.println(Hex.toHexString(nonce));
|
||||
Block block = new Block(parentHash, unclesHash, coinbase, stateRoot, txTrieRoot, difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp, extraData, nonce, null, null);
|
||||
assertEquals(CPP_PoC5_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(block.getEncoded()));
|
||||
assertEquals(CPP_PoC5_GENESIS_HEX_HASH, block.hash());
|
||||
}
|
||||
|
||||
private byte[] doubleToByteArray(double d) {
|
||||
byte[] output = new byte[8];
|
||||
long lng = Double.doubleToLongBits(d);
|
||||
for(int i = 0; i < 8; i++) output[i] = (byte)((lng >> ((7 - i) * 8)) & 0xff);
|
||||
return output;
|
||||
}
|
||||
|
||||
@Test /* create BlockData from part of real RLP BLOCKS message */
|
||||
public void test3(){
|
||||
|
||||
String blocksMsg= "F8C8F8C4A07B2536237CBF114A043B0F9B27C76F84AC160EA5B87B53E42C7E76148964D450A01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347943854AAF203BA5F8D49B1EC221329C7AEBCF050D3A07A3BE0EE10ECE4B03097BF74AABAC628AA0FAE617377D30AB1B97376EE31F41AA01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347833FBFE884533F1CE880A0000000000000000000000000000000000000000000000000F3DEEA84969B6E95C0C0";
|
||||
String blocksMsg = "F8C8F8C4A07B2536237CBF114A043B0F9B27C76F84AC160EA5B87B53E42C7E76148964D450A01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347943854AAF203BA5F8D49B1EC221329C7AEBCF050D3A07A3BE0EE10ECE4B03097BF74AABAC628AA0FAE617377D30AB1B97376EE31F41AA01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347833FBFE884533F1CE880A0000000000000000000000000000000000000000000000000F3DEEA84969B6E95C0C0";
|
||||
|
||||
byte[] payload = Hex.decode(blocksMsg);
|
||||
|
||||
|
|
|
@ -351,10 +351,10 @@ public class MessagesTest {
|
|||
Utils.toHexString(block.getCoinbase()).toUpperCase());
|
||||
|
||||
assertEquals("5E2D2CC0B42B38B5B18C9D65734F9877C035DD390B9C12C48624F2243668A268",
|
||||
Utils.toHexString(block.getStateHash()).toUpperCase());
|
||||
Utils.toHexString(block.getStateRoot()).toUpperCase());
|
||||
|
||||
assertEquals("1DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347",
|
||||
Utils.toHexString(block.getTxTrieHash()).toUpperCase());
|
||||
Utils.toHexString(block.getTxTrieRoot()).toUpperCase());
|
||||
|
||||
assertEquals("02471A26", Utils.toHexString(block.getDifficulty()).toUpperCase());
|
||||
assertEquals(1398260220, block.getTimestamp());
|
||||
|
@ -395,10 +395,10 @@ public class MessagesTest {
|
|||
Utils.toHexString(block.getCoinbase()).toUpperCase());
|
||||
|
||||
assertEquals("990DC3B5ACBEE04124361D958FE51ACB582593613FC290683940A0769549D3ED",
|
||||
Utils.toHexString(block.getStateHash()).toUpperCase());
|
||||
Utils.toHexString(block.getStateRoot()).toUpperCase());
|
||||
|
||||
assertEquals("9BFE4817D274EA3EB8672E9FE848C3885B53BBBD1D7C26E6039F90FB96B942B0",
|
||||
Utils.toHexString(block.getTxTrieHash()).toUpperCase());
|
||||
Utils.toHexString(block.getTxTrieRoot()).toUpperCase());
|
||||
|
||||
assertEquals("3FF000", Utils.toHexString(block.getDifficulty()).toUpperCase());
|
||||
assertEquals(1396643511, block.getTimestamp());
|
||||
|
|
Loading…
Reference in New Issue