示例#1
0
        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);
        }
示例#4
0
        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));
        }
示例#5
0
        public void GenerateLoginResponse(ref JObject response, string guid, string address)
        {
            var result = new JObject();
            var job = new JObject();

            if (!Helpers.IsValidAddress(address, uint.Parse(Statics.Config.IniReadValue("base58-prefix"))))
            {
                result["error"] = "Invalid Address";
                return;
            }

            var 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;

            var seed = 0;

            job["blob"] = Helpers.GenerateUniqueWork(ref seed);

            job["job_id"] = Guid.NewGuid().ToString();

            var 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();

            Program..ConnectedClients.Add(guid, worker);

            // Add a new client in the database.
            if (Program.RedisPoolDatabase.Miners.Any(x => x.Address == worker.Address))
            {
                var miner = Program.RedisPoolDatabase.Miners.First(x => x.Address == worker.Address);
                var minerWorker = new MinerWorker(guid, miner.Identifier, 0);
                minerWorker.NewJobRequest();
                miner.MinersWorker.Add(guid);
                Program.RedisPoolDatabase.SaveChanges(miner);
                Program.RedisPoolDatabase.SaveChanges(minerWorker);
            }
            else
            {
                var miner = new Miner(worker.Address, 0);
                var minerWorker = new MinerWorker(guid, miner.Identifier, 0);
                minerWorker.NewJobRequest();
                miner.MinersWorker.Add(guid);
                Program.RedisPoolDatabase.SaveChanges(miner);
                Program.RedisPoolDatabase.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);
        }