hashForWitnessV0 method

dynamic hashForWitnessV0(
  1. int inIndex,
  2. Uint8List prevOutScript,
  3. int value,
  4. int hashType,
)

Implementation

hashForWitnessV0(
    int inIndex, Uint8List prevOutScript, int value, int hashType) {
  var tbuffer = Uint8List.fromList([]);
  var toffset = 0;
  // Any changes made to the ByteData will also change the buffer, and vice versa.
  // https://api.dart.dev/stable/2.7.1/dart-typed_data/ByteBuffer/asByteData.html
  ByteData bytes = tbuffer.buffer.asByteData();
  var hashOutputs = ZERO;
  var hashPrevouts = ZERO;
  var hashSequence = ZERO;

  writeSlice(slice) {
    tbuffer.setRange(toffset, toffset + slice.length as int, slice);
    toffset += slice.length as int;
  }

  writeUInt32(i) {
    bytes.setUint32(toffset, i, Endian.little);
    toffset += 4;
  }

  writeUInt64(i) {
    bytes.setUint64(toffset, i, Endian.little);
    toffset += 8;
  }

  writeVarInt(i) {
    varuint.encode(i, tbuffer, toffset);
    toffset += varuint.encodingLength(i);
  }

  writeVarSlice(slice) {
    writeVarInt(slice.length);
    writeSlice(slice);
  }

  if ((hashType & SIGHASH_ANYONECANPAY) == 0) {
    tbuffer = new Uint8List(36 * this.ins.length);
    bytes = tbuffer.buffer.asByteData();
    toffset = 0;

    ins.forEach((txIn) {
      writeSlice(txIn.hash);
      writeUInt32(txIn.index);
    });
    hashPrevouts = bcrypto.hash256(tbuffer);
  }

  if ((hashType & SIGHASH_ANYONECANPAY) == 0 &&
      (hashType & 0x1f) != SIGHASH_SINGLE &&
      (hashType & 0x1f) != SIGHASH_NONE) {
    tbuffer = new Uint8List(4 * this.ins.length);
    bytes = tbuffer.buffer.asByteData();
    toffset = 0;
    ins.forEach((txIn) {
      writeUInt32(txIn.sequence);
    });
    hashSequence = bcrypto.hash256(tbuffer);
  }

  if ((hashType & 0x1f) != SIGHASH_SINGLE &&
      (hashType & 0x1f) != SIGHASH_NONE) {
    var txOutsSize = outs.fold(
        0, (dynamic sum, output) => sum + 8 + varSliceSize(output.script!));
    tbuffer = new Uint8List(txOutsSize);
    bytes = tbuffer.buffer.asByteData();
    toffset = 0;
    outs.forEach((txOut) {
      writeUInt64(txOut.value);
      writeVarSlice(txOut.script);
    });
    hashOutputs = bcrypto.hash256(tbuffer);
  } else if ((hashType & 0x1f) == SIGHASH_SINGLE && inIndex < outs.length) {
    // SIGHASH_SINGLE only hash that according output
    var output = outs[inIndex];
    tbuffer = new Uint8List(8 + varSliceSize(output.script!));
    bytes = tbuffer.buffer.asByteData();
    toffset = 0;
    writeUInt64(output.value);
    writeVarSlice(output.script);
    hashOutputs = bcrypto.hash256(tbuffer);
  }

  tbuffer = new Uint8List(156 + varSliceSize(prevOutScript));
  bytes = tbuffer.buffer.asByteData();
  toffset = 0;
  var input = ins[inIndex];
  writeUInt32(version);
  writeSlice(hashPrevouts);
  writeSlice(hashSequence);
  writeSlice(input.hash);
  writeUInt32(input.index);
  writeVarSlice(prevOutScript);
  writeUInt64(value);
  writeUInt32(input.sequence);
  writeSlice(hashOutputs);
  writeUInt32(this.locktime);
  writeUInt32(hashType);

  return bcrypto.hash256(tbuffer);
}