Ejemplo n.º 1
0
        public override async Task ConfigureAsync(XPoolConfig clusterConfig, PoolConfig poolConfig)
        {
            await base.ConfigureAsync(clusterConfig, poolConfig);

            poolExtraConfig = poolConfig.Extra.SafeExtensionDataAs <ZCashPoolConfigExtra>();

            var blockchainInfoResponse = await daemon.ExecuteCmdSingleAsync <BlockchainInfo>(BitcoinCommands.GetBlockchainInfo);

            if (blockchainInfoResponse.Response.Chain.ToLower() == "test")
            {
                networkType = BitcoinNetworkType.Test;
            }
            else if (blockchainInfoResponse.Response.Chain.ToLower() == "regtest")
            {
                networkType = BitcoinNetworkType.RegTest;
            }
            else
            {
                networkType = BitcoinNetworkType.Main;
            }

            if (ZCashConstants.CoinbaseTxConfig.TryGetValue(poolConfig.Coin.Type, out var coinbaseTx))
            {
                coinbaseTx.TryGetValue(networkType, out coinbaseTxConfig);
            }

            var response = await daemon.ExecuteCmdSingleAsync <JObject>(ZCashCommands.ZShieldCoinbase);

            supportsNativeShielding = response.Error.Code != (int)BitcoinRPCErrorCode.RPC_METHOD_NOT_FOUND;
        }
Ejemplo n.º 2
0
 protected void SetupBanning(XPoolConfig clusterConfig)
 {
     if (poolConfig.Banning?.Enabled == true)
     {
         var managerType = clusterConfig.Banning?.Manager ?? BanManagerKind.Integrated;
         banManager = ctx.ResolveKeyed <IBanManager>(managerType);
     }
 }
        public void Start(XPoolConfig clusterConfig)
        {
            this.clusterConfig = clusterConfig;

            ConfigureRecovery();
            InitializeQueue();

            logger.Info(() => "Online");
        }
Ejemplo n.º 4
0
        public virtual void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            Assertion.RequiresNonNull(poolConfig, nameof(poolConfig));
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));

            logger             = LogUtil.GetPoolScopedLogger(typeof(PoolBase), poolConfig);
            this.poolConfig    = poolConfig;
            this.clusterConfig = clusterConfig;
        }
Ejemplo n.º 5
0
        public void Start(XPoolConfig clusterConfig)
        {
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));
            this.clusterConfig = clusterConfig;

            logger.Info(() => $"Launching ...");
            StartApi(clusterConfig);
            StartAdminApi(clusterConfig);
        }
Ejemplo n.º 6
0
        private static void DumpParsedConfig(XPoolConfig config)
        {
            Console.WriteLine("\nCurrent configuration as parsed from config file:");

            Console.WriteLine(JsonConvert.SerializeObject(config, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                Formatting       = Formatting.Indented
            }));
        }
Ejemplo n.º 7
0
        public virtual void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            Assertion.RequiresNonNull(poolConfig, nameof(poolConfig));
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));

            logger             = LogUtil.GetPoolScopedLogger(typeof(JobManagerBase <TJob>), poolConfig);
            this.poolConfig    = poolConfig;
            this.clusterConfig = clusterConfig;

            ConfigureDaemons();
        }
Ejemplo n.º 8
0
        public override void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            base.Configure(poolConfig, clusterConfig);

            extraConfig = poolConfig.Extra.SafeExtensionDataAs <ZCashPoolConfigExtra>();

            if (string.IsNullOrEmpty(extraConfig?.ZAddress))
            {
                logger.ThrowLogPoolStartupException($"Pool z-address is not configured", LogCat);
            }
        }
Ejemplo n.º 9
0
        public override void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            base.Configure(poolConfig, clusterConfig);

            var extraConfig = poolConfig.PaymentProcessing?.Extra?.SafeExtensionDataAs <EthereumPoolPaymentProcessingConfigExtra>();

            if (clusterConfig.PaymentProcessing?.Enabled == true && extraConfig?.CoinbasePassword == null)
            {
                logger.ThrowLogPoolStartupException("\"paymentProcessing.coinbasePassword\" pool-configuration property missing or empty (required for unlocking wallet during payment processing)");
            }
        }
Ejemplo n.º 10
0
        public static void loadConfig(string configFile)
        {
            clusterConfig = ReadConfig(configFile);

            if (dumpConfigOption.HasValue())
            {
                DumpParsedConfig(clusterConfig);
                return;
            }

            ValidateConfig();
        }
