Beispiel #1
0
    private async Task SendWork(EthereumWorkerContext context, StratumConnection connection, object requestId)
    {
        var parameters = manager.GetWorkParamsForStratum(context);

        // respond
        await connection.RespondAsync(parameters, requestId);
    }
Beispiel #2
0
        protected virtual async Task OnSubscribeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;

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

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

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

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

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

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

            await connection.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
        }
Beispiel #3
0
    protected async Task OnSubscribeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.ContextAs <BitcoinWorkerContext>();

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

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

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

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

        // setup worker context
        context.IsSubscribed = true;
        context.UserAgent    = requestParams.FirstOrDefault()?.Trim();
    }
Beispiel #4
0
    private async Task OnSuggestDifficultyAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.ContextAs <BitcoinWorkerContext>();

        // acknowledge
        await connection.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[connection.LocalEndpoint.Port];

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

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

        catch (Exception ex)
        {
            logger.Error(ex, () => $"Unable to convert suggested difficulty {request.Params}");
        }
    }
Beispiel #5
0
    private async Task OnConfigureMiningAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.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>();

        if (extensions != null)
        {
            foreach (var extension in extensions)
            {
                switch (extension)
                {
                case BitcoinStratumExtensions.VersionRolling:
                    ConfigureVersionRolling(connection, context, extensionParams, result);
                    break;

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

        await connection.RespondAsync(result, request.Id);
    }
Beispiel #6
0
        private async Task OnLoginAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = connection.ContextAs <CryptonoteWorkerContext>();

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

            var loginRequest = request.ParamsAs <CryptonoteLoginRequest>();

            if (string.IsNullOrEmpty(loginRequest?.Login))
            {
                throw new StratumException(StratumError.MinusOne, "missing login");
            }

            // extract worker/miner/paymentid
            var split = loginRequest.Login.Split('.');

            context.Miner     = split[0].Trim();
            context.Worker    = split.Length > 1 ? split[1].Trim() : null;
            context.UserAgent = loginRequest.UserAgent?.Trim();

            var addressToValidate = context.Miner;

            // extract paymentid
            var index = context.Miner.IndexOf('#');

            if (index != -1)
            {
                var paymentId = context.Miner[(index + 1)..].Trim();
Beispiel #7
0
    private async Task OnGetWorkAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.ContextAs <EthereumWorkerContext>();

        await SendWork(context, connection, request.Id);
    }
Beispiel #8
0
    protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, double newDiff, CancellationToken ct)
    {
        await base.OnVarDiffUpdateAsync(connection, newDiff, ct);

        if (connection.Context.ApplyPendingDifficulty())
        {
            await connection.NotifyAsync(EquihashStratumMethods.SetTarget, new object[] { EncodeTarget(connection.Context.Difficulty) });

            await connection.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
        }
    }
Beispiel #9
0
    private async Task SendJob(EthereumWorkerContext context, StratumConnection connection, object parameters)
    {
        // varDiff: if the client has a pending difficulty change, apply it now
        if (context.ApplyPendingDifficulty())
        {
            await connection.NotifyAsync(EthereumStratumMethods.SetDifficulty, new object[] { context.Difficulty });
        }

        // send job
        await connection.NotifyAsync(EthereumStratumMethods.MiningNotify, parameters);
    }
Beispiel #10
0
    protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, double newDiff)
    {
        var context = connection.ContextAs <ErgoWorkerContext>();

        context.EnqueueNewDifficulty(newDiff);

        if (context.ApplyPendingDifficulty())
        {
            await SendJob(connection, context, currentJobParams);
        }
    }
Beispiel #11
0
    protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, double newDiff, CancellationToken ct)
    {
        await base.OnVarDiffUpdateAsync(connection, newDiff, ct);

        var context = connection.ContextAs <ErgoWorkerContext>();

        if (context.ApplyPendingDifficulty())
        {
            await SendJob(connection, context, currentJobParams);
        }
    }
Beispiel #12
0
        protected override async Task <double?> GetNicehashStaticMinDiff(StratumConnection connection, string userAgent, string coinName, string algoName)
        {
            var result = await base.GetNicehashStaticMinDiff(connection, userAgent, coinName, algoName);

            // adjust value to fit with our target value calculation
            if (result.HasValue)
            {
                result = result.Value / uint.MaxValue;
            }

            return(result);
        }
