コード例 #1
0
        protected override async Task OnRequestAsync(StratumClient client,
                                                     Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <MoneroWorkerContext>();

            switch (request.Method)
            {
            case MoneroStratumMethods.Login:
                OnLogin(client, tsRequest);
                break;

            case MoneroStratumMethods.GetJob:
                OnGetJob(client, tsRequest);
                break;

            case MoneroStratumMethods.Submit:
                await OnSubmitAsync(client, tsRequest);

                break;

            case MoneroStratumMethods.KeepAlive:
                // recognize activity
                context.LastActivity = clock.Now;
                break;

            default:
                logger.Debug(() => $"[{LogCat}] [{client.ConnectionId}] Unsupported RPC request: {JsonConvert.SerializeObject(request, serializerSettings)}");

                client.RespondError(StratumError.Other, $"Unsupported request {request.Method}", request.Id);
                break;
            }
        }
コード例 #2
0
        private async Task OnSuggestDifficultyAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <BitcoinWorkerContext>();

            // acknowledge
            await client.RespondAsync(true, request.Id);

            try
            {
                var requestedDiff = (double)Convert.ChangeType(request.Params, TypeCode.Double);

                // client may suggest higher-than-base difficulty, but not a lower one
                var poolEndpoint = poolConfig.Ports[client.PoolEndpoint.Port];

                if (requestedDiff > poolEndpoint.Difficulty)
                {
                    context.SetDifficulty(requestedDiff);
                    await client.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { context.Difficulty });

                    logger.Info(() => $"[{client.ConnectionId}] Difficulty set to {requestedDiff} as requested by miner");
                }
            }

            catch (Exception ex)
            {
                logger.Error(ex, () => $"Unable to convert suggested difficulty {request.Params}");
            }
        }
コード例 #3
0
        private void OnGetJob(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <MoneroWorkerContext>();

            if (request.Id == null)
            {
                client.RespondError(StratumError.MinusOne, "missing request id", request.Id);
                return;
            }

            var getJobRequest = request.ParamsAs <MoneroGetJobRequest>();

            // validate worker
            if (client.ConnectionId != getJobRequest?.WorkerId || !context.IsAuthorized)
            {
                client.RespondError(StratumError.MinusOne, "unauthorized", request.Id);
                return;
            }

            // respond
            var job = CreateWorkerJob(client);

            client.Respond(job, request.Id);
        }
コード例 #4
0
        private async Task OnConfigureMiningAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <BitcoinWorkerContext>();

            var requestParams   = request.ParamsAs <JToken[]>();
            var extensions      = requestParams[0].ToObject <string[]>();
            var extensionParams = requestParams[1].ToObject <Dictionary <string, JToken> >();
            var result          = new Dictionary <string, object>();

            foreach (var extension in extensions)
            {
                switch (extension)
                {
                case BitcoinStratumExtensions.VersionRolling:
                    ConfigureVersionRolling(client, context, extensionParams, result);
                    break;

                case BitcoinStratumExtensions.MinimumDiff:
                    ConfigureMinimumDiff(client, context, extensionParams, result);
                    break;
                }
            }

            await client.RespondAsync(result, request.Id);
        }
コード例 #5
0
        private CryptonoteJobParams CreateWorkerJob(StratumClient client)
        {
            var context = client.ContextAs <CryptonoteWorkerContext>();
            var job     = new CryptonoteWorkerJob(NextJobId(), context.Difficulty);

            manager.PrepareWorkerJob(job, out var blob, out var target);

            // should never happen
            if (string.IsNullOrEmpty(blob) || string.IsNullOrEmpty(blob))
            {
                return(null);
            }

            var result = new CryptonoteJobParams
            {
                JobId  = job.Id,
                Blob   = blob,
                Target = target
            };

            // update context
            lock (context)
            {
                context.AddJob(job);
            }

            return(result);
        }
