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.
251raise RuntimeError("JSON encode/decode loses precision")254class Binaries:255"""Helper class to provide information about bitcoin binaries257Attributes:258paths: Object returned from get_binary_paths() containing information259which binaries and command lines to use from environment variables and260the config file.261bin_dir: An optional string containing a directory path to look for262binaries, which takes precedence over the paths above, if specified.263This is used by tests calling binaries from previous releases.264"""265def __init__(self, paths, bin_dir, *, use_valgrind=False):266self.paths = paths267self.bin_dir = bin_dir268suppressions_file = pathlib.Path(__file__).resolve().parents[3] / "test" / "sanitizer_suppressions" / "valgrind.supp"269self.valgrind_cmd = [270"valgrind",271f"--suppressions={suppressions_file}",272"--gen-suppressions=all",273"--trace-children=yes", # Needed for 'bitcoin' wrapper274"--exit-on-first-error=yes",275"--error-exitcode=1",276"--quiet",277] if use_valgrind else []279def node_argv(self, **kwargs):280"Return argv array that should be used to invoke bitcoind"281return self._argv("node", self.paths.bitcoind, **kwargs)283def rpc_argv(self):284"Return argv array that should be used to invoke bitcoin-cli"285# Add -nonamed because "bitcoin rpc" enables -named by default, but bitcoin-cli doesn't286return self._argv("rpc", self.paths.bitcoincli) + ["-nonamed"]288def bench_argv(self):289"Return argv array that should be used to invoke bench_bitcoin"290return self._argv("bench", self.paths.bitcoin_bench)292def tx_argv(self):293"Return argv array that should be used to invoke bitcoin-tx"294return self._argv("tx", self.paths.bitcointx)296def util_argv(self):297"Return argv array that should be used to invoke bitcoin-util"298return self._argv("util", self.paths.bitcoinutil)300def wallet_argv(self):301"Return argv array that should be used to invoke bitcoin-wallet"302return self._argv("wallet", self.paths.bitcoinwallet)304def chainstate_argv(self):305"Return argv array that should be used to invoke bitcoin-chainstate"306return self._argv("chainstate", self.paths.bitcoinchainstate)308def _argv(self, command, bin_path, *, need_ipc=False, use_gui=False):309"""Return argv array that should be used to invoke the command.311It either uses the bitcoin wrapper executable (if BITCOIN_CMD, need_ipc,312or use_gui are set), or the direct binary path (bitcoind, etc). When313bin_dir is set (by tests calling binaries from previous releases) it314always uses the direct path.316The returned args include valgrind, except when bin_dir is set317(previous releases). Also, valgrind will only apply to the bitcoin318wrapper executable directly, not to the commands that `bitcoin` calls.319"""320if self.bin_dir is not None:321return [os.path.join(self.bin_dir, os.path.basename(bin_path))]322elif self.paths.bitcoin_cmd is not None or need_ipc or use_gui:323# If the current test needs IPC or GUI functionality, use the324# bitcoin wrapper binary and add appropriate options.325bitcoin_cmd = self.paths.bitcoin_cmd or [self.paths.bitcoin_bin]326subcommand = "gui" if use_gui and command == "node" else command327return self.valgrind_cmd + bitcoin_cmd + (["-m"] if need_ipc else []) + [subcommand]328else:329return self.valgrind_cmd + [bin_path]332def get_binary_paths(config):333"""Get paths of all binaries from environment variables or their default values"""335paths = types.SimpleNamespace()336binaries = {337"bitcoin": "BITCOIN_BIN",338"bitcoind": "BITCOIND",339"bench_bitcoin": "BITCOIN_BENCH",340"bitcoin-cli": "BITCOINCLI",341"bitcoin-util": "BITCOINUTIL",342"bitcoin-tx": "BITCOINTX",343"bitcoin-chainstate": "BITCOINCHAINSTATE",344"bitcoin-wallet": "BITCOINWALLET",345}346# Set paths to bitcoin core binaries allowing overrides with environment347# variables.348for binary, env_variable_name in binaries.items():349default_filename = os.path.join(350config["environment"]["BUILDDIR"],351"bin",352binary + config["environment"]["EXEEXT"],353)354setattr(paths, env_variable_name.lower(), os.getenv(env_variable_name, default=default_filename))355# BITCOIN_CMD environment variable can be specified to invoke bitcoin356# wrapper binary instead of other executables.357paths.bitcoin_cmd = shlex.split(os.getenv("BITCOIN_CMD", "")) or None358return paths361def export_env_build_path(config):362os.environ["PATH"] = os.pathsep.join([363os.path.join(config["environment"]["BUILDDIR"], "bin"),364os.environ["PATH"],365])368def count_bytes(hex_string):369return len(bytearray.fromhex(hex_string))372def str_to_b64str(string):373return b64encode(string.encode('utf-8')).decode('ascii')376def ceildiv(a, b):377"""378Divide 2 ints and round up to next int rather than round down379Implementation requires python integers, which have a // operator that does floor division.380Other types like decimal.Decimal whose // operator truncates towards 0 will not work.381"""382assert isinstance(a, int)383assert isinstance(b, int)384return -(-a // b)387def random_bitflip(data):388data = list(data)389data[random.randrange(len(data))] ^= (1 << (random.randrange(8)))390return bytes(data)393def get_fee(tx_size, feerate_btc_kvb):394"""Calculate the fee in BTC given a feerate is BTC/kvB. Reflects CFeeRate::GetFee"""395feerate_sat_kvb = int(feerate_btc_kvb * Decimal(1e8)) # Fee in sat/kvb as an int to avoid float precision errors396target_fee_sat = ceildiv(feerate_sat_kvb * tx_size, 1000) # Round calculated fee up to nearest sat397return target_fee_sat / Decimal(1e8) # Return result in BTC400def satoshi_round(amount: Union[int, float, str], *, rounding: str) -> Decimal:401"""Rounds a Decimal amount to the nearest satoshi using the specified rounding mode."""402return Decimal(amount).quantize(SATOSHI_PRECISION, rounding=rounding)405def ensure_for(*, duration, f, check_interval=0.2):406"""Check if the predicate keeps returning True for duration.408check_interval can be used to configure the wait time between checks.409Setting check_interval to 0 will allow to have two checks: one in the410beginning and one after duration.411"""412# If check_interval is 0 or negative or larger than duration, we fall back413# to checking once in the beginning and once at the end of duration414if check_interval <= 0 or check_interval > duration:415check_interval = duration416time_end = time.time() + duration417predicate_source = "''''\n" + inspect.getsource(f) + "'''"418while True:419if not f():420raise AssertionError(f"Predicate {predicate_source} became false within {duration} seconds")421if time.time() > time_end:422return423time.sleep(check_interval)426def wait_until_helper_internal(predicate, *, timeout=60, lock=None, timeout_factor=1.0, check_interval=0.05):427"""Sleep until the predicate resolves to be True.429Warning: Note that this method is not recommended to be used in tests as it is430not aware of the context of the test framework. Using the `wait_until()` members431from `BitcoinTestFramework` or `P2PInterface` class ensures the timeout is432properly scaled. Furthermore, `wait_until()` from `P2PInterface` class in433`p2p.py` has a preset lock.434"""435timeout = timeout * timeout_factor436time_end = time.time() + timeout438while time.time() < time_end:439if lock:440with lock:441if predicate():442return443else:444if predicate():445return446time.sleep(check_interval)448# Print the cause of the timeout449predicate_source = "''''\n" + inspect.getsource(predicate) + "'''"450logger.error("wait_until() failed. Predicate: {}".format(predicate_source))451raise AssertionError("Predicate {} not true after {} seconds".format(predicate_source, timeout))454def bpf_cflags():455return [456"-Wno-error=implicit-function-declaration",457"-Wno-duplicate-decl-specifier", # https://github.com/bitcoin/bitcoin/issues/32322458]461def sha256sum_file(filename):462h = hashlib.sha256()463with open(filename, 'rb') as f:464d = f.read(4096)465while len(d) > 0:466h.update(d)467d = f.read(4096)468return h.digest()471def util_xor(data, key, *, offset):472data = bytearray(data)473for i in range(len(data)):474data[i] ^= key[(i + offset) % len(key)]475return bytes(data)478# RPC/P2P connection constants and functions479############################################481# The maximum number of nodes a single test can spawn482MAX_NODES = 12483# Don't assign p2p, rpc or tor ports lower than this484PORT_MIN = int(os.getenv('TEST_RUNNER_PORT_MIN', default=11000))485# The number of ports to "reserve" for p2p, rpc and tor, each486PORT_RANGE = 5000489class PortSeed:490# Must be initialized with a unique integer for each process491n = None493def p2p_port(n):494assert n <= MAX_NODES495return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)498def rpc_port(n):499return p2p_port(n) + PORT_RANGE
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.