public static BlockHash Hash(byte[] bytes) => BlockHash.FromHashDigest(HashDigest <SHA256> .DeriveFrom(bytes));
/// <summary> /// Converts a given hexadecimal representation of a digest into /// a <see cref="HashDigest{T}"/> object. /// <para>This is a shortcut of /// <see cref="HashDigest{T}.FromString(string)"/> method.</para> /// <para>This is an inverse function of /// <see cref="HashDigest{T}.ToString()"/> method.</para> /// </summary> /// <param name="hexDigest">A hexadecimal representation of /// a <see cref="HashDigest{T}"/>.</param> /// <typeparam name="T">A <see cref="HashAlgorithm"/> which corresponds /// to a digest.</typeparam> /// <returns>A corresponding <see cref="HashDigest{T}"/> value. /// </returns> /// <exception cref="ArgumentNullException">Thrown when the given /// <paramref name="hexDigest"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the given /// <paramref name="hexDigest"/>'s length is not the double of /// the <see cref="HashDigest{T}.Size"/>, the hash algorithm /// (i.e., <typeparamref name="T"/> requires.</exception> /// <seealso cref="HashDigest{T}.FromString(string)"/> /// <seealso cref="HashDigest{T}.ToString()"/> public static HashDigest <T> ToHashDigest <T>(this string hexDigest) where T : HashAlgorithm { return(HashDigest <T> .FromString(hexDigest)); }
public static void Validate(IEnumerable <Block <T> > blocks) { HashDigest <SHA256>?prevHash = null; DateTime? prevTimestamp = null; DateTime now = DateTime.UtcNow; IEnumerable <(ulong i, DifficultyExpectation)> indexedDifficulties = ExpectDifficulties(blocks) .Select((exp, i) => { return((ulong)i, exp); }); foreach (var(i, exp) in indexedDifficulties) { Trace.Assert(exp.Block != null); Block <T> block = exp.Block; if (i != block.Index) { throw new InvalidBlockIndexException( $"the expected block index is {i}, but its index is" + $" {block.Index}'" ); } if (block.Difficulty < exp.Difficulty) { throw new InvalidBlockDifficultyException( $"the expected difficulty of the block #{i} " + $"is {exp.Difficulty}, but its difficulty is " + $"{block.Difficulty}'" ); } if (block.PreviousHash != prevHash) { if (prevHash == null) { throw new InvalidBlockPreviousHashException( "the genesis block must have not previous block" ); } throw new InvalidBlockPreviousHashException( $"the block #{i} is not continuous from the block #{i - 1};" + $"while previous block's hash is {prevHash}, " + $"the block #{i}'s pointer to the previous hash refers to " + $"{block.PreviousHash?.ToString() ?? "nothing"}" ); } if (now < block.Timestamp) { throw new InvalidBlockTimestampException( $"the block #{i}'s timestamp ({block.Timestamp}) is " + $"later than now ({now})" ); } if (block.Timestamp <= prevTimestamp) { throw new InvalidBlockTimestampException( $"the block #{i}'s timestamp ({block.Timestamp}) is earlier than " + $"the block #{i - 1}'s ({prevTimestamp})" ); } block.Validate(); prevHash = block.Hash; prevTimestamp = block.Timestamp; } }