示例#1
0
        private List<Subsidy> GetNewSubsidies()
        {
            int lastKnownBlockHeight = 0;
//            HashSet<string> p2poolAddresses = null;
            Retry.ExecuteAction(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    lastKnownBlockHeight = (from b in db.Blocks
                                            orderby b.BlockHeight descending
                                            select b.BlockHeight).Take(1).FirstOrDefault();
                    //var p2poolAddressesQuery = (from u in db.Users
                    //                            select u.Address).Distinct();
                    //p2poolAddresses = new HashSet<string>(p2poolAddressesQuery);
                }
            });

            foreach (var backend in _backends)
            {
                try
                {
                    //return backend.GetNewSubsidies(lastKnownBlockHeight, p2poolAddresses);
                }
                catch
                {
                    //absorb
                }
            }

            return new List<Subsidy>();
        }
示例#2
0
        private List<Block> GetNewBlocks()
        {
            int lastKnownBlockHeight = 0;
            string[] lastKnownBlockHashes = null;
            HashSet<string> knownTxHashes = null;
            Retry.ExecuteAction(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    lastKnownBlockHeight = (from b in db.Blocks
                                            orderby b.BlockHeight descending
                                            select b.BlockHeight).Take(1).FirstOrDefault();
                    lastKnownBlockHashes = (from b in db.Blocks
                                            where b.BlockHeight == lastKnownBlockHeight
                                            select b.Id).ToArray();
                    knownTxHashes = new HashSet<string>(from b in db.Blocks 
                                                        where b.IsP2Pool || b.IsFalseP2Pool
                                                        select b.GenerationTxHash);
                }
            });

            IEnumerable<Block> newBlocks = null;

            foreach (var backend in _backends)
            {
                try
                {
                    var someNewBlocks = backend.GetNewBlocks(lastKnownBlockHeight, lastKnownBlockHashes, knownTxHashes);
                    if (newBlocks == null)
                    {
                        newBlocks = someNewBlocks;
                    }
                    else
                    {
                        newBlocks = newBlocks.Union(someNewBlocks, new BlockEqualityComparer());
                    }
                    knownTxHashes.UnionWith(from b in someNewBlocks select b.GenerationTxHash);
                }
                catch
                {
                    //absorb
                }
            }

            return new List<Block>(newBlocks ?? new Block[] { });
        }
        public ActionResult Stats(long? from)
        {
            Stopwatch timer = new Stopwatch();
            Debug.WriteLine("Starting stats update, from = {0}", from);
            timer.Start();
            return Retry.ExecuteAction<ActionResult>(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    int cutoff = 0;

                    var statsQuery = db.Stats.AsQueryable();

                    if (from.HasValue)
                    {
                        cutoff = (int)from.Value / 1000;
                        statsQuery = statsQuery.Where(s => s.Timestamp > cutoff);
                    }

                    var ratesQuery = (from s in statsQuery
                                      group s by Math.Floor(s.Timestamp / 7200m) into grouped
                                      select new { Timestamp = grouped.Key * 7200000, Rate = grouped.Average(x => x.Rate), Users = grouped.Max(x => x.Users) });

                    if (from.HasValue)
                    {
                        ratesQuery = ratesQuery.Where(x => x.Timestamp > from.Value);
                    }

                    var rates = ratesQuery.ToList();

                    if (rates.Count == 0)
                    {
                        return Json(new
                        {
                            rates = new int[] { },
                            users = new int[] { }
                        }, JsonRequestBehavior.AllowGet);
                    }

                    var ratesArray = (from r in rates
                                      orderby r.Timestamp
                                      select new List<object> { (long)r.Timestamp, Math.Round((double)r.Rate, 1) }).ToList();

                    var users = (from r in rates
                                 orderby r.Timestamp
                                 select new List<object> { (long)r.Timestamp, (int)r.Users }).ToList();


                    var maxRate = (from s in db.Stats
                                   select s.Rate).Max();
                    var maxUsers = (from s in db.Stats
                                    select s.Users).Max();


                    var result = new
                    {
                        rates = ratesArray,
                        users = users.ToList(),
                        maxRate = maxRate,
                        maxUsers = maxUsers,
                    };

                    string json = JsonConvert.SerializeObject(result);

                    timer.Stop();
                    Debug.WriteLine("..End stats update, from = {0}, time = {1}", from, timer.ElapsedMilliseconds / 1000m);

                    return Content(json, "application/json");
                }
            });
        }
        private List<Block> GetBlocks()
        {
            Stopwatch timer = new Stopwatch();
            Debug.WriteLine("Starting blocks update");
            timer.Start();
            return Retry.ExecuteAction<List<Block>>(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    var dbBlockCount = (from b in db.Blocks where b.IsP2Pool select b).Count();

                    if (DateTime.Now < _blocksExpire && _blocks != null && dbBlockCount == _blocks.Count)
                    {
                        var lastBlock = (from b in db.Blocks where b.IsP2Pool orderby b.BlockHeight descending select b).First();
                        if (lastBlock.Id == _blocks[0].Id && lastBlock.IsOrphaned == _blocks[0].IsOrphaned)
                        {
                            return _blocks;
                        }
                    }

                    var blocks = (from b in db.Blocks where b.IsP2Pool orderby b.BlockHeight, b.Timestamp select b).ToList();

                    try
                    {
                        //build hashrate list
                        List<Stat> stats = (from s in db.Stats orderby s.Timestamp select s).ToList();

                        Block lastBlock = null;
                        foreach (var block in blocks)
                        {
                            if (lastBlock != null)
                            {
                                block.RoundDuration = block.Timestamp - lastBlock.Timestamp;
                                decimal averageRateBetweenBlocks = GetAverageHashBetweenTimes(lastBlock.Timestamp, block.Timestamp, stats) * 1000000000;
                                decimal difficulty = block.Difficulty;
                                block.ExpectedDuration = (int)(difficulty * 4294967296 / averageRateBetweenBlocks);
                                block.ActualShares = (long)((block.RoundDuration * averageRateBetweenBlocks) / 4294967296);
                                block.ExpectedShares = (long)difficulty;


                            }
                            lastBlock = block;
                        }
                        blocks.Sort(new Comparison<Block>((a, b) =>
                        {
                            var result = b.BlockHeight.CompareTo(a.BlockHeight);
                            if (result == 0)
                            {
                                result = b.Timestamp.CompareTo(a.Timestamp);
                            }
                            return result;
                        }));
                        _blocks = blocks;
                        _blocksExpire = DateTime.Now.AddHours(2);
                        return blocks;
                    }
                    catch
                    {
                        return _blocks;
                    }
                    finally
                    {
                        timer.Stop();
                        Debug.WriteLine("..End blocks update, time = {0}", timer.ElapsedMilliseconds / 1000m);
                    }

                }
            });
        }
        public ActionResult Users() 
        {
            return Retry.ExecuteAction<ActionResult>(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    int cutoff = (int)(DateTime.UtcNow.AddHours(-24) - new DateTime(1970, 1, 1)).TotalSeconds;

                    var rawUsers = (from u in db.Users
                                    where u.Timestamp > cutoff
                                    select u).ToList();

                    decimal sum = rawUsers.Sum(u => u.Portion);

                    List<Stat> stats = (from s in db.Stats
                                        where s.Timestamp > (cutoff - 86400)
                                        select s).ToList();

                    decimal totalHashrate = GetAverageHashBetweenTimes(cutoff, cutoff + 86400, stats);

                    var response = (from u in rawUsers
                                    group u by u.Address into g
                                    select new
                                    {
                                        Address = g.Key,
                                        Hashrate = Math.Round(totalHashrate * (g.Sum(u => u.Portion) / sum) * 1000, 0)
                                    })
                                    .OrderByDescending(u => u.Hashrate).Select(u => new
                                    {
                                        Address = u.Address,
                                        Hashrate = u.Hashrate.ToString("#,0 MH/s")
                                    });


                    return Json(response, JsonRequestBehavior.AllowGet);
                }
            });
        }
 public ActionResult Donations()
 {
     return Retry.ExecuteAction<ActionResult>(() =>
     {
         using (P2PoolDb db = new P2PoolDb())
         {
             var response = (from s in db.Subsidies
                             orderby s.BlockHeight descending
                             select s).ToList();
             return Json(response, JsonRequestBehavior.AllowGet);
         }
     });
 }
        public ActionResult Payouts()
        {
            return Retry.ExecuteAction<ActionResult>(() =>
            {
                using (P2PoolDb db = new P2PoolDb())
                {
                    string payoutsJson = db.CurrentPayouts.Find(1).Payouts;
                    var payouts = JObject.Parse(payoutsJson);

                    var response = (from a in
                                        (from p in payouts.Properties()
                                         select new
                                         {
                                             Address = P2PHelper.ExtractAddress(p.Name) ?? "Unknown",
                                             Payment = (decimal)p.Value
                                         })
                                    group a by a.Address into g
                                    select new
                                    {
                                        Address = g.Key,
                                        Payment = g.Sum(a => a.Payment)
                                    })
                                    .OrderByDescending(p => p.Payment).ToList();

                    return Json(response, JsonRequestBehavior.AllowGet);
                }
            });
        }