コード例 #6
0
        protected override void OnSubscribe(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <BitcoinWorkerContext>();

            if (request.Id == null)
            {
                client.RespondError(StratumError.Other, "missing request id", request.Id);
                return;
            }

            var requestParams = request.ParamsAs <string[]>();

            var data = new object[]
            {
                client.ConnectionId,
            }
            .Concat(manager.GetSubscriberData(client))
            .ToArray();

            client.Respond(data, request.Id);

            // setup worker context
            context.IsSubscribed = true;
            context.UserAgent    = requestParams?.Length > 0 ? requestParams[0].Trim() : null;
        }
コード例 #7
0
        private void EnsureInitialWorkSent(StratumClient client)
        {
            var       context         = client.ContextAs <AionWorkerContext>();
            ArrayList arrayTarget     = new ArrayList();
            var       sendInitialWork = false;

            lock (context)
            {
                if (context.IsSubscribed && context.IsAuthorized && !context.IsInitialWorkSent)
                {
                    context.IsInitialWorkSent = true;
                    string newTarget = AionUtils.diffToTarget(context.Difficulty);
                    arrayTarget.Add(newTarget);
                    sendInitialWork = true;
                }
            }

            if (sendInitialWork)
            {
                // send intial update
                // await client.NotifyAsync(AionStratumMethods.MiningNotify, currentJobParams);
                // await client.NotifyAsync(AionStratumMethods.SetTarget, arrayTarget);
                client.Notify(AionStratumMethods.MiningNotify, currentJobParams);
                client.Notify(AionStratumMethods.SetTarget, arrayTarget);
            }
        }
コード例 #8
0
        protected virtual async Task OnSubscribeAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;

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

            var context       = client.ContextAs <BitcoinWorkerContext>();
            var requestParams = request.ParamsAs <string[]>();

            var data = new object[]
            {
                new object[]
                {
                    new object[] { BitcoinStratumMethods.SetDifficulty, client.ConnectionId },
                    new object[] { BitcoinStratumMethods.MiningNotify, client.ConnectionId }
                }
            }
            .Concat(manager.GetSubscriberData(client))
            .ToArray();

            await client.RespondAsync(data, request.Id);

            // setup worker context
            context.IsSubscribed = true;
            context.UserAgent    = requestParams?.Length > 0 ? requestParams[0].Trim() : null;

            // send intial update
            await client.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { context.Difficulty });

            await client.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
        }
コード例 #9
0
ファイル: EquihashPool.cs プロジェクト: seperatis/miningcore
        protected async Task OnSubscribeAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <BitcoinWorkerContext>();

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

            var requestParams = request.ParamsAs <string[]>();

            var data = new object[]
            {
                client.ConnectionId,
            }
            .Concat(manager.GetSubscriberData(client))
            .ToArray();

            await client.RespondAsync(data, request.Id);

            // setup worker context
            context.IsSubscribed = true;
            context.UserAgent    = requestParams?.Length > 0 ? requestParams[0].Trim() : null;
        }
