예제 #1
0
        private async Task <bool> SubmitBlockAsync(MoneroShare share)
        {
            var response = await daemon.ExecuteCmdAnyAsync <SubmitResponse>(MC.SubmitBlock, new[] { share.BlobHex });

            if (response.Error != null || response?.Response?.Status != "OK")
            {
                var error = response.Error?.Message ?? response.Response?.Status;

                logger.Warn(() => $"[{LogCat}] Block {share.BlockHeight} [{share.BlobHash.Substring(0, 6)}] submission failed with: {error}");
                return(false);
            }

            return(true);
        }
예제 #2
0
        public MoneroShare ProcessShare(string nonce, uint workerExtraNonce, string workerHash, StratumClient <MoneroWorkerContext> 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");

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

            // clone template
            var blob = new byte[blobTemplate.Length];

            Buffer.BlockCopy(blobTemplate, 0, blob, 0, blobTemplate.Length);

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

            Buffer.BlockCopy(extraNonceBytes, 0, blob, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

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

            Buffer.BlockCopy(nonceBytes, 0, blob, MoneroConstants.BlobNonceOffset, nonceBytes.Length);

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

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

            // hash it
            var hashBytes = LibCryptonote.CryptonightHashSlow(blobConverted);
            var hash      = hashBytes.ToHexString();

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

            // check difficulty
            var headerValue = System.Numerics.BigInteger.Parse("0" + hashBytes.ToReverseArray().ToHexString(), NumberStyles.HexNumber);

            var shareDiff         = (double)new BigRational(MoneroConstants.Diff1b, headerValue);
            var stratumDifficulty = worker.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 (worker.Context.VarDiff?.LastUpdate != null && worker.Context.PreviousDifficulty.HasValue)
                {
                    ratio = shareDiff / worker.Context.PreviousDifficulty.Value;

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

                    // use previous difficulty
                    stratumDifficulty = worker.Context.PreviousDifficulty.Value;
                }

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

            var result = new MoneroShare
            {
                BlockHeight       = BlockTemplate.Height,
                IsBlockCandidate  = isBlockCandidate,
                BlobHex           = blob.ToHexString(),
                BlobHash          = ComputeBlockHash(blobConverted).ToHexString(),
                StratumDifficulty = stratumDifficulty,
            };

            return(result);
        }
예제 #3
0
        public MoneroShare ProcessShare(string nonce, uint workerExtraNonce, string workerHash, double stratumDifficulty)
        {
            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>(extraNonce != 0, $"{nameof(extraNonce)} must not be empty");

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

            // clone template
            var blob = new byte[blobTemplate.Length];

            Buffer.BlockCopy(blobTemplate, 0, blob, 0, blobTemplate.Length);

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

            Buffer.BlockCopy(extraNonceBytes, 0, blob, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

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

            Buffer.BlockCopy(nonceBytes, 0, blob, MoneroConstants.BlobNonceOffset, nonceBytes.Length);

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

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

            // hash it
            var hashBytes = LibCryptonote.CryptonightHashSlow(blobConverted);
            var hash      = hashBytes.ToHexString();

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

            // check difficulty
            var headerValue = new System.Numerics.BigInteger(hashBytes);
            var shareDiff   = (double)new BigRational(MoneroConstants.Diff1b, headerValue);
            var ratio       = shareDiff / stratumDifficulty;

            // test if share meets at least workers current difficulty
            if (ratio < 0.99)
            {
                throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
            }

            // valid share, check if the share also meets the much harder block difficulty (block candidate)
            var isBlockCandidate = shareDiff >= BlockTemplate.Difficulty;

            var result = new MoneroShare
            {
                BlockHeight      = BlockTemplate.Height,
                IsBlockCandidate = isBlockCandidate,
                BlobHex          = blob.ToHexString(),
                BlobHash         = ComputeBlockHash(blobConverted).ToHexString()
            };

            return(result);
        }