/* * 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.longrun; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.TransactionReceipt; import org.ethereum.db.DbFlushManager; import org.ethereum.facade.Ethereum; import org.ethereum.facade.EthereumFactory; import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.net.eth.message.StatusMessage; import org.ethereum.net.rlpx.Node; import org.ethereum.net.server.Channel; import org.ethereum.sync.SyncPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import javax.annotation.PostConstruct; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Vector; import static java.lang.Thread.sleep; /** * BasicNode of ethereum instance */ class BasicNode implements Runnable { static final Logger sLogger = LoggerFactory.getLogger("sample"); private String loggerName; public Logger logger; @Autowired protected Ethereum ethereum; @Autowired protected SystemProperties config; @Autowired protected SyncPool syncPool; @Autowired protected CommonConfig commonConfig; @Autowired protected DbFlushManager dbFlushManager; // Spring config class which add this sample class as a bean to the components collections // and make it possible for autowiring other components private static class Config { @Bean public BasicNode basicSample() { return new BasicNode(); } } public static void main(String[] args) throws Exception { sLogger.info("Starting EthereumJ!"); // Based on Config class the BasicNode would be created by Spring // and its springInit() method would be called as an entry point EthereumFactory.createEthereum(Config.class); } public BasicNode() { this("sample"); } /** * logger name can be passed if more than one EthereumJ instance is created * in a single JVM to distinguish logging output from different instances */ public BasicNode(String loggerName) { this.loggerName = loggerName; } /** * The method is called after all EthereumJ instances are created */ @PostConstruct private void springInit() { logger = LoggerFactory.getLogger(loggerName); // adding the main EthereumJ callback to be notified on different kind of events ethereum.addListener(listener); logger.info("Sample component created. Listening for ethereum events..."); // starting lifecycle tracking method run() new Thread(this, "SampleWorkThread").start(); } /** * The method tracks step-by-step the instance lifecycle from node discovery till sync completion. * At the end the method onSyncDone() is called which might be overridden by a sample subclass * to start making other things with the Ethereum network */ public void run() { try { logger.info("Sample worker thread started."); if (!config.peerDiscovery()) { logger.info("Peer discovery disabled. We should actively connect to another peers or wait for incoming connections"); } waitForSync(); onSyncDone(); } catch (Exception e) { logger.error("Error occurred in Sample: ", e); } } /** * Waits until the whole blockchain sync is complete */ public void waitForSync() throws Exception { logger.info("Waiting for the whole blockchain sync (will take up to an hour on fast sync for the whole chain)..."); while(true) { sleep(10000); if (syncComplete) { logger.info("[v] Sync complete! The best block: " + bestBlock.getShortDescr()); return; } } } /** * Is called when the whole blockchain sync is complete */ public void onSyncDone() throws Exception { logger.info("Monitoring new blocks in real-time..."); } public void onSyncDoneImpl(EthereumListener.SyncState state) { logger.info("onSyncDone: " + state); } protected Map<Node, StatusMessage> ethNodes = new Hashtable<>(); protected List<Node> syncPeers = new Vector<>(); protected Block bestBlock = null; EthereumListener.SyncState syncState = null; boolean syncComplete = false; /** * The main EthereumJ callback. */ EthereumListener listener = new EthereumListenerAdapter() { @Override public void onSyncDone(SyncState state) { syncState = state; if (state.equals(SyncState.COMPLETE)) syncComplete = true; onSyncDoneImpl(state); } @Override public void onEthStatusUpdated(Channel channel, StatusMessage statusMessage) { ethNodes.put(channel.getNode(), statusMessage); } @Override public void onPeerAddedToSyncPool(Channel peer) { syncPeers.add(peer.getNode()); } @Override public void onBlock(Block block, List<TransactionReceipt> receipts) { bestBlock = block; if (syncComplete) { logger.info("New block: " + block.getShortDescr()); } } }; }