コード例 #10
0
ファイル: BitcoinPool.cs プロジェクト: edtrade/miningcore
        protected virtual async Task OnAuthorizeAsync(StratumClient client, Timestamped<JsonRpcRequest> tsRequest, CancellationToken ct)
        {
            var request = tsRequest.Value;

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

            var context = client.ContextAs<BitcoinWorkerContext>();
            var requestParams = request.ParamsAs<string[]>();
            var workerValue = requestParams?.Length > 0 ? requestParams[0] : null;
            var password = requestParams?.Length > 1 ? requestParams[1] : null;
            var passParts = password?.Split(PasswordControlVarsSeparator);

            // extract worker/miner
            var split = workerValue?.Split('.');
            var minerName = split?.FirstOrDefault()?.Trim();
            var workerName = split?.Skip(1).FirstOrDefault()?.Trim() ?? string.Empty;

            // assumes that workerName is an address
            context.IsAuthorized = !string.IsNullOrEmpty(minerName) && await manager.ValidateAddressAsync(minerName, ct);
            context.Miner = minerName;
            context.Worker = workerName;

            if (context.IsAuthorized)
            {
                // respond
                await client.RespondAsync(context.IsAuthorized, request.Id);

                // log association
                logger.Info(() => $"[{client.ConnectionId}] Authorized worker {workerValue}");

                // extract control vars from password
                var staticDiff = GetStaticDiffFromPassparts(passParts);
                if (staticDiff.HasValue &&
                    (context.VarDiff != null && staticDiff.Value >= context.VarDiff.Config.MinDiff ||
                        context.VarDiff == null && staticDiff.Value > context.Difficulty))
                {
                    context.VarDiff = null; // disable vardiff
                    context.SetDifficulty(staticDiff.Value);

                    logger.Info(() => $"[{client.ConnectionId}] Setting static difficulty of {staticDiff.Value}");

                    await client.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { context.Difficulty });
                }
            }

            else
            {
                // respond
                await client.RespondErrorAsync(StratumError.UnauthorizedWorker, "Authorization failed", request.Id, context.IsAuthorized);

                // issue short-time ban if unauthorized to prevent DDos on daemon (validateaddress RPC)
                logger.Info(() => $"[{client.ConnectionId}] Banning unauthorized worker for 60 sec");

                banManager.Ban(client.RemoteEndpoint.Address, TimeSpan.FromSeconds(60));

                DisconnectClient(client);
            }
        }
コード例 #11
0
        protected virtual Task OnVarDiffUpdateAsync(StratumClient client, double newDiff)
        {
            var context = client.ContextAs <WorkerContextBase>();

            context.EnqueueNewDifficulty(newDiff);

            return(Task.FromResult(true));
        }
コード例 #12
0
        public async ValueTask <Share> SubmitShareAsync(StratumClient worker, CryptonoteSubmitShareRequest request, CryptonoteWorkerJob workerJob, double stratumDifficultyBase, CancellationToken ct)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.RequiresNonNull(request, nameof(request));

            logger.Debug(() => $"{ worker.ConnectionId } {request}");

            var context = worker.ContextAs <CryptonoteWorkerContext>();

            var job = currentJob;

            if (workerJob.Height != job?.BlockTemplate.Height)
            {
                throw new StratumException(StratumError.MinusOne, "block expired");
            }

            // validate & process share
            var(share, blobHex) = job.ProcessShare(request.Nonce, workerJob.ExtraNonce, request.Hash, worker);

            // enrich share with common data
            share.PoolId            = poolConfig.Id;
            share.IpAddress         = worker.RemoteEndpoint.Address.ToString();
            share.Miner             = context.Miner;
            share.Worker            = context.Worker;
            share.UserAgent         = context.UserAgent;
            share.Source            = clusterConfig.ClusterName;
            share.NetworkDifficulty = job.BlockTemplate.Difficulty;
            share.Created           = clock.UtcNow;

            // if block candidate, submit & check if accepted by network
            if (share.IsBlockCandidate)
            {
                logger.Info(() => $"Submitting block {share.BlockHeight} [{share.BlockHash.Substring(0, 6)}]");

                share.IsBlockCandidate = await SubmitBlockAsync(share, blobHex, share.BlockHash);

                if (share.IsBlockCandidate)
                {
                    logger.Info(() => $"Daemon accepted block {share.BlockHeight} [{share.BlockHash.Substring(0, 6)}] submitted by {context.Miner}");

                    OnBlockFound();

                    share.TransactionConfirmationData = share.BlockHash;
                }

                else
                {
                    // clear fields that no longer apply
                    share.TransactionConfirmationData = null;
                }
            }

            return(share);
        }
