Example usage for com.google.common.util.concurrent SettableFuture create

List of usage examples for com.google.common.util.concurrent SettableFuture create

Introduction

In this page you can find the example usage for com.google.common.util.concurrent SettableFuture create.

Prototype

public static <V> SettableFuture<V> create() 

Source Link

Document

Creates a new SettableFuture that can be completed or cancelled by a later method call.

Usage

From source file:com.google.bitcoin.examples.PrintPeers.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();//from   w w w . j  a  va 2s  .c om
    System.out.println("=== DNS ===");
    printDNS();
    System.out.println("=== Version/chain heights ===");

    ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
    for (InetSocketAddress peer : dnsPeers)
        addrs.add(peer.getAddress());
    System.out.println("Scanning " + addrs.size() + " peers:");

    final NetworkParameters params = MainNetParams.get();
    final Object lock = new Object();
    final long[] bestHeight = new long[1];

    List<ListenableFuture<Void>> futures = Lists.newArrayList();
    NioClientManager clientManager = new NioClientManager();
    for (final InetAddress addr : addrs) {
        InetSocketAddress address = new InetSocketAddress(addr, params.getPort());
        final Peer peer = new Peer(params, new VersionMessage(params, 0), null, new PeerAddress(address));
        final SettableFuture future = SettableFuture.create();
        // Once the connection has completed version handshaking ...
        peer.addEventListener(new AbstractPeerEventListener() {
            public void onPeerConnected(Peer p, int peerCount) {
                // Check the chain height it claims to have.
                VersionMessage ver = peer.getPeerVersionMessage();
                long nodeHeight = ver.bestHeight;
                synchronized (lock) {
                    long diff = bestHeight[0] - nodeHeight;
                    if (diff > 0) {
                        System.out.println("Node is behind by " + diff + " blocks: " + addr);
                    } else if (diff == 0) {
                        System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
                        bestHeight[0] = nodeHeight;
                    } else if (diff < 0) {
                        System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
                        bestHeight[0] = nodeHeight;
                    }
                }
                // Now finish the future and close the connection
                future.set(null);
                peer.close();
            }

            public void onPeerDisconnected(Peer p, int peerCount) {
                if (!future.isDone())
                    System.out.println("Failed to talk to " + addr);
                future.set(null);
            }
        });
        clientManager.openConnection(address, peer);
        futures.add(future);
    }
    // Wait for every tried connection to finish.
    Futures.successfulAsList(futures).get();
}

From source file:org.guldenj.examples.PrintPeers.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();//from   w  w w. java  2 s. c o  m
    System.out.println("=== DNS ===");
    printDNS();
    System.out.println("=== Version/chain heights ===");

    ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
    for (InetSocketAddress peer : dnsPeers)
        addrs.add(peer.getAddress());
    System.out.println("Scanning " + addrs.size() + " peers:");

    final NetworkParameters params = MainNetParams.get();
    final Object lock = new Object();
    final long[] bestHeight = new long[1];

    List<ListenableFuture<Void>> futures = Lists.newArrayList();
    NioClientManager clientManager = new NioClientManager();
    for (final InetAddress addr : addrs) {
        InetSocketAddress address = new InetSocketAddress(addr, params.getPort());
        final Peer peer = new Peer(params, new VersionMessage(params, 0), null, new PeerAddress(address));
        final SettableFuture<Void> future = SettableFuture.create();
        // Once the connection has completed version handshaking ...
        peer.addConnectedEventListener(new PeerConnectedEventListener() {
            @Override
            public void onPeerConnected(Peer p, int peerCount) {
                // Check the chain height it claims to have.
                VersionMessage ver = peer.getPeerVersionMessage();
                long nodeHeight = ver.bestHeight;
                synchronized (lock) {
                    long diff = bestHeight[0] - nodeHeight;
                    if (diff > 0) {
                        System.out.println("Node is behind by " + diff + " blocks: " + addr);
                    } else if (diff == 0) {
                        System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
                        bestHeight[0] = nodeHeight;
                    } else if (diff < 0) {
                        System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
                        bestHeight[0] = nodeHeight;
                    }
                }
                // Now finish the future and close the connection
                future.set(null);
                peer.close();
            }
        });
        peer.addDisconnectedEventListener(new PeerDisconnectedEventListener() {
            @Override
            public void onPeerDisconnected(Peer p, int peerCount) {
                if (!future.isDone())
                    System.out.println("Failed to talk to " + addr);
                future.set(null);
            }
        });
        clientManager.openConnection(address, peer);
        futures.add(future);
    }
    // Wait for every tried connection to finish.
    Futures.successfulAsList(futures).get();
}

From source file:com.dogecoin.dogecoinj.examples.PrintPeers.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*from   w ww. jav  a2s .c  om*/
    System.out.println("=== DNS ===");
    printDNS();
    System.out.println("=== Version/chain heights ===");

    ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
    for (InetSocketAddress peer : dnsPeers)
        addrs.add(peer.getAddress());
    System.out.println("Scanning " + addrs.size() + " peers:");

    final NetworkParameters params = MainNetParams.get();
    final Object lock = new Object();
    final long[] bestHeight = new long[1];

    List<ListenableFuture<Void>> futures = Lists.newArrayList();
    NioClientManager clientManager = new NioClientManager();
    for (final InetAddress addr : addrs) {
        InetSocketAddress address = new InetSocketAddress(addr, params.getPort());
        final Peer peer = new Peer(params, new VersionMessage(params, 0), null, new PeerAddress(address));
        final SettableFuture<Void> future = SettableFuture.create();
        // Once the connection has completed version handshaking ...
        peer.addEventListener(new AbstractPeerEventListener() {
            @Override
            public void onPeerConnected(Peer p, int peerCount) {
                // Check the chain height it claims to have.
                VersionMessage ver = peer.getPeerVersionMessage();
                long nodeHeight = ver.bestHeight;
                synchronized (lock) {
                    long diff = bestHeight[0] - nodeHeight;
                    if (diff > 0) {
                        System.out.println("Node is behind by " + diff + " blocks: " + addr);
                    } else if (diff == 0) {
                        System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
                        bestHeight[0] = nodeHeight;
                    } else if (diff < 0) {
                        System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
                        bestHeight[0] = nodeHeight;
                    }
                }
                // Now finish the future and close the connection
                future.set(null);
                peer.close();
            }

            @Override
            public void onPeerDisconnected(Peer p, int peerCount) {
                if (!future.isDone())
                    System.out.println("Failed to talk to " + addr);
                future.set(null);
            }
        });
        clientManager.openConnection(address, peer);
        futures.add(future);
    }
    // Wait for every tried connection to finish.
    Futures.successfulAsList(futures).get();
}

From source file:org.bitcoinj.examples.PrintPeers.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*from ww w . j a  va 2 s  .c o m*/
    System.out.println("=== DNS ===");
    printDNS();
    System.out.println("=== Version/chain heights ===");

    ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
    for (InetSocketAddress peer : dnsPeers)
        addrs.add(peer.getAddress());
    System.out.println("Scanning " + addrs.size() + " peers:");

    final NetworkParameters params = MainNetParams.get();
    final Object lock = new Object();
    final long[] bestHeight = new long[1];

    List<ListenableFuture<Void>> futures = Lists.newArrayList();
    NioClientManager clientManager = new NioClientManager();
    for (final InetAddress addr : addrs) {
        InetSocketAddress address = new InetSocketAddress(addr, params.getPort());
        final Peer peer = new Peer(params, new VersionMessage(params, 0), null,
                new PeerAddress(params, address));
        final SettableFuture<Void> future = SettableFuture.create();
        // Once the connection has completed version handshaking ...
        peer.addConnectedEventListener(new PeerConnectedEventListener() {
            @Override
            public void onPeerConnected(Peer p, int peerCount) {
                // Check the chain height it claims to have.
                VersionMessage ver = peer.getPeerVersionMessage();
                long nodeHeight = ver.bestHeight;
                synchronized (lock) {
                    long diff = bestHeight[0] - nodeHeight;
                    if (diff > 0) {
                        System.out.println("Node is behind by " + diff + " blocks: " + addr);
                    } else if (diff == 0) {
                        System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
                        bestHeight[0] = nodeHeight;
                    } else if (diff < 0) {
                        System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
                        bestHeight[0] = nodeHeight;
                    }
                }
                // Now finish the future and close the connection
                future.set(null);
                peer.close();
            }
        });
        peer.addDisconnectedEventListener(new PeerDisconnectedEventListener() {
            @Override
            public void onPeerDisconnected(Peer p, int peerCount) {
                if (!future.isDone())
                    System.out.println("Failed to talk to " + addr);
                future.set(null);
            }
        });
        clientManager.openConnection(address, peer);
        futures.add(future);
    }
    // Wait for every tried connection to finish.
    Futures.successfulAsList(futures).get();
}

