private static UInt256 GetOutputsHash(Transaction txTo) { using var hw = new HashWriter(); foreach (var o in txTo.Outputs) { hw.Add(o); } return(hw.GetHashFinal()); }
private static UInt256 GetSequenceHash(Transaction txTo) { using var hw = new HashWriter(); foreach (var i in txTo.Inputs) { hw.Add(i.Sequence); } return(hw.GetHashFinal()); }
public static UInt256 GetPrevOutHash(Transaction txTo) { using var hw = new HashWriter(); foreach (var i in txTo.Inputs) { hw.Add(i.PrevOut); } return(hw.GetHashFinal()); }
public void WriterHash() { using var hw = new HashWriter(); var empty = hw.GetHashFinal().ToHex(); Assert.Equal("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", empty); hw.Add("abc".AsciiToBytes()); var abc = hw.GetHashFinal().ToHex(); Assert.Equal("4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358", abc); hw.Add("de188941a3375d3a8a061e67576e926d".HexToBytes()); // ReSharper disable once InconsistentNaming var rc4_16 = hw.GetHashFinal().ToHex(); Assert.Equal("2182d3fe9882fd597d25daf6a85e3a574e5a9861dbc75c13ce3f47fe98572246", rc4_16); hw.Add("56f47c020000000008516365655252516a".HexToBytes()); var idx2 = hw.GetHashFinal().ToString(); Assert.Equal("1e05cef9f4a9bbf62f9293b5466087b467ed3326d1f03af72f2d4ff2cf66797a", idx2); }
public static UInt256 ComputeSignatureHash ( Script scriptCode, Transaction txTo, int nIn, SignatureHashType sigHashType, Amount amount, ScriptFlags flags = ScriptFlags.ENABLE_SIGHASH_FORKID ) { if (sigHashType.HasForkId && (flags & ScriptFlags.ENABLE_SIGHASH_FORKID) != 0) { var hashPrevOuts = new UInt256(); var hashSequence = new UInt256(); var hashOutputs = new UInt256(); if (!sigHashType.HasAnyoneCanPay) { hashPrevOuts = GetPrevOutHash(txTo); } var baseNotSingleOrNone = (sigHashType.GetBaseType() != BaseSignatureHashEnum.Single) && (sigHashType.GetBaseType() != BaseSignatureHashEnum.None); if (!sigHashType.HasAnyoneCanPay && baseNotSingleOrNone) { hashSequence = GetSequenceHash(txTo); } if (baseNotSingleOrNone) { hashOutputs = GetOutputsHash(txTo); } else if (sigHashType.GetBaseType() == BaseSignatureHashEnum.Single && nIn < txTo.Outputs.Length) { using var hw = new HashWriter(); hw.Add(txTo.Outputs[nIn]); hashOutputs = hw.GetHashFinal(); } using var writer = new HashWriter(); writer // Version .Add(txTo.Version) // Input prevouts/nSequence (none/all, depending on flags) .Add(hashPrevOuts) .Add(hashSequence) // The input being signed (replacing the scriptSig with scriptCode + // amount). The prevout may already be contained in hashPrevout, and the // nSequence may already be contain in hashSequence. .Add(txTo.Inputs[nIn].PrevOut) .Add(scriptCode) .Add(amount) .Add(txTo.Inputs[nIn].Sequence) // Outputs (none/one/all, depending on flags) .Add(hashOutputs) // Locktime .Add(txTo.LockTime) // Sighash type .Add(sigHashType.RawSigHashType); return(writer.GetHashFinal()); } if (nIn >= txTo.Inputs.Length) { // nIn out of range return(UInt256.One); } // Check for invalid use of SIGHASH_SINGLE if (sigHashType.GetBaseType() == BaseSignatureHashEnum.Single && nIn >= txTo.Outputs.Length) { // nOut out of range return(UInt256.One); } { // Original digest algorithm... var hasAnyoneCanPay = sigHashType.HasAnyoneCanPay; // ReSharper disable once UnusedVariable var numberOfInputs = hasAnyoneCanPay ? 1 : txTo.Inputs.Length; using var writer = new HashWriter(); // Start with the version... writer.Add(txTo.Version); // Add Input(s)... if (hasAnyoneCanPay) { // AnyoneCanPay serializes only the input being signed. var i = txTo.Inputs[nIn]; writer .Add((byte)1) .Add(i.PrevOut) .Add(scriptCode, true) .Add(i.Sequence); } else { // Non-AnyoneCanPay case. Process all inputs but handle input being signed in its own way. var isSingleOrNone = sigHashType.IsBaseSingle || sigHashType.IsBaseNone; writer.Add(txTo.Inputs.Length.AsVarIntBytes()); for (var nInput = 0; nInput < txTo.Inputs.Length; nInput++) { var i = txTo.Inputs[nInput]; writer.Add(i.PrevOut); if (nInput != nIn) { writer.Add(Script.None); } else { writer.Add(scriptCode, true); } if (nInput != nIn && isSingleOrNone) { writer.Add(0); } else { writer.Add(i.Sequence); } } } // Add Output(s)... var nOutputs = sigHashType.IsBaseNone ? 0 : sigHashType.IsBaseSingle ? nIn + 1 : txTo.Outputs.Length; writer.Add(nOutputs.AsVarIntBytes()); for (var nOutput = 0; nOutput < nOutputs; nOutput++) { if (sigHashType.IsBaseSingle && nOutput != nIn) { writer.Add(TxOut.Null); } else { writer.Add(txTo.Outputs[nOutput]); } } // Finish up... writer .Add(txTo.LockTime) .Add(sigHashType.RawSigHashType) ; return(writer.GetHashFinal()); } }