/// <summary> /// Handle packet received from remote node sync. /// </summary> /// <param name="packet"></param> private static void HandlePacketReceivedFromSync(string packet) { var splitPacket = packet.Split(new[] { "|" }, StringSplitOptions.None); switch (splitPacket[0]) { case ClassRemoteNodeCommandForWallet.RemoteNodeRecvPacketEnumeration.WalletYourNumberTransaction: ClassConsole.ConsoleWriteLine("Their is " + splitPacket[1] + " transaction to sync for wallet address: " + CurrentWalletAddressOnSync, ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); CurrentWalletTransactionToSync = int.Parse(splitPacket[1]); CurrentWalletOnSyncTransaction = false; break; case ClassRemoteNodeCommandForWallet.RemoteNodeRecvPacketEnumeration.WalletYourAnonymityNumberTransaction: ClassConsole.ConsoleWriteLine("Their is " + splitPacket[1] + " anonymous transaction to sync for wallet address: " + CurrentWalletAddressOnSync, ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); CurrentWalletAnonymousTransactionToSync = int.Parse(splitPacket[1]); CurrentWalletOnSyncTransaction = false; break; case ClassRemoteNodeCommandForWallet.RemoteNodeRecvPacketEnumeration.WalletTransactionPerId: ClassSortingTransaction.SaveTransactionSorted(splitPacket[1], CurrentWalletAddressOnSync, ClassRpcDatabase.RpcDatabaseContent[CurrentWalletAddressOnSync].GetWalletPublicKey(), false); ClassConsole.ConsoleWriteLine(CurrentWalletAddressOnSync + " total transaction sync " + ClassRpcDatabase.RpcDatabaseContent[CurrentWalletAddressOnSync].GetWalletTotalTransactionSync() + "/" + CurrentWalletTransactionToSync, ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); CurrentWalletOnSyncTransaction = false; break; case ClassRemoteNodeCommandForWallet.RemoteNodeRecvPacketEnumeration.WalletAnonymityTransactionPerId: ClassSortingTransaction.SaveTransactionSorted(splitPacket[1], CurrentWalletAddressOnSync, ClassRpcDatabase.RpcDatabaseContent[CurrentWalletAddressOnSync].GetWalletPublicKey(), true); ClassConsole.ConsoleWriteLine(CurrentWalletAddressOnSync + " total anonymous transaction sync " + ClassRpcDatabase.RpcDatabaseContent[CurrentWalletAddressOnSync].GetWalletTotalAnonymousTransactionSync() + "/" + CurrentWalletAnonymousTransactionToSync, ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); CurrentWalletOnSyncTransaction = false; break; default: ClassConsole.ConsoleWriteLine("Unknown packet received: " + packet, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); break; } }
/// <summary> /// Insert a new transaction to database. /// </summary> /// <param name="walletAddress"></param> /// <param name="transaction"></param> public static async void InsertTransactionToSyncDatabaseAsync(string walletAddress, string walletPublicKey, string transaction) { await Task.Factory.StartNew(delegate { InSave = true; bool success = false; while (!success) { try { transaction = ClassAlgo.GetEncryptedResultManual(ClassAlgoEnumeration.Rijndael, transaction, walletAddress + walletPublicKey, ClassWalletNetworkSetting.KeySize); string transactionLine = ClassSyncDatabaseEnumeration.DatabaseSyncStartLine + walletAddress + "|" + transaction; SyncDatabaseStreamWriter.WriteLine(transactionLine); success = true; } catch { SyncDatabaseStreamWriter = new StreamWriter(ClassUtility.ConvertPath(System.AppDomain.CurrentDomain.BaseDirectory + SyncDatabaseFile), true, Encoding.UTF8, 8192) { AutoFlush = true }; } } TotalTransactionRead++; ClassConsole.ConsoleWriteLine("Total transaction saved: " + TotalTransactionRead); InSave = false; }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current); }
/// <summary> /// This method permit to get back the real ip behind a proxy and check the list of banned IP. /// </summary> private bool GetAndCheckForwardedIp(string packet) { var splitPacket = packet.Split(new[] { "\n" }, StringSplitOptions.None); foreach (var packetEach in splitPacket) { if (packetEach != null) { if (!string.IsNullOrEmpty(packetEach)) { if (packetEach.ToLower().Contains("x-forwarded-for: ")) { _ip = packetEach.ToLower().Replace("x-forwarded-for: ", ""); ClassConsole.ConsoleWriteLine("HTTP/HTTPS API - X-Forwarded-For ip of the client is: " + _ip, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelApi); if (ClassRpcSetting.RpcWalletApiIpWhitelist.Count > 0) { if (!ClassRpcSetting.RpcWalletApiIpWhitelist.Contains(_ip)) { return(false); } } } } } } return(true); }
/// <summary> /// Set automatic affinity, use native function depending of the Operating system. /// </summary> /// <param name="threadIdMining"></param> public static void SetAffinity(int threadIdMining) { try { if (Environment.OSVersion.Platform == PlatformID.Unix) // Linux/UNIX { if (Environment.ProcessorCount > threadIdMining && threadIdMining >= 0) { ulong processorMask = 1UL << threadIdMining; sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref processorMask); } } else { if (Environment.ProcessorCount > threadIdMining && threadIdMining >= 0) { Thread.BeginThreadAffinity(); int threadId = GetCurrentThreadId(); ProcessThread thread = Process.GetCurrentProcess().Threads.Cast <ProcessThread>() .Single(t => t.Id == threadId); ulong cpuMask = 1UL << threadIdMining; thread.ProcessorAffinity = (IntPtr)cpuMask; SetThreadAffinityMask((IntPtr)threadIdMining, (IntPtr)cpuMask); } } } catch (Exception error) { ClassConsole.WriteLine( "Cannot apply Automatic Affinity with thread id: " + threadIdMining + " | Exception: " + error.Message, 3); } }
/// <summary> /// Set manual affinity, use native function depending of the Operating system. /// </summary> /// <param name="threadAffinity"></param> public static void SetManualAffinity(string threadAffinity) { try { ulong handle = Convert.ToUInt64(threadAffinity, 16); if (Environment.OSVersion.Platform == PlatformID.Unix) // Linux/UNIX { sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref handle); } else { Thread.BeginThreadAffinity(); int threadId = GetCurrentThreadId(); ProcessThread thread = Process.GetCurrentProcess().Threads.Cast <ProcessThread>() .Single(t => t.Id == threadId); thread.ProcessorAffinity = (IntPtr)handle; SetThreadAffinityMask((IntPtr)threadId, (IntPtr)handle); } } catch (Exception error) { ClassConsole.WriteLine( "Cannot apply Manual Affinity with: " + threadAffinity + " | Exception: " + error.Message, 3); } }
/// <summary> /// Connect RPC Wallet to a remote node selected. /// </summary> public static async Task ConnectRpcWalletToRemoteNodeSyncAsync() { while (!ConnectionStatus && !Program.Exit) { try { TcpRemoteNodeClient?.Close(); TcpRemoteNodeClient?.Dispose(); TcpRemoteNodeClient = new TcpClient(); await TcpRemoteNodeClient.ConnectAsync(ClassRpcSetting.RpcWalletRemoteNodeHost, ClassRpcSetting.RpcWalletRemoteNodePort); ConnectionStatus = true; break; } catch { ClassConsole.ConsoleWriteLine("Unable to connect to Remote Node host " + ClassRpcSetting.RpcWalletRemoteNodeHost + ":" + ClassRpcSetting.RpcWalletRemoteNodePort + " retry in 5 seconds.", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); ConnectionStatus = false; } Thread.Sleep(5000); } if (ConnectionStatus) { ClassConsole.ConsoleWriteLine("Connect to Remote Node host " + ClassRpcSetting.RpcWalletRemoteNodeHost + ":" + ClassRpcSetting.RpcWalletRemoteNodePort + " successfully done, start to sync.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); LastPacketReceived = DateTimeOffset.Now.ToUnixTimeSeconds(); if (!EnableCheckConnectionStatus) { EnableCheckConnectionStatus = true; CheckRpcWalletConnectionToSync(); } ListenRemoteNodeSync(); AutoSyncWallet(); } }
public static void Connect(string ip) { IPEndPoint serverEp = new IPEndPoint(IPAddress.Parse(ip), Config.Port); Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.ReceiveTimeout = -1; ClassConsole.WriteLine("Connecting to seed node " + (seedNodeListNo + 1) + " on address " + Config.SeedNodes[seedNodeListNo] + ":" + Config.Port, "NODE_CLI", Colors.DarkYellow, Colors.Cyan); // Connect to the server. try { server.Connect(serverEp); } catch (Exception) { // Error connecing to server ClassConsole.WriteLine("Could not connect to " + serverEp + "!", "NODE_CLI", Colors.Red, Colors.Cyan); if (seedNodeListNo == Config.SeedNodes.Length - 1) { seedNodeListNo = 0; } else { seedNodeListNo = seedNodeListNo + 1; } Connect(Config.SeedNodes[seedNodeListNo]); return; } // Connected ClassConsole.WriteLine("Connected to seed node " + (seedNodeListNo + 1) + " on address " + serverEp, "NODE_CLI", Colors.Green, Colors.Cyan); WorkWithServer(server); }
/// <summary> /// Initialize sync database. /// </summary> /// <returns></returns> public static bool InitializeSyncDatabase() { try { if (!File.Exists(ClassUtility.ConvertPath(System.AppDomain.CurrentDomain.BaseDirectory + SyncDatabaseFile))) { File.Create(ClassUtility.ConvertPath(System.AppDomain.CurrentDomain.BaseDirectory + SyncDatabaseFile)).Close(); } else { using (FileStream fs = File.Open(ClassUtility.ConvertPath(System.AppDomain.CurrentDomain.BaseDirectory + SyncDatabaseFile), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (BufferedStream bs = new BufferedStream(fs)) { using (StreamReader sr = new StreamReader(bs)) { string line; int lineRead = 0; while ((line = sr.ReadLine()) != null) { lineRead++; if (line.Contains(ClassSyncDatabaseEnumeration.DatabaseSyncStartLine)) { string transactionLine = line.Replace(ClassSyncDatabaseEnumeration.DatabaseSyncStartLine, ""); var splitTransactionLine = transactionLine.Split(new[] { "|" }, StringSplitOptions.None); string walletAddress = splitTransactionLine[0]; if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(walletAddress)) { string transaction = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, splitTransactionLine[1], walletAddress + ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletPublicKey(), ClassWalletNetworkSetting.KeySize); var splitTransaction = transaction.Split(new[] { "#" }, StringSplitOptions.None); if (splitTransaction[0] == "anonymous") { ClassRpcDatabase.RpcDatabaseContent[walletAddress].InsertWalletTransactionSync(transaction, true, false); } else { ClassRpcDatabase.RpcDatabaseContent[walletAddress].InsertWalletTransactionSync(transaction, false, false); } TotalTransactionRead++; } } } } } } } } catch { return(false); } SyncDatabaseStreamWriter = new StreamWriter(ClassUtility.ConvertPath(System.AppDomain.CurrentDomain.BaseDirectory + SyncDatabaseFile), true, Encoding.UTF8, 8192) { AutoFlush = true }; ClassConsole.ConsoleWriteLine("Total transaction read from sync database: " + TotalTransactionRead, ClassConsoleColorEnumeration.IndexConsoleGreenLog, ClassConsoleLogLevelEnumeration.LogLevelSyncDatabase); return(true); }
public static void Connection() { try { listener = new TcpListener(IPAddress.Any, Config.ApiPort); listener.Start(); ClassConsole.WriteLine("Starting API server on " + IPAddress.Any + ":" + Config.ApiPort, "API", Colors.DarkGreen, Colors.DarkMagenta); } catch (Exception) { ClassConsole.WriteLine("Could not start server, port " + Config.ApiPort + " is already used!", "API", Colors.Red, Colors.DarkMagenta); return; } ClassConsole.WriteLine("API server started", "API", Colors.Green, Colors.DarkMagenta); while (true) { TcpClient tcpClient = listener.AcceptTcpClient(); NetworkStream networkStream = tcpClient.GetStream(); string request = ToString(networkStream); string[] requestLines = Regex.Split(request, "\r\n"); string getRequest = requestLines[0].Split(' ')[1]; // Send Request Header StringBuilder responseBuilder = new StringBuilder(); responseBuilder.AppendLine(@"HTTP/1.1 200 OK"); responseBuilder.AppendLine(@"Content-Type: application/json"); responseBuilder.AppendLine(@""); // Api Requests if (getRequest == ApiRequests.GET_STATUS) { ApiStatus getStatus = new ApiStatus(); getStatus.version = Config.CoinNetworkVersion; getStatus.result = "error"; responseBuilder.AppendLine(JsonConvert.SerializeObject(getStatus)); } else if (getRequest == "/favicon.ico") { } else { ApiError apiError = new ApiError(); apiError.version = Config.CoinNetworkVersion; apiError.result = "error"; responseBuilder.AppendLine(JsonConvert.SerializeObject(apiError)); } byte[] sendBytes = enc.GetBytes(responseBuilder.ToString()); networkStream.Write(sendBytes, 0, sendBytes.Length); networkStream.Close(); tcpClient.Close(); } }
public static void Open() { int backlog = -1, port = Config.Port; Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.ReceiveTimeout = -1; // Start listening. try { ClassConsole.WriteLine("Starting node server on address " + IPAddress.Any + ":" + Config.Port, "NODE_SRV", Colors.DarkGreen, Colors.DarkCyan); server.Bind(new IPEndPoint(IPAddress.Any, port)); server.Listen(backlog); } catch (Exception) { ClassConsole.WriteLine("Could not start server, port " + Config.Port + " is already used!", "NODE_SRV", Colors.Red, Colors.DarkCyan); return; } ClassConsole.WriteLine("Node server started", "NODE_SRV", Colors.Green, Colors.DarkCyan); while (true) { // If connection is made with client Socket client = server.Accept(); new System.Threading.Thread(() => { try { clientSockets.Add(client); connections = (connections + 1); Process(client); } catch (Exception ex) { if (ex.Message == "An existing connection was forcibly closed by the remote host.") { connections = (connections - 1); ClassConsole.SetTitle(connections); ClassConsole.WriteLine("Node disconnected from address " + client.RemoteEndPoint, "NODE_SRV", Colors.DarkGreen, Colors.DarkCyan); } else { ClassConsole.WriteLine("Client connection processing error: " + ex.Message, "NODE_SRV", Colors.Red, Colors.DarkCyan); } } }).Start(); } }
static void Process(Socket client) { ClassConsole.SetTitle(connections); ClassConsole.WriteLine("Node connected from address " + client.RemoteEndPoint, "NODE_SRV", Colors.DarkGreen, Colors.DarkCyan); const int maxMessageSize = 1024; byte[] response; int received; //client.Send(Encoding.ASCII.GetBytes("FromServer7")); while (true) { // Receive message from the server: response = new byte[maxMessageSize]; received = client.Receive(response); List <byte> respBytesList = new List <byte>(response); respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end if (Encoding.ASCII.GetString(respBytesList.ToArray()) == "") { connections = (connections - 1); ClassConsole.SetTitle(connections); ClassConsole.WriteLine("Node disconnected from address " + client.RemoteEndPoint, "NODE_SRV", Colors.DarkGreen, Colors.DarkCyan); client.Close(); return; } else { ClassConsole.WriteLine("[" + client.RemoteEndPoint + "] " + Encoding.ASCII.GetString(respBytesList.ToArray()), "NODE_SRV", Colors.DarkBlue, Colors.DarkCyan); } } /*while (true) * { * * // Send message to the client: * client.Send(Encoding.ASCII.GetBytes("FromServer")); * * // Receive message from the server: * response = new byte[maxMessageSize]; * received = client.Receive(response); * * List<byte> respBytesList = new List<byte>(response); * respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end * Console.WriteLine("[SRV] [" + client.RemoteEndPoint + "] Client->Server: " + Encoding.ASCII.GetString(respBytesList.ToArray())); * }*/ }
/// <summary> /// Log Initialization. /// </summary> /// <returns></returns> public static bool LogInitialization(bool fromThread = false) { try { LogInitializationFile(); LogInitizaliationStreamWriter(); if (!fromThread) { AutoWriteLog(); } } catch (Exception error) { ClassConsole.ConsoleWriteLine("Failed to initialize log system, exception error: " + error.Message, ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelGeneral); return(false); } return(true); }
/// <summary> /// Check rpc wallet connection to remote node sync. /// </summary> private static void CheckRpcWalletConnectionToSync() { if (ThreadRemoteNodeCheckConnection != null && (ThreadRemoteNodeCheckConnection.IsAlive || ThreadRemoteNodeCheckConnection != null)) { ThreadRemoteNodeCheckConnection.Abort(); GC.SuppressFinalize(ThreadRemoteNodeCheckConnection); } ThreadRemoteNodeCheckConnection = new Thread(async delegate() { while (!Program.Exit) { try { if (!ConnectionStatus || LastPacketReceived + MaxTimeout < DateTimeOffset.Now.ToUnixTimeSeconds()) { ConnectionStatus = false; LastPacketReceived = 0; Thread.Sleep(100); if (ThreadRemoteNodeListen != null && (ThreadRemoteNodeListen.IsAlive || ThreadRemoteNodeListen != null)) { ThreadRemoteNodeListen.Abort(); GC.SuppressFinalize(ThreadRemoteNodeListen); } if (ThreadAutoSync != null && (ThreadAutoSync.IsAlive || ThreadAutoSync != null)) { ThreadAutoSync.Abort(); GC.SuppressFinalize(ThreadAutoSync); } Thread.Sleep(1000); ClassConsole.ConsoleWriteLine("Connection to remote node host is closed, retry to connect", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); await ConnectRpcWalletToRemoteNodeSyncAsync(); } } catch { ConnectionStatus = false; LastPacketReceived = 0; } Thread.Sleep(1000); } }); ThreadRemoteNodeCheckConnection.Start(); }
/// <summary> /// Update wallet balance from token system. /// </summary> /// <param name="token"></param> /// <param name="getSeedNodeRandom"></param> /// <param name="walletAddress"></param> public static async Task <bool> GetWalletBalanceTokenAsync(string getSeedNodeRandom, string walletAddress) { string token = await GetWalletTokenAsync(getSeedNodeRandom, walletAddress); if (token != RpcTokenNetworkNotExist) { string encryptedRequest = ClassRpcWalletCommand.TokenAskBalance + "|" + token + "|" + (DateTimeOffset.Now.ToUnixTimeSeconds() + 1); encryptedRequest = ClassAlgo.GetEncryptedResultManual(ClassAlgoEnumeration.Rijndael, encryptedRequest, walletAddress + ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletPublicKey(), ClassWalletNetworkSetting.KeySize); string responseWallet = await ProceedTokenRequestAsync("http://" + getSeedNodeRandom + ":" + ClassConnectorSetting.SeedNodeTokenPort + "/" + ClassConnectorSettingEnumeration.WalletTokenType + "|" + walletAddress + "|" + encryptedRequest); var responseWalletJson = JObject.Parse(responseWallet); responseWallet = responseWalletJson["result"].ToString(); if (responseWallet != RpcTokenNetworkNotExist) { responseWallet = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, responseWallet, walletAddress + ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletPublicKey() + token, ClassWalletNetworkSetting.KeySize); if (responseWallet != ClassAlgoErrorEnumeration.AlgoError) { string walletBalance = responseWallet; var splitWalletBalance = walletBalance.Split(new[] { "|" }, StringSplitOptions.None); if ((long.Parse(splitWalletBalance[splitWalletBalance.Length - 1]) + 10) - DateTimeOffset.Now.ToUnixTimeSeconds() < 60) { if (long.Parse(splitWalletBalance[splitWalletBalance.Length - 1]) + 10 >= DateTimeOffset.Now.ToUnixTimeSeconds()) { ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletBalance(splitWalletBalance[1]); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletPendingBalance(splitWalletBalance[2]); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletUniqueId(splitWalletBalance[3]); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletAnonymousUniqueId(splitWalletBalance[4]); return(true); } else { ClassConsole.ConsoleWriteLine("Wallet packet time balance token request: " + walletBalance + " is expired.", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); } } else { ClassConsole.ConsoleWriteLine("Wallet packet time balance token request: " + walletBalance + " is too huge", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); } } } } return(false); }
public static void BlockchainCheckData() { // Check if database directory exists if (!Directory.Exists("Blockchain")) { // If not, create it Directory.CreateDirectory("Blockchain"); ClassConsole.WriteLine("Blockchain directory has been created", "BLOCKCHAIN", Colors.DarkGreen, Colors.Yellow); } else { // If it is, message and next step ClassConsole.WriteLine("Blockchain directory exists", "BLOCKCHAIN", Colors.DarkGreen, Colors.Yellow); if (File.Exists("Blockchain/" + Config.BlockchainBlocksDatabase)) { ClassConsole.WriteLine("Database file '" + Config.BlockchainBlocksDatabase + "' exists", "BLOCKCHAIN", Colors.Green, Colors.Yellow); } else { using (var blocksFile = new StreamWriter("Blockchain/" + Config.BlockchainBlocksDatabase, true)) { StringBuilder kevin = new StringBuilder(); kevin.Append("{ \"1\": \"BLOCKNO1\" }"); blocksFile.WriteLine(kevin.ToString()); } } if (File.Exists("Blockchain/" + Config.BlockchainTransactionsDatabase)) { ClassConsole.WriteLine("Database file '" + Config.BlockchainTransactionsDatabase + "' exists", "BLOCKCHAIN", Colors.Green, Colors.Yellow); } else { using (var transactionsFile = new StreamWriter("Blockchain/" + Config.BlockchainTransactionsDatabase, true)) { transactionsFile.WriteLine("The next line!"); } } } }
/// <summary> /// Constructor /// </summary> /// <param name="walletAddress"></param> /// <param name="walletPublicKey"></param> /// <param name="walletContentReadLine">Content line of the database keep it encrypted.</param> public ClassWalletObject(string walletAddress, string walletPublicKey, string walletPassword, string walletPrivateKey, string walletPinCode, string walletContentReadLine) { WalletAddress = walletAddress; WalletPublicKey = walletPublicKey; WalletPassword = walletPassword; WalletPrivateKey = walletPrivateKey; WalletPinCode = walletPinCode; #if DEBUG ClassConsole.ConsoleWriteLine("ClassWalletObject - Initialize object -> Wallet Address: " + WalletAddress + " | Wallet Public Key: " + WalletPublicKey + " | Wallet Private Key: " + WalletPrivateKey + " | Wallet Password: "******" | Wallet Pin Code: " + walletPinCode); #endif WalletBalance = "0"; WalletLastUpdate = 0; WalletPendingBalance = "0"; WalletUniqueId = "-1"; WalletAnonymousUniqueId = "-1"; WalletOnSendingTransaction = false; WalletListOfTransaction = new List <string>(); WalletListOfAnonymousTransaction = new List <string>(); WalletContentReadLine = walletContentReadLine; WalletInUpdate = false; }
/// <summary> /// Update pending balance. /// </summary> /// <param name="pendingBalance"></param> public void SetWalletPendingBalance(string pendingBalance) { ClassConsole.ConsoleWriteLine("Wallet " + WalletAddress + " - Pending Balance " + WalletPendingBalance + " " + ClassConnectorSetting.CoinNameMin + "->" + pendingBalance + " " + ClassConnectorSetting.CoinNameMin, ClassConsoleColorEnumeration.IndexConsoleBlueLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); WalletPendingBalance = pendingBalance; }
/// <summary> /// Update wallet anonymous unique id (used for synchronisation) /// </summary> /// <param name="uniqueId"></param> public void SetWalletAnonymousUniqueId(string anonymousUniqueId) { ClassConsole.ConsoleWriteLine("Wallet " + WalletAddress + " - Unique Anonymous ID " + WalletAnonymousUniqueId + "->" + anonymousUniqueId, ClassConsoleColorEnumeration.IndexConsoleBlueLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); WalletAnonymousUniqueId = anonymousUniqueId; }
static void Main(string[] args) { EnableCatchUnexpectedException(); Console.CancelKeyPress += Console_CancelKeyPress; Thread.CurrentThread.Name = Path.GetFileName(Environment.GetCommandLineArgs()[0]); GlobalCultureInfo = new CultureInfo("fr-FR"); ClassLog.LogInitialization(); ServicePointManager.DefaultConnectionLimit = 65535; ClassConsole.ConsoleWriteLine(ClassConnectorSetting.CoinName + " RPC Wallet - " + Assembly.GetExecutingAssembly().GetName().Version + "R", ClassConsoleColorEnumeration.IndexConsoleBlueLog, LogLevel); if (ClassRpcSetting.InitializeRpcWalletSetting()) { ClassConsole.ConsoleWriteLine("Please write your rpc wallet password for decrypt your databases of wallet (Input keys are hidden): ", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); ClassRpcDatabase.SetRpcDatabasePassword(ClassUtility.GetHiddenConsoleInput()); ClassConsole.ConsoleWriteLine("RPC Wallet Database loading..", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); if (ClassRpcDatabase.LoadRpcDatabaseFile()) { ClassConsole.ConsoleWriteLine("RPC Wallet Database successfully loaded.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, LogLevel); ClassConsole.ConsoleWriteLine("RPC Sync Database loading..", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); if (ClassSyncDatabase.InitializeSyncDatabase()) { ClassConsole.ConsoleWriteLine("RPC Sync Database successfully loaded.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, LogLevel); if (ClassRpcSetting.WalletEnableAutoUpdateWallet) { ClassConsole.ConsoleWriteLine("Enable Auto Update Wallet System..", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); ClassWalletUpdater.EnableAutoUpdateWallet(); ClassConsole.ConsoleWriteLine("Enable Auto Update Wallet System done.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, LogLevel); } ClassConsole.ConsoleWriteLine("Start RPC Wallet API Server..", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); ClassApi.StartApiHttpServer(); ClassConsole.ConsoleWriteLine("Start RPC Wallet API Server sucessfully started.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, LogLevel); if (ClassRpcSetting.RpcWalletEnableRemoteNodeSync && ClassRpcSetting.RpcWalletRemoteNodeHost != string.Empty && ClassRpcSetting.RpcWalletRemoteNodePort != 0) { ClassConsole.ConsoleWriteLine("RPC Remote Node Sync system loading..", ClassConsoleColorEnumeration.IndexConsoleYellowLog, LogLevel); ThreadRemoteNodeSync = new Thread(async() => await ClassRemoteSync.ConnectRpcWalletToRemoteNodeSyncAsync()); ThreadRemoteNodeSync.Start(); } ClassConsole.ConsoleWriteLine("Enable Command Line system.", ClassConsoleColorEnumeration.IndexConsoleGreenLog, LogLevel); ClassConsoleCommandLine.EnableConsoleCommandLine(); } else { ClassConsole.ConsoleWriteLine("Cannot read RPC Sync Database, the database is maybe corrupted.", ClassConsoleColorEnumeration.IndexConsoleRedLog, LogLevel); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); Environment.Exit(0); } } else { ClassConsole.ConsoleWriteLine("Cannot read RPC Wallet Database, the database is maybe corrupted.", ClassConsoleColorEnumeration.IndexConsoleRedLog, LogLevel); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); Environment.Exit(0); } } else { ClassConsole.ConsoleWriteLine("Cannot read RPC Wallet setting, the setting is maybe corrupted, you can delete your setting file to build another one.", ClassConsoleColorEnumeration.IndexConsoleRedLog, LogLevel); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); Environment.Exit(0); } }
/// <summary> /// Handle get request received from client. /// </summary> /// <param name="packet"></param> /// <returns></returns> private async Task HandlePacketHttpAsync(string packet) { if (packet.Contains("|")) { var splitPacket = packet.Split(new[] { "|" }, StringSplitOptions.None); switch (splitPacket[0]) { case ClassApiEnumeration.UpdateWalletByAddress: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { if (!ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletUpdateStatus()) { await ClassWalletUpdater.UpdateWallet(splitPacket[1]); Dictionary <string, string> walletUpdateContent = new Dictionary <string, string>() { { "wallet_address", splitPacket[1] }, { "wallet_balance", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletBalance() }, { "wallet_pending_balance", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletPendingBalance() }, { "wallet_unique_id", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletUniqueId() }, { "wallet_unique_anonymous_id", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletAnonymousUniqueId() }, }; await BuildAndSendHttpPacketAsync(string.Empty, true, walletUpdateContent); break; } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletBusyOnUpdate); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.UpdateWalletByIndex: if (int.TryParse(splitPacket[1], out var walletIndexUpdate)) { int counter = 0; bool found = false; foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { counter++; if (counter == walletIndexUpdate) { found = true; if (!walletObject.Value.GetWalletUpdateStatus()) { await ClassWalletUpdater.UpdateWallet(walletObject.Key); Dictionary <string, string> walletUpdateContent = new Dictionary <string, string>() { { "wallet_address", walletObject.Key }, { "wallet_balance", walletObject.Value.GetWalletBalance() }, { "wallet_pending_balance", walletObject.Value.GetWalletPendingBalance() }, { "wallet_unique_id", walletObject.Value.GetWalletUniqueId() }, { "wallet_unique_anonymous_id", walletObject.Value.GetWalletAnonymousUniqueId() }, }; await BuildAndSendHttpPacketAsync(string.Empty, true, walletUpdateContent); break; } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletBusyOnUpdate); break; } } } if (!found) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletAddressByIndex: if (int.TryParse(splitPacket[1], out var walletIndex)) { bool found = false; int counter = 0; foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { counter++; if (counter == walletIndex) { found = true; await BuildAndSendHttpPacketAsync(walletObject.Key); break; } } if (!found) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletBalanceByIndex: if (int.TryParse(splitPacket[1], out var walletIndex2)) { bool found = false; int counter = 0; foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { counter++; if (counter == walletIndex2) { found = true; Dictionary <string, string> walletBalanceContent = new Dictionary <string, string>() { { "wallet_address", walletObject.Key }, { "wallet_balance", walletObject.Value.GetWalletBalance() }, { "wallet_pending_balance", walletObject.Value.GetWalletPendingBalance() } }; await BuildAndSendHttpPacketAsync(null, true, walletBalanceContent); break; } } if (!found) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletBalanceByWalletAddress: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { Dictionary <string, string> walletBalanceContent = new Dictionary <string, string>() { { "wallet_address", splitPacket[1] }, { "wallet_balance", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletBalance() }, { "wallet_pending_balance", ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletPendingBalance() } }; await BuildAndSendHttpPacketAsync(null, true, walletBalanceContent); } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.SendTransactionByWalletAddress: if (splitPacket.Length >= 6) { var walletAddressSource = splitPacket[1]; var amount = splitPacket[2]; var fee = splitPacket[3]; var anonymousOption = splitPacket[4]; var walletAddressTarget = splitPacket[5]; if (anonymousOption == "1") { string result = await ClassWalletUpdater.ProceedTransactionTokenRequestAsync(walletAddressSource, amount, fee, walletAddressTarget, true); var splitResult = result.Split(new[] { "|" }, StringSplitOptions.None); Dictionary <string, string> walletTransactionContent = new Dictionary <string, string>() { { "result", splitResult[0] }, { "hash", splitResult[1].ToLower() }, { "wallet_balance", ClassRpcDatabase.RpcDatabaseContent[walletAddressSource].GetWalletBalance() }, { "wallet_pending_balance", ClassRpcDatabase.RpcDatabaseContent[walletAddressSource].GetWalletPendingBalance() } }; await BuildAndSendHttpPacketAsync(string.Empty, true, walletTransactionContent); } else { string result = await ClassWalletUpdater.ProceedTransactionTokenRequestAsync(walletAddressSource, amount, fee, walletAddressTarget, false); var splitResult = result.Split(new[] { "|" }, StringSplitOptions.None); Dictionary <string, string> walletTransactionContent = new Dictionary <string, string>() { { "result", splitResult[0] }, { "hash", splitResult[1].ToLower() }, { "wallet_balance", ClassRpcDatabase.RpcDatabaseContent[walletAddressSource].GetWalletBalance() }, { "wallet_pending_balance", ClassRpcDatabase.RpcDatabaseContent[walletAddressSource].GetWalletPendingBalance() } }; await BuildAndSendHttpPacketAsync(string.Empty, true, walletTransactionContent); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.PacketNotExist); } break; case ClassApiEnumeration.CreateWallet: if (long.TryParse(splitPacket[1], out var timeout)) { var dateTimeEnd = DateTimeOffset.Now.ToUnixTimeSeconds() + timeout; bool success = false; while (dateTimeEnd >= DateTimeOffset.Now.ToUnixTimeSeconds()) { using (var walletCreatorObject = new ClassWalletCreator()) { await Task.Run(async delegate { if (!await walletCreatorObject.StartWalletConnectionAsync(ClassWalletPhase.Create, ClassUtility.MakeRandomWalletPassword())) { ClassConsole.ConsoleWriteLine("RPC Wallet cannot create a new wallet.", ClassConsoleColorEnumeration.IndexConsoleRedLog, Program.LogLevel); } }).ConfigureAwait(false); while (walletCreatorObject.WalletCreateResult == ClassWalletCreatorEnumeration.WalletCreatorPending) { await Task.Delay(100); } switch (walletCreatorObject.WalletCreateResult) { case ClassWalletCreatorEnumeration.WalletCreatorSuccess: success = true; await BuildAndSendHttpPacketAsync(walletCreatorObject.WalletAddressResult); dateTimeEnd = DateTimeOffset.Now.ToUnixTimeSeconds(); break; } } } if (!success) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.CreateWalletError); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.CreateWalletError); } break; case ClassApiEnumeration.GetWalletTotalTransactionByIndex: if (int.TryParse(splitPacket[1], out var walletIndex3)) { bool found = false; int counter = 0; foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { counter++; if (counter == walletIndex3) { found = true; Dictionary <string, string> walletTotalTransactionContent = new Dictionary <string, string>() { { "wallet_address", walletObject.Key }, { "wallet_total_transaction", "" + walletObject.Value.GetWalletTotalTransactionSync() } }; await BuildAndSendHttpPacketAsync(null, true, walletTotalTransactionContent); break; } } if (!found) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletTotalAnonymousTransactionByIndex: if (int.TryParse(splitPacket[1], out var walletIndex4)) { bool found = false; int counter = 0; foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { counter++; if (counter == walletIndex4) { found = true; Dictionary <string, string> walletTotalAnonymousTransactionContent = new Dictionary <string, string>() { { "wallet_address", walletObject.Key }, { "wallet_total_anonymous_transaction", "" + walletObject.Value.GetWalletTotalAnonymousTransactionSync() } }; await BuildAndSendHttpPacketAsync(null, true, walletTotalAnonymousTransactionContent); break; } } if (!found) { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletTotalTransactionByWalletAddress: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { Dictionary <string, string> walletTotalTransactionContent = new Dictionary <string, string>() { { "wallet_address", splitPacket[1] }, { "wallet_total_transaction", "" + ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletTotalTransactionSync() } }; await BuildAndSendHttpPacketAsync(null, true, walletTotalTransactionContent); } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletTotalAnonymousTransactionByWalletAddress: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { Dictionary <string, string> walletTotalAnonymousTransactionContent = new Dictionary <string, string>() { { "wallet_address", splitPacket[1] }, { "wallet_total_anonymous_transaction", "" + ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletTotalAnonymousTransactionSync() } }; await BuildAndSendHttpPacketAsync(null, true, walletTotalAnonymousTransactionContent); } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletTransaction: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { if (int.TryParse(splitPacket[2], out var transactionIndex)) { if (transactionIndex == 0) { transactionIndex++; } string transaction = ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletTransactionSyncByIndex(transactionIndex); if (transaction != null) { var splitTransaction = transaction.Split(new[] { "#" }, StringSplitOptions.None); var type = splitTransaction[1]; var hash = splitTransaction[2]; var walletDst = splitTransaction[3]; var amount = splitTransaction[4]; var fee = splitTransaction[5]; var timestampSend = splitTransaction[6]; var timestampRecv = splitTransaction[7]; var blockchainHeight = splitTransaction[8]; Dictionary <string, string> walletTransactionContent = new Dictionary <string, string>() { { "index", "" + transactionIndex }, { "type", splitTransaction[0] }, { "mode", type }, { "hash", hash }, { "wallet_dst_or_src", walletDst }, { "amount", amount }, { "fee", fee }, { "timestamp_send", timestampSend }, { "timestamp_recv", timestampRecv }, { "blockchain_height", blockchainHeight } }; await BuildAndSendHttpPacketAsync(null, true, walletTransactionContent); } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.IndexNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.IndexNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; case ClassApiEnumeration.GetWalletAnonymousTransaction: if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(splitPacket[1])) { if (int.TryParse(splitPacket[2], out var transactionIndex)) { if (transactionIndex == 0) { transactionIndex++; } string transaction = ClassRpcDatabase.RpcDatabaseContent[splitPacket[1]].GetWalletAnonymousTransactionSyncByIndex(transactionIndex); if (transaction != null) { var splitTransaction = transaction.Split(new[] { "#" }, StringSplitOptions.None); var type = splitTransaction[1]; var hash = splitTransaction[2]; var walletDst = splitTransaction[3]; var amount = splitTransaction[4]; var fee = splitTransaction[5]; var timestampSend = splitTransaction[6]; var timestampRecv = splitTransaction[7]; var blockchainHeight = splitTransaction[8]; Dictionary <string, string> walletAnonymousTransactionContent = new Dictionary <string, string>() { { "index", "" + transactionIndex }, { "type", splitTransaction[0] }, { "mode", type }, { "hash", hash }, { "wallet_dst_or_src", walletDst }, { "amount", amount }, { "fee", fee }, { "timestamp_send", timestampSend }, { "timestamp_recv", timestampRecv }, { "blockchain_height", blockchainHeight } }; await BuildAndSendHttpPacketAsync(null, true, walletAnonymousTransactionContent); } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.IndexNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.IndexNotExist); } } else { await BuildAndSendHttpPacketAsync(ClassApiEnumeration.WalletNotExist); } break; default: await BuildAndSendHttpPacketAsync(ClassApiEnumeration.PacketNotExist); break; } } else { switch (packet) { case ClassApiEnumeration.GetTotalWalletIndex: await BuildAndSendHttpPacketAsync("" + ClassRpcDatabase.RpcDatabaseContent.Count); break; case ClassApiEnumeration.CreateWallet: using (var walletCreatorObject = new ClassWalletCreator()) { await Task.Factory.StartNew(async delegate { if (!await walletCreatorObject.StartWalletConnectionAsync(ClassWalletPhase.Create, ClassUtility.MakeRandomWalletPassword())) { ClassConsole.ConsoleWriteLine("RPC Wallet cannot create a new wallet.", ClassConsoleColorEnumeration.IndexConsoleRedLog, Program.LogLevel); } }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current).ConfigureAwait(false); while (walletCreatorObject.WalletCreateResult == ClassWalletCreatorEnumeration.WalletCreatorPending) { await Task.Delay(100); } switch (walletCreatorObject.WalletCreateResult) { case ClassWalletCreatorEnumeration.WalletCreatorError: await BuildAndSendHttpPacketAsync(ClassApiEnumeration.CreateWalletError); break; case ClassWalletCreatorEnumeration.WalletCreatorSuccess: await BuildAndSendHttpPacketAsync(walletCreatorObject.WalletAddressResult); break; } } break; default: await BuildAndSendHttpPacketAsync(ClassApiEnumeration.PacketNotExist); break; } } }
/// <summary> /// Listen remote node sync packet received. /// </summary> private static void ListenRemoteNodeSync() { if (ThreadRemoteNodeListen != null && (ThreadRemoteNodeListen.IsAlive || ThreadRemoteNodeListen != null)) { ThreadRemoteNodeListen.Abort(); GC.SuppressFinalize(ThreadRemoteNodeListen); } ThreadRemoteNodeListen = new Thread(async delegate() { while (ConnectionStatus && !Program.Exit) { try { using (var networkReader = new NetworkStream(TcpRemoteNodeClient.Client)) { using (BufferedStream bufferedStreamNetwork = new BufferedStream(networkReader, ClassConnectorSetting.MaxNetworkPacketSize)) { byte[] buffer = new byte[ClassConnectorSetting.MaxNetworkPacketSize]; int received = await bufferedStreamNetwork.ReadAsync(buffer, 0, buffer.Length); if (received > 0) { LastPacketReceived = DateTimeOffset.Now.ToUnixTimeSeconds(); string packetReceived = Encoding.UTF8.GetString(buffer, 0, received); if (packetReceived.Contains("*")) { var splitPacketReceived = packetReceived.Split(new[] { "*" }, StringSplitOptions.None); if (splitPacketReceived.Length > 1) { foreach (var packetEach in splitPacketReceived) { if (packetEach != null) { if (!string.IsNullOrEmpty(packetEach)) { if (packetEach.Length > 1) { await Task.Factory.StartNew(() => HandlePacketReceivedFromSync(packetEach), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current).ConfigureAwait(false); } } } } } else { await Task.Factory.StartNew(() => HandlePacketReceivedFromSync(packetReceived.Replace("*", "")), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current).ConfigureAwait(false); } } else { await Task.Factory.StartNew(() => HandlePacketReceivedFromSync(packetReceived), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current).ConfigureAwait(false); } } } } } catch (Exception error) { ClassConsole.ConsoleWriteLine("Exception: " + error.Message + " to listen packet received from Remote Node host " + ClassRpcSetting.RpcWalletRemoteNodeHost + ":" + ClassRpcSetting.RpcWalletRemoteNodePort + " retry to connect in a few seconds..", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); break; } } ConnectionStatus = false; }); ThreadRemoteNodeListen.Start(); }
/// <summary> /// Start to listen incoming client. /// </summary> /// <returns></returns> public async Task StartHandleClientHttpAsync() { var isWhitelisted = true; if (ClassRpcSetting.RpcWalletApiIpWhitelist.Count > 0) { if (!ClassRpcSetting.RpcWalletApiIpWhitelist.Contains(_ip)) { ClassConsole.ConsoleWriteLine(_ip + " is not whitelisted.", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelApi); isWhitelisted = false; } } int totalWhile = 0; if (isWhitelisted) { await Task.Run(() => MaxKeepAliveFunctionAsync()).ConfigureAwait(false); try { while (_clientStatus) { try { using (NetworkStream clientHttpReader = new NetworkStream(_client.Client)) { using (BufferedStream bufferedStreamNetwork = new BufferedStream(clientHttpReader, ClassConnectorSetting.MaxNetworkPacketSize)) { byte[] buffer = new byte[ClassConnectorSetting.MaxNetworkPacketSize]; int received = await bufferedStreamNetwork.ReadAsync(buffer, 0, buffer.Length); if (received > 0) { string packet = Encoding.UTF8.GetString(buffer, 0, received); if (ClassRpcSetting.RpcWalletApiEnableXForwardedForResolver) { try { if (!GetAndCheckForwardedIp(packet)) { break; } } catch { } } packet = ClassUtility.GetStringBetween(packet, "GET /", "HTTP"); packet = packet.Replace("%7C", "|"); // Translate special character | packet = packet.Replace(" ", ""); // Remove empty,space characters ClassConsole.ConsoleWriteLine("HTTP API - packet received from IP: " + _ip + " - " + packet, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelApi); if (ClassRpcSetting.RpcWalletApiKeyRequestEncryption != string.Empty) { packet = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, packet, ClassRpcSetting.RpcWalletApiKeyRequestEncryption, ClassWalletNetworkSetting.KeySize); if (packet == ClassAlgoErrorEnumeration.AlgoError) { ClassConsole.ConsoleWriteLine("HTTP API - wrong packet received from IP: " + _ip + " - " + packet, ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelApi); break; } ClassConsole.ConsoleWriteLine("HTTP API - decrypted packet received from IP: " + _ip + " - " + packet, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelApi); } await HandlePacketHttpAsync(packet); break; } else { totalWhile++; } if (totalWhile >= 8) { break; } } } } catch (Exception error) { ClassConsole.ConsoleWriteLine("HTTP API - exception error: " + error.Message, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelApi); break; } } } catch { } } CloseClientConnection(); }
/// <summary> /// Send a transaction with token system with a selected wallet address, amount and fee. /// </summary> /// <param name="walletAddress"></param> /// <returns></returns> public static async Task <string> ProceedTransactionTokenRequestAsync(string walletAddress, string amount, string fee, string walletAddressTarget, bool anonymous) { if (anonymous) { ClassConsole.ConsoleWriteLine("Attempt to send an anonymous transaction from wallet address " + walletAddress + " of amount " + amount + " " + ClassConnectorSetting.CoinNameMin + " fee " + fee + " " + ClassConnectorSetting.CoinNameMin + " and anonymous fee option of: " + ClassConnectorSetting.MinimumWalletTransactionAnonymousFee + " " + ClassConnectorSetting.CoinNameMin + " to target -> " + walletAddressTarget, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); } else { ClassConsole.ConsoleWriteLine("Attempt to send transaction from wallet address " + walletAddress + " of amount " + amount + " " + ClassConnectorSetting.CoinNameMin + " fee " + fee + " " + ClassConnectorSetting.CoinNameMin + " to target -> " + walletAddressTarget, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); } if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(walletAddress)) { if (!ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletUpdateStatus() && !ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletOnSendTransactionStatus()) { ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(true); decimal balanceFromDatabase = decimal.Parse(ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletBalance().Replace(".", ","), NumberStyles.Currency, Program.GlobalCultureInfo); decimal balanceFromRequest = decimal.Parse(amount.Replace(".", ","), NumberStyles.Currency, Program.GlobalCultureInfo); decimal feeFromRequest = decimal.Parse(fee.Replace(".", ","), NumberStyles.Currency, Program.GlobalCultureInfo); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetLastWalletUpdate(DateTimeOffset.Now.ToUnixTimeSeconds()); string getSeedNodeRandom = string.Empty; bool seedNodeSelected = false; foreach (var seedNode in ClassConnectorSetting.SeedNodeIp) { getSeedNodeRandom = seedNode.Key; Task taskCheckSeedNode = Task.Run(async() => seedNodeSelected = await CheckTcp.CheckTcpClientAsync(getSeedNodeRandom, ClassConnectorSetting.SeedNodeTokenPort)); taskCheckSeedNode.Wait(ClassConnectorSetting.MaxTimeoutConnect); if (seedNodeSelected) { break; } } if (seedNodeSelected) { try { return(await SendWalletTransactionTokenAsync(getSeedNodeRandom, walletAddress, walletAddressTarget, amount, fee, anonymous)); } catch (Exception error) { ClassConsole.ConsoleWriteLine("Error on send transaction from wallet: " + ClassRpcDatabase.RpcDatabaseContent[walletAddress] + " exception: " + error.Message, ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(ClassRpcWalletCommand.SendTokenTransactionRefused + "|None"); } } else { ClassConsole.ConsoleWriteLine("Error on send transaction from wallet: " + ClassRpcDatabase.RpcDatabaseContent[walletAddress] + " exception: can't connect on each seed nodes checked.", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(ClassRpcWalletCommand.SendTokenTransactionRefused + "|None"); } } else { if (ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletUpdateStatus()) { return(RpcTokenNetworkWalletBusyOnUpdate + "|None"); } else { return(ClassRpcWalletCommand.SendTokenTransactionBusy + "|None"); } } } return(RpcTokenNetworkWalletAddressNotExist + "|None"); }
/// <summary> /// Send a transaction from a selected wallet address stored to a specific wallet address target. /// </summary> /// <param name="getSeedNodeRandom"></param> /// <param name="walletAddress"></param> /// <param name="walletAddressTarget"></param> /// <param name="amount"></param> /// <param name="fee"></param> /// <param name="anonymous"></param> /// <returns></returns> private static async Task <string> SendWalletTransactionTokenAsync(string getSeedNodeRandom, string walletAddress, string walletAddressTarget, string amount, string fee, bool anonymous) { string tokenWallet = await GetWalletTokenAsync(getSeedNodeRandom, walletAddress); if (tokenWallet != RpcTokenNetworkNotExist) { string encryptedRequest = string.Empty; if (anonymous) { encryptedRequest = ClassRpcWalletCommand.TokenAskWalletSendTransaction + "|" + tokenWallet + "|" + walletAddressTarget + "|" + amount + "|" + fee + "|1|" + (DateTimeOffset.Now.ToUnixTimeSeconds() + 1); } else { encryptedRequest = ClassRpcWalletCommand.TokenAskWalletSendTransaction + "|" + tokenWallet + "|" + walletAddressTarget + "|" + amount + "|" + fee + "|0|" + (DateTimeOffset.Now.ToUnixTimeSeconds() + 1); } encryptedRequest = ClassAlgo.GetEncryptedResultManual(ClassAlgoEnumeration.Rijndael, encryptedRequest, walletAddress + ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletPublicKey(), ClassWalletNetworkSetting.KeySize); string responseWallet = await ProceedTokenRequestAsync("http://" + getSeedNodeRandom + ":" + ClassConnectorSetting.SeedNodeTokenPort + "/" + ClassConnectorSettingEnumeration.WalletTokenType + "|" + walletAddress + "|" + encryptedRequest); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnUpdateStatus(false); var responseWalletJson = JObject.Parse(responseWallet); responseWallet = responseWalletJson["result"].ToString(); if (responseWallet != RpcTokenNetworkNotExist) { responseWallet = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, responseWallet, walletAddress + ClassRpcDatabase.RpcDatabaseContent[walletAddress].GetWalletPublicKey() + tokenWallet, ClassWalletNetworkSetting.KeySize); if (responseWallet != ClassAlgoErrorEnumeration.AlgoError) { string walletTransaction = responseWallet; if (responseWallet != RpcTokenNetworkNotExist) { var splitWalletTransaction = walletTransaction.Split(new[] { "|" }, StringSplitOptions.None); if ((long.Parse(splitWalletTransaction[splitWalletTransaction.Length - 1]) + 10) - DateTimeOffset.Now.ToUnixTimeSeconds() < 60) { if (long.Parse(splitWalletTransaction[splitWalletTransaction.Length - 1]) + 10 >= DateTimeOffset.Now.ToUnixTimeSeconds()) { ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletBalance(splitWalletTransaction[1]); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletPendingBalance(splitWalletTransaction[2]); ClassConsole.ConsoleWriteLine("Send transaction response " + splitWalletTransaction[0] + " from wallet address " + walletAddress + " of amount " + amount + " " + ClassConnectorSetting.CoinNameMin + " fee " + fee + " " + ClassConnectorSetting.CoinNameMin + " transaction hash: " + splitWalletTransaction[3] + " to target -> " + walletAddressTarget, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(splitWalletTransaction[0] + "|" + splitWalletTransaction[3]); } return(splitWalletTransaction[0] + "|expired_packet"); } } else { ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(ClassRpcWalletCommand.SendTokenTransactionBusy + "|None"); } } else { ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(ClassRpcWalletCommand.SendTokenTransactionBusy + "|None"); } } } ClassConsole.ConsoleWriteLine("Send transaction refused from wallet address " + walletAddress + " of amount " + amount + " " + ClassConnectorSetting.CoinNameMin + " fee " + fee + " " + ClassConnectorSetting.CoinNameMin + " to target -> " + walletAddressTarget, ClassConsoleColorEnumeration.IndexConsoleYellowLog, ClassConsoleLogLevelEnumeration.LogLevelWalletObject); ClassRpcDatabase.RpcDatabaseContent[walletAddress].SetWalletOnSendTransactionStatus(false); return(ClassRpcWalletCommand.SendTokenTransactionRefused + "|None"); }
/// <summary> /// Make setting of RPC Wallet /// </summary> private static void MakeRpcWalletSetting() { ClassConsole.ConsoleWriteLine("Setting up Web API:", ClassConsoleColorEnumeration.IndexConsoleYellowLog); ClassConsole.ConsoleWriteLine("Please select a port for your API to listen (By default 8000): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); string choose = Console.ReadLine(); int portTmp = 0; while (!int.TryParse(choose, out var port)) { ClassConsole.ConsoleWriteLine(choose + " is not a valid port number, please select a port for your API ", ClassConsoleColorEnumeration.IndexConsoleRedLog); choose = Console.ReadLine(); } RpcWalletApiPort = portTmp; if (RpcWalletApiPort <= 0) { RpcWalletApiPort = 8000; } ClassConsole.ConsoleWriteLine("Do you want to accept only IP whitelisted? [Y/N]", ClassConsoleColorEnumeration.IndexConsoleBlueLog); bool yourChoose = Console.ReadLine().ToLower() == "y"; if (yourChoose) { bool finish = false; while (!finish) { ClassConsole.ConsoleWriteLine("Write an IP to whitelist: ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); string ip = Console.ReadLine(); RpcWalletApiIpWhitelist.Add(ip); ClassConsole.ConsoleWriteLine("Do you want to write another IP? [Y/N]", ClassConsoleColorEnumeration.IndexConsoleBlueLog); yourChoose = Console.ReadLine().ToLower() == "y"; if (!yourChoose) { finish = true; } } } ClassConsole.ConsoleWriteLine("Do you want to use an encryption key of request in the API [AES 256bit is used]? [Y/N]", ClassConsoleColorEnumeration.IndexConsoleBlueLog); yourChoose = Console.ReadLine().ToLower() == "y"; if (yourChoose) { ClassConsole.ConsoleWriteLine("Write your API Key (" + RpcApiKeyMinSize + " characters minimum required by the salt encryption system.): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); RpcWalletApiKeyRequestEncryption = Console.ReadLine(); while (RpcWalletApiKeyRequestEncryption.Length < RpcApiKeyMinSize) { ClassConsole.ConsoleWriteLine("Your API Key characters length is less than " + RpcApiKeyMinSize + " characters (Minimum required by the salt encryption system.), please write another one: ", ClassConsoleColorEnumeration.IndexConsoleRedLog); RpcWalletApiKeyRequestEncryption = Console.ReadLine(); } } ClassConsole.ConsoleWriteLine("Do you want to enable the X-FORWARDED-FOR resolver? (This option should be used once the API is behind a Proxy setting correctly.) [Y/N]", ClassConsoleColorEnumeration.IndexConsoleBlueLog); yourChoose = Console.ReadLine().ToLower() == "y"; if (yourChoose) { RpcWalletApiEnableXForwardedForResolver = true; } ClassConsole.ConsoleWriteLine("Do you want to use a remote node for sync transactions of your wallets? [Y/N]", ClassConsoleColorEnumeration.IndexConsoleBlueLog); RpcWalletEnableRemoteNodeSync = Console.ReadLine().ToLower() == "y"; if (RpcWalletEnableRemoteNodeSync) { ClassConsole.ConsoleWriteLine("Write the remote node IP/Hostname address: ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); RpcWalletRemoteNodeHost = Console.ReadLine(); ClassConsole.ConsoleWriteLine("Write the remote node port (by default " + ClassConnectorSetting.RemoteNodePort + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); int port = ClassConnectorSetting.RemoteNodePort; while (!int.TryParse(Console.ReadLine(), out port)) { ClassConsole.ConsoleWriteLine("Write a valid the remote node port (by default " + ClassConnectorSetting.RemoteNodePort + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); } RpcWalletRemoteNodePort = port; } using (var settingWriter = new StreamWriter(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcWalletSettingFile), true, Encoding.UTF8, 8192) { AutoFlush = true }) { settingWriter.WriteLine("// RPC Wallet API port."); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingApiPortSetting + "=" + RpcWalletApiPort); settingWriter.WriteLine("// List of IP whitelisted on the API Server, if the list is empty everyone can try to access on the port. use ; between each ip/hostname address"); string host = ClassRpcSettingEnumeration.SettingApiWhitelist + "="; if (RpcWalletApiIpWhitelist.Count > 0) { for (int i = 0; i < RpcWalletApiIpWhitelist.Count; i++) { if (i < RpcWalletApiIpWhitelist.Count) { if (i < RpcWalletApiIpWhitelist.Count - 1) { host += RpcWalletApiIpWhitelist[i] + ";"; } else { host += RpcWalletApiIpWhitelist[i]; } } } } settingWriter.WriteLine(host); settingWriter.WriteLine("// The key for encrypt request to receive/sent on the API. (" + RpcApiKeyMinSize + " characters minimum required by the salt encryption system.)"); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingApiKeyRequestEncryption + "=" + RpcWalletApiKeyRequestEncryption); settingWriter.WriteLine("// The X-FORWARDED-FOR resolver, permit to resolve the IP from an incomming connection, this option should be used only if the API is behind a proxy."); if (RpcWalletApiEnableXForwardedForResolver) { settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingApiEnableXForwardedForResolver + "=Y"); } else { settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingApiEnableXForwardedForResolver + "=N"); } settingWriter.WriteLine("// Enable remote node sync"); if (RpcWalletEnableRemoteNodeSync) { settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingEnableRemoteNodeSync + "=Y"); } else { settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingEnableRemoteNodeSync + "=N"); } settingWriter.WriteLine("//Remote Node Host address"); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingRemoteNodeHost + "=" + RpcWalletRemoteNodeHost); settingWriter.WriteLine("// Remote Node Port"); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingRemoteNodePort + "=" + RpcWalletRemoteNodePort); ClassConsole.ConsoleWriteLine("Do you want to enable the auto update system? (By default this function is not enabled) [Y/N]: ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); yourChoose = Console.ReadLine().ToLower() == "y"; if (yourChoose) { WalletEnableAutoUpdateWallet = true; settingWriter.WriteLine("//Enable auto update of wallets informations."); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingWalletEnableAutoUpdate + "=Y"); settingWriter.WriteLine("// Interval of time in second(s) between whole updates of wallets informations."); ClassConsole.ConsoleWriteLine("Write the interval of time in second(s) to update wallets informations. (By default " + WalletUpdateInterval + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); int interval = WalletUpdateInterval; while (!int.TryParse(Console.ReadLine(), out interval)) { ClassConsole.ConsoleWriteLine("Write a valid interval of time in second(s) to update wallets informations. (By default " + WalletUpdateInterval + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); } WalletUpdateInterval = interval; settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingWalletUpdateInterval + "=" + WalletUpdateInterval); ClassConsole.ConsoleWriteLine("Write the max keep alive update wallet of time in second(s). (By default " + WalletMaxKeepAliveUpdate + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); interval = WalletMaxKeepAliveUpdate; while (!int.TryParse(Console.ReadLine(), out interval)) { ClassConsole.ConsoleWriteLine("Write a max keep alive update wallet of time in second(s). (By default " + WalletMaxKeepAliveUpdate + "): ", ClassConsoleColorEnumeration.IndexConsoleBlueLog); } WalletMaxKeepAliveUpdate = interval; settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingWalletMaxKeepAliveUpdate + "=" + WalletMaxKeepAliveUpdate); } else { WalletEnableAutoUpdateWallet = false; settingWriter.WriteLine("//Enable auto update of wallets informations."); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingWalletEnableAutoUpdate + "=N"); settingWriter.WriteLine("// Interval of time in second(s) between whole updates of wallets informations."); settingWriter.WriteLine(ClassRpcSettingEnumeration.SettingWalletUpdateInterval + "=" + WalletUpdateInterval); } } }
/// <summary> /// Load RPC Database file. /// </summary> /// <returns></returns> public static bool LoadRpcDatabaseFile() { RpcDatabaseContent = new Dictionary <string, ClassWalletObject>(); try { if (File.Exists(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcDatabaseFile))) { using (FileStream fs = File.Open(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcDatabaseFile), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (BufferedStream bs = new BufferedStream(fs)) { using (StreamReader sr = new StreamReader(bs)) { string line; int lineRead = 0; while ((line = sr.ReadLine()) != null) { lineRead++; if (line.StartsWith(ClassRpcDatabaseEnumeration.DatabaseWalletStartLine)) { string walletData = line.Replace(ClassRpcDatabaseEnumeration.DatabaseWalletStartLine, ""); walletData = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, walletData, RpcDatabasePassword, ClassWalletNetworkSetting.KeySize); if (walletData != ClassAlgoErrorEnumeration.AlgoError) { var splitWalletData = walletData.Split(new[] { "|" }, StringSplitOptions.None); var walletAddress = splitWalletData[0]; if (!RpcDatabaseContent.ContainsKey(walletAddress)) { var walletPublicKey = splitWalletData[1]; var walletPrivateKey = splitWalletData[2]; var walletPinCode = splitWalletData[3]; var walletPassword = splitWalletData[4]; var walletObject = new ClassWalletObject(walletAddress, walletPublicKey, walletPassword, walletPrivateKey, walletPinCode, walletData); if (!RpcDatabaseContent.ContainsKey(walletAddress)) { RpcDatabaseContent.Add(walletAddress, walletObject); } } } else { ClassConsole.ConsoleWriteLine("Decrypt database of wallets failed at line: " + lineRead); return(false); } } } } } } } else { File.Create(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcDatabaseFile)).Close(); } } catch { return(false); } RpcDatabaseStreamWriter = new StreamWriter(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcDatabaseFile), true, Encoding.UTF8, 8192) { AutoFlush = true }; return(true); }
public static bool WalletEnableAutoUpdateWallet = false; // Enable auto update of wallets informations. /// <summary> /// Initialize setting of RPC Wallet /// </summary> /// <returns></returns> public static bool InitializeRpcWalletSetting() { try { if (File.Exists(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcWalletSettingFile))) { bool containUpdate = false; using (var streamReaderConfigPool = new StreamReader(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcWalletSettingFile))) { 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 Console.WriteLine("Config line read: " + splitLine[0] + " argument read: " + splitLine[1]); #endif switch (splitLine[0]) { case ClassRpcSettingEnumeration.SettingApiPortSetting: if (splitLine.Length > 1) { RpcWalletApiPort = int.Parse(splitLine[1]); } else { RpcWalletApiPort = 8000; } break; case ClassRpcSettingEnumeration.SettingApiWhitelist: if (splitLine.Length > 1) { if (splitLine[1].Contains(";")) { var splitLineIp = splitLine[1].Split(new[] { ";" }, StringSplitOptions.None); foreach (var lineIp in splitLineIp) { if (lineIp != null) { if (!string.IsNullOrEmpty(lineIp)) { if (lineIp.Length > 1) { RpcWalletApiIpWhitelist.Add(lineIp); } } } } } else { if (splitLine[1] != null) { if (!string.IsNullOrEmpty(splitLine[1])) { if (splitLine[1].Length > 1) { RpcWalletApiIpWhitelist.Add(splitLine[1]); } } } } } break; case ClassRpcSettingEnumeration.SettingApiKeyRequestEncryption: if (splitLine.Length > 1) { RpcWalletApiKeyRequestEncryption = splitLine[1]; if (RpcWalletApiKeyRequestEncryption.Length < RpcApiKeyMinSize) { ClassConsole.ConsoleWriteLine("Warning the current API Key encryption length is less than " + RpcApiKeyMinSize + " characters required by the salt system of encryption !", ClassConsoleColorEnumeration.IndexConsoleRedLog, Program.LogLevel); } } break; case ClassRpcSettingEnumeration.SettingEnableRemoteNodeSync: if (splitLine.Length > 1) { if (splitLine[1].ToLower() == "y" || splitLine[1].ToLower() == "true") { RpcWalletEnableRemoteNodeSync = true; } } break; case ClassRpcSettingEnumeration.SettingRemoteNodeHost: if (splitLine.Length > 1) { RpcWalletRemoteNodeHost = splitLine[1]; } break; case ClassRpcSettingEnumeration.SettingRemoteNodePort: if (splitLine.Length > 1) { RpcWalletRemoteNodePort = int.Parse(splitLine[1]); } break; case ClassRpcSettingEnumeration.SettingWalletUpdateInterval: if (int.TryParse(splitLine[1], out var walletUpdateInterval)) { WalletUpdateInterval = walletUpdateInterval; } break; case ClassRpcSettingEnumeration.SettingWalletEnableAutoUpdate: if (splitLine[1].ToLower() == "y" || splitLine[1].ToLower() == "true") { ClassConsole.ConsoleWriteLine("Warning auto update is enabled, be sure to select a good interval time of update for don't be detected has flooding on seed nodes.", ClassConsoleColorEnumeration.IndexConsoleRedLog); WalletEnableAutoUpdateWallet = true; } else { ClassConsole.ConsoleWriteLine("Warning auto update system is disabled, be sure to use your API to update manually wallets informations.", ClassConsoleColorEnumeration.IndexConsoleRedLog); WalletEnableAutoUpdateWallet = false; } break; case ClassRpcSettingEnumeration.SettingWalletMaxKeepAliveUpdate: if (int.TryParse(splitLine[1], out var walletMaxKeepAliveUpdate)) { WalletMaxKeepAliveUpdate = walletMaxKeepAliveUpdate; } break; case ClassRpcSettingEnumeration.SettingApiEnableXForwardedForResolver: if (splitLine[1].ToLower() == "y" || splitLine[1].ToLower() == "true") { RpcWalletApiEnableXForwardedForResolver = true; } containUpdate = true; break; default: if (splitLine.Length > 1) { Console.WriteLine("Unknown config line: " + splitLine[0] + " with argument: " + splitLine[1] + " on line: " + numberOfLines); } else { Console.WriteLine("Unknown config line: " + splitLine[0] + " with no argument on line: " + numberOfLines); } break; } } catch { Console.WriteLine("Error on line:" + numberOfLines); } } else { Console.WriteLine("Error on config line: " + splitLine[0] + " on line:" + numberOfLines); } } } } } } if (!containUpdate) { ClassConsole.ConsoleWriteLine("Setting system of RPC Wallet has been updated, create a new setting file now: ", ClassConsoleColorEnumeration.IndexConsoleMagentaLog); File.Create(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcWalletSettingFile)).Close(); MakeRpcWalletSetting(); } } else { File.Create(ClassUtility.ConvertPath(AppDomain.CurrentDomain.BaseDirectory + RpcWalletSettingFile)).Close(); MakeRpcWalletSetting(); } } catch { return(false); } return(true); }
/// <summary> /// Handle packet wallet received from the blockchain network. /// </summary> /// <param name="packet"></param> private void HandlePacketBlockchainNetworkWallet(string packet) { var splitPacket = packet.Split(new[] { "|" }, StringSplitOptions.None); switch (splitPacket[0]) { case ClassWalletCommand.ClassWalletReceiveEnumeration.WaitingCreatePhase: //ClassConsole.ConsoleWriteLine("Please wait a moment, your wallet pending creation..", ClassConsoleEnumeration.IndexConsoleYellowLog); break; case ClassWalletCommand.ClassWalletReceiveEnumeration.WalletCreatePasswordNeedLetters: case ClassWalletCommand.ClassWalletReceiveEnumeration.WalletCreatePasswordNeedMoreCharacters: WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); break; case ClassWalletCommand.ClassWalletReceiveEnumeration.CreatePhase: if (splitPacket[1] == ClassAlgoErrorEnumeration.AlgoError) { WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); } else { var decryptWalletDataCreate = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, splitPacket[1], WalletPassword, ClassWalletNetworkSetting.KeySize); if (decryptWalletDataCreate == ClassAlgoErrorEnumeration.AlgoError) { WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); } else { string walletDataCreate = ClassUtils.DecompressData(decryptWalletDataCreate); var splitDecryptWalletDataCreate = walletDataCreate.Split(new[] { "\n" }, StringSplitOptions.None); var pinWallet = splitPacket[2]; var walletAddress = splitDecryptWalletDataCreate[0]; var publicKey = splitDecryptWalletDataCreate[2]; var privateKey = splitDecryptWalletDataCreate[3]; WalletAddressResult = walletAddress; ClassRpcDatabase.InsertNewWalletAsync(walletAddress, publicKey, privateKey, pinWallet, WalletPassword); WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorSuccess; FullDisconnection(); } } break; case ClassWalletCommand.ClassWalletReceiveEnumeration.WalletAskSuccess: string walletDataCreation = splitPacket[1]; if (walletDataCreation == ClassAlgoErrorEnumeration.AlgoError) { ClassConsole.ConsoleWriteLine("Restoring wallet failed, please try again later.", ClassConsoleColorEnumeration.IndexConsoleRedLog); WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); } else { var decryptWalletDataCreation = ClassAlgo.GetDecryptedResultManual(ClassAlgoEnumeration.Rijndael, walletDataCreation, WalletPrivateKey, ClassWalletNetworkSetting.KeySize); if (decryptWalletDataCreation == ClassAlgoErrorEnumeration.AlgoError) { ClassConsole.ConsoleWriteLine("Restoring wallet failed, please try again later.", ClassConsoleColorEnumeration.IndexConsoleRedLog); WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); } else { var splitWalletData = decryptWalletDataCreation.Split(new[] { "\n" }, StringSplitOptions.None); var publicKey = splitWalletData[2]; var privateKey = splitWalletData[3]; var pinCode = splitWalletData[4]; if (ClassRpcDatabase.RpcDatabaseContent.ContainsKey(WalletAddress)) { ClassRpcDatabase.RpcDatabaseContent[WalletAddress].SetWalletAddress(WalletAddress); ClassRpcDatabase.RpcDatabaseContent[WalletAddress].SetWalletPublicKey(publicKey); ClassRpcDatabase.RpcDatabaseContent[WalletAddress].SetWalletPrivateKey(privateKey); ClassRpcDatabase.RpcDatabaseContent[WalletAddress].SetWalletPinCode(pinCode); WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorSuccess; FullDisconnection(); } else { ClassConsole.ConsoleWriteLine("Restoring wallet failed, wallet address: " + WalletAddress + " not exist inside database, please try again later.", ClassConsoleColorEnumeration.IndexConsoleRedLog); WalletCreateResult = ClassWalletCreatorEnumeration.WalletCreatorError; FullDisconnection(); } } } break; } }
/// <summary> /// Auto sync wallets. /// </summary> private static void AutoSyncWallet() { if (ThreadAutoSync != null && (ThreadAutoSync.IsAlive || ThreadAutoSync != null)) { ThreadAutoSync.Abort(); GC.SuppressFinalize(ThreadAutoSync); } ThreadAutoSync = new Thread(async delegate() { while (ConnectionStatus && !Program.Exit) { try { foreach (var walletObject in ClassRpcDatabase.RpcDatabaseContent) { if (walletObject.Value.GetWalletUniqueId() != "-1" && walletObject.Value.GetWalletAnonymousUniqueId() != "-1") { #region Attempt to sync the current wallet on the database. CurrentWalletIdOnSync = walletObject.Value.GetWalletUniqueId(); CurrentAnonymousWalletIdOnSync = walletObject.Value.GetWalletAnonymousUniqueId(); CurrentWalletAddressOnSync = walletObject.Key; CurrentWalletOnSyncTransaction = true; if (await SendPacketToRemoteNode(ClassRemoteNodeCommandForWallet.RemoteNodeSendPacketEnumeration.WalletAskHisNumberTransaction + "|" + walletObject.Value.GetWalletUniqueId())) { while (CurrentWalletOnSyncTransaction) { if (!ConnectionStatus) { break; } Thread.Sleep(50); } if (CurrentWalletTransactionToSync > 0) { if (CurrentWalletTransactionToSync > walletObject.Value.GetWalletTotalTransactionSync()) // Start to sync transaction. { for (int i = walletObject.Value.GetWalletTotalTransactionSync(); i < CurrentWalletTransactionToSync; i++) { CurrentWalletOnSyncTransaction = true; if (!await SendPacketToRemoteNode(ClassRemoteNodeCommandForWallet.RemoteNodeSendPacketEnumeration.WalletAskTransactionPerId + "|" + walletObject.Value.GetWalletUniqueId() + "|" + i)) { ConnectionStatus = false; break; } while (CurrentWalletOnSyncTransaction) { if (!ConnectionStatus) { break; } Thread.Sleep(50); } } } } CurrentWalletOnSyncTransaction = true; if (await SendPacketToRemoteNode(ClassRemoteNodeCommandForWallet.RemoteNodeSendPacketEnumeration.WalletAskHisAnonymityNumberTransaction + "|" + walletObject.Value.GetWalletAnonymousUniqueId())) { while (CurrentWalletOnSyncTransaction) { if (!ConnectionStatus) { break; } Thread.Sleep(50); } if (CurrentWalletAnonymousTransactionToSync > 0) { if (CurrentWalletAnonymousTransactionToSync > walletObject.Value.GetWalletTotalAnonymousTransactionSync()) // Start to sync transaction. { for (int i = walletObject.Value.GetWalletTotalAnonymousTransactionSync(); i < CurrentWalletAnonymousTransactionToSync; i++) { CurrentWalletOnSyncTransaction = true; if (!await SendPacketToRemoteNode(ClassRemoteNodeCommandForWallet.RemoteNodeSendPacketEnumeration.WalletAskAnonymityTransactionPerId + "|" + walletObject.Value.GetWalletAnonymousUniqueId() + "|" + i)) { ConnectionStatus = false; break; } while (CurrentWalletOnSyncTransaction) { if (!ConnectionStatus) { break; } Thread.Sleep(50); } } } } } else { ConnectionStatus = false; break; } } else { ConnectionStatus = false; break; } #endregion } } } catch (Exception error) { ClassConsole.ConsoleWriteLine("Exception: " + error.Message + " to send packet on Remote Node host " + ClassRpcSetting.RpcWalletRemoteNodeHost + ":" + ClassRpcSetting.RpcWalletRemoteNodePort + " retry to connect in a few seconds..", ClassConsoleColorEnumeration.IndexConsoleRedLog, ClassConsoleLogLevelEnumeration.LogLevelRemoteNodeSync); break; } Thread.Sleep(1000); } ConnectionStatus = false; }); ThreadAutoSync.Start(); }