Пример #1
0
        private async Task OnSubmitAsync(StratumClient <MoneroWorkerContext> client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;

            try
            {
                if (request.Id == null)
                {
                    throw new StratumException(StratumError.MinusOne, "missing request id");
                }

                // check age of submission (aged submissions are usually caused by high server load)
                var requestAge = clock.UtcNow - tsRequest.Timestamp.UtcDateTime;

                if (requestAge > maxShareAge)
                {
                    logger.Debug(() => $"[{LogCat}] [{client.ConnectionId}] Dropping stale share submission request (not client's fault)");
                    return;
                }

                // check request
                var submitRequest = request.ParamsAs <MoneroSubmitShareRequest>();

                // validate worker
                if (client.ConnectionId != submitRequest?.WorkerId || !client.Context.IsAuthorized)
                {
                    throw new StratumException(StratumError.MinusOne, "unauthorized");
                }

                // recognize activity
                client.Context.LastActivity = clock.UtcNow;

                MoneroWorkerJob job;

                lock (client.Context)
                {
                    var jobId = submitRequest?.JobId;

                    if (string.IsNullOrEmpty(jobId) ||
                        (job = client.Context.ValidJobs.FirstOrDefault(x => x.Id == jobId)) == null)
                    {
                        throw new StratumException(StratumError.MinusOne, "invalid jobid");
                    }
                }

                // dupe check
                var nonceLower = submitRequest.Nonce.ToLower();

                lock (job)
                {
                    if (job.Submissions.Contains(nonceLower))
                    {
                        throw new StratumException(StratumError.MinusOne, "duplicate share");
                    }

                    job.Submissions.Add(nonceLower);
                }

                var poolEndpoint = poolConfig.Ports[client.PoolEndpoint.Port];

                var share = await manager.SubmitShareAsync(client, submitRequest, job, poolEndpoint.Difficulty);

                // success
                client.Respond(new MoneroResponseBase(), request.Id);
                shareSubject.OnNext(Tuple.Create((object)client, share));

                logger.Info(() => $"[{LogCat}] [{client.ConnectionId}] Share accepted: D={Math.Round(share.Difficulty, 3)}");

                // update pool stats
                if (share.IsBlockCandidate)
                {
                    poolStats.LastPoolBlockTime = clock.UtcNow;
                }

                // update client stats
                client.Context.Stats.ValidShares++;
            }

            catch (StratumException ex)
            {
                client.RespondError(ex.Code, ex.Message, request.Id, false);

                // update client stats
                client.Context.Stats.InvalidShares++;
                logger.Info(() => $"[{LogCat}] [{client.ConnectionId}] Share rejected: {ex.Message}");

                // banning
                if (poolConfig.Banning?.Enabled == true)
                {
                    ConsiderBan(client, client.Context, poolConfig.Banning);
                }
            }
        }
Пример #2
0
        private async Task OnSubmitAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <MoneroWorkerContext>();

            try
            {
                if (request.Id == null)
                {
                    throw new StratumException(StratumError.MinusOne, "missing request id");
                }

                // check age of submission (aged submissions are usually caused by high server load)
                var requestAge = clock.Now - tsRequest.Timestamp.UtcDateTime;

                if (requestAge > maxShareAge)
                {
                    logger.Debug(() => $"[{client.ConnectionId}] Dropping stale share submission request (not client's fault)");
                    return;
                }

                // check request
                var submitRequest = request.ParamsAs <MoneroSubmitShareRequest>();

                // validate worker
                if (client.ConnectionId != submitRequest?.WorkerId || !context.IsAuthorized)
                {
                    throw new StratumException(StratumError.MinusOne, "unauthorized");
                }

                // recognize activity
                context.LastActivity = clock.Now;

                MoneroWorkerJob job;

                lock (context)
                {
                    var jobId = submitRequest?.JobId;

                    if ((job = context.FindJob(jobId)) == null)
                    {
                        throw new StratumException(StratumError.MinusOne, "invalid jobid");
                    }
                }

                // dupe check
                var nonceLower = submitRequest.Nonce.ToLower();

                lock (job)
                {
                    if (job.Submissions.Contains(nonceLower))
                    {
                        throw new StratumException(StratumError.MinusOne, "duplicate share");
                    }

                    job.Submissions.Add(nonceLower);
                }

                var poolEndpoint = poolConfig.Ports[client.PoolEndpoint.Port];

                var share = await manager.SubmitShareAsync(client, submitRequest, job, poolEndpoint.Difficulty);

                client.Respond(new MoneroResponseBase(), request.Id);

                // publish
                messageBus.SendMessage(new ClientShare(client, share));

                // telemetry
                PublishTelemetry(TelemetryCategory.Share, clock.Now - tsRequest.Timestamp.UtcDateTime, true);

                logger.Info(() => $"[{client.ConnectionId}] Share accepted: D={Math.Round(share.Difficulty, 3)}");

                // update pool stats
                if (share.IsBlockCandidate)
                {
                    poolStats.LastPoolBlockTime = clock.Now;
                }

                // update client stats
                context.Stats.ValidShares++;
                UpdateVarDiff(client);
            }

            catch (StratumException ex)
            {
                client.RespondError(ex.Code, ex.Message, request.Id, false);

                // telemetry
                PublishTelemetry(TelemetryCategory.Share, clock.Now - tsRequest.Timestamp.UtcDateTime, false);

                // update client stats
                context.Stats.InvalidShares++;
                logger.Info(() => $"[{client.ConnectionId}] Share rejected: {ex.Message}");

                // banning
                ConsiderBan(client, context, poolConfig.Banning);
            }
        }