コード例 #13
0
        public async Task <Share> SubmitShareAsync(StratumClient worker,
                                                   MoneroSubmitShareRequest request, MoneroWorkerJob workerJob, double stratumDifficultyBase)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.RequiresNonNull(request, nameof(request));

            logger.LogInvoke(new[] { worker.ConnectionId });
            var context = worker.ContextAs <MoneroWorkerContext>();

            var job = currentJob;

            if (workerJob.Height != job?.BlockTemplate.Height)
            {
                throw new StratumException(StratumError.MinusOne, "block expired");
            }

            // validate & process
            var(share, blobHex, blobHash) = job.ProcessShare(request.Nonce, workerJob.ExtraNonce, request.Hash, worker);

            // enrich share with common data
            share.PoolId            = poolConfig.Id;
            share.IpAddress         = worker.RemoteEndpoint.Address.ToString();
            share.Miner             = context.MinerName;
            share.Worker            = context.WorkerName;
            share.PayoutInfo        = context.PaymentId;
            share.UserAgent         = context.UserAgent;
            share.Source            = clusterConfig.ClusterName;
            share.NetworkDifficulty = job.BlockTemplate.Difficulty;
            share.Created           = clock.Now;

            // if block candidate, submit & check if accepted by network
            if (share.IsBlockCandidate)
            {
                logger.Info(() => $"Submitting block {share.BlockHeight} [{blobHash.Substring(0, 6)}]");

                share.IsBlockCandidate = await SubmitBlockAsync(share, blobHex, blobHash);

                if (share.IsBlockCandidate)
                {
                    logger.Info(() => $"Daemon accepted block {share.BlockHeight} [{blobHash.Substring(0, 6)}] submitted by {context.MinerName}");
                    blockSubmissionSubject.OnNext(Unit.Default);

                    share.TransactionConfirmationData = blobHash;
                }

                else
                {
                    // clear fields that no longer apply
                    share.TransactionConfirmationData = null;
                }
            }

            return(share);
        }
コード例 #14
0
        public virtual (Share Share, string BlockHex) ProcessShare(StratumClient worker,
                                                                   string extraNonce2, string nTime, string nonce, string versionBits = null)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(extraNonce2), $"{nameof(extraNonce2)} must not be empty");
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(nTime), $"{nameof(nTime)} must not be empty");
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(nonce), $"{nameof(nonce)} must not be empty");

            var context = worker.ContextAs <BitcoinWorkerContext>();

            // validate nTime
            if (nTime.Length != 8)
            {
                throw new StratumException(StratumError.Other, "incorrect size of ntime");
            }

            var nTimeInt = uint.Parse(nTime, NumberStyles.HexNumber);

            if (nTimeInt < BlockTemplate.CurTime || nTimeInt > ((DateTimeOffset)clock.Now).ToUnixTimeSeconds() + 7200)
            {
                throw new StratumException(StratumError.Other, "ntime out of range");
            }

            // validate nonce
            if (nonce.Length != 8)
            {
                throw new StratumException(StratumError.Other, "incorrect size of nonce");
            }

            var nonceInt = uint.Parse(nonce, NumberStyles.HexNumber);

            // validate version-bits (overt ASIC boost)
            uint versionBitsInt = 0;

            if (context.VersionRollingMask.HasValue && versionBits != null)
            {
                versionBitsInt = uint.Parse(versionBits, NumberStyles.HexNumber);

                // enforce that only bits covered by current mask are changed by miner
                if ((versionBitsInt & ~context.VersionRollingMask.Value) != 0)
                {
                    throw new StratumException(StratumError.Other, "rolling-version mask violation");
                }
            }

            // dupe check
            if (!RegisterSubmit(context.ExtraNonce1, extraNonce2, nTime, nonce))
            {
                throw new StratumException(StratumError.DuplicateShare, "duplicate share");
            }

            return(ProcessShareInternal(worker, extraNonce2, nTimeInt, nonceInt, versionBitsInt));
        }
コード例 #15
0
        private async Task OnSubmitHashrateAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <EthereumWorkerContext>();

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

            // Dummy command, just predend like you did something with it and send true to keep the miner happy
            await client.RespondAsync(true, request.Id);
        }
