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.
501if nobinaries:502remove_str = ', '.join(i[1] for i in nobinaries)503log.info(504f"removing *{fragment} binaries ({remove_str}) from verification "505f"since {HOST1} does not host *{fragment} binaries")506hashes_to_verify = [i for i in hashes_to_verify if fragment not in i[1]]508# download binaries509for _, binary_filename in hashes_to_verify:510log.info(f"downloading {binary_filename} to {WORKINGDIR}")511success, output = download_with_wget(512HOST1 + remote_dir + binary_filename, binary_filename)514if not success:515log.error(516f"failed to download {binary_filename}\n"517f"wget output:\n{indent(output)}")518return ReturnCode.BINARY_DOWNLOAD_FAILED520# verify hashes521hashes_status, files_to_hashes = verify_binary_hashes(hashes_to_verify)522if hashes_status != ReturnCode.SUCCESS:523return hashes_status526if args.cleanup:527cleanup()528else:529log.info(f"did not clean up {WORKINGDIR}")531if args.json:532output = {533'good_trusted_sigs': [str(s) for s in good_trusted],534'good_untrusted_sigs': [str(s) for s in good_untrusted],535'unknown_sigs': [str(s) for s in unknown],536'bad_sigs': [str(s) for s in bad],537'verified_binaries': files_to_hashes,538}539print(json.dumps(output, indent=2))540else:541for filename in files_to_hashes:542print(f"VERIFIED: {filename}")544return ReturnCode.SUCCESS547def verify_binaries_handler(args: argparse.Namespace) -> ReturnCode:548binary_to_basename = {}549for file in args.binary:550binary_to_basename[PurePath(file).name] = file552sums_sig_path = None553if args.sums_sig_file:554sums_sig_path = Path(args.sums_sig_file)555else:556log.info(f"No signature file specified, assuming it is {args.sums_file}.asc")557sums_sig_path = Path(args.sums_file).with_suffix(".asc")559# Verify the signature on the SHA256SUMS file560sigs_status, good_trusted, good_untrusted, unknown, bad = verify_shasums_signature(str(sums_sig_path), args.sums_file, args)561if sigs_status != ReturnCode.SUCCESS:562return sigs_status564# Extract hashes and filenames565hashes_to_verify = parse_sums_file(args.sums_file, [k for k, n in binary_to_basename.items()])566if not hashes_to_verify:567log.error(f"No files in {args.sums_file} match the specified binaries")568return ReturnCode.NO_BINARIES_MATCH570# Make sure all files are accounted for571sums_file_path = Path(args.sums_file)572missing_files = []573files_to_hash = []574if len(binary_to_basename) > 0:575for file_hash, file in hashes_to_verify:576files_to_hash.append([file_hash, binary_to_basename[file]])577del binary_to_basename[file]578if len(binary_to_basename) > 0:579log.error(f"Not all specified binaries are in {args.sums_file}")580return ReturnCode.NO_BINARIES_MATCH581else:582log.info(f"No binaries specified, assuming all files specified in {args.sums_file} are located relatively")583for file_hash, file in hashes_to_verify:584file_path = Path(sums_file_path.parent.joinpath(file))585if file_path.exists():586files_to_hash.append([file_hash, str(file_path)])587else:588missing_files.append(file)590# verify hashes591hashes_status, files_to_hashes = verify_binary_hashes(files_to_hash)592if hashes_status != ReturnCode.SUCCESS:593return hashes_status595if args.json:596output = {597'good_trusted_sigs': [str(s) for s in good_trusted],598'good_untrusted_sigs': [str(s) for s in good_untrusted],599'unknown_sigs': [str(s) for s in unknown],600'bad_sigs': [str(s) for s in bad],601'verified_binaries': files_to_hashes,602"missing_binaries": missing_files,603}604print(json.dumps(output, indent=2))605else:606for filename in files_to_hashes:607print(f"VERIFIED: {filename}")608for filename in missing_files:609print(f"MISSING: {filename}")611return ReturnCode.SUCCESS614def main():615parser = argparse.ArgumentParser(description=__doc__)616parser.add_argument(617'-v', '--verbose', action='store_true',618default=bool_from_env('BINVERIFY_VERBOSE'),619)620parser.add_argument(621'-q', '--quiet', action='store_true',622default=bool_from_env('BINVERIFY_QUIET'),623)624parser.add_argument(625'--import-keys', action='store_true',626default=bool_from_env('BINVERIFY_IMPORTKEYS'),627help='if specified, ask to import each unknown builder key'628)629parser.add_argument(630'--min-good-sigs', type=int, action='store', nargs='?',631default=int(os.environ.get('BINVERIFY_MIN_GOOD_SIGS', 3)),632help=(633'The minimum number of good signatures to require successful termination.'),634)635parser.add_argument(636'--keyserver', action='store', nargs='?',637default=os.environ.get('BINVERIFY_KEYSERVER', 'hkps://keys.openpgp.org'),638help='which keyserver to use',639)640parser.add_argument(641'--trusted-keys', action='store', nargs='?',642default=os.environ.get('BINVERIFY_TRUSTED_KEYS', ''),643help='A list of trusted signer GPG keys, separated by commas. Not "trusted keys" in the GPG sense.',644)645parser.add_argument(646'--json', action='store_true',647default=bool_from_env('BINVERIFY_JSON'),648help='If set, output the result as JSON',649)651subparsers = parser.add_subparsers(title="Commands", required=True, dest="command")653pub_parser = subparsers.add_parser("pub", help="Verify a published release.")654pub_parser.set_defaults(func=verify_published_handler)655pub_parser.add_argument(656'version', type=str, help=(657f'version of the bitcoin release to download; of the format '658f'{VERSION_FORMAT}. Example: {VERSION_EXAMPLE}')659)660pub_parser.add_argument(661'--cleanup', action='store_true',662default=bool_from_env('BINVERIFY_CLEANUP'),663help='if specified, clean up files afterwards'664)665pub_parser.add_argument(666'--require-all-hosts', action='store_true',667default=bool_from_env('BINVERIFY_REQUIRE_ALL_HOSTS'),668help=(669f'If set, require all hosts ({HOST1}, {HOST2}) to provide signatures. '670'(Sometimes bitcoin.org lags behind bitcoincore.org.)')671)673bin_parser = subparsers.add_parser("bin", help="Verify local binaries.")674bin_parser.set_defaults(func=verify_binaries_handler)675bin_parser.add_argument("--sums-sig-file", "-s", help="Path to the SHA256SUMS.asc file to verify")676bin_parser.add_argument("sums_file", help="Path to the SHA256SUMS file to verify")677bin_parser.add_argument(678"binary", nargs="*",679help="Path to a binary distribution file to verify. Can be specified multiple times for multiple files to verify."680)682args = parser.parse_args()683if args.quiet:684log.setLevel(logging.WARNING)686return args.func(args)689if __name__ == '__main__':690sys.exit(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.