示例#1
0
        protected virtual (Share Share, string BlockHex) ProcessShareInternal(
            StratumClient worker, string extraNonce2, uint nTime, uint nonce, uint?versionBits)
        {
            var context     = worker.ContextAs <BitcoinWorkerContext>();
            var extraNonce1 = context.ExtraNonce1;

            // build coinbase
            var         coinbase     = SerializeCoinbase(extraNonce1, extraNonce2);
            Span <byte> coinbaseHash = stackalloc byte[32];

            coinbaseHasher.Digest(coinbase, coinbaseHash);

            // hash block-header
            var         headerBytes = SerializeHeader(coinbaseHash, nTime, nonce, context.VersionRollingMask, versionBits);
            Span <byte> headerHash  = stackalloc byte[32];

            headerHasher.Digest(headerBytes, headerHash, (ulong)nTime, BlockTemplate, coin, networkParams);
            var headerValue = new uint256(headerHash);

            // calc share-diff
            var shareDiff         = (double)new BigRational(BitcoinConstants.Diff1, headerHash.ToBigInteger()) * shareMultiplier;
            var stratumDifficulty = context.Difficulty;
            var ratio             = shareDiff / stratumDifficulty;

            // check if the share meets the much harder block difficulty (block candidate)
            var isBlockCandidate = headerValue <= blockTargetValue;

            // 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})");
                }
            }

            var result = new Share
            {
                BlockHeight       = BlockTemplate.Height,
                NetworkDifficulty = Difficulty,
                Difficulty        = stratumDifficulty / shareMultiplier,
            };

            if (isBlockCandidate)
            {
                result.IsBlockCandidate = true;

                Span <byte> blockHash = stackalloc byte[32];
                blockHasher.Digest(headerBytes, blockHash, nTime);
                result.BlockHash = blockHash.ToHexString();

                var blockBytes = SerializeBlock(headerBytes, coinbase);
                var blockHex   = blockBytes.ToHexString();

                return(result, blockHex);
            }

            return(result, null);
        }
        protected virtual (Share Share, string BlockHex) ProcessShareInternal(StratumClient worker, string extraNonce,
                                                                              uint nTime, string nonce, string solution)
        {
            var context         = worker.ContextAs <BitcoinWorkerContext>();
            var solutionBytes   = solution.HexToByteArray();
            var extraNonceBytes = extraNonce.HexToByteArray();
            var nonceInt        = uint.Parse(nonce, NumberStyles.HexNumber);

            // hash block-header
            var headerBytes = SerializeHeader(nTime, extraNonceBytes, nonceInt);

            // hash block-header
            var headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray();
            var headerHash          = headerHasher.Digest(headerSolutionBytes);
            var headerValue         = new uint256(headerHash);

            // calc share-diff
            double shareDiff         = (double)new BigRational(chainConfig.Diff1b, headerHash.ToBigInteger());
            var    stratumDifficulty = context.Difficulty;
            var    ratio             = shareDiff / stratumDifficulty;

            // check if the share meets the much harder block difficulty (block candidate)
            var isBlockCandidate = headerValue < blockTarget.ToUInt256();

            // 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})");
                }
            }

            var result = new Share
            {
                BlockHeight       = BlockHeader.Height,
                NetworkDifficulty = Difficulty,
                Difficulty        = stratumDifficulty,
            };

            if (isBlockCandidate)
            {
                result.IsBlockCandidate = true;
                result.BlockHash        = headerValue.ToString();

                var blockHex = headerSolutionBytes.ToHexString();

                return(result, blockHex);
            }

            return(result, null);
        }
