Esempio n. 1
0
        public byte[] ComputeHash(IHashFactory hashFactory)
        {
            IByteConverter converter = hashFactory.GetByteConverter();
            IDigest        digest    = hashFactory.GetDigest();

            string data = converter.ConvertToString(Nonce) +
                          converter.ConvertToString(PreviousHash) +
                          CreationTime.ToString() +
                          converter.ConvertToString(MerkleRoot) +
                          converter.ConvertToString(MinerAddress) +
                          HashAlgorithmId +
                          Difficulty;

            byte[] rawData = Encoding.ASCII.GetBytes(data);

            return(digest.GetHash(rawData));
        }
Esempio n. 2
0
        public void MineBlock(Block block)
        {
            INonceGenerator nonceGenerator = HashFactory.GetNonceGenerator();
            IByteConverter  converter      = HashFactory.GetByteConverter();

            if (Difficulty >= HashFactory.GetDigest().HashLength)
            {
                throw new ArgumentException("Difficulty can not be greater or equal to hash length.");
            }

            if (Difficulty <= 0)
            {
                throw new ArgumentException("Difficulty can not be greater or equal to zero.");
            }

            byte[] target = new byte[Difficulty];

            block.HashAlgorithmId = HashAlgorithmId;
            block.Difficulty      = Difficulty;

            nonceGenerator.Reset();

            #region Parallel mining.

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            object locker        = new object();
            byte[] solutionNonce = null;
            byte[] solutionHash  = null;

            string immutableData = converter.ConvertToString(block.PreviousHash) +
                                   block.CreationTime.ToString() +
                                   converter.ConvertToString(block.MerkleRoot) +
                                   converter.ConvertToString(block.MinerAddress) +
                                   block.HashAlgorithmId +
                                   block.Difficulty;
            try
            {
                Parallel.ForEach(nonceGenerator, new ParallelOptions()
                {
                    CancellationToken = tokenSource.Token
                }, (byte[] nonce) =>
                {
                    IDigest digest = HashFactory.GetDigest();

                    converter = HashFactory.GetByteConverter();

                    string dataWithNonce = converter.ConvertToString(nonce) + immutableData;
                    byte[] rawData       = Encoding.ASCII.GetBytes(dataWithNonce);
                    byte[] hash          = digest.GetHash(rawData);

                    if (hash.Take(Difficulty).SequenceEqual(target))
                    {
                        lock (locker)
                        {
                            solutionNonce = nonce;
                            solutionHash  = hash;
                        }

                        tokenSource.Cancel();
                    }
                });
            }
            catch (OperationCanceledException)
            {
            }

            block.Nonce = solutionNonce ?? throw new MiningFailureException("Couldn't resolve block", block);
            block.Hash  = solutionHash;

            #endregion
        }