Beispiel #13
0
    protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, double newDiff)
    {
        var context = connection.ContextAs <BitcoinWorkerContext>();

        context.EnqueueNewDifficulty(newDiff);

        // apply immediately and notify
        if (context.ApplyPendingDifficulty())
        {
            await connection.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { context.Difficulty });

            await connection.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
        }
    }
Beispiel #14
0
    private async Task OnSubscribeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.ContextAs <EthereumWorkerContext>();

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

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

        if (requestParams == null || requestParams.Length < 2 || requestParams.Any(string.IsNullOrEmpty))
        {
            throw new StratumException(StratumError.MinusOne, "invalid request");
        }

        manager.PrepareWorker(connection);

        context.UserAgent = requestParams.FirstOrDefault()?.Trim();

        var data = new object[]
        {
            new object[]
            {
                EthereumStratumMethods.MiningNotify,
                connection.ConnectionId,
                EthereumConstants.EthereumStratumVersion
            },
            context.ExtraNonce1
        }
        .ToArray();

        // Nicehash's stupid validator insists on "error" property present
        // in successful responses which is a violation of the JSON-RPC spec
        var response = new JsonRpcResponse <object[]>(data, request.Id);

        if (context.IsNicehash)
        {
            response.Extra          = new Dictionary <string, object>();
            response.Extra["error"] = null;
        }

        await connection.RespondAsync(response);

        // setup worker context
        context.IsSubscribed = true;
    }
Beispiel #15
0
    protected override async Task OnRequestAsync(StratumConnection connection,
                                                 Timestamped <JsonRpcRequest> tsRequest, CancellationToken ct)
    {
        var request = tsRequest.Value;

        try
        {
            switch (request.Method)
            {
            case BitcoinStratumMethods.Subscribe:
                await OnSubscribeAsync(connection, tsRequest);

                break;

            case BitcoinStratumMethods.Authorize:
                await OnAuthorizeAsync(connection, tsRequest, ct);

                break;

            case BitcoinStratumMethods.SubmitShare:
                await OnSubmitAsync(connection, tsRequest, ct);

                break;

            case EquihashStratumMethods.SuggestTarget:
                await OnSuggestTargetAsync(connection, tsRequest);

                break;

            case BitcoinStratumMethods.ExtraNonceSubscribe:
                // ignored
                break;

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

                await connection.RespondErrorAsync(StratumError.Other, $"Unsupported request {request.Method}", request.Id);

                break;
            }
        }

        catch (StratumException ex)
        {
            await connection.RespondErrorAsync(ex.Code, ex.Message, request.Id, false);
        }
    }
Beispiel #16
0
        public override object[] GetSubscriberData(StratumConnection 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);
        }
Beispiel #17
0
        protected override async Task OnVarDiffUpdateAsync(StratumConnection client, double newDiff)
        {
            await base.OnVarDiffUpdateAsync(client, newDiff);

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

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

                // send job
                await client.NotifyAsync(EthereumStratumMethods.SetDifficulty, new object[] { context.Difficulty });

                await client.NotifyAsync(EthereumStratumMethods.MiningNotify, currentJobParams);
            }
        }
Beispiel #18
0
        private async Task OnAuthorizeAsync(StratumConnection 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");
            }

            var requestParams = request.ParamsAs <string[]>();
            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;

            // 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 worker {workerValue}");
        }
Beispiel #19
0
    protected virtual async Task OnSubscribeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;

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

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

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

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

        // setup worker context
        context.IsSubscribed = true;
        context.UserAgent    = requestParams.FirstOrDefault()?.Trim();

        // Nicehash support
        var nicehashDiff = await GetNicehashStaticMinDiff(context, coin.Name, coin.GetAlgorithmName());

        if (nicehashDiff.HasValue)
        {
            logger.Info(() => $"[{connection.ConnectionId}] Nicehash detected. Using API supplied difficulty of {nicehashDiff.Value}");

            context.VarDiff = null; // disable vardiff
            context.SetDifficulty(nicehashDiff.Value);
        }

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

        await connection.NotifyAsync(BitcoinStratumMethods.MiningNotify, currentJobParams);
    }
Beispiel #20
0
    private async Task OnSuggestTargetAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
    {
        var request = tsRequest.Value;
        var context = connection.ContextAs <BitcoinWorkerContext>();

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

        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(manager.ChainConfig.Diff1BValue, targetBig);
                var poolEndpoint = poolConfig.Ports[connection.LocalEndpoint.Port];

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

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

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

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

        else
        {
            await connection.RespondErrorAsync(StratumError.Other, "invalid target", request.Id);
        }
    }