コード例 #16
0
        protected override async Task OnAuthorizeAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            await base.OnAuthorizeAsync(client, tsRequest);

            var context = client.ContextAs <BitcoinWorkerContext>();

            if (context.IsAuthorized)
            {
                // send intial update
                client.Notify(ZCashStratumMethods.SetTarget, new object[] { EncodeTarget(context.Difficulty) });
                client.Notify(BitcoinStratumMethods.MiningNotify, currentJobParams);
            }
        }
コード例 #17
0
ファイル: BitcoinPool.cs プロジェクト: edtrade/miningcore
        protected override async Task OnVarDiffUpdateAsync(StratumClient client, double newDiff)
        {
            var context = client.ContextAs<BitcoinWorkerContext>();
            context.EnqueueNewDifficulty(newDiff);

            // apply immediately and notify client
            if (context.HasPendingDifficulty)
            {
                context.ApplyPendingDifficulty();

                await client.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { context.Difficulty });
                await client.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
            }
        }
コード例 #18
0
        private async Task OnSubmitLoginAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <EthereumWorkerContext>();

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

            context.IsSubscribed = true;

            var requestParams = request.ParamsAs <string[]>();
            // setup worker context
            var workerValue = requestParams?.Length > 0 ? requestParams[0] : "0";
            var password    = requestParams?.Length > 1 ? requestParams[1] : null;
            var passParts   = password?.Split(PasswordControlVarsSeparator);

            // extract worker/miner
            var workerParts = workerValue?.Split('.');
            var minerName   = workerParts?.Length > 0 ? workerParts[0].Trim() : null;
            var workerName  = workerParts?.Length > 1 ? workerParts[1].Trim() : "0";

            // assumes that workerName is an address
            context.IsAuthorized     = !string.IsNullOrEmpty(minerName) && manager.ValidateAddress(minerName);
            context.Miner            = minerName.ToLower();
            context.Worker           = workerName;
            context.IsNiceHashClient = false;

            // respond
            await client.RespondAsync(context.IsAuthorized, request.Id);

            // extract control vars from password
            var staticDiff = GetStaticDiffFromPassparts(passParts);

            if (staticDiff.HasValue &&
                (context.VarDiff != null && staticDiff.Value >= context.VarDiff.Config.MinDiff ||
                 context.VarDiff == null && staticDiff.Value > context.Difficulty))
            {
                context.VarDiff = null; // disable vardiff
                context.SetDifficulty(staticDiff.Value);

                logger.Info(() => $"[{client.ConnectionId}] Setting static difficulty of {staticDiff.Value}");
            }

            await EnsureInitialWorkSent(client);

            // log association
            logger.Info(() => $"[{client.ConnectionId}] Authorized Stratum-Proxy Worker {workerValue}");
        }
コード例 #19
0
        public virtual (Share Share, string BlockHex) ProcessShare(StratumClient worker, string extraNonce, string nTime, string nonce, string solution)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(extraNonce), $"{nameof(extraNonce)} must not be empty");
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(nTime), $"{nameof(nTime)} must not be empty");
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(solution), $"{nameof(solution)} must not be empty");

            var context = worker.ContextAs <BitcoinWorkerContext>();

            // validate nTime
            if (nTime.Length != 8)
            {
                throw new StratumException(StratumError.Other, "incorrect size of ntime");
            }

            var nTimeInt = uint.Parse(nTime, NumberStyles.HexNumber);

            if (nTimeInt < BlockHeader.Timestamp || nTimeInt > ((DateTimeOffset)clock.Now).ToUnixTimeSeconds() + 7200)
            {
                throw new StratumException(StratumError.Other, "ntime out of range");
            }

            // validate nonce
            if (extraNonce.Length != 24)
            {
                throw new StratumException(StratumError.Other, "incorrect size of extraNonce2");
            }

            var extraNonce2 = extraNonce.Substring(0, extraNonce.Length - 8);

            if (!extraNonce.Equals(extraNonce2 + context.ExtraNonce1))
            {
                throw new StratumException(StratumError.Other, "incorrect extraNonce");
            }

            // validate solution
            if (solution.Length != chainConfig.SolutionSize * 2)
            {
                throw new StratumException(StratumError.Other, "incorrect size of solution");
            }

            // dupe check
            if (!RegisterSubmit(extraNonce, nonce, solution))
            {
                throw new StratumException(StratumError.DuplicateShare, "duplicate share");
            }

            return(ProcessShareInternal(worker, extraNonce, nTimeInt, nonce, solution));
        }