示例#8
0
        public void UpdateDatabase()
        {
            try
            {
                //look for subsidies before we add new blocks because we depend on lastKnowBlockHeight to know where to start looking
                var subsidies = GetNewSubsidies();

                if (subsidies.Count > 0)
                {
                    Retry.ExecuteAction(() =>
                    {
                        using (P2PoolDb db = new P2PoolDb())
                        {
                            foreach (var subsidy in subsidies)
                            {
                                var existingSubsidy = db.Subsidies.Find(subsidy.TxHash);
                                if (existingSubsidy == null)
                                {
                                    Log(string.Format("Adding subsidy of {0} BTC, {1}", subsidy.Amount, subsidy.TxHash));
                                    db.Subsidies.Add(subsidy);
                                }
                                else if (existingSubsidy.BlockHeight != subsidy.BlockHeight || existingSubsidy.BlockHash != subsidy.BlockHash)
                                {
                                    Log(string.Format("Updating subsidy of {0} BTC, {1}", subsidy.Amount, subsidy.TxHash));
                                    existingSubsidy.BlockHash = subsidy.BlockHash;
                                    existingSubsidy.BlockHeight = subsidy.BlockHeight;
                                }
                                db.SaveChanges();
                            }
                        }
                    });
                }

                var blocks = GetNewBlocks();
                if (blocks.Count > 0)
                {
                    Retry.ExecuteAction(() =>
                    {
                        using (P2PoolDb db = new P2PoolDb())
                        {
                            foreach (var block in blocks)
                            {
                                var existingBlock = db.Blocks.Find(block.Id);
                                if (existingBlock == null)
                                {
                                    Log(string.Format("Adding block {0}, {1}{2}", block.BlockHeight, block.Id, block.IsP2Pool ? " (p2pool)" : ""));
                                    db.Blocks.Add(block);
                                }
                                else
                                {
                                    Log(string.Format("Updating block {0}, {1}{2}", block.BlockHeight, block.Id, block.IsP2Pool ? " (p2pool)" : ""));
                                    existingBlock.BlockHeight = block.BlockHeight;
                                    existingBlock.Difficulty = block.Difficulty;
                                    existingBlock.GenerationTxHash = block.GenerationTxHash;
                                    existingBlock.IsOrphaned = block.IsOrphaned;
                                    existingBlock.IsP2Pool = block.IsP2Pool;
                                    existingBlock.PrevBlock = block.PrevBlock;
                                    existingBlock.Timestamp = block.Timestamp;
                                }
                                db.SaveChanges();
                            }

                            //the following logic is too simplistic and only finds orphaned blocks if they are immediatly orphaned (vs a race between to candidate chains that lasts more than 1 block)

                            // this clears the orphaned flag from any blocks that now have a later block pointing at them
                            //db.Database.ExecuteSqlCommand("update p2pool_Blocks set isorphaned=0 where isorphaned=1 and exists (select * from p2pool_Blocks as b2 where b2.PrevBlock = p2pool_Blocks.Id)");

                            // this sets the orphaned flag for any blocks that aren't pointed at by some later block
                            db.Database.ExecuteSqlCommand("update p2pool_Blocks set isorphaned=1 where blockheight < (select max(blockheight) from p2pool_Blocks) and not exists (select * from p2pool_Blocks as b2 where b2.PrevBlock = p2pool_Blocks.Id)");
                        }
                    });
                }

            }
            catch (Exception ex)
            {
                Log("UpdateDatabase: " + ex.Message);
            }
        }
