TransactionHashResolver.java

/*
 * @copyright defined in LICENSE.txt
 */

package hera.spec.resolver;

import static hera.api.model.BytesValue.of;
import static hera.util.NumberUtils.positiveToByteArray;
import static hera.util.Sha256Utils.digest;
import static org.slf4j.LoggerFactory.getLogger;

import hera.annotation.ApiAudience;
import hera.annotation.ApiStability;
import hera.api.model.RawTransaction;
import hera.api.model.Signature;
import hera.api.model.TxHash;
import hera.exception.HerajException;
import hera.util.LittleEndianDataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.slf4j.Logger;

@ApiAudience.Private
@ApiStability.Unstable
public class TransactionHashResolver {

  protected static final Logger logger = getLogger(TransactionHashResolver.class);

  /**
   * Calculate a hash of transaction.
   *
   * @param rawTransaction a raw transaction
   * @return a hash of transaction
   */
  public static TxHash calculateHash(final RawTransaction rawTransaction) {
    try {
      final ByteArrayOutputStream raw = new ByteArrayOutputStream();
      final LittleEndianDataOutputStream dataOut = makeStream(raw, rawTransaction);
      dataOut.flush();
      dataOut.close();
      return new TxHash(of(digest(raw.toByteArray())));
    } catch (final IOException e) {
      throw new HerajException(e);
    }
  }

  /**
   * Calculate a hash of transaction.
   *
   * @param rawTransaction a raw transaction
   * @param signature a signature
   * @return a hash of transaction
   */
  public static TxHash calculateHash(final RawTransaction rawTransaction,
      final Signature signature) {
    try {
      final ByteArrayOutputStream raw = new ByteArrayOutputStream();
      final LittleEndianDataOutputStream dataOut = makeStream(raw, rawTransaction);
      dataOut.write(signature.getSign().getValue());
      dataOut.flush();
      dataOut.close();
      return new TxHash(of(digest(raw.toByteArray())));
    } catch (final IOException e) {
      throw new HerajException(e);
    }
  }

  protected static LittleEndianDataOutputStream makeStream(final ByteArrayOutputStream raw,
      final RawTransaction rawTransaction) throws IOException {
    final LittleEndianDataOutputStream dataOut = new LittleEndianDataOutputStream(raw);
    // WARNING : follow the stream order with server
    dataOut.writeLong(rawTransaction.getNonce());
    dataOut.write(rawTransaction.getSender().getBytesValue().getValue());
    dataOut.write(rawTransaction.getRecipient().getBytesValue().getValue());
    dataOut.write(positiveToByteArray(rawTransaction.getAmount().getValue()));
    dataOut.write(rawTransaction.getPayload().getValue());
    dataOut.writeLong(rawTransaction.getFee().getLimit());
    dataOut.write(positiveToByteArray(rawTransaction.getFee().getPrice().getValue()));
    dataOut.writeInt(rawTransaction.getTxType().getIntValue());
    dataOut.write(rawTransaction.getChainIdHash().getBytesValue().getValue());
    return dataOut;
  }

}