hash method

  1. @override
Uint8List hash(
  1. Tx tx,
  2. int inputIndex,
  3. SigHashType hashType, {
  4. Uint8List? prevScript,
  5. BigInt? amount,
})
override

Creates a combined hash code for a number of objects.

The hash code is computed for all arguments that are actually supplied, even if they are null, by numerically combining the Object.hashCode of each argument.

Example:

class SomeObject {
  final Object a, b, c;
  SomeObject(this.a, this.b, this.c);
  bool operator ==(Object other) =>
      other is SomeObject && a == other.a && b == other.b && c == other.c;
  int get hashCode => Object.hash(a, b, c);
}

The computed value will be consistent when the function is called with the same arguments multiple times during the execution of a single program.

The hash value generated by this function is not guaranteed to be stable over different runs of the same program, or between code run in different isolates of the same program. The exact algorithm used may differ between different platforms, or between different versions of the platform libraries, and it may depend on values that change on each program execution.

The hashAll function gives the same result as this function when called with a collection containing the actual arguments to this function in the same order.

Implementation

@override
Uint8List hash(
  Tx tx,
  int inputIndex,
  SigHashType hashType, {
  Uint8List? prevScript,
  BigInt? amount,
}) {
  if (prevScript == null) {
    throw ArgumentError('prevScript required for forked sighash');
  }
  if (amount == null) {
    throw ArgumentError('amount required for forked sighash');
  }

  // hashType | FORKID_FLAG | (forkId << 8)
  final forkHashType =
      SigHashType.fromFlag(hashType.flag | sighashForkIdFlag);
  final hashTypeWord = forkHashType.flag | (forkId << 8);

  final baseType = forkHashType.baseType;
  final anyoneCanPay = forkHashType.anyoneCanPay;

  // hashPrevouts
  Uint8List hashPrevouts;
  if (!anyoneCanPay) {
    final measure = WireMeasure();
    for (final inp in tx.inputs) {
      inp.prevOut.writeTo(measure);
    }
    final buf = Uint8List(measure.size);
    final w = WireWriter(buf);
    for (final inp in tx.inputs) {
      inp.prevOut.writeTo(w);
    }
    hashPrevouts = sha256d(buf);
  } else {
    hashPrevouts = Uint8List(32);
  }

  // hashSequence
  Uint8List hashSequence;
  if (!anyoneCanPay && baseType != 0x02 && baseType != 0x03) {
    final buf = Uint8List(tx.inputs.length * 4);
    final w = WireWriter(buf);
    for (final inp in tx.inputs) {
      w.writeUInt32(inp.sequence);
    }
    hashSequence = sha256d(buf);
  } else {
    hashSequence = Uint8List(32);
  }

  // hashOutputs
  Uint8List hashOutputs;
  if (baseType != 0x02 && baseType != 0x03) {
    final measure = WireMeasure();
    for (final out in tx.outputs) {
      out.writeTo(measure);
    }
    final buf = Uint8List(measure.size);
    final w = WireWriter(buf);
    for (final out in tx.outputs) {
      out.writeTo(w);
    }
    hashOutputs = sha256d(buf);
  } else if (baseType == 0x03 && inputIndex < tx.outputs.length) {
    final measure = WireMeasure();
    tx.outputs[inputIndex].writeTo(measure);
    final buf = Uint8List(measure.size);
    final w = WireWriter(buf);
    tx.outputs[inputIndex].writeTo(w);
    hashOutputs = sha256d(buf);
  } else {
    hashOutputs = Uint8List(32);
  }

  final measure = WireMeasure();
  measure.writeInt32(0); // version
  measure.writeSlice(hashPrevouts);
  measure.writeSlice(hashSequence);
  tx.inputs[inputIndex].prevOut.writeTo(measure);
  measure.writeVarSlice(prevScript);
  measure.writeUInt64(BigInt.zero); // amount placeholder
  measure.writeUInt32(0); // sequence placeholder
  measure.writeSlice(hashOutputs);
  measure.writeUInt32(0); // locktime placeholder
  measure.writeUInt32(0); // hashType placeholder

  final preimage = Uint8List(measure.size);
  final pw = WireWriter(preimage);
  pw.writeInt32(tx.version);
  pw.writeSlice(hashPrevouts);
  pw.writeSlice(hashSequence);
  tx.inputs[inputIndex].prevOut.writeTo(pw);
  pw.writeVarSlice(prevScript);
  pw.writeUInt64(amount);
  pw.writeUInt32(tx.inputs[inputIndex].sequence);
  pw.writeSlice(hashOutputs);
  pw.writeUInt32(tx.locktime);
  pw.writeUInt32(hashTypeWord);

  return sha256d(preimage);
}