From source file:com.google.worldcoin.examples.PrintPeers.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*from w  w w  . j  a  v  a  2s . c o m*/
    System.out.println("=== DNS ===");
    printDNS();
    System.out.println("=== Version/chain heights ===");

    ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
    for (InetSocketAddress peer : dnsPeers)
        addrs.add(peer.getAddress());
    //addrs.add(convertAddress());

    System.out.println("Scanning " + addrs.size() + " peers:");

    final NetworkParameters params = MainNetParams.get();
    final Object lock = new Object();
    final long[] bestHeight = new long[1];

    List<ListenableFuture<Void>> futures = Lists.newArrayList();
    NioClientManager clientManager = new NioClientManager();
    for (final InetAddress addr : addrs) {
        InetSocketAddress address = new InetSocketAddress(addr, params.getPort());
        final Peer peer = new Peer(params, new VersionMessage(params, 0), null, new PeerAddress(address));
        final SettableFuture future = SettableFuture.create();
        // Once the connection has completed version handshaking ...
        peer.addEventListener(new AbstractPeerEventListener() {
            public void onPeerConnected(Peer p, int peerCount) {
                // Check the chain height it claims to have.
                VersionMessage ver = peer.getPeerVersionMessage();
                long nodeHeight = ver.bestHeight;
                synchronized (lock) {
                    long diff = bestHeight[0] - nodeHeight;
                    if (diff > 0) {
                        System.out.println("Node is behind by " + diff + " blocks: " + addr);
                    } else if (diff == 0) {
                        System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
                        bestHeight[0] = nodeHeight;
                    } else if (diff < 0) {
                        System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
                        bestHeight[0] = nodeHeight;
                    }
                }
                // Now finish the future and close the connection
                future.set(null);
                peer.close();
            }

            public void onPeerDisconnected(Peer p, int peerCount) {
                if (!future.isDone())
                    System.out.println("Failed to talk to " + addr);
                future.set(null);
            }
        });
        clientManager.start();
        clientManager.openConnection(address, peer);
        futures.add(future);
    }
    // Wait for every tried connection to finish.
    Futures.successfulAsList(futures).get();
}