Ejemplo n.º 11
0
        public override void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <BitcoinPoolConfigExtra>();
            extraPoolPaymentProcessingConfig = poolConfig.PaymentProcessing?.Extra?.SafeExtensionDataAs <BitcoinPoolPaymentProcessingConfigExtra>();

            if (extraPoolConfig?.MaxActiveJobs.HasValue == true)
            {
                maxActiveJobs = extraPoolConfig.MaxActiveJobs.Value;
            }

            hasLegacyDaemon = extraPoolConfig?.HasLegacyDaemon == true;

            base.Configure(poolConfig, clusterConfig);
        }
Ejemplo n.º 12
0
        private void StartAdminApi(XPoolConfig clusterConfig)
        {
            var address = clusterConfig.Api?.ListenAddress != null
                ? (clusterConfig.Api.ListenAddress != "*" ? IPAddress.Parse(clusterConfig.Api.ListenAddress) : IPAddress.Any)
                : IPAddress.Parse("127.0.0.1");

            var port = clusterConfig.Api?.AdminPort ?? 4001;

            webHostAdmin = new WebHostBuilder()
                           .Configure(app => { app.Run(HandleRequestAdmin); })
                           .UseKestrel(options => { options.Listen(address, port); })
                           .Build();

            webHostAdmin.Start();

            logger.Info(() => $"Admin API Online @ {address}:{port}");
        }
Ejemplo n.º 13
0
        public async Task ConfigureAsync(XPoolConfig clusterConfig, PoolConfig poolConfig)
        {
            this.poolConfig    = poolConfig;
            this.clusterConfig = clusterConfig;
            extraConfig        = poolConfig.PaymentProcessing.Extra.SafeExtensionDataAs <EthereumPoolPaymentProcessingConfigExtra>();

            logger = LogUtil.GetPoolScopedLogger(typeof(EthereumPayoutHandler), poolConfig);

            var jsonSerializerSettings = ctx.Resolve <JsonSerializerSettings>();

            var daemonEndpoints = poolConfig.Daemons
                                  .Where(x => string.IsNullOrEmpty(x.Category))
                                  .ToArray();

            daemon = new DaemonClient(jsonSerializerSettings);
            daemon.Configure(daemonEndpoints);

            await DetectChainAsync();
        }
        public virtual Task ConfigureAsync(XPoolConfig clusterConfig, PoolConfig poolConfig)
        {
            Assertion.RequiresNonNull(poolConfig, nameof(poolConfig));

            this.poolConfig    = poolConfig;
            this.clusterConfig = clusterConfig;

            extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <BitcoinDaemonEndpointConfigExtra>();
            extraPoolPaymentProcessingConfig = poolConfig.PaymentProcessing.Extra.SafeExtensionDataAs <BitcoinPoolPaymentProcessingConfigExtra>();
            coinProperties = BitcoinProperties.GetCoinProperties(poolConfig.Coin.Type, poolConfig.Coin.Algorithm);

            logger = LogUtil.GetPoolScopedLogger(typeof(BitcoinPayoutHandler), poolConfig);

            var jsonSerializerSettings = ctx.Resolve <JsonSerializerSettings>();

            daemon = new DaemonClient(jsonSerializerSettings);
            daemon.Configure(poolConfig.Daemons);

            return(Task.FromResult(true));
        }
        public WebhookNotificationService(
            XPoolConfig clusterConfig,
            JsonSerializerSettings serializerSettings,
            IMessageBus messageBus)
        {
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));
            Assertion.RequiresNonNull(messageBus, nameof(messageBus));

            this.clusterConfig      = clusterConfig;
            this.serializerSettings = serializerSettings;

            poolConfigs = clusterConfig.Pools.ToDictionary(x => x.Id, x => x);

            adminEmail = clusterConfig.Notifications?.Admin?.EmailAddress;

            if (clusterConfig.Notifications?.Enabled == true)
            {
                queue = new BlockingCollection <QueuedNotification>();

                queueSub = queue.GetConsumingEnumerable()
                           .ToObservable(TaskPoolScheduler.Default)
                           .Select(notification => Observable.FromAsync(() => SendNotificationAsync(notification)))
                           .Concat()
                           .Subscribe();

                messageBus.Listen <BlockNotification>()
                .Subscribe(x =>
                {
                    queue?.Add(new QueuedNotification
                    {
                        Category = NotificationCategory.Block,
                        PoolId   = x.PoolId,
                        Subject  = "Block Notification",
                        Msg      = $"Pool {x.PoolId} found block candidate {x.BlockHeight}"
                    });
                });
            }
        }
        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);
            }
        }
