/// <summary> /// Catch unexpected exception and them to a log file. /// </summary> private static void EnableCatchUnexpectedException() { AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs args2) { var filePath = ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + UnexpectedExceptionFile); var exception = (Exception)args2.ExceptionObject; using (var writer = new StreamWriter(filePath, true)) { writer.WriteLine("Message :" + exception.Message + "<br/>" + Environment.NewLine + "StackTrace :" + exception.StackTrace + "" + Environment.NewLine + "Date :" + DateTime.Now); writer.WriteLine(Environment.NewLine + "-----------------------------------------------------------------------------" + Environment.NewLine); } Trace.TraceError(exception.StackTrace); Console.WriteLine("Unexpected error catched, check the error file: " + ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + UnexpectedExceptionFile)); Environment.Exit(1); }; }
/// <summary> /// Initilize mining configuration. /// </summary> /// <returns></returns> public static void MiningConfigInitialization() { if (File.Exists(ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + MiningConfigFile))) { using (var streamReaderConfigPool = new StreamReader(ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + MiningConfigFile))) { int numberOfLines = 0; string line = string.Empty; while ((line = streamReaderConfigPool.ReadLine()) != null) { numberOfLines++; if (!string.IsNullOrEmpty(line)) { if (!line.StartsWith("/")) { if (line.Contains("=")) { var splitLine = line.Split(new[] { "=" }, StringSplitOptions.None); if (splitLine.Length > 1) { try { #if DEBUG Debug.WriteLine("Config line read: " + splitLine[0] + " argument read: " + splitLine[1]); #endif switch (splitLine[0]) { case ClassMiningConfigEnumeration.MiningConfigPoolHost: MiningPoolHost = splitLine[1]; break; case ClassMiningConfigEnumeration.MiningConfigPoolPort: MiningPoolPort = int.Parse(splitLine[1]); break; case ClassMiningConfigEnumeration.MiningConfigWalletAdress: MiningWalletAddress = splitLine[1]; break; case ClassMiningConfigEnumeration.MiningConfigThread: MiningConfigThread = int.Parse(splitLine[1]); break; case ClassMiningConfigEnumeration.MiningConfigThreadIntensity: MiningConfigThreadIntensity = int.Parse(splitLine[1]); if (MiningConfigThreadIntensity > 4) { MiningConfigThreadIntensity = 4; } if (MiningConfigThreadIntensity < 0) { MiningConfigThreadIntensity = 0; } break; } } catch { Console.WriteLine("Error on line:" + numberOfLines); } } #if DEBUG else { Debug.WriteLine("Error on config line: " + splitLine[0] + " on line:" + numberOfLines); } #endif } } } } } } else { File.Create(ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + MiningConfigFile)).Close(); ClassConsole.ConsoleWriteLine("Write your wallet address: ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); string tmpwall = Console.ReadLine(); while (tmpwall.Length > ClassConnectorSetting.MaxWalletAddressSize || tmpwall.Length < ClassConnectorSetting.MinWalletAddressSize) { ClassConsole.ConsoleWriteLine("Input wallet address is wrong, Xiropht wallet addresses are between 48 and 96 characters long, please try again: ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); tmpwall = Console.ReadLine(); } MiningWalletAddress = tmpwall; ClassConsole.ConsoleWriteLine("Write the mining pool host: ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); MiningPoolHost = Console.ReadLine(); ClassConsole.ConsoleWriteLine("Write the mining pool port: ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); int portTmp = 0; while (!int.TryParse(Console.ReadLine(), out portTmp)) { ClassConsole.ConsoleWriteLine("Input port is wrong, please try again: ", ClassConsoleEnumeration.IndexPoolConsoleRedLog); } MiningPoolPort = portTmp; ClassConsole.ConsoleWriteLine("Select the number of thread to use, detected thread " + Environment.ProcessorCount + ": ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); int threadTmp = 0; while (!int.TryParse(Console.ReadLine(), out threadTmp)) { ClassConsole.ConsoleWriteLine("Input number of thread is wrong, please try again: ", ClassConsoleEnumeration.IndexPoolConsoleRedLog); } MiningConfigThread = threadTmp; ClassConsole.ConsoleWriteLine("Select the intensity of thread(s) to use, min 0 | max 4: ", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); int threadIntensityTmp = 0; while (!int.TryParse(Console.ReadLine(), out threadIntensityTmp)) { ClassConsole.ConsoleWriteLine("Input intensity of thread(s) is wrong, please try again: ", ClassConsoleEnumeration.IndexPoolConsoleRedLog); } MiningConfigThreadIntensity = threadIntensityTmp; if (MiningConfigThreadIntensity > 4) { MiningConfigThreadIntensity = 4; } if (MiningConfigThreadIntensity < 0) { MiningConfigThreadIntensity = 0; } using (var streamWriterConfigMiner = new StreamWriter(ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + MiningConfigFile)) { AutoFlush = true }) { streamWriterConfigMiner.WriteLine(ClassMiningConfigEnumeration.MiningConfigWalletAdress + "=" + MiningWalletAddress); streamWriterConfigMiner.WriteLine(ClassMiningConfigEnumeration.MiningConfigPoolHost + "=" + MiningPoolHost); streamWriterConfigMiner.WriteLine(ClassMiningConfigEnumeration.MiningConfigPoolPort + "=" + MiningPoolPort); streamWriterConfigMiner.WriteLine(ClassMiningConfigEnumeration.MiningConfigThread + "=" + MiningConfigThread); streamWriterConfigMiner.WriteLine(ClassMiningConfigEnumeration.MiningConfigThreadIntensity + "=" + MiningConfigThreadIntensity); } ClassConsole.ConsoleWriteLine(ClassUtility.ConvertPath(Directory.GetCurrentDirectory() + MiningConfigFile) + " miner config file saved", ClassConsoleEnumeration.IndexPoolConsoleGreenLog); } }
/// <summary> /// Start thread mining. /// </summary> private static async Task StartThreadMiningAsync(int idThread) { decimal minRange = Math.Round((ClassMiningStats.CurrentBlockDifficulty / ClassMiningConfig.MiningConfigThread) * (idThread - 1), 0); if (minRange <= 1) { minRange = 2; } decimal maxRange = Math.Round(((ClassMiningStats.CurrentBlockDifficulty / ClassMiningConfig.MiningConfigThread) * idThread), 0); ClassConsole.ConsoleWriteLine("Start mining thread id: " + idThread + " on mining job: " + ClassMiningStats.CurrentMiningDifficulty + " with range: " + minRange + "|" + maxRange, ClassConsoleEnumeration.IndexPoolConsoleBlueLog); var currentMiningJobIndication = ClassMiningStats.CurrentJobIndication; int currentBlockDifficultyLength = ClassMiningStats.CurrentMiningDifficulty.ToString().Length; while (ClassMiningNetwork.IsLogged && ThreadMiningRunning) { if (currentMiningJobIndication != ClassMiningStats.CurrentJobIndication) { minRange = Math.Round((ClassMiningStats.CurrentBlockDifficulty / ClassMiningConfig.MiningConfigThread) * (idThread - 1), 0); if (minRange <= 1) { minRange = 2; } maxRange = (Math.Round(((ClassMiningStats.CurrentBlockDifficulty / ClassMiningConfig.MiningConfigThread) * idThread), 0)); maxRange = Math.Round(maxRange, 0); currentMiningJobIndication = ClassMiningStats.CurrentJobIndication; ClassConsole.ConsoleWriteLine("Start mining thread id: " + idThread + " on mining job difficulty: " + ClassMiningStats.CurrentMiningDifficulty + " with range: " + minRange + "|" + maxRange, ClassConsoleEnumeration.IndexPoolConsoleBlueLog); currentBlockDifficultyLength = ClassMiningStats.CurrentMiningDifficulty.ToString().Length; } string firstNumber = string.Empty; string secondNumber = string.Empty; if (ClassUtils.GetRandomBetween(0, 100) >= ClassUtils.GetRandomBetween(0, 100)) { firstNumber = ClassUtility.GenerateNumberMathCalculation(minRange, maxRange, currentBlockDifficultyLength); } else { firstNumber = ClassUtility.GetRandomBetweenJob(minRange, maxRange).ToString(); } if (ClassUtils.GetRandomBetween(0, 100) >= ClassUtils.GetRandomBetween(0, 100)) { secondNumber = ClassUtility.GenerateNumberMathCalculation(minRange, maxRange, currentBlockDifficultyLength); } else { secondNumber = ClassUtility.GetRandomBetweenJob(minRange, maxRange).ToString(); } for (int i = 0; i < ClassUtility.RandomOperatorCalculation.Length; i++) { if (i < ClassUtility.RandomOperatorCalculation.Length) { #region Test unreverted calculation string calculation = firstNumber + " " + ClassUtility.RandomOperatorCalculation[i] + " " + secondNumber; decimal calculationResult = ClassUtility.ComputeCalculation(firstNumber, ClassUtility.RandomOperatorCalculation[i], secondNumber); if (calculationResult >= ClassMiningStats.CurrentMinRangeJob && calculationResult <= ClassMiningStats.CurrentBlockDifficulty) { if (calculationResult - Math.Round(calculationResult, 0) == 0) // Check if the result contain decimal places, if yes ignore it. { string encryptedShare = MakeEncryptedShare(calculation, (idThread - 1)); if (encryptedShare != ClassAlgoErrorEnumeration.AlgoError) { // Generate SHA512 hash for block hash indication. string hashEncryptedShare = ClassUtility.GenerateSHA512(encryptedShare); string hashEncryptedShareForPool = ClassUtility.EncryptXorShare(hashEncryptedShare, ClassMiningStats.CurrentJobKeyEncryption); hashEncryptedShareForPool = ClassUtility.HashJobToHexString(hashEncryptedShareForPool); if (ClassMiningStats.CurrentJobIndication.ContainsKey(hashEncryptedShareForPool) || hashEncryptedShare == ClassMiningStats.CurrentBlockIndication) { if (!DictionaryShareSubmittedCache.ContainsKey(hashEncryptedShareForPool)) { try { DictionaryShareSubmittedCache.Add(hashEncryptedShareForPool, calculation); } catch { } JObject share = new JObject { { "type", ClassMiningRequest.TypeSubmit }, { ClassMiningRequest.SubmitResult, calculationResult.ToString("F0") }, { ClassMiningRequest.SubmitFirstNumber, firstNumber }, { ClassMiningRequest.SubmitSecondNumber, secondNumber }, { ClassMiningRequest.SubmitOperator, ClassUtility.RandomOperatorCalculation[i] }, { ClassMiningRequest.SubmitShare, encryptedShare }, { ClassMiningRequest.SubmitHash, hashEncryptedShareForPool } }; await ClassMiningNetwork.SendPacketToPoolAsync(share.ToString(Formatting.None)).ConfigureAwait(false); } } } } else // Test reverted { #region Test reverted calculation calculation = secondNumber + " " + ClassUtility.RandomOperatorCalculation[i] + " " + firstNumber; calculationResult = ClassUtility.ComputeCalculation(secondNumber, ClassUtility.RandomOperatorCalculation[i], firstNumber); if (calculationResult >= ClassMiningStats.CurrentMinRangeJob && calculationResult <= ClassMiningStats.CurrentBlockDifficulty) { if (calculationResult - Math.Round(calculationResult, 0) == 0) // Check if the result contain decimal places, if yes ignore it. { string encryptedShare = MakeEncryptedShare(calculation, (idThread - 1)); if (encryptedShare != ClassAlgoErrorEnumeration.AlgoError) { // Generate SHA512 hash for block hash indication. string hashEncryptedShare = ClassUtility.GenerateSHA512(encryptedShare); string hashEncryptedShareForPool = ClassUtility.EncryptXorShare(hashEncryptedShare, ClassMiningStats.CurrentJobKeyEncryption); hashEncryptedShareForPool = ClassUtility.HashJobToHexString(hashEncryptedShareForPool); if (ClassMiningStats.CurrentJobIndication.ContainsKey(hashEncryptedShareForPool) || hashEncryptedShare == ClassMiningStats.CurrentBlockIndication) { if (!DictionaryShareSubmittedCache.ContainsKey(hashEncryptedShareForPool)) { try { DictionaryShareSubmittedCache.Add(hashEncryptedShareForPool, calculation); } catch { } JObject share = new JObject { { "type", ClassMiningRequest.TypeSubmit }, { ClassMiningRequest.SubmitResult, calculationResult.ToString("F0") }, { ClassMiningRequest.SubmitFirstNumber, secondNumber }, { ClassMiningRequest.SubmitSecondNumber, firstNumber }, { ClassMiningRequest.SubmitOperator, ClassUtility.RandomOperatorCalculation[i] }, { ClassMiningRequest.SubmitShare, encryptedShare }, { ClassMiningRequest.SubmitHash, hashEncryptedShareForPool } }; await ClassMiningNetwork.SendPacketToPoolAsync(share.ToString(Formatting.None)).ConfigureAwait(false); } } } } } #endregion } } else // Test reverted { #region Test reverted calculation calculation = secondNumber + " " + ClassUtility.RandomOperatorCalculation[i] + " " + firstNumber; calculationResult = ClassUtility.ComputeCalculation(secondNumber, ClassUtility.RandomOperatorCalculation[i], firstNumber); if (calculationResult >= ClassMiningStats.CurrentMinRangeJob && calculationResult <= ClassMiningStats.CurrentBlockDifficulty) { if (calculationResult - Math.Round(calculationResult, 0) == 0) // Check if the result contain decimal places, if yes ignore it. { string encryptedShare = MakeEncryptedShare(calculation, (idThread - 1)); if (encryptedShare != ClassAlgoErrorEnumeration.AlgoError) { // Generate SHA512 hash for block hash indication. string hashEncryptedShare = ClassUtility.GenerateSHA512(encryptedShare); string hashEncryptedShareForPool = ClassUtility.EncryptXorShare(hashEncryptedShare, ClassMiningStats.CurrentJobKeyEncryption); hashEncryptedShareForPool = ClassUtility.HashJobToHexString(hashEncryptedShareForPool); if (ClassMiningStats.CurrentJobIndication.ContainsKey(hashEncryptedShareForPool) || hashEncryptedShare == ClassMiningStats.CurrentBlockIndication) { if (!DictionaryShareSubmittedCache.ContainsKey(hashEncryptedShareForPool)) { try { DictionaryShareSubmittedCache.Add(hashEncryptedShareForPool, calculation); } catch { } JObject share = new JObject { { "type", ClassMiningRequest.TypeSubmit }, { ClassMiningRequest.SubmitResult, calculationResult.ToString("F0") }, { ClassMiningRequest.SubmitFirstNumber, secondNumber }, { ClassMiningRequest.SubmitSecondNumber, firstNumber }, { ClassMiningRequest.SubmitOperator, ClassUtility.RandomOperatorCalculation[i] }, { ClassMiningRequest.SubmitShare, encryptedShare }, { ClassMiningRequest.SubmitHash, hashEncryptedShareForPool } }; await ClassMiningNetwork.SendPacketToPoolAsync(share.ToString(Formatting.None)).ConfigureAwait(false); } } } } } #endregion } #endregion } } } ThreadMiningRunning = false; }
/// <summary> /// Handle packets received from pool. /// </summary> /// <param name="packet"></param> private static void HandleMiningPoolPacket(JObject jsonPacket) { try { switch (jsonPacket["type"].ToString().ToLower()) { case ClassMiningRequest.TypeLogin: if (jsonPacket.ContainsKey(ClassMiningRequest.TypeLoginWrong)) { ClassConsole.ConsoleWriteLine("Wrong login/wallet address, please check your setting. Disconnect now.", ClassConsoleEnumeration.IndexPoolConsoleRedLog); DisconnectMiner(); } else { if (jsonPacket.ContainsKey(ClassMiningRequest.TypeLoginOk)) { ClassConsole.ConsoleWriteLine("Login/Wallet Address accepted by the pool. Waiting job.", ClassConsoleEnumeration.IndexPoolConsoleGreenLog); } } break; case ClassMiningRequest.TypeKeepAlive: LastPacketReceived = DateTimeOffset.Now.ToUnixTimeSeconds(); break; case ClassMiningRequest.TypeJob: LastPacketReceived = DateTimeOffset.Now.ToUnixTimeSeconds(); IsLogged = true; ClassMiningStats.CurrentBlockId = int.Parse(jsonPacket[ClassMiningRequest.TypeBlock].ToString()); ClassMiningStats.CurrentBlockTimestampCreate = jsonPacket[ClassMiningRequest.TypeBlockTimestampCreate].ToString(); ClassMiningStats.CurrentBlockKey = jsonPacket[ClassMiningRequest.TypeBlockKey].ToString(); ClassMiningStats.CurrentBlockIndication = jsonPacket[ClassMiningRequest.TypeBlockIndication].ToString(); ClassMiningStats.CurrentBlockDifficulty = decimal.Parse(jsonPacket[ClassMiningRequest.TypeBlockDifficulty].ToString()); var currentJobIndicationSplit = jsonPacket[ClassMiningRequest.TypeJobIndication].ToString().Split(new[] { ";" }, StringSplitOptions.None); var dictionaryJobIndication = new Dictionary <string, int>(); string currentJobIndication = string.Empty; int counterJob = 0; foreach (var jobIndication in currentJobIndicationSplit) { if (jobIndication != null) { if (!string.IsNullOrEmpty(jobIndication)) { if (jobIndication.Length > 1) { counterJob++; dictionaryJobIndication.Add(jobIndication, counterJob); currentJobIndication += jobIndication; } } } } ClassMiningStats.CurrentJobIndicationMinimized = ClassUtility.GenerateSHA512(currentJobIndication); ClassMiningStats.CurrentJobIndication = dictionaryJobIndication; ClassMiningStats.CurrentMinRangeJob = decimal.Parse(jsonPacket[ClassMiningRequest.TypeMinRange].ToString()); ClassMiningStats.CurrentMaxRangeJob = decimal.Parse(jsonPacket[ClassMiningRequest.TypeMaxRange].ToString()); ClassMiningStats.CurrentMethodName = jsonPacket[ClassMiningRequest.TypeJobMiningMethodName].ToString(); ClassMiningStats.CurrentRoundAesRound = int.Parse(jsonPacket[ClassMiningRequest.TypeJobMiningMethodAesRound].ToString()); ClassMiningStats.CurrentRoundAesSize = int.Parse(jsonPacket[ClassMiningRequest.TypeJobMiningMethodAesSize].ToString()); ClassMiningStats.CurrentRoundAesKey = jsonPacket[ClassMiningRequest.TypeJobMiningMethodAesKey].ToString(); ClassMiningStats.CurrentRoundXorKey = int.Parse(jsonPacket[ClassMiningRequest.TypeJobMiningMethodXorKey].ToString()); ClassMiningStats.CurrentJobKeyEncryption = jsonPacket[ClassMiningRequest.TypeJobKeyEncryption].ToString(); int totalShareToFound = ClassMiningStats.CurrentJobIndication.Count; if (jsonPacket.ContainsKey(ClassMiningRequest.TypeJobDifficulty)) { ClassMiningStats.CurrentMiningDifficulty = decimal.Parse(jsonPacket[ClassMiningRequest.TypeJobDifficulty].ToString()); } using (var pdb = new PasswordDeriveBytes(ClassMiningStats.CurrentBlockKey, Encoding.UTF8.GetBytes(ClassMiningStats.CurrentRoundAesKey))) { ClassMiningStats.CurrentAesKeyBytes = pdb.GetBytes(ClassMiningStats.CurrentRoundAesSize / 8); ClassMiningStats.CurrentAesIvBytes = pdb.GetBytes(ClassMiningStats.CurrentRoundAesSize / 8); } ClassMining.ProceedMining(); ClassConsole.ConsoleWriteLine("New Mining Job: " + ClassMiningStats.CurrentJobIndicationMinimized + " | Job Difficulty: " + ClassMiningStats.CurrentMiningDifficulty + " | Block ID: " + ClassMiningStats.CurrentBlockId + " | Block Difficulty: " + ClassMiningStats.CurrentBlockDifficulty + " | Block Hash Indication: " + ClassMiningStats.CurrentBlockIndication, ClassConsoleEnumeration.IndexPoolConsoleMagentaLog); ClassConsole.ConsoleWriteLine("Mining Job range received: " + ClassMiningStats.CurrentMinRangeJob + "|" + ClassMiningStats.CurrentMaxRangeJob, ClassConsoleEnumeration.IndexPoolConsoleMagentaLog); ClassConsole.ConsoleWriteLine("Total Share(s) to Found: " + totalShareToFound, ClassConsoleEnumeration.IndexPoolConsoleMagentaLog); break; case ClassMiningRequest.TypeShare: LastPacketReceived = DateTimeOffset.Now.ToUnixTimeSeconds(); switch (jsonPacket[ClassMiningRequest.TypeResult].ToString().ToLower()) { case ClassMiningRequest.TypeResultShareOk: ClassMiningStats.TotalGoodShare++; ClassConsole.ConsoleWriteLine("Good Share ! [Total = " + ClassMiningStats.TotalGoodShare + "]", ClassConsoleEnumeration.IndexPoolConsoleGreenLog); ClassMiningStats.TotalInvalidShare = 0; break; case ClassMiningRequest.TypeResultShareInvalid: ClassMiningStats.TotalInvalidShare++; if (ClassMiningStats.TotalInvalidShare >= ClassMiningConfig.MiningConfigMaxInvalidShare) { DisconnectMiner(); ClassMiningStats.TotalInvalidShare = 0; } ClassConsole.ConsoleWriteLine("Invalid Share ! [Total = " + ClassMiningStats.TotalInvalidShare + "]", ClassConsoleEnumeration.IndexPoolConsoleRedLog); break; case ClassMiningRequest.TypeResultShareDuplicate: ClassMiningStats.TotalDuplicateShare++; ClassConsole.ConsoleWriteLine("Duplicate Share ! [Total = " + ClassMiningStats.TotalDuplicateShare + "]", ClassConsoleEnumeration.IndexPoolConsoleYellowLog); break; case ClassMiningRequest.TypeResultShareLowDifficulty: ClassMiningStats.TotalLowDifficultyShare++; ClassConsole.ConsoleWriteLine("Low Difficulty Share ! [Total = " + ClassMiningStats.TotalLowDifficultyShare + "]", ClassConsoleEnumeration.IndexPoolConsoleRedLog); break; } break; } } catch { } }