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);
  }

  writeUInt8(i) {
    bytes.setUint8(toffset, i);
    toffset++;
  }

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

  writeInt32(i) {
    bytes.setInt32(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);
  }

  writeVector(vector) {
    writeVarInt(vector.length);
    vector.forEach((buf) {
      writeVarSlice(buf);
    });
  }

  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, (sum, output) => (sum as int) + 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);
}