From source file:org.bitcoinj.core.BitcoindComparisonTool.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();//from   w  ww  . j  ava  2  s . c o  m
    System.out.println("USAGE: bitcoinjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
    boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;

    params = RegTestParams.get();
    Context ctx = new Context(params);

    File blockFile = File.createTempFile("testBlocks", ".dat");
    blockFile.deleteOnExit();

    FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
    final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
    final Map<Sha256Hash, Block> preloadedBlocks = new HashMap<>();
    final Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));

    try {
        H2FullPrunedBlockStore store = new H2FullPrunedBlockStore(params,
                args.length > 0 ? args[0] : "BitcoindComparisonTool", blockList.maximumReorgBlockCount);
        store.resetStore();
        //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
        chain = new FullPrunedBlockChain(params, store);
    } catch (BlockStoreException e) {
        e.printStackTrace();
        System.exit(1);
    }

    VersionMessage ver = new VersionMessage(params, 42);
    ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
    ver.localServices = VersionMessage.NODE_NETWORK;
    final Peer bitcoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)),
            new PeerAddress(params, InetAddress.getLocalHost()));
    Preconditions.checkState(bitcoind.getVersionMessage().hasBlockChain());

    final BlockWrapper currentBlock = new BlockWrapper();

    final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final Set<Sha256Hash> blocksPendingSend = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final AtomicInteger unexpectedInvs = new AtomicInteger(0);
    final SettableFuture<Void> connectedFuture = SettableFuture.create();
    bitcoind.addConnectedEventListener(Threading.SAME_THREAD, new PeerConnectedEventListener() {
        @Override
        public void onPeerConnected(Peer peer, int peerCount) {
            if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
                System.out.println();
                System.out.println(
                        "************************************************************************************************************************\n"
                                + "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n"
                                + "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Bitcoin\n"
                                + "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n"
                                + "Instead, go work on making Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n"
                                + "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n"
                                + "************************************************************************************************************************");
                System.out.println();
            }
            log.info("bitcoind connected");
            // Make sure bitcoind has no blocks
            bitcoind.setDownloadParameters(0, false);
            bitcoind.startBlockChainDownload();
            connectedFuture.set(null);
        }
    });

    bitcoind.addDisconnectedEventListener(Threading.SAME_THREAD, new PeerDisconnectedEventListener() {
        @Override
        public void onPeerDisconnected(Peer peer, int peerCount) {
            log.error("bitcoind node disconnected!");
            System.exit(1);
        }
    });

    bitcoind.addPreMessageReceivedEventListener(Threading.SAME_THREAD, new PreMessageReceivedEventListener() {
        @Override
        public Message onPreMessageReceived(Peer peer, Message m) {
            if (m instanceof HeadersMessage) {
                if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
                    Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
                    log.info("Got header from bitcoind " + b.getHashAsString());
                    bitcoindChainHead = b.getHash();
                } else
                    log.info("Got empty header message from bitcoind");
                return null;
            } else if (m instanceof Block) {
                log.error("bitcoind sent us a block it already had, make sure bitcoind has no blocks!");
                System.exit(1);
            } else if (m instanceof GetDataMessage) {
                for (InventoryItem item : ((GetDataMessage) m).items)
                    if (item.type == InventoryItem.Type.Block) {
                        log.info("Requested " + item.hash);
                        if (currentBlock.block.getHash().equals(item.hash))
                            bitcoind.sendMessage(currentBlock.block);
                        else {
                            Block nextBlock = preloadedBlocks.get(item.hash);
                            if (nextBlock != null)
                                bitcoind.sendMessage(nextBlock);
                            else {
                                blocksPendingSend.add(item.hash);
                                log.info("...which we will not provide yet");
                            }
                        }
                        blocksRequested.add(item.hash);
                    }
                return null;
            } else if (m instanceof GetHeadersMessage) {
                try {
                    if (currentBlock.block == null) {
                        log.info("Got a request for a header before we had even begun processing blocks!");
                        return null;
                    }
                    LinkedList<Block> headers = new LinkedList<>();
                    Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
                    while (it != null) {
                        headers.addFirst(it);
                        it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
                    }
                    LinkedList<Block> sendHeaders = new LinkedList<>();
                    boolean found = false;
                    for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
                        for (Block b : headers) {
                            if (found) {
                                sendHeaders.addLast(b);
                                log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
                                if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
                                    break;
                            } else if (b.getHash().equals(hash)) {
                                log.info("Found header " + b.getHashAsString());
                                found = true;
                            }
                        }
                        if (found)
                            break;
                    }
                    if (!found)
                        sendHeaders = headers;
                    bitcoind.sendMessage(new HeadersMessage(params, sendHeaders));
                    InventoryMessage i = new InventoryMessage(params);
                    for (Block b : sendHeaders)
                        i.addBlock(b);
                    bitcoind.sendMessage(i);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            } else if (m instanceof InventoryMessage) {
                if (mostRecentInv != null) {
                    log.error("Got an inv when we weren't expecting one");
                    unexpectedInvs.incrementAndGet();
                }
                mostRecentInv = (InventoryMessage) m;
            }
            return m;
        }
    });

    bitcoindChainHead = params.getGenesisBlock().getHash();

    // bitcoind MUST be on localhost or we will get banned as a DoSer
    new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),
            args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), bitcoind, 1000);

    connectedFuture.get();

    ArrayList<Sha256Hash> locator = new ArrayList<>(1);
    locator.add(params.getGenesisBlock().getHash());
    Sha256Hash hashTo = Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000000");

    int rulesSinceFirstFail = 0;
    for (Rule rule : blockList.list) {
        if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
            FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
            boolean threw = false;
            Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
            // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
            for (int i = 0; i < 1 || nextBlock == null || !nextBlock.getHash().equals(block.blockHash); i++) {
                try {
                    Block b = blocks.next();
                    Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
                    if (oldBlockWithSameHash != null
                            && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
                        blocksRequested.remove(b.getHash());
                    nextBlock = preloadedBlocks.get(block.blockHash);
                } catch (NoSuchElementException e) {
                    if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
                        throw e;
                }
            }
            currentBlock.block = nextBlock;
            log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
            try {
                if (chain.add(nextBlock) != block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    rulesSinceFirstFail++;
                }
            } catch (VerificationException e) {
                threw = true;
                if (!block.throwsException) {
                    log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                } else if (block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                }
            }
            if (!threw && block.throwsException) {
                log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                rulesSinceFirstFail++;
            } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
                log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName
                        + "\"");
                rulesSinceFirstFail++;
            } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
                log.error(
                        "ERROR: New block head didn't match the correct height after block " + block.ruleName);
                rulesSinceFirstFail++;
            }

            // Shouldnt double-request
            boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
            if (shouldntRequest)
                blocksRequested.remove(nextBlock.getHash());
            InventoryMessage message = new InventoryMessage(params);
            message.addBlock(nextBlock);
            bitcoind.sendMessage(message);
            log.info("Sent inv with block " + nextBlock.getHashAsString());
            if (blocksPendingSend.contains(nextBlock.getHash())) {
                bitcoind.sendMessage(nextBlock);
                log.info("Sent full block " + nextBlock.getHashAsString());
            }
            // bitcoind doesn't request blocks inline so we can't rely on a ping for synchronization
            for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
                int SLEEP_TIME = 1;
                if (i % 1000 / SLEEP_TIME == 1000 / SLEEP_TIME - 1)
                    log.error("bitcoind still hasn't requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                Thread.sleep(SLEEP_TIME);
                if (i > 60000 / SLEEP_TIME) {
                    log.error("bitcoind failed to request block " + block.ruleName);
                    System.exit(1);
                }
            }
            if (shouldntRequest) {
                Thread.sleep(100);
                if (blocksRequested.contains(nextBlock.getHash())) {
                    log.error("ERROR: bitcoind re-requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                    rulesSinceFirstFail++;
                }
            }
            // If the block throws, we may want to get bitcoind to request the same block again
            if (block.throwsException)
                blocksRequested.remove(nextBlock.getHash());
            //bitcoind.sendMessage(nextBlock);
            locator.clear();
            locator.add(bitcoindChainHead);
            bitcoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
            bitcoind.ping().get();
            if (!chain.getChainHead().getHeader().getHash().equals(bitcoindChainHead)) {
                rulesSinceFirstFail++;
                log.error(
                        "ERROR: bitcoind and bitcoinj acceptance differs on block \"" + block.ruleName + "\"");
            }
            if (block.sendOnce)
                preloadedBlocks.remove(nextBlock.getHash());
            log.info("Block \"" + block.ruleName + "\" completed processing");
        } else if (rule instanceof MemoryPoolState) {
            MemoryPoolMessage message = new MemoryPoolMessage();
            bitcoind.sendMessage(message);
            bitcoind.ping().get();
            if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had an empty mempool, but we expected some transactions on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had a non-empty mempool, but we expected an empty one on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null) {
                Set<InventoryItem> originalRuleSet = new HashSet<>(((MemoryPoolState) rule).mempool);
                boolean matches = mostRecentInv.items.size() == ((MemoryPoolState) rule).mempool.size();
                for (InventoryItem item : mostRecentInv.items)
                    if (!((MemoryPoolState) rule).mempool.remove(item))
                        matches = false;
                if (matches)
                    continue;
                log.error("bitcoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
                log.info("  bitcoind's mempool was: ");
                for (InventoryItem item : mostRecentInv.items)
                    log.info("    " + item.hash);
                log.info("  The expected mempool was: ");
                for (InventoryItem item : originalRuleSet)
                    log.info("    " + item.hash);
                rulesSinceFirstFail++;
            }
            mostRecentInv = null;
        } else if (rule instanceof UTXORule) {
            if (bitcoind.getPeerVersionMessage().isGetUTXOsSupported()) {
                UTXORule r = (UTXORule) rule;
                UTXOsMessage result = bitcoind.getUTXOs(r.query).get();
                if (!result.equals(r.result)) {
                    log.error("utxo result was not what we expected.");
                    log.error("Wanted  {}", r.result);
                    log.error("but got {}", result);
                    rulesSinceFirstFail++;
                } else {
                    log.info("Successful utxo query {}: {}", r.ruleName, result);
                }
            }
        } else {
            throw new RuntimeException("Unknown rule");
        }
        if (rulesSinceFirstFail > 0)
            rulesSinceFirstFail++;
        if (rulesSinceFirstFail > 6)
            System.exit(1);
    }

    if (unexpectedInvs.get() > 0)
        log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from bitcoind");
    log.info("Done testing.");
    System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
}