示例#9
0
        public void UpdateStats()
        {
            try
            {
                int timestamp = DateTime.UtcNow.ToUnixTime();

                int remainder = timestamp % 300;
                timestamp -= remainder;

                Log(string.Format("Updating stats for timestamp {0}", timestamp));

                IEnumerable<string> servers = null;

                bool updatedData = false;
                P2PWebClient client = new P2PWebClient();
                client.RequestTimeout = 3000;

                Retry.ExecuteAction(() =>
                {
                    using (P2PoolDb db = new P2PoolDb())
                    {
                        var existingUsersCount = (from u in db.Users where u.Timestamp == timestamp select u.Address).Count();

                        if (existingUsersCount == 0)
                        {
                            JObject users = null;

                            if (servers == null)
                            {
                                servers = GetServers();
                            }
                            foreach (var server in servers)
                            {
                                if (string.IsNullOrWhiteSpace(server))
                                {
                                    continue;
                                }
                                try
                                {
                                    var baseUrl = new Uri(server.Trim());
                                    users = JObject.Parse(client.DownloadString(new Uri(baseUrl, "/users")));
                                    Log(string.Format(" Stats: Retrived users from {0}", server));
                                    break;
                                }
                                catch (Exception ex)
                                {
                                    Log(" Stats: " + ex.Message);
                                }
                            }

                            if (users == null)
                            {
                                return;
                            }

                            Dictionary<string, decimal> addresses = new Dictionary<string, decimal>();
                            foreach (var userEntry in users.Properties())
                            {
                                string address = P2PHelper.ExtractAddress(userEntry.Name) ?? "Unknown";
                                if (address != null)
                                {
                                    decimal portion = 0;
                                    if (addresses.ContainsKey(address))
                                    {
                                        portion += addresses[address];
                                    }
                                    portion += (decimal)userEntry.Value;
                                    addresses[address] = portion;
                                }
                            }
                            foreach (var item in addresses)
                            {
                                User user = new User()
                                {
                                    Timestamp = timestamp,
                                    Address = item.Key,
                                    Portion = item.Value
                                };
                                db.Users.Add(user);

                            }
                            db.SaveChanges();
                            updatedData = true;
                            Log(string.Format(" Stats: Added {0} users", addresses.Count));
                        }


                    }
                });

                Retry.ExecuteAction(() =>
                {
                    using (P2PoolDb db = new P2PoolDb())
                    {


                        Stat entry = db.Stats.Find(timestamp);
                        if (entry == null)
                        {
                            decimal rate = -1;
                            if (servers == null)
                            {
                                servers = GetServers();
                            }
                            foreach (var server in servers)
                            {
                                if (string.IsNullOrWhiteSpace(server))
                                {
                                    continue;
                                }
                                try
                                {
                                    var baseUrl = new Uri(server.Trim());
                                    rate = decimal.Parse(client.DownloadString(new Uri(baseUrl, "/rate"))) / 1000000000m;
                                    Log(string.Format(" Stats: Retrived rate from {0}", server));
                                    break;
                                }
                                catch (Exception ex)
                                {
                                    Log(" Stats: " + ex.Message);
                                }
                            }

                            if (rate == -1)
                            {
                                return;
                            }

                            int userCount;

                            userCount = db.Database.SqlQuery<int>("select count (distinct address) from p2pool_Users where timestamp >= @start and timestamp <= @end", new SqlParameter("start", timestamp - 86400), new SqlParameter("end", timestamp)).First();

                            entry = new Stat
                            {
                                Timestamp = timestamp,
                                Rate = rate,
                                Users = userCount
                            };
                            db.Stats.Add(entry);
                            db.SaveChanges();
                            updatedData = true;
                            Log(string.Format(" Stats: Saved new rate: {0}", rate));

                        }
                    }
                });

                if (updatedData)
                {

                    Retry.ExecuteAction(() =>
                    {
                        using (P2PoolDb db = new P2PoolDb())
                        {
                            CurrentPayouts entry = db.CurrentPayouts.Find(1);
                            if (entry != null)
                            {
                                JObject payouts = null;
                                if (servers == null)
                                {
                                    servers = GetServers();
                                }
                                foreach (var server in servers)
                                {
                                    if (string.IsNullOrWhiteSpace(server))
                                    {
                                        continue;
                                    }
                                    try
                                    {
                                        var baseUrl = new Uri(server.Trim());
                                        payouts = JObject.Parse(client.DownloadString(new Uri(baseUrl, "/current_payouts")));
                                        Log(string.Format(" Stats: Retrived payouts from {0}", server));
                                        break;
                                    }
                                    catch (Exception ex)
                                    {
                                        Log(" Stats: " + ex.Message);
                                    }
                                }
                                if (payouts == null)
                                {
                                    return;
                                }
                                entry.Payouts = payouts.ToString();
                                entry.Updated = timestamp;
                                db.SaveChanges();
                                Log(" Stats: Saved updated payouts");
                            }
                        }
                    });

                    //cleanup old user stats
                    Retry.ExecuteAction(() =>
                    {
                        using (P2PoolDb db = new P2PoolDb())
                        {
                            // delete all the specific user stats older than 3 days
                            var result = db.Database.ExecuteSqlCommand("delete from p2pool_Users where [Timestamp] < @cutoff", new SqlParameter("cutoff", timestamp - 259200));
                            Log(string.Format(" Stats: Deleted old user rows", result));
                        }
                    });

                }

            }
            catch (Exception ex)
            {
                Log(" Stats: UpdateStats Exception: " + ex.Message);
            }
        }