private int GetCurrentBlockHeight() { P2PWebClient client = new P2PWebClient(); client.RequestTimeout = 10000; string data = client.DownloadString("http://blockchain.info/q/getblockcount"); return int.Parse(data); }
private List<Block> GetBlocksAtHeight(int height) { List<Block> blocks = new List<Block>(); P2PWebClient client = new P2PWebClient(); client.RequestTimeout = 10000; var blocksAtHeight = JObject.Parse(client.DownloadString(string.Format("http://blockchain.info/block-height/{0}?format=json", height))); foreach (var blockData in (JArray)blocksAtHeight["blocks"]) { Block block = new Block(); block.Id = (string)blockData["hash"]; block.BlockHeight = (int)blockData["height"]; block.Difficulty = (decimal)BitcoinMathHelper.Difficulty((long)blockData["bits"]); block.PrevBlock = (string)blockData["prev_block"]; block.Timestamp = (int)blockData["time"]; block.IsOrphaned = !(bool)blockData["main_chain"]; var genTx = blockData["tx"][0]; block.GenerationTxHash = (string)genTx["hash"]; var outputs = (JArray)genTx["out"]; foreach (var output in outputs) { if ((string)output["addr"] == DonationAddress) { var lastOutput = outputs[outputs.Count - 1]; if (outputs.Count > 25 && (decimal)lastOutput["value"] == 0 && (decimal)lastOutput["type"] == -1) { block.IsP2Pool = true; } break; } } blocks.Add(block); } return blocks; }
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); } }
public List<Block> FindOrphans(HashSet<string> knownTxHashes) { List<Block> newBlocks = new List<Block>(); P2PWebClient client = new P2PWebClient(); client.RequestTimeout = 30000; var addressData = JObject.Parse(client.DownloadString("http://blockchain.info/address/1Kz5QaUPDtKrj5SqW5tFkn7WZh8LmQaQi4?format=json&filter=0")); foreach (var tx in (JArray)addressData["txs"]) { try { if (tx["inputs"] != null && tx["inputs"].Type == JTokenType.Array && ((JArray)tx["inputs"]).Count == 1 && ((JArray)tx["inputs"])[0]["prev_out"] == null) { string generationTxHash = (string)tx["hash"]; if (!knownTxHashes.Contains(generationTxHash)) { int blockHeight; if (tx["block_height"] != null) { blockHeight = (int)tx["block_height"]; var blocksAtHeight = JObject.Parse(client.DownloadString(string.Format("http://blockchain.info/block-height/{0}?format=json", blockHeight))); foreach (var blockData in (JArray)blocksAtHeight["blocks"]) { try { if (blockData["tx"] != null && blockData["tx"][0] != null && blockData["tx"][0]["hash"] != null && (string)blockData["tx"][0]["hash"] == generationTxHash && blockData["tx"][0]["out"] is JArray && ((JArray)blockData["tx"][0]["out"]).Count > 25) { Block block = new Block(); block.Id = (string)blockData["hash"]; block.BlockHeight = (int)blockData["height"]; block.Difficulty = (decimal)BitcoinMathHelper.Difficulty((long)blockData["bits"]); block.GenerationTxHash = generationTxHash; block.IsP2Pool = true; block.PrevBlock = (string)blockData["prev_block"]; block.Timestamp = (int)blockData["time"]; block.IsOrphaned = !(bool)blockData["main_chain"]; newBlocks.Add(block); break; } } catch { //absorb and check next block } } } else { string TxDataHtml = client.DownloadString(string.Format("http://blockchain.info/tx/{0}", generationTxHash)); bool doneParsing = false; HtmlDocument document = new HtmlDocument(); document.LoadHtml(TxDataHtml); var tables = document.DocumentNode.SelectNodes("//table"); foreach (var table in tables) { var header = table.SelectSingleNode("tr/th"); if (header == null || header.InnerText.ToLower() != "summary") { continue; } var links = table.SelectNodes(".//a"); foreach (var link in links) { var blockUrl = link.GetAttributeValue("href", ""); if (blockUrl.StartsWith("/block-index/")) { var blockData = JObject.Parse(client.DownloadString(string.Format("http://blockchain.info{0}?format=json", blockUrl))); try { if (((JArray)blockData["tx"][0]["out"]).Count > 10) { Block block = new Block(); block.Id = (string)blockData["hash"]; block.BlockHeight = (int)blockData["height"]; block.Difficulty = (decimal)BitcoinMathHelper.Difficulty((long)blockData["bits"]); block.GenerationTxHash = generationTxHash; block.IsP2Pool = true; block.PrevBlock = (string)blockData["prev_block"]; block.Timestamp = (int)blockData["time"]; block.IsOrphaned = !(bool)blockData["main_chain"]; newBlocks.Add(block); } } catch { //absorb } doneParsing = true; break; } } if (doneParsing) { break; } } } } } } catch { //absorb and check next tx } } return newBlocks; }