Beispiel #21
0
        public virtual object[] GetSubscriberData(StratumConnection 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,
                BitcoinConstants.ExtranoncePlaceHolderLength - ExtranonceBytes,
            };

            return(responseData);
        }
Beispiel #22
0
        protected override async Task OnRequestAsync(StratumConnection client,
                                                     Timestamped <JsonRpcRequest> tsRequest, CancellationToken ct)
        {
            var request = tsRequest.Value;

            try
            {
                switch (request.Method)
                {
                case EthereumStratumMethods.Subscribe:
                    await OnSubscribeAsync(client, tsRequest);

                    break;

                case EthereumStratumMethods.Authorize:
                    await OnAuthorizeAsync(client, tsRequest);

                    break;

                case EthereumStratumMethods.SubmitShare:
                    await OnSubmitAsync(client, tsRequest, ct);

                    break;

                case EthereumStratumMethods.ExtraNonceSubscribe:
                    // Pretend to support it even though we actually do not. Some miners drop the connection upon receiving an error from this
                    await client.RespondAsync(true, request.Id);

                    break;

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

                    await client.RespondErrorAsync(StratumError.Other, $"Unsupported request {request.Method}", request.Id);

                    break;
                }
            }

            catch (StratumException ex)
            {
                await client.RespondErrorAsync(ex.Code, ex.Message, request.Id, false);
            }
        }
Beispiel #23
0
    private void ConfigureMinimumDiff(StratumConnection connection, BitcoinWorkerContext context,
                                      IReadOnlyDictionary <string, JToken> extensionParams, Dictionary <string, object> result)
    {
        var requestedDiff = extensionParams[BitcoinStratumExtensions.MinimumDiffValue].Value <double>();

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

        if (requestedDiff > poolEndpoint.Difficulty)
        {
            context.VarDiff = null; // disable vardiff
            context.SetDifficulty(requestedDiff);

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

            // enabled
            result[BitcoinStratumExtensions.MinimumDiff] = true;
        }
    }
