public void Crytonight_Heavy()
        {
            var blobConverted = "0106f1adafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42597710c48c6d885e2622f40f82ecd9b9fd538f28df9b0557e07cd3237a31c76569ada98001".HexToByteArray();
            var buf           = new byte[32];

            LibCryptonight.CryptonightHeavy(blobConverted, buf, 0);
            var result = buf.ToHexString();

            Assert.Equal("1559665f933c0aab5bf2b11db406b9db170a78d82d180ee5a7cf88f1c2041f9e", result);

            Array.Clear(buf, 0, buf.Length);

            LibCryptonight.CryptonightHeavy(blobConverted, buf, 0);
            result = buf.ToHexString();
            Assert.Equal("1559665f933c0aab5bf2b11db406b9db170a78d82d180ee5a7cf88f1c2041f9e", result);
        }
        public void Crytonight_Heavy()
        {
            var blobConverted = "0106f1adafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42597710c48c6d885e2622f40f82ecd9b9fd538f28df9b0557e07cd3237a31c76569ada98001".HexToByteArray();
            var buf           = new byte[32];

            LibCryptonight.CryptonightHeavy(blobConverted, buf, CryptonightVariant.VARIANT_0, 0);
            var result = buf.ToHexString();

            Assert.Equal("93b6815d8f19abe0ff8ba8d8cf951cd264aa123e450bd52dc806fac298f83d9f", result);

            Array.Clear(buf, 0, buf.Length);

            LibCryptonight.CryptonightHeavy(blobConverted, buf, CryptonightVariant.VARIANT_0, 0);
            result = buf.ToHexString();
            Assert.Equal("93b6815d8f19abe0ff8ba8d8cf951cd264aa123e450bd52dc806fac298f83d9f", result);
        }
        public void Crytonight_Heavy_Variant_1()
        {
            var blobConverted = "0106f1adafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42597710c48c6d885e2622f40f82ecd9b9fd538f28df9b0557e07cd3237a31c76569ada98001".HexToByteArray();
            var buf           = new byte[32];

            LibCryptonight.CryptonightHeavy(blobConverted, buf, 1);
            var result = buf.ToHexString();

            Assert.Equal("342418ec4bf806aafb102b34d64fc33ab91d89ad40786b92d1b54ceeb4d50822", result);

            Array.Clear(buf, 0, buf.Length);

            LibCryptonight.CryptonightHeavy(blobConverted, buf, 1);
            result = buf.ToHexString();
            Assert.Equal("342418ec4bf806aafb102b34d64fc33ab91d89ad40786b92d1b54ceeb4d50822", result);
        }
Beispiel #4
0
        public (Share Share, string BlobHex, string BlobHash) ProcessShare(string nonce, uint workerExtraNonce, string workerHash, StratumClient worker)
        {
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(nonce), $"{nameof(nonce)} must not be empty");
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(workerHash), $"{nameof(workerHash)} must not be empty");
            Contract.Requires <ArgumentException>(workerExtraNonce != 0, $"{nameof(workerExtraNonce)} must not be empty");

            var context = worker.ContextAs <CryptonoteWorkerContext>();

            // validate nonce
            if (!CryptonoteConstants.RegexValidNonce.IsMatch(nonce))
            {
                throw new StratumException(StratumError.MinusOne, "malformed nonce");
            }

            // clone template
            Span <byte> blob = stackalloc byte[blobTemplate.Length];

            blobTemplate.CopyTo(blob);

            // inject extranonce
            var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());

            extraNonceBytes.CopyTo(blob.Slice(BlockTemplate.ReservedOffset, extraNonceBytes.Length));

            // inject nonce
            var nonceBytes = nonce.HexToByteArray();

            nonceBytes.CopyTo(blob.Slice(CryptonoteConstants.BlobNonceOffset, nonceBytes.Length));

            // convert
            var blobConverted = LibCryptonote.ConvertBlob(blob, blobTemplate.Length);

            if (blobConverted == null)
            {
                throw new StratumException(StratumError.MinusOne, "malformed blob");
            }

            // hash it
            Span <byte> headerHash = stackalloc byte[32];
            var         variant    = coin.HashVariant;

            // auto-select?
            if (variant == 0)
            {
                variant = blobConverted[0] >= 7 ? blobConverted[0] - 6 : 0;
            }

            switch (coin.Hash)
            {
            case CryptonightHashType.Normal:
                LibCryptonight.Cryptonight(blobConverted, headerHash, variant);
                break;

            case CryptonightHashType.Lite:
                LibCryptonight.CryptonightLight(blobConverted, headerHash, variant);
                break;

            case CryptonightHashType.Heavy:
                LibCryptonight.CryptonightHeavy(blobConverted, headerHash, variant);
                break;
            }

            var headerHashString = headerHash.ToHexString();

            if (headerHashString != workerHash)
            {
                throw new StratumException(StratumError.MinusOne, "bad hash");
            }

            // check difficulty
            var headerValue       = headerHash.ToBigInteger();
            var shareDiff         = (double)new BigRational(CryptonoteConstants.Diff1b, headerValue);
            var stratumDifficulty = context.Difficulty;
            var ratio             = shareDiff / stratumDifficulty;
            var isBlockCandidate  = shareDiff >= BlockTemplate.Difficulty;

            // test if share meets at least workers current difficulty
            if (!isBlockCandidate && ratio < 0.99)
            {
                // check if share matched the previous difficulty from before a vardiff retarget
                if (context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue)
                {
                    ratio = shareDiff / context.PreviousDifficulty.Value;

                    if (ratio < 0.99)
                    {
                        throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
                    }

                    // use previous difficulty
                    stratumDifficulty = context.PreviousDifficulty.Value;
                }

                else
                {
                    throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
                }
            }

            // Compute block hash
            Span <byte> blockHash = stackalloc byte[32];

            ComputeBlockHash(blobConverted, blockHash);

            var result = new Share
            {
                BlockHeight      = BlockTemplate.Height,
                IsBlockCandidate = isBlockCandidate,
                BlockHash        = blockHash.ToHexString(),
                Difficulty       = stratumDifficulty,
            };

            var blobHex  = blob.ToHexString();
            var blobHash = blockHash.ToHexString();

            return(result, blobHex, blobHash);
        }