/**
   * Takes a Msg and encodes it into a single byte[], in a way that is compatible with the way that
   * PyBitmessage does. This payload can then be sent to a server to be disseminated across the
   * network. The payload is stored as a Payload object.
   *
   * @param encMsg - A msg Object containing the message data used to create the payload.
   * @param powDone - A boolean value indicating whether or not POW has been done for this message
   * @param toPubkey - A Pubkey object containing the data for the Pubkey of the address that this
   *     message is being sent to
   * @return A Payload object containing the message payload
   */
  private Payload constructMsgPayloadForDissemination(
      BMObject encMsg, boolean powDone, Pubkey toPubkey) {
    // Create a new Payload object to hold the payload data
    Payload msgPayload = new Payload();
    msgPayload.setBelongsToMe(true);
    msgPayload.setPOWDone(powDone);
    msgPayload.setType(Payload.OBJECT_TYPE_MSG);

    // Encode the POW nonce, expiration time, object type, object version, and stream number values
    // into byte form
    byte[] powNonceBytes = ByteUtils.longToBytes(encMsg.getPOWNonce());
    byte[] expirationTimeBytes = ByteUtils.longToBytes(encMsg.getExpirationTime());
    byte[] objectTypeBytes = ByteUtils.intToBytes(OBJECT_TYPE_MSG);
    byte[] objectVersionBytes = VarintEncoder.encode(OBJECT_VERSION_MSG);
    byte[] streamNumberBytes = VarintEncoder.encode(encMsg.getStreamNumber());

    byte[] payload = null;
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
      if (powDone) {
        outputStream.write(powNonceBytes);
      }
      outputStream.write(expirationTimeBytes);
      outputStream.write(objectTypeBytes);
      outputStream.write(objectVersionBytes);
      outputStream.write(streamNumberBytes);
      outputStream.write(encMsg.getPayload());

      payload = outputStream.toByteArray();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException(
          "IOException occurred in DataProcessor.constructMsgPayloadForDissemination()", e);
    }

    msgPayload.setPayload(payload);

    // Save the Payload object to the database
    PayloadProvider payProv = PayloadProvider.get(App.getContext());
    long msgPayloadId = payProv.addPayload(msgPayload);

    // Finally, set the msg payload ID to the one generated by the SQLite database
    msgPayload.setId(msgPayloadId);

    return msgPayload;
  }
  /**
   * Takes a Msg and constructs the payload needed to do POW for it.
   *
   * @param msg - The msg Object to construct the POW payload for
   * @return The POW payload
   */
  private byte[] constructMsgPayloadForPOW(BMObject msg) {
    try {
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

      outputStream.write(
          ByteUtils.longToBytes(
              msg.getExpirationTime())); // This conversion results in a byte[] of length 8, which
      // is what we want
      outputStream.write(ByteUtils.intToBytes(OBJECT_TYPE_MSG));
      outputStream.write(VarintEncoder.encode(OBJECT_VERSION_MSG));
      outputStream.write(VarintEncoder.encode(msg.getStreamNumber()));
      outputStream.write(msg.getPayload());

      return outputStream.toByteArray();
    } catch (IOException e) {
      throw new RuntimeException(
          "IOException occurred in OutgoingMessageProcessor.constructMsgPayloadForPOW()", e);
    }
  }