Ejemplo n.º 1
0
        private bool checkCycle()
        {
            var _logger = Log.ForContext <Share>();

            if (Cycle.Length != CYCLE_LENGTH)
            {
                return(false);
            }

            var blakeHash = new HMACBlake2B(256);

            byte[] keys = blakeHash.ComputeHash(Encoding.ASCII.GetBytes(BlockHash.ToHexString()));

            UInt64 k0 = (UInt64)BitConverter.ToInt64(keys.Slice(0, 8), 0).LittleEndian();
            UInt64 k1 = (UInt64)BitConverter.ToInt64(keys.Slice(8, 16), 0).LittleEndian();

            UInt32 edgeMask = (UInt32)(1 << Job.EdgeBits) - 1;

            UInt32[] uvs  = new UInt32[2 * CYCLE_LENGTH];
            UInt32   xor0 = 0;
            UInt32   xor1 = 0;

            for (var n = 0; n < CYCLE_LENGTH; n++)
            {
                if (Cycle[n] > edgeMask)
                {
                    _logger.Error("POW_TOO_BIG");
                    return(false);
                }

                if (n > 0 && Cycle[n] <= Cycle[n - 1])
                {
                    _logger.Error("POW_TOO_SMALL");
                    return(false);
                }

                xor0 ^= uvs[2 * n] = sipnode(k0, k1, edgeMask, Cycle[n], 0);
                xor1 ^= uvs[2 * n + 1] = sipnode(k0, k1, edgeMask, Cycle[n], 1);
            }

            // matching endpoints imply zero xors
            if ((xor0 | xor1) != 0)
            {
                var cycleStr = "";
                foreach (var edge in Cycle)
                {
                    cycleStr += edge.ToString("x") + ",";
                }
                cycleStr = cycleStr.Remove(cycleStr.Length - 1);

                _logger.Debug("Block hash: {0}", BlockHash.ToHexString());
                _logger.Debug("Cycle: {0}", cycleStr);

                _logger.Error("POW_NON_MATCHING");
                return(false);
            }

            int m = 0, i = 0, j;

            do   // follow cycle
            {
                for (int k = j = i; (k = (k + 2) % (2 * CYCLE_LENGTH)) != i;)
                {
                    if (uvs[k] == uvs[i])   // find other edge endpoint identical to one at i
                    {
                        if (j != i)         // already found one before
                        {
                            _logger.Error("POW_BRANCH");
                            return(false);
                        }

                        j = k;
                    }
                }

                if (j == i)
                {
                    _logger.Error("POW_DEAD_END");
                    return(false);
                }

                i = j ^ 1;
                m++;
            } while (i != 0); // must cycle back to start or we would have found branch

            if (m != CYCLE_LENGTH)
            {
                _logger.Error("POW_SHORT_CYCLE");
                return(false);
            }

            return(true);
        }