From source file:org.guldenj.core.BitcoindComparisonTool.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*w  ww .  j  ava2 s.  c  o m*/
    System.out.println("USAGE: guldenjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
    boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;

    params = RegTestParams.get();
    Context ctx = new Context(params);

    File blockFile = File.createTempFile("testBlocks", ".dat");
    blockFile.deleteOnExit();

    FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
    final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
    final Map<Sha256Hash, Block> preloadedBlocks = new HashMap<Sha256Hash, Block>();
    final Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));

    try {
        H2FullPrunedBlockStore store = new H2FullPrunedBlockStore(params,
                args.length > 0 ? args[0] : "BitcoindComparisonTool", blockList.maximumReorgBlockCount);
        store.resetStore();
        //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
        chain = new FullPrunedBlockChain(params, store);
    } catch (BlockStoreException e) {
        e.printStackTrace();
        System.exit(1);
    }

    VersionMessage ver = new VersionMessage(params, 42);
    ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
    ver.localServices = VersionMessage.NODE_NETWORK;
    final Peer bitcoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)),
            new PeerAddress(params, InetAddress.getLocalHost()));
    Preconditions.checkState(bitcoind.getVersionMessage().hasBlockChain());

    final BlockWrapper currentBlock = new BlockWrapper();

    final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final Set<Sha256Hash> blocksPendingSend = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final AtomicInteger unexpectedInvs = new AtomicInteger(0);
    final SettableFuture<Void> connectedFuture = SettableFuture.create();
    bitcoind.addConnectedEventListener(Threading.SAME_THREAD, new PeerConnectedEventListener() {
        @Override
        public void onPeerConnected(Peer peer, int peerCount) {
            if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
                System.out.println();
                System.out.println(
                        "************************************************************************************************************************\n"
                                + "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n"
                                + "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Bitcoin\n"
                                + "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n"
                                + "Instead, go work on making Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n"
                                + "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n"
                                + "************************************************************************************************************************");
                System.out.println();
            }
            log.info("bitcoind connected");
            // Make sure bitcoind has no blocks
            bitcoind.setDownloadParameters(0, false);
            bitcoind.startBlockChainDownload();
            connectedFuture.set(null);
        }
    });

    bitcoind.addDisconnectedEventListener(Threading.SAME_THREAD, new PeerDisconnectedEventListener() {
        @Override
        public void onPeerDisconnected(Peer peer, int peerCount) {
            log.error("bitcoind node disconnected!");
            System.exit(1);
        }
    });

    bitcoind.addPreMessageReceivedEventListener(Threading.SAME_THREAD, new PreMessageReceivedEventListener() {
        @Override
        public Message onPreMessageReceived(Peer peer, Message m) {
            if (m instanceof HeadersMessage) {
                if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
                    Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
                    log.info("Got header from bitcoind " + b.getHashAsString());
                    bitcoindChainHead = b.getHash();
                } else
                    log.info("Got empty header message from bitcoind");
                return null;
            } else if (m instanceof Block) {
                log.error("bitcoind sent us a block it already had, make sure bitcoind has no blocks!");
                System.exit(1);
            } else if (m instanceof GetDataMessage) {
                for (InventoryItem item : ((GetDataMessage) m).items)
                    if (item.type == InventoryItem.Type.Block) {
                        log.info("Requested " + item.hash);
                        if (currentBlock.block.getHash().equals(item.hash))
                            bitcoind.sendMessage(currentBlock.block);
                        else {
                            Block nextBlock = preloadedBlocks.get(item.hash);
                            if (nextBlock != null)
                                bitcoind.sendMessage(nextBlock);
                            else {
                                blocksPendingSend.add(item.hash);
                                log.info("...which we will not provide yet");
                            }
                        }
                        blocksRequested.add(item.hash);
                    }
                return null;
            } else if (m instanceof GetHeadersMessage) {
                try {
                    if (currentBlock.block == null) {
                        log.info("Got a request for a header before we had even begun processing blocks!");
                        return null;
                    }
                    LinkedList<Block> headers = new LinkedList<Block>();
                    Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
                    while (it != null) {
                        headers.addFirst(it);
                        it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
                    }
                    LinkedList<Block> sendHeaders = new LinkedList<Block>();
                    boolean found = false;
                    for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
                        for (Block b : headers) {
                            if (found) {
                                sendHeaders.addLast(b);
                                log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
                                if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
                                    break;
                            } else if (b.getHash().equals(hash)) {
                                log.info("Found header " + b.getHashAsString());
                                found = true;
                            }
                        }
                        if (found)
                            break;
                    }
                    if (!found)
                        sendHeaders = headers;
                    bitcoind.sendMessage(new HeadersMessage(params, sendHeaders));
                    InventoryMessage i = new InventoryMessage(params);
                    for (Block b : sendHeaders)
                        i.addBlock(b);
                    bitcoind.sendMessage(i);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            } else if (m instanceof InventoryMessage) {
                if (mostRecentInv != null) {
                    log.error("Got an inv when we weren't expecting one");
                    unexpectedInvs.incrementAndGet();
                }
                mostRecentInv = (InventoryMessage) m;
            }
            return m;
        }
    });

    bitcoindChainHead = params.getGenesisBlock().getHash();

    // bitcoind MUST be on localhost or we will get banned as a DoSer
    new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),
            args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), bitcoind, 1000);

    connectedFuture.get();

    ArrayList<Sha256Hash> locator = new ArrayList<Sha256Hash>(1);
    locator.add(params.getGenesisBlock().getHash());
    Sha256Hash hashTo = Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000000");

    int rulesSinceFirstFail = 0;
    for (Rule rule : blockList.list) {
        if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
            FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
            boolean threw = false;
            Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
            // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
            for (int i = 0; i < 1 || nextBlock == null || !nextBlock.getHash().equals(block.blockHash); i++) {
                try {
                    Block b = blocks.next();
                    Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
                    if (oldBlockWithSameHash != null
                            && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
                        blocksRequested.remove(b.getHash());
                    nextBlock = preloadedBlocks.get(block.blockHash);
                } catch (NoSuchElementException e) {
                    if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
                        throw e;
                }
            }
            currentBlock.block = nextBlock;
            log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
            try {
                if (chain.add(nextBlock) != block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    rulesSinceFirstFail++;
                }
            } catch (VerificationException e) {
                threw = true;
                if (!block.throwsException) {
                    log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                } else if (block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                }
            }
            if (!threw && block.throwsException) {
                log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                rulesSinceFirstFail++;
            } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
                log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName
                        + "\"");
                rulesSinceFirstFail++;
            } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
                log.error(
                        "ERROR: New block head didn't match the correct height after block " + block.ruleName);
                rulesSinceFirstFail++;
            }

            // Shouldnt double-request
            boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
            if (shouldntRequest)
                blocksRequested.remove(nextBlock.getHash());
            InventoryMessage message = new InventoryMessage(params);
            message.addBlock(nextBlock);
            bitcoind.sendMessage(message);
            log.info("Sent inv with block " + nextBlock.getHashAsString());
            if (blocksPendingSend.contains(nextBlock.getHash())) {
                bitcoind.sendMessage(nextBlock);
                log.info("Sent full block " + nextBlock.getHashAsString());
            }
            // bitcoind doesn't request blocks inline so we can't rely on a ping for synchronization
            for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
                int SLEEP_TIME = 1;
                if (i % 1000 / SLEEP_TIME == 1000 / SLEEP_TIME - 1)
                    log.error("bitcoind still hasn't requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                Thread.sleep(SLEEP_TIME);
                if (i > 60000 / SLEEP_TIME) {
                    log.error("bitcoind failed to request block " + block.ruleName);
                    System.exit(1);
                }
            }
            if (shouldntRequest) {
                Thread.sleep(100);
                if (blocksRequested.contains(nextBlock.getHash())) {
                    log.error("ERROR: bitcoind re-requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                    rulesSinceFirstFail++;
                }
            }
            // If the block throws, we may want to get bitcoind to request the same block again
            if (block.throwsException)
                blocksRequested.remove(nextBlock.getHash());
            //bitcoind.sendMessage(nextBlock);
            locator.clear();
            locator.add(bitcoindChainHead);
            bitcoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
            bitcoind.ping().get();
            if (!chain.getChainHead().getHeader().getHash().equals(bitcoindChainHead)) {
                rulesSinceFirstFail++;
                log.error("ERROR: bitcoind and guldenj acceptance differs on block \"" + block.ruleName + "\"");
            }
            if (block.sendOnce)
                preloadedBlocks.remove(nextBlock.getHash());
            log.info("Block \"" + block.ruleName + "\" completed processing");
        } else if (rule instanceof MemoryPoolState) {
            MemoryPoolMessage message = new MemoryPoolMessage();
            bitcoind.sendMessage(message);
            bitcoind.ping().get();
            if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had an empty mempool, but we expected some transactions on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had a non-empty mempool, but we expected an empty one on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null) {
                Set<InventoryItem> originalRuleSet = new HashSet<InventoryItem>(
                        ((MemoryPoolState) rule).mempool);
                boolean matches = mostRecentInv.items.size() == ((MemoryPoolState) rule).mempool.size();
                for (InventoryItem item : mostRecentInv.items)
                    if (!((MemoryPoolState) rule).mempool.remove(item))
                        matches = false;
                if (matches)
                    continue;
                log.error("bitcoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
                log.info("  bitcoind's mempool was: ");
                for (InventoryItem item : mostRecentInv.items)
                    log.info("    " + item.hash);
                log.info("  The expected mempool was: ");
                for (InventoryItem item : originalRuleSet)
                    log.info("    " + item.hash);
                rulesSinceFirstFail++;
            }
            mostRecentInv = null;
        } else if (rule instanceof UTXORule) {
            if (bitcoind.getPeerVersionMessage().isGetUTXOsSupported()) {
                UTXORule r = (UTXORule) rule;
                UTXOsMessage result = bitcoind.getUTXOs(r.query).get();
                if (!result.equals(r.result)) {
                    log.error("utxo result was not what we expected.");
                    log.error("Wanted  {}", r.result);
                    log.error("but got {}", result);
                    rulesSinceFirstFail++;
                } else {
                    log.info("Successful utxo query {}: {}", r.ruleName, result);
                }
            }
        } else {
            throw new RuntimeException("Unknown rule");
        }
        if (rulesSinceFirstFail > 0)
            rulesSinceFirstFail++;
        if (rulesSinceFirstFail > 6)
            System.exit(1);
    }

    if (unexpectedInvs.get() > 0)
        log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from bitcoind");
    log.info("Done testing.");
    System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
}

