private async Task <BlockSummary> GetBlockSummary(IHeader header, UInt64 height, UInt64 topHeight) { var hashStr = Binary.ByteArrayToHexString(header.Hash); var key = "blockSummary" + hashStr; if (memoryCache_.TryGetValue(key, out BlockSummary ret)) { return(ret); } using (var blockHeaderResult = await chain_.FetchBlockHeaderByHashTxSizesAsync(header.Hash)) { Utils.CheckBitprimApiErrorCode(blockHeaderResult.ErrorCode, "FetchBlockHeaderByHashTxSizesAsync(" + header.Hash + ") failed, check error log"); PoolInfo poolInfo; using (DisposableApiCallResult <GetTxDataResult> coinbase = await chain_.FetchTransactionAsync(blockHeaderResult.Result.TransactionHashes[0], true)) { Utils.CheckBitprimApiErrorCode(coinbase.ErrorCode, "FetchTransactionAsync(" + blockHeaderResult.Result.TransactionHashes[0] + ") failed, check error log"); poolInfo = poolsInfo_.GetPoolInfo(coinbase.Result.Tx); } var blockSummary = new BlockSummary { height = height, size = blockHeaderResult.Result.SerializedBlockSize, hash = Binary.ByteArrayToHexString(header.Hash), time = header.Timestamp, txlength = blockHeaderResult.Result.TransactionHashes.Count, poolInfo = new DTOs.PoolInfo { poolName = poolInfo.Name, url = poolInfo.Url } }; var confirmations = topHeight - height + 1; if (confirmations >= Constants.Cache.BLOCK_CACHE_CONFIRMATIONS) { memoryCache_.Set(key, blockSummary, new MemoryCacheEntryOptions { Size = Constants.Cache.BLOCK_CACHE_SUMMARY_SIZE }); } return(blockSummary); } }
public void SummarizeBlocks(int begin, int end) { //columns: blocknum, time, difficulty, valuein, valueout, reward, fees, version OutputColumns(); for (int i = end; i >= begin; i--) { var s = new BlockSummary(); var hash = Bit.InvokeMethod("getblockhash", i)["result"]; var info = Bit.InvokeMethod("getblock", hash)["result"]; s.BlockNum = info["height"].ToObject <int>(); s.Version = info["version"].ToObject <int>(); s.Time = info["time"].ToObject <long>().AsUnixTimestamp().ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss"); s.Difficulty = info["difficulty"].ToObject <decimal>(); //tallies decimal fees = 0M; decimal reward = 0M; decimal valuein = 0M; decimal valueout = 0M; //info about the genesis transaction is difficult to get at if (i == 0) { WriteSummaryLine(s); continue; } int txn = 0; List <string> PayoutAddresses = new List <string>(2); foreach (var t in info["tx"]) { var txcode = Bit.InvokeMethod("getrawtransaction", t, 1)["result"]; if (txcode == null) { throw new NotSupportedException("apparently doesn't support getrawtransaction. such shitcoin"); } bool coinbase = false; decimal txin = 0M; decimal txout = 0M; foreach (var vin in txcode["vin"]) { if (vin["coinbase"] != null) { coinbase = true; //mined continue; } txin += GetValueOut(vin["txid"].ToString(), vin["vout"].ToObject <int>()); } foreach (var vout in txcode["vout"]) { decimal tmp = vout["value"].ToObject <decimal>(); if (coinbase) { reward += tmp; var pubkey = vout["scriptPubKey"]; if (pubkey != null && pubkey["addresses"] != null) { foreach (var address in pubkey["addresses"]) { PayoutAddresses.Add(address.ToString()); } } } txout += tmp; } if (!coinbase) { decimal txfees = txin - txout; if (txfees < 0) { if (txn == 1 && decimal.Parse(txcode["vout"][0]["value"].ToString()) == 0M && txcode["vout"][0]["scriptPubKey"]["asm"].ToString() == "" && reward == 0) { //PoS reward reward += -txfees; txfees = 0; s.Type = "PoS"; } else { throw new ApplicationException("This transaction appears to have negative fees. This could mean the network has an exploit, or that this code can't handle some portion of it"); } } fees = txfees; } s.TxCount++; valuein += txin; valueout += txout; txn++; } //this is by no means meant to be exact or secure. It is only for eye balling where rewards go for blocks and what pool it's going to string payouts = ""; //ugh not possible with linq?! foreach (var addr in PayoutAddresses) { payouts += addr; } var hasher = new RIPEMD160Managed(); s.AddressHash = BitConverter.ToString(hasher.ComputeHash(Encoding.ASCII.GetBytes(payouts))).Replace("-", "").ToLower().Substring(0, 6); s.ValueIn = valuein; s.ValueOut = valueout; s.Fees = fees; s.Reward = reward - fees; WriteSummaryLine(s); } }
void WriteSummaryLine(BlockSummary s) { Console.WriteLine("{0,-10} {1,-20} {2,-15} {3,-10} {4,-20} {5,-20} {6,-20} {7,-20} {8,-10} {9,-6} {10,-10}", s.BlockNum, s.Time, s.Difficulty, s.TxCount, s.ValueIn, s.ValueOut, s.Reward, s.Fees, s.Version, s.Type, s.AddressHash); }