/**
  * Handle an inventory request
  *
  * <p>This method is called when a 'getdata' message is received. The application should send the
  * inventory items to the requesting peer. A 'notfound' message should be returned to the
  * requesting peer if one or more items cannot be sent.
  *
  * @param msg Message
  * @param invList Inventory item list
  */
 @Override
 public void sendInventory(Message msg, List<InventoryItem> invList) {
   Peer peer = msg.getPeer();
   List<InventoryItem> notFoundList = new ArrayList<>(invList.size());
   //
   // Process the inventory list and request new transactions
   //
   invList
       .stream()
       .forEach(
           (item) -> {
             switch (item.getType()) {
               case InventoryItem.INV_TX:
                 try {
                   SendTransaction sendTx = Parameters.wallet.getSendTx(item.getHash());
                   if (sendTx != null) {
                     Message txMsg =
                         TransactionMessage.buildTransactionMessage(peer, sendTx.getTxData());
                     Parameters.networkHandler.sendMessage(txMsg);
                     log.info(
                         String.format(
                             "Transaction sent to peer %s\n  Tx %s",
                             peer.getAddress().toString(), item.getHash().toString()));
                   } else {
                     log.debug(
                         String.format(
                             "Requested transaction not found\n  Tx %s",
                             item.getHash().toString()));
                     notFoundList.add(item);
                   }
                 } catch (WalletException exc) {
                   log.error("Unable to retrieve wallet transaction", exc);
                   notFoundList.add(item);
                 }
                 break;
               default:
                 notFoundList.add(item);
             }
           });
   //
   // Send a 'notfound' message if we couldn't process all of the requests
   //
   if (!notFoundList.isEmpty()) {
     Message invMsg = NotFoundMessage.buildNotFoundMessage(peer, notFoundList);
     Parameters.networkHandler.sendMessage(invMsg);
   }
 }
 /**
  * Process a version message
  *
  * <p>This method is called when a 'version' message is received. The application should return a
  * 'verack' message to the sender if the connection is accepted.
  *
  * @param msg Message
  * @param localAddress Local address as seen by the peer
  */
 @Override
 public void processVersion(Message msg, PeerAddress localAddress) {
   Peer peer = msg.getPeer();
   //
   // Disconnect the peer if it doesn't provide node services.  Otherwise, increment
   // the version handshake stage.
   //
   if ((peer.getServices() & NetParams.NODE_NETWORK) == 0) {
     peer.setDisconnect(true);
     log.info(String.format("Connection rejected from %s", peer.getAddress().toString()));
   } else {
     peer.incVersionCount();
     Message ackMsg = VersionAckMessage.buildVersionAckMessage(peer);
     Parameters.networkHandler.sendMessage(ackMsg);
     log.info(
         String.format(
             "Peer %s: Protocol level %d, Services %d, Agent %s, Height %d",
             peer.getAddress().toString(),
             peer.getVersion(),
             peer.getServices(),
             peer.getUserAgent(),
             peer.getHeight()));
   }
 }
 /**
  * Process a pong
  *
  * <p>This method is called when a 'pong' message is received.
  *
  * @param msg Message
  * @param nonce Nonce
  */
 @Override
 public void processPong(Message msg, long nonce) {
   Peer peer = msg.getPeer();
   peer.setPing(false);
   log.info(String.format("'pong' response received from %s", peer.getAddress().toString()));
 }