hashForWitnessV1 method
Implementation
Uint8List hashForWitnessV1(int inIndex, List<Uint8List> prevOutScripts,
List<int> values, int hashType, Uint8List? leafHash, Uint8List? annex) {
final outputType = hashType == SIGHASH_DEFAULT
? SIGHASH_ALL
: hashType & SIGHASH_OUTPUT_MASK;
final inputType = hashType & SIGHASH_INPUT_MASK;
final isAnyoneCanPay = inputType == SIGHASH_ANYONECANPAY;
final isNone = outputType == SIGHASH_NONE;
final isSingle = outputType == SIGHASH_SINGLE;
var hashPrevouts = Uint8List.fromList([]);
var hashAmounts = Uint8List.fromList([]);
var hashScriptPubKeys = Uint8List.fromList([]);
var hashSequences = Uint8List.fromList([]);
var hashOutputs = Uint8List.fromList([]);
if (!isAnyoneCanPay) {
// Hash txid.
final hashBuf = Buffer(36 * ins.length);
for (var txIn in ins) {
hashBuf.writeSlice(txIn.hash);
hashBuf.writeUInt32(txIn.index);
}
hashPrevouts = hashBuf.toSha256();
// Hash value.
final valueBuf = Buffer(8 * ins.length);
for (var value in values) {
valueBuf.writeUInt64(value);
}
hashAmounts = valueBuf.toSha256();
// Hash prevout script.
final scriptBuf =
Buffer(prevOutScripts.map(varSliceSize).reduce((a, b) => a + b));
for (var prevOutScript in prevOutScripts) {
scriptBuf.writeVarSlice(prevOutScript);
}
hashScriptPubKeys = scriptBuf.toSha256();
// Hash sequence.
final sequenceBuf = Buffer(4 * ins.length);
for (var txIn in ins) {
sequenceBuf.writeUInt32(txIn.sequence);
}
hashSequences = sequenceBuf.toSha256();
}
if (!(isNone || isSingle)) {
final txOutsSize = outs
.map((output) => 8 + varSliceSize(output.script!))
.reduce((a, b) => a + b);
final outBuf = Buffer(txOutsSize);
for (var out in outs) {
outBuf.writeUInt64(out.value);
outBuf.writeVarSlice(out.script);
}
hashOutputs = outBuf.toSha256();
} else if (isSingle && inIndex < outs.length) {
final output = outs[inIndex];
final outBuf = Buffer(8 + varSliceSize(output.script!));
outBuf.writeUInt64(output.value);
outBuf.writeVarSlice(output.script);
hashOutputs = outBuf.toSha256();
}
final spendType = (leafHash != null ? 2 : 0) + (annex != null ? 1 : 0);
final sigMsgSize = 174 -
(isAnyoneCanPay ? 49 : 0) -
(isNone ? 32 : 0) +
(annex != null ? 32 : 0) +
(leafHash != null ? 37 : 0);
final buf = Buffer(sigMsgSize);
buf.writeUInt8(hashType);
// Transaction
buf.writeInt32(version);
buf.writeUInt32(locktime);
buf.writeSlice(hashPrevouts);
buf.writeSlice(hashAmounts);
buf.writeSlice(hashScriptPubKeys);
buf.writeSlice(hashSequences);
if (!(isNone || isSingle)) buf.writeSlice(hashOutputs);
// Input
buf.writeUInt8(spendType);
if (isAnyoneCanPay) {
final input = ins[inIndex];
buf.writeSlice(input.hash);
buf.writeUInt32(input.index);
buf.writeUInt64(values[inIndex]);
buf.writeVarSlice(prevOutScripts[inIndex]);
buf.writeUInt32(input.sequence);
} else {
buf.writeUInt32(inIndex);
}
if (annex != null) {
final annexBuf = Buffer(varSliceSize(annex));
annexBuf.writeVarSlice(annex);
buf.writeSlice(annexBuf.toSha256());
}
// Output
if (isSingle) buf.writeSlice(hashOutputs);
// BIP342 extension
if (leafHash != null) {
buf.writeSlice(leafHash);
buf.writeUInt8(0);
buf.writeUInt32(0xffffffff);
}
// Extra zero byte because:
// https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-19
return Uint8List.fromList(
bscript.taggedHash('TapSighash', [0x00] + buf.tBuffer));
}