@Test public void invDownloadTxMultiPeer() throws Exception { // Check co-ordination of which peer to download via the memory pool. VersionMessage ver = new VersionMessage(unitTestParams, 100); InetSocketAddress address = new InetSocketAddress("127.0.0.1", 4242); Peer peer2 = new Peer(unitTestParams, ver, new PeerAddress(address), blockChain, memoryPool); peer2.addWallet(wallet); VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT); peerVersion.clientVersion = 70001; peerVersion.localServices = VersionMessage.NODE_NETWORK; connect(); InboundMessageQueuer writeTarget2 = connect(peer2, peerVersion); // Make a tx and advertise it to one of the peers. BigInteger value = Utils.toNanoCoins(1, 0); Transaction tx = createFakeTx(unitTestParams, value, this.address); InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()); inv.addItem(item); inbound(writeTarget, inv); // We got a getdata message. GetDataMessage message = (GetDataMessage) outbound(writeTarget); assertEquals(1, message.getItems().size()); assertEquals(tx.getHash(), message.getItems().get(0).hash); assertTrue(memoryPool.maybeWasSeen(tx.getHash())); // Advertising to peer2 results in no getdata message. inbound(writeTarget2, inv); pingAndWait(writeTarget2); assertNull(outbound(writeTarget2)); }
@Override public void setUp(BlockStore blockStore) throws Exception { super.setUp(blockStore); remoteVersionMessage = new VersionMessage(unitTestParams, 1); remoteVersionMessage.localServices = VersionMessage.NODE_NETWORK; remoteVersionMessage.clientVersion = NotFoundMessage.MIN_PROTOCOL_VERSION; blockJobs = false; initPeerGroup(); }
private void stepThroughInit(VersionMessage versionMessage, InboundMessageQueuer writeTarget) throws InterruptedException { checkState(writeTarget.nextMessageBlocking() instanceof VersionMessage); checkState(writeTarget.nextMessageBlocking() instanceof VersionAck); if (versionMessage.isBloomFilteringSupported()) { checkState(writeTarget.nextMessageBlocking() instanceof BloomFilter); checkState(writeTarget.nextMessageBlocking() instanceof MemoryPoolMessage); } }
// handle peer discovered by PeerGroup protected InboundMessageQueuer handleConnectToPeer(int id, VersionMessage versionMessage) throws Exception { InboundMessageQueuer writeTarget = newPeerWriteTargetQueue.take(); checkArgument(versionMessage.hasBlockChain()); // Complete handshake with the peer - send/receive version(ack)s, receive bloom filter writeTarget.sendMessage(versionMessage); writeTarget.sendMessage(new VersionAck()); stepThroughInit(versionMessage, writeTarget); return writeTarget; }
protected InboundMessageQueuer connectPeer(int id, VersionMessage versionMessage) throws Exception { checkArgument(versionMessage.hasBlockChain()); InboundMessageQueuer writeTarget = connectPeerWithoutVersionExchange(id); // Complete handshake with the peer - send/receive version(ack)s, receive bloom filter writeTarget.sendMessage(versionMessage); writeTarget.sendMessage(new VersionAck()); stepThroughInit(versionMessage, writeTarget); return writeTarget; }
@Override public ProductMessage onVersionMessage(List<Message> messages) throws ParseException { VersionMessage version = Messages.getVersionMessage(messages); if (!version.getLanguage().equals(JAVA)) { throw new IllegalArgumentException("wrong language in version message"); } ProductMessage ast = Messages.getProductMessage(messages, AST, JAVA); if (!ast.getLanguage().equals(JAVA)) { throw new IllegalArgumentException("wrong language in ast product message"); } NonTerminal root = (NonTerminal) ASTs.decode(ast); OutlineTrimmer trimmer = new OutlineTrimmer(); root.accept(trimmer); return new ProductMessage( version.getVersionId(), new LongKey(1), version.getSource(), OUTLINE, JAVA, Outlines.encode(trimmer.getConverted()), new ProductDependency(ast)); }
protected InboundMessageQueuer connect(Peer peer, VersionMessage versionMessage) throws Exception { checkArgument(versionMessage.hasBlockChain()); final AtomicBoolean doneConnecting = new AtomicBoolean(false); final Thread thisThread = Thread.currentThread(); peer.addEventListener( new AbstractPeerEventListener() { @Override public void onPeerDisconnected(Peer p, int peerCount) { synchronized (doneConnecting) { if (!doneConnecting.get()) thisThread.interrupt(); } } }); if (clientType == ClientType.NIO_CLIENT_MANAGER || clientType == ClientType.BLOCKING_CLIENT_MANAGER) channels.openConnection(new InetSocketAddress("127.0.0.1", 2000), peer); else if (clientType == ClientType.NIO_CLIENT) new NioClient(new InetSocketAddress("127.0.0.1", 2000), peer, 100); else if (clientType == ClientType.BLOCKING_CLIENT) new BlockingClient( new InetSocketAddress("127.0.0.1", 2000), peer, 100, SocketFactory.getDefault(), null); else throw new RuntimeException(); // Claim we are connected to a different IP that what we really are, so tx confidence // broadcastBy sets work InboundMessageQueuer writeTarget = newPeerWriteTargetQueue.take(); writeTarget.peer = peer; // Complete handshake with the peer - send/receive version(ack)s, receive bloom filter writeTarget.sendMessage(versionMessage); writeTarget.sendMessage(new VersionAck()); try { checkState(writeTarget.nextMessageBlocking() instanceof VersionMessage); checkState(writeTarget.nextMessageBlocking() instanceof VersionAck); synchronized (doneConnecting) { doneConnecting.set(true); } Thread.interrupted(); // Clear interrupted bit in case it was set before we got into the CS } catch (InterruptedException e) { // We were disconnected before we got back version/verack } return writeTarget; }
@Test public void peerGroupWalletIntegration() throws Exception { // Make sure we can create spends, and that they are announced. Then do the same with offline // mode. // Set up connections and block chain. VersionMessage ver = new VersionMessage(params, 2); ver.localServices = VersionMessage.NODE_NETWORK; InboundMessageQueuer p1 = connectPeer(1, ver); InboundMessageQueuer p2 = connectPeer(2); // Send ourselves a bit of money. Block b1 = TestUtils.makeSolvedTestBlock(blockStore, address); inbound(p1, b1); pingAndWait(p1); assertNull(outbound(p1)); assertEquals(Utils.toNanoCoins(50, 0), wallet.getBalance()); // Check that the wallet informs us of changes in confidence as the transaction ripples across // the network. final Transaction[] transactions = new Transaction[1]; wallet.addEventListener( new AbstractWalletEventListener() { @Override public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { transactions[0] = tx; } }); // Now create a spend, and expect the announcement on p1. Address dest = new ECKey().toAddress(params); Wallet.SendResult sendResult = wallet.sendCoins(peerGroup, dest, Utils.toNanoCoins(1, 0)); assertNotNull(sendResult.tx); Threading.waitForUserCode(); assertFalse(sendResult.broadcastComplete.isDone()); assertEquals(transactions[0], sendResult.tx); assertEquals(0, transactions[0].getConfidence().numBroadcastPeers()); transactions[0] = null; Transaction t1 = (Transaction) outbound(p1); assertNotNull(t1); // 49 BTC in change. assertEquals(Utils.toNanoCoins(49, 0), t1.getValueSentToMe(wallet)); // The future won't complete until it's heard back from the network on p2. InventoryMessage inv = new InventoryMessage(params); inv.addTransaction(t1); inbound(p2, inv); pingAndWait(p2); Threading.waitForUserCode(); assertTrue(sendResult.broadcastComplete.isDone()); assertEquals(transactions[0], sendResult.tx); assertEquals(1, transactions[0].getConfidence().numBroadcastPeers()); // Confirm it. Block b2 = TestUtils.createFakeBlock(blockStore, t1).block; inbound(p1, b2); pingAndWait(p1); assertNull(outbound(p1)); // Do the same thing with an offline transaction. peerGroup.removeWallet(wallet); Wallet.SendRequest req = Wallet.SendRequest.to(dest, Utils.toNanoCoins(2, 0)); req.ensureMinRequiredFee = false; Transaction t3 = checkNotNull(wallet.sendCoinsOffline(req)); assertNull(outbound(p1)); // Nothing sent. // Add the wallet to the peer group (simulate initialization). Transactions should be announced. peerGroup.addWallet(wallet); // Transaction announced to the first peer. assertEquals(t3.getHash(), ((Transaction) outbound(p1)).getHash()); }
private void connectWithVersion(int version) throws Exception { VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT); peerVersion.clientVersion = version; peerVersion.localServices = VersionMessage.NODE_NETWORK; writeTarget = connect(peer, peerVersion); }