コード例 #20
0
        public async Task <Share> SubmitShareAsync(StratumClient worker,
                                                   string[] request, double stratumDifficulty, double stratumDifficultyBase)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.RequiresNonNull(request, nameof(request));

            logger.LogInvoke(new[] { worker.ConnectionId });
            var context = worker.ContextAs <AionWorkerContext>();

            var     miner = request[0];
            var     jobId = request[1];
            var     time  = request[2];
            var     nonce = request[3];
            var     soln  = request[4];
            AionJob job;

            // stale?
            lock (jobLock)
            {
                if (!validJobs.TryGetValue(jobId, out job))
                {
                    // logger.Info(() => $"!!! src/Mingingcore/Blockchain/Aion/AionJobManager.cs/SubmitShareAsync stale-share jobId '{jobId}'");
                    throw new StratumException(StratumError.MinusOne, "stale share");
                }
            }

            // validate & process
            var(share, fullNonceHex, solution, headerHash, nTime) = await job.ProcessShareAsync(worker, nonce, time, soln);

            // enrich share with common data
            share.PoolId  = poolConfig.Id;
            share.Source  = clusterConfig.ClusterName;
            share.Created = clock.Now;

            // if block candidate, submit & check if accepted by network
            if (share.IsBlockCandidate)
            {
                logger.Info(() => $"Submitting block {share.BlockHeight}");

                share.IsBlockCandidate = await SubmitBlockAsync(share, fullNonceHex, headerHash, solution, nTime);

                if (share.IsBlockCandidate)
                {
                    logger.Info(() => $"Daemon accepted block {share.BlockHeight} submitted by {context.MinerName}");
                }
            }

            return(share);
        }
コード例 #21
0
        private async Task OnAuthorizeAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <AionWorkerContext>();

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

            var requestParams = request.ParamsAs <string[]>();
            var workerValue   = requestParams?.Length > 0 ? requestParams[0] : null;
            var password      = requestParams?.Length > 1 ? requestParams[1] : null;
            var passParts     = password?.Split(PasswordControlVarsSeparator);

            // extract worker/miner
            var workerParts    = workerValue?.Split('.');
            var minerName      = workerParts?.Length > 0 ? workerParts[0].Trim() : null;
            var workerName     = workerParts?.Length > 1 ? workerParts[1].Trim() : null;
            var minimumPayment = GetMinimumPaymentFromPassparts(passParts);

            // assumes that workerName is an address
            context.IsAuthorized = !string.IsNullOrEmpty(minerName) && await manager.ValidateAddressAsync(minerName);

            context.MinerName  = minerName;
            context.WorkerName = workerName;
            // respond
            // await client.RespondAsync(context.IsAuthorized, request.Id);
            client.Respond(context.IsAuthorized, request.Id);

            // extract control vars from password
            var staticDiff = GetStaticDiffFromPassparts(passParts);

            if (staticDiff.HasValue &&
                (context.VarDiff != null && staticDiff.Value >= context.VarDiff.Config.MinDiff ||
                 context.VarDiff == null && staticDiff.Value > context.Difficulty))
            {
                context.VarDiff = null; // disable vardiff
                context.SetDifficulty(staticDiff.Value);
            }

            messageBus.SendMessage(new MinerInfo(poolConfig.Id,
                                                 context.MinerName, context.MinimumPayment = minimumPayment));

            EnsureInitialWorkSent(client);

            // log association
            logger.Info(() => $"[{client.ConnectionId}] Authorized worker {workerValue} mp {minimumPayment}");
        }
