/// <summary> /// Enable mining pool command line. /// </summary> private static void EnableMiningPoolCommandLine() { ThreadMiningPoolCommandLines = new Thread(delegate() { while (!Exit) { string commandLine = Console.ReadLine(); try { var splitCommandLine = commandLine.Split(new char[0], StringSplitOptions.None); switch (splitCommandLine[0].ToLower()) { case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineHelp: ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineHelp + " - Command line to get list of commands details.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineStats + " - Show mining pool stats.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineBanMiner + " - ban a miner wallet address, syntax: " + MiningPoolCommandLinesEnumeration.MiningPoolCommandLineBanMiner + " wallet_address time", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineBanMinerList + " - Show the list of miner wallet address banned.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineUnBanMiner + " - Permit to unban a wallet address, syntax: " + MiningPoolCommandLinesEnumeration.MiningPoolCommandLineUnBanMiner + " wallet_address", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog(MiningPoolCommandLinesEnumeration.MiningPoolCommandLineExit + " - Stop mining pool, save and exit.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); break; case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineStats: ClassLog.ConsoleWriteLog("Mining Pool Stats: ", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog("Total miners connected: " + ClassMiningPoolGlobalStats.TotalWorkerConnected, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog("Total blocks found: " + ClassMiningPoolGlobalStats.TotalBlockFound, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog("Total miners hashrate: " + ClassMiningPoolGlobalStats.TotalMinerHashrate.ToString("F2"), ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog("Pool Wallet Total Balance: " + ClassMiningPoolGlobalStats.PoolCurrentBalance + " " + ClassConnectorSetting.CoinNameMin, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); ClassLog.ConsoleWriteLog("Pool Wallet Total Balance in Pending: " + ClassMiningPoolGlobalStats.PoolPendingBalance + " " + ClassConnectorSetting.CoinNameMin, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); if (ClassNetworkBlockchain.IsConnected) { ClassLog.ConsoleWriteLog("Mining pool is connected to retrieve last blocktemplate.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleMagentaLog, true); } else { ClassLog.ConsoleWriteLog("Mining pool is not connected to retrieve last blocktemplate.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } break; case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineBanMiner: string walletAddress = splitCommandLine[1]; if (!ClassMinerStats.ManualBanWalletAddress(walletAddress, int.Parse(splitCommandLine[2]))) { ClassLog.ConsoleWriteLog("Cannot ban wallet address: " + walletAddress + " because this one not exist.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } else { ClassLog.ConsoleWriteLog("Wallet address: " + walletAddress + " is banned successfully pending " + splitCommandLine[2] + " second(s).", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } break; case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineBanMinerList: if (ClassMinerStats.DictionaryMinerStats.Count > 0) { int totalBanned = 0; foreach (var minerStats in ClassMinerStats.DictionaryMinerStats) { if (minerStats.Value.IsBanned) { long minerBanTime = minerStats.Value.DateOfBan - DateTimeOffset.Now.ToUnixTimeSeconds(); ClassLog.ConsoleWriteLog("Wallet address: " + minerStats.Key + " is banned pending: " + minerBanTime + " second(s).", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); totalBanned++; } else { if (minerStats.Value.TotalBan > MiningPoolSetting.MiningPoolMaxTotalBanMiner) { ClassLog.ConsoleWriteLog("Wallet address: " + minerStats.Key + " is banned forever (until to restart the pool or manual unban).", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); totalBanned++; } } } if (totalBanned == 0) { ClassLog.ConsoleWriteLog("Their is any miner(s) banned.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); } } break; case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineUnBanMiner: if (ClassMinerStats.DictionaryMinerStats.Count > 0) { if (ClassMinerStats.DictionaryMinerStats.ContainsKey(splitCommandLine[1])) { ClassMinerStats.DictionaryMinerStats[splitCommandLine[1]].DateOfBan = 0; ClassMinerStats.DictionaryMinerStats[splitCommandLine[1]].IsBanned = false; ClassMinerStats.DictionaryMinerStats[splitCommandLine[1]].TotalBan = 0; ClassLog.ConsoleWriteLog("Miner wallet address: " + splitCommandLine[1] + " is unbanned.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); } else { ClassLog.ConsoleWriteLog("Miner wallet address: " + splitCommandLine[1] + " not exist.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); } } else { ClassLog.ConsoleWriteLog("Miner wallet address: " + splitCommandLine[1] + " not exist.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); } break; case MiningPoolCommandLinesEnumeration.MiningPoolCommandLineExit: if (ClassPayment.PoolOnSendingTransaction) { ClassLog.ConsoleWriteLog("Can't close mining pool, the pool is currently on sending transaction(s).", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } else { if (ClassPayment.PoolOnProceedBlockReward) { ClassLog.ConsoleWriteLog("Can't close mining pool, the pool is currently on proceed block reward(s).", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } else { Exit = true; new Thread(delegate() { if (ListMiningPool.Count > 0) { foreach (var miningPool in ListMiningPool) { miningPool.Value.StopMiningPool(); } } ClassApi.StopApiHttpServer(); ClassMinerStats.StopCheckMinerStats(); ClassPayment.StopAutoPaymentSystem(); ClassFilteringMiner.StopFileringMiner(); ClassMiningPoolDatabase.StopAutoSaveMiningPoolDatabases(); ClassLog.ConsoleWriteLog("Mining pool stopped.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleBlueLog, true); ClassLog.StopLogSystem(); if (ThreadMiningPoolCommandLines != null && (ThreadMiningPoolCommandLines.IsAlive || ThreadMiningPoolCommandLines != null)) { ThreadMiningPoolCommandLines.Abort(); GC.SuppressFinalize(ThreadMiningPoolCommandLines); } }).Start(); } } break; } } catch (Exception error) { ClassLog.ConsoleWriteLog("Error on command line: " + commandLine + " exception: " + error.Message, ClassLogEnumeration.IndexPoolGeneralErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } }); ThreadMiningPoolCommandLines.Start(); }
/// <summary> /// Initialization of the mining pool. /// </summary> /// <returns></returns> private static bool InitializeMiningPool() { ClassLog.ConsoleWriteLog("Initialize Log system..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); if (ClassLog.LogInitialization()) { ClassLog.ConsoleWriteLog("Initialize pool settings..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); if (MiningPoolSettingInitialization.InitializationPoolSettingFile()) { ClassLog.ConsoleWriteLog("Pool settings initialized.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); ClassLog.ConsoleWriteLog("Intialize pool databases..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); if (ClassMiningPoolDatabase.InitializationMiningPoolDatabases()) { ClassMiningPoolDatabase.AutoSaveMiningPoolDatabases(); ClassLog.ConsoleWriteLog("Pool databases initialized.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); ClassLog.ConsoleWriteLog("Log System initialized.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); ThreadNetworkBlockchain = new Thread(async delegate() { ClassLog.ConsoleWriteLog("Connect Pool to the network for retrieve current blocktemplate..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); bool notConnected = true; while (notConnected) { Certificate = ClassUtils.GenerateCertificate(); while (!await ClassNetworkBlockchain.ConnectToBlockchainAsync()) { Thread.Sleep(5000); ClassLog.ConsoleWriteLog("Can't connect Pool to the network, retry in 5 seconds.. (Press CTRL+C to cancel and close the pool.)", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } Certificate = ClassUtils.GenerateCertificate(); ClassLog.ConsoleWriteLog("Certificate generate, send to the network..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); if (!await ClassNetworkBlockchain.SendPacketToNetworkBlockchain(Certificate, false)) { ClassLog.ConsoleWriteLog("Can't send certificate, reconnect now..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } else { ClassLog.ConsoleWriteLog("Certificate sent, start to login..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); ClassNetworkBlockchain.ListenBlockchain(); Thread.Sleep(1000); if (!await ClassNetworkBlockchain.SendPacketToNetworkBlockchain(ClassConnectorSettingEnumeration.MinerLoginType + "|" + MiningPoolSetting.MiningPoolWalletAddress, true)) { ClassLog.ConsoleWriteLog("Can't login to the network, reconnect now.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } else { ClassLog.ConsoleWriteLog("Login successfully sent, waiting confirmation..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); notConnected = false; } } if (notConnected) { ClassLog.ConsoleWriteLog("Can't long Pool to the network, retry in 5 seconds.. (Press CTRL+C to cancel and close the pool.)", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); Thread.Sleep(5000); } else { break; } } }) { IsBackground = true }; ThreadNetworkBlockchain.Start(); if (MiningPoolSetting.MiningPoolEnableFiltering) { ClassLog.ConsoleWriteLog("Enable Filtering Miner System..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); ClassFilteringMiner.EnableFilteringMiner(); } if (MiningPoolSetting.MiningPoolEnableCheckMinerStats) { ClassLog.ConsoleWriteLog("Enable Check Miner Stats System..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); ClassMinerStats.EnableCheckMinerStats(); } if (MiningPoolSetting.MiningPoolEnableTrustedShare) { ClassLog.ConsoleWriteLog("Enable Trusted Share System..", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); ClassMinerStats.EnableCheckTrustedMinerStats(); } if (MiningPoolSetting.MiningPoolEnablePayment) { ClassPayment.EnableAutoPaymentSystem(); } if (MiningPoolSetting.MiningPoolMiningPort.Count > 0) { foreach (var miningPoolPort in MiningPoolSetting.MiningPoolMiningPort) { var miningPoolObject = new ClassMiningPool(miningPoolPort.Key, miningPoolPort.Value); miningPoolObject.StartMiningPool(); ListMiningPool.Add(miningPoolPort.Key, miningPoolObject); } ClassApi.StartApiHttpServer(); EnableMiningPoolCommandLine(); } else { ClassLog.ConsoleWriteLog("Cannot start mining pool, their is any ports on the setting.", ClassLogEnumeration.IndexPoolGeneralErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); return(false); } } else { return(false); } } else { return(false); } } else { return(false); } return(true); }
/// <summary> /// Enable auto payment system. /// </summary> public static void EnableAutoPaymentSystem() { if (ThreadAutoPaymentSystem != null && (ThreadAutoPaymentSystem.IsAlive || ThreadAutoPaymentSystem != null)) { ThreadAutoPaymentSystem.Abort(); GC.SuppressFinalize(ThreadAutoPaymentSystem); } if (MiningPoolSetting.MiningPoolIntervalPayment > 0) { if (MiningPoolSetting.MiningPoolMinimumBalancePayment > 0) { if (MiningPoolSetting.MiningPoolFeeTransactionPayment > 0) { if (MiningPoolSetting.MiningPoolFeeTransactionPayment >= ClassConnectorSetting.MinimumWalletTransactionFee) { ThreadAutoPaymentSystem = new Thread(async delegate() { while (!Program.Exit) { try { if (!PoolOnProceedBlockReward) { PoolOnSendingTransaction = true; if (await ClassRpcWallet.GetCurrentBalance()) { ClassLog.ConsoleWriteLog("Start to proceed payments.", ClassLogEnumeration.IndexPoolPaymentLog); if (ClassMinerStats.DictionaryMinerStats.Count > 0) { foreach (var minerStats in ClassMinerStats.DictionaryMinerStats) { if (minerStats.Value.TotalBan <= MiningPoolSetting.MiningPoolMaxTotalBanMiner) { if (minerStats.Value.TotalBalance >= MiningPoolSetting.MiningPoolMinimumBalancePayment) { if (minerStats.Value.CustomMinimumPayment == 0 || minerStats.Value.TotalBalance >= minerStats.Value.CustomMinimumPayment) // Make payment if the miner don't have select a custom minimum payment or when his current balance reach his custom minimum payment set. { if (await ClassRpcWallet.GetCurrentBalance()) { if (minerStats.Value.TotalBalance <= ClassMiningPoolGlobalStats.PoolCurrentBalance) { decimal minersBalanceBase = minerStats.Value.TotalBalance; decimal minersBalance = minerStats.Value.TotalBalance; minersBalance = minersBalance - MiningPoolSetting.MiningPoolFeeTransactionPayment; ClassLog.ConsoleWriteLog("Attempt to send transaction of " + minersBalance + " " + ClassConnectorSetting.CoinNameMin + " to miner " + minerStats.Key, ClassLogEnumeration.IndexPoolPaymentLog); long dateSent = ClassUtility.GetCurrentDateInSecond(); string resultPayment = await ClassRpcWallet.SendTransaction(minerStats.Key, minersBalance); if (resultPayment != string.Empty) { var resultPaymentSplit = resultPayment.Split(new[] { "|" }, StringSplitOptions.None); switch (resultPaymentSplit[0]) { case ClassRpcWalletCommand.SendTokenTransactionConfirmed: minerStats.Value.TotalBalance -= minersBalanceBase; minerStats.Value.TotalPaid += minersBalanceBase; ClassMiningPoolGlobalStats.PoolTotalPaid += minersBalanceBase; ClassMinerStats.InsertTransactionPayment(minerStats.Key, resultPaymentSplit[1], minersBalance, dateSent); ClassLog.ConsoleWriteLog("Transaction sent to miner " + minerStats.Key + " is confirmed, transaction hash: " + resultPaymentSplit[1], ClassLogEnumeration.IndexPoolPaymentLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); break; default: ClassLog.ConsoleWriteLog("Transaction sent to miner " + minerStats.Key + " is not confirmed, response received: " + resultPaymentSplit[0], ClassLogEnumeration.IndexPoolPaymentLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); break; } } else { ClassLog.ConsoleWriteLog("No response from RPC Wallet to proceed payment to miner: " + minerStats.Key, ClassLogEnumeration.IndexPoolPaymentErrorLog); } } else { ClassLog.ConsoleWriteLog("Can't proceed payment to miner: " + minerStats.Key + ", not enought coin on the pool wallet. | " + minerStats.Value.TotalBalance + "/" + ClassMiningPoolGlobalStats.PoolCurrentBalance, ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } else { ClassLog.ConsoleWriteLog("Can't proceed payment to miner: " + minerStats.Key + ", cannot get current pool balance.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } } } else { ClassLog.ConsoleWriteLog("Can't proceed payment to miner: " + minerStats.Key + ", the miner have reach too much ban.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog); } } } ClassLog.ConsoleWriteLog("End to proceed payments.", ClassLogEnumeration.IndexPoolPaymentLog); } else { ClassLog.ConsoleWriteLog("Can't proceed payment, cannot get current pool balance.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } PoolOnSendingTransaction = false; } else { ClassLog.ConsoleWriteLog("Pool currently on proceed block reward, payments will are launch after.", ClassLogEnumeration.IndexPoolPaymentLog, ClassLogConsoleEnumeration.IndexPoolConsoleYellowLog, true); } } catch (Exception error) { PoolOnSendingTransaction = false; ClassLog.ConsoleWriteLog("Proceed payments exception error: " + error.Message, ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } Thread.Sleep(MiningPoolSetting.MiningPoolIntervalPayment * 1000); } }); ThreadAutoPaymentSystem.Start(); } else { ClassLog.ConsoleWriteLog("Warning, the transaction " + ClassConnectorSetting.CoinNameMin + " fee is less than the minimum accepted of: " + ClassConnectorSetting.MinimumWalletTransactionFee + ", the payment system will not be enabled.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } else { ClassLog.ConsoleWriteLog("Warning, the transaction " + ClassConnectorSetting.CoinNameMin + " fee is less or equals of 0, the payment system will not be enabled.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } else { ClassLog.ConsoleWriteLog("Warning, the minimum of " + ClassConnectorSetting.CoinNameMin + " to reach for proceed payment, is less or equals of 0, the payment system will not be enabled.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } } else { ClassLog.ConsoleWriteLog("Warning, the interval of payment is less or equals of 0 second, the payment system will not be enabled.", ClassLogEnumeration.IndexPoolPaymentErrorLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); } }