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; }
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"); }
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; }
public void Start(XPoolConfig clusterConfig) { Assertion.RequiresNonNull(clusterConfig, nameof(clusterConfig)); this.clusterConfig = clusterConfig; logger.Info(() => $"Launching ..."); StartApi(clusterConfig); StartAdminApi(clusterConfig); }
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 })); }
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(); }
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); } }
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)"); } }
public static void loadConfig(string configFile) { clusterConfig = ReadConfig(configFile); if (dumpConfigOption.HasValue()) { DumpParsedConfig(clusterConfig); return; } ValidateConfig(); }
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); }
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}"); }
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); } }
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 }; }
public void Configure(XPoolConfig clusterConfig) { this.clusterConfig = clusterConfig; }
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"); } }
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); }