/* * Copyright (c) [2016] [ <ether.camp> ] * This file is part of the ethereumJ library. * * The ethereumJ library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ethereumJ library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>. */ package org.ethereum.core; import org.ethereum.config.SystemProperties; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.trie.SecureTrie; import org.ethereum.trie.Trie; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.*; import org.junit.runners.MethodSorters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; import java.util.Collection; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class BlockTest { private static final Logger logger = LoggerFactory.getLogger("test"); // https://github.com/ethereum/tests/blob/71d80bd63aaf7cee523b6ca9d12a131698d41e98/BasicTests/genesishashestest.json private String GENESIS_RLP = "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0"; private String GENESIS_HASH = "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca"; private String GENESIS_STATE_ROOT = "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e"; private String MESSY_NONCE_GENESIS_RLP = "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0da3d5bd4c2f8443fbca1f12c0b9eaa4996825e9d32d239ffb302b8f98f202c97a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008301000080832fefd8808080a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0"; private String MESSY_NONCE_GENESIS_HASH = "b096cfdeb2a3c0abd3ce9f77cf5adc92a8cead34aa4d2be54c004373e3986788"; static String TEST_GENESIS = "{" + "'0000000000000000000000000000000000000001': { 'wei': '1' }" + "'0000000000000000000000000000000000000002': { 'wei': '1' }" + "'0000000000000000000000000000000000000003': { 'wei': '1' }" + "'0000000000000000000000000000000000000004': { 'wei': '1' }" + "'dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'e6716f9544a56c530d868e4bfbacb172315bdead': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'b9c015918bdaba24b4ff057a92a3873d6eb201be': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'1a26338f0d905e295fccb71fa9ea849ffa12aaf4': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'2ef47100e0787b915105fd5e3f4ff6752079d5cb': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'cd2a3d9f938e13cd947ec05abc7fe734df8dd826': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'6c386a4b26f73c802f34673f7248bb118f97424a': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "'e4157b34ea9615cfbde6b4fda419828124b70c78': { 'wei': '1606938044258990275541962092341162602522202993782792835301376' }" + "}"; static { TEST_GENESIS = TEST_GENESIS.replace("'", "\""); } @Test public void testGenesisFromRLP() { // from RLP encoding byte[] genesisBytes = Hex.decode(GENESIS_RLP); Block genesisFromRLP = new Block(genesisBytes); Block genesis = GenesisLoader.loadGenesis(getClass().getResourceAsStream("/genesis/olympic.json")); assertEquals(Hex.toHexString(genesis.getHash()), Hex.toHexString(genesisFromRLP.getHash())); assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash())); assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot())); } private Block loadGenesisFromFile(String resPath) { Block genesis = GenesisLoader.loadGenesis(getClass().getResourceAsStream(resPath)); logger.info(genesis.toString()); logger.info("genesis hash: [{}]", Hex.toHexString(genesis.getHash())); logger.info("genesis rlp: [{}]", Hex.toHexString(genesis.getEncoded())); return genesis; } @Test public void testGenesisFromNew() { Block genesis = loadGenesisFromFile("/genesis/olympic.json"); assertEquals(GENESIS_HASH, Hex.toHexString(genesis.getHash())); assertEquals(GENESIS_RLP, Hex.toHexString(genesis.getEncoded())); } /** * Test genesis loading from JSON with some * freedom for user like odd length of hex values etc. */ @Test public void testGenesisFromNewMessy() { Block genesis = loadGenesisFromFile("/genesis/olympic-messy.json"); assertEquals(GENESIS_HASH, Hex.toHexString(genesis.getHash())); assertEquals(GENESIS_RLP, Hex.toHexString(genesis.getEncoded())); } /** * Test genesis with empty nonce * + alloc addresses with 0x */ @Test public void testGenesisEmptyNonce() { Block genesis = loadGenesisFromFile("/genesis/nonce-messy.json"); assertEquals(MESSY_NONCE_GENESIS_HASH, Hex.toHexString(genesis.getHash())); assertEquals(MESSY_NONCE_GENESIS_RLP, Hex.toHexString(genesis.getEncoded())); } /** * Test genesis with short nonce * + alloc addresses with 0x */ @Test public void testGenesisShortNonce() { Block genesis = loadGenesisFromFile("/genesis/nonce-messy2.json"); assertEquals(MESSY_NONCE_GENESIS_HASH, Hex.toHexString(genesis.getHash())); assertEquals(MESSY_NONCE_GENESIS_RLP, Hex.toHexString(genesis.getEncoded())); } @Test public void testGenesisPremineData() { Genesis genesis = GenesisLoader.loadGenesis(getClass().getResourceAsStream("/genesis/olympic.json")); Collection<Genesis.PremineAccount> accounts = genesis.getPremine().values(); assertTrue(accounts.size() == 12); } @Test public void testPremineFromJSON() throws ParseException { JSONParser parser = new JSONParser(); JSONObject genesisMap = (JSONObject) parser.parse(TEST_GENESIS); Set keys = genesisMap.keySet(); Trie state = new SecureTrie((byte[]) null); for (Object key : keys) { JSONObject val = (JSONObject) genesisMap.get(key); String denom = (String) val.keySet().toArray()[0]; String value = (String) val.values().toArray()[0]; BigInteger wei = Denomination.valueOf(denom.toUpperCase()).value().multiply(new BigInteger(value)); AccountState acctState = new AccountState(BigInteger.ZERO, wei); state.put(Hex.decode(key.toString()), acctState.getEncoded()); } logger.info("root: " + Hex.toHexString(state.getRootHash())); assertEquals(GENESIS_STATE_ROOT, Hex.toHexString(state.getRootHash())); } @Test public void testFrontierGenesis(){ SystemProperties config = new SystemProperties(); config.setGenesisInfo("frontier.json"); Block genesis = config.getGenesis(); String hash = Hex.toHexString(genesis.getHash()); String root = Hex.toHexString(genesis.getStateRoot()); assertEquals("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544", root); assertEquals("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", hash); } @Test public void testZeroPrecedingDifficultyGenesis(){ SystemProperties config = new SystemProperties(); config.setGenesisInfo("genesis-low-difficulty.json"); Block genesis = config.getGenesis(); String hash = Hex.toHexString(genesis.getHash()); String root = Hex.toHexString(genesis.getStateRoot()); assertEquals("8028c28b55eab8be08883e921f20d1b6cc9f2aa02cc6cd90cfaa9b0462ff6d3e", root); assertEquals("05b2dc41ade973d26db921052bcdaf54e2e01b308c9e90723b514823a0923592", hash); } }