def draw_gui(self, screen): standard_width = options.standard_size()[0] standard_height = options.standard_size()[1] xoffset = (screen.get_width() - standard_width) / 2 yoffset = (screen.get_height() - standard_height) / 2 if screen.get_width() > standard_width or screen.get_height() > standard_height: # so that in dev mode you can see what the actual screen size would be. pygame.draw.rect(screen,(255,0,0), pygame.Rect(xoffset,yoffset,standard_width,standard_height), 1) level_text = self.font.render("Level: "+str(self.get_level_num() + 1), True, (255, 255, 255)) level_title = self.font.render(str(self.get_level_manager().current_level.name), True, (255, 255, 255)) death_text = self.font.render("Deaths: "+str(self.death_count), True, (255, 255, 255)) text_height = level_text.get_height() best_total_time = self.get_level_manager().get_best_run_time() total_time_text_color = self.get_time_display_color(self.total_time, best_total_time, start_color=(255, 255, 255), end_color=(255, 255, 255)) total_time_text = self.font.render("Total: " + utilities.format_time(self.total_time), True, total_time_text_color) best_level_time = self.get_level_manager().get_best_level_time(self.get_level_num()) level_time_text_color = self.get_time_display_color(self.level_time, best_level_time) level_time_text = self.font.render("Level: "+utilities.format_time(self.level_time), True, level_time_text_color) screen.blit(level_text, (xoffset, yoffset)) screen.blit(level_title, (xoffset, yoffset + text_height)) if self.settings.single_level_mode(): screen.blit(level_time_text, (xoffset + standard_width/2 - level_time_text.get_width()/2, yoffset)) else: screen.blit(total_time_text, (xoffset + standard_width/2 - total_time_text.get_width()/2, yoffset)) screen.blit(level_time_text, (xoffset + standard_width/2 - level_time_text.get_width()/2, yoffset + text_height)) screen.blit(death_text, (xoffset + standard_width - death_text.get_width(), yoffset))
def dump_highscores_to_file(self, suppress_printing=0): "0 = print nothing, 1 = print message, 2 = print entire file" if self.settings.dev_mode(): utilities.log("Not saving high scores because we're in dev mode") return if suppress_printing > 0: utilities.log("Saving highscores to "+self.get_highscores_filename()+"...") highscores = LevelManager.generate_empty_highscores_dict(self.get_num_levels(), checksums=[]) highscores["best_overall_run_total"] = utilities.format_time(self.best_overall_run_total) highscores["best_individual_scores"] = [utilities.format_time(self.best_individual_scores[i]) for i in range(0, self.get_num_levels())] highscores["best_overall_run_scores"] = [utilities.format_time(self.best_overall_run_scores[i]) for i in range(0, self.get_num_levels())] highscores["ghosts"] = [actors.Ghost.to_json(g) for g in self.ghosts] highscores["checksums"] = [self.get_checksum(i) for i in range(0, self.get_num_levels())] with open(self.get_highscores_filename(), 'w') as file: json_string = utilities.level_json_to_string(highscores) if suppress_printing > 1: utilities.log("writing text:\n" + json_string) file.write(json_string)
def update_level_highscore(self, level_num, time, ghost_recorder=None): dirty = False current_record = self.best_individual_scores[level_num] if current_record == None or time < current_record: utilities.log("***NEW LEVEL RECORD***\n" + "Level " + str(level_num)+"'s record of " + str(utilities.format_time(current_record)) + " broken with " + utilities.format_time(time) + "!") self.best_individual_scores[level_num] = time if ghost_recorder != None: self.ghosts[level_num] = ghost_recorder.to_ghost() dirty = True else: utilities.log("Level " + str(level_num) + " completed! Time: " + str(utilities.format_time(time)) + "\t Best: " + utilities.format_time(current_record)) self.current_run_times[level_num] = time if level_num == self.get_num_levels()-1: #last level final_time = 0 for val in self.current_run_times: if val == None: final_time = None break; else: final_time += val if final_time != None: if self.best_overall_run_total == None or final_time < self.best_overall_run_total: utilities.log("***NEW FULL RUN RECORD***\n" + "Previous record " + str(utilities.format_time(self.best_overall_run_total)) + " broken with " + str(utilities.format_time(final_time))) self.best_overall_run_total = final_time self.best_overall_run_scores = [self.current_run_times[i] for i in range(0,self.get_num_levels())] dirty = True else: utilities.log("Game Completed! Final time: " + str(utilities.format_time(final_time))) if dirty: self.dump_highscores_to_file(0)
def write_transaction_info(): if not option_tx_get_txs: writer.pln('<div class="transaction-section">') writer.pln('<a id="txid_{txid}" name="txid_{txid}"/>'.format(txid=txid)) writer.pln('<div class="transaction-section-header">') writer.pln('<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>'.format(txid=txid)) writer.pln("</div>") writer.pln("</div>") return tx_total_output_value_satoshi = 0 for txout in tx_info["vout"]: if "value" in txout: tx_total_output_value_satoshi += btc_to_satoshi(txout["value"]) assert option_tx_get_txs tx_fee_satoshi = calculate_tx_fee_satoshi(tx_info, src_tx_infos) writer.pln('<div class="transaction-section">') writer.pln('<div class="transaction-section-header">') writer.pln('<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>'.format(txid=txid)) if tx_fee_satoshi is None or not (tx_fee_satoshi > 0): writer.pln( '<span style="float:right"><strong>(Size: {size}) {time}</strong></span>'.format( size=format_bytes(len(tx_info["hex"]) / 2), time=format_time(tx_info["time"]) ) ) else: writer.pln( '<span style="float:right"><strong>(Fee: {fee} - Size: {size}) {time}</strong></span>'.format( fee=format_satoshi(tx_fee_satoshi), size=format_bytes(len(tx_info["hex"]) / 2), time=format_time(tx_info["time"]), ) ) writer.pln("</div>") def write_inputs(): writer.pln('<div class="tx-inputs">') writer.pln("<h4>Inputs</h4>") src_txids = [] for src_tx in tx_info["vin"]: if "txid" in src_tx: src_txid, src_out_index = src_tx["txid"], src_tx["vout"] src_txids.append((src_txid, src_out_index)) if len(src_txids) > 0: writer.pln('<table class="tx-inputs-table">') for src_txid, src_out_index in src_txids: writer.pln("<tr>") writer.pln( '<td><a href="/transaction?txid={src_txid}">{src_txid}</a>[<a href="/transaction?txid={src_txid}&output_idx={src_out_index}#output_{src_out_index}">{src_out_index}</a>]</td>'.format( src_txid=src_txid, src_out_index=src_out_index ) ) if option_tx_get_txs: src_tx_info = src_tx_infos[src_txid] src_output_value_satoshi = btc_to_satoshi(src_tx_info["vout"][src_out_index]["value"]) writer.pln( "<td>{src_output_value}</td>".format( src_output_value=format_satoshi(src_output_value_satoshi) ) ) writer.pln("</tr>") writer.pln("</table>") else: writer.pln("<strong>No Inputs (Newly Generated Coins)</strong>") writer.pln("</div>") write_inputs() def write_outputs(): writer.pln('<div class="tx-outputs">') writer.pln("<h4>Outputs</h4>") writer.pln('<table class="tx-outputs-table">') param_output_idx = request.getParameter("output_idx") if param_output_idx is None: param_output_idx = int(-1) param_output_idx = int(param_output_idx) for tx_output_entry_index in range(len(tx_info["vout"])): tx_output_entry = tx_info["vout"][tx_output_entry_index] if tx_output_entry_index == param_output_idx: writer.pln('<tr class="transaction-highlight-output-row">') else: writer.pln("<tr>") addresses = [] if "scriptPubKey" in tx_output_entry: if "addresses" in tx_output_entry["scriptPubKey"]: for address in tx_output_entry["scriptPubKey"]["addresses"]: addresses.append(address) writer.pln("<td>") writer.pln( '<a id="output_{output_idx}" name="output_{output_idx}" />'.format( output_idx=tx_output_entry_index ) ) if len(addresses) > 0: writer.pln("<ul>") for address in addresses: writer.pln("<li>{address}</li>".format(address=address)) writer.pln("</ul>") writer.pln("</td>") writer.pln( "<td>{value}</td>".format(value=format_satoshi(btc_to_satoshi(tx_output_entry["value"]))) ) writer.pln("</tr>") writer.pln("</table>") writer.pln("</div>") write_outputs() writer.pln('<div class="transaction-section-footer">') writer.pln( '<div class="transaction-total-output">{transaction_total_output}</div>'.format( transaction_total_output=format_satoshi(tx_total_output_value_satoshi) ) ) writer.pln("</div>") writer.pln("<!-- end transaction-section -->") writer.pln("</div>")
def service(self,request, response): print 'BlockView' try: access = self.server.create_access() config = self.server.config def configure_options(): option_blk_get_txs = request.getParameter('blk_get_txs') option_blk_get_tx_inputs = request.getParameter('blk_get_tx_inputs') if option_blk_get_txs != None: if option_blk_get_txs == '1': option_blk_get_txs = True elif option_blk_get_txs == '0': option_blk_get_txs = False else: option_blk_get_txs = None if option_blk_get_tx_inputs != None: if option_blk_get_tx_inputs == '1': option_blk_get_tx_inputs = True elif option_blk_get_tx_inputs == '0': option_blk_get_tx_inputs = False else: option_blk_get_tx_inputs = None if option_blk_get_txs is None: option_blk_get_txs = config['blk_get_txs'] if option_blk_get_txs is None: option_blk_get_tx_inputs = config['blk_get_tx_inputs'] return option_blk_get_txs,option_blk_get_tx_inputs option_blk_get_txs,option_blk_get_tx_inputs = configure_options() option_blk_get_tx_inputs = option_blk_get_txs and option_blk_get_tx_inputs rawtransactions = {} blk_hash = request.getParameter('hash') if blk_hash is None: height = request.getParameter('height') if height is None: response.setContentType('text/html') writer = response.getWriter() writer.pln('Invalid block identifier') self.basehandler.send_error(404) return height = int(height) blockcount = access.getblockcount() if not (height < blockcount): response.setContentType('text/html') writer = response.getWriter() writer.pln('Invalid block; not yet in blockchain. blockcount: {blockcount}'.format(blockcount=blockcount)) self.basehandler.send_error(404) return blk_hash = access.getblockhash(height) blk_info = access.getblock(blk_hash) height = blk_info['height'] reward_satoshi = calc_reward_satoshi(height) response.setContentType('text/html') tx_infos = {} if option_blk_get_txs: for txid in blk_info['tx']: tx_info = access.getrawtransaction(txid,1) tx_infos[txid] = tx_info rawtransactions[txid] = tx_info if option_blk_get_tx_inputs: for txid,tx_info in tx_infos.iteritems(): tx_input_value = 0 for txin in tx_info['vin']: if 'txid' in txin: in_txid = txin['txid'] in_tx_outidx = txin['vout'] in_tx_info = access.getrawtransaction(in_txid,1) rawtransactions[in_txid] = in_tx_info def calculate_tx_input_satoshi(txid): if not option_blk_get_txs: return None if not option_blk_get_tx_inputs: return None tx_info = tx_infos[txid] tx_total_input_value_satoshi = 0 for src_tx_entry in tx_info['vin']: if 'txid' in src_tx_entry: src_txid = src_tx_entry['txid'] src_tx_outidx = src_tx_entry['vout'] src_tx_info = rawtransactions[src_txid] tx_total_input_value_satoshi += btc_to_satoshi(src_tx_info['vout'][src_tx_outidx]['value']) return tx_total_input_value_satoshi def calculate_tx_output_satoshi(txid): if not option_blk_get_txs: return None tx_info = tx_infos[txid] tx_total_output_value = 0 for tx_output in tx_info['vout']: tx_total_output_value += btc_to_satoshi(tx_output['value']) return tx_total_output_value def is_tx_coinbase(txid): tx_info = tx_infos[txid] for tx_input in tx_info['vin']: if 'coinbase' in tx_input: return True return False def calculate_tx_fee_satoshi(txid): if not option_blk_get_txs: return None if not option_blk_get_tx_inputs: return None if is_tx_coinbase(txid): return 0 tx_total_output_value = calculate_tx_output_satoshi(txid) tx_total_input_value = calculate_tx_input_satoshi(txid) tx_fee_satoshi = tx_total_input_value - tx_total_output_value assert tx_fee_satoshi >= 0 return tx_fee_satoshi writer = response.getWriter() writer.pln('<html><head><link rel="stylesheet" href="/style.css"></head><body>') def write_top_header_bar(): writer.pln('<div class="top-header-bar">') writer.pln('<strong>Nav:</strong> <a href="/">Main Page</a>') writer.pln('<!-- end of top-header-bar -->') writer.pln('</div>') write_top_header_bar() def write_top_title_bar(): writer.pln('<div class="top-title-bar">') writer.pln('<h2>Block</h2> <h4>View information about a bitcoin block.</h4>') writer.pln('<span class="top-title-bar-button-field">') """ url_parts = urlparse.urlparse(path) query = urlparse.parse_qs(url_parts.query, True) """ fastest_detail_text = 'Fastest detail{default_comment}'.format(default_comment= (' (default)' if not config['blk_get_txs'] else '') ) some_detail_text = 'Some detail{default_comment}'.format(default_comment= (' (default)' if config['blk_get_txs'] and not config['blk_get_tx_inputs'] else '') ) most_detail_text = 'Most detail{default_comment}'.format(default_comment= (' (default)' if config['blk_get_tx_inputs'] else '') ) if not option_blk_get_txs: writer.pln(fastest_detail_text) else: writer.pln('<a href="/block?hash={hash}&blk_get_txs=0">{text}</a>'.format(hash=blk_hash,text=fastest_detail_text)) writer.pln(' | ') if option_blk_get_txs and not option_blk_get_tx_inputs: writer.pln(some_detail_text) else: writer.pln('<a href="/block?hash={hash}&blk_get_txs=1">{text}</a>'.format(hash=blk_hash,text=some_detail_text)) writer.pln(' | ') if option_blk_get_txs and option_blk_get_tx_inputs: writer.pln(most_detail_text) else: writer.pln('<a href="/block?hash={hash}&blk_get_txs=1&blk_get_tx_inputs=1">{text}</a>'.format(hash=blk_hash,text=most_detail_text)) writer.pln('</span>') writer.pln('<!-- end of top-header-bar -->') writer.pln('</div>') write_top_title_bar() writer.pln('<table class="block-hashes-table">') writer.pln('<tr><th colspan="2">Hashes</th></tr>') writer.pln('<tr>') writer.pln('<td>Hash</td>') writer.pln('<td><a href="/block?hash={hash}">{hash}</a>'.format(hash=blk_info['hash'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Previous Block</td>') writer.pln('<td><a href="/block?hash={previousblockhash}">{previousblockhash}</a></td>'.format(previousblockhash=blk_info['previousblockhash'])) writer.pln('</tr>') if 'nextblockhash' in blk_info: writer.pln('<tr>') writer.pln('<td>Next Block</td>') writer.pln('<td><a href="/block?hash={nextblockhash}">{nextblockhash}</a></td>'.format(nextblockhash=blk_info['nextblockhash'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Merkle Root</td>') writer.pln('<td>{merkleroot}</td>'.format(merkleroot=blk_info['merkleroot'])) writer.pln('</tr>') writer.pln('</table>') writer.pln('<table class="block-summary-table">') writer.pln('<tr>') writer.pln('<th colspan="2">Summary</th>') writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Number of Transactions</td>') writer.pln('<td>{transactions}</td>'.format(transactions=len(blk_info['tx']))) writer.pln('</tr>') if option_blk_get_txs: output_total_satoshi = 0 for txid in blk_info['tx']: tx_info = tx_infos[txid] for txout in tx_info['vout']: output_total_satoshi += btc_to_satoshi(txout['value']) writer.pln('<tr>') writer.pln('<td>Output Total</td>') writer.pln('<td>{output_total}</td>'.format(output_total=format_satoshi(output_total_satoshi))) writer.pln('</tr>') else: writer.pln('<tr>') writer.pln('<td>Output Total</td>') writer.pln('<td>N/A (turn on <i>blk_get_txs</i> in settings)</td>') writer.pln('</tr>') if option_blk_get_txs and option_blk_get_tx_inputs: total_fees_satoshi = 0 for txid in blk_info['tx']: tx_fee_satoshi = calculate_tx_fee_satoshi(txid) if tx_fee_satoshi != None: total_fees_satoshi += tx_fee_satoshi writer.pln('<tr>') writer.pln('<td>Transaction Fees</td>') writer.pln('<td>{tx_fees}</td>'.format(tx_fees=format_satoshi(total_fees_satoshi))) writer.pln('</tr>') else: writer.pln('<tr>') writer.pln('<td>Transaction Fees</td>') writer.pln('<td>N/A (requires options <i>blk_get_txs</i> and <i>blk_get_tx_inputs</i>)</td>') writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Height</td>') writer.pln('<td><a href="/block?height={height}">{height}</a></td>'.format(height=height)) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Timestamp</td>') writer.pln('<td>{timestamp}</td>'.format(timestamp=format_time(blk_info['time']))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Difficulty</td>') writer.pln('<td>{difficulty}</td>'.format(difficulty=blk_info['difficulty'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Bits</td>') writer.pln('<td>{bits}</td>'.format(bits=int(blk_info['bits'],16))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Size</td>') writer.pln('<td>{size}</td>'.format(size=format_bytes(blk_info['size']))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Version</td>') writer.pln('<td>{version}</td>'.format(version=blk_info['version'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Nonce</td>') writer.pln('<td>{nonce}</td>'.format(nonce=blk_info['nonce'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Block Reward</td>') writer.pln('<td>{reward}</td>'.format(reward=format_satoshi(reward_satoshi))) writer.pln('</tr>') writer.pln('</table>') writer.pln('<div class="transactions-section">') writer.pln('<h3>Transactions</h3> Transactions contained within this block.') for txid in blk_info['tx']: if not option_blk_get_txs: writer.pln('<div class="transaction-section">') writer.pln('<a href="#txid_{txid}"/>'.format(txid=txid)) writer.pln('<div class="transaction-section-header">') writer.pln('<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>'.format(txid=txid)) writer.pln('</div>') writer.pln('</div>') continue tx_info = tx_infos[txid] tx_total_output_value_satoshi = 0 for txout in tx_info['vout']: if 'value' in txout: tx_total_output_value_satoshi += btc_to_satoshi(txout['value']) tx_fee_satoshi = calculate_tx_fee_satoshi(txid) writer.pln('<div class="transaction-section">') writer.pln('<div class="transaction-section-header">') writer.pln('<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>'.format(txid=txid)) if tx_fee_satoshi is None or not(tx_fee_satoshi>0): writer.pln('<span style="float:right"><strong>(Size: {size}) {time}</strong></span>'.format(size=format_bytes(len(tx_info['hex'])/2), time=format_time(tx_info['time']))) else: writer.pln('<span style="float:right"><strong>(Fee: {fee} - Size: {size}) {time}</strong></span>'.format(fee=format_satoshi(tx_fee_satoshi), size=format_bytes(len(tx_info['hex'])/2), time=format_time(tx_info['time']))) writer.pln('</div>') def write_inputs(): writer.pln('<div class="tx-inputs">') writer.pln('<h4>Inputs</h4>') src_txids = [] for src_tx in tx_info['vin']: if 'txid' in src_tx: src_txid,src_out_index = src_tx['txid'],src_tx['vout'] src_txids.append((src_txid,src_out_index)) if len(src_txids) > 0: writer.pln('<table class="tx-inputs-table">') for src_txid,src_out_index in src_txids: writer.pln('<tr>') writer.pln('<td><a href="/transaction?txid={src_txid}">{src_txid}</a>[<a href="/transaction?txid={src_txid}&output_idx={src_out_index}#output_{src_out_index}">{src_out_index}</a>]</td>'.format(src_txid=src_txid,src_out_index=src_out_index)) if option_blk_get_tx_inputs: src_tx_info = rawtransactions[src_txid] src_output_value_satoshi = btc_to_satoshi(src_tx_info['vout'][src_out_index]['value']) writer.pln('<td>{src_output_value}</td>'.format(src_output_value=format_satoshi(src_output_value_satoshi))) writer.pln('</tr>') writer.pln('</table>') else: writer.pln('<strong>No Inputs (Newly Generated Coins)</strong>') writer.pln('</div>') write_inputs() def write_outputs(): writer.pln('<div class="tx-outputs">') writer.pln('<h4>Outputs</h4>') writer.pln('<table class="tx-outputs-table">') for txout in tx_info['vout']: writer.pln('<tr>') addresses = [] if 'scriptPubKey' in txout: if 'addresses' in txout['scriptPubKey']: for address in txout['scriptPubKey']['addresses']: addresses.append(address) writer.pln('<td>') if len(addresses) > 0: writer.pln('<ul>') for address in addresses: writer.pln('<li>{address}</li>'.format(address=address)) writer.pln('</ul>') writer.pln('</td>') writer.pln('<td>{value}</td>'.format(value=format_satoshi(btc_to_satoshi(txout['value'])))) writer.pln('</tr>') writer.pln('</table>') writer.pln('</div>') write_outputs() writer.pln('<div class="transaction-section-footer">') writer.pln('<div class="transaction-total-output">{transaction_total_output}</div>'.format(transaction_total_output=format_satoshi(tx_total_output_value_satoshi))) writer.pln('</div>') #writer.pln('<pre>') #pprint(tx_info,writer) #writer.pln('</pre>') writer.pln('<!-- end transaction-section -->') writer.pln('</div>') writer.pln('<!-- end transactions-section -->') writer.pln('</div>') writer.pln('<div class="clear"/>') htmlize_blk_info(writer,blk_info) writer.pln('</body></html>') except JSONRPCException as e: raise
def write_transaction_info(): if not option_tx_get_txs: writer.pln('<div class="transaction-section">') writer.pln( '<a id="txid_{txid}" name="txid_{txid}"/>'.format( txid=txid)) writer.pln('<div class="transaction-section-header">') writer.pln( '<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>' .format(txid=txid)) writer.pln('</div>') writer.pln('</div>') return tx_total_output_value_satoshi = 0 for txout in tx_info['vout']: if 'value' in txout: tx_total_output_value_satoshi += btc_to_satoshi( txout['value']) assert option_tx_get_txs tx_fee_satoshi = calculate_tx_fee_satoshi( tx_info, src_tx_infos) writer.pln('<div class="transaction-section">') writer.pln('<div class="transaction-section-header">') writer.pln( '<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>' .format(txid=txid)) if tx_fee_satoshi is None or not (tx_fee_satoshi > 0): writer.pln( '<span style="float:right"><strong>(Size: {size}) {time}</strong></span>' .format(size=format_bytes(len(tx_info['hex']) / 2), time=format_time(tx_info['time']))) else: writer.pln( '<span style="float:right"><strong>(Fee: {fee} - Size: {size}) {time}</strong></span>' .format(fee=format_satoshi(tx_fee_satoshi), size=format_bytes(len(tx_info['hex']) / 2), time=format_time(tx_info['time']))) writer.pln('</div>') def write_inputs(): writer.pln('<div class="tx-inputs">') writer.pln('<h4>Inputs</h4>') src_txids = [] for src_tx in tx_info['vin']: if 'txid' in src_tx: src_txid, src_out_index = src_tx['txid'], src_tx[ 'vout'] src_txids.append((src_txid, src_out_index)) if len(src_txids) > 0: writer.pln('<table class="tx-inputs-table">') for src_txid, src_out_index in src_txids: writer.pln('<tr>') writer.pln( '<td><a href="/transaction?txid={src_txid}">{src_txid}</a>[<a href="/transaction?txid={src_txid}&output_idx={src_out_index}#output_{src_out_index}">{src_out_index}</a>]</td>' .format(src_txid=src_txid, src_out_index=src_out_index)) if option_tx_get_txs: src_tx_info = src_tx_infos[src_txid] src_output_value_satoshi = btc_to_satoshi( src_tx_info['vout'][src_out_index] ['value']) writer.pln( '<td>{src_output_value}</td>'.format( src_output_value=format_satoshi( src_output_value_satoshi))) writer.pln('</tr>') writer.pln('</table>') else: writer.pln( '<strong>No Inputs (Newly Generated Coins)</strong>' ) writer.pln('</div>') write_inputs() def write_outputs(): writer.pln('<div class="tx-outputs">') writer.pln('<h4>Outputs</h4>') writer.pln('<table class="tx-outputs-table">') param_output_idx = request.getParameter('output_idx') if param_output_idx is None: param_output_idx = int(-1) param_output_idx = int(param_output_idx) for tx_output_entry_index in range(len(tx_info['vout'])): tx_output_entry = tx_info['vout'][ tx_output_entry_index] if tx_output_entry_index == param_output_idx: writer.pln( '<tr class="transaction-highlight-output-row">' ) else: writer.pln('<tr>') addresses = [] if 'scriptPubKey' in tx_output_entry: if 'addresses' in tx_output_entry['scriptPubKey']: for address in tx_output_entry['scriptPubKey'][ 'addresses']: addresses.append(address) writer.pln('<td>') writer.pln( '<a id="output_{output_idx}" name="output_{output_idx}" />' .format(output_idx=tx_output_entry_index)) if len(addresses) > 0: writer.pln('<ul>') for address in addresses: writer.pln('<li>{address}</li>'.format( address=address)) writer.pln('</ul>') writer.pln('</td>') writer.pln( '<td>{value}</td>'.format(value=format_satoshi( btc_to_satoshi(tx_output_entry['value'])))) writer.pln('</tr>') writer.pln('</table>') writer.pln('</div>') write_outputs() writer.pln('<div class="transaction-section-footer">') writer.pln( '<div class="transaction-total-output">{transaction_total_output}</div>' .format(transaction_total_output=format_satoshi( tx_total_output_value_satoshi))) writer.pln('</div>') writer.pln('<!-- end transaction-section -->') writer.pln('</div>')
def service(self, request, response): print 'BlockView' try: access = self.server.create_access() config = self.server.config def configure_options(): option_blk_get_txs = request.getParameter('blk_get_txs') option_blk_get_tx_inputs = request.getParameter( 'blk_get_tx_inputs') if option_blk_get_txs != None: if option_blk_get_txs == '1': option_blk_get_txs = True elif option_blk_get_txs == '0': option_blk_get_txs = False else: option_blk_get_txs = None if option_blk_get_tx_inputs != None: if option_blk_get_tx_inputs == '1': option_blk_get_tx_inputs = True elif option_blk_get_tx_inputs == '0': option_blk_get_tx_inputs = False else: option_blk_get_tx_inputs = None if option_blk_get_txs is None: option_blk_get_txs = config['blk_get_txs'] if option_blk_get_txs is None: option_blk_get_tx_inputs = config['blk_get_tx_inputs'] return option_blk_get_txs, option_blk_get_tx_inputs option_blk_get_txs, option_blk_get_tx_inputs = configure_options() option_blk_get_tx_inputs = option_blk_get_txs and option_blk_get_tx_inputs rawtransactions = {} blk_hash = request.getParameter('hash') if blk_hash is None: height = request.getParameter('height') if height is None: response.setContentType('text/html') writer = response.getWriter() writer.pln('Invalid block identifier') self.basehandler.send_error(404) return height = int(height) blockcount = access.getblockcount() if not (height < blockcount): response.setContentType('text/html') writer = response.getWriter() writer.pln( 'Invalid block; not yet in blockchain. blockcount: {blockcount}' .format(blockcount=blockcount)) self.basehandler.send_error(404) return blk_hash = access.getblockhash(height) blk_info = access.getblock(blk_hash) height = blk_info['height'] reward_satoshi = calc_reward_satoshi(height) response.setContentType('text/html') tx_infos = {} if option_blk_get_txs: for txid in blk_info['tx']: tx_info = access.getrawtransaction(txid, 1) tx_infos[txid] = tx_info rawtransactions[txid] = tx_info if option_blk_get_tx_inputs: for txid, tx_info in tx_infos.iteritems(): tx_input_value = 0 for txin in tx_info['vin']: if 'txid' in txin: in_txid = txin['txid'] in_tx_outidx = txin['vout'] in_tx_info = access.getrawtransaction( in_txid, 1) rawtransactions[in_txid] = in_tx_info def calculate_tx_input_satoshi(txid): if not option_blk_get_txs: return None if not option_blk_get_tx_inputs: return None tx_info = tx_infos[txid] tx_total_input_value_satoshi = 0 for src_tx_entry in tx_info['vin']: if 'txid' in src_tx_entry: src_txid = src_tx_entry['txid'] src_tx_outidx = src_tx_entry['vout'] src_tx_info = rawtransactions[src_txid] tx_total_input_value_satoshi += btc_to_satoshi( src_tx_info['vout'][src_tx_outidx]['value']) return tx_total_input_value_satoshi def calculate_tx_output_satoshi(txid): if not option_blk_get_txs: return None tx_info = tx_infos[txid] tx_total_output_value = 0 for tx_output in tx_info['vout']: tx_total_output_value += btc_to_satoshi(tx_output['value']) return tx_total_output_value def is_tx_coinbase(txid): tx_info = tx_infos[txid] for tx_input in tx_info['vin']: if 'coinbase' in tx_input: return True return False def calculate_tx_fee_satoshi(txid): if not option_blk_get_txs: return None if not option_blk_get_tx_inputs: return None if is_tx_coinbase(txid): return 0 tx_total_output_value = calculate_tx_output_satoshi(txid) tx_total_input_value = calculate_tx_input_satoshi(txid) tx_fee_satoshi = tx_total_input_value - tx_total_output_value assert tx_fee_satoshi >= 0 return tx_fee_satoshi writer = response.getWriter() writer.pln( '<html><head><link rel="stylesheet" href="/style.css"></head><body>' ) def write_top_header_bar(): writer.pln('<div class="top-header-bar">') writer.pln('<strong>Nav:</strong> <a href="/">Main Page</a>') writer.pln('<!-- end of top-header-bar -->') writer.pln('</div>') write_top_header_bar() def write_top_title_bar(): writer.pln('<div class="top-title-bar">') writer.pln( '<h2>Block</h2> <h4>View information about a bitcoin block.</h4>' ) writer.pln('<span class="top-title-bar-button-field">') """ url_parts = urlparse.urlparse(path) query = urlparse.parse_qs(url_parts.query, True) """ fastest_detail_text = 'Fastest detail{default_comment}'.format( default_comment=( ' (default)' if not config['blk_get_txs'] else '')) some_detail_text = 'Some detail{default_comment}'.format( default_comment=(' (default)' if config['blk_get_txs'] and not config['blk_get_tx_inputs'] else '')) most_detail_text = 'Most detail{default_comment}'.format( default_comment=( ' (default)' if config['blk_get_tx_inputs'] else '')) if not option_blk_get_txs: writer.pln(fastest_detail_text) else: writer.pln( '<a href="/block?hash={hash}&blk_get_txs=0">{text}</a>' .format(hash=blk_hash, text=fastest_detail_text)) writer.pln(' | ') if option_blk_get_txs and not option_blk_get_tx_inputs: writer.pln(some_detail_text) else: writer.pln( '<a href="/block?hash={hash}&blk_get_txs=1">{text}</a>' .format(hash=blk_hash, text=some_detail_text)) writer.pln(' | ') if option_blk_get_txs and option_blk_get_tx_inputs: writer.pln(most_detail_text) else: writer.pln( '<a href="/block?hash={hash}&blk_get_txs=1&blk_get_tx_inputs=1">{text}</a>' .format(hash=blk_hash, text=most_detail_text)) writer.pln('</span>') writer.pln('<!-- end of top-header-bar -->') writer.pln('</div>') write_top_title_bar() writer.pln('<table class="block-hashes-table">') writer.pln('<tr><th colspan="2">Hashes</th></tr>') writer.pln('<tr>') writer.pln('<td>Hash</td>') writer.pln('<td><a href="/block?hash={hash}">{hash}</a>'.format( hash=blk_info['hash'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Previous Block</td>') writer.pln( '<td><a href="/block?hash={previousblockhash}">{previousblockhash}</a></td>' .format(previousblockhash=blk_info['previousblockhash'])) writer.pln('</tr>') if 'nextblockhash' in blk_info: writer.pln('<tr>') writer.pln('<td>Next Block</td>') writer.pln( '<td><a href="/block?hash={nextblockhash}">{nextblockhash}</a></td>' .format(nextblockhash=blk_info['nextblockhash'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Merkle Root</td>') writer.pln('<td>{merkleroot}</td>'.format( merkleroot=blk_info['merkleroot'])) writer.pln('</tr>') writer.pln('</table>') writer.pln('<table class="block-summary-table">') writer.pln('<tr>') writer.pln('<th colspan="2">Summary</th>') writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Number of Transactions</td>') writer.pln('<td>{transactions}</td>'.format( transactions=len(blk_info['tx']))) writer.pln('</tr>') if option_blk_get_txs: output_total_satoshi = 0 for txid in blk_info['tx']: tx_info = tx_infos[txid] for txout in tx_info['vout']: output_total_satoshi += btc_to_satoshi(txout['value']) writer.pln('<tr>') writer.pln('<td>Output Total</td>') writer.pln('<td>{output_total}</td>'.format( output_total=format_satoshi(output_total_satoshi))) writer.pln('</tr>') else: writer.pln('<tr>') writer.pln('<td>Output Total</td>') writer.pln( '<td>N/A (turn on <i>blk_get_txs</i> in settings)</td>') writer.pln('</tr>') if option_blk_get_txs and option_blk_get_tx_inputs: total_fees_satoshi = 0 for txid in blk_info['tx']: tx_fee_satoshi = calculate_tx_fee_satoshi(txid) if tx_fee_satoshi != None: total_fees_satoshi += tx_fee_satoshi writer.pln('<tr>') writer.pln('<td>Transaction Fees</td>') writer.pln('<td>{tx_fees}</td>'.format( tx_fees=format_satoshi(total_fees_satoshi))) writer.pln('</tr>') else: writer.pln('<tr>') writer.pln('<td>Transaction Fees</td>') writer.pln( '<td>N/A (requires options <i>blk_get_txs</i> and <i>blk_get_tx_inputs</i>)</td>' ) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Height</td>') writer.pln( '<td><a href="/block?height={height}">{height}</a></td>'. format(height=height)) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Timestamp</td>') writer.pln('<td>{timestamp}</td>'.format( timestamp=format_time(blk_info['time']))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Difficulty</td>') writer.pln('<td>{difficulty}</td>'.format( difficulty=blk_info['difficulty'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Bits</td>') writer.pln( '<td>{bits}</td>'.format(bits=int(blk_info['bits'], 16))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Size</td>') writer.pln( '<td>{size}</td>'.format(size=format_bytes(blk_info['size']))) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Version</td>') writer.pln( '<td>{version}</td>'.format(version=blk_info['version'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Nonce</td>') writer.pln('<td>{nonce}</td>'.format(nonce=blk_info['nonce'])) writer.pln('</tr>') writer.pln('<tr>') writer.pln('<td>Block Reward</td>') writer.pln('<td>{reward}</td>'.format( reward=format_satoshi(reward_satoshi))) writer.pln('</tr>') writer.pln('</table>') writer.pln('<div class="transactions-section">') writer.pln( '<h3>Transactions</h3> Transactions contained within this block.' ) for txid in blk_info['tx']: if not option_blk_get_txs: writer.pln('<div class="transaction-section">') writer.pln('<a href="#txid_{txid}"/>'.format(txid=txid)) writer.pln('<div class="transaction-section-header">') writer.pln( '<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>' .format(txid=txid)) writer.pln('</div>') writer.pln('</div>') continue tx_info = tx_infos[txid] tx_total_output_value_satoshi = 0 for txout in tx_info['vout']: if 'value' in txout: tx_total_output_value_satoshi += btc_to_satoshi( txout['value']) tx_fee_satoshi = calculate_tx_fee_satoshi(txid) writer.pln('<div class="transaction-section">') writer.pln('<div class="transaction-section-header">') writer.pln( '<span style=""><a href="/transaction?txid={txid}">{txid}</a></span>' .format(txid=txid)) if tx_fee_satoshi is None or not (tx_fee_satoshi > 0): writer.pln( '<span style="float:right"><strong>(Size: {size}) {time}</strong></span>' .format(size=format_bytes(len(tx_info['hex']) / 2), time=format_time(tx_info['time']))) else: writer.pln( '<span style="float:right"><strong>(Fee: {fee} - Size: {size}) {time}</strong></span>' .format(fee=format_satoshi(tx_fee_satoshi), size=format_bytes(len(tx_info['hex']) / 2), time=format_time(tx_info['time']))) writer.pln('</div>') def write_inputs(): writer.pln('<div class="tx-inputs">') writer.pln('<h4>Inputs</h4>') src_txids = [] for src_tx in tx_info['vin']: if 'txid' in src_tx: src_txid, src_out_index = src_tx['txid'], src_tx[ 'vout'] src_txids.append((src_txid, src_out_index)) if len(src_txids) > 0: writer.pln('<table class="tx-inputs-table">') for src_txid, src_out_index in src_txids: writer.pln('<tr>') writer.pln( '<td><a href="/transaction?txid={src_txid}">{src_txid}</a>[<a href="/transaction?txid={src_txid}&output_idx={src_out_index}#output_{src_out_index}">{src_out_index}</a>]</td>' .format(src_txid=src_txid, src_out_index=src_out_index)) if option_blk_get_tx_inputs: src_tx_info = rawtransactions[src_txid] src_output_value_satoshi = btc_to_satoshi( src_tx_info['vout'][src_out_index] ['value']) writer.pln( '<td>{src_output_value}</td>'.format( src_output_value=format_satoshi( src_output_value_satoshi))) writer.pln('</tr>') writer.pln('</table>') else: writer.pln( '<strong>No Inputs (Newly Generated Coins)</strong>' ) writer.pln('</div>') write_inputs() def write_outputs(): writer.pln('<div class="tx-outputs">') writer.pln('<h4>Outputs</h4>') writer.pln('<table class="tx-outputs-table">') for txout in tx_info['vout']: writer.pln('<tr>') addresses = [] if 'scriptPubKey' in txout: if 'addresses' in txout['scriptPubKey']: for address in txout['scriptPubKey'][ 'addresses']: addresses.append(address) writer.pln('<td>') if len(addresses) > 0: writer.pln('<ul>') for address in addresses: writer.pln('<li>{address}</li>'.format( address=address)) writer.pln('</ul>') writer.pln('</td>') writer.pln( '<td>{value}</td>'.format(value=format_satoshi( btc_to_satoshi(txout['value'])))) writer.pln('</tr>') writer.pln('</table>') writer.pln('</div>') write_outputs() writer.pln('<div class="transaction-section-footer">') writer.pln( '<div class="transaction-total-output">{transaction_total_output}</div>' .format(transaction_total_output=format_satoshi( tx_total_output_value_satoshi))) writer.pln('</div>') #writer.pln('<pre>') #pprint(tx_info,writer) #writer.pln('</pre>') writer.pln('<!-- end transaction-section -->') writer.pln('</div>') writer.pln('<!-- end transactions-section -->') writer.pln('</div>') writer.pln('<div class="clear"/>') htmlize_blk_info(writer, blk_info) writer.pln('</body></html>') except JSONRPCException as e: raise