public static uint WorkerVardiffDifficulty(ConnectedWorker worker) { double aTargetTime = int.Parse(Statics.Config.IniReadValue("vardiff-targettime-seconds")); uint returnValue = 0; // Don't keep it no zone forever if ((DateTime.Now - worker.LastShare).TotalSeconds > aTargetTime) { double deviance = 100 - (((DateTime.Now - worker.LastShare).Seconds * 100) / aTargetTime); if (Math.Abs(deviance) > int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation"))) { deviance = -int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation")); } returnValue = (uint)((worker.LastDifficulty * (100 + deviance)) / 100); } else { //We calculate average of last 4 shares. double aTime = worker.ShareDifficulty.Skip(worker.ShareDifficulty.Count - 4).Take(4).Sum(x => x.Key.TotalSeconds) / 4; double deviance = 100 - ((aTime * 100) / int.Parse(Statics.Config.IniReadValue("vardiff-targettime-seconds"))); if (Math.Abs(deviance) < int.Parse(Statics.Config.IniReadValue("vardiff-targettime-deviation-allowed"))) { returnValue = worker.LastDifficulty; } else if (deviance > 0) { if (deviance > int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation"))) { deviance = int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation")); } returnValue = (uint)((worker.LastDifficulty * (100 + deviance)) / 100); } else { if (Math.Abs(deviance) > int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation"))) { deviance = -int.Parse(Statics.Config.IniReadValue("vardiff-targettime-maxdeviation")); } returnValue = (uint)((worker.LastDifficulty * (100 + deviance)) / 100); } } if (returnValue < uint.Parse(Statics.Config.IniReadValue("base-difficulty"))) { returnValue = uint.Parse(Statics.Config.IniReadValue("base-difficulty")); } else if (returnValue > uint.Parse(Statics.Config.IniReadValue("vardiff-max-difficulty"))) { returnValue = uint.Parse(Statics.Config.IniReadValue("vardiff-max-difficulty")); } Logger.Log(Logger.LogLevel.Debug, "Returning new difficulty if {0} vs previous {1}", returnValue, worker.LastDifficulty); return(returnValue); }
public static void GenerateGetJobResponse(ref JObject response, string guid) { JObject job = new JObject(); ConnectedWorker worker = Statics.ConnectedClients.First(x => x.Key == guid).Value; worker.LastSeen = DateTime.Now; /*if (worker.ShareDifficulty.Count >= 4) * worker.LastDifficulty = Helpers.WorkerVardiffDifficulty(worker); */ Logger.Log(Logger.LogLevel.General, "Getwork request from {0}", guid); //result["id"] = guid; int seed = 0; if (worker.PendingDifficulty != worker.LastDifficulty || worker.CurrentBlock != Statics.CurrentBlockHeight) { worker.CurrentBlock = Statics.CurrentBlockHeight; worker.LastDifficulty = worker.PendingDifficulty; job["blob"] = Helpers.GenerateUniqueWork(ref seed); job["job_id"] = Guid.NewGuid().ToString(); ShareJob shareJob = new ShareJob(); shareJob.CurrentDifficulty = worker.LastDifficulty; shareJob.Seed = seed; worker.JobSeed.Add(new KeyValuePair <string, ShareJob>((string)job["job_id"], shareJob)); if (worker.JobSeed.Count > int.Parse(Statics.Config.IniReadValue("max-concurrent-works"))) { worker.JobSeed.RemoveAt(0); } job["target"] = BitConverter.ToString( BitConverter.GetBytes(Helpers.GetTargetFromDifficulty((uint)shareJob.CurrentDifficulty))) .Replace("-", ""); } else { job["blob"] = ""; job["job_id"] = ""; job["target"] = ""; } response["result"] = job; MinerWorker minerWorker = Statics.RedisDb.MinerWorkers.First(x => x.Identifier == guid); minerWorker.NewJobRequest(); Statics.RedisDb.SaveChanges(minerWorker); Statics.ConnectedClients[guid] = worker; Logger.Log(Logger.LogLevel.Verbose, "Finsihed getjob response"); }
public void IncreaseShareCount(string guid, uint difficulty) { ConnectedWorker worker = Statics.ConnectedClients[guid]; double shareValue = (double)difficulty / int.Parse(Statics.Config.IniReadValue("base-difficulty")); Block block; if (Statics.RedisDb.Blocks.Any(x => x.BlockHeight == Statics.CurrentBlockHeight)) { block = Statics.RedisDb.Blocks.First(x => x.BlockHeight == Statics.CurrentBlockHeight); } else { block = new Block(Statics.CurrentBlockHeight); } Miner miner; if (Statics.RedisDb.Miners.Any(x => x.Address == worker.Address)) { miner = Statics.RedisDb.Miners.First(x => x.Address == worker.Address); } else { miner = new Miner(worker.Address, 0); } foreach (var fBlockReward in Statics.RedisDb.BlockRewards) { if (fBlockReward.Block == block.Identifier && fBlockReward.Miner == miner.Identifier) { Share fShare = new Share(fBlockReward.Identifier, shareValue); fBlockReward.Shares.Add(fShare.Identifier); Statics.RedisDb.SaveChanges(fBlockReward); Statics.RedisDb.SaveChanges(fShare); Statics.RedisDb.SaveChanges(miner); Statics.RedisDb.SaveChanges(block); return; } } BlockReward blockReward = new BlockReward(miner.Identifier, block.Identifier); Share share = new Share(blockReward.Identifier, shareValue); blockReward.Shares.Add(share.Identifier); miner.BlockReward.Add(blockReward.Identifier); block.BlockRewards.Add(blockReward.Identifier); Statics.RedisDb.SaveChanges(blockReward); Statics.RedisDb.SaveChanges(share); Statics.RedisDb.SaveChanges(miner); Statics.RedisDb.SaveChanges(block); }
public static double GetWorkerHashRate(ConnectedWorker worker) { ulong time = (ulong) (worker.ShareDifficulty.Skip(worker.ShareDifficulty.Count - 4).First().Key - worker.ShareDifficulty.Last().Key).Seconds; return(GetHashRate( worker.ShareDifficulty.Skip(worker.ShareDifficulty.Count - 4) .ToDictionary(x => x.Key, x => (uint)x.Value) .Values.ToList(), time)); }
public void GenerateLoginResponse(ref JObject response, string guid, string address) { JObject result = new JObject(); JObject job = new JObject(); if (!Helpers.IsValidAddress(address, uint.Parse(Statics.Config.IniReadValue("base58-prefix")))) { result["error"] = "Invalid Address"; return; } ConnectedWorker worker = new ConnectedWorker(); worker.Address = address; worker.LastSeen = DateTime.Now; worker.LastDifficulty = uint.Parse(Statics.Config.IniReadValue("base-difficulty")); worker.CurrentBlock = Statics.CurrentBlockHeight; Logger.Log(Logger.LogLevel.General, "Adding {0} to connected clients", guid); result["id"] = guid; int seed = 0; job["blob"] = Helpers.GenerateUniqueWork(ref seed); job["job_id"] = Guid.NewGuid().ToString(); ShareJob shareJob = new ShareJob(); shareJob.CurrentDifficulty = worker.LastDifficulty; shareJob.Seed = seed; worker.JobSeed.Add(new KeyValuePair <string, ShareJob>((string)job["job_id"], shareJob)); job["target"] = BitConverter.ToString( BitConverter.GetBytes(Helpers.GetTargetFromDifficulty((uint)shareJob.CurrentDifficulty))) .Replace("-", ""); Logger.Log(Logger.LogLevel.General, "Sending new work with target {0}", (string)job["target"]); result["job"] = job; result["status"] = "OK"; response["result"] = result; worker.NewJobRequest(); Statics.ConnectedClients.Add(guid, worker); //Initialize new client in DB if (Statics.RedisDb.Miners.Any(x => x.Address == worker.Address)) { Miner miner = Statics.RedisDb.Miners.First(x => x.Address == worker.Address); MinerWorker minerWorker = new MinerWorker(guid, miner.Identifier, 0); minerWorker.NewJobRequest(); miner.MinersWorker.Add(guid); Statics.RedisDb.SaveChanges(miner); Statics.RedisDb.SaveChanges(minerWorker); } else { Miner miner = new Miner(worker.Address, 0); MinerWorker minerWorker = new MinerWorker(guid, miner.Identifier, 0); minerWorker.NewJobRequest(); miner.MinersWorker.Add(guid); Statics.RedisDb.SaveChanges(miner); Statics.RedisDb.SaveChanges(minerWorker); } Logger.Log(Logger.LogLevel.Verbose, "Finished login response"); }
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); }