Example #1
0
        private byte[] Compress(ChecksummedByteCollection aInputs)
        {
            byte[]     result     = new byte[100];
            uint       seed       = aInputs.Checksum;
            Mersenne32 gen        = new Mersenne32(seed);
            int        inputCount = aInputs.Count;

            for (int i = 0; i < 100; i++)
            {
                byte[] source = aInputs.Get((int)(gen.NextUInt32() % inputCount));
                result[i] = source[gen.NextUInt32() % source.Length];
            }

            return(result);
        }
Example #2
0
        private ChecksummedByteCollection Hash(byte[] aBlockHeader, int aRound)
        {
            if ((aRound < 1) || (aRound > N))
            {
                throw new ArgumentOutOfRangeException(string.Format("Round '{0}' must be between 0 and N inclusive",
                                                                    nameof(aRound)));
            }

            // NOTE: instance is destroyed by caller!
            ChecksummedByteCollection roundOutputs = new ChecksummedByteCollection();

            Mersenne32 gen = new Mersenne32(0);

            byte[] roundInput;
            uint   seed;

            if (aRound == 1)
            {
                seed = Checksum(aBlockHeader);
                gen.Initialize(seed);
                roundInput = aBlockHeader;
            }
            else
            {
                ChecksummedByteCollection parentOutputs;
                if ((aRound == N) && (aBlockHeader.Length >= 4) && (NextNonce == GetNonce(aBlockHeader)) &&
                    Arrays.AreEqual(aBlockHeader, _cachedHeader))
                {
                    // Parent (round N - 1) has already been calculated so re-use values. This saves 50% of calculations!
                    parentOutputs = _cachedOutput;
                }
                else
                {
                    // Need to calculate parent output
                    parentOutputs = Hash(aBlockHeader, aRound - 1);
                }

                seed = parentOutputs.Checksum;

                gen.Initialize(seed);
                roundOutputs.AddRange(parentOutputs);

                // Determine the neighbouring nonce
                uint   neighbourNonce       = gen.NextUInt32();
                byte[] neighbourNonceHeader = ChangeNonce(aBlockHeader, neighbourNonce);
                ChecksummedByteCollection neighbourOutputs = Hash(neighbourNonceHeader, aRound - 1);

                // Cache neighbour nonce n-1 calculation if on final round (neighbour will be next nonce)
                if (aRound == N)
                {
                    _cachedNonce  = neighbourNonce;
                    _cachedHeader = neighbourNonceHeader;
                    _cachedOutput = neighbourOutputs.Clone();
                }

                roundOutputs.AddRange(neighbourOutputs);
                roundInput = Compress(roundOutputs);
            }

            Func <byte[], byte[]> hashFunc = _hashAlg[gen.NextUInt32() % 18];

            byte[] output = hashFunc(roundInput);
            output = Expand(output, N - aRound);
            roundOutputs.Add(output);

            return(roundOutputs);
        }
Example #3
0
        private byte[] Expand(byte[] aInput, int aExpansionFactor)
        {
            int        inputSize = aInput.Length;
            Mersenne32 gen       = new Mersenne32(Checksum(aInput));

            byte[] output = new byte[inputSize + (aExpansionFactor * M)];

            // Copy the genesis blob
            Array.Copy(aInput, 0, output, 0, inputSize);
            int readEnd = inputSize - 1;
            int copyLen = inputSize;

            while (readEnd < (output.Length - 1))
            {
                if ((readEnd + 1 + copyLen) > output.Length)
                {
                    copyLen = (output.Length) - (readEnd + 1);
                }

                switch (gen.NextUInt32() % 8)
                {
                case 0:
                    MemTransform1(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 1:
                    MemTransform2(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 2:
                    MemTransform3(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 3:
                    MemTransform4(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 4:
                    MemTransform5(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 5:
                    MemTransform6(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 6:
                    MemTransform7(ref output, 0, readEnd + 1, copyLen);
                    break;

                case 7:
                    MemTransform8(ref output, 0, readEnd + 1, copyLen);
                    break;

                default:
                    throw new ArgumentException("invalid argument");
                }

                readEnd += copyLen;
                copyLen += copyLen;
            }

            return(output);
        }