Ejemplo n.º 17
0
        public virtual void Init(TBlockTemplate blockTemplate, string jobId,
                                 PoolConfig poolConfig, XPoolConfig clusterConfig, IMasterClock clock,
                                 IDestination poolAddressDestination, BitcoinNetworkType networkType,
                                 bool isPoS, double shareMultiplier, decimal blockrewardMultiplier,
                                 IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher)
        {
            Assertion.RequiresNonNull(blockTemplate, nameof(blockTemplate));
            Assertion.RequiresNonNull(poolConfig, nameof(poolConfig));
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));
            Assertion.RequiresNonNull(clock, nameof(clock));
            Assertion.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination));
            Assertion.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher));
            Assertion.RequiresNonNull(headerHasher, nameof(headerHasher));
            Assertion.RequiresNonNull(blockHasher, nameof(blockHasher));
            Assertion.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty");

            this.poolConfig             = poolConfig;
            this.clusterConfig          = clusterConfig;
            this.clock                  = clock;
            this.poolAddressDestination = poolAddressDestination;
            this.networkType            = networkType;
            BlockTemplate               = blockTemplate;
            JobId      = jobId;
            Difficulty = new Target(new NBitcoin.BouncyCastle.Math.BigInteger(BlockTemplate.Target, 16)).Difficulty;

            extraNoncePlaceHolderLength = BitcoinConstants.ExtranoncePlaceHolderLength;
            this.isPoS                 = isPoS;
            this.shareMultiplier       = shareMultiplier;
            this.blockRewardMultiplier = blockrewardMultiplier;

            this.coinbaseHasher = coinbaseHasher;
            this.headerHasher   = headerHasher;
            this.blockHasher    = blockHasher;

            if (!string.IsNullOrEmpty(BlockTemplate.Target))
            {
                blockTargetValue = new uint256(BlockTemplate.Target);
            }
            else
            {
                var tmp = new Target(BlockTemplate.Bits.HexToByteArray());
                blockTargetValue = tmp.ToUInt256();
            }

            previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash
                                           .HexToByteArray()
                                           .ReverseByteOrder()
                                           .ToHexString();

            BuildMerkleBranches();
            BuildCoinbase();

            jobParams = new object[]
            {
                JobId,
                previousBlockHashReversedHex,
                coinbaseInitialHex,
                coinbaseFinalHex,
                merkleBranchesHex,
                BlockTemplate.Version.ToStringHex8(),
                BlockTemplate.Bits,
                BlockTemplate.CurTime.ToStringHex8(),
                false
            };
        }
Ejemplo n.º 18
0
 public void Configure(XPoolConfig clusterConfig)
 {
     this.clusterConfig = clusterConfig;
 }
Ejemplo n.º 19
0
        public void RecoverShares(XPoolConfig clusterConfig, string recoveryFilename)
        {
            logger.Info(() => $"Recovering shares using {recoveryFilename} ...");

            try
            {
                var       successCount = 0;
                var       failCount    = 0;
                const int bufferSize   = 20;

                using (var stream = new FileStream(recoveryFilename, FileMode.Open, FileAccess.Read))
                {
                    using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
                    {
                        var shares             = new List <Share>();
                        var lastProgressUpdate = DateTime.UtcNow;

                        while (!reader.EndOfStream)
                        {
                            var line = reader.ReadLine().Trim();

                            if (line.Length == 0)
                            {
                                continue;
                            }

                            if (line.StartsWith("#"))
                            {
                                continue;
                            }

                            try
                            {
                                var share = JsonConvert.DeserializeObject <Share>(line, jsonSerializerSettings);
                                shares.Add(share);
                            }

                            catch (JsonException ex)
                            {
                                logger.Error(ex, () => $"Unable to parse share record: {line}");
                                failCount++;
                            }

                            try
                            {
                                if (shares.Count == bufferSize)
                                {
                                    PersistShares(shares);

                                    shares.Clear();
                                    successCount += shares.Count;
                                }
                            }

                            catch (Exception ex)
                            {
                                logger.Error(ex, () => $"Unable to import shares");
                                failCount++;
                            }

                            var now = DateTime.UtcNow;
                            if (now - lastProgressUpdate > TimeSpan.FromMinutes(1))
                            {
                                logger.Info($"{successCount} shares imported");
                                lastProgressUpdate = now;
                            }
                        }

                        try
                        {
                            if (shares.Count > 0)
                            {
                                PersistShares(shares);

                                successCount += shares.Count;
                            }
                        }

                        catch (Exception ex)
                        {
                            logger.Error(ex, () => $"Unable to import shares");
                            failCount++;
                        }
                    }
                }

                if (failCount == 0)
                {
                    logger.Info(() => $"Successfully recovered {successCount} shares");
                }
                else
                {
                    logger.Warn(() => $"Successfully {successCount} shares with {failCount} failures");
                }
            }

            catch (FileNotFoundException)
            {
                logger.Error(() => $"Recovery file {recoveryFilename} was not found");
            }
        }
