Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251x=space_above,252y=1,253height=box_win_height,254width=box_win_width,255title="Event log",256)257# actual logging window258log_lines = box_win_height - 2 # top and bottom box lines259log_line_len = box_win_width - 2 - 1 # box lines and left padding260win = win_box.derwin(log_lines, log_line_len, 1, 2)261win.idlok(True)262win.scrollok(True)263win_box.refresh()264win.refresh()265self._event_log_win_box = win_box266self._event_log_win = win268def calculate_metrics(self, events):269"""Calculate count and rate metrics."""270count, rate = {}, {}271for event_ts, event_type, event_data in events:272self._timestamps[event_type].append(event_ts)273for event_type, ts in self._timestamps.items():274# remove timestamps older than ten minutes but keep track of their275# count for the 'total' metric276#277self._event_history[event_type] += len(278[t for t in ts if Dashboard.timestamp_age(t) >= 600]279)280ts = [t for t in ts if Dashboard.timestamp_age(t) < 600]281self._timestamps[event_type] = ts282# count metric283count_1m = len([t for t in ts if Dashboard.timestamp_age(t) < 60])284count_10m = len(ts)285count_total = self._event_history[event_type] + len(ts)286count[event_type] = (count_total, count_1m, count_10m)287# rate metric288runtime = Dashboard.timestamp_age(self._time_started)289rate_1m = count_1m / min(60, runtime)290rate_10m = count_10m / min(600, runtime)291rate_total = count_total / runtime292rate[event_type] = (rate_total, rate_1m, rate_10m)293return count, rate295def _update_event_count(self, count):296"""Update the event count window."""297w = self._event_count_win298row_format = " {:<8} {:>6}tx {:>5}tx {:>5}tx "299for line, metric in enumerate(["added", "removed", "replaced", "rejected"]):300w.addstr(2 + line, 1, row_format.format(metric, *count[metric]))301w.refresh()303def _update_event_rate(self, rate):304"""Update the event rate window."""305w = self._event_rate_win306row_format = " {:<8} {:>5.1f}tx/s {:>5.1f}tx/s {:>5.1f}tx/s "307for line, metric in enumerate(["added", "removed", "replaced", "rejected"]):308w.addstr(2 + line, 1, row_format.format(metric, *rate[metric]))309w.refresh()311def _update_event_log(self, events):312"""Update the event log window."""313w = self._event_log_win314for event in events:315w.addstr(Dashboard.parse_event(event) + "\n")316w.refresh()318def render(self, events):319"""Render the dashboard."""320count, rate = self.calculate_metrics(events)321self._update_event_count(count)322self._update_event_rate(rate)323self._update_event_log(events)324events.clear()326@staticmethod327def parse_event(event):328"""Converts events into human-readable messages"""330ts_dt, type_, data = event331ts = ts_dt.strftime("%H:%M:%SZ")332if type_ == "added":333return (334f"{ts} added {bytes(data.hash)[::-1].hex()}"335f" with feerate {data.fee/data.vsize:.2f} sat/vB"336f" ({data.fee} sat, {data.vsize} vbytes)"337)339if type_ == "removed":340return (341f"{ts} removed {bytes(data.hash)[::-1].hex()}"342f" with feerate {data.fee/data.vsize:.2f} sat/vB"343f" ({data.fee} sat, {data.vsize} vbytes)"344f" received {ts_dt.timestamp()-data.entry_time:.1f} seconds ago"345f": {data.reason.decode('UTF-8')}"346)348if type_ == "rejected":349return (350f"{ts} rejected {bytes(data.hash)[::-1].hex()}"351f": {data.reason.decode('UTF-8')}"352)354if type_ == "replaced":355return (356f"{ts} replaced {bytes(data.replaced_hash)[::-1].hex()}"357f" with feerate {data.replaced_fee/data.replaced_vsize:.2f} sat/vB"358f" received {ts_dt.timestamp()-data.replaced_entry_time:.1f} seconds ago"359f" ({data.replaced_fee} sat, {data.replaced_vsize} vbytes)"360f" with {bytes(data.replacement_hash)[::-1].hex()}"361f" with feerate {data.replacement_fee/data.replacement_vsize:.2f} sat/vB"362f" ({data.replacement_fee} sat, {data.replacement_vsize} vbytes)"363)365raise NotImplementedError("Unsupported event type: {type_}")367@staticmethod368def timestamp_age(timestamp):369"""Return age of timestamp in seconds."""370return (datetime.now(timezone.utc) - timestamp).total_seconds()373if __name__ == "__main__":374if len(sys.argv) < 2:375print("USAGE: ", sys.argv[0], "<pid of bitcoind>")376exit(1)378pid = sys.argv[1]379main(pid)
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.