From source file:org.litecoinj.core.BitcoindComparisonTool.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*  w w w .j  a  v  a  2s.  c  o  m*/
    System.out.println("USAGE: bitcoinjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
    boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;

    params = RegTestParams.get();
    Context ctx = new Context(params);

    File blockFile = File.createTempFile("testBlocks", ".dat");
    blockFile.deleteOnExit();

    FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
    final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
    final Map<Sha256Hash, Block> preloadedBlocks = new HashMap<>();
    final Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));

    try {
        H2FullPrunedBlockStore store = new H2FullPrunedBlockStore(params,
                args.length > 0 ? args[0] : "BitcoindComparisonTool", blockList.maximumReorgBlockCount);
        store.resetStore();
        //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
        chain = new FullPrunedBlockChain(params, store);
    } catch (BlockStoreException e) {
        e.printStackTrace();
        System.exit(1);
    }

    VersionMessage ver = new VersionMessage(params, 42);
    ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
    ver.localServices = VersionMessage.NODE_NETWORK;
    final Peer bitcoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)),
            new PeerAddress(params, InetAddress.getLocalHost()));
    Preconditions.checkState(bitcoind.getVersionMessage().hasBlockChain());

    final BlockWrapper currentBlock = new BlockWrapper();

    final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final Set<Sha256Hash> blocksPendingSend = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final AtomicInteger unexpectedInvs = new AtomicInteger(0);
    final SettableFuture<Void> connectedFuture = SettableFuture.create();
    bitcoind.addConnectedEventListener(Threading.SAME_THREAD, new PeerConnectedEventListener() {
        @Override
        public void onPeerConnected(Peer peer, int peerCount) {
            if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
                System.out.println();
                System.out.println(
                        "************************************************************************************************************************\n"
                                + "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n"
                                + "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Bitcoin\n"
                                + "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n"
                                + "Instead, go work on making Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n"
                                + "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n"
                                + "************************************************************************************************************************");
                System.out.println();
            }
            log.info("bitcoind connected");
            // Make sure bitcoind has no blocks
            bitcoind.setDownloadParameters(0, false);
            bitcoind.startBlockChainDownload();
            connectedFuture.set(null);
        }
    });

    bitcoind.addDisconnectedEventListener(Threading.SAME_THREAD, new PeerDisconnectedEventListener() {
        @Override
        public void onPeerDisconnected(Peer peer, int peerCount) {
            log.error("bitcoind node disconnected!");
            System.exit(1);
        }
    });

    bitcoind.addPreMessageReceivedEventListener(Threading.SAME_THREAD, new PreMessageReceivedEventListener() {
        @Override
        public Message onPreMessageReceived(Peer peer, Message m) {
            if (m instanceof HeadersMessage) {
                if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
                    Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
                    log.info("Got header from bitcoind " + b.getHashAsString());
                    bitcoindChainHead = b.getHash();
                } else
                    log.info("Got empty header message from bitcoind");
                return null;
            } else if (m instanceof Block) {
                log.error("bitcoind sent us a block it already had, make sure bitcoind has no blocks!");
                System.exit(1);
            } else if (m instanceof GetDataMessage) {
                for (InventoryItem item : ((GetDataMessage) m).items)
                    if (item.type == InventoryItem.Type.Block) {
                        log.info("Requested " + item.hash);
                        if (currentBlock.block.getHash().equals(item.hash))
                            bitcoind.sendMessage(currentBlock.block);
                        else {
                            Block nextBlock = preloadedBlocks.get(item.hash);
                            if (nextBlock != null)
                                bitcoind.sendMessage(nextBlock);
                            else {
                                blocksPendingSend.add(item.hash);
                                log.info("...which we will not provide yet");
                            }
                        }
                        blocksRequested.add(item.hash);
                    }
                return null;
            } else if (m instanceof GetHeadersMessage) {
                try {
                    if (currentBlock.block == null) {
                        log.info("Got a request for a header before we had even begun processing blocks!");
                        return null;
                    }
                    LinkedList<Block> headers = new LinkedList<>();
                    Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
                    while (it != null) {
                        headers.addFirst(it);
                        it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
                    }
                    LinkedList<Block> sendHeaders = new LinkedList<>();
                    boolean found = false;
                    for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
                        for (Block b : headers) {
                            if (found) {
                                sendHeaders.addLast(b);
                                log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
                                if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
                                    break;
                            } else if (b.getHash().equals(hash)) {
                                log.info("Found header " + b.getHashAsString());
                                found = true;
                            }
                        }
                        if (found)
                            break;
                    }
                    if (!found)
                        sendHeaders = headers;
                    bitcoind.sendMessage(new HeadersMessage(params, sendHeaders));
                    InventoryMessage i = new InventoryMessage(params);
                    for (Block b : sendHeaders)
                        i.addBlock(b);
                    bitcoind.sendMessage(i);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            } else if (m instanceof InventoryMessage) {
                if (mostRecentInv != null) {
                    log.error("Got an inv when we weren't expecting one");
                    unexpectedInvs.incrementAndGet();
                }
                mostRecentInv = (InventoryMessage) m;
            }
            return m;
        }
    });

    bitcoindChainHead = params.getGenesisBlock().getHash();

    // bitcoind MUST be on localhost or we will get banned as a DoSer
    new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),
            args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), bitcoind, 1000);

    connectedFuture.get();

    ArrayList<Sha256Hash> locator = new ArrayList<>(1);
    locator.add(params.getGenesisBlock().getHash());
    Sha256Hash hashTo = Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000000");

    int rulesSinceFirstFail = 0;
    for (Rule rule : blockList.list) {
        if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
            FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
            boolean threw = false;
            Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
            // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
            for (int i = 0; i < 1 || nextBlock == null || !nextBlock.getHash().equals(block.blockHash); i++) {
                try {
                    Block b = blocks.next();
                    Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
                    if (oldBlockWithSameHash != null
                            && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
                        blocksRequested.remove(b.getHash());
                    nextBlock = preloadedBlocks.get(block.blockHash);
                } catch (NoSuchElementException e) {
                    if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
                        throw e;
                }
            }
            currentBlock.block = nextBlock;
            log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
            try {
                if (chain.add(nextBlock) != block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    rulesSinceFirstFail++;
                }
            } catch (VerificationException e) {
                threw = true;
                if (!block.throwsException) {
                    log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                } else if (block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                }
            }
            if (!threw && block.throwsException) {
                log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                rulesSinceFirstFail++;
            } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
                log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName
                        + "\"");
                rulesSinceFirstFail++;
            } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
                log.error(
                        "ERROR: New block head didn't match the correct height after block " + block.ruleName);
                rulesSinceFirstFail++;
            }

            // Shouldnt double-request
            boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
            if (shouldntRequest)
                blocksRequested.remove(nextBlock.getHash());
            InventoryMessage message = new InventoryMessage(params);
            message.addBlock(nextBlock);
            bitcoind.sendMessage(message);
            log.info("Sent inv with block " + nextBlock.getHashAsString());
            if (blocksPendingSend.contains(nextBlock.getHash())) {
                bitcoind.sendMessage(nextBlock);
                log.info("Sent full block " + nextBlock.getHashAsString());
            }
            // bitcoind doesn't request blocks inline so we can't rely on a ping for synchronization
            for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
                int SLEEP_TIME = 1;
                if (i % 1000 / SLEEP_TIME == 1000 / SLEEP_TIME - 1)
                    log.error("bitcoind still hasn't requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                Thread.sleep(SLEEP_TIME);
                if (i > 60000 / SLEEP_TIME) {
                    log.error("bitcoind failed to request block " + block.ruleName);
                    System.exit(1);
                }
            }
            if (shouldntRequest) {
                Thread.sleep(100);
                if (blocksRequested.contains(nextBlock.getHash())) {
                    log.error("ERROR: bitcoind re-requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                    rulesSinceFirstFail++;
                }
            }
            // If the block throws, we may want to get bitcoind to request the same block again
            if (block.throwsException)
                blocksRequested.remove(nextBlock.getHash());
            //bitcoind.sendMessage(nextBlock);
            locator.clear();
            locator.add(bitcoindChainHead);
            bitcoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
            bitcoind.ping().get();
            if (!chain.getChainHead().getHeader().getHash().equals(bitcoindChainHead)) {
                rulesSinceFirstFail++;
                log.error(
                        "ERROR: bitcoind and litecoinj acceptance differs on block \"" + block.ruleName + "\"");
            }
            if (block.sendOnce)
                preloadedBlocks.remove(nextBlock.getHash());
            log.info("Block \"" + block.ruleName + "\" completed processing");
        } else if (rule instanceof MemoryPoolState) {
            MemoryPoolMessage message = new MemoryPoolMessage();
            bitcoind.sendMessage(message);
            bitcoind.ping().get();
            if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had an empty mempool, but we expected some transactions on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had a non-empty mempool, but we expected an empty one on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null) {
                Set<InventoryItem> originalRuleSet = new HashSet<>(((MemoryPoolState) rule).mempool);
                boolean matches = mostRecentInv.items.size() == ((MemoryPoolState) rule).mempool.size();
                for (InventoryItem item : mostRecentInv.items)
                    if (!((MemoryPoolState) rule).mempool.remove(item))
                        matches = false;
                if (matches)
                    continue;
                log.error("bitcoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
                log.info("  bitcoind's mempool was: ");
                for (InventoryItem item : mostRecentInv.items)
                    log.info("    " + item.hash);
                log.info("  The expected mempool was: ");
                for (InventoryItem item : originalRuleSet)
                    log.info("    " + item.hash);
                rulesSinceFirstFail++;
            }
            mostRecentInv = null;
        } else if (rule instanceof UTXORule) {
            if (bitcoind.getPeerVersionMessage().isGetUTXOsSupported()) {
                UTXORule r = (UTXORule) rule;
                UTXOsMessage result = bitcoind.getUTXOs(r.query).get();
                if (!result.equals(r.result)) {
                    log.error("utxo result was not what we expected.");
                    log.error("Wanted  {}", r.result);
                    log.error("but got {}", result);
                    rulesSinceFirstFail++;
                } else {
                    log.info("Successful utxo query {}: {}", r.ruleName, result);
                }
            }
        } else {
            throw new RuntimeException("Unknown rule");
        }
        if (rulesSinceFirstFail > 0)
            rulesSinceFirstFail++;
        if (rulesSinceFirstFail > 6)
            System.exit(1);
    }

    if (unexpectedInvs.get() > 0)
        log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from bitcoind");
    log.info("Done testing.");
    System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
}