示例#3
0
        private (Share Share, string BlockHex) ProcessShareInternal(StratumClient worker, string nonce,
                                                                    uint nTime, string solution)
        {
            var context       = worker.ContextAs <BitcoinWorkerContext>();
            var solutionBytes = (Span <byte>)solution.HexToByteArray();

            // serialize block-header
            var headerBytes = SerializeHeader(nTime, nonce);

            // verify solution
            if (!solver.Verify(headerBytes, solutionBytes.Slice(networkParams.SolutionPreambleSize)))
            {
                throw new StratumException(StratumError.Other, "invalid solution");
            }

            // concat header and solution
            Span <byte> headerSolutionBytes = stackalloc byte[headerBytes.Length + solutionBytes.Length];

            headerBytes.CopyTo(headerSolutionBytes);
            solutionBytes.CopyTo(headerSolutionBytes.Slice(headerBytes.Length));

            // hash block-header
            Span <byte> headerHash = stackalloc byte[32];

            headerHasher.Digest(headerSolutionBytes, headerHash, (ulong)nTime);
            var headerValue = new uint256(headerHash);

            // calc share-diff
            var shareDiff         = (double)new BigRational(networkParams.Diff1BValue, headerHash.ToBigInteger());
            var stratumDifficulty = context.Difficulty;
            var ratio             = shareDiff / stratumDifficulty;

            // check if the share meets the much harder block difficulty (block candidate)
            var isBlockCandidate = headerValue <= blockTargetValue;

            // 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})");
                }
            }

            var result = new Share
            {
                BlockHeight       = BlockTemplate.Height,
                NetworkDifficulty = Difficulty,
                Difficulty        = stratumDifficulty,
            };

            if (isBlockCandidate)
            {
                var headerHashReversed = headerHash.ToNewReverseArray();

                result.IsBlockCandidate = true;
                result.BlockReward      = rewardToPool.ToDecimal(MoneyUnit.BTC);
                result.BlockHash        = headerHashReversed.ToHexString();

                var blockBytes = SerializeBlock(headerBytes, coinbaseInitial, solutionBytes);
                var blockHex   = blockBytes.ToHexString();

                return(result, blockHex);
            }

            return(result, null);
        }
示例#4
0
        protected virtual BitcoinShare ProcessShareInternal(StratumClient worker, string extraNonce2, uint nTime, uint nonce)
        {
            var context     = worker.GetContextAs <BitcoinWorkerContext>();
            var extraNonce1 = context.ExtraNonce1;

            // build coinbase
            var coinbase     = SerializeCoinbase(extraNonce1, extraNonce2);
            var coinbaseHash = coinbaseHasher.Digest(coinbase);

            // hash block-header
            var headerBytes = SerializeHeader(coinbaseHash, nTime, nonce);
            var headerHash  = headerHasher.Digest(headerBytes, (ulong)nTime);
            var headerValue = new uint256(headerHash);

            // calc share-diff
            var shareDiff         = (double)new BigRational(BitcoinConstants.Diff1, headerHash.ToBigInteger()) * shareMultiplier;
            var stratumDifficulty = context.Difficulty;
            var ratio             = shareDiff / stratumDifficulty;

            // check if the share meets the much harder block difficulty (block candidate)
            var isBlockCandidate = headerValue <= blockTargetValue;

            // 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})");
                }
            }

            var result = new BitcoinShare
            {
                BlockHeight       = BlockTemplate.Height,
                BlockReward       = rewardToPool.ToDecimal(MoneyUnit.BTC),
                NetworkDifficulty = Difficulty * shareMultiplier,
                Difficulty        = stratumDifficulty,
            };

            var blockBytes = SerializeBlock(headerBytes, coinbase);

            if (isBlockCandidate)
            {
                result.IsBlockCandidate = true;
                result.BlockHex         = blockBytes.ToHexString();
                result.BlockHash        = blockHasher.Digest(headerBytes, nTime).ToHexString();
            }

            return(result);
        }
