/// <summary> /// Permit to ban manualy a wallet address with a delay selected. /// </summary> /// <param name="wallet"></param> /// <param name="time"></param> /// <returns></returns> public static bool ManualBanWalletAddress(string walletAddress, int time) { if (DictionaryMinerStats.ContainsKey(walletAddress)) { DictionaryMinerStats[walletAddress].DateOfBan = ClassUtility.GetCurrentDateInSecond() + time; DictionaryMinerStats[walletAddress].IsBanned = true; return(true); } return(false); }
/// <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); } }
/// <summary> /// Handle packet received from the network. /// </summary> /// <param name="packet"></param> private static async Task HandlePacketNetworkAsync(string packet) { packet = packet.Replace("*", ""); var packetSplit = packet.Split(new[] { "|" }, StringSplitOptions.None); switch (packetSplit[0]) { case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.SendLoginAccepted: LoginAccepted = true; ClassLog.ConsoleWriteLog("Mining pool logged successfully to the blockchain network.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); AskMiningMethod(); break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.SendListBlockMethod: var methodList = packetSplit[1]; if (methodList.Contains("#")) { var splitMethodList = methodList.Split(new[] { "#" }, StringSplitOptions.None); if (ListOfMiningMethodName.Count > 1) { foreach (var methodName in splitMethodList) { if (!string.IsNullOrEmpty(methodName)) { if (ListOfMiningMethodName.Contains(methodName) == false) { ListOfMiningMethodName.Add(methodName); } if (!await SendPacketToNetworkBlockchain(ClassSoloMiningPacketEnumeration.SoloMiningSendPacketEnumeration.ReceiveAskContentBlockMethod + "|" + methodName, true).ConfigureAwait(false)) { IsConnected = false; break; } await Task.Delay(1000); } } } else { foreach (var methodName in splitMethodList) { if (!string.IsNullOrEmpty(methodName)) { if (ListOfMiningMethodName.Contains(methodName) == false) { ListOfMiningMethodName.Add(methodName); } if (!await SendPacketToNetworkBlockchain(ClassSoloMiningPacketEnumeration.SoloMiningSendPacketEnumeration.ReceiveAskContentBlockMethod + "|" + methodName, true).ConfigureAwait(false)) { IsConnected = false; break; } await Task.Delay(1000); } } } } else { if (ListOfMiningMethodName.Contains(methodList) == false) { ListOfMiningMethodName.Add(methodList); } if (!await SendPacketToNetworkBlockchain(ClassSoloMiningPacketEnumeration.SoloMiningSendPacketEnumeration.ReceiveAskContentBlockMethod + "|" + methodList, true).ConfigureAwait(false)) { IsConnected = false; } } break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.SendContentBlockMethod: if (ListOfMiningMethodContent.Count == 0) { ListOfMiningMethodContent.Add(packetSplit[1]); } else { ListOfMiningMethodContent[0] = packetSplit[1]; } break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.SendCurrentBlockMining: if (packetSplit[1] != ClassMiningPoolGlobalStats.CurrentBlockTemplate) { var splitBlockContent = packetSplit[1].Split(new[] { "&" }, StringSplitOptions.None); if (splitBlockContent[0].Replace("ID=", "") != "" && splitBlockContent[0].Replace("ID=", "").Length > 0) { if (splitBlockContent[0].Replace("ID=", "") != ClassMiningPoolGlobalStats.CurrentBlockId) { ClassMiningPoolGlobalStats.CurrentBlockId = splitBlockContent[0].Replace("ID=", ""); ClassMiningPoolGlobalStats.CurrentBlockHash = splitBlockContent[1].Replace("HASH=", ""); ClassMiningPoolGlobalStats.CurrentBlockAlgorithm = splitBlockContent[2].Replace("ALGORITHM=", ""); ClassMiningPoolGlobalStats.CurrentBlockSize = splitBlockContent[3].Replace("SIZE=", ""); ClassMiningPoolGlobalStats.CurrentBlockMethod = splitBlockContent[4].Replace("METHOD=", ""); ClassMiningPoolGlobalStats.CurrentBlockKey = splitBlockContent[5].Replace("KEY=", ""); ClassMiningPoolGlobalStats.CurrentBlockJob = splitBlockContent[6].Replace("JOB=", ""); ClassMiningPoolGlobalStats.CurrentBlockJobMinRange = decimal.Parse(ClassMiningPoolGlobalStats.CurrentBlockJob.Split(new[] { ";" }, StringSplitOptions.None)[0]); ClassMiningPoolGlobalStats.CurrentBlockJobMaxRange = decimal.Parse(ClassMiningPoolGlobalStats.CurrentBlockJob.Split(new[] { ";" }, StringSplitOptions.None)[1]); ClassMiningPoolGlobalStats.CurrentBlockReward = splitBlockContent[7].Replace("REWARD=", ""); ClassMiningPoolGlobalStats.CurrentBlockDifficulty = splitBlockContent[8].Replace("DIFFICULTY=", ""); ClassMiningPoolGlobalStats.CurrentBlockTimestampCreate = splitBlockContent[9].Replace("TIMESTAMP=", ""); ClassMiningPoolGlobalStats.CurrentBlockIndication = splitBlockContent[10].Replace("INDICATION=", ""); ClassMiningPoolGlobalStats.CurrentBlockTemplate = packetSplit[1]; int idMethod = 0; if (ListOfMiningMethodName.Count > 0) { for (int i = 0; i < ListOfMiningMethodName.Count; i++) { if (i < ListOfMiningMethodName.Count) { if (ListOfMiningMethodName[i] == ClassMiningPoolGlobalStats.CurrentBlockMethod) { idMethod = i; } } } } var splitMethod = ListOfMiningMethodContent[idMethod].Split(new[] { "#" }, StringSplitOptions.None); ClassMiningPoolGlobalStats.CurrentRoundAesRound = int.Parse(splitMethod[0]); ClassMiningPoolGlobalStats.CurrentRoundAesSize = int.Parse(splitMethod[1]); ClassMiningPoolGlobalStats.CurrentRoundAesKey = splitMethod[2]; ClassMiningPoolGlobalStats.CurrentRoundXorKey = int.Parse(splitMethod[3]); using (var pdb = new PasswordDeriveBytes(ClassMiningPoolGlobalStats.CurrentBlockKey, Encoding.UTF8.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesKey))) { ClassMiningPoolGlobalStats.CurrentAesKeyIv = pdb.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesSize / 8); ClassMiningPoolGlobalStats.CurrentAesSalt = pdb.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesSize / 8); } if (ClassMinerStats.DictionaryMinerStats.Count > 0) { foreach (var miner in ClassMinerStats.DictionaryMinerStats) { if (miner.Value.ListOfMinerTcpObject.Count > 0) { for (int i = 0; i < miner.Value.ListOfMinerTcpObject.Count; i++) { if (i < miner.Value.ListOfMinerTcpObject.Count) { if (miner.Value.ListOfMinerTcpObject[i] != null) { if (miner.Value.ListOfMinerTcpObject[i].IsLogged) { miner.Value.ListOfMinerTcpObject[i].MiningPoolSendJobAsync(miner.Value.ListOfMinerTcpObject[i].CurrentMiningJobDifficulty); } } } } } } } ClassLog.ConsoleWriteLog("New block to mining id: " + ClassMiningPoolGlobalStats.CurrentBlockId + " difficulty: " + ClassMiningPoolGlobalStats.CurrentBlockDifficulty + " hash: " + ClassMiningPoolGlobalStats.CurrentBlockHash, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleBlueLog, true); ClassLog.ConsoleWriteLog("Current Mining Method: " + ClassMiningPoolGlobalStats.CurrentBlockMethod + " = AES ROUND: " + ClassMiningPoolGlobalStats.CurrentRoundAesRound + " AES SIZE: " + ClassMiningPoolGlobalStats.CurrentRoundAesSize + " AES BYTE KEY: " + ClassMiningPoolGlobalStats.CurrentRoundAesKey + " XOR KEY: " + ClassMiningPoolGlobalStats.CurrentRoundXorKey, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleBlueLog, true); } else { if (splitBlockContent[1].Replace("HASH=", "") != ClassMiningPoolGlobalStats.CurrentBlockHash) { ClassMiningPoolGlobalStats.CurrentBlockId = splitBlockContent[0].Replace("ID=", ""); ClassMiningPoolGlobalStats.CurrentBlockHash = splitBlockContent[1].Replace("HASH=", ""); ClassMiningPoolGlobalStats.CurrentBlockAlgorithm = splitBlockContent[2].Replace("ALGORITHM=", ""); ClassMiningPoolGlobalStats.CurrentBlockSize = splitBlockContent[3].Replace("SIZE=", ""); ClassMiningPoolGlobalStats.CurrentBlockMethod = splitBlockContent[4].Replace("METHOD=", ""); ClassMiningPoolGlobalStats.CurrentBlockKey = splitBlockContent[5].Replace("KEY=", ""); ClassMiningPoolGlobalStats.CurrentBlockJob = splitBlockContent[6].Replace("JOB=", ""); ClassMiningPoolGlobalStats.CurrentBlockJobMinRange = decimal.Parse(ClassMiningPoolGlobalStats.CurrentBlockJob.Split(new[] { ";" }, StringSplitOptions.None)[0]); ClassMiningPoolGlobalStats.CurrentBlockJobMaxRange = decimal.Parse(ClassMiningPoolGlobalStats.CurrentBlockJob.Split(new[] { ";" }, StringSplitOptions.None)[1]); ClassMiningPoolGlobalStats.CurrentBlockReward = splitBlockContent[7].Replace("REWARD=", ""); ClassMiningPoolGlobalStats.CurrentBlockDifficulty = splitBlockContent[8].Replace("DIFFICULTY=", ""); ClassMiningPoolGlobalStats.CurrentBlockTimestampCreate = splitBlockContent[9].Replace("TIMESTAMP=", ""); ClassMiningPoolGlobalStats.CurrentBlockIndication = splitBlockContent[10].Replace("INDICATION=", ""); ClassMiningPoolGlobalStats.CurrentBlockTemplate = packetSplit[1]; int idMethod = 0; if (ListOfMiningMethodName.Count > 0) { for (int i = 0; i < ListOfMiningMethodName.Count; i++) { if (i < ListOfMiningMethodName.Count) { if (ListOfMiningMethodName[i] == ClassMiningPoolGlobalStats.CurrentBlockMethod) { idMethod = i; } } } } var splitMethod = ListOfMiningMethodContent[idMethod].Split(new[] { "#" }, StringSplitOptions.None); ClassMiningPoolGlobalStats.CurrentRoundAesRound = int.Parse(splitMethod[0]); ClassMiningPoolGlobalStats.CurrentRoundAesSize = int.Parse(splitMethod[1]); ClassMiningPoolGlobalStats.CurrentRoundAesKey = splitMethod[2]; ClassMiningPoolGlobalStats.CurrentRoundXorKey = int.Parse(splitMethod[3]); using (var pdb = new PasswordDeriveBytes(ClassMiningPoolGlobalStats.CurrentBlockKey, Encoding.UTF8.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesKey))) { ClassMiningPoolGlobalStats.CurrentAesKeyIv = pdb.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesSize / 8); ClassMiningPoolGlobalStats.CurrentAesSalt = pdb.GetBytes(ClassMiningPoolGlobalStats.CurrentRoundAesSize / 8); } if (ClassMinerStats.DictionaryMinerStats.Count > 0) { foreach (var miner in ClassMinerStats.DictionaryMinerStats) { if (miner.Value.ListOfMinerTcpObject.Count > 0) { for (int i = 0; i < miner.Value.ListOfMinerTcpObject.Count; i++) { if (i < miner.Value.ListOfMinerTcpObject.Count) { if (miner.Value.ListOfMinerTcpObject[i] != null) { if (miner.Value.ListOfMinerTcpObject[i].IsLogged) { miner.Value.ListOfMinerTcpObject[i].MiningPoolSendJobAsync(miner.Value.ListOfMinerTcpObject[i].CurrentMiningJobDifficulty); } } } } } } } ClassLog.ConsoleWriteLog("Renewed block to mining id: " + ClassMiningPoolGlobalStats.CurrentBlockId + " difficulty: " + ClassMiningPoolGlobalStats.CurrentBlockDifficulty + " hash: " + ClassMiningPoolGlobalStats.CurrentBlockHash, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleBlueLog, true); ClassLog.ConsoleWriteLog("Current Mining Method: " + ClassMiningPoolGlobalStats.CurrentBlockMethod + " = AES ROUND: " + ClassMiningPoolGlobalStats.CurrentRoundAesRound + " AES SIZE: " + ClassMiningPoolGlobalStats.CurrentRoundAesSize + " AES BYTE KEY: " + ClassMiningPoolGlobalStats.CurrentRoundAesKey + " XOR KEY: " + ClassMiningPoolGlobalStats.CurrentRoundXorKey, ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleBlueLog, true); } } } } break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.SendJobStatus: switch (packetSplit[1]) { case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.ShareUnlock: ClassLog.ConsoleWriteLog("Block ID: " + packetSplit[2] + " has been successfully found and accepted by Blockchain !", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleGreenLog, true); ClassMiningPoolGlobalStats.ListBlockFound.Add(ClassMiningPoolGlobalStats.ListBlockFound.Count, int.Parse(packetSplit[2]) + "|" + ClassUtility.GetCurrentDateInSecond()); await Task.Factory.StartNew(() => ClassPayment.ProceedMiningScoreRewardAsync(packetSplit[2]), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Current).ConfigureAwait(false); break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.ShareBad: ClassLog.ConsoleWriteLog("Block ID: " + packetSplit[2] + " has been found by someone else before the pool or the share sent is invalid.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); break; case ClassSoloMiningPacketEnumeration.SoloMiningRecvPacketEnumeration.ShareAleady: ClassLog.ConsoleWriteLog("Block ID: " + packetSplit[2] + " is already found by someone else.", ClassLogEnumeration.IndexPoolGeneralLog, ClassLogConsoleEnumeration.IndexPoolConsoleRedLog, true); break; } break; } }