From source file:org.bitcoinj_extra.core.BitcoindComparisonTool.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();//from  w  w w. j a  v  a  2 s . c  o m
    System.out.println("USAGE: bitcoinjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
    boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;

    params = RegTestParams.get();
    Context ctx = new Context(params);

    File blockFile = File.createTempFile("testBlocks", ".dat");
    blockFile.deleteOnExit();

    FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
    final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
    final Map<Sha256Hash, Block> preloadedBlocks = new HashMap<Sha256Hash, Block>();
    final Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));

    try {
        H2FullPrunedBlockStore store = new H2FullPrunedBlockStore(params,
                args.length > 0 ? args[0] : "BitcoindComparisonTool", blockList.maximumReorgBlockCount);
        store.resetStore();
        //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
        chain = new FullPrunedBlockChain(params, store);
    } catch (BlockStoreException e) {
        e.printStackTrace();
        System.exit(1);
    }

    VersionMessage ver = new VersionMessage(params, 42);
    ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
    ver.localServices = VersionMessage.NODE_NETWORK;
    final Peer bitcoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)),
            new PeerAddress(params, InetAddress.getLocalHost()));
    Preconditions.checkState(bitcoind.getVersionMessage().hasBlockChain());

    final BlockWrapper currentBlock = new BlockWrapper();

    final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final Set<Sha256Hash> blocksPendingSend = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final AtomicInteger unexpectedInvs = new AtomicInteger(0);
    final SettableFuture<Void> connectedFuture = SettableFuture.create();
    bitcoind.addConnectedEventListener(Threading.SAME_THREAD, new PeerConnectedEventListener() {
        @Override
        public void onPeerConnected(Peer peer, int peerCount) {
            if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
                System.out.println();
                System.out.println(
                        "************************************************************************************************************************\n"
                                + "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n"
                                + "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Bitcoin\n"
                                + "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n"
                                + "Instead, go work on making Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n"
                                + "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n"
                                + "************************************************************************************************************************");
                System.out.println();
            }
            log.info("bitcoind connected");
            // Make sure bitcoind has no blocks
            bitcoind.setDownloadParameters(0, false);
            bitcoind.startBlockChainDownload();
            connectedFuture.set(null);
        }
    });

    bitcoind.addDisconnectedEventListener(Threading.SAME_THREAD, new PeerDisconnectedEventListener() {
        @Override
        public void onPeerDisconnected(Peer peer, int peerCount) {
            log.error("bitcoind node disconnected!");
            System.exit(1);
        }
    });

    bitcoind.addPreMessageReceivedEventListener(Threading.SAME_THREAD, new PreMessageReceivedEventListener() {
        @Override
        public Message onPreMessageReceived(Peer peer, Message m) {
            if (m instanceof HeadersMessage) {
                if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
                    Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
                    log.info("Got header from bitcoind " + b.getHashAsString());
                    bitcoindChainHead = b.getHash();
                } else
                    log.info("Got empty header message from bitcoind");
                return null;
            } else if (m instanceof Block) {
                log.error("bitcoind sent us a block it already had, make sure bitcoind has no blocks!");
                System.exit(1);
            } else if (m instanceof GetDataMessage) {
                for (InventoryItem item : ((GetDataMessage) m).items)
                    if (item.type == InventoryItem.Type.Block) {
                        log.info("Requested " + item.hash);
                        if (currentBlock.block.getHash().equals(item.hash))
                            bitcoind.sendMessage(currentBlock.block);
                        else {
                            Block nextBlock = preloadedBlocks.get(item.hash);
                            if (nextBlock != null)
                                bitcoind.sendMessage(nextBlock);
                            else {
                                blocksPendingSend.add(item.hash);
                                log.info("...which we will not provide yet");
                            }
                        }
                        blocksRequested.add(item.hash);
                    }
                return null;
            } else if (m instanceof GetHeadersMessage) {
                try {
                    if (currentBlock.block == null) {
                        log.info("Got a request for a header before we had even begun processing blocks!");
                        return null;
                    }
                    LinkedList<Block> headers = new LinkedList<Block>();
                    Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
                    while (it != null) {
                        headers.addFirst(it);
                        it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
                    }
                    LinkedList<Block> sendHeaders = new LinkedList<Block>();
                    boolean found = false;
                    for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
                        for (Block b : headers) {
                            if (found) {
                                sendHeaders.addLast(b);
                                log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
                                if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
                                    break;
                            } else if (b.getHash().equals(hash)) {
                                log.info("Found header " + b.getHashAsString());
                                found = true;
                            }
                        }
                        if (found)
                            break;
                    }
                    if (!found)
                        sendHeaders = headers;
                    bitcoind.sendMessage(new HeadersMessage(params, sendHeaders));
                    InventoryMessage i = new InventoryMessage(params);
                    for (Block b : sendHeaders)
                        i.addBlock(b);
                    bitcoind.sendMessage(i);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            } else if (m instanceof InventoryMessage) {
                if (mostRecentInv != null) {
                    log.error("Got an inv when we weren't expecting one");
                    unexpectedInvs.incrementAndGet();
                }
                mostRecentInv = (InventoryMessage) m;
            }
            return m;
        }
    });

    bitcoindChainHead = params.getGenesisBlock().getHash();

    // bitcoind MUST be on localhost or we will get banned as a DoSer
    new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),
            args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), bitcoind, 1000);

    connectedFuture.get();

    ArrayList<Sha256Hash> locator = new ArrayList<Sha256Hash>(1);
    locator.add(params.getGenesisBlock().getHash());
    Sha256Hash hashTo = Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000000");

    int rulesSinceFirstFail = 0;
    for (Rule rule : blockList.list) {
        if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
            FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
            boolean threw = false;
            Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
            // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
            for (int i = 0; i < 1 || nextBlock == null || !nextBlock.getHash().equals(block.blockHash); i++) {
                try {
                    Block b = blocks.next();
                    Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
                    if (oldBlockWithSameHash != null
                            && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
                        blocksRequested.remove(b.getHash());
                    nextBlock = preloadedBlocks.get(block.blockHash);
                } catch (NoSuchElementException e) {
                    if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
                        throw e;
                }
            }
            currentBlock.block = nextBlock;
            log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
            try {
                if (chain.add(nextBlock) != block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    rulesSinceFirstFail++;
                }
            } catch (VerificationException e) {
                threw = true;
                if (!block.throwsException) {
                    log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                } else if (block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                }
            }
            if (!threw && block.throwsException) {
                log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                rulesSinceFirstFail++;
            } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
                log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName
                        + "\"");
                rulesSinceFirstFail++;
            } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
                log.error(
                        "ERROR: New block head didn't match the correct height after block " + block.ruleName);
                rulesSinceFirstFail++;
            }

            // Shouldnt double-request
            boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
            if (shouldntRequest)
                blocksRequested.remove(nextBlock.getHash());
            InventoryMessage message = new InventoryMessage(params);
            message.addBlock(nextBlock);
            bitcoind.sendMessage(message);
            log.info("Sent inv with block " + nextBlock.getHashAsString());
            if (blocksPendingSend.contains(nextBlock.getHash())) {
                bitcoind.sendMessage(nextBlock);
                log.info("Sent full block " + nextBlock.getHashAsString());
            }
            // bitcoind doesn't request blocks inline so we can't rely on a ping for synchronization
            for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
                int SLEEP_TIME = 1;
                if (i % 1000 / SLEEP_TIME == 1000 / SLEEP_TIME - 1)
                    log.error("bitcoind still hasn't requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                Thread.sleep(SLEEP_TIME);
                if (i > 60000 / SLEEP_TIME) {
                    log.error("bitcoind failed to request block " + block.ruleName);
                    System.exit(1);
                }
            }
            if (shouldntRequest) {
                Thread.sleep(100);
                if (blocksRequested.contains(nextBlock.getHash())) {
                    log.error("ERROR: bitcoind re-requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                    rulesSinceFirstFail++;
                }
            }
            // If the block throws, we may want to get bitcoind to request the same block again
            if (block.throwsException)
                blocksRequested.remove(nextBlock.getHash());
            //bitcoind.sendMessage(nextBlock);
            locator.clear();
            locator.add(bitcoindChainHead);
            bitcoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
            bitcoind.ping().get();
            if (!chain.getChainHead().getHeader().getHash().equals(bitcoindChainHead)) {
                rulesSinceFirstFail++;
                log.error("ERROR: bitcoind and bitcoinj_extra acceptance differs on block \"" + block.ruleName
                        + "\"");
            }
            if (block.sendOnce)
                preloadedBlocks.remove(nextBlock.getHash());
            log.info("Block \"" + block.ruleName + "\" completed processing");
        } else if (rule instanceof MemoryPoolState) {
            MemoryPoolMessage message = new MemoryPoolMessage();
            bitcoind.sendMessage(message);
            bitcoind.ping().get();
            if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had an empty mempool, but we expected some transactions on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: bitcoind had a non-empty mempool, but we expected an empty one on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null) {
                Set<InventoryItem> originalRuleSet = new HashSet<InventoryItem>(
                        ((MemoryPoolState) rule).mempool);
                boolean matches = mostRecentInv.items.size() == ((MemoryPoolState) rule).mempool.size();
                for (InventoryItem item : mostRecentInv.items)
                    if (!((MemoryPoolState) rule).mempool.remove(item))
                        matches = false;
                if (matches)
                    continue;
                log.error("bitcoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
                log.info("  bitcoind's mempool was: ");
                for (InventoryItem item : mostRecentInv.items)
                    log.info("    " + item.hash);
                log.info("  The expected mempool was: ");
                for (InventoryItem item : originalRuleSet)
                    log.info("    " + item.hash);
                rulesSinceFirstFail++;
            }
            mostRecentInv = null;
        } else if (rule instanceof UTXORule) {
            if (bitcoind.getPeerVersionMessage().isGetUTXOsSupported()) {
                UTXORule r = (UTXORule) rule;
                UTXOsMessage result = bitcoind.getUTXOs(r.query).get();
                if (!result.equals(r.result)) {
                    log.error("utxo result was not what we expected.");
                    log.error("Wanted  {}", r.result);
                    log.error("but got {}", result);
                    rulesSinceFirstFail++;
                } else {
                    log.info("Successful utxo query {}: {}", r.ruleName, result);
                }
            }
        } else {
            throw new RuntimeException("Unknown rule");
        }
        if (rulesSinceFirstFail > 0)
            rulesSinceFirstFail++;
        if (rulesSinceFirstFail > 6)
            System.exit(1);
    }

    if (unexpectedInvs.get() > 0)
        log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from bitcoind");
    log.info("Done testing.");
    System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
}