示例#5
0
        private (Share Share, string nonce, string solution, string headerHash, string nTime) ProcessShareInternal(
            StratumClient worker, string nonce, string nTime, string solution)
        {
            var context       = worker.ContextAs <AionWorkerContext>();
            var solutionBytes = solution.HexToByteArray();
            // serialize block-header
            var headerBytes = SerializeHeader(nonce);

            // verify solution
            if (!equihash.Verify(headerBytes, solutionBytes))
            {
                throw new StratumException(StratumError.Other, "invalid solution");
            }

            // hash block-header
            var         headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray();
            Span <byte> headerHash          = stackalloc byte[32];

            headerHasher.Digest(headerSolutionBytes, headerHash);
            var headerHashReversed = headerHash.ToNewReverseArray();
            var headerValue        = headerHashReversed.ToBigInteger();
            var target             = new BigInteger(blockTarget.ToBytes());

            var isBlockCandidate = target > headerValue;

            logger.Debug(() => $"context.Difficulty:{context.Difficulty} Difficulty: {Difficulty}");
            // calc share-diff
            var stratumDifficulty = context.Difficulty > Difficulty ? Difficulty : context.Difficulty;
            var shareDiff         = stratumDifficulty;
            var ratio             = shareDiff / stratumDifficulty;

            var sentTargetInt  = new uint256(AionUtils.diffToTarget(context.Difficulty).HexToReverseByteArray());
            var sentTarget     = new BigInteger(sentTargetInt.ToBytes());
            var isLowDiffShare = sentTarget <= headerValue;

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

            var result = new Share
            {
                BlockHeight                 = (long)BlockTemplate.Height,
                IpAddress                   = worker.RemoteEndpoint?.Address?.ToString(),
                Miner                       = context.MinerName,
                Worker                      = context.WorkerName,
                UserAgent                   = context.UserAgent,
                NetworkDifficulty           = Difficulty,
                Difficulty                  = stratumDifficulty,
                IsBlockCandidate            = isBlockCandidate,
                TransactionConfirmationData = headerHash.ToHexString(),
            };

            if (isBlockCandidate)
            {
                // result.BlockReward = AionUtils.calculateReward((long) BlockTemplate.Height);
                result.BlockHash = headerHashReversed.ToHexString();
            }

            return(result, nonce, solution, BlockTemplate.HeaderHash, nTime);
        }
示例#6
0
        private async Task <(Share Share, string nonce, string solution, string headerHash, string nTime)> ProcessShareInternal(
            StratumClient worker, string nonce, string nTime, string solution)
        {
            var context       = worker.GetContextAs <AionWorkerContext>();
            var solutionBytes = solution.HexToByteArray();

            // serialize block-header
            var headerBytes = SerializeHeader(nonce);

            // verify solution
            if (!equihash.Verify210(headerBytes, solutionBytes))
            {
                throw new StratumException(StratumError.Other, "invalid solution");
            }

            // hash block-header
            var headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray();
            var headerHash          = headerHasher.Digest(headerSolutionBytes);
            var headerHashReversed  = headerHash.ToReverseArray();
            var headerBigInt        = headerHashReversed.ToBigInteger();
            var target = new BigInteger(blockTarget.ToBytes());

            var isBlockCandidate = target > headerBigInt;

            // calc share-diff
            var stratumDifficulty = context.Difficulty > Difficulty ? Difficulty : context.Difficulty;
            var shareDiff         = stratumDifficulty;
            var ratio             = shareDiff / stratumDifficulty;

            var sentTargetInt  = new uint256(AionUtils.diffToTarget(context.Difficulty).HexToByteArray().ReverseArray());
            var sentTarget     = new BigInteger(sentTargetInt.ToBytes());
            var isLowDiffShare = sentTarget <= headerBigInt;

            if (isLowDiffShare)
            {
                // Check if matched a previous varDiff before retarget
                if (context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue)
                {
                    var prevSentTargetInt = new uint256(AionUtils.diffToTarget(context.PreviousDifficulty.Value).HexToByteArray().ReverseArray());
                    var prevSentTargetBi  = new BigInteger(prevSentTargetInt.ToBytes());
                    if (prevSentTargetBi <= headerBigInt)
                    {
                        stratumDifficulty = context.PreviousDifficulty.Value;
                    }
                }
                else
                {
                    throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
                }
            }

            var result = new Share
            {
                BlockHeight                 = (long)BlockTemplate.Height,
                IpAddress                   = worker.RemoteEndpoint?.Address?.ToString(),
                Miner                       = context.MinerName,
                Worker                      = context.WorkerName,
                UserAgent                   = context.UserAgent,
                NetworkDifficulty           = Difficulty,
                Difficulty                  = stratumDifficulty,
                IsBlockCandidate            = isBlockCandidate,
                TransactionConfirmationData = headerHash.ToHexString(),
            };

            if (isBlockCandidate)
            {
                result.BlockReward = AionUtils.calculateReward((long)BlockTemplate.Height);
                result.BlockHash   = headerHashReversed.ToHexString();
            }

            return(result, nonce, solution, BlockTemplate.HeaderHash, nTime);
        }
示例#7
0
 public void Digest(ReadOnlySpan <byte> data, Span <byte> result, params object[] extra)
 {
     upstream.Digest(data, result, extra);
     result.Reverse();
 }