Beispiel #24
0
        static void Mainasdfasdfasdf(string[] args)
        {
            var serversList = new List <StratumConnection>
            {
                //groestl - StratumConnection.Parse("hub.miningpoolhub.com,12004,wchasik,home,x");
                //myr-gr - StratumConnection.Parse("hub.miningpoolhub.com,12005,wchasik,home,x");

                StratumConnection.Parse(AlgoNiceHashEnum.X11, "hub.miningpoolhub.com,12007,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.X13, "hub.miningpoolhub.com,12008,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.X15, "hub.miningpoolhub.com,12009,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.NeoScrypt, "hub.miningpoolhub.com,12012,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.Qubit, "hub.miningpoolhub.com,12014,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.Quark, "hub.miningpoolhub.com,12015,wchasik,home,x"),
                // skein - StratumConnection.Parse("hub.miningpoolhub.com,12016,wchasik,home,x");
                StratumConnection.Parse(AlgoNiceHashEnum.Lyra2REv2, "hub.miningpoolhub.com,12018,wchasik,home,x"),
                // vanilla - StratumConnection.Parse("hub.miningpoolhub.com,12019,wchasik,home,x");
                StratumConnection.Parse(AlgoNiceHashEnum.DaggerHashimoto, "europe.ethash-hub.miningpoolhub.com,12020,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.Equihash, "europe.equihash-hub.miningpoolhub.com,12023,wchasik,home,x"),
                StratumConnection.Parse(AlgoNiceHashEnum.CryptoNight, "europe.cryptonight-hub.miningpoolhub.com,12024,wchasik,home,x")
            };

            serversList.Where(sc => sc.Algo == AlgoNiceHashEnum.NeoScrypt || sc.Algo == AlgoNiceHashEnum.Equihash || sc.Algo == AlgoNiceHashEnum.CryptoNight || sc.Algo == AlgoNiceHashEnum.Lyra2REv2)
            .ToList().ForEach(server =>
            {
                var pinger = new PingServer(server, 10000);

                pinger.PingResultChanged += result =>
                {
                    //System.Console.BackgroundColor = result.Success ? ConsoleColor.Cyan : ConsoleColor.Red;

                    System.Console.WriteLine($"minutes: {(DateTime.Now - result.DateTime).TotalMinutes:#######.##} ; {result.Success} ; {result.Result}");
                };

                pinger.GotResponse += (sender, stratumEventArgs) =>
                {
                };
            });



            System.Console.ReadLine();
        }
Beispiel #25
0
    private void ConfigureVersionRolling(StratumConnection connection, BitcoinWorkerContext context,
                                         IReadOnlyDictionary <string, JToken> extensionParams, Dictionary <string, object> result)
    {
        //var requestedBits = extensionParams[BitcoinStratumExtensions.VersionRollingBits].Value<int>();
        var requestedMask = BitcoinConstants.VersionRollingPoolMask;

        if (extensionParams.TryGetValue(BitcoinStratumExtensions.VersionRollingMask, out var requestedMaskValue))
        {
            requestedMask = uint.Parse(requestedMaskValue.Value <string>(), NumberStyles.HexNumber);
        }

        // Compute effective mask
        context.VersionRollingMask = BitcoinConstants.VersionRollingPoolMask & requestedMask;

        // enabled
        result[BitcoinStratumExtensions.VersionRolling]     = true;
        result[BitcoinStratumExtensions.VersionRollingMask] = context.VersionRollingMask.Value.ToStringHex8();

        logger.Info(() => $"[{connection.ConnectionId}] Using version-rolling mask {result[BitcoinStratumExtensions.VersionRollingMask]}");
    }
Beispiel #26
0
        private async Task SendJob(StratumConnection connection, ErgoWorkerContext context, object[] jobParams)
        {
            // clone job params
            var jobParamsActual = new object[jobParams.Length];

            for (var i = 0; i < jobParamsActual.Length; i++)
            {
                jobParamsActual[i] = jobParams[i];
            }

            var target = new BigRational(BitcoinConstants.Diff1 * (BigInteger)(1 / context.Difficulty * 0x10000), 0x10000).GetWholePart();

            jobParamsActual[6] = target.ToString();

            // send static diff of 1 since actual diff gets pre-multiplied to target
            await connection.NotifyAsync(BitcoinStratumMethods.SetDifficulty, new object[] { 1 });

            // send target
            await connection.NotifyAsync(BitcoinStratumMethods.MiningNotify, jobParamsActual);
        }
Beispiel #27
0
        private async Task EnsureInitialWorkSent(StratumConnection connection)
        {
            var context         = connection.ContextAs <EthereumWorkerContext>();
            var sendInitialWork = false;

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

            if (sendInitialWork)
            {
                // send intial update
                await connection.NotifyAsync(EthereumStratumMethods.SetDifficulty, new object[] { context.Difficulty });

                await connection.NotifyAsync(EthereumStratumMethods.MiningNotify, currentJobParams);
            }
        }
Beispiel #28
0
    protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, double newDiff, CancellationToken ct)
    {
        await base.OnVarDiffUpdateAsync(connection, newDiff, ct);

        var context = connection.ContextAs <EthereumWorkerContext>();

        if (context.ApplyPendingDifficulty())
        {
            switch (context.ProtocolVersion)
            {
            case 1:
                await SendWork(context, connection, 0);

                break;

            case 2:
                await SendJob(context, connection, manager.GetJobParamsForStratum());

                break;
            }
        }
    }
Beispiel #29
0
        private async Task OnSubscribeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest)
        {
            var request = tsRequest.Value;
            var context = connection.ContextAs <EthereumWorkerContext>();

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

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

            if (requestParams == null || requestParams.Length < 2 || requestParams.Any(string.IsNullOrEmpty))
            {
                throw new StratumException(StratumError.MinusOne, "invalid request");
            }

            manager.PrepareWorker(connection);

            var data = new object[]
            {
                new object[]
                {
                    EthereumStratumMethods.MiningNotify,
                    connection.ConnectionId,
                    EthereumConstants.EthereumStratumVersion
                },
                context.ExtraNonce1
            }
            .ToArray();

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

            // setup worker context
            context.IsSubscribed = true;
            context.UserAgent    = requestParams[0].Trim();
        }
Beispiel #30
0
    protected virtual async Task OnAuthorizeAsync(StratumConnection connection, Timestamped <JsonRpcRequest> tsRequest, CancellationToken ct)
    {
        var request = tsRequest.Value;

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

        var context       = connection.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 minerName is an address
        context.IsAuthorized = await manager.ValidateAddressAsync(minerName, ct);

        context.Miner  = minerName;
        context.Worker = workerName;

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

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

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

            // Static diff
            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(() => $"[{connection.ConnectionId}] Setting static difficulty of {staticDiff.Value}");

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

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

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

            banManager.Ban(connection.RemoteEndpoint.Address, loginFailureBanTimeout);

            CloseConnection(connection);
        }
    }