コード例 #22
0
        protected override void OnVarDiffUpdate(StratumClient client, double newDiff)
        {
            var context = client.ContextAs <BitcoinWorkerContext>();

            context.EnqueueNewDifficulty(newDiff);

            // apply immediately and notify client
            if (context.HasPendingDifficulty)
            {
                context.ApplyPendingDifficulty();

                client.Notify(ZCashStratumMethods.SetTarget, new object[] { EncodeTarget(context.Difficulty) });
                client.Notify(BitcoinStratumMethods.MiningNotify, currentJobParams);
            }
        }
コード例 #23
0
        private void EnsureInitialWorkSent(StratumClient client)
        {
            var context = client.ContextAs <EthereumWorkerContext>();

            lock (context)
            {
                if (context.IsAuthorized && context.IsAuthorized && !context.IsInitialWorkSent)
                {
                    context.IsInitialWorkSent = true;

                    // send intial update
                    client.Notify(EthereumStratumMethods.SetDifficulty, new object[] { context.Difficulty });
                    client.Notify(EthereumStratumMethods.MiningNotify, currentJobParams);
                }
            }
        }
コード例 #24
0
        protected override async Task OnVarDiffUpdateAsync(StratumClient client, double newDiff)
        {
            await base.OnVarDiffUpdateAsync(client, newDiff);

            // apply immediately and notify client
            var context = client.ContextAs <CryptonoteWorkerContext>();

            if (context.HasPendingDifficulty)
            {
                context.ApplyPendingDifficulty();

                // re-send job
                var job = CreateWorkerJob(client);
                await client.NotifyAsync(CryptonoteStratumMethods.JobNotify, job);
            }
        }
コード例 #25
0
ファイル: MoneroPool.cs プロジェクト: zhq1/miningcore
        protected override void OnVarDiffUpdate(StratumClient client, double newDiff)
        {
            base.OnVarDiffUpdate(client, newDiff);

            // apply immediately and notify client
            var context = client.ContextAs <MoneroWorkerContext>();

            if (context.HasPendingDifficulty)
            {
                context.ApplyPendingDifficulty();

                // re-send job
                var job = CreateWorkerJob(client);
                client.Notify(MoneroStratumMethods.JobNotify, job);
            }
        }
コード例 #26
0
        protected override void OnVarDiffUpdate(StratumClient client, double newDiff)
        {
            base.OnVarDiffUpdate(client, newDiff);

            // apply immediately and notify client
            var context = client.ContextAs <EthereumWorkerContext>();

            if (context.HasPendingDifficulty)
            {
                context.ApplyPendingDifficulty();

                // send job
                client.Notify(EthereumStratumMethods.SetDifficulty, new object[] { context.Difficulty });
                client.Notify(EthereumStratumMethods.MiningNotify, currentJobParams);
            }
        }
コード例 #27
0
        public async Task <Share> SubmitShareAsync(StratumClient worker,
                                                   string[] request, double stratumDifficulty, double stratumDifficultyBase)
        {
            Contract.RequiresNonNull(worker, nameof(worker));
            Contract.RequiresNonNull(request, nameof(request));

            logger.LogInvoke(LogCat, new[] { worker.ConnectionId });
            var context = worker.ContextAs <EthereumWorkerContext>();

            // var miner = request[0];
            var         jobId = request[1];
            var         nonce = request[2];
            EthereumJob job;

            // stale?
            lock (jobLock)
            {
                if (!validJobs.TryGetValue(jobId, out job))
                {
                    throw new StratumException(StratumError.MinusOne, "stale share");
                }
            }

            // validate & process
            var(share, fullNonceHex, headerHash, mixHash) = await job.ProcessShareAsync(worker, nonce, ethash);

            // enrich share with common data
            share.PoolId            = poolConfig.Id;
            share.NetworkDifficulty = BlockchainStats.NetworkDifficulty;
            share.Source            = clusterConfig.ClusterName;
            share.Created           = clock.Now;

            // if block candidate, submit & check if accepted by network
            if (share.IsBlockCandidate)
            {
                logger.Info(() => $"[{LogCat}] Submitting block {share.BlockHeight}");

                share.IsBlockCandidate = await SubmitBlockAsync(share, fullNonceHex, headerHash, mixHash);

                if (share.IsBlockCandidate)
                {
                    logger.Info(() => $"[{LogCat}] Daemon accepted block {share.BlockHeight} submitted by {context.MinerName}");
                }
            }

            return(share);
        }
