public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig) { extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <EthereumPoolConfigExtra>(); // extract standard daemon endpoints daemonEndpoints = poolConfig.Daemons .Where(x => string.IsNullOrEmpty(x.Category)) .ToArray(); base.Configure(poolConfig, clusterConfig); if (poolConfig.EnableInternalStratum == true) { // ensure dag location is configured var dagDir = !string.IsNullOrEmpty(extraPoolConfig?.DagDir) ? Environment.ExpandEnvironmentVariables(extraPoolConfig.DagDir) : Dag.GetDefaultDagDirectory(); // create it if necessary Directory.CreateDirectory(dagDir); // setup ethash ethash = new EthashFull(3, dagDir); } }
public override void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig) { extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <EthereumPoolConfigExtra>(); daemonEndpoints = poolConfig.Daemons .Where(x => string.IsNullOrEmpty(x.Category)) .ToArray(); base.Configure(poolConfig, clusterConfig); if (poolConfig.EnableInternalStratum == true) { var dagDir = !string.IsNullOrEmpty(extraPoolConfig?.DagDir) ? Environment.ExpandEnvironmentVariables(extraPoolConfig.DagDir) : Dag.GetDefaultDagDirectory(); Directory.CreateDirectory(dagDir); ethash = new EthashFull(3, dagDir); } }
public async Task <EthereumShare> ProcessShareAsync(StratumClient worker, string nonce, EthashFull ethash) { // duplicate nonce? lock (workerNonces) { RegisterNonce(worker, nonce); } // assemble full-nonce var context = worker.GetContextAs <EthereumWorkerContext>(); var fullNonceHex = context.ExtraNonce1 + nonce; var fullNonce = ulong.Parse(fullNonceHex, NumberStyles.HexNumber); // get dag for block var dag = await ethash.GetDagAsync(BlockTemplate.Height); // compute if (!dag.Compute(BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) { throw new StratumException(StratumError.MinusOne, "bad hash"); } resultBytes.ReverseArray(); // test if share meets at least workers current difficulty var resultValue = new uint256(resultBytes); var resultValueBig = resultBytes.ToBigInteger(); var shareDiff = (double)BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32; var stratumDifficulty = context.Difficulty; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = resultValue <= blockTarget; 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})"); } } // create share var share = new EthereumShare { BlockHeight = (long)BlockTemplate.Height, IpAddress = worker.RemoteEndpoint?.Address?.ToString(), Miner = context.MinerName, Worker = context.WorkerName, UserAgent = context.UserAgent, FullNonceHex = "0x" + fullNonceHex, HeaderHash = BlockTemplate.Header, MixHash = mixDigest.ToHexString(true), IsBlockCandidate = isBlockCandidate, Difficulty = stratumDifficulty * EthereumConstants.Pow2x32, BlockHash = mixDigest.ToHexString(true) // OW: is this correct? }; if (share.IsBlockCandidate) { share.TransactionConfirmationData = $"{mixDigest.ToHexString(true)}:{share.FullNonceHex}"; } return(share); }
public async ValueTask <(Share Share, string FullNonceHex, string HeaderHash, string MixHash)> ProcessShareAsync( StratumClient worker, string nonce, EthashFull ethash, CancellationToken ct) { // duplicate nonce? lock (workerNonces) { RegisterNonce(worker, nonce); } // assemble full-nonce var context = worker.ContextAs <EthereumWorkerContext>(); var fullNonceHex = nonce.StartsWith("0x") ? nonce.Substring(2) : nonce; if (context.IsNiceHashClient && !string.IsNullOrEmpty(context.ExtraNonce1)) { fullNonceHex = context.ExtraNonce1 + fullNonceHex; } if (!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce)) { throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); } // get dag for block var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger, ct); // compute if (!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) { throw new StratumException(StratumError.MinusOne, "bad hash"); } // test if share meets at least workers current difficulty resultBytes.ReverseInPlace(); var resultValue = new uint256(resultBytes); var resultValueBig = resultBytes.AsSpan().ToBigInteger(); var shareDiff = (double)BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32; var stratumDifficulty = context.Difficulty; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = resultValue <= blockTarget; 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})"); } } // create share var share = new Share { BlockHeight = (long)BlockTemplate.Height, IpAddress = worker.RemoteEndpoint?.Address?.ToString(), Miner = context.Miner, Worker = context.Worker, UserAgent = context.UserAgent, IsBlockCandidate = isBlockCandidate, Difficulty = stratumDifficulty * EthereumConstants.Pow2x32, BlockHash = mixDigest.ToHexString(true) }; if (share.IsBlockCandidate) { fullNonceHex = "0x" + fullNonceHex; var headerHash = BlockTemplate.Header; var mixHash = mixDigest.ToHexString(true); share.TransactionConfirmationData = $"{mixDigest.ToHexString(true)}:{fullNonceHex}"; return(share, fullNonceHex, headerHash, mixHash); } return(share, null, null, null); }
public async Task <(Share Share, string FullNonceHex, string HeaderHash, string MixHash)> ProcessShareAsync(StratumClient worker, string nonce, EthashFull ethash) { lock (workerNonces) { RegisterNonce(worker, nonce); } var context = worker.GetContextAs <EthereumWorkerContext>(); var fullNonceHex = context.ExtraNonce1 + nonce; if (!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce)) { throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); } var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger); if (!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) { throw new StratumException(StratumError.MinusOne, "bad hash"); } resultBytes.ReverseArray(); var resultValue = new uint256(resultBytes); var resultValueBig = resultBytes.ToBigInteger(); var shareDiff = (double)BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32; var stratumDifficulty = context.Difficulty; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = resultValue <= blockTarget; 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 share = new Share { BlockHeight = (long)BlockTemplate.Height, IpAddress = worker.RemoteEndpoint?.Address?.ToString(), Miner = context.MinerName, Worker = context.WorkerName, UserAgent = context.UserAgent, IsBlockCandidate = isBlockCandidate, Difficulty = stratumDifficulty * EthereumConstants.Pow2x32, BlockHash = mixDigest.ToHexString(true) }; if (share.IsBlockCandidate) { fullNonceHex = "0x" + fullNonceHex; var headerHash = BlockTemplate.Header; var mixHash = mixDigest.ToHexString(true); share.TransactionConfirmationData = $"{mixDigest.ToHexString(true)}:{fullNonceHex}"; return(share, fullNonceHex, headerHash, mixHash); } return(share, null, null, null); }
public async Task <(Share Share, string FullNonceHex, string HeaderHash, string MixHash)> ProcessShareAsync(StratumClient worker, string nonce, EthashFull ethash) { // duplicate nonce? //lock (workerNonces) //{ // RegisterNonce(worker, nonce); //} // assemble full-nonce var context = worker.GetContextAs <EthereumWorkerContext>(); var fullNonceHex = nonce.StartsWith("0x") ? nonce.Substring(2) : nonce; if (context.IsNiceHashClient && !string.IsNullOrEmpty(context.ExtraNonce1)) { fullNonceHex = context.ExtraNonce1 + fullNonceHex; } if (!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce)) { throw new StratumException(StratumError.Other, "bad nonce " + fullNonceHex); } // get dag for block var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger); // compute if (!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) { throw new StratumException(StratumError.Other, "bad hash"); } resultBytes.ReverseArray(); // test if share meets at least workers current difficulty var resultValue = new uint256(resultBytes); var resultValueBig = resultBytes.ToBigInteger(); var shareDiff = (double)BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig); var stratumDifficulty = context.Difficulty * EthereumConstants.StratumDiffFactor; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = resultValue <= blockTarget; if (!isBlockCandidate && ratio < 0.98) { throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); } // create share var share = new Share { BlockHeight = (long)BlockTemplate.Height, IpAddress = worker.RemoteEndpoint?.Address?.ToString(), Miner = context.MinerName, Worker = context.WorkerName, UserAgent = context.UserAgent, IsBlockCandidate = isBlockCandidate, Difficulty = stratumDifficulty, BlockHash = mixDigest.ToHexString(true) }; if (share.IsBlockCandidate) { var headerHash = BlockTemplate.Header; var mixHash = mixDigest.ToHexString(true); share.TransactionConfirmationData = $"{mixDigest.ToHexString(true)}:{nonce}"; return(share, fullNonceHex, headerHash, mixHash); } return(share, null, null, null); }