Ejemplo n.º 20
0
        public override void Init(ZCashBlockTemplate blockTemplate, string jobId,
            PoolConfig poolConfig, XPoolConfig clusterConfig, IMasterClock clock,
            IDestination poolAddressDestination, BitcoinNetworkType networkType,
            bool isPoS, double shareMultiplier, decimal blockrewardMultiplier,
            IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher)
        {
            Assertion.RequiresNonNull(blockTemplate, nameof(blockTemplate));
            Assertion.RequiresNonNull(poolConfig, nameof(poolConfig));
            Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig));
            Assertion.RequiresNonNull(clock, nameof(clock));
            Assertion.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination));
            Assertion.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher));
            Assertion.RequiresNonNull(headerHasher, nameof(headerHasher));
            Assertion.RequiresNonNull(blockHasher, nameof(blockHasher));
            Assertion.Requires<ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty");

            this.poolConfig = poolConfig;
            this.clusterConfig = clusterConfig;
            this.clock = clock;
            this.poolAddressDestination = poolAddressDestination;
            this.networkType = networkType;

            if (ZCashConstants.CoinbaseTxConfig.TryGetValue(poolConfig.Coin.Type, out var coinbaseTx))
                coinbaseTx.TryGetValue(networkType, out coinbaseTxConfig);

            BlockTemplate = blockTemplate;
            JobId = jobId;
            Difficulty = (double) new BigRational(coinbaseTxConfig.Diff1b, BlockTemplate.Target.HexToByteArray().ReverseArray().ToBigInteger());

            this.isPoS = isPoS;
            this.shareMultiplier = shareMultiplier;

            this.headerHasher = headerHasher;
            this.blockHasher = blockHasher;

            if (!string.IsNullOrEmpty(BlockTemplate.Target))
                blockTargetValue = new uint256(BlockTemplate.Target);
            else
            {
                var tmp = new Target(BlockTemplate.Bits.HexToByteArray());
                blockTargetValue = tmp.ToUInt256();
            }

            previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash
                .HexToByteArray()
                .ReverseArray()
                .ToHexString();

            blockReward = blockTemplate.Subsidy.Miner * BitcoinConstants.SatoshisPerBitcoin;

            if (coinbaseTxConfig?.PayFoundersReward == true)
            {
                var founders = blockTemplate.Subsidy.Founders ?? blockTemplate.Subsidy.Community;

                if (!founders.HasValue)
                    throw new Exception("Error, founders reward missing for block template");

                blockReward = (blockTemplate.Subsidy.Miner + founders.Value) * BitcoinConstants.SatoshisPerBitcoin;
            }

            rewardFees = blockTemplate.Transactions.Sum(x => x.Fee);

            BuildCoinbase();

                        var txHashes = new List<uint256> { new uint256(coinbaseInitialHash) };
            txHashes.AddRange(BlockTemplate.Transactions.Select(tx => new uint256(tx.Hash.HexToByteArray().ReverseArray())));

                        merkleRoot = MerkleNode.GetRoot(txHashes).Hash.ToBytes().ReverseArray();
            merkleRootReversed = merkleRoot.ReverseArray();
            merkleRootReversedHex = merkleRootReversed.ToHexString();

            jobParams = new object[]
            {
                JobId,
                BlockTemplate.Version.ReverseByteOrder().ToStringHex8(),
                previousBlockHashReversedHex,
                merkleRootReversedHex,
                sha256Empty.ToHexString(),                 BlockTemplate.CurTime.ReverseByteOrder().ToStringHex8(),
                BlockTemplate.Bits.HexToByteArray().ReverseArray().ToHexString(),
                false
            };
        }
        public override void Configure(PoolConfig poolConfig, XPoolConfig clusterConfig)
        {
            zcashExtraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <ZCashPoolConfigExtra>();

            base.Configure(poolConfig, clusterConfig);
        }