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.
1#!/usr/bin/env python32# Copyright (c) 2022-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.6""" Tests the validation:* tracepoint API interface.7See https://github.com/bitcoin/bitcoin/blob/master/doc/tracing.md#context-validation8"""10import ctypes11import time13# Test will be skipped if we don't have bcc installed14try:15from bcc import BPF, USDT # type: ignore[import]16except ImportError:17pass19from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE20from test_framework.test_framework import BitcoinTestFramework21from test_framework.util import (22assert_equal,23bpf_cflags,24)26validation_blockconnected_program = """27#include <uapi/linux/ptrace.h>29typedef signed long long i64;31struct connected_block32{33char hash[32];34int height;35i64 transactions;36int inputs;37i64 sigops;38u64 duration;39};41BPF_PERF_OUTPUT(block_connected);42int trace_block_connected(struct pt_regs *ctx) {43struct connected_block block = {};44void *phash = NULL;45bpf_usdt_readarg(1, ctx, &phash);46bpf_probe_read_user(&block.hash, sizeof(block.hash), phash);47bpf_usdt_readarg(2, ctx, &block.height);48bpf_usdt_readarg(3, ctx, &block.transactions);49bpf_usdt_readarg(4, ctx, &block.inputs);50bpf_usdt_readarg(5, ctx, &block.sigops);51bpf_usdt_readarg(6, ctx, &block.duration);52block_connected.perf_submit(ctx, &block, sizeof(block));53return 0;54}55"""58class ValidationTracepointTest(BitcoinTestFramework):59def set_test_params(self):60self.num_nodes = 162def skip_test_if_missing_module(self):63self.skip_if_platform_not_linux()64self.skip_if_no_bitcoind_tracepoints()65self.skip_if_no_python_bcc()66self.skip_if_no_bpf_permissions()67self.skip_if_running_under_valgrind()69def run_test(self):70# Tests the validation:block_connected tracepoint by generating blocks71# and comparing the values passed in the tracepoint arguments with the72# blocks.73# See https://github.com/bitcoin/bitcoin/blob/master/doc/tracing.md#tracepoint-validationblock_connected75class Block(ctypes.Structure):76_fields_ = [77("hash", ctypes.c_ubyte * 32),78("height", ctypes.c_int),79("transactions", ctypes.c_int64),80("inputs", ctypes.c_int),81("sigops", ctypes.c_int64),82("duration", ctypes.c_uint64),83]85def __repr__(self):86return "ConnectedBlock(hash=%s height=%d, transactions=%d, inputs=%d, sigops=%d, duration=%d)" % (87bytes(self.hash[::-1]).hex(),88self.height,89self.transactions,90self.inputs,91self.sigops,92self.duration)94BLOCKS_EXPECTED = 295expected_blocks = dict()96events = []98self.log.info("hook into the validation:block_connected tracepoint")99ctx = USDT(pid=self.nodes[0].process.pid)100ctx.enable_probe(probe="validation:block_connected",101fn_name="trace_block_connected")102bpf = BPF(text=validation_blockconnected_program,103usdt_contexts=[ctx], debug=0, cflags=bpf_cflags())105def handle_blockconnected(_, data, __):106event = ctypes.cast(data, ctypes.POINTER(Block)).contents107self.log.info(f"handle_blockconnected(): {event}")108events.append(event)110bpf["block_connected"].open_perf_buffer(111handle_blockconnected)113self.log.info(f"mine {BLOCKS_EXPECTED} blocks")114generatetoaddress_duration = dict()115for _ in range(BLOCKS_EXPECTED):116start = time.time()117hash = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE)[0]118generatetoaddress_duration[hash] = (time.time() - start) * 1e9 # in nanoseconds119expected_blocks[hash] = self.nodes[0].getblock(hash, 2)121bpf.perf_buffer_poll(timeout=200)123self.log.info(f"check that we correctly traced {BLOCKS_EXPECTED} blocks")124for event in events:125block_hash = bytes(event.hash[::-1]).hex()126block = expected_blocks[block_hash]127assert_equal(block["hash"], block_hash)128assert_equal(block["height"], event.height)129assert_equal(len(block["tx"]), event.transactions)130assert_equal(len([tx["vin"] for tx in block["tx"]]), event.inputs)131assert_equal(0, event.sigops) # no sigops in coinbase tx132# only plausibility checks133assert event.duration > 0134# generatetoaddress (mining and connecting) takes longer than135# connecting the block. In case the duration unit is off, we'll136# detect it with this assert.137assert event.duration < generatetoaddress_duration[block_hash]138del expected_blocks[block_hash]139assert_equal(BLOCKS_EXPECTED, len(events))140assert_equal(0, len(expected_blocks))142bpf.cleanup()145if __name__ == '__main__':146ValidationTracepointTest(__file__).main()
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.