/**
  * Process the 'getblocks' message and return an 'inv' message
  *
  * @param msg Message
  * @param inBuffer Input buffer
  * @param msgListener Message listener
  * @throws EOFException End-of-data processing stream
  * @throws VerificationException Message verification failed
  */
 public static void processGetBlocksMessage(
     Message msg, SerializedBuffer inBuffer, MessageListener msgListener)
     throws EOFException, VerificationException {
   //
   // Process the message
   //
   int version = inBuffer.getInt();
   if (version < NetParams.MIN_PROTOCOL_VERSION)
     throw new VerificationException(
         String.format("Protocol version %d is not supported", version));
   int count = inBuffer.getVarInt();
   if (count < 0 || count > 500)
     throw new VerificationException("More than 500 locator entries in 'getblocks' message");
   List<Sha256Hash> blockList = new ArrayList<>(count);
   for (int i = 0; i < count; i++)
     blockList.add(new Sha256Hash(Helper.reverseBytes(inBuffer.getBytes(32))));
   Sha256Hash stopBlock = new Sha256Hash(Helper.reverseBytes(inBuffer.getBytes(32)));
   //
   // Notify the message listener
   //
   msgListener.processGetBlocks(msg, version, blockList, stopBlock);
 }
 /**
  * Creates a new transaction from the serialized data in the byte stream
  *
  * @param inBuffer Serialized buffer
  * @throws EOFException Byte stream is too short
  * @throws VerificationException Verification error
  */
 public Transaction(SerializedBuffer inBuffer) throws EOFException, VerificationException {
   //
   // Mark our current position within the input stream
   //
   int segmentStart = inBuffer.getSegmentStart();
   inBuffer.setSegmentStart();
   //
   // Get the transaction version
   //
   txVersion = inBuffer.getInt();
   //
   // Get the transaction inputs
   //
   int inCount = inBuffer.getVarInt();
   if (inCount < 0) throw new VerificationException("Transaction input count is negative");
   txInputs = new ArrayList<>(Math.max(inCount, 1));
   for (int i = 0; i < inCount; i++) txInputs.add(new TransactionInput(this, i, inBuffer));
   //
   // A coinbase transaction has a single unconnected input with a transaction hash of zero
   // and an output index of -1
   //
   if (txInputs.size() == 1) {
     OutPoint outPoint = txInputs.get(0).getOutPoint();
     coinBase = (outPoint.getHash().equals(Sha256Hash.ZERO_HASH) && outPoint.getIndex() == -1);
   } else {
     coinBase = false;
   }
   //
   // Get the transaction outputs
   //
   int outCount = inBuffer.getVarInt();
   if (outCount < 0) throw new EOFException("Transaction output count is negative");
   txOutputs = new ArrayList<>(Math.max(outCount, 1));
   for (int i = 0; i < outCount; i++) txOutputs.add(new TransactionOutput(i, inBuffer));
   //
   // Get the transaction lock time
   //
   txLockTime = inBuffer.getUnsignedInt();
   //
   // Save a copy of the serialized transaction
   //
   txData = inBuffer.getSegmentBytes();
   //
   // Calculate the transaction hash using the serialized data
   //
   txHash = new Sha256Hash(Utils.reverseBytes(Utils.doubleDigest(txData)));
   //
   // Calculate the normalized transaction ID
   //
   List<byte[]> bufferList = new ArrayList<>(txInputs.size() + txOutputs.size());
   txInputs
       .stream()
       .forEach(
           (txInput) -> {
             bufferList.add(txInput.getOutPoint().getBytes());
           });
   txOutputs
       .stream()
       .forEach(
           (txOutput) -> {
             bufferList.add(txOutput.getBytes());
           });
   normID = new Sha256Hash(Utils.reverseBytes(Utils.doubleDigest(bufferList)));
   //
   // Restore the previous segment (if any)
   //
   inBuffer.setSegmentStart(segmentStart);
 }