From source file:org.neoscoinj.core.NeoscoindComparisonTool.java

public static void main(String[] args) throws Exception {
    BriefLogFormatter.init();/*from   ww  w.  j a v a  2  s .c om*/
    System.out.println("USAGE: neoscoinjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
    boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;

    params = RegTestParams.get();

    File blockFile = File.createTempFile("testBlocks", ".dat");
    blockFile.deleteOnExit();

    FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
    final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
    final Map<Sha256Hash, Block> preloadedBlocks = new HashMap<Sha256Hash, Block>();
    final Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));

    try {
        store = new H2FullPrunedBlockStore(params, args.length > 0 ? args[0] : "NeoscoindComparisonTool",
                blockList.maximumReorgBlockCount);
        ((H2FullPrunedBlockStore) store).resetStore();
        //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
        chain = new FullPrunedBlockChain(params, store);
    } catch (BlockStoreException e) {
        e.printStackTrace();
        System.exit(1);
    }

    VersionMessage ver = new VersionMessage(params, 42);
    ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
    ver.localServices = VersionMessage.NODE_NETWORK;
    final Peer neoscoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)),
            new PeerAddress(InetAddress.getLocalHost()));
    Preconditions.checkState(neoscoind.getVersionMessage().hasBlockChain());

    final BlockWrapper currentBlock = new BlockWrapper();

    final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final Set<Sha256Hash> blocksPendingSend = Collections.synchronizedSet(new HashSet<Sha256Hash>());
    final AtomicInteger unexpectedInvs = new AtomicInteger(0);
    final SettableFuture<Void> connectedFuture = SettableFuture.create();
    neoscoind.addEventListener(new AbstractPeerEventListener() {
        @Override
        public void onPeerConnected(Peer peer, int peerCount) {
            if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
                System.out.println();
                System.out.println(
                        "************************************************************************************************************************\n"
                                + "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n"
                                + "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Neoscoin\n"
                                + "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n"
                                + "Instead, go work on making Neoscoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n"
                                + "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n"
                                + "************************************************************************************************************************");
                System.out.println();
                System.out.println("Giving you 30 seconds to think about the above warning...");
                Uninterruptibles.sleepUninterruptibly(30, TimeUnit.SECONDS);
            }
            log.info("neoscoind connected");
            // Make sure neoscoind has no blocks
            neoscoind.setDownloadParameters(0, false);
            neoscoind.startBlockChainDownload();
            connectedFuture.set(null);
        }

        @Override
        public void onPeerDisconnected(Peer peer, int peerCount) {
            log.error("neoscoind node disconnected!");
            System.exit(1);
        }

        @Override
        public Message onPreMessageReceived(Peer peer, Message m) {
            if (m instanceof HeadersMessage) {
                if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
                    Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
                    log.info("Got header from neoscoind " + b.getHashAsString());
                    neoscoindChainHead = b.getHash();
                } else
                    log.info("Got empty header message from neoscoind");
                return null;
            } else if (m instanceof Block) {
                log.error("neoscoind sent us a block it already had, make sure neoscoind has no blocks!");
                System.exit(1);
            } else if (m instanceof GetDataMessage) {
                for (InventoryItem item : ((GetDataMessage) m).items)
                    if (item.type == InventoryItem.Type.Block) {
                        log.info("Requested " + item.hash);
                        if (currentBlock.block.getHash().equals(item.hash))
                            neoscoind.sendMessage(currentBlock.block);
                        else {
                            Block nextBlock = preloadedBlocks.get(item.hash);
                            if (nextBlock != null)
                                neoscoind.sendMessage(nextBlock);
                            else {
                                blocksPendingSend.add(item.hash);
                                log.info("...which we will not provide yet");
                            }
                        }
                        blocksRequested.add(item.hash);
                    }
                return null;
            } else if (m instanceof GetHeadersMessage) {
                try {
                    if (currentBlock.block == null) {
                        log.info("Got a request for a header before we had even begun processing blocks!");
                        return null;
                    }
                    LinkedList<Block> headers = new LinkedList<Block>();
                    Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
                    while (it != null) {
                        headers.addFirst(it);
                        it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
                    }
                    LinkedList<Block> sendHeaders = new LinkedList<Block>();
                    boolean found = false;
                    for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
                        for (Block b : headers) {
                            if (found) {
                                sendHeaders.addLast(b);
                                log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
                                if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
                                    break;
                            } else if (b.getHash().equals(hash)) {
                                log.info("Found header " + b.getHashAsString());
                                found = true;
                            }
                        }
                        if (found)
                            break;
                    }
                    if (!found)
                        sendHeaders = headers;
                    neoscoind.sendMessage(new HeadersMessage(params, sendHeaders));
                    InventoryMessage i = new InventoryMessage(params);
                    for (Block b : sendHeaders)
                        i.addBlock(b);
                    neoscoind.sendMessage(i);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            } else if (m instanceof InventoryMessage) {
                if (mostRecentInv != null) {
                    log.error("Got an inv when we weren't expecting one");
                    unexpectedInvs.incrementAndGet();
                }
                mostRecentInv = (InventoryMessage) m;
            }
            return m;
        }
    }, Threading.SAME_THREAD);

    neoscoindChainHead = params.getGenesisBlock().getHash();

    // neoscoind MUST be on localhost or we will get banned as a DoSer
    new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),
            args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), neoscoind, 1000);

    connectedFuture.get();

    ArrayList<Sha256Hash> locator = new ArrayList<Sha256Hash>(1);
    locator.add(params.getGenesisBlock().getHash());
    Sha256Hash hashTo = new Sha256Hash("0000000000000000000000000000000000000000000000000000000000000000");

    int rulesSinceFirstFail = 0;
    for (Rule rule : blockList.list) {
        if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
            FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
            boolean threw = false;
            Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
            // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
            for (int i = 0; i < 1 || nextBlock == null || !nextBlock.getHash().equals(block.blockHash); i++) {
                try {
                    Block b = blocks.next();
                    Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
                    if (oldBlockWithSameHash != null
                            && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
                        blocksRequested.remove(b.getHash());
                    nextBlock = preloadedBlocks.get(block.blockHash);
                } catch (NoSuchElementException e) {
                    if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
                        throw e;
                }
            }
            currentBlock.block = nextBlock;
            log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
            try {
                if (chain.add(nextBlock) != block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    rulesSinceFirstFail++;
                }
            } catch (VerificationException e) {
                threw = true;
                if (!block.throwsException) {
                    log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                } else if (block.connects) {
                    log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
                    e.printStackTrace();
                    rulesSinceFirstFail++;
                }
            }
            if (!threw && block.throwsException) {
                log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
                rulesSinceFirstFail++;
            } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
                log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName
                        + "\"");
                rulesSinceFirstFail++;
            } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
                log.error(
                        "ERROR: New block head didn't match the correct height after block " + block.ruleName);
                rulesSinceFirstFail++;
            }

            // Shouldnt double-request
            boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
            if (shouldntRequest)
                blocksRequested.remove(nextBlock.getHash());
            InventoryMessage message = new InventoryMessage(params);
            message.addBlock(nextBlock);
            neoscoind.sendMessage(message);
            log.info("Sent inv with block " + nextBlock.getHashAsString());
            if (blocksPendingSend.contains(nextBlock.getHash())) {
                neoscoind.sendMessage(nextBlock);
                log.info("Sent full block " + nextBlock.getHashAsString());
            }
            // neoscoind doesn't request blocks inline so we can't rely on a ping for synchronization
            for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
                int SLEEP_TIME = 1;
                if (i % 1000 / SLEEP_TIME == 1000 / SLEEP_TIME - 1)
                    log.error("neoscoind still hasn't requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                Thread.sleep(SLEEP_TIME);
                if (i > 60000 / SLEEP_TIME) {
                    log.error("neoscoind failed to request block " + block.ruleName);
                    System.exit(1);
                }
            }
            if (shouldntRequest) {
                Thread.sleep(100);
                if (blocksRequested.contains(nextBlock.getHash())) {
                    log.error("ERROR: neoscoind re-requested block " + block.ruleName + " with hash "
                            + nextBlock.getHash());
                    rulesSinceFirstFail++;
                }
            }
            // If the block throws, we may want to get neoscoind to request the same block again
            if (block.throwsException)
                blocksRequested.remove(nextBlock.getHash());
            //neoscoind.sendMessage(nextBlock);
            locator.clear();
            locator.add(neoscoindChainHead);
            neoscoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
            neoscoind.ping().get();
            if (!chain.getChainHead().getHeader().getHash().equals(neoscoindChainHead)) {
                rulesSinceFirstFail++;
                log.error("ERROR: neoscoind and neoscoinj acceptance differs on block \"" + block.ruleName
                        + "\"");
            }
            if (block.sendOnce)
                preloadedBlocks.remove(nextBlock.getHash());
            log.info("Block \"" + block.ruleName + "\" completed processing");
        } else if (rule instanceof MemoryPoolState) {
            MemoryPoolMessage message = new MemoryPoolMessage();
            neoscoind.sendMessage(message);
            neoscoind.ping().get();
            if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: neoscoind had an empty mempool, but we expected some transactions on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
                log.error("ERROR: neoscoind had a non-empty mempool, but we expected an empty one on rule "
                        + rule.ruleName);
                rulesSinceFirstFail++;
            } else if (mostRecentInv != null) {
                Set<InventoryItem> originalRuleSet = new HashSet<InventoryItem>(
                        ((MemoryPoolState) rule).mempool);
                boolean matches = mostRecentInv.items.size() == ((MemoryPoolState) rule).mempool.size();
                for (InventoryItem item : mostRecentInv.items)
                    if (!((MemoryPoolState) rule).mempool.remove(item))
                        matches = false;
                if (matches)
                    continue;
                log.error("neoscoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
                log.info("  neoscoind's mempool was: ");
                for (InventoryItem item : mostRecentInv.items)
                    log.info("    " + item.hash);
                log.info("  The expected mempool was: ");
                for (InventoryItem item : originalRuleSet)
                    log.info("    " + item.hash);
                rulesSinceFirstFail++;
            }
            mostRecentInv = null;
        } else if (rule instanceof UTXORule) {
            if (neoscoind.getPeerVersionMessage().isGetUTXOsSupported()) {
                UTXORule r = (UTXORule) rule;
                UTXOsMessage result = neoscoind.getUTXOs(r.query).get();
                if (!result.equals(r.result)) {
                    log.error("utxo result was not what we expected.");
                    log.error("Wanted  {}", r.result);
                    log.error("but got {}", result);
                    rulesSinceFirstFail++;
                } else {
                    log.info("Successful utxo query {}: {}", r.ruleName, result);
                }
            }
        } else {
            throw new RuntimeException("Unknown rule");
        }
        if (rulesSinceFirstFail > 0)
            rulesSinceFirstFail++;
        if (rulesSinceFirstFail > 6)
            System.exit(1);
    }

    if (unexpectedInvs.get() > 0)
        log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from neoscoind");
    log.info("Done testing.");
    System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
}