/* * 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.net; import com.typesafe.config.ConfigFactory; import org.ethereum.config.NoAutoscan; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.crypto.ECKey; import org.ethereum.facade.Ethereum; import org.ethereum.facade.EthereumFactory; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.mine.Ethash; import org.ethereum.net.eth.handler.Eth62; import org.ethereum.net.eth.message.*; import org.ethereum.net.server.Channel; import org.ethereum.util.RLP; import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.encoders.Hex; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static java.lang.Math.max; import static java.lang.Math.min; import static org.ethereum.crypto.HashUtil.sha3; /** * Created by Anton Nashatyrev on 13.10.2015. */ @Ignore public class TwoPeerTest { @Configuration @NoAutoscan public static class SysPropConfig1 { static Eth62 testHandler = null; @Bean @Scope("prototype") public Eth62 eth62() { return testHandler; // return new Eth62(); } static SystemProperties props = new SystemProperties();; @Bean public SystemProperties systemProperties() { return props; } } @Configuration @NoAutoscan public static class SysPropConfig2 { static SystemProperties props= new SystemProperties(); @Bean public SystemProperties systemProperties() { return props; } } public Block createNextBlock(Block parent, String stateRoot, String extraData) { Block b = new Block(parent.getHash(), sha3(RLP.encodeList()), parent.getCoinbase(), parent.getLogBloom(), parent.getDifficulty(), parent.getNumber() + 1, parent.getGasLimit(), parent.getGasUsed(), System.currentTimeMillis() / 1000, new byte[0], new byte[0], new byte[0], parent.getReceiptsRoot(), parent.getTxTrieRoot(), Hex.decode(stateRoot), // Hex.decode("7c22bebbe3e6cf5af810bef35ad7a7b8172e0a247eaeb44f63fffbce87285a7a"), Collections.<Transaction>emptyList(), Collections.<BlockHeader>emptyList()); // b.getHeader().setDifficulty(b.getHeader().calcDifficulty(bestBlock.getHeader()).toByteArray()); if (extraData != null) { b.getHeader().setExtraData(extraData.getBytes()); } return b; } public Block addNextBlock(BlockchainImpl blockchain1, Block parent, String extraData) { Block b = createNextBlock(parent, "00", extraData); System.out.println("Adding block."); // blockchain1.add(b, new Miner() { // @Override // public long mine(BlockHeader header) { // return Ethash.getForBlock(header.getNumber()).mineLight(header); // } // // @Override // public boolean validate(BlockHeader header) { // return true; // } // }); return b; } @Test public void testTest() throws FileNotFoundException, InterruptedException { SysPropConfig1.props.overrideParams( "peer.listen.port", "30334", "peer.privateKey", "3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c", // nodeId: 3973cb86d7bef9c96e5d589601d788370f9e24670dcba0480c0b3b1b0647d13d0f0fffed115dd2d4b5ca1929287839dcd4e77bdc724302b44ae48622a8766ee6 "genesis", "genesis-light.json", "database.dir", "testDB-1"); SysPropConfig2.props.overrideParams(ConfigFactory.parseString( "peer.listen.port = 30335 \n" + "peer.privateKey = 6ef8da380c27cea8fdf7448340ea99e8e2268fc2950d79ed47cbf6f85dc977ec \n" + "peer.active = [{ url = \"enode://3973cb86d7bef9c96e5d589601d788370f9e24670dcba0480c0b3b1b0647d13d0f0fffed115dd2d4b5ca1929287839dcd4e77bdc724302b44ae48622a8766ee6@localhost:30334\" }] \n" + "sync.enabled = true \n" + "genesis = genesis-light.json \n" + "database.dir = testDB-2 \n")); final List<Block> alternativeFork = new ArrayList<>(); SysPropConfig1.testHandler = new Eth62() { @Override protected void processGetBlockHeaders(GetBlockHeadersMessage msg) { if (msg.getBlockHash() != null) { System.out.println("=== (1)"); for (int i = 0; i < alternativeFork.size(); i++) { if (Arrays.equals(msg.getBlockHash(), alternativeFork.get(i).getHash())) { System.out.println("=== (2)"); int endIdx = max(0, i - msg.getSkipBlocks()); int startIdx = max(0, i - msg.getMaxHeaders()); if (!msg.isReverse()) { startIdx = min(alternativeFork.size() - 1, i + msg.getSkipBlocks()); endIdx = min(alternativeFork.size() - 1, i + msg.getMaxHeaders()); } List<BlockHeader> headers = new ArrayList<>(); for (int j = startIdx; j <= endIdx; j++) { headers.add(alternativeFork.get(j).getHeader()); } if (msg.isReverse()) { Collections.reverse(headers); } sendMessage(new BlockHeadersMessage(headers)); return; } } } super.processGetBlockHeaders(msg); } @Override protected void processGetBlockBodies(GetBlockBodiesMessage msg) { List<byte[]> bodies = new ArrayList<>(msg.getBlockHashes().size()); for (byte[] hash : msg.getBlockHashes()) { Block block = null; for (Block b : alternativeFork) { if (Arrays.equals(b.getHash(), hash)) { block = b; break; } } if (block == null) { block = blockchain.getBlockByHash(hash); } bodies.add(block.getEncodedBody()); } sendMessage(new BlockBodiesMessage(bodies)); } }; Ethereum ethereum1 = EthereumFactory.createEthereum(SysPropConfig1.props, SysPropConfig1.class); BlockchainImpl blockchain = (BlockchainImpl) ethereum1.getBlockchain(); Block bGen = blockchain.getBestBlock(); Block b1 = addNextBlock(blockchain, bGen, "chain A"); Block b2 = addNextBlock(blockchain, b1, null); Block b3 = addNextBlock(blockchain, b2, null); Block b4 = addNextBlock(blockchain, b3, null); List<BlockHeader> listOfHeadersStartFrom = blockchain.getListOfHeadersStartFrom(new BlockIdentifier(null, 3), 0, 100, true); // Block b1b = addNextBlock(blockchain, bGen, "chain B"); Block b1b = createNextBlock(bGen, "7c22bebbe3e6cf5af810bef35ad7a7b8172e0a247eaeb44f63fffbce87285a7a", "chain B"); Ethash.getForBlock(SystemProperties.getDefault(), b1b.getNumber()).mineLight(b1b); Block b2b = createNextBlock(b1b, Hex.toHexString(b2.getStateRoot()), "chain B"); Ethash.getForBlock(SystemProperties.getDefault(), b2b.getNumber()).mineLight(b2b); alternativeFork.add(bGen); alternativeFork.add(b1b); alternativeFork.add(b2b); // byte[] root = ((RepositoryImpl) ethereum.getRepository()).getRoot(); // ((RepositoryImpl) ethereum.getRepository()).syncToRoot(root); // byte[] root1 = ((RepositoryImpl) ethereum.getRepository()).getRoot(); // Block b2b = addNextBlock(blockchain, b1, "chain B"); System.out.println("Blocks added"); Ethereum ethereum2 = EthereumFactory.createEthereum(SysPropConfig2.props, SysPropConfig2.class); final CountDownLatch semaphore = new CountDownLatch(1); final Channel[] channel1 = new Channel[1]; ethereum1.addListener(new EthereumListenerAdapter() { @Override public void onEthStatusUpdated(Channel channel, StatusMessage statusMessage) { channel1[0] = channel; System.out.println("==== Got the Channel: " + channel); } }); ethereum2.addListener(new EthereumListenerAdapter() { @Override public void onBlock(Block block, List<TransactionReceipt> receipts) { if (block.getNumber() == 4) { semaphore.countDown(); } } }); System.out.println("======= Waiting for block #4"); semaphore.await(60, TimeUnit.SECONDS); if(semaphore.getCount() > 0) { throw new RuntimeException("4 blocks were not imported."); } System.out.println("======= Sending forked block without parent..."); // ((EthHandler) channel1[0].getEthHandler()).sendNewBlock(b2b); // Block b = b4; // for (int i = 0; i < 10; i++) { // Thread.sleep(3000); // System.out.println("===== Adding next block..."); // b = addNextBlock(blockchain, b, null); // } Thread.sleep(10000000); ethereum1.close(); ethereum2.close(); System.out.println("Passed."); } public static void main(String[] args) throws Exception { ECKey k = ECKey.fromPrivate(Hex.decode("6ef8da380c27cea8fdf7448340ea99e8e2268fc2950d79ed47cbf6f85dc977ec")); System.out.println(Hex.toHexString(k.getPrivKeyBytes())); System.out.println(Hex.toHexString(k.getAddress())); System.out.println(Hex.toHexString(k.getNodeId())); } }