コード例 #28
0
        private async Task OnSuggestTargetAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <BitcoinWorkerContext>();

            if (request.Id == null)
            {
                await client.RespondErrorAsync(StratumError.Other, "missing request id", request.Id);

                return;
            }

            var requestParams = request.ParamsAs <string[]>();
            var target        = requestParams.FirstOrDefault();

            if (!string.IsNullOrEmpty(target))
            {
                if (System.Numerics.BigInteger.TryParse(target, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var targetBig))
                {
                    var newDiff      = (double)new BigRational(chainConfig.Diff1b, targetBig);
                    var poolEndpoint = poolConfig.Ports[client.PoolEndpoint.Port];

                    if (newDiff >= poolEndpoint.Difficulty)
                    {
                        context.EnqueueNewDifficulty(newDiff);
                        context.ApplyPendingDifficulty();

                        await client.NotifyAsync(ZCashStratumMethods.SetTarget, new object[] { EncodeTarget(context.Difficulty) });
                    }

                    else
                    {
                        await client.RespondErrorAsync(StratumError.Other, "suggested difficulty too low", request.Id);
                    }
                }

                else
                {
                    await client.RespondErrorAsync(StratumError.Other, "invalid target", request.Id);
                }
            }

            else
            {
                await client.RespondErrorAsync(StratumError.Other, "invalid target", request.Id);
            }
        }
コード例 #29
0
        public override object[] GetSubscriberData(StratumClient worker)
        {
            Contract.RequiresNonNull(worker, nameof(worker));

            var context = worker.ContextAs <BitcoinWorkerContext>();

            // assign unique ExtraNonce1 to worker (miner)
            context.ExtraNonce1 = extraNonceProvider.Next();

            // setup response data
            var responseData = new object[]
            {
                context.ExtraNonce1
            };

            return(responseData);
        }
コード例 #30
0
        private async Task OnAuthorizeAsync(StratumClient client, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = client.ContextAs <EthereumWorkerContext>();

            if (request.Id == null)
            {
                await client.RespondErrorAsync(StratumError.Other, "missing request id", request.Id);

                return;
            }

            var requestParams = request.ParamsAs <string[]>();
            var workerValue   = requestParams?.Length > 0 ? requestParams[0] : null;
            var password      = requestParams?.Length > 1 ? requestParams[1] : null;
            var passParts     = password?.Split(PasswordControlVarsSeparator);

            // extract worker/miner
            var workerParts = workerValue?.Split('.');
            var minerName   = workerParts?.Length > 0 ? workerParts[0].Trim() : null;
            var workerName  = workerParts?.Length > 1 ? workerParts[1].Trim() : null;

            // assumes that workerName is an address
            context.IsAuthorized = !string.IsNullOrEmpty(minerName) && manager.ValidateAddress(minerName);
            context.MinerName    = minerName;
            context.WorkerName   = workerName;

            // respond
            await client.RespondAsync(context.IsAuthorized, request.Id);

            // extract control vars from password
            var staticDiff = GetStaticDiffFromPassparts(passParts);

            if (staticDiff.HasValue &&
                (context.VarDiff != null && staticDiff.Value >= context.VarDiff.Config.MinDiff ||
                 context.VarDiff == null && staticDiff.Value > context.Difficulty))
            {
                context.VarDiff = null; // disable vardiff
                context.SetDifficulty(staticDiff.Value);
            }

            await EnsureInitialWorkSent(client);

            // log association
            logger.Info(() => $"[{LogCat}] [{client.ConnectionId}] = {workerValue} = {client.RemoteEndpoint.Address}");
        }