/// <summary> /// Calculates and returns the ID of the transaction. /// ID is actually a hash computed from all the inputs and outputs. /// </summary> /// <remarks> /// This method will not assign the computed value to <see cref="Id"/> /// nor will it return the value of said field. It has to compute /// the hash from what are actually in the inputs and outputs so that /// validation of transactions can compare the computed value with /// <see cref="Id"/> to check for its correctness. /// </remarks> public string GetId() { string hash; using (var stream = new MemoryStream()) { using var streamWriter = new StreamWriter(stream); for (int i = 0, c = Inputs.Count; i < c; ++i) { var txIn = Inputs[i]; streamWriter.Write(txIn.TxId); HexUtils.AppendHexFromInt(streamWriter, txIn.TxOutIndex); } for (int i = 0, c = Outputs.Count; i < c; ++i) { var txOut = Outputs[i]; streamWriter.Write(txOut.Address); HexUtils.AppendHexFromLong(streamWriter, txOut.AmountInNekoshi); } streamWriter.Flush(); hash = HashUtils.SHA256(stream); } return(hash); }
/// <summary> /// Prepares header of the block to serve PoW hashing. /// This is similar to `getblocktemplate` in Bitcoin protocol. /// </summary> /// <param name="writer">Writer of a stream that will receive the block header.</param> public void PrepareForPowHash(TextWriter writer) { HexUtils.AppendHexFromInt(writer, Index); HexUtils.AppendHexFromLong(writer, Timestamp); writer.Write(MerkleHash); writer.Write(PreviousBlockHash); writer.Flush(); }