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) { 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); }
private void EnsureInitialWorkSent(StratumClient client) { var context = client.GetContextAs <AionWorkerContext>(); lock (context) { if (context.IsAuthorized && context.IsAuthorized && !context.IsInitialWorkSent) { context.IsInitialWorkSent = true; string newTarget = AionUtils.diffToTarget(context.Difficulty); // update the difficulty (((object[])currentJobParams)[2]) = newTarget; // send intial update client.Notify(AionStratumMethods.MiningNotify, currentJobParams); } } }
private void EnsureInitialWorkSent(StratumClient client) { var context = client.GetContextAs <AionWorkerContext>(); lock (context) { if (context.IsAuthorized && !context.IsInitialWorkSent) { context.IsInitialWorkSent = true; string newTarget = AionUtils.diffToTarget(context.Difficulty); ArrayList arrayTarget = new ArrayList(); arrayTarget.Add(newTarget); // send intial update client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, arrayTarget); } } }
protected override void OnVarDiffUpdate(StratumClient client, double newDiff) { base.OnVarDiffUpdate(client, newDiff); // apply immediately and notify client var context = client.GetContextAs <AionWorkerContext>(); if (context.HasPendingDifficulty) { context.ApplyPendingDifficulty(); string newTarget = AionUtils.diffToTarget(newDiff); ArrayList targetArray = new ArrayList(); targetArray.Add(newTarget); // send job client.Notify(AionStratumMethods.SetDifficulty, new object[] { context.Difficulty }); client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, targetArray); } }
private void OnNewJob(object jobParams) { currentJobParams = jobParams; logger.Info(() => $"[{LogCat}] Broadcasting job"); ForEachClient(client => { var context = client.GetContextAs <AionWorkerContext>(); if (context.IsSubscribed && context.IsAuthorized && context.IsInitialWorkSent) { // check alive var lastActivityAgo = clock.Now - context.LastActivity; if (poolConfig.ClientConnectionTimeout > 0 && lastActivityAgo.TotalSeconds > poolConfig.ClientConnectionTimeout) { logger.Info(() => $"[{LogCat}] [{client.ConnectionId}] Booting zombie-worker (idle-timeout exceeded)"); DisconnectClient(client); return; } // varDiff: if the client has a pending difficulty change, apply it now if (context.ApplyPendingDifficulty()) { client.Notify(AionStratumMethods.SetDifficulty, new object[] { context.Difficulty }); } string newTarget = AionUtils.diffToTarget(context.Difficulty); ArrayList arrayTarget = new ArrayList(); arrayTarget.Add(newTarget); client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, arrayTarget); } }); }