public bool GenerateSubmitResponse(ref JObject response, string jobId, string guid, byte[] nonce, string resultHash, string ipAddress) { ConnectedWorker worker = Statics.ConnectedClients[guid]; Statics.TotalShares++; JObject result = new JObject(); if (nonce == null || nonce.Length == 0) { response["error"] = "Invalid arguments!"; return(false); } try { ShareJob shareJob = worker.JobSeed.First(x => x.Key == jobId).Value; if (!shareJob.SubmittedShares.Contains(BitConverter.ToInt32(nonce, 0))) { shareJob.SubmittedShares.Add(BitConverter.ToInt32(nonce, 0)); } else { response["error"] = "Duplicate share"; return(false); } int jobSeed = shareJob.Seed; worker.ShareRequest(shareJob.CurrentDifficulty); Statics.RedisDb.MinerWorkers.First(x => x.Identifier == guid).ShareRequest(shareJob.CurrentDifficulty); byte[] prevJobBlock = Helpers.GenerateShareWork(jobSeed, true); Array.Copy(nonce, 0, prevJobBlock, 39, nonce.Length); byte[] blockHash = Hash.CryptoNight(prevJobBlock); Statics.ConnectedClients[guid].LastSeen = DateTime.Now; if (resultHash.ToUpper() != BitConverter.ToString(blockHash).Replace("-", "")) { Logger.Log(Logger.LogLevel.General, "Hash mismatch from {0}", guid); result["status"] = "Hash mismatch "; // throw new Exception(); } else { ShareProcess shareProcess = Helpers.ProcessShare(blockHash, (int)Statics.CurrentBlockTemplate["difficulty"], (uint)shareJob.CurrentDifficulty); string address = Statics.ConnectedClients[guid].Address; worker.TotalShares++; if (shareProcess == ShareProcess.ValidShare || shareProcess == ShareProcess.ValidBlock) { Statics.HashRate.Difficulty += (uint)shareJob.CurrentDifficulty; Statics.HashRate.Time = (ulong)((DateTime.Now - Statics.HashRate.Begin).TotalSeconds); try { IncreaseShareCount(guid, (uint)shareJob.CurrentDifficulty); } catch (Exception e) { Logger.Log(Logger.LogLevel.Error, e.ToString()); throw; } if (shareProcess == ShareProcess.ValidBlock && !Statics.BlocksPendingSubmition.Any(x => x.BlockHeight == worker.CurrentBlock)) { Logger.Log(Logger.LogLevel.Special, "Block found by {0}", guid); byte[] shareWork = Helpers.GenerateShareWork(jobSeed, false); Array.Copy(nonce, 0, shareWork, 39, nonce.Length); Statics.BlocksPendingSubmition.Add(new PoolBlock(shareWork, worker.CurrentBlock, "", Statics.ConnectedClients[guid].Address)); } result["status"] = "OK"; } else { result["status"] = "Share failed valdiation!"; worker.RejectedShares++; if ((double)worker.RejectedShares / worker.TotalShares > int.Parse(Statics.Config.IniReadValue("ban-reject-percentage")) && worker.TotalShares > int.Parse(Statics.Config.IniReadValue("ban-after-shares"))) { result["status"] = "You're banished!"; int minutes = int.Parse(Statics.Config.IniReadValue("ban-time-minutes")); Logger.Log(Logger.LogLevel.General, "Client with address {0} ip {1} banned for {2} minutes for having a reject rate of {3}", worker.Address, ipAddress, minutes, (double)worker.RejectedShares / worker.TotalShares); Ban ban = new Ban(); ban.AddressBan = worker.Address; ban.IpBan = ipAddress; ban.Begin = DateTime.Now; ban.Minutes = minutes; Statics.RedisDb.SaveChanges(ban); response["result"] = result; return(true); } } } } catch { result["error"] = "Invalid job id"; } response["result"] = result; return(false); }
private static async void AcceptClient(HttpListenerContext client) { // client.AcceptWebSocketAsync() string abcdef = GetRequestBody(client.Request); if (abcdef == "") { return; } // Console.WriteLine(abcdef); JObject request = JObject.Parse(abcdef); client.Response.ContentType = "application/json"; JObject response = new JObject(); response["id"] = 0; response["jsonrpc"] = "2.0"; string guid; if ((string)request["method"] == "login") { guid = Guid.NewGuid().ToString(); } else { guid = (string)request["params"]["id"]; } try { if ((string)request["method"] == "login" || ConnectedClients.ContainsKey(guid) && (string)request["method"] == "getjob") { JObject result = new JObject(); if ((string)request["method"] == "login") { Console.WriteLine("login request from {0}", guid); result["id"] = guid; } JObject job = new JObject(); JObject blob = json.InvokeMethod("getblocktemplate", new JObject(new JProperty("reserve_size", 4), new JProperty("wallet_address", config.IniReadValue("wallet-address")))); if ((string)request["method"] == "login" || (int)blob["result"]["height"] > (int)ConnectedClients[guid].work["result"]["height"]) { if ((string)request["method"] == "getjob") { Console.WriteLine("getjob request from {0}", guid); worker abc = ConnectedClients[guid]; abc.work = blob; ConnectedClients[guid] = abc; //.work = blob; } else { worker worker = new worker(); //worker.guid = guid; worker.address = (string)request["params"]["login"]; worker.work = blob; Console.WriteLine("Adding {0} to connected clients", guid); try { ConnectedClients.Add(guid, worker); } catch (Exception e) { Console.WriteLine(e.ToString()); } } job["blob"] = (string)blob["result"]["blocktemplate_blob"]; job["job_id"] = Guid.NewGuid().ToString(); job["target"] = config.IniReadValue("miner-target-hex"); } else { job["blob"] = ""; job["job_id"] = ""; job["target"] = ""; } result["job"] = job; if ((string)request["method"] == "login") { result["status"] = "OK"; } response["result"] = result; } else if (ConnectedClients.ContainsKey(guid) && (string)request["method"] == "submit") { JObject prevjob = ConnectedClients[guid].work; byte[] nonce = StringToByteArray((string)request["params"]["nonce"]); byte[] blockdata = StringToByteArray((string)prevjob["result"]["blocktemplate_blob"]); Array.Copy(nonce, 0, blockdata, 39, nonce.Length); JObject result = new JObject(); byte[] blockHash = CryptoNight(blockdata); //Console.WriteLine(BitConverter.ToString(test).Replace("-", "")); if (((string)request["params"]["result"]).ToUpper() != BitConverter.ToString(blockHash).Replace("-", "")) { throw new Exception(); } ShareProcess shareProcess = ProcessShare(blockHash, (int)prevjob["result"]["difficulty"], BitConverter.ToInt32(StringToByteArray(config.IniReadValue("miner-target-hex")), 0)); string address = ConnectedClients[guid].address; if (shareProcess == ShareProcess.ValidShare || shareProcess == ShareProcess.ValidBlock) { try { IncreaseShareCount(address); } catch (Exception e) { Console.WriteLine(e.ToString()); throw; } if (shareProcess == ShareProcess.ValidBlock) { ProcessBlock(blockdata); } result["status"] = "OK"; } else { result["status"] = "NOTOK"; } response["result"] = result; // Console.WriteLine(response.ToString()); } worker abc2 = ConnectedClients[guid]; abc2.last_heard = DateTime.Now; ConnectedClients[guid] = abc2; string s = JsonConvert.SerializeObject(response); // Console.WriteLine(s); byte[] byteArray = Encoding.UTF8.GetBytes(s); client.Response.ContentLength64 = byteArray.Length; client.Response.OutputStream.Write(byteArray, 0, byteArray.Length); client.Response.OutputStream.Close(); //client.Response.Close(); } catch (Exception e) { ConnectedClients.Remove(guid); Console.WriteLine("Exception : {0}", e.Message); } }