protected virtual (Share Share, string BlockHex) ProcessShareInternal(StratumClient worker, string nonce, uint nTime, string solution) { var context = worker.GetContextAs<BitcoinWorkerContext>(); var solutionBytes = solution.HexToByteArray(); var headerBytes = SerializeHeader(nTime, nonce); if (!equihash.Verify(headerBytes, solutionBytes.Skip(3).ToArray())) throw new StratumException(StratumError.Other, "invalid solution"); var headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray(); var headerHash = headerHasher.Digest(headerSolutionBytes, (ulong) nTime); var headerHashReversed = headerHash.ToReverseArray(); var headerValue = new uint256(headerHash); var shareDiff = (double) new BigRational(coinbaseTxConfig.Diff1b, headerHash.ToBigInteger()) * shareMultiplier; var stratumDifficulty = context.Difficulty; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = headerValue <= blockTargetValue; if (!isBlockCandidate && ratio < 0.99) { 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})"); 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) { 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); }
protected virtual BitcoinShare ProcessShareInternal(StratumClient <BitcoinWorkerContext> worker, string nonce, uint nTime, string solution) { var solutionBytes = solution.HexToByteArray(); // serialize block-header var headerBytes = SerializeHeader(nTime, nonce); // 144 bytes (doesn't contain soln) // verify solution if (!equihash.Verify(headerBytes, solutionBytes.Skip(3).ToArray())) // skip preamble (3 bytes) { throw new StratumException(StratumError.Other, "invalid solution"); } // hash block-header var headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray(); var headerHash = headerHasher.Digest(headerSolutionBytes, (ulong)nTime); var headerValue = BigInteger.Parse("00" + headerHash.ReverseArray().ToHexString(), NumberStyles.HexNumber); // calc share-diff var shareDiff = (double)new BigRational(ZCashConstants.Diff1b, headerValue) * shareMultiplier; var stratumDifficulty = worker.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 (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 BitcoinShare { BlockHeight = BlockTemplate.Height, IsBlockCandidate = isBlockCandidate }; var blockBytes = SerializeBlock(headerBytes, coinbaseInitial, solutionBytes); result.BlockHex = blockBytes.ToHexString(); result.BlockHash = headerHash.ToHexString(); result.BlockHeight = BlockTemplate.Height; result.BlockReward = rewardToPool.ToDecimal(MoneyUnit.BTC); result.Difficulty = stratumDifficulty; return(result); }
protected virtual (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); }
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); }