From 67e0422ca032d12ed3a41a33d502756e3d9b4cc9 Mon Sep 17 00:00:00 2001 From: stringintech Date: Sun, 1 Feb 2026 16:43:40 +0330 Subject: [PATCH 1/2] Squashed 'depend/bitcoin/' changes from eb0594e23f..891030ac8b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 891030ac8b Merge bitcoin/bitcoin#33822: kernel: Add block header support and validation 0871e104a2 Merge bitcoin/bitcoin#34242: Prepare string and net utils for future HTTP operations 1b079becf1 Merge bitcoin/bitcoin#34317: fuzz: Exclude too expensive inputs in descriptor_parse targets cdb42a8df8 Merge bitcoin/bitcoin#34380: test: Fix P2PK script test 7b48b09b7f Merge bitcoin/bitcoin#34376: bench/test: clarify merkle bench and witness test intent fab2f3df4b fuzz: Exclude too expensive inputs in descriptor_parse targets 1911db8c6d string: add LineReader ee62405cce time: implement and test RFC1123 timestamp string eea38787b9 string: add AsciiCaseInsensitive{KeyEqual, Hash} for unordered map 1d8cb78d5b Merge bitcoin/bitcoin#34309: guix: stop passing depends sources to codesigning 4e300df712 string: add `base` argument for ToIntegral to operate on hexadecimal 0b0d9125c1 Modernize GetBindAddress() 7041648ee5 Merge bitcoin/bitcoin#34375: doc: mempool: fix `removeUnchecked` incorrect comment 9a9d797ef6 kernel: Add support for block headers 1137debb85 doc: mempool: fix `removeUnchecked` incorrect comment c9ce1c7c4a test: Fix P2PK script test 691dc830c6 Merge bitcoin/bitcoin#34377: test: Rename wallet in restore attempt in wallet_assumeutxo d7fd8c6952 Merge bitcoin/bitcoin#34090: net: Fix `-Wmissing-braces` 1fbbdd20cd Merge bitcoin/bitcoin#34355: doc: Fix wrong code in WITH_LOCK doxygen comment 9016858282 Merge bitcoin/bitcoin#34297: p2p: add validation checks for initial self-announcement e1dc4afeeb test: Rename wallet name in restore attempt in wallet_assumeutxo 8b9d30e3fa bench/test: clarify merkle bench and witness test intent 5715748333 Merge bitcoin/bitcoin#34366: test: switch order of error code and message check 2a1234001c Merge bitcoin/bitcoin#34269: wallet: disallow creating new or restoring to an unnamed (default) wallet 3ea2b6fe18 Merge bitcoin/bitcoin#34369: test: Scale NetworkThread close timeout with timeout_factor fab055c907 test: Scale NetworkThread close timeout with timeout_factor e324925d19 Merge bitcoin/bitcoin#34363: Update libmultiprocess subtree to avoid occasional rpc_misc.py timeout fa267551c4 Merge bitcoin/bitcoin#34353: refactor: Use std::bind_front over std::bind b851ff6cae kernel: Add Handle/View pattern for BlockValidationState fa61fadad1 doc: Fix wrong code in WITH_LOCK doxygen comment 52096de212 Merge bitcoin/bitcoin#34032: util: Add some more Unexpected and Expected methods 0aba464ce7 test: switch order of error code and message check 8c07800b19 Merge bitcoin/bitcoin#32497: merkle: pre‑reserve leaves to prevent reallocs with odd vtx count a365c9fe1f Merge bitcoin/bitcoin#33738: log: avoid collecting `GetSerializeSize` data when compact block logging is disabled bc3c4cd8b2 Merge bitcoin/bitcoin#32724: Musig2 tests f7e88e298a Merge bitcoin/bitcoin#32471: wallet/rpc: fix listdescriptors RPC fails to return descriptors with private key information when wallet contains descriptors missing any key 7f5ebef56a Merge bitcoin/bitcoin#34302: fuzz: Restore SendMessages coverage in process_message(s) fuzz targets a6e8cd306e Merge bitcoin/bitcoin#34310: iwyu: Add missed line to IWYU patch f4413706f9 Merge bitcoin/bitcoin#34344: ci: update GitHub Actions versions faa18dceba refactor: Use std::bind_front over std::bind c84c752506 Merge bitcoin/bitcoin#34319: Drop some `IWYU pragma: export` and document IWYU usage 38f951f828 Merge bitcoin/bitcoin#34308: doc: Document IWYU workaround ab80588f52 Merge bitcoin/bitcoin#34345: clang-format: use AngleBracket for main includes 977be171f2 Merge bitcoin/bitcoin#34188: test: Add multiple transactions and error handling tests for getreceivedbyaddress 347840164f Merge bitcoin/bitcoin#32143: Fix 11-year-old mis-categorized error code in OP_IF evaluation 969c840db5 log,blocks: avoid `ComputeTotalSize` and `GetHash` work when logging is disabled babfda332b log,net: avoid `ComputeTotalSize` when logging is disabled 1658b8f82b refactor: rename `CTransaction::GetTotalSize` to signal that it's not cached 75b704df9d wallettool: Disallow creating new unnamed wallets 5875a9c502 wallet: disallow unnamed wallets in createwallet and restorewallet 0dafc0d83c clang-format: use AngleBracket for main includes 03f363d378 doc: Document IWYU workaround d938947b3a doc: Add "Using IWYU" to Developer Notes e1a90bcecc iwyu: Do not export `crypto/hex_base.h` header 19a2edde50 iwyu: Do not export C++ headers in most cases 9482f00df0 chore: Update outdated GitHub Actions versions 898e8d3a2d Merge bitcoin/bitcoin#34296: refactor: [move-only] Merge core_io module, remove from libkernel faf07bd1ab doc: Fix typo found by LLM faf66673ac refactor: [move-only] Merge core_io module fa6947f491 kernel: Remove unused core_read.cpp from kernel 5e49f5d63c Merge bitcoin/bitcoin#33779: ci, iwyu: Fix warnings in `src/kernel` and treat them as errors c57fbbe99d Merge bitcoin/bitcoin#31650: refactor: Avoid copies by using const references or by move-construction d45ec3fba9 test: Add getreceivedbyaddress coverage to wallet_listreceivedby 22bde74d1d Merge bitcoin-core/gui#924: Show an error message if the restored wallet name is empty 81bf4209e9 Merge bitcoin/bitcoin#34318: contrib: Revert "verify-commits sha1 exceptions" a5a8c4139c ci, iwyu: Fix warnings in `src/kernel` and treat them as errors fa38ffac6f contrib: [refactor] Use shorter read_text from pathlib fab8bc0308 contrib: Revert "verify-commits sha1 exceptions" de509c6df9 iwyu: Add missed line to IWYU patch faa59b3679 util: Add Expected::swap() fabb47e4e3 util: Implement Expected::operator*()&& d94d7b1a4b guix: stop passing depends sources to codesigning 0ffb20dee1 Merge bitcoin/bitcoin#34282: qa: Fix Windows logging bug fab9721430 util: Implement Expected::value()&& and Expected::error()&& fac4800959 util: Add Expected specialization fa6575d6c2 util: Make Expected::value() throw 697bc7f6a2 Merge bitcoin/bitcoin#34300: test: use ephemeral ports in p2p_private_broadcast.py 37cb209277 Merge bitcoin/bitcoin#34238: wallet: remove erroneous-on-reorg Assume() fabf8d1c5b fuzz: Restore SendMessages coverage in process_message(s) fuzz targets fac7fed397 refactor: Use std::reference_wrapper in Connman d08c1b3ed9 Merge bitcoin/bitcoin#34288: fuzz: Exclude too expensive inputs in miniscript_string target 6a8dbf9b93 p2p: add validation check for initial self-announcement baa554f708 Merge bitcoin/bitcoin#34259: Find minimal chunks in SFL 3e340672ec test: use ephemeral ports in p2p_private_broadcast.py 9d2b8fddad Merge bitcoin/bitcoin#34210: bench: Remove -priority-level= option ae3b5a99f8 Merge bitcoin/bitcoin#34186: test: use dynamic port allocation in proxy tests f4364cedb3 Merge bitcoin/bitcoin#33728: test: Add bitcoin-chainstate test for assumeutxo functionality 80c4c2df3f Merge bitcoin/bitcoin#34146: p2p: send first addr self-announcement in separate message 🎄 fa64d8424b refactor: Enforce readability-avoid-const-params-in-decls faf0c2d942 refactor: Avoid copies by using const references or by move-construction cd0959ce9b Merge bitcoin/bitcoin#34185: test: fix `feature_pruning` when built without wallet b0b65336e7 Merge bitcoin/bitcoin#32740: refactor: Header sync optimisations & simplifications fac70ea8b5 fuzz: Exclude too expensive inputs in miniscript_string target fa90786478 iwyu: Fix includes for test/fuzz/util/descriptor module c0219f6bea Merge bitcoin/bitcoin#34285: ci: Install `pyzmq` for functional tests on Windows f62568c97c ci: Install `pyzmq` for functional tests on Windows 2d380aee43 Merge bitcoin/bitcoin#34243: doc: validation: fix `PackageMempoolChecks` incorrect comment db6e576710 Merge bitcoin/bitcoin#34279: test: Fail on self-check warnings in test_runner.py c447eea43d Merge bitcoin/bitcoin#34145: test: Add unit test for OP_NUMEQUALVERIFY 979d41bfab qa: Fix Windows logging bug 28f70c571b Merge bitcoin/bitcoin#34240: ci: Run feature_unsupported_utxo_db.py on Windows fa2959e16d test: Fail on self-check warnings in test_runner.py ac76d94117 Merge bitcoin/bitcoin#34109: refactor: Use uint64_t over size_t for serialize corruption check in fees.dat fa5032f0e4 ci: Run feature_unsupported_utxo_db.py on Windows 57350c5352 Merge bitcoin/bitcoin#34272: psbt: Fix `PSBTInputSignedAndVerified` bounds `assert` 88a7294356 Merge bitcoin/bitcoin#34260: contrib: Remove unused functions 8e8d8f29a8 Merge bitcoin/bitcoin#33775: guix: use GCC 14.3.0 over 13.3.0 d20037893a Merge bitcoin/bitcoin#34244: test: Prevent loop from running out of utxos in bip68 test 4aa80c3b5e Merge bitcoin/bitcoin#34230: fuzz: Reject too large descriptor leaf sizes in scriptpubkeyman target 72e0999ddb Merge bitcoin/bitcoin#34099: test: Improve code coverage for pubkey checks 377c6dbc3c Merge bitcoin/bitcoin#34224: init: Return EXIT_SUCCESS on interrupt c094a966d6 Merge bitcoin/bitcoin#34246: verify-commits: Allow specific commits to allow sha1 c352d3c51c Merge bitcoin/bitcoin#34168: qa: Require `--exclude` for each excluded test d30ad4a912 wallet, rpc: Use HandleWalletError in createwallet 7fc465ece8 doc: fix incorrect description of `PackageMempoolChecks` 62557c9529 Merge bitcoin/bitcoin#33819: mining: getCoinbase() returns struct instead of raw tx 73d0fe62d3 Merge commit '7562e2aeed95b0dc627e8e3a849941992f0189bb' into pr/subtree-7 7562e2aeed Squashed 'src/ipc/libmultiprocess/' changes from a4f92969649..1fc65008f7d 2f5b1c5f80 psbt: Fix `PSBTInputSignedAndVerified` bounds `assert` fa3df52712 bench: Require semicolon after BENCHMARK(foo) fa8938f08c bench: Remove incorrect __LINE__ in BENCHMARK macro fa51a28a94 scripted-diff: Remove priority_level from BENCHMARK macro fa790c3eea bench: Remove -priority-level= option dd904298c1 gui: Show an error message if the restored wallet name is empty 3c8d389a84 Merge bitcoin/bitcoin#34249: doc: archive v30.2 release notes 5e98a6a470 Merge bitcoin/bitcoin#34266: release note: cpfp carveout removed in 31.0 61726483e1 release note: cpfp carveout removed in 31.0 da56ef239b clusterlin: minimize chunks (feature) d09a19fd41 test: add coverage for issue 34206 a0ca851d26 Make GetBindAddress() callable from outside net.cpp 796f18e559 Merge bitcoin/bitcoin#29415: Broadcast own transactions only via short-lived Tor or I2P connections facaf56214 contrib: Remove unused functions abc6a3a4eb Merge bitcoin/bitcoin#34252: doc: add 433 (Pay to Anchor) to bips.md 44b12cdb11 doc: add 433 (Pay to Anchor) to bips.md f664860e52 doc: archive v30.2 release notes ce63d37ebe test: use dynamic port allocation to avoid test conflicts 8ac134be5e contrib: verify-commits sha1 exceptions ab41492c6b test: Prevent loop from running out of utxos in bip68 test aeaa67a9ea Merge bitcoin/bitcoin#33428: depends: Boost 1.90.0 1412b779ad refactor: execute `PackageMempoolChecks` during package rbf only 4c7cfd37ad wallet: remove erroneous-on-reorg Assume() 8fb5e5f41d test: check wallet rescan properly in feature_pruning 595504a432 Merge bitcoin/bitcoin#34236: Add sedited to trusted-keys 5c724f3b04 Merge bitcoin/bitcoin#34235: miniminer: stop assuming ancestor fees >= self fees 2d87afcf7d Merge bitcoin/bitcoin#34227: guix: Fix `osslsigncode` tests 7b17fb78fa Merge bitcoin/bitcoin#34226: wallet: test: Relative wallet failed migration cleanup eeaf28dbe0 wallet: test: Failed migration cleanup 997e7b4d7c init: Fix non-zero code on interrupt d1b227f3ad Add sedited to trusted-keys 6c3fb719d1 Merge bitcoin-core/gui#921: Remove deprecated "Starting Block" from Peer Detail 2cade5d5d1 [miniminer] stop assuming ancestor fees >= self fees fa8d56f9f0 fuzz: Reject too large descriptor leaf sizes in scriptpubkeyman target fabac1b395 fuzz: Reject some more "expensive" descriptors in the scriptpubkeyman target 194114daf3 guix: Fix `osslsigncode` tests 333333356f fuzz: [refactor] Use std::span over FuzzBufferType in descriptor utils 8d5700ab0f Merge bitcoin/bitcoin#34221: test: migration, avoid backup name mismatch in default_wallet_failure cbf0bd35bb test: migration, avoid backup name mismatch in default_wallet_failure cd6e4c9235 Merge bitcoin/bitcoin#34215: wallettool: fix unnamed createfromdump failure walletsdir deletion 90d651a81f Merge bitcoin/bitcoin#34156: wallet: fix unnamed legacy wallet migration failure 9c7e4771b1 test: Test listdescs with priv works even with missing priv keys ed945a6854 walletrpc: reject listdes with priv key on w-only wallets 9e5e9824f1 descriptor: ToPrivateString() pass if at least 1 priv key exists 5c4db25b61 descriptor: refactor ToPrivateString for providers 2dc74e3f4e wallet/migration: use HavePrivateKeys in place of ToPrivateString e842eb90bb descriptors: add HavePrivateKeys() f78f6f1dc8 wallettool: do not use fs::remove_all in createfromdump cleanup a9daa6dbd3 Merge bitcoin/bitcoin#34135: rpc: [wallet] Use unsigned type for tx version in sendall a3c71c7201 [test] Add BIP 328 test vectors for Musig2 b7c34d08dd test: coverage for migration failure when last sync is beyond prune height 82caa8193a wallet: migration, fix watch-only and solvables wallets names d70b159c42 wallet: improve post-migration logging f011e0f068 test: restorewallet, coverage for existing dirs, unnamed wallet and prune failure 36093bde63 test: add coverage for unnamed wallet migration failure f4c7e28e80 wallet: fix unnamed wallet migration failure 4ed0693a3f wallet: RestoreWallet failure, erase only what was created c60f9cb66e Merge bitcoin/bitcoin#34085: cluster mempool: exploit SFL properties in txgraph 2a746500fa ci: migrate some jobs to Debian Trixie, use GCC 14 fb0e6edfe8 guix: Apply SSA generation patch to maintain determinism 34909799fe guix: use GCC 14.3.0 over 13.3.0 47be9122a7 guix: disable gprofng in GCC ea29329eb7 guix: build GCC with --enable-host-bind-now 6f54e267d0 guix: disable libquadmath in GCC 7735901ed2 guix: disable building libgomp in GCC 114901c065 Merge bitcoin/bitcoin#34203: doc: p2p: replace last remaining "command" terminology with "message type" d7cbdfa090 Merge bitcoin/bitcoin#34204: test: fix intermittent failure in p2p_addr_selfannouncement 301d9eea66 qt: Remove "Starting Block" from Peer Detail. Following Deprecation in `bitcoin#34197` 0ad4376a49 Merge bitcoin/bitcoin#33142: test: Run bench sanity checks in parallel with functional tests c267b3a2c6 Merge bitcoin/bitcoin#34197: rpc, net: deprecate `startingheight` field of `getpeerinfo` RPC d6a6afd955 Merge bitcoin/bitcoin#34010: psbt: detect invalid MuSig2 pubkeys in deserialization 5b7bf47f9b doc: p2p: replace last remaining "command" terminology with "message type" 1808b5aaf7 clusterlin: remove unused FixLinearization (cleanup) 34a77138b7 txgraph: permit non-topological clusters to defer fixing (optimization) 3380e0cbb5 txgraph: use PostLinearize less prior to linearizing 62dd88624a txgraph: drop NEEDS_SPLIT_ACCEPTABLE (simplification) 01ffcf464a clusterlin: support fixing linearizations (feature) 755f0900a2 Merge bitcoin/bitcoin#34136: test: Allow mempool_updatefromblock.py to run on 32-bit 5805a8b540 psbt: detect invalid MuSig2 pubkeys in deserialization 792e2edf57 p2p: first addr self-announcement in separate msg 31852057ea test: fix intermittent failure in p2p_addr_selfannouncement 48f57bb35b mining: add new getCoinbaseTx() returning a struct bd4f4782f2 Merge bitcoin/bitcoin#34154: test: Enable ruff E713 lint 4ce3f4a265 rpc, net: deprecate `startingheight` field of `getpeerinfo` RPC ab233255d4 Merge bitcoin/bitcoin#33866: refactor: Let CCoinsViewCache::BatchWrite return void 2628de7479 Merge bitcoin/bitcoin#33135: wallet: warn against accidental unsafe older() import 9b57c8d2bd test: fix feature_pruning when built without wallet c631553732 Merge bitcoin/bitcoin#34191: doc: archive release notes for v30.1 bd730cb0a1 doc: archive release notes for v30.1 c5825d4b7f qa: Require `--exclude` for each excluded test 6ed2cf5184 Merge bitcoin/bitcoin#34169: fuzz: change fuzz runner test_runner.py to be cwd independent fb49d62d8f Merge bitcoin/bitcoin#34177: policy/refactor: remove constant parameter from `IsWellFormedPackage` fa65bc0e79 test: Run bench sanity checks in parallel with functional tests fa9fdbce79 test: Pass bench exe into test framework utils adbb4b3208 Merge bitcoin/bitcoin#34174: doc: update copyright year to 2026 891aed2f75 Merge bitcoin/bitcoin#34172: Fix intermittent issue in p2p_1p1c_network.py 7590a72a5e Merge bitcoin/bitcoin#34182: doc: Update OpenBSD Build Guide a50d7a7929 Merge bitcoin/bitcoin#34183: doc: fix double-word typos in comments 2bff9ebeff Merge bitcoin/bitcoin#34102: depends: capnp 1.3.0 08ed802bab doc: fix double-word typos in comments 84d8c52662 doc: Update OpenBSD Build Guide 77c9b3c08f change test_runner.py to be cwd independent by calling subprocess.run with cwd arg. 658d38106a policy: remove constant parameter from `IsWellFormedPackage` b23b901363 doc: update copyright year 95ef0fc5e7 test: ensure clean orphanage before continuing 25e84d3772 test: change low fee parents to 0-fee 2bcb3f6464 Merge bitcoin/bitcoin#34112: rpc: [mempool] Remove erroneous Univalue integral casts 7249bcc4f8 Merge bitcoin/bitcoin#34119: contrib: remove `copyright_header.py` 0f6a526f43 Merge bitcoin/bitcoin#34160: policy: Remove stale rationale paragraph 337b4a2369 Remove stale rationale paragraph 94ddc2dced Merge bitcoin/bitcoin#34113: refactor: [rpc] Remove confusing and brittle integral casts c575990651 Merge bitcoin/bitcoin#34147: scripted-diff: refactor: wallet: Delete duplicate IsCrypted() fab300b378 test: Enable ruff E713 lint 11ce5cf799 scripted-diff: refactor: wallet: Delete IsCrypted b762538756 test: Add unit test for SCRIPT_ERR_NUMEQUALVERIFY 3dd815f048 validation: pre-reserve leaves to prevent reallocs with odd vtx count 7fd47e0e56 bench: make `MerkleRoot` benchmark more representative fac5a1b10a test: Allow mempool_updatefromblock.py to run on 32-bit fafbc70d48 rpc: [wallet] Use unsigned type for tx version in sendall ba6315d2f6 contrib: remove copyright_header.py 3e4765ee10 scripted-diff: [doc] Unify stale copyright headers fa66e2d07a refactor: [rpc] Remove confusing and brittle integral casts fab1f4b800 rpc: [mempool] Remove erroneous Univalue integral casts d59b4cdb57 mining: rename getCoinbaseTx() to ..RawTx() fa1d17d56c refactor: Use uint64_t over size_t for serialize corruption check in fees.dat 7b5d256af4 test: Add bitcoin-chainstate test for assumeutxo functionality 2bc3265649 Fix `ChainstateManager::AddChainstate()` assertion crash 5f3d6bdb66 Add regtest support to bitcoin-chainstate tool 719158db5c depends: capnp 1.3.0 6bb66fcccb test: Improve code coverage for pubkey checks f46e3ec0f9 net: Fix `-Wmissing-braces` 8937221304 doc: add release notes for 29415 582016fa5f test: add unit test for the private broadcast storage e74d54e048 test: add functional test for private broadcast 818b780a05 rpc: use private broadcast from sendrawtransaction RPC if -privatebroadcast is ON eab595f9cf net_processing: retry private broadcast 37b79f9c39 net_processing: stop private broadcast of a transaction after round-trip 2de53eee74 net_processing: handle ConnectionType::PRIVATE_BROADCAST connections 30a9853ad3 net_processing: move a debug check in VERACK processing earlier d1092e5d48 net_processing: modernize PushNodeVersion() 9937a12a2f net_processing: move the debug log about receiving VERSION earlier a098f37b9e net_processing: reorder the code that handles the VERSION message 679ce3a0b8 net_processing: store transactions for private broadcast in PeerManager a3faa6f944 node: extend node::TxBroadcast with a 3rd option 95c051e210 net_processing: rename RelayTransaction() to better describe what it does bb49d26032 net: implement opening PRIVATE_BROADCAST connections 01dad4efe2 net: introduce a new connection type for private broadcast 94aaa5d31b init: introduce a new option to enable/disable private broadcast d6ee490e0a log: introduce a new category for private broadcast 6da6f503a6 refactor: Let CCoinsViewCache::BatchWrite return void f0a2183108 test: adjust `ComputeMerkleRoot` tests fa1de1103f util: Add Unexpected::error() faa109f8be test: refactor: Use BOOST_CHECK_EQUAL over BOOST_CHECK == fad4a9fe2b Set bugprone-unused-return-value.AllowCastToVoid ca4a844eed depends: Boost 1.90.0 76c092ff80 wallet: warn against accidental unsafe older() import 592157b759 test: move SEQUENCE_LOCKTIME flags to script de4242f474 refactor: Use reference for chain_start in HeadersSyncState e37555e540 refactor: Use initializer list in CompressedHeader 0488bdfefe refactor: Remove unused parameter in ReportHeadersPresync 256246a9fa refactor: Remove redundant parameter from CheckHeadersPoW ca0243e3a6 refactor: Remove useless CBlock::GetBlockHeader 4568652222 refactor: Use std::span in HasValidProofOfWork 4066bfe561 refactor: Compute work from headers without CBlockIndex 0bf6139e19 p2p: Avoid an IsAncestorOfBestHeaderOrTip call a7b581423e Fix 11-year-old mis-categorized error code in OP_IF evaluation git-subtree-dir: depend/bitcoin git-subtree-split: 891030ac8b9e3f91084a9c8e0d8d9a158a2bbf93 --- .github/workflows/ci.yml | 29 +- CMakeLists.txt | 2 +- COPYING | 4 +- ci/test/00_setup_env_arm.sh | 4 +- ci/test/00_setup_env_i686_no_ipc.sh | 2 +- .../00_setup_env_native_fuzz_with_valgrind.sh | 2 +- ci/test/00_setup_env_native_valgrind.sh | 4 +- ci/test/00_setup_env_s390x.sh | 5 +- ci/test/00_setup_env_win64_msvcrt.sh | 2 +- ci/test/01_iwyu.patch | 6 +- ci/test/03_test_script.sh | 4 +- contrib/debian/copyright | 2 +- contrib/devtools/README.md | 59 -- contrib/devtools/circular-dependencies.py | 7 - contrib/devtools/copyright_header.py | 601 ------------------ contrib/devtools/utils.py | 21 - contrib/guix/guix-codesign | 12 - contrib/guix/manifest.scm | 37 +- contrib/guix/patches/gcc-ssa-generation.patch | 49 ++ contrib/guix/symbol-check.py | 2 +- contrib/linearize/linearize-data.py | 4 +- contrib/verify-binaries/verify.py | 19 - contrib/verify-commits/trusted-keys | 1 + contrib/verify-commits/verify-commits.py | 23 +- depends/packages/boost.mk | 9 +- depends/packages/native_capnp.mk | 4 +- .../patches/boost/skip_compiled_targets.patch | 136 ---- doc/bips.md | 1 + doc/build-openbsd.md | 9 +- doc/developer-notes.md | 17 +- doc/policy/packages.md | 8 - doc/release-notes-29415.md | 14 + doc/release-notes-33629.md | 8 + doc/release-notes-33819.md | 8 + doc/release-notes-34197.md | 7 + doc/release-notes/release-notes-30.1.md | 108 ++++ doc/release-notes/release-notes-30.2.md | 91 +++ src/.clang-format | 1 + src/.clang-tidy | 3 + src/CMakeLists.txt | 4 +- src/addrman.h | 2 +- src/addrman_impl.h | 4 +- src/bench/CMakeLists.txt | 4 - src/bench/addrman.cpp | 12 +- src/bench/base58.cpp | 6 +- src/bench/bech32.cpp | 4 +- src/bench/bench.cpp | 42 +- src/bench/bench.h | 27 +- src/bench/bench_bitcoin.cpp | 15 - src/bench/bip324_ecdh.cpp | 2 +- src/bench/block_assemble.cpp | 4 +- src/bench/blockencodings.cpp | 6 +- src/bench/ccoins_caching.cpp | 2 +- src/bench/chacha20.cpp | 12 +- src/bench/checkblock.cpp | 4 +- src/bench/checkblockindex.cpp | 2 +- src/bench/checkqueue.cpp | 2 +- src/bench/cluster_linearize.cpp | 18 +- src/bench/coin_selection.cpp | 6 +- src/bench/connectblock.cpp | 6 +- src/bench/crypto_hash.cpp | 48 +- src/bench/descriptors.cpp | 2 +- src/bench/disconnected_transactions.cpp | 6 +- src/bench/duplicate_inputs.cpp | 4 +- src/bench/ellswift.cpp | 2 +- src/bench/examples.cpp | 2 +- src/bench/gcs_filter.cpp | 10 +- src/bench/hashpadding.cpp | 4 +- src/bench/index_blockfilter.cpp | 2 +- src/bench/load_external.cpp | 2 +- src/bench/lockedpool.cpp | 2 +- src/bench/logging.cpp | 10 +- src/bench/mempool_ephemeral_spends.cpp | 2 +- src/bench/mempool_eviction.cpp | 2 +- src/bench/mempool_stress.cpp | 10 +- src/bench/merkle_root.cpp | 32 +- src/bench/obfuscation.cpp | 2 +- src/bench/parse_hex.cpp | 2 +- src/bench/peer_eviction.cpp | 12 +- src/bench/poly1305.cpp | 6 +- src/bench/pool.cpp | 4 +- src/bench/prevector.cpp | 4 +- src/bench/random.cpp | 32 +- src/bench/readwriteblock.cpp | 6 +- src/bench/rollingbloom.cpp | 4 +- src/bench/rpc_blockchain.cpp | 8 +- src/bench/rpc_mempool.cpp | 2 +- src/bench/sign_transaction.cpp | 8 +- src/bench/streams_findbyte.cpp | 2 +- src/bench/strencodings.cpp | 2 +- src/bench/txgraph.cpp | 2 +- src/bench/txorphanage.cpp | 8 +- src/bench/util_time.cpp | 8 +- src/bench/verify_script.cpp | 4 +- src/bench/wallet_balance.cpp | 8 +- src/bench/wallet_create.cpp | 4 +- src/bench/wallet_create_tx.cpp | 6 +- src/bench/wallet_ismine.cpp | 4 +- src/bench/wallet_loading.cpp | 2 +- src/bench/wallet_migration.cpp | 2 +- src/bitcoin-chainstate.cpp | 12 +- src/bitcoin-cli.cpp | 2 + src/blockencodings.cpp | 28 +- src/chain.cpp | 4 +- src/chain.h | 10 +- src/chainparams.h | 4 +- src/chainparamsbase.h | 4 +- src/cluster_linearize.h | 249 ++++++-- src/coins.cpp | 41 +- src/coins.h | 12 +- src/common/bloom.h | 4 +- src/common/messages.h | 2 +- src/common/signmessage.h | 2 +- src/compat/compat.h | 12 + src/consensus/merkle.cpp | 10 +- src/{core_write.cpp => core_io.cpp} | 265 +++++++- src/core_io.h | 9 +- src/core_read.cpp | 264 -------- src/crypto/hex_base.h | 6 +- src/deploymentinfo.h | 2 +- src/external_signer.cpp | 5 +- src/external_signer.h | 6 +- src/headerssync.cpp | 45 +- src/headerssync.h | 21 +- src/httpserver.cpp | 2 +- src/init.cpp | 52 +- src/interfaces/mining.h | 25 +- src/interfaces/wallet.h | 4 +- src/ipc/capnp/mining.capnp | 13 +- .../libmultiprocess/.github/workflows/ci.yml | 78 ++- src/ipc/libmultiprocess/ci/README.md | 26 + .../libmultiprocess/ci/configs/netbsd.bash | 11 + src/ipc/libmultiprocess/ci/scripts/run.sh | 2 +- .../cmake/TargetCapnpSources.cmake | 17 +- src/ipc/libmultiprocess/doc/design.md | 187 +++++- src/ipc/libmultiprocess/doc/versions.md | 46 ++ src/ipc/libmultiprocess/include/mp/proxy-io.h | 10 +- .../libmultiprocess/include/mp/proxy-types.h | 12 +- src/ipc/libmultiprocess/include/mp/util.h | 11 +- src/ipc/libmultiprocess/include/mp/version.h | 26 + src/ipc/libmultiprocess/src/mp/gen.cpp | 2 +- src/ipc/libmultiprocess/src/mp/proxy.cpp | 6 +- src/ipc/libmultiprocess/src/mp/util.cpp | 56 +- src/ipc/libmultiprocess/test/CMakeLists.txt | 1 + .../test/mp/test/spawn_tests.cpp | 110 ++++ src/ipc/libmultiprocess/test/mp/test/test.cpp | 8 + src/ipc/test/ipc_test.cpp | 4 +- src/kernel/CMakeLists.txt | 3 - src/kernel/bitcoinkernel.cpp | 115 +++- src/kernel/bitcoinkernel.h | 168 ++++- src/kernel/bitcoinkernel_wrapper.h | 125 +++- src/kernel/chainparams.cpp | 9 +- src/kernel/chainparams.h | 3 +- src/kernel/checks.cpp | 2 +- src/kernel/coinstats.cpp | 8 +- src/kernel/coinstats.h | 3 +- src/kernel/disconnected_transactions.h | 2 + src/logging.cpp | 1 + src/logging.h | 1 + src/merkleblock.cpp | 2 +- src/net.cpp | 243 +++++-- src/net.h | 84 ++- src/net_processing.cpp | 390 +++++++++--- src/net_processing.h | 19 +- src/netaddress.h | 2 +- src/netbase.cpp | 16 + src/netbase.h | 6 +- src/node/blockstorage.cpp | 1 + src/node/blockstorage.h | 2 +- src/node/connection_types.cpp | 2 + src/node/connection_types.h | 7 + src/node/interfaces.cpp | 8 +- src/node/miner.cpp | 36 +- src/node/miner.h | 8 +- src/node/mini_miner.cpp | 8 +- src/node/peerman_args.cpp | 2 + src/node/protocol_version.h | 4 +- src/node/transaction.cpp | 12 +- src/node/transaction.h | 2 +- src/node/types.h | 53 ++ src/policy/fees/block_policy_estimator.cpp | 2 +- src/policy/fees/block_policy_estimator.h | 2 +- src/policy/packages.cpp | 4 +- src/policy/packages.h | 2 +- src/pow.h | 2 +- src/primitives/block.h | 12 - src/primitives/transaction.cpp | 2 +- src/primitives/transaction.h | 4 +- src/private_broadcast.cpp | 133 ++++ src/private_broadcast.h | 166 +++++ src/psbt.cpp | 4 +- src/psbt.h | 11 +- src/qt/addresstablemodel.h | 2 +- src/qt/bitcoin.cpp | 77 +-- src/qt/bitcoingui.cpp | 6 +- src/qt/forms/debugwindow.ui | 91 +-- src/qt/guiutil.cpp | 2 + src/qt/networkstyle.h | 4 +- src/qt/rpcconsole.cpp | 6 +- src/qt/rpcconsole.h | 8 +- src/qt/transactiondesc.cpp | 2 +- src/qt/walletmodel.cpp | 12 +- src/qt/walletmodel.h | 6 +- src/random.h | 2 +- src/rpc/blockchain.cpp | 20 +- src/rpc/blockchain.h | 4 +- src/rpc/fees.cpp | 4 +- src/rpc/mempool.cpp | 60 +- src/rpc/mining.cpp | 8 +- src/rpc/net.cpp | 13 +- src/rpc/rawtransaction.cpp | 6 +- src/rpc/rawtransaction_util.cpp | 4 +- src/rpc/rawtransaction_util.h | 2 +- src/rpc/util.h | 8 +- src/script/descriptor.cpp | 143 ++++- src/script/descriptor.h | 18 +- src/script/interpreter.cpp | 2 +- src/script/miniscript.h | 45 +- src/script/script_error.h | 2 +- src/script/sigcache.h | 2 +- src/signet.cpp | 6 +- src/sync.h | 4 +- src/test/CMakeLists.txt | 2 + src/test/argsman_tests.cpp | 4 +- src/test/bip328_tests.cpp | 114 ++++ src/test/blockfilter_index_tests.cpp | 3 +- src/test/cluster_linearize_tests.cpp | 20 +- src/test/coins_tests.cpp | 13 +- src/test/data/script_tests.json | 53 +- src/test/descriptor_tests.cpp | 57 +- src/test/fuzz/block_header.cpp | 4 +- src/test/fuzz/block_index_tree.cpp | 2 +- src/test/fuzz/cluster_linearize.cpp | 110 ++-- src/test/fuzz/coins_view.cpp | 4 +- src/test/fuzz/coinscache_sim.cpp | 3 +- src/test/fuzz/descriptor_parse.cpp | 19 +- src/test/fuzz/headerssync.cpp | 4 +- src/test/fuzz/i2p.cpp | 3 +- src/test/fuzz/integer.cpp | 4 +- src/test/fuzz/miniscript.cpp | 12 +- src/test/fuzz/process_message.cpp | 27 +- src/test/fuzz/process_messages.cpp | 27 +- src/test/fuzz/transaction.cpp | 4 +- src/test/fuzz/txgraph.cpp | 2 +- src/test/fuzz/util.h | 6 +- src/test/fuzz/util/descriptor.cpp | 36 +- src/test/fuzz/util/descriptor.h | 61 +- src/test/fuzz/utxo_snapshot.cpp | 4 +- src/test/headers_sync_chainwork_tests.cpp | 2 +- src/test/i2p_tests.cpp | 5 +- src/test/kernel/test_kernel.cpp | 57 +- src/test/merkle_tests.cpp | 14 +- src/test/miniscript_tests.cpp | 2 +- src/test/netbase_tests.cpp | 7 +- src/test/private_broadcast_tests.cpp | 96 +++ src/test/scheduler_tests.cpp | 10 +- src/test/script_tests.cpp | 2 +- src/test/txpackage_tests.cpp | 18 +- src/test/util/cluster_linearize.h | 16 +- src/test/util/net.h | 3 + src/test/util/setup_common.h | 8 +- src/test/util_expected_tests.cpp | 84 ++- src/test/util_string_tests.cpp | 152 +++++ src/test/util_tests.cpp | 48 ++ src/test/validation_block_tests.cpp | 4 +- src/test/validation_flush_tests.cpp | 2 +- src/torcontrol.cpp | 24 +- src/txdb.cpp | 4 +- src/txdb.h | 2 +- src/txgraph.cpp | 145 ++--- src/txmempool.h | 13 +- src/txrequest.h | 2 +- src/util/expected.h | 90 ++- src/util/moneystr.h | 2 +- src/util/strencodings.h | 28 +- src/util/string.cpp | 54 ++ src/util/string.h | 39 +- src/util/time.cpp | 22 + src/util/time.h | 6 + src/validation.cpp | 52 +- src/validation.h | 6 +- src/wallet/coinselection.h | 10 +- src/wallet/crypter.h | 2 +- src/wallet/db.h | 1 + src/wallet/dump.cpp | 13 +- src/wallet/interfaces.cpp | 4 +- src/wallet/rpc/backup.cpp | 12 +- src/wallet/rpc/coins.cpp | 4 +- src/wallet/rpc/encrypt.cpp | 8 +- src/wallet/rpc/spend.cpp | 2 +- src/wallet/rpc/util.cpp | 6 +- src/wallet/rpc/util.h | 2 +- src/wallet/rpc/wallet.cpp | 11 +- src/wallet/scriptpubkeyman.cpp | 7 +- src/wallet/scriptpubkeyman.h | 6 +- src/wallet/spend.cpp | 1 - src/wallet/spend.h | 2 +- src/wallet/test/fuzz/scriptpubkeyman.cpp | 13 +- src/wallet/test/fuzz/spend.cpp | 2 +- src/wallet/test/init_test_fixture.h | 2 +- src/wallet/test/util.h | 2 +- src/wallet/test/wallet_test_fixture.h | 2 +- src/wallet/test/walletload_tests.cpp | 2 + src/wallet/wallet.cpp | 147 ++++- src/wallet/wallet.h | 13 +- src/wallet/walletdb.h | 4 +- src/wallet/wallettool.cpp | 8 +- test/CMakeLists.txt | 1 + test/config.ini.in | 1 + test/functional/data/invalid_txs.py | 2 +- test/functional/data/rpc_psbt.json | 18 +- test/functional/feature_anchors.py | 6 +- test/functional/feature_bip68_sequence.py | 13 +- test/functional/feature_config_args.py | 24 + test/functional/feature_proxy.py | 15 +- test/functional/feature_pruning.py | 22 +- test/functional/interface_ipc.py | 101 ++- test/functional/mempool_persist.py | 10 +- test/functional/mempool_updatefromblock.py | 15 +- .../mining_prioritisetransaction.py | 52 ++ test/functional/p2p_1p1c_network.py | 50 +- test/functional/p2p_addr_selfannouncement.py | 18 +- test/functional/p2p_private_broadcast.py | 442 +++++++++++++ test/functional/p2p_v2_transport.py | 2 +- test/functional/rpc_net.py | 5 +- test/functional/rpc_psbt.py | 4 +- test/functional/rpc_setban.py | 4 +- test/functional/test_framework/blocktools.py | 4 +- test/functional/test_framework/descriptors.py | 4 +- test/functional/test_framework/p2p.py | 5 +- test/functional/test_framework/script.py | 5 + test/functional/test_framework/socks5.py | 3 + .../test_framework/test_framework.py | 11 +- test/functional/test_framework/test_node.py | 1 - test/functional/test_framework/util.py | 11 +- test/functional/test_runner.py | 42 +- test/functional/tool_bench_sanity_check.py | 41 ++ test/functional/tool_bitcoin_chainstate.py | 95 ++- test/functional/tool_wallet.py | 11 + test/functional/wallet_abandonconflict.py | 2 +- test/functional/wallet_assumeutxo.py | 2 +- test/functional/wallet_backup.py | 61 +- test/functional/wallet_createwallet.py | 1 + test/functional/wallet_importdescriptors.py | 37 ++ test/functional/wallet_listdescriptors.py | 34 +- test/functional/wallet_listreceivedby.py | 13 +- test/functional/wallet_migration.py | 132 ++++ test/functional/wallet_send.py | 2 +- test/functional/wallet_startup.py | 16 +- test/functional/wallet_v3_txs.py | 106 +++ test/fuzz/test_runner.py | 6 +- test/lint/test_runner/src/main.rs | 1 + 352 files changed, 6413 insertions(+), 2720 deletions(-) delete mode 100755 contrib/devtools/copyright_header.py delete mode 100755 contrib/devtools/utils.py create mode 100644 contrib/guix/patches/gcc-ssa-generation.patch delete mode 100644 depends/patches/boost/skip_compiled_targets.patch create mode 100644 doc/release-notes-29415.md create mode 100644 doc/release-notes-33819.md create mode 100644 doc/release-notes-34197.md create mode 100644 doc/release-notes/release-notes-30.1.md create mode 100644 doc/release-notes/release-notes-30.2.md rename src/{core_write.cpp => core_io.cpp} (54%) delete mode 100644 src/core_read.cpp create mode 100644 src/ipc/libmultiprocess/ci/configs/netbsd.bash create mode 100644 src/ipc/libmultiprocess/doc/versions.md create mode 100644 src/ipc/libmultiprocess/include/mp/version.h create mode 100644 src/ipc/libmultiprocess/test/mp/test/spawn_tests.cpp create mode 100644 src/private_broadcast.cpp create mode 100644 src/private_broadcast.h create mode 100644 src/test/bip328_tests.cpp create mode 100644 src/test/private_broadcast_tests.cpp create mode 100755 test/functional/p2p_private_broadcast.py create mode 100755 test/functional/tool_bench_sanity_check.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e5b0c48..f54e0661 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -258,7 +258,7 @@ jobs: sed -i '1s/^/set(ENV{CMAKE_POLICY_VERSION_MINIMUM} 3.5)\n/' "${VCPKG_INSTALLATION_ROOT}/scripts/ports.cmake" - name: vcpkg tools cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: C:/vcpkg/downloads/tools key: ${{ github.job }}-vcpkg-tools @@ -320,12 +320,15 @@ jobs: BITCOIN_BIN: '${{ github.workspace }}\build\bin\Release\bitcoin.exe' BITCOIND: '${{ github.workspace }}\build\bin\Release\bitcoind.exe' BITCOINCLI: '${{ github.workspace }}\build\bin\Release\bitcoin-cli.exe' + BITCOIN_BENCH: '${{ github.workspace }}\build\bin\Release\bench_bitcoin.exe' BITCOINTX: '${{ github.workspace }}\build\bin\Release\bitcoin-tx.exe' BITCOINUTIL: '${{ github.workspace }}\build\bin\Release\bitcoin-util.exe' BITCOINWALLET: '${{ github.workspace }}\build\bin\Release\bitcoin-wallet.exe' BITCOINCHAINSTATE: '${{ github.workspace }}\build\bin\Release\bitcoin-chainstate.exe' TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }} - run: py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --ci --quiet --tmpdirprefix="${RUNNER_TEMP}" --combinedlogslen=99999999 --timeout-factor=${TEST_RUNNER_TIMEOUT_FACTOR} ${TEST_RUNNER_EXTRA} + run: | + py -3 -m pip install pyzmq + py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --quiet --tmpdirprefix="${RUNNER_TEMP}" --combinedlogslen=99999999 --timeout-factor=${TEST_RUNNER_TIMEOUT_FACTOR} ${TEST_RUNNER_EXTRA} - name: Clone corpora if: matrix.job-type == 'fuzz' @@ -406,7 +409,7 @@ jobs: uses: ./.github/actions/save-caches - name: Upload built executables - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: ${{ matrix.artifact-name }}-${{ github.run_id }} path: | @@ -444,7 +447,7 @@ jobs: ref: ${{ needs.record-frozen-commit.outputs.commit }} - name: Download built executables - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: ${{ matrix.artifact-name }}-${{ github.run_id }} @@ -483,9 +486,6 @@ jobs: ./src/univalue/object.exe ./src/univalue/unitester.exe - - name: Run benchmarks - run: ./bin/bench_bitcoin.exe -sanity-check - - name: Adjust paths in test/config.ini shell: pwsh run: | @@ -501,11 +501,18 @@ jobs: - name: Run functional tests env: - # TODO: Fix the excluded test and re-enable it. - # feature_unsupported_utxo_db.py fails on windows because of emojis in the test data directory - EXCLUDE: '--exclude wallet_multiwallet.py,feature_unsupported_utxo_db.py' TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }} - run: py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --ci --quiet --tmpdirprefix="$RUNNER_TEMP" --combinedlogslen=99999999 --timeout-factor=$TEST_RUNNER_TIMEOUT_FACTOR $EXCLUDE $TEST_RUNNER_EXTRA + run: | + py -3 -m pip install pyzmq + py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --quiet --tmpdirprefix="$RUNNER_TEMP" --combinedlogslen=99999999 --timeout-factor=$TEST_RUNNER_TIMEOUT_FACTOR $TEST_RUNNER_EXTRA \ + `# feature_unsupported_utxo_db.py fails on Windows because of emojis in the test data directory.` \ + --exclude feature_unsupported_utxo_db.py \ + `# See https://github.com/bitcoin/bitcoin/issues/31409.` \ + --exclude wallet_multiwallet.py + # Run feature_unsupported_utxo_db sequentially in ASCII-only tmp dir, + # because it is excluded above due to lack of UTF-8 support in the + # ancient release. + py -3 test/functional/feature_unsupported_utxo_db.py --previous-releases --tmpdir="${RUNNER_TEMP}/test_feature_unsupported_utxo_db" ci-matrix: name: ${{ matrix.name }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e6c255d..1b1df77b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ set(CLIENT_VERSION_MINOR 99) set(CLIENT_VERSION_BUILD 0) set(CLIENT_VERSION_RC 0) set(CLIENT_VERSION_IS_RELEASE "false") -set(COPYRIGHT_YEAR "2025") +set(COPYRIGHT_YEAR "2026") # During the enabling of the CXX and CXXOBJ languages, we modify # CMake's compiler/linker invocation strings by appending the content diff --git a/COPYING b/COPYING index 23dc5e90..89960cbf 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2009-2025 The Bitcoin Core developers -Copyright (c) 2009-2025 Bitcoin Developers +Copyright (c) 2009-2026 The Bitcoin Core developers +Copyright (c) 2009-2026 Bitcoin Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh index c410a80d..f4ad97d2 100755 --- a/ci/test/00_setup_env_arm.sh +++ b/ci/test/00_setup_env_arm.sh @@ -10,10 +10,8 @@ export HOST=arm-linux-gnueabihf export DPKG_ADD_ARCH="armhf" export PACKAGES="python3-zmq g++-arm-linux-gnueabihf libc6:armhf libstdc++6:armhf libfontconfig1:armhf libxcb1:armhf" export CONTAINER_NAME=ci_arm_linux -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" # Check that https://packages.ubuntu.com/noble/g++-arm-linux-gnueabihf (version 13.x, similar to guix) can cross-compile +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # Check that https://packages.debian.org/trixie/g++-arm-linux-gnueabihf (version 14.x, similar to guix) can cross-compile export CI_IMAGE_PLATFORM="linux/arm64" -export RUN_UNIT_TESTS=true -export RUN_FUNCTIONAL_TESTS=false export GOAL="install" export CI_LIMIT_STACK_SIZE=1 # -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1" diff --git a/ci/test/00_setup_env_i686_no_ipc.sh b/ci/test/00_setup_env_i686_no_ipc.sh index c32e68cb..dca0486f 100755 --- a/ci/test/00_setup_env_i686_no_ipc.sh +++ b/ci/test/00_setup_env_i686_no_ipc.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu export CONTAINER_NAME=ci_i686_no_multiprocess -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" export CI_IMAGE_PLATFORM="linux/amd64" export PACKAGES="llvm clang g++-multilib" export DEP_OPTS="DEBUG=1 NO_IPC=1" diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh index f1d99f81..d8b0f5f1 100755 --- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh +++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" export CONTAINER_NAME=ci_native_fuzz_valgrind export PACKAGES="libevent-dev libboost-dev libsqlite3-dev valgrind libcapnp-dev capnproto" export NO_DEPENDS=1 diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh index 884bc395..30c84bf4 100755 --- a/ci/test/00_setup_env_native_valgrind.sh +++ b/ci/test/00_setup_env_native_valgrind.sh @@ -6,14 +6,14 @@ export LC_ALL=C.UTF-8 -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" export CONTAINER_NAME=ci_native_valgrind export PACKAGES="valgrind python3-zmq libevent-dev libboost-dev libzmq3-dev libsqlite3-dev libcapnp-dev capnproto python3-pip" export PIP_PACKAGES="--break-system-packages pycapnp" export USE_VALGRIND=1 export NO_DEPENDS=1 # bind tests excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 -export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra" +export TEST_RUNNER_EXTRA="--exclude rpc_bind --exclude feature_bind_extra" export GOAL="install" # TODO enable GUI export BITCOIN_CONFIG="\ diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh index b7d23fbf..d1e34070 100755 --- a/ci/test/00_setup_env_s390x.sh +++ b/ci/test/00_setup_env_s390x.sh @@ -9,9 +9,10 @@ export LC_ALL=C.UTF-8 export HOST=s390x-linux-gnu export PACKAGES="python3-zmq" export CONTAINER_NAME=ci_s390x -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" export CI_IMAGE_PLATFORM="linux/s390x" -export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 +# bind tests excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 +export TEST_RUNNER_EXTRA="--exclude rpc_bind --exclude feature_bind_extra" export RUN_FUNCTIONAL_TESTS=true export GOAL="install" export BITCOIN_CONFIG="\ diff --git a/ci/test/00_setup_env_win64_msvcrt.sh b/ci/test/00_setup_env_win64_msvcrt.sh index 86e0ea9c..6c948aeb 100755 --- a/ci/test/00_setup_env_win64_msvcrt.sh +++ b/ci/test/00_setup_env_win64_msvcrt.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_win64_msvcrt -export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" # Check that https://packages.ubuntu.com/noble/g++-mingw-w64-x86-64-posix (version 13.x, similar to guix) can cross-compile +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # Check that https://packages.debian.org/trixie/g++-mingw-w64-x86-64-posix (version 14.x, similar to guix) can cross-compile export HOST=x86_64-w64-mingw32 export PACKAGES="g++-mingw-w64-x86-64-posix nsis" export RUN_UNIT_TESTS=false diff --git a/ci/test/01_iwyu.patch b/ci/test/01_iwyu.patch index e14316bf..e7d75f4e 100644 --- a/ci/test/01_iwyu.patch +++ b/ci/test/01_iwyu.patch @@ -539,10 +539,11 @@ See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/ }; const IncludeMapEntry stdlib_c_include_map[] = { -@@ -601,31 +601,31 @@ const IncludeMapEntry stdlib_c_include_map[] = { +@@ -600,32 +600,32 @@ const IncludeMapEntry stdlib_c_include_map[] = { + // https://github.com/cplusplus/draft/blob/c+%2B20/source/lib-intro.tex // // $ curl -s -N https://raw.githubusercontent.com/cplusplus/draft/c%2B%2B20/source/lib-intro.tex | sed -n '/begin{multicolfloattable}.*{headers.cpp.c}/,/end{multicolfloattable}/p' | grep tcode | perl -nle 'm/tcode{}/ && print qq@ { "<$1.h>", kPublic, "", kPublic },@' | sort - { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, - { "", kPublic, "", kPublic }, - { "", kPublic, "", kPublic }, - { "", kPublic, "", kPublic }, @@ -568,6 +569,7 @@ See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/ - { "", kPublic, "", kPublic }, - { "", kPublic, "", kPublic }, - { "", kPublic, "", kPublic }, ++ { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 1cf9eb23..050d9e6a 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -184,7 +184,7 @@ if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then eval "TEST_RUNNER_EXTRA=($TEST_RUNNER_EXTRA)" LD_LIBRARY_PATH="${DEPENDS_DIR}/${HOST}/lib" \ "${BASE_BUILD_DIR}/test/functional/test_runner.py" \ - --ci "${MAKEJOBS}" \ + "${MAKEJOBS}" \ --tmpdirprefix "${BASE_SCRATCH_DIR}/test_runner/" \ --ansi \ --combinedlogslen=99999999 \ @@ -215,7 +215,7 @@ fi if [[ "${RUN_IWYU}" == true ]]; then # TODO: Consider enforcing IWYU across the entire codebase. - FILES_WITH_ENFORCED_IWYU="/src/((crypto|index)/.*\\.cpp|node/blockstorage.cpp|node/utxo_snapshot.cpp|core_read.cpp|signet.cpp|kernel/chain.cpp)" + FILES_WITH_ENFORCED_IWYU="/src/((crypto|index|kernel)/.*\\.cpp|node/blockstorage.cpp|node/utxo_snapshot.cpp|core_io.cpp|signet.cpp)" jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns)))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_errors.json" jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns) | not))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_warnings.json" diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 4e4deef9..4f703770 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -5,7 +5,7 @@ Upstream-Contact: Satoshi Nakamoto Source: https://github.com/bitcoin/bitcoin Files: * -Copyright: 2009-2025, Bitcoin Core Developers +Copyright: 2009-2026, Bitcoin Core Developers License: Expat Comment: The Bitcoin Core Developers encompasses all contributors to the project, listed in the release notes or the git log. diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 3309057b..50e80781 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -61,65 +61,6 @@ the script should be called from the git root folder as follows. git diff -U0 HEAD~1.. | ./contrib/devtools/clang-format-diff.py -p1 -i -v ``` -copyright\_header.py -==================== - -Provides utilities for managing copyright headers of `The Bitcoin Core -developers` in repository source files. It has three subcommands: - -``` -$ ./copyright_header.py report [verbose] -$ ./copyright_header.py update -$ ./copyright_header.py insert -``` -Running these subcommands without arguments displays a usage string. - -copyright\_header.py report \ [verbose] ---------------------------------------------------------- - -Produces a report of all copyright header notices found inside the source files -of a repository. Useful to quickly visualize the state of the headers. -Specifying `verbose` will list the full filenames of files of each category. - -copyright\_header.py update \ [verbose] ---------------------------------------------------------- -Updates all the copyright headers of `The Bitcoin Core developers` which were -changed in a year more recent than is listed. For example: -``` -// Copyright (c) - The Bitcoin Core developers -``` -will be updated to: -``` -// Copyright (c) - The Bitcoin Core developers -``` -where `` is obtained from the `git log` history. - -This subcommand also handles copyright headers that have only a single year. In -those cases: -``` -// Copyright (c) The Bitcoin Core developers -``` -will be updated to: -``` -// Copyright (c) - The Bitcoin Core developers -``` -where the update is appropriate. - -copyright\_header.py insert \ ------------------------------------- -Inserts a copyright header for `The Bitcoin Core developers` at the top of the -file in either Python or C++ style as determined by the file extension. If the -file is a Python file and it has `#!` starting the first line, the header is -inserted in the line below it. - -The copyright dates will be set to be `-` where -`` is according to the `git log` history. If -`` is equal to ``, it will be set as a single -year rather than two hyphenated years. - -If the file already has a copyright for `The Bitcoin Core developers`, the -script will exit. - gen-manpages.py =============== diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index af19b3a0..7c058171 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -6,11 +6,6 @@ import sys import re -MAPPING = { - 'core_read.cpp': 'core_io.cpp', - 'core_write.cpp': 'core_io.cpp', -} - # Directories with header-based modules, where the assumption that .cpp files # define functions and variables declared in corresponding .h files is # incorrect. @@ -19,8 +14,6 @@ ] def module_name(path): - if path in MAPPING: - path = MAPPING[path] if any(path.startswith(dirpath) for dirpath in HEADER_MODULE_PATHS): return path if path.endswith(".h"): diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py deleted file mode 100755 index aa77de8a..00000000 --- a/contrib/devtools/copyright_header.py +++ /dev/null @@ -1,601 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2016-present The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import re -import fnmatch -import sys -import subprocess -import datetime -import os - -################################################################################ -# file filtering -################################################################################ - -EXCLUDE = [ - # auto generated: - 'src/qt/bitcoinstrings.cpp', - 'src/chainparamsseeds.h', - # other external copyrights: - 'src/test/fuzz/FuzzedDataProvider.h', - 'src/tinyformat.h', - 'src/bench/nanobench.h', - # python init: - '*__init__.py', -] -EXCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in EXCLUDE])) - -EXCLUDE_DIRS = [ - # git subtrees - "src/crypto/ctaes/", - "src/leveldb/", - "src/minisketch", - "src/secp256k1/", - "src/crc32c/", -] - -INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py', '*.sh', '*.bash-completion'] -INCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in INCLUDE])) - -def applies_to_file(filename): - for excluded_dir in EXCLUDE_DIRS: - if filename.startswith(excluded_dir): - return False - return ((EXCLUDE_COMPILED.match(filename) is None) and - (INCLUDE_COMPILED.match(filename) is not None)) - -################################################################################ -# obtain list of files in repo according to INCLUDE and EXCLUDE -################################################################################ - -GIT_LS_CMD = 'git ls-files --full-name'.split(' ') -GIT_TOPLEVEL_CMD = 'git rev-parse --show-toplevel'.split(' ') - -def call_git_ls(base_directory): - out = subprocess.check_output([*GIT_LS_CMD, base_directory], text=True) - return [f for f in out.split('\n') if f != ''] - -def call_git_toplevel(): - "Returns the absolute path to the project root" - return subprocess.check_output(GIT_TOPLEVEL_CMD, text=True).strip() - -def get_filenames_to_examine(base_directory): - "Returns an array of absolute paths to any project files in the base_directory that pass the include/exclude filters" - root = call_git_toplevel() - filenames = call_git_ls(base_directory) - return sorted([os.path.join(root, filename) for filename in filenames if - applies_to_file(filename)]) - -################################################################################ -# define and compile regexes for the patterns we are looking for -################################################################################ - - -COPYRIGHT_WITH_C = r'Copyright \(c\)' -COPYRIGHT_WITHOUT_C = 'Copyright' -ANY_COPYRIGHT_STYLE = '(%s|%s)' % (COPYRIGHT_WITH_C, COPYRIGHT_WITHOUT_C) - -YEAR = "20[0-9][0-9]" -YEAR_RANGE = '(%s)(-%s)?' % (YEAR, YEAR) -YEAR_LIST = '(%s)(, %s)+' % (YEAR, YEAR) -ANY_YEAR_STYLE = '(%s|%s)' % (YEAR_RANGE, YEAR_LIST) -ANY_COPYRIGHT_STYLE_OR_YEAR_STYLE = ("%s %s" % (ANY_COPYRIGHT_STYLE, - ANY_YEAR_STYLE)) - -ANY_COPYRIGHT_COMPILED = re.compile(ANY_COPYRIGHT_STYLE_OR_YEAR_STYLE) - -def compile_copyright_regex(copyright_style, year_style, name): - return re.compile(r'%s %s,? %s( +\*)?\n' % (copyright_style, year_style, name)) - -EXPECTED_HOLDER_NAMES = [ - r"Satoshi Nakamoto", - r"The Bitcoin Core developers", - r"BitPay Inc\.", - r"Pieter Wuille", - r"Wladimir J\. van der Laan", - r"Jeff Garzik", - r"Jan-Klaas Kollhof", - r"ArtForz -- public domain half-a-node", - r"Intel Corporation ?", - r"The Zcash developers", - r"Jeremy Rubin", -] - -DOMINANT_STYLE_COMPILED = {} -YEAR_LIST_STYLE_COMPILED = {} -WITHOUT_C_STYLE_COMPILED = {} - -for holder_name in EXPECTED_HOLDER_NAMES: - DOMINANT_STYLE_COMPILED[holder_name] = ( - compile_copyright_regex(COPYRIGHT_WITH_C, YEAR_RANGE, holder_name)) - YEAR_LIST_STYLE_COMPILED[holder_name] = ( - compile_copyright_regex(COPYRIGHT_WITH_C, YEAR_LIST, holder_name)) - WITHOUT_C_STYLE_COMPILED[holder_name] = ( - compile_copyright_regex(COPYRIGHT_WITHOUT_C, ANY_YEAR_STYLE, - holder_name)) - -################################################################################ -# search file contents for copyright message of particular category -################################################################################ - -def get_count_of_copyrights_of_any_style_any_holder(contents): - return len(ANY_COPYRIGHT_COMPILED.findall(contents)) - -def file_has_dominant_style_copyright_for_holder(contents, holder_name): - match = DOMINANT_STYLE_COMPILED[holder_name].search(contents) - return match is not None - -def file_has_year_list_style_copyright_for_holder(contents, holder_name): - match = YEAR_LIST_STYLE_COMPILED[holder_name].search(contents) - return match is not None - -def file_has_without_c_style_copyright_for_holder(contents, holder_name): - match = WITHOUT_C_STYLE_COMPILED[holder_name].search(contents) - return match is not None - -################################################################################ -# get file info -################################################################################ - -def read_file(filename): - return open(filename, 'r').read() - -def gather_file_info(filename): - info = {} - info['filename'] = filename - c = read_file(filename) - info['contents'] = c - - info['all_copyrights'] = get_count_of_copyrights_of_any_style_any_holder(c) - - info['classified_copyrights'] = 0 - info['dominant_style'] = {} - info['year_list_style'] = {} - info['without_c_style'] = {} - for holder_name in EXPECTED_HOLDER_NAMES: - has_dominant_style = ( - file_has_dominant_style_copyright_for_holder(c, holder_name)) - has_year_list_style = ( - file_has_year_list_style_copyright_for_holder(c, holder_name)) - has_without_c_style = ( - file_has_without_c_style_copyright_for_holder(c, holder_name)) - info['dominant_style'][holder_name] = has_dominant_style - info['year_list_style'][holder_name] = has_year_list_style - info['without_c_style'][holder_name] = has_without_c_style - if has_dominant_style or has_year_list_style or has_without_c_style: - info['classified_copyrights'] = info['classified_copyrights'] + 1 - return info - -################################################################################ -# report execution -################################################################################ - -SEPARATOR = '-'.join(['' for _ in range(80)]) - -def print_filenames(filenames, verbose): - if not verbose: - return - for filename in filenames: - print("\t%s" % filename) - -def print_report(file_infos, verbose): - print(SEPARATOR) - examined = [i['filename'] for i in file_infos] - print("%d files examined according to INCLUDE and EXCLUDE fnmatch rules" % - len(examined)) - print_filenames(examined, verbose) - - print(SEPARATOR) - print('') - zero_copyrights = [i['filename'] for i in file_infos if - i['all_copyrights'] == 0] - print("%4d with zero copyrights" % len(zero_copyrights)) - print_filenames(zero_copyrights, verbose) - one_copyright = [i['filename'] for i in file_infos if - i['all_copyrights'] == 1] - print("%4d with one copyright" % len(one_copyright)) - print_filenames(one_copyright, verbose) - two_copyrights = [i['filename'] for i in file_infos if - i['all_copyrights'] == 2] - print("%4d with two copyrights" % len(two_copyrights)) - print_filenames(two_copyrights, verbose) - three_copyrights = [i['filename'] for i in file_infos if - i['all_copyrights'] == 3] - print("%4d with three copyrights" % len(three_copyrights)) - print_filenames(three_copyrights, verbose) - four_or_more_copyrights = [i['filename'] for i in file_infos if - i['all_copyrights'] >= 4] - print("%4d with four or more copyrights" % len(four_or_more_copyrights)) - print_filenames(four_or_more_copyrights, verbose) - print('') - print(SEPARATOR) - print('Copyrights with dominant style:\ne.g. "Copyright (c)" and ' - '"" or "-":\n') - for holder_name in EXPECTED_HOLDER_NAMES: - dominant_style = [i['filename'] for i in file_infos if - i['dominant_style'][holder_name]] - if len(dominant_style) > 0: - print("%4d with '%s'" % (len(dominant_style), - holder_name.replace('\n', '\\n'))) - print_filenames(dominant_style, verbose) - print('') - print(SEPARATOR) - print('Copyrights with year list style:\ne.g. "Copyright (c)" and ' - '", , ...":\n') - for holder_name in EXPECTED_HOLDER_NAMES: - year_list_style = [i['filename'] for i in file_infos if - i['year_list_style'][holder_name]] - if len(year_list_style) > 0: - print("%4d with '%s'" % (len(year_list_style), - holder_name.replace('\n', '\\n'))) - print_filenames(year_list_style, verbose) - print('') - print(SEPARATOR) - print('Copyrights with no "(c)" style:\ne.g. "Copyright" and "" or ' - '"-":\n') - for holder_name in EXPECTED_HOLDER_NAMES: - without_c_style = [i['filename'] for i in file_infos if - i['without_c_style'][holder_name]] - if len(without_c_style) > 0: - print("%4d with '%s'" % (len(without_c_style), - holder_name.replace('\n', '\\n'))) - print_filenames(without_c_style, verbose) - - print('') - print(SEPARATOR) - - unclassified_copyrights = [i['filename'] for i in file_infos if - i['classified_copyrights'] < i['all_copyrights']] - print("%d with unexpected copyright holder names" % - len(unclassified_copyrights)) - print_filenames(unclassified_copyrights, verbose) - print(SEPARATOR) - -def exec_report(base_directory, verbose): - filenames = get_filenames_to_examine(base_directory) - file_infos = [gather_file_info(f) for f in filenames] - print_report(file_infos, verbose) - -################################################################################ -# report cmd -################################################################################ - -REPORT_USAGE = """ -Produces a report of all copyright header notices found inside the source files -of a repository. - -Usage: - $ ./copyright_header.py report [verbose] - -Arguments: - - The base directory of a bitcoin source code repository. - [verbose] - Includes a list of every file of each subcategory in the report. -""" - -def report_cmd(argv): - if len(argv) == 2: - sys.exit(REPORT_USAGE) - - base_directory = argv[2] - if not os.path.exists(base_directory): - sys.exit("*** bad : %s" % base_directory) - - if len(argv) == 3: - verbose = False - elif argv[3] == 'verbose': - verbose = True - else: - sys.exit("*** unknown argument: %s" % argv[2]) - - exec_report(base_directory, verbose) - -################################################################################ -# query git for year of last change -################################################################################ - -GIT_LOG_CMD = "git log --pretty=format:%%ai %s" - -def call_git_log(filename): - out = subprocess.check_output((GIT_LOG_CMD % filename).split(' '), text=True) - return out.split('\n') - -def get_git_change_years(filename): - git_log_lines = call_git_log(filename) - if len(git_log_lines) == 0: - return [datetime.date.today().year] - # timestamp is in ISO 8601 format. e.g. "2016-09-05 14:25:32 -0600" - return [line.split(' ')[0].split('-')[0] for line in git_log_lines] - -def get_most_recent_git_change_year(filename): - return max(get_git_change_years(filename)) - -################################################################################ -# read and write to file -################################################################################ - -def read_file_lines(filename): - with open(filename, 'r') as f: - file_lines = f.readlines() - return file_lines - -def write_file_lines(filename, file_lines): - with open(filename, 'w') as f: - f.write(''.join(file_lines)) - -################################################################################ -# update header years execution -################################################################################ - -COPYRIGHT = r'Copyright \(c\)' -YEAR = "20[0-9][0-9]" -YEAR_RANGE = '(%s)(-%s)?' % (YEAR, YEAR) -HOLDER = 'The Bitcoin Core developers' -UPDATEABLE_LINE_COMPILED = re.compile(' '.join([COPYRIGHT, YEAR_RANGE, HOLDER])) - -def get_updatable_copyright_line(file_lines): - index = 0 - for line in file_lines: - if UPDATEABLE_LINE_COMPILED.search(line) is not None: - return index, line - index = index + 1 - return None, None - -def parse_year_range(year_range): - year_split = year_range.split('-') - start_year = year_split[0] - if len(year_split) == 1: - return start_year, start_year - return start_year, year_split[1] - -def year_range_to_str(start_year, end_year): - if start_year == end_year: - return start_year - return "%s-%s" % (start_year, end_year) - -def create_updated_copyright_line(line, last_git_change_year): - copyright_splitter = 'Copyright (c) ' - copyright_split = line.split(copyright_splitter) - # Preserve characters on line that are ahead of the start of the copyright - # notice - they are part of the comment block and vary from file-to-file. - before_copyright = copyright_split[0] - after_copyright = copyright_split[1] - - space_split = after_copyright.split(' ') - year_range = space_split[0] - start_year, end_year = parse_year_range(year_range) - if end_year >= last_git_change_year: - return line - return (before_copyright + copyright_splitter + - year_range_to_str(start_year, last_git_change_year) + ' ' + - ' '.join(space_split[1:])) - -def update_updatable_copyright(filename): - file_lines = read_file_lines(filename) - index, line = get_updatable_copyright_line(file_lines) - if not line: - print_file_action_message(filename, "No updatable copyright.") - return - last_git_change_year = get_most_recent_git_change_year(filename) - new_line = create_updated_copyright_line(line, last_git_change_year) - if line == new_line: - print_file_action_message(filename, "Copyright up-to-date.") - return - file_lines[index] = new_line - write_file_lines(filename, file_lines) - print_file_action_message(filename, - "Copyright updated! -> %s" % last_git_change_year) - -def exec_update_header_year(base_directory): - for filename in get_filenames_to_examine(base_directory): - update_updatable_copyright(filename) - -################################################################################ -# update cmd -################################################################################ - -UPDATE_USAGE = """ -Updates all the copyright headers of "The Bitcoin Core developers" which were -changed in a year more recent than is listed. For example: - -// Copyright (c) - The Bitcoin Core developers - -will be updated to: - -// Copyright (c) - The Bitcoin Core developers - -where is obtained from the 'git log' history. - -This subcommand also handles copyright headers that have only a single year. In those cases: - -// Copyright (c) The Bitcoin Core developers - -will be updated to: - -// Copyright (c) - The Bitcoin Core developers - -where the update is appropriate. - -Usage: - $ ./copyright_header.py update - -Arguments: - - The base directory of a bitcoin source code repository. -""" - -def print_file_action_message(filename, action): - print("%-52s %s" % (filename, action)) - -def update_cmd(argv): - if len(argv) != 3: - sys.exit(UPDATE_USAGE) - - base_directory = argv[2] - if not os.path.exists(base_directory): - sys.exit("*** bad base_directory: %s" % base_directory) - exec_update_header_year(base_directory) - -################################################################################ -# inserted copyright header format -################################################################################ - -def get_header_lines(header, start_year, end_year): - lines = header.split('\n')[1:-1] - lines[0] = lines[0] % year_range_to_str(start_year, end_year) - return [line + '\n' for line in lines] - -CPP_HEADER = ''' -// Copyright (c) %s The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -''' - -def get_cpp_header_lines_to_insert(start_year, end_year): - return reversed(get_header_lines(CPP_HEADER, start_year, end_year)) - -SCRIPT_HEADER = ''' -# Copyright (c) %s The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -''' - -def get_script_header_lines_to_insert(start_year, end_year): - return reversed(get_header_lines(SCRIPT_HEADER, start_year, end_year)) - -################################################################################ -# query git for year of last change -################################################################################ - -def get_git_change_year_range(filename): - years = get_git_change_years(filename) - return min(years), max(years) - -################################################################################ -# check for existing core copyright -################################################################################ - -def file_already_has_core_copyright(file_lines): - index, _ = get_updatable_copyright_line(file_lines) - return index is not None - -################################################################################ -# insert header execution -################################################################################ - -def file_has_hashbang(file_lines): - if len(file_lines) < 1: - return False - if len(file_lines[0]) <= 2: - return False - return file_lines[0][:2] == '#!' - -def insert_script_header(filename, file_lines, start_year, end_year): - if file_has_hashbang(file_lines): - insert_idx = 1 - else: - insert_idx = 0 - header_lines = get_script_header_lines_to_insert(start_year, end_year) - for line in header_lines: - file_lines.insert(insert_idx, line) - write_file_lines(filename, file_lines) - -def insert_cpp_header(filename, file_lines, start_year, end_year): - file_lines.insert(0, '\n') - header_lines = get_cpp_header_lines_to_insert(start_year, end_year) - for line in header_lines: - file_lines.insert(0, line) - write_file_lines(filename, file_lines) - -def exec_insert_header(filename, style): - file_lines = read_file_lines(filename) - if file_already_has_core_copyright(file_lines): - sys.exit('*** %s already has a copyright by The Bitcoin Core developers' - % (filename)) - start_year, end_year = get_git_change_year_range(filename) - if style in ['python', 'shell']: - insert_script_header(filename, file_lines, start_year, end_year) - else: - insert_cpp_header(filename, file_lines, start_year, end_year) - -################################################################################ -# insert cmd -################################################################################ - -INSERT_USAGE = """ -Inserts a copyright header for "The Bitcoin Core developers" at the top of the -file in either Python or C++ style as determined by the file extension. If the -file is a Python file and it has a '#!' starting the first line, the header is -inserted in the line below it. - -The copyright dates will be set to be: - -"-" - -where is according to the 'git log' history. If - is equal to , the date will be set to be: - -"" - -If the file already has a copyright for "The Bitcoin Core developers", the -script will exit. - -Usage: - $ ./copyright_header.py insert - -Arguments: - - A source file in the bitcoin repository. -""" - -def insert_cmd(argv): - if len(argv) != 3: - sys.exit(INSERT_USAGE) - - filename = argv[2] - if not os.path.isfile(filename): - sys.exit("*** bad filename: %s" % filename) - _, extension = os.path.splitext(filename) - if extension not in ['.h', '.cpp', '.cc', '.c', '.py', '.sh']: - sys.exit("*** cannot insert for file extension %s" % extension) - - if extension == '.py': - style = 'python' - elif extension == '.sh': - style = 'shell' - else: - style = 'cpp' - exec_insert_header(filename, style) - -################################################################################ -# UI -################################################################################ - -USAGE = """ -copyright_header.py - utilities for managing copyright headers of 'The Bitcoin -Core developers' in repository source files. - -Usage: - $ ./copyright_header - -Subcommands: - report - update - insert - -To see subcommand usage, run them without arguments. -""" - -SUBCOMMANDS = ['report', 'update', 'insert'] - -if __name__ == "__main__": - if len(sys.argv) == 1: - sys.exit(USAGE) - subcommand = sys.argv[1] - if subcommand not in SUBCOMMANDS: - sys.exit(USAGE) - if subcommand == 'report': - report_cmd(sys.argv) - elif subcommand == 'update': - update_cmd(sys.argv) - elif subcommand == 'insert': - insert_cmd(sys.argv) diff --git a/contrib/devtools/utils.py b/contrib/devtools/utils.py deleted file mode 100755 index 7f37c607..00000000 --- a/contrib/devtools/utils.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2021-present The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -''' -Common utility functions -''' -import shutil -import sys -import os - - -def determine_wellknown_cmd(envvar, progname) -> list[str]: - maybe_env = os.getenv(envvar) - maybe_which = shutil.which(progname) - if maybe_env: - return maybe_env.split(' ') # Well-known vars are often meant to be word-split - elif maybe_which: - return [ maybe_which ] - else: - sys.exit(f"{progname} not found") diff --git a/contrib/guix/guix-codesign b/contrib/guix/guix-codesign index ac7aae3a..ec8fbc0c 100755 --- a/contrib/guix/guix-codesign +++ b/contrib/guix/guix-codesign @@ -328,16 +328,6 @@ EOF # container so that we have something to build. '/bitcoin' was # chosen arbitrarily. # - # ${SOURCES_PATH:+--share="$SOURCES_PATH"} - # - # make the downloaded depends sources path available - # inside the isolated container - # - # The isolated container has no network access as it's in a - # different network namespace from the main machine, so we have to - # make the downloaded depends sources available to it. The sources - # should have been downloaded prior to this invocation. - # # ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} # # fetch substitute from SUBSTITUTE_URLS if they are @@ -359,7 +349,6 @@ EOF --share="$DETACHED_SIGS_REPO"=/detached-sigs \ --expose="$(git rev-parse --git-common-dir)" \ --expose="$(git -C "$DETACHED_SIGS_REPO" rev-parse --git-common-dir)" \ - ${SOURCES_PATH:+--share="$SOURCES_PATH"} \ --cores="$JOBS" \ --keep-failed \ --fallback \ @@ -372,7 +361,6 @@ EOF JOBS="$JOBS" \ SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \ ${V:+V=1} \ - ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \ DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \ OUTDIR="$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST" codesigned)" \ DIST_ARCHIVE_BASE=/outdir-base/dist-archive \ diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 011ba0de..ea1ffe5d 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -2,6 +2,7 @@ ((gnu packages bash) #:select (bash-minimal)) (gnu packages bison) ((gnu packages certs) #:select (nss-certs)) + ((gnu packages check) #:select (libfaketime)) ((gnu packages cmake) #:select (cmake-minimal)) (gnu packages commencement) (gnu packages compression) @@ -93,7 +94,17 @@ chain for " target " development.")) (home-page (package-home-page xgcc)) (license (package-license xgcc))))) -(define base-gcc gcc-13) ;; 13.3.0 +(define base-gcc + (package + (inherit gcc-14) ;; 14.2.0 + (version "14.3.0") + (source (origin + (method url-fetch) + (uri (string-append "mirror://gnu/gcc/gcc-" + version "/gcc-" version ".tar.xz")) + (sha256 + (base32 + "0fna78ly417g69fdm4i5f3ms96g8xzzjza8gwp41lqr5fqlpgp70")))))) (define base-linux-kernel-headers linux-libre-headers-6.1) @@ -113,7 +124,7 @@ desirable for building Bitcoin Core release binaries." (define (gcc-libgcc-patches gcc) (package-with-extra-patches gcc - (search-our-patches "gcc-remap-guix-store.patch"))) + (search-our-patches "gcc-remap-guix-store.patch" "gcc-ssa-generation.patch"))) (define (binutils-mingw-patches binutils) (package-with-extra-patches binutils @@ -208,7 +219,17 @@ and abstract ELF, PE and MachO formats.") (base32 "1j47vwq4caxfv0xw68kw5yh00qcpbd56d7rq6c483ma3y7s96yyz")))) (build-system cmake-build-system) - (inputs (list openssl)) + (arguments + (list + #:phases + #~(modify-phases %standard-phases + (replace 'check + (lambda* (#:key tests? #:allow-other-keys) + (if tests? + (invoke "faketime" "-f" "@2025-01-01 00:00:00" ;; Tests fail after 2025. + "ctest" "--output-on-failure" "--no-tests=error") + (format #t "test suite not run~%"))))))) + (inputs (list libfaketime openssl)) (home-page "https://github.com/mtrojnar/osslsigncode") (synopsis "Authenticode signing and timestamping tool") (description "osslsigncode is a small tool that implements part of the @@ -421,7 +442,9 @@ inspecting signatures in Mach-O binaries.") ;; https://gcc.gnu.org/install/configure.html (list "--enable-threads=posix", "--enable-default-ssp=yes", + "--enable-host-bind-now=yes", "--disable-gcov", + "--disable-libgomp", building-on))))))) (define-public linux-base-gcc @@ -435,9 +458,13 @@ inspecting signatures in Mach-O binaries.") (list "--enable-initfini-array=yes", "--enable-default-ssp=yes", "--enable-default-pie=yes", + "--enable-host-bind-now=yes", "--enable-standard-branch-protection=yes", "--enable-cet=yes", + "--enable-gprofng=no", "--disable-gcov", + "--disable-libgomp", + "--disable-libquadmath", "--disable-libsanitizer", building-on))) ((#:phases phases) @@ -544,7 +571,7 @@ inspecting signatures in Mach-O binaries.") gzip xz ;; Build tools - gcc-toolchain-13 + gcc-toolchain-14 cmake-minimal gnu-make ninja @@ -564,7 +591,7 @@ inspecting signatures in Mach-O binaries.") ((string-contains target "-linux-") (list bison pkg-config - (list gcc-toolchain-13 "static") + (list gcc-toolchain-14 "static") (make-bitcoin-cross-toolchain target))) ((string-contains target "darwin") (list clang-toolchain-19 diff --git a/contrib/guix/patches/gcc-ssa-generation.patch b/contrib/guix/patches/gcc-ssa-generation.patch new file mode 100644 index 00000000..2e5a6002 --- /dev/null +++ b/contrib/guix/patches/gcc-ssa-generation.patch @@ -0,0 +1,49 @@ +commit b46614ebfc57ccca8a050668ad0e8ba5968c5943 +Author: Jakub Jelinek +Date: Tue Jan 6 08:36:20 2026 +0100 + + tree-object-size: Deterministic SSA generation [PR123351] + + The order of evaluation of function arguments is unspecified in C++. + The function object_sizes_set_temp called object_sizes_set with two + calls to make_ssa_name() as arguments. Since make_ssa_name() has the + side effect of incrementing the global SSA version counter, different + architectures of the same compiler evaluated these calls in different + orders. + + This resulted in non-deterministic SSA version numbering between + x86_64 and aarch64 hosts during cross-compilation, leading to + divergent object files. + + Sequencing the calls into separate statements ensures deterministic + evaluation order. + + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123351 + https://gcc.gnu.org/pipermail/gcc-patches/2026-January/704817.html + + 2026-01-06 Jakub Jelinek + Marco Falke + + PR tree-optimization/123351 + * tree-object-size.cc (object_sizes_set_temp): Separate calls to + make_ssa_name to ensure deterministic execution order. + +diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc +index 018fbc30cbb..24e7d710371 100644 +--- a/gcc/tree-object-size.cc ++++ b/gcc/tree-object-size.cc +@@ -319,9 +319,11 @@ object_sizes_set_temp (struct object_size_info *osi, unsigned varno) + tree val = object_sizes_get (osi, varno); + + if (size_initval_p (val, osi->object_size_type)) +- object_sizes_set (osi, varno, +- make_ssa_name (sizetype), +- make_ssa_name (sizetype)); ++ { ++ val = make_ssa_name (sizetype); ++ tree wholeval = make_ssa_name (sizetype); ++ object_sizes_set (osi, varno, val, wholeval); ++ } + } + + /* Initialize OFFSET_LIMIT variable. */ diff --git a/contrib/guix/symbol-check.py b/contrib/guix/symbol-check.py index c32c1b5b..93002ddc 100755 --- a/contrib/guix/symbol-check.py +++ b/contrib/guix/symbol-check.py @@ -172,7 +172,7 @@ def check_version(max_versions, version, arch) -> bool: (lib, _, ver) = version.rpartition('_') ver = tuple([int(x) for x in ver.split('.')]) - if not lib in max_versions: + if lib not in max_versions: return False if isinstance(max_versions[lib], tuple): return ver <= max_versions[lib] diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 9b29fe71..afaaca18 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -229,7 +229,7 @@ def run(self): inExtent = BlockExtent(self.inFn, self.inF.tell(), inhdr, blk_hdr, inLen) self.hash_str = calc_hash_str(blk_hdr) - if not self.hash_str in blkmap: + if self.hash_str not in blkmap: # Because blocks can be written to files out-of-order as of 0.10, the script # may encounter blocks it doesn't know about. Treat as debug output. if settings['debug_output'] == 'true': @@ -320,7 +320,7 @@ def run(self): blkmap = mkblockmap(blkindex) # Block hash map won't be byte-reversed. Neither should the genesis hash. - if not settings['genesis'] in blkmap: + if settings['genesis'] not in blkmap: print("Genesis block not found in hashlist") else: BlockDataCopier(settings, blkindex, blkmap).run() diff --git a/contrib/verify-binaries/verify.py b/contrib/verify-binaries/verify.py index af891122..c989e8bd 100755 --- a/contrib/verify-binaries/verify.py +++ b/contrib/verify-binaries/verify.py @@ -39,8 +39,6 @@ import shutil import tempfile import textwrap -import urllib.request -import urllib.error import enum from hashlib import sha256 from pathlib import PurePath, Path @@ -116,18 +114,6 @@ def download_with_wget(remote_file, local_file): return result.returncode == 0, result.stdout.decode().rstrip() -def download_lines_with_urllib(url) -> tuple[bool, list[str]]: - """Get (success, text lines of a file) over HTTP.""" - try: - return (True, [ - line.strip().decode() for line in urllib.request.urlopen(url).readlines()]) - except urllib.error.HTTPError as e: - log.warning(f"HTTP request to {url} failed (HTTPError): {e}") - except Exception as e: - log.warning(f"HTTP request to {url} failed ({e})") - return (False, []) - - def verify_with_gpg( filename, signature_filename, @@ -148,11 +134,6 @@ def verify_with_gpg( return result.returncode, gpg_data -def remove_files(filenames): - for filename in filenames: - os.remove(filename) - - class SigData: """GPG signature data as parsed from GPG stdout.""" def __init__(self): diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index f2548677..0121f290 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -3,3 +3,4 @@ D1DBF2C4B96F2DEBF4C16654410108112E7EA81F 152812300785C96444D3334D17565732E08E5E41 6B002C6EA3F91B1B0DF0C9BC8F617F1200A6D25C 4D1B3D5ECBA1A7E05371EEBE46800E30FC748A66 +A8FC55F3B04BA3146F3492E79303B33A305224CB diff --git a/contrib/verify-commits/verify-commits.py b/contrib/verify-commits/verify-commits.py index 1af6b031..b053fbd1 100755 --- a/contrib/verify-commits/verify-commits.py +++ b/contrib/verify-commits/verify-commits.py @@ -7,6 +7,7 @@ import hashlib import logging import os +from pathlib import Path import subprocess import sys import time @@ -80,20 +81,14 @@ def main(): args = parser.parse_args() # get directory of this program and read data files - dirname = os.path.dirname(os.path.abspath(__file__)) - print("Using verify-commits data from " + dirname) - with open(dirname + "/trusted-git-root", "r") as f: - verified_root = f.read().splitlines()[0] - with open(dirname + "/trusted-sha512-root-commit", "r") as f: - verified_sha512_root = f.read().splitlines()[0] - with open(dirname + "/allow-revsig-commits", "r") as f: - revsig_allowed = f.read().splitlines() - with open(dirname + "/allow-unclean-merge-commits", "r") as f: - unclean_merge_allowed = f.read().splitlines() - with open(dirname + "/allow-incorrect-sha512-commits", "r") as f: - incorrect_sha512_allowed = f.read().splitlines() - with open(dirname + "/trusted-keys", "r") as f: - trusted_keys = f.read().splitlines() + dirname = Path(__file__).absolute().parent + print(f"Using verify-commits data from {dirname}") + verified_root = (dirname / "trusted-git-root").read_text().splitlines()[0] + verified_sha512_root = (dirname / "trusted-sha512-root-commit").read_text().splitlines()[0] + revsig_allowed = (dirname / "allow-revsig-commits").read_text().splitlines() + unclean_merge_allowed = (dirname / "allow-unclean-merge-commits").read_text().splitlines() + incorrect_sha512_allowed = (dirname / "allow-incorrect-sha512-commits").read_text().splitlines() + trusted_keys = (dirname / "trusted-keys").read_text().splitlines() # Set commit and variables current_commit = args.commit diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 312f19e2..2d027c68 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,9 +1,8 @@ package=boost -$(package)_version = 1.88.0 +$(package)_version = 1.90.0 $(package)_download_path = https://github.com/boostorg/boost/releases/download/boost-$($(package)_version) $(package)_file_name = boost-$($(package)_version)-cmake.tar.gz -$(package)_sha256_hash = dcea50f40ba1ecfc448fdf886c0165cf3e525fef2c9e3e080b9804e8117b9694 -$(package)_patches = skip_compiled_targets.patch +$(package)_sha256_hash = 913ca43d49e93d1b158c9862009add1518a4c665e7853b349a6492d158b036d4 $(package)_build_subdir = build define $(package)_set_vars @@ -16,10 +15,6 @@ define $(package)_set_vars $(package)_config_opts += -DCMAKE_DISABLE_FIND_PACKAGE_ICU=ON endef -define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/skip_compiled_targets.patch -endef - define $(package)_config_cmds $($(package)_cmake) -S .. -B . endef diff --git a/depends/packages/native_capnp.mk b/depends/packages/native_capnp.mk index a3a089d4..0cd0dcdf 100644 --- a/depends/packages/native_capnp.mk +++ b/depends/packages/native_capnp.mk @@ -1,9 +1,9 @@ package=native_capnp -$(package)_version=1.2.0 +$(package)_version=1.3.0 $(package)_download_path=https://capnproto.org/ $(package)_download_file=capnproto-c++-$($(package)_version).tar.gz $(package)_file_name=capnproto-cxx-$($(package)_version).tar.gz -$(package)_sha256_hash=ed00e44ecbbda5186bc78a41ba64a8dc4a861b5f8d4e822959b0144ae6fd42ef +$(package)_sha256_hash=098f824a495a1a837d56ae17e07b3f721ac86f8dbaf58896a389923458522108 define $(package)_set_vars $(package)_config_opts := -DBUILD_TESTING=OFF diff --git a/depends/patches/boost/skip_compiled_targets.patch b/depends/patches/boost/skip_compiled_targets.patch deleted file mode 100644 index 32b69ce6..00000000 --- a/depends/patches/boost/skip_compiled_targets.patch +++ /dev/null @@ -1,136 +0,0 @@ -cmake: Add `BOOST_TEST_HEADERS_ONLY` configuration variable - -This change allows the build to be configured to install only the -Boost.Test headers required for using the headers-only variant of the -Unit Test Framework. - -Upstream commit: 097e97820e654ead9c477b47443a545cef5d3b12 - - ---- a/libs/test/CMakeLists.txt -+++ b/libs/test/CMakeLists.txt -@@ -30,60 +30,70 @@ set(_boost_test_dependencies - Boost::utility - ) - --# Compiled targets -+option(BOOST_TEST_HEADERS_ONLY "Boost.Test: Only install headers" OFF) - --function(boost_test_add_library name) -+set(_boost_test_libraries "") - -- add_library(boost_${name} ${ARGN}) -- add_library(Boost::${name} ALIAS boost_${name}) -+if (NOT BOOST_TEST_HEADERS_ONLY) - -- target_include_directories(boost_${name} PUBLIC include) -- target_link_libraries(boost_${name} PUBLIC ${_boost_test_dependencies}) -+ # Compiled targets - -- target_compile_definitions(boost_${name} -- PUBLIC BOOST_TEST_NO_LIB -- # Source files already define BOOST_TEST_SOURCE -- # PRIVATE BOOST_TEST_SOURCE -- ) -+ function(boost_test_add_library name) - -- if(BUILD_SHARED_LIBS) -- target_compile_definitions(boost_${name} PUBLIC BOOST_TEST_DYN_LINK) -- else() -- target_compile_definitions(boost_${name} PUBLIC BOOST_TEST_STATIC_LINK) -- endif() -+ add_library(boost_${name} ${ARGN}) -+ add_library(Boost::${name} ALIAS boost_${name}) - --endfunction() -+ target_include_directories(boost_${name} PUBLIC include) -+ target_link_libraries(boost_${name} PUBLIC ${_boost_test_dependencies}) - --boost_test_add_library(prg_exec_monitor -- src/cpp_main.cpp -- src/debug.cpp -- src/execution_monitor.cpp --) -+ target_compile_definitions(boost_${name} -+ PUBLIC BOOST_TEST_NO_LIB -+ # Source files already define BOOST_TEST_SOURCE -+ # PRIVATE BOOST_TEST_SOURCE -+ ) - --set(SOURCES -- src/compiler_log_formatter.cpp -- src/debug.cpp -- src/decorator.cpp -- src/execution_monitor.cpp -- src/framework.cpp -- src/junit_log_formatter.cpp -- src/plain_report_formatter.cpp -- src/progress_monitor.cpp -- src/results_collector.cpp -- src/results_reporter.cpp -- src/test_framework_init_observer.cpp -- src/test_tools.cpp -- src/test_tree.cpp -- src/unit_test_log.cpp -- src/unit_test_main.cpp -- src/unit_test_monitor.cpp -- src/unit_test_parameters.cpp -- src/xml_log_formatter.cpp -- src/xml_report_formatter.cpp --) -+ if(BUILD_SHARED_LIBS) -+ target_compile_definitions(boost_${name} PUBLIC BOOST_TEST_DYN_LINK) -+ else() -+ target_compile_definitions(boost_${name} PUBLIC BOOST_TEST_STATIC_LINK) -+ endif() -+ -+ endfunction() - --boost_test_add_library(test_exec_monitor STATIC ${SOURCES} src/test_main.cpp) --boost_test_add_library(unit_test_framework ${SOURCES}) -+ boost_test_add_library(prg_exec_monitor -+ src/cpp_main.cpp -+ src/debug.cpp -+ src/execution_monitor.cpp -+ ) -+ -+ set(SOURCES -+ src/compiler_log_formatter.cpp -+ src/debug.cpp -+ src/decorator.cpp -+ src/execution_monitor.cpp -+ src/framework.cpp -+ src/junit_log_formatter.cpp -+ src/plain_report_formatter.cpp -+ src/progress_monitor.cpp -+ src/results_collector.cpp -+ src/results_reporter.cpp -+ src/test_framework_init_observer.cpp -+ src/test_tools.cpp -+ src/test_tree.cpp -+ src/unit_test_log.cpp -+ src/unit_test_main.cpp -+ src/unit_test_monitor.cpp -+ src/unit_test_parameters.cpp -+ src/xml_log_formatter.cpp -+ src/xml_report_formatter.cpp -+ ) -+ -+ boost_test_add_library(test_exec_monitor STATIC ${SOURCES} src/test_main.cpp) -+ boost_test_add_library(unit_test_framework ${SOURCES}) -+ -+ set(_boost_test_libraries boost_prg_exec_monitor boost_test_exec_monitor boost_unit_test_framework) -+ -+endif() - - # Header-only targets - -@@ -107,7 +117,7 @@ if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13) - - boost_install( - TARGETS -- boost_prg_exec_monitor boost_test_exec_monitor boost_unit_test_framework -+ ${_boost_test_libraries} - boost_included_prg_exec_monitor boost_included_test_exec_monitor boost_included_unit_test_framework - VERSION ${BOOST_SUPERPROJECT_VERSION} - HEADER_DIRECTORY include diff --git a/doc/bips.md b/doc/bips.md index 97645d0e..c814717a 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -73,3 +73,4 @@ BIPs that are implemented by Bitcoin Core: * [`BIP 386`](https://github.com/bitcoin/bips/blob/master/bip-0386.mediawiki): tr() Output Script Descriptors are implemented as of **v22.0** ([PR 22051](https://github.com/bitcoin/bitcoin/pull/22051)). * [`BIP 387`](https://github.com/bitcoin/bips/blob/master/bip-0387.mediawiki): Tapscript Multisig Output Script Descriptors are implemented as of **v24.0** ([PR 24043](https://github.com/bitcoin/bitcoin/pull/24043)). * [`BIP 431`](https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki): transactions with nVersion=3 are standard and treated as Topologically Restricted Until Confirmation as of **v28.0** ([PR 29496](https://github.com/bitcoin/bitcoin/pull/29496)). +* [`BIP 433`](https://github.com/bitcoin/bips/blob/master/bip-0433.mediawiki): Spending of Pay to Anchor (P2A) outputs is standard as of **v28.0** ([PR 30352](https://github.com/bitcoin/bitcoin/pull/30352)). diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index fdeafe88..4ea58795 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -1,6 +1,6 @@ # OpenBSD Build Guide -**Updated for OpenBSD [7.6](https://www.openbsd.org/76.html)** +**Updated for OpenBSD [7.8](https://www.openbsd.org/78.html)** This guide describes how to build bitcoind, command-line utilities, and GUI on OpenBSD. @@ -21,8 +21,11 @@ pkg_add sqlite3 To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`. -Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)) -and can be built from source: https://capnproto.org/install.html +Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)): + +```bash +pkg_add capnproto +``` Compile with `-DENABLE_IPC=OFF` if you do not need IPC functionality. diff --git a/doc/developer-notes.md b/doc/developer-notes.md index d17f8024..b8a16ec0 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -558,6 +558,21 @@ llvm-cov show \ The generated coverage report can be accessed at `build/coverage_report/index.html`. +### Using IWYU + +The [`include-what-you-use`](https://github.com/include-what-you-use/include-what-you-use) tool (IWYU) +helps to enforce the source code organization [policy](#source-code-organization) in this repository. + +To ensure consistency, it is recommended to run the IWYU CI job locally rather than running the tool directly. + +In some cases, IWYU might suggest headers that seem unnecessary at first glance, but are actually required. +For example, a macro may use a symbol that requires its own include. Another example is passing a string literal +to a function that accepts a `std::string` parameter. An implicit conversion occurs at the callsite using the +`std::string` constructor, which makes the corresponding header required. We accept these suggestions as is. + +Use `IWYU pragma: export` very sparingly, as this enforces transitive inclusion of headers +and undermines the specific purpose of IWYU. + ### Performance profiling with perf Profiling is a good way to get a precise idea of where time is being spent in @@ -1057,7 +1072,7 @@ Write scripts in Python or Rust rather than bash, when possible. - *Rationale*: Excluding headers because they are already indirectly included results in compilation failures when those indirect dependencies change. Furthermore, it obscures what the real code - dependencies are. + dependencies are. The [Using IWYU](#using-iwyu) section describes a tool to help enforce this. - Don't import anything into the global namespace (`using namespace ...`). Use fully specified types such as `std::string`. diff --git a/doc/policy/packages.md b/doc/policy/packages.md index d48afed4..71b1f2e4 100644 --- a/doc/policy/packages.md +++ b/doc/policy/packages.md @@ -99,14 +99,6 @@ submitted as a package. transaction (i.e. in which a replacement transaction with a higher fee cannot be signed) being rejected from the mempool when transaction volume is high and the mempool minimum feerate rises. -*Rationale*: Avoid situations in which the mempool contains non-bumped transactions below min relay -feerate (which we consider to have pay 0 fees and thus receiving free relay). While package -submission would ensure these transactions are bumped at the time of entry, it is not guaranteed -that the transaction will always be bumped. For example, a later transaction could replace the -fee-bumping child without still bumping the parent. These no-longer-bumped transactions should be -removed during a replacement, but we do not have a DoS-resistant way of removing them or enforcing a -limit on their quantity. Instead, prevent their entry into the mempool. - Implementation Note: Transactions within a package are always validated individually first, and package validation is used for the transactions that failed. Since package feerate is only calculated using transactions that are not in the mempool, this implementation detail affects the diff --git a/doc/release-notes-29415.md b/doc/release-notes-29415.md new file mode 100644 index 00000000..d5040a31 --- /dev/null +++ b/doc/release-notes-29415.md @@ -0,0 +1,14 @@ +P2P and network changes +----------------------- + +- Normally local transactions are broadcast to all connected peers with + which we do transaction relay. Now, for the `sendrawtransaction` RPC + this behavior can be changed to only do the broadcast via the Tor or + I2P networks. A new boolean option `-privatebroadcast` has been added + to enable this behavior. This improves the privacy of the transaction + originator in two aspects: + 1. Their IP address (and thus geolocation) is never known to the + recipients. + 2. If the originator sends two otherwise unrelated transactions, they + will not be linkable. This is because a separate connection is used + for broadcasting each transaction. (#29415) diff --git a/doc/release-notes-33629.md b/doc/release-notes-33629.md index 16bdf0fd..46adf220 100644 --- a/doc/release-notes-33629.md +++ b/doc/release-notes-33629.md @@ -41,3 +41,11 @@ are noted: mempool. - Chunk size and chunk fees are now also included in the output of `getmempoolentry`. + +- The "CPFP Carveout" has been removed from the mempool logic. The CPFP carveout + allowed one additional child transaction to be added to a package that's already + at its descendant limit, but only if that child has exactly one ancestor + (the package's root) and is small (no larger than 10kvB). Nothing is allowed to + bypass the cluster count limit. It is expected that smart contracting use-cases + requiring similar functionality employ TRUC transactions and sibling eviction + instead going forward. diff --git a/doc/release-notes-33819.md b/doc/release-notes-33819.md new file mode 100644 index 00000000..79ed1f70 --- /dev/null +++ b/doc/release-notes-33819.md @@ -0,0 +1,8 @@ +Mining IPC +---------- + +- The `getCoinbaseTx()` method is renamed to `getCoinbaseRawTx()` and deprecated. + IPC clients do not use the function name, so they're not affected. (#33819) +- Adds `getCoinbaseTx()` which clients should use instead of `getCoinbaseRawTx()`. It + contains all fields required to construct a coinbase transaction, and omits the + dummy output which Bitcoin Core uses internally. (#33819) diff --git a/doc/release-notes-34197.md b/doc/release-notes-34197.md new file mode 100644 index 00000000..377ca9cc --- /dev/null +++ b/doc/release-notes-34197.md @@ -0,0 +1,7 @@ +Updated RPCs +------------ + +- The `getpeerinfo` RPC no longer returns the `startingheight` field unless + the configuration option `-deprecatedrpc=startingheight` is used. The + `startingheight` field will be fully removed in the next major release. + (#34197) diff --git a/doc/release-notes/release-notes-30.1.md b/doc/release-notes/release-notes-30.1.md new file mode 100644 index 00000000..3299af4e --- /dev/null +++ b/doc/release-notes/release-notes-30.1.md @@ -0,0 +1,108 @@ +v30.1 Release Notes +=================== + +Bitcoin Core version v30.1 is now available from: + + + +This release includes new features, various bug fixes and performance +improvements, as well as updated translations. + +Please report bugs using the issue tracker at GitHub: + + + +To receive security and update notifications, please subscribe to: + + + +How to Upgrade +============== + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes in some cases), then run the +installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS) +or `bitcoind`/`bitcoin-qt` (on Linux). + +Upgrading directly from a version of Bitcoin Core that has reached its EOL is +possible, but it might take some time if the data directory needs to be migrated. Old +wallet versions of Bitcoin Core are generally supported. + +Compatibility +============== + +Bitcoin Core is supported and tested on operating systems using the +Linux Kernel 3.17+, macOS 13+, and Windows 10+. Bitcoin +Core should also work on most other Unix-like systems but is not as +frequently tested on them. It is not recommended to use Bitcoin Core on +unsupported systems. + +Notable changes +=============== + +### Wallet + +- #33528 wallet: don't consider unconfirmed TRUC coins with ancestors + +### Build + +- #33580 depends: Use `$(package)_file_name` when downloading from the fallback +- #33906 depends: Add patch for Windows11Style plugin +- #32009 contrib: turn off compression of macOS SDK to fix determinism + +### IPC + +- #33229 multiprocess: Don't require bitcoin -m argument when IPC options are used +- #33517 multiprocess: Fix high overhead from message logging +- #33519 Update libmultiprocess subtree in 30.x branch +- #33566 miner: fix empty mempool case for waitNext() +- #33676 interfaces: enable cancelling running waitNext calls + +### P2P + +- #33723 chainparams: remove dnsseed.bitcoin.dashjr-list-of-p2p-nodes.us + +### GUI + +- gui#899 qt: Modernize custom filtering +- gui#901 Add createwallet, createwalletdescriptor, and migratewallet to history filter + +### Test + +- #33612 test: change log rate limit version gate + +### Doc + +- #33630 doc: correct topology requirements in submitpackage helptext +- #33826 scripted-diff: Remove obsolete comment +- #33827 doc: Correct pkgin command usage on NetBSD + +### Misc + +- #33508 ci: fix buildx gha cache authentication on forks +- #33558 ci: Use native platform for win-cross task +- #33581 ci: Properly include $FILE_ENV in DEPENDS_HASH +- #33744 ci: Fix lint runner selection (and docker cache) +- #33996 contrib: fix manpage generation + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- Ava Chow +- Cory Fields +- Eugene Siegel +- fanquake +- glozow +- Hennadii Stepanov +- ismaelsadeeq +- MarcoFalke +- Ryan Ofsky +- SatsAndSports +- Sjors Provoost +- WakeTrainDev +- willcl-ark + +As well as to everyone that helped with translations on +[Transifex](https://explore.transifex.com/bitcoin/bitcoin/). diff --git a/doc/release-notes/release-notes-30.2.md b/doc/release-notes/release-notes-30.2.md new file mode 100644 index 00000000..888b3f91 --- /dev/null +++ b/doc/release-notes/release-notes-30.2.md @@ -0,0 +1,91 @@ +v30.2 Release Notes +=================== + +Bitcoin Core version v30.2 is now available from: + + + +This release includes new features, various bug fixes and performance +improvements, as well as updated translations. + +Please report bugs using the issue tracker at GitHub: + + + +To receive security and update notifications, please subscribe to: + + + +How to Upgrade +============== + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes in some cases), then run the +installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS) +or `bitcoind`/`bitcoin-qt` (on Linux). + +Upgrading directly from a version of Bitcoin Core that has reached its EOL is +possible, but it might take some time if the data directory needs to be migrated. Old +wallet versions of Bitcoin Core are generally supported. + +Compatibility +============== + +Bitcoin Core is supported and tested on operating systems using the +Linux Kernel 3.17+, macOS 13+, and Windows 10+. Bitcoin +Core should also work on most other Unix-like systems but is not as +frequently tested on them. It is not recommended to use Bitcoin Core on +unsupported systems. + +Notable changes +=============== + +### Wallet + +- #34156 wallet: fix unnamed legacy wallet migration failure +- #34215 wallettool: fix unnamed createfromdump failure walletsdir deletion +- #34221 test: migration, avoid backup name mismatch in default_wallet_failure + +### IPC + +- #33511 init: Fix Ctrl-C shutdown hangs during wait calls + +### Build + +- #33950 guix: reduce allowed exported symbols +- #34107 build: Update minimum required Boost version +- #34227 guix: Fix osslsigncode tests + +### Test + +- #34137 test: Avoid hard time.sleep(1) in feature_init.py +- #34226 wallet: test: Relative wallet failed migration cleanup + +### Fuzz + +- #34091 fuzz: doc: remove any mention to address_deserialize_v2 + +### Doc + +- #34182 doc: Update OpenBSD Build Guide + +### Misc + +- #34174 doc: update copyright year to 2026 + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- Ava Chow +- brunoerg +- davidgumberg +- fanquake +- furszy +- Hennadii Stepanov +- MarcoFalke +- Ryan Ofsky + +As well as to everyone that helped with translations on +[Transifex](https://explore.transifex.com/bitcoin/bitcoin/). diff --git a/src/.clang-format b/src/.clang-format index 4db09138..2b74e40b 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -142,6 +142,7 @@ LambdaBodyIndentation: Signature LineEnding: DeriveLF MacroBlockBegin: '' MacroBlockEnd: '' +MainIncludeChar: AngleBracket MaxEmptyLinesToKeep: 2 NamespaceIndentation: None ObjCBinPackProtocolList: Auto diff --git a/src/.clang-tidy b/src/.clang-tidy index 01153649..f54e07fa 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -24,6 +24,7 @@ performance-*, -performance-no-int-to-ptr, -performance-noexcept-move-constructor, -performance-unnecessary-value-param, +readability-avoid-const-params-in-decls, readability-const-return-type, readability-container-contains, readability-redundant-declaration, @@ -40,3 +41,5 @@ CheckOptions: value: false - key: bugprone-unused-return-value.CheckedReturnTypes value: '^::std::error_code$;^::std::error_condition$;^::std::errc$;^::std::expected$;^::util::Result$;^::util::Expected$' + - key: bugprone-unused-return-value.AllowCastToVoid + value: true # Can be removed with C++26 once the _ placeholder exists. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43d67f40..cf1f26c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,8 +106,7 @@ add_library(bitcoin_common STATIC EXCLUDE_FROM_ALL common/system.cpp common/url.cpp compressor.cpp - core_read.cpp - core_write.cpp + core_io.cpp deploymentinfo.cpp external_signer.cpp init/common.cpp @@ -244,6 +243,7 @@ add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL policy/rbf.cpp policy/settings.cpp policy/truc_policy.cpp + private_broadcast.cpp rest.cpp rpc/blockchain.cpp rpc/external_signer.cpp diff --git a/src/addrman.h b/src/addrman.h index 3a323014..8368e30b 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -172,7 +172,7 @@ class AddrMan * * @return A vector of randomly selected addresses from vRandom. */ - std::vector GetAddr(size_t max_addresses, size_t max_pct, std::optional network, const bool filtered = true) const; + std::vector GetAddr(size_t max_addresses, size_t max_pct, std::optional network, bool filtered = true) const; /** * Returns an information-location pair for all addresses in the selected addrman table. diff --git a/src/addrman_impl.h b/src/addrman_impl.h index f825d20b..c1716f89 100644 --- a/src/addrman_impl.h +++ b/src/addrman_impl.h @@ -135,7 +135,7 @@ class AddrManImpl std::pair Select(bool new_only, const std::unordered_set& networks) const EXCLUSIVE_LOCKS_REQUIRED(!cs); - std::vector GetAddr(size_t max_addresses, size_t max_pct, std::optional network, const bool filtered = true) const + std::vector GetAddr(size_t max_addresses, size_t max_pct, std::optional network, bool filtered = true) const EXCLUSIVE_LOCKS_REQUIRED(!cs); std::vector> GetEntries(bool from_tried) const @@ -267,7 +267,7 @@ class AddrManImpl * */ nid_type GetEntry(bool use_tried, size_t bucket, size_t position) const EXCLUSIVE_LOCKS_REQUIRED(cs); - std::vector GetAddr_(size_t max_addresses, size_t max_pct, std::optional network, const bool filtered = true) const EXCLUSIVE_LOCKS_REQUIRED(cs); + std::vector GetAddr_(size_t max_addresses, size_t max_pct, std::optional network, bool filtered = true) const EXCLUSIVE_LOCKS_REQUIRED(cs); std::vector> GetEntries_(bool from_tried) const EXCLUSIVE_LOCKS_REQUIRED(cs); diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt index e0e03b1d..50b29a14 100644 --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -84,8 +84,4 @@ if(ENABLE_WALLET) target_link_libraries(bench_bitcoin bitcoin_wallet) endif() -add_test(NAME bench_sanity_check - COMMAND bench_bitcoin -sanity-check -) - install_binary_component(bench_bitcoin INTERNAL) diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp index 4ba02242..907c7d2e 100644 --- a/src/bench/addrman.cpp +++ b/src/bench/addrman.cpp @@ -175,9 +175,9 @@ static void AddrManAddThenGood(benchmark::Bench& bench) }); } -BENCHMARK(AddrManAdd, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddrManSelect, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddrManSelectFromAlmostEmpty, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddrManSelectByNetwork, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddrManGetAddr, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddrManAddThenGood, benchmark::PriorityLevel::HIGH); +BENCHMARK(AddrManAdd); +BENCHMARK(AddrManSelect); +BENCHMARK(AddrManSelectFromAlmostEmpty); +BENCHMARK(AddrManSelectByNetwork); +BENCHMARK(AddrManGetAddr); +BENCHMARK(AddrManAddThenGood); diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index bc82d739..0be16439 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -51,6 +51,6 @@ static void Base58Decode(benchmark::Bench& bench) } -BENCHMARK(Base58Encode, benchmark::PriorityLevel::HIGH); -BENCHMARK(Base58CheckEncode, benchmark::PriorityLevel::HIGH); -BENCHMARK(Base58Decode, benchmark::PriorityLevel::HIGH); +BENCHMARK(Base58Encode); +BENCHMARK(Base58CheckEncode); +BENCHMARK(Base58Decode); diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp index 065ee9e7..c5e864ae 100644 --- a/src/bench/bech32.cpp +++ b/src/bench/bech32.cpp @@ -31,5 +31,5 @@ static void Bech32Decode(benchmark::Bench& bench) } -BENCHMARK(Bech32Encode, benchmark::PriorityLevel::HIGH); -BENCHMARK(Bech32Decode, benchmark::PriorityLevel::HIGH); +BENCHMARK(Bech32Encode); +BENCHMARK(Bech32Decode); diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 3eb99ab5..0b2ee6e3 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -5,25 +5,20 @@ #include #include // IWYU pragma: keep -#include +#include #include -#include #include #include #include #include #include -#include -#include #include -#include -#include #include +#include #include using namespace std::chrono_literals; -using util::Join; const std::function G_TEST_LOG_FUN{}; @@ -69,37 +64,15 @@ void GenerateTemplateResults(const std::vector& bench namespace benchmark { -// map a label to one or multiple priority levels -std::map map_label_priority = { - {"high", PriorityLevel::HIGH}, - {"low", PriorityLevel::LOW}, - {"all", 0xff} -}; - -std::string ListPriorities() -{ - using item_t = std::pair; - auto sort_by_priority = [](item_t a, item_t b){ return a.second < b.second; }; - std::set sorted_priorities(map_label_priority.begin(), map_label_priority.end(), sort_by_priority); - return Join(sorted_priorities, ',', [](const auto& entry){ return entry.first; }); -} - -uint8_t StringToPriority(const std::string& str) -{ - auto it = map_label_priority.find(str); - if (it == map_label_priority.end()) throw std::runtime_error(strprintf("Unknown priority level %s", str)); - return it->second; -} - BenchRunner::BenchmarkMap& BenchRunner::benchmarks() { static BenchmarkMap benchmarks_map; return benchmarks_map; } -BenchRunner::BenchRunner(std::string name, BenchFunction func, PriorityLevel level) +BenchRunner::BenchRunner(std::string name, BenchFunction func) { - benchmarks().insert(std::make_pair(name, std::make_pair(func, level))); + Assert(benchmarks().try_emplace(std::move(name), std::move(func)).second); } void BenchRunner::RunAll(const Args& args) @@ -120,12 +93,7 @@ void BenchRunner::RunAll(const Args& args) }; std::vector benchmarkResults; - for (const auto& [name, bench_func] : benchmarks()) { - const auto& [func, priority_level] = bench_func; - - if (!(priority_level & args.priority)) { - continue; - } + for (const auto& [name, func] : benchmarks()) { if (!std::regex_match(name, baseMatch, reFilter)) { continue; diff --git a/src/bench/bench.h b/src/bench/bench.h index f6c41486..f7df42a3 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -10,11 +10,9 @@ #include #include -#include #include #include #include -#include #include /* @@ -40,17 +38,7 @@ namespace benchmark { using ankerl::nanobench::Bench; -typedef std::function BenchFunction; - -enum PriorityLevel : uint8_t -{ - LOW = 1 << 0, - HIGH = 1 << 2, -}; - -// List priority labels, comma-separated and sorted by increasing priority -std::string ListPriorities(); -uint8_t StringToPriority(const std::string& str); +using BenchFunction = std::function; struct Args { bool is_list_only; @@ -60,25 +48,24 @@ struct Args { fs::path output_csv; fs::path output_json; std::string regex_filter; - uint8_t priority; std::vector setup_args; }; class BenchRunner { - // maps from "name" -> (function, priority_level) - typedef std::map> BenchmarkMap; + // maps from "name" -> function + using BenchmarkMap = std::map; static BenchmarkMap& benchmarks(); public: - BenchRunner(std::string name, BenchFunction func, PriorityLevel level); + BenchRunner(std::string name, BenchFunction func); static void RunAll(const Args& args); }; } // namespace benchmark -// BENCHMARK(foo) expands to: benchmark::BenchRunner bench_11foo("foo", foo, priority_level); -#define BENCHMARK(n, priority_level) \ - benchmark::BenchRunner PASTE2(bench_, PASTE2(__LINE__, n))(STRINGIZE(n), n, priority_level); +// BENCHMARK(foo); expands to: benchmark::BenchRunner bench_runner_foo{"foo", foo}; +#define BENCHMARK(n) \ + benchmark::BenchRunner PASTE2(bench_runner_, n) { STRINGIZE(n), n } #endif // BITCOIN_BENCH_BENCH_H diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 841d6258..987523a1 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -18,12 +18,8 @@ #include #include -using util::SplitString; - static const char* DEFAULT_BENCH_FILTER = ".*"; static constexpr int64_t DEFAULT_MIN_TIME_MS{10}; -/** Priority level default value, run "all" priority levels */ -static const std::string DEFAULT_PRIORITY{"all"}; static void SetupBenchArgs(ArgsManager& argsman) { @@ -37,8 +33,6 @@ static void SetupBenchArgs(ArgsManager& argsman) argsman.AddArg("-output-csv=", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-output-json=", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-sanity-check", "Run benchmarks for only one iteration with no output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-priority-level=", strprintf("Run benchmarks of one or multiple priority level(s) (%s), default: '%s'", - benchmark::ListPriorities(), DEFAULT_PRIORITY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); } // parses a comma separated list like "10,20,30,50" @@ -54,14 +48,6 @@ static std::vector parseAsymptote(const std::string& str) { return numbers; } -static uint8_t parsePriorityLevel(const std::string& str) { - uint8_t levels{0}; - for (const auto& level: SplitString(str, ',')) { - levels |= benchmark::StringToPriority(level); - } - return levels; -} - static std::vector parseTestSetupArgs(const ArgsManager& argsman) { // Parses unit test framework arguments supported by the benchmark framework. @@ -144,7 +130,6 @@ int main(int argc, char** argv) args.output_json = argsman.GetPathArg("-output-json"); args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER); args.sanity_check = argsman.GetBoolArg("-sanity-check", false); - args.priority = parsePriorityLevel(argsman.GetArg("-priority-level", DEFAULT_PRIORITY)); args.setup_args = parseTestSetupArgs(argsman); benchmark::BenchRunner::RunAll(args); diff --git a/src/bench/bip324_ecdh.cpp b/src/bench/bip324_ecdh.cpp index b94c2bd2..65deb8b7 100644 --- a/src/bench/bip324_ecdh.cpp +++ b/src/bench/bip324_ecdh.cpp @@ -46,4 +46,4 @@ static void BIP324_ECDH(benchmark::Bench& bench) }); } -BENCHMARK(BIP324_ECDH, benchmark::PriorityLevel::HIGH); +BENCHMARK(BIP324_ECDH); diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index 4214d635..297465be 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -69,5 +69,5 @@ static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench) }); } -BENCHMARK(AssembleBlock, benchmark::PriorityLevel::HIGH); -BENCHMARK(BlockAssemblerAddPackageTxns, benchmark::PriorityLevel::LOW); +BENCHMARK(AssembleBlock); +BENCHMARK(BlockAssemblerAddPackageTxns); diff --git a/src/bench/blockencodings.cpp b/src/bench/blockencodings.cpp index f12d22fa..3f6be56b 100644 --- a/src/bench/blockencodings.cpp +++ b/src/bench/blockencodings.cpp @@ -126,6 +126,6 @@ static void BlockEncodingLargeExtra(benchmark::Bench& bench) BlockEncodingBench(bench, 50000, 5000); } -BENCHMARK(BlockEncodingNoExtra, benchmark::PriorityLevel::HIGH); -BENCHMARK(BlockEncodingStdExtra, benchmark::PriorityLevel::HIGH); -BENCHMARK(BlockEncodingLargeExtra, benchmark::PriorityLevel::HIGH); +BENCHMARK(BlockEncodingNoExtra); +BENCHMARK(BlockEncodingStdExtra); +BENCHMARK(BlockEncodingLargeExtra); diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp index 26d15fc2..2b7315f4 100644 --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -54,4 +54,4 @@ static void CCoinsCaching(benchmark::Bench& bench) }); } -BENCHMARK(CCoinsCaching, benchmark::PriorityLevel::HIGH); +BENCHMARK(CCoinsCaching); diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp index cc029b1b..37165177 100644 --- a/src/bench/chacha20.cpp +++ b/src/bench/chacha20.cpp @@ -71,9 +71,9 @@ static void FSCHACHA20POLY1305_1MB(benchmark::Bench& bench) FSCHACHA20POLY1305(bench, BUFFER_SIZE_LARGE); } -BENCHMARK(CHACHA20_64BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(CHACHA20_256BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(CHACHA20_1MB, benchmark::PriorityLevel::HIGH); -BENCHMARK(FSCHACHA20POLY1305_64BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(FSCHACHA20POLY1305_256BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(FSCHACHA20POLY1305_1MB, benchmark::PriorityLevel::HIGH); +BENCHMARK(CHACHA20_64BYTES); +BENCHMARK(CHACHA20_256BYTES); +BENCHMARK(CHACHA20_1MB); +BENCHMARK(FSCHACHA20POLY1305_64BYTES); +BENCHMARK(FSCHACHA20POLY1305_256BYTES); +BENCHMARK(FSCHACHA20POLY1305_1MB); diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index acf29767..765b8b0d 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -60,5 +60,5 @@ static void DeserializeAndCheckBlockTest(benchmark::Bench& bench) }); } -BENCHMARK(DeserializeBlockTest, benchmark::PriorityLevel::HIGH); -BENCHMARK(DeserializeAndCheckBlockTest, benchmark::PriorityLevel::HIGH); +BENCHMARK(DeserializeBlockTest); +BENCHMARK(DeserializeAndCheckBlockTest); diff --git a/src/bench/checkblockindex.cpp b/src/bench/checkblockindex.cpp index a5c152b3..78e70a8d 100644 --- a/src/bench/checkblockindex.cpp +++ b/src/bench/checkblockindex.cpp @@ -19,4 +19,4 @@ static void CheckBlockIndex(benchmark::Bench& bench) } -BENCHMARK(CheckBlockIndex, benchmark::PriorityLevel::HIGH); +BENCHMARK(CheckBlockIndex); diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 2aa715cb..2c9126dd 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -65,4 +65,4 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::Bench& bench) control.Complete(); }); } -BENCHMARK(CCheckQueueSpeedPrevectorJob, benchmark::PriorityLevel::HIGH); +BENCHMARK(CCheckQueueSpeedPrevectorJob); diff --git a/src/bench/cluster_linearize.cpp b/src/bench/cluster_linearize.cpp index a856d247..88f8bf28 100644 --- a/src/bench/cluster_linearize.cpp +++ b/src/bench/cluster_linearize.cpp @@ -150,12 +150,12 @@ static void LinearizeOptimallyPerCost(benchmark::Bench& bench) BenchLinearizeOptimallyPerCost(bench, "LinearizeOptimallySyntheticPerCost", CLUSTERS_SYNTHETIC); } -BENCHMARK(PostLinearize16TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(PostLinearize32TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(PostLinearize48TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(PostLinearize64TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(PostLinearize75TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(PostLinearize99TxWorstCase, benchmark::PriorityLevel::HIGH); - -BENCHMARK(LinearizeOptimallyTotal, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyPerCost, benchmark::PriorityLevel::HIGH); +BENCHMARK(PostLinearize16TxWorstCase); +BENCHMARK(PostLinearize32TxWorstCase); +BENCHMARK(PostLinearize48TxWorstCase); +BENCHMARK(PostLinearize64TxWorstCase); +BENCHMARK(PostLinearize75TxWorstCase); +BENCHMARK(PostLinearize99TxWorstCase); + +BENCHMARK(LinearizeOptimallyTotal); +BENCHMARK(LinearizeOptimallyPerCost); diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index 41d01dfc..72b3d70e 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -130,12 +130,12 @@ static void BnBExhaustion(benchmark::Bench& bench) bench.run([&] { // Benchmark CAmount target = make_hard_case(17, utxo_pool); - [[maybe_unused]] auto _{SelectCoinsBnB(utxo_pool, target, /*cost_of_change=*/0, MAX_STANDARD_TX_WEIGHT)}; // Should exhaust + (void)SelectCoinsBnB(utxo_pool, target, /*cost_of_change=*/0, MAX_STANDARD_TX_WEIGHT); // Should exhaust // Cleanup utxo_pool.clear(); }); } -BENCHMARK(CoinSelection, benchmark::PriorityLevel::HIGH); -BENCHMARK(BnBExhaustion, benchmark::PriorityLevel::HIGH); +BENCHMARK(CoinSelection); +BENCHMARK(BnBExhaustion); diff --git a/src/bench/connectblock.cpp b/src/bench/connectblock.cpp index cc972966..434bcdcb 100644 --- a/src/bench/connectblock.cpp +++ b/src/bench/connectblock.cpp @@ -126,6 +126,6 @@ static void ConnectBlockAllEcdsa(benchmark::Bench& bench) BenchmarkConnectBlock(bench, keys, outputs, *test_setup); } -BENCHMARK(ConnectBlockAllSchnorr, benchmark::PriorityLevel::HIGH); -BENCHMARK(ConnectBlockMixedEcdsaSchnorr, benchmark::PriorityLevel::HIGH); -BENCHMARK(ConnectBlockAllEcdsa, benchmark::PriorityLevel::HIGH); +BENCHMARK(ConnectBlockAllSchnorr); +BENCHMARK(ConnectBlockMixedEcdsaSchnorr); +BENCHMARK(ConnectBlockAllEcdsa); diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 0fd7245b..666ff3c0 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -260,27 +260,27 @@ static void MuHashFinalize(benchmark::Bench& bench) }); } -BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA1, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_STANDARD, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_SSE4, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_AVX2, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_SHANI, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA512, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA3_256_1M, benchmark::PriorityLevel::HIGH); - -BENCHMARK(SHA256_32b_STANDARD, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_32b_SSE4, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH); -BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH); -BENCHMARK(SHA256D64_1024_SHANI, benchmark::PriorityLevel::HIGH); - -BENCHMARK(MuHash, benchmark::PriorityLevel::HIGH); -BENCHMARK(MuHashMul, benchmark::PriorityLevel::HIGH); -BENCHMARK(MuHashDiv, benchmark::PriorityLevel::HIGH); -BENCHMARK(MuHashPrecompute, benchmark::PriorityLevel::HIGH); -BENCHMARK(MuHashFinalize, benchmark::PriorityLevel::HIGH); +BENCHMARK(BenchRIPEMD160); +BENCHMARK(SHA1); +BENCHMARK(SHA256_STANDARD); +BENCHMARK(SHA256_SSE4); +BENCHMARK(SHA256_AVX2); +BENCHMARK(SHA256_SHANI); +BENCHMARK(SHA512); +BENCHMARK(SHA3_256_1M); + +BENCHMARK(SHA256_32b_STANDARD); +BENCHMARK(SHA256_32b_SSE4); +BENCHMARK(SHA256_32b_AVX2); +BENCHMARK(SHA256_32b_SHANI); +BENCHMARK(SipHash_32b); +BENCHMARK(SHA256D64_1024_STANDARD); +BENCHMARK(SHA256D64_1024_SSE4); +BENCHMARK(SHA256D64_1024_AVX2); +BENCHMARK(SHA256D64_1024_SHANI); + +BENCHMARK(MuHash); +BENCHMARK(MuHashMul); +BENCHMARK(MuHashDiv); +BENCHMARK(MuHashPrecompute); +BENCHMARK(MuHashFinalize); diff --git a/src/bench/descriptors.cpp b/src/bench/descriptors.cpp index 719e69e3..c375d312 100644 --- a/src/bench/descriptors.cpp +++ b/src/bench/descriptors.cpp @@ -35,4 +35,4 @@ static void ExpandDescriptor(benchmark::Bench& bench) }); } -BENCHMARK(ExpandDescriptor, benchmark::PriorityLevel::HIGH); +BENCHMARK(ExpandDescriptor); diff --git a/src/bench/disconnected_transactions.cpp b/src/bench/disconnected_transactions.cpp index e4c72aa5..4dd5de42 100644 --- a/src/bench/disconnected_transactions.cpp +++ b/src/bench/disconnected_transactions.cpp @@ -134,6 +134,6 @@ static void AddAndRemoveDisconnectedBlockTransactions10(benchmark::Bench& bench) }); } -BENCHMARK(AddAndRemoveDisconnectedBlockTransactionsAll, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddAndRemoveDisconnectedBlockTransactions90, benchmark::PriorityLevel::HIGH); -BENCHMARK(AddAndRemoveDisconnectedBlockTransactions10, benchmark::PriorityLevel::HIGH); +BENCHMARK(AddAndRemoveDisconnectedBlockTransactionsAll); +BENCHMARK(AddAndRemoveDisconnectedBlockTransactions90); +BENCHMARK(AddAndRemoveDisconnectedBlockTransactions10); diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 9bd7551d..5b1ca5f5 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -58,7 +58,7 @@ static void DuplicateInputs(benchmark::Bench& bench) naughtyTx.vout[0].nValue = 0; naughtyTx.vout[0].scriptPubKey = SCRIPT_PUB; - uint64_t n_inputs = (((MAX_BLOCK_SERIALIZED_SIZE / WITNESS_SCALE_FACTOR) - (CTransaction(coinbaseTx).GetTotalSize() + CTransaction(naughtyTx).GetTotalSize())) / 41) - 100; + uint64_t n_inputs = (((MAX_BLOCK_SERIALIZED_SIZE / WITNESS_SCALE_FACTOR) - (CTransaction(coinbaseTx).ComputeTotalSize() + CTransaction(naughtyTx).ComputeTotalSize())) / 41) - 100; for (uint64_t x = 0; x < (n_inputs - 1); ++x) { naughtyTx.vin.emplace_back(Txid::FromUint256(GetRandHash()), 0, CScript(), 0); } @@ -76,4 +76,4 @@ static void DuplicateInputs(benchmark::Bench& bench) }); } -BENCHMARK(DuplicateInputs, benchmark::PriorityLevel::HIGH); +BENCHMARK(DuplicateInputs); diff --git a/src/bench/ellswift.cpp b/src/bench/ellswift.cpp index 21868fb8..2daf1a9e 100644 --- a/src/bench/ellswift.cpp +++ b/src/bench/ellswift.cpp @@ -29,4 +29,4 @@ static void EllSwiftCreate(benchmark::Bench& bench) }); } -BENCHMARK(EllSwiftCreate, benchmark::PriorityLevel::HIGH); +BENCHMARK(EllSwiftCreate); diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp index 0769b80d..07c0eabd 100644 --- a/src/bench/examples.cpp +++ b/src/bench/examples.cpp @@ -18,4 +18,4 @@ static void Trig(benchmark::Bench& bench) }); } -BENCHMARK(Trig, benchmark::PriorityLevel::HIGH); +BENCHMARK(Trig); diff --git a/src/bench/gcs_filter.cpp b/src/bench/gcs_filter.cpp index d66402da..ea48592a 100644 --- a/src/bench/gcs_filter.cpp +++ b/src/bench/gcs_filter.cpp @@ -86,8 +86,8 @@ static void GCSFilterMatch(benchmark::Bench& bench) filter.Match(GCSFilter::Element()); }); } -BENCHMARK(GCSBlockFilterGetHash, benchmark::PriorityLevel::HIGH); -BENCHMARK(GCSFilterConstruct, benchmark::PriorityLevel::HIGH); -BENCHMARK(GCSFilterDecode, benchmark::PriorityLevel::HIGH); -BENCHMARK(GCSFilterDecodeSkipCheck, benchmark::PriorityLevel::HIGH); -BENCHMARK(GCSFilterMatch, benchmark::PriorityLevel::HIGH); +BENCHMARK(GCSBlockFilterGetHash); +BENCHMARK(GCSFilterConstruct); +BENCHMARK(GCSFilterDecode); +BENCHMARK(GCSFilterDecodeSkipCheck); +BENCHMARK(GCSFilterMatch); diff --git a/src/bench/hashpadding.cpp b/src/bench/hashpadding.cpp index 74047a0c..4825c5f6 100644 --- a/src/bench/hashpadding.cpp +++ b/src/bench/hashpadding.cpp @@ -26,7 +26,7 @@ static void PrePadded(benchmark::Bench& bench) }); } -BENCHMARK(PrePadded, benchmark::PriorityLevel::HIGH); +BENCHMARK(PrePadded); static void RegularPadded(benchmark::Bench& bench) { @@ -44,4 +44,4 @@ static void RegularPadded(benchmark::Bench& bench) }); } -BENCHMARK(RegularPadded, benchmark::PriorityLevel::HIGH); +BENCHMARK(RegularPadded); diff --git a/src/bench/index_blockfilter.cpp b/src/bench/index_blockfilter.cpp index eac09688..ea40b132 100644 --- a/src/bench/index_blockfilter.cpp +++ b/src/bench/index_blockfilter.cpp @@ -56,4 +56,4 @@ static void BlockFilterIndexSync(benchmark::Bench& bench) }); } -BENCHMARK(BlockFilterIndexSync, benchmark::PriorityLevel::HIGH); +BENCHMARK(BlockFilterIndexSync); diff --git a/src/bench/load_external.cpp b/src/bench/load_external.cpp index 18f21be4..3350d16a 100644 --- a/src/bench/load_external.cpp +++ b/src/bench/load_external.cpp @@ -71,4 +71,4 @@ static void LoadExternalBlockFile(benchmark::Bench& bench) fs::remove(blkfile); } -BENCHMARK(LoadExternalBlockFile, benchmark::PriorityLevel::HIGH); +BENCHMARK(LoadExternalBlockFile); diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp index 5f8834f5..27fd609a 100644 --- a/src/bench/lockedpool.cpp +++ b/src/bench/lockedpool.cpp @@ -38,4 +38,4 @@ static void BenchLockedPool(benchmark::Bench& bench) addr.clear(); } -BENCHMARK(BenchLockedPool, benchmark::PriorityLevel::HIGH); +BENCHMARK(BenchLockedPool); diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index 487ddcf3..498469dc 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -57,8 +57,8 @@ static void LogWithoutWriteToFile(benchmark::Bench& bench) }); } -BENCHMARK(LogWithDebug, benchmark::PriorityLevel::HIGH); -BENCHMARK(LogWithoutDebug, benchmark::PriorityLevel::HIGH); -BENCHMARK(LogWithThreadNames, benchmark::PriorityLevel::HIGH); -BENCHMARK(LogWithoutThreadNames, benchmark::PriorityLevel::HIGH); -BENCHMARK(LogWithoutWriteToFile, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogWithDebug); +BENCHMARK(LogWithoutDebug); +BENCHMARK(LogWithThreadNames); +BENCHMARK(LogWithoutThreadNames); +BENCHMARK(LogWithoutWriteToFile); diff --git a/src/bench/mempool_ephemeral_spends.cpp b/src/bench/mempool_ephemeral_spends.cpp index a572d945..2f89f0da 100644 --- a/src/bench/mempool_ephemeral_spends.cpp +++ b/src/bench/mempool_ephemeral_spends.cpp @@ -84,4 +84,4 @@ static void MempoolCheckEphemeralSpends(benchmark::Bench& bench) }); } -BENCHMARK(MempoolCheckEphemeralSpends, benchmark::PriorityLevel::HIGH); +BENCHMARK(MempoolCheckEphemeralSpends); diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index 7e64592d..ad3ab08a 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -144,4 +144,4 @@ static void MempoolEviction(benchmark::Bench& bench) }); } -BENCHMARK(MempoolEviction, benchmark::PriorityLevel::HIGH); +BENCHMARK(MempoolEviction); diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp index 3e83b2c2..768913ac 100644 --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -140,7 +140,7 @@ static void ComplexMemPool(benchmark::Bench& bench) // Add all transactions to the mempool. // Also store the first 10 transactions from each cluster as the - // transactions we'll "mine" in the the benchmark. + // transactions we'll "mine" in the benchmark. int tx_count = 0; for (auto& tx : transactions) { if (tx_count < 10) { @@ -208,7 +208,7 @@ static void MempoolCheck(benchmark::Bench& bench) }); } -BENCHMARK(MemPoolAncestorsDescendants, benchmark::PriorityLevel::HIGH); -BENCHMARK(MemPoolAddTransactions, benchmark::PriorityLevel::HIGH); -BENCHMARK(ComplexMemPool, benchmark::PriorityLevel::HIGH); -BENCHMARK(MempoolCheck, benchmark::PriorityLevel::HIGH); +BENCHMARK(MemPoolAncestorsDescendants); +BENCHMARK(MemPoolAddTransactions); +BENCHMARK(ComplexMemPool); +BENCHMARK(MempoolCheck); diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp index f9c933ec..17f7fa86 100644 --- a/src/bench/merkle_root.cpp +++ b/src/bench/merkle_root.cpp @@ -7,21 +7,33 @@ #include #include +#include #include static void MerkleRoot(benchmark::Bench& bench) { - FastRandomContext rng(true); - std::vector leaves; - leaves.resize(9001); - for (auto& item : leaves) { + FastRandomContext rng{/*fDeterministic=*/true}; + + std::vector hashes{}; + hashes.resize(9001); + for (auto& item : hashes) { item = rng.rand256(); } - bench.batch(leaves.size()).unit("leaf").run([&] { - bool mutation = false; - uint256 hash = ComputeMerkleRoot(std::vector(leaves), &mutation); - leaves[mutation] = hash; - }); + + constexpr uint256 expected_root{"d8d4dfd014a533bc3941b8663fa6e7f3a8707af124f713164d75b0c3179ecb08"}; + for (bool mutate : {false, true}) { + bench.name(mutate ? "MerkleRootWithMutation" : "MerkleRoot").batch(hashes.size()).unit("leaf").run([&] { + std::vector leaves; + leaves.reserve((hashes.size() + 1) & ~1ULL); // capacity rounded up to even + for (const auto& hash : hashes) { + leaves.push_back(hash); + } + + bool mutated{false}; + const uint256 root{ComputeMerkleRoot(std::move(leaves), mutate ? &mutated : nullptr)}; + assert(root == expected_root); + }); + } } -BENCHMARK(MerkleRoot, benchmark::PriorityLevel::HIGH); +BENCHMARK(MerkleRoot); diff --git a/src/bench/obfuscation.cpp b/src/bench/obfuscation.cpp index 178be56a..c7392e03 100644 --- a/src/bench/obfuscation.cpp +++ b/src/bench/obfuscation.cpp @@ -22,4 +22,4 @@ static void ObfuscationBench(benchmark::Bench& bench) }); } -BENCHMARK(ObfuscationBench, benchmark::PriorityLevel::HIGH); +BENCHMARK(ObfuscationBench); diff --git a/src/bench/parse_hex.cpp b/src/bench/parse_hex.cpp index fa08f5d8..928176bd 100644 --- a/src/bench/parse_hex.cpp +++ b/src/bench/parse_hex.cpp @@ -34,4 +34,4 @@ static void HexParse(benchmark::Bench& bench) }); } -BENCHMARK(HexParse, benchmark::PriorityLevel::HIGH); +BENCHMARK(HexParse); diff --git a/src/bench/peer_eviction.cpp b/src/bench/peer_eviction.cpp index 43d819cc..2360fb49 100644 --- a/src/bench/peer_eviction.cpp +++ b/src/bench/peer_eviction.cpp @@ -140,15 +140,15 @@ static void EvictionProtection3Networks250Candidates(benchmark::Bench& bench) // - 250 candidates is the number of peers reported by operators of busy nodes // No disadvantaged networks, with 250 eviction candidates. -BENCHMARK(EvictionProtection0Networks250Candidates, benchmark::PriorityLevel::HIGH); +BENCHMARK(EvictionProtection0Networks250Candidates); // 1 disadvantaged network (Tor) with 250 eviction candidates. -BENCHMARK(EvictionProtection1Networks250Candidates, benchmark::PriorityLevel::HIGH); +BENCHMARK(EvictionProtection1Networks250Candidates); // 2 disadvantaged networks (I2P, Tor) with 250 eviction candidates. -BENCHMARK(EvictionProtection2Networks250Candidates, benchmark::PriorityLevel::HIGH); +BENCHMARK(EvictionProtection2Networks250Candidates); // 3 disadvantaged networks (I2P/localhost/Tor) with 50/100/250 eviction candidates. -BENCHMARK(EvictionProtection3Networks050Candidates, benchmark::PriorityLevel::HIGH); -BENCHMARK(EvictionProtection3Networks100Candidates, benchmark::PriorityLevel::HIGH); -BENCHMARK(EvictionProtection3Networks250Candidates, benchmark::PriorityLevel::HIGH); +BENCHMARK(EvictionProtection3Networks050Candidates); +BENCHMARK(EvictionProtection3Networks100Candidates); +BENCHMARK(EvictionProtection3Networks250Candidates); diff --git a/src/bench/poly1305.cpp b/src/bench/poly1305.cpp index eaa7857f..e782164a 100644 --- a/src/bench/poly1305.cpp +++ b/src/bench/poly1305.cpp @@ -41,6 +41,6 @@ static void POLY1305_1MB(benchmark::Bench& bench) POLY1305(bench, BUFFER_SIZE_LARGE); } -BENCHMARK(POLY1305_64BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(POLY1305_256BYTES, benchmark::PriorityLevel::HIGH); -BENCHMARK(POLY1305_1MB, benchmark::PriorityLevel::HIGH); +BENCHMARK(POLY1305_64BYTES); +BENCHMARK(POLY1305_256BYTES); +BENCHMARK(POLY1305_1MB); diff --git a/src/bench/pool.cpp b/src/bench/pool.cpp index b31046cf..cf4ba132 100644 --- a/src/bench/pool.cpp +++ b/src/bench/pool.cpp @@ -49,5 +49,5 @@ static void PoolAllocator_StdUnorderedMapWithPoolResource(benchmark::Bench& benc BenchFillClearMap(bench, map); } -BENCHMARK(PoolAllocator_StdUnorderedMap, benchmark::PriorityLevel::HIGH); -BENCHMARK(PoolAllocator_StdUnorderedMapWithPoolResource, benchmark::PriorityLevel::HIGH); +BENCHMARK(PoolAllocator_StdUnorderedMap); +BENCHMARK(PoolAllocator_StdUnorderedMapWithPoolResource); diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp index 85ef196e..8d386ec2 100644 --- a/src/bench/prevector.cpp +++ b/src/bench/prevector.cpp @@ -116,12 +116,12 @@ static void PrevectorFillVectorIndirect(benchmark::Bench& bench) { \ Prevector##name(bench); \ } \ - BENCHMARK(Prevector##name##Nontrivial, benchmark::PriorityLevel::HIGH); \ + BENCHMARK(Prevector##name##Nontrivial); \ static void Prevector##name##Trivial(benchmark::Bench& bench) \ { \ Prevector##name(bench); \ } \ - BENCHMARK(Prevector##name##Trivial, benchmark::PriorityLevel::HIGH); + BENCHMARK(Prevector##name##Trivial); PREVECTOR_TEST(Clear) PREVECTOR_TEST(Destructor) diff --git a/src/bench/random.cpp b/src/bench/random.cpp index c2aa6685..c3ac72ea 100644 --- a/src/bench/random.cpp +++ b/src/bench/random.cpp @@ -86,20 +86,20 @@ void InsecureRandom_stdshuffle100(benchmark::Bench& bench) { BenchRandom_stdshuf } // namespace -BENCHMARK(FastRandom_rand64, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_rand32, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_randbool, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_randbits, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_randrange100, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_randrange1000, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_randrange1000000, benchmark::PriorityLevel::HIGH); -BENCHMARK(FastRandom_stdshuffle100, benchmark::PriorityLevel::HIGH); +BENCHMARK(FastRandom_rand64); +BENCHMARK(FastRandom_rand32); +BENCHMARK(FastRandom_randbool); +BENCHMARK(FastRandom_randbits); +BENCHMARK(FastRandom_randrange100); +BENCHMARK(FastRandom_randrange1000); +BENCHMARK(FastRandom_randrange1000000); +BENCHMARK(FastRandom_stdshuffle100); -BENCHMARK(InsecureRandom_rand64, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_rand32, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_randbool, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_randbits, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_randrange100, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_randrange1000, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_randrange1000000, benchmark::PriorityLevel::HIGH); -BENCHMARK(InsecureRandom_stdshuffle100, benchmark::PriorityLevel::HIGH); +BENCHMARK(InsecureRandom_rand64); +BENCHMARK(InsecureRandom_rand32); +BENCHMARK(InsecureRandom_randbool); +BENCHMARK(InsecureRandom_randbits); +BENCHMARK(InsecureRandom_randrange100); +BENCHMARK(InsecureRandom_randrange1000); +BENCHMARK(InsecureRandom_randrange1000000); +BENCHMARK(InsecureRandom_stdshuffle100); diff --git a/src/bench/readwriteblock.cpp b/src/bench/readwriteblock.cpp index d756789b..e1372a26 100644 --- a/src/bench/readwriteblock.cpp +++ b/src/bench/readwriteblock.cpp @@ -63,6 +63,6 @@ static void ReadRawBlockBench(benchmark::Bench& bench) }); } -BENCHMARK(WriteBlockBench, benchmark::PriorityLevel::HIGH); -BENCHMARK(ReadBlockBench, benchmark::PriorityLevel::HIGH); -BENCHMARK(ReadRawBlockBench, benchmark::PriorityLevel::HIGH); +BENCHMARK(WriteBlockBench); +BENCHMARK(ReadBlockBench); +BENCHMARK(ReadRawBlockBench); diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp index a9b7806e..8331eb6a 100644 --- a/src/bench/rollingbloom.cpp +++ b/src/bench/rollingbloom.cpp @@ -34,5 +34,5 @@ static void RollingBloomReset(benchmark::Bench& bench) }); } -BENCHMARK(RollingBloom, benchmark::PriorityLevel::HIGH); -BENCHMARK(RollingBloomReset, benchmark::PriorityLevel::HIGH); +BENCHMARK(RollingBloom); +BENCHMARK(RollingBloomReset); diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 0dc217ea..0e89ac78 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -70,9 +70,9 @@ static void BlockToJsonVerbosity3(benchmark::Bench& bench) BlockToJson(bench, TxVerbosity::SHOW_DETAILS_AND_PREVOUT); } -BENCHMARK(BlockToJsonVerbosity1, benchmark::PriorityLevel::HIGH); -BENCHMARK(BlockToJsonVerbosity2, benchmark::PriorityLevel::HIGH); -BENCHMARK(BlockToJsonVerbosity3, benchmark::PriorityLevel::HIGH); +BENCHMARK(BlockToJsonVerbosity1); +BENCHMARK(BlockToJsonVerbosity2); +BENCHMARK(BlockToJsonVerbosity3); static void BlockToJsonVerboseWrite(benchmark::Bench& bench) { @@ -85,4 +85,4 @@ static void BlockToJsonVerboseWrite(benchmark::Bench& bench) }); } -BENCHMARK(BlockToJsonVerboseWrite, benchmark::PriorityLevel::HIGH); +BENCHMARK(BlockToJsonVerboseWrite); diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index c710c2c8..b27a7e72 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -48,4 +48,4 @@ static void RpcMempool(benchmark::Bench& bench) }); } -BENCHMARK(RpcMempool, benchmark::PriorityLevel::HIGH); +BENCHMARK(RpcMempool); diff --git a/src/bench/sign_transaction.cpp b/src/bench/sign_transaction.cpp index f4294389..96af48c5 100644 --- a/src/bench/sign_transaction.cpp +++ b/src/bench/sign_transaction.cpp @@ -100,7 +100,7 @@ static void SignSchnorrWithNullMerkleRoot(benchmark::Bench& bench) SignSchnorrTapTweakBenchmark(bench, /*use_null_merkle_root=*/true); } -BENCHMARK(SignTransactionECDSA, benchmark::PriorityLevel::HIGH); -BENCHMARK(SignTransactionSchnorr, benchmark::PriorityLevel::HIGH); -BENCHMARK(SignSchnorrWithMerkleRoot, benchmark::PriorityLevel::HIGH); -BENCHMARK(SignSchnorrWithNullMerkleRoot, benchmark::PriorityLevel::HIGH); +BENCHMARK(SignTransactionECDSA); +BENCHMARK(SignTransactionSchnorr); +BENCHMARK(SignSchnorrWithMerkleRoot); +BENCHMARK(SignSchnorrWithNullMerkleRoot); diff --git a/src/bench/streams_findbyte.cpp b/src/bench/streams_findbyte.cpp index 9c52a72a..45e93d77 100644 --- a/src/bench/streams_findbyte.cpp +++ b/src/bench/streams_findbyte.cpp @@ -30,4 +30,4 @@ static void FindByte(benchmark::Bench& bench) assert(file.fclose() == 0); } -BENCHMARK(FindByte, benchmark::PriorityLevel::HIGH); +BENCHMARK(FindByte); diff --git a/src/bench/strencodings.cpp b/src/bench/strencodings.cpp index 38af7ad7..a0767b49 100644 --- a/src/bench/strencodings.cpp +++ b/src/bench/strencodings.cpp @@ -18,4 +18,4 @@ static void HexStrBench(benchmark::Bench& bench) }); } -BENCHMARK(HexStrBench, benchmark::PriorityLevel::HIGH); +BENCHMARK(HexStrBench); diff --git a/src/bench/txgraph.cpp b/src/bench/txgraph.cpp index 70824c2a..078f77b4 100644 --- a/src/bench/txgraph.cpp +++ b/src/bench/txgraph.cpp @@ -123,4 +123,4 @@ void BenchTxGraphTrim(benchmark::Bench& bench) static void TxGraphTrim(benchmark::Bench& bench) { BenchTxGraphTrim(bench); } -BENCHMARK(TxGraphTrim, benchmark::PriorityLevel::HIGH); +BENCHMARK(TxGraphTrim); diff --git a/src/bench/txorphanage.cpp b/src/bench/txorphanage.cpp index dd614fa3..1f94553b 100644 --- a/src/bench/txorphanage.cpp +++ b/src/bench/txorphanage.cpp @@ -262,7 +262,7 @@ static void OrphanageEraseForPeer(benchmark::Bench& bench) OrphanageEraseAll(bench, /*block_or_disconnect=*/false); } -BENCHMARK(OrphanageSinglePeerEviction, benchmark::PriorityLevel::LOW); -BENCHMARK(OrphanageMultiPeerEviction, benchmark::PriorityLevel::LOW); -BENCHMARK(OrphanageEraseForBlock, benchmark::PriorityLevel::LOW); -BENCHMARK(OrphanageEraseForPeer, benchmark::PriorityLevel::LOW); +BENCHMARK(OrphanageSinglePeerEviction); +BENCHMARK(OrphanageMultiPeerEviction); +BENCHMARK(OrphanageEraseForBlock); +BENCHMARK(OrphanageEraseForPeer); diff --git a/src/bench/util_time.cpp b/src/bench/util_time.cpp index a4f30516..bc3e3892 100644 --- a/src/bench/util_time.cpp +++ b/src/bench/util_time.cpp @@ -36,7 +36,7 @@ static void BenchTimeMillisSys(benchmark::Bench& bench) }); } -BENCHMARK(BenchTimeDeprecated, benchmark::PriorityLevel::HIGH); -BENCHMARK(BenchTimeMillis, benchmark::PriorityLevel::HIGH); -BENCHMARK(BenchTimeMillisSys, benchmark::PriorityLevel::HIGH); -BENCHMARK(BenchTimeMock, benchmark::PriorityLevel::HIGH); +BENCHMARK(BenchTimeDeprecated); +BENCHMARK(BenchTimeMillis); +BENCHMARK(BenchTimeMillisSys); +BENCHMARK(BenchTimeMock); diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 1266f6dd..e740f86c 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -87,5 +87,5 @@ static void VerifyNestedIfScript(benchmark::Bench& bench) }); } -BENCHMARK(VerifyScriptBench, benchmark::PriorityLevel::HIGH); -BENCHMARK(VerifyNestedIfScript, benchmark::PriorityLevel::HIGH); +BENCHMARK(VerifyScriptBench); +BENCHMARK(VerifyNestedIfScript); diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp index 5f3711ad..03774ef5 100644 --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -64,8 +64,8 @@ static void WalletBalanceClean(benchmark::Bench& bench) { WalletBalance(bench, / static void WalletBalanceMine(benchmark::Bench& bench) { WalletBalance(bench, /*set_dirty=*/false, /*add_mine=*/true); } static void WalletBalanceWatch(benchmark::Bench& bench) { WalletBalance(bench, /*set_dirty=*/false, /*add_mine=*/false); } -BENCHMARK(WalletBalanceDirty, benchmark::PriorityLevel::HIGH); -BENCHMARK(WalletBalanceClean, benchmark::PriorityLevel::HIGH); -BENCHMARK(WalletBalanceMine, benchmark::PriorityLevel::HIGH); -BENCHMARK(WalletBalanceWatch, benchmark::PriorityLevel::HIGH); +BENCHMARK(WalletBalanceDirty); +BENCHMARK(WalletBalanceClean); +BENCHMARK(WalletBalanceMine); +BENCHMARK(WalletBalanceWatch); } // namespace wallet diff --git a/src/bench/wallet_create.cpp b/src/bench/wallet_create.cpp index 9d3527e7..1c92bedd 100644 --- a/src/bench/wallet_create.cpp +++ b/src/bench/wallet_create.cpp @@ -60,7 +60,7 @@ static void WalletCreate(benchmark::Bench& bench, bool encrypted) static void WalletCreatePlain(benchmark::Bench& bench) { WalletCreate(bench, /*encrypted=*/false); } static void WalletCreateEncrypted(benchmark::Bench& bench) { WalletCreate(bench, /*encrypted=*/true); } -BENCHMARK(WalletCreatePlain, benchmark::PriorityLevel::LOW); -BENCHMARK(WalletCreateEncrypted, benchmark::PriorityLevel::LOW); +BENCHMARK(WalletCreatePlain); +BENCHMARK(WalletCreateEncrypted); } // namespace wallet diff --git a/src/bench/wallet_create_tx.cpp b/src/bench/wallet_create_tx.cpp index cd9ffd10..8ff1e39a 100644 --- a/src/bench/wallet_create_tx.cpp +++ b/src/bench/wallet_create_tx.cpp @@ -215,6 +215,6 @@ static void WalletCreateTxUsePresetInputsAndCoinSelection(benchmark::Bench& benc static void WalletAvailableCoins(benchmark::Bench& bench) { AvailableCoins(bench, {OutputType::BECH32M}); } -BENCHMARK(WalletCreateTxUseOnlyPresetInputs, benchmark::PriorityLevel::LOW) -BENCHMARK(WalletCreateTxUsePresetInputsAndCoinSelection, benchmark::PriorityLevel::LOW) -BENCHMARK(WalletAvailableCoins, benchmark::PriorityLevel::LOW); +BENCHMARK(WalletCreateTxUseOnlyPresetInputs); +BENCHMARK(WalletCreateTxUsePresetInputsAndCoinSelection); +BENCHMARK(WalletAvailableCoins); diff --git a/src/bench/wallet_ismine.cpp b/src/bench/wallet_ismine.cpp index aa0fd276..d26f893b 100644 --- a/src/bench/wallet_ismine.cpp +++ b/src/bench/wallet_ismine.cpp @@ -66,6 +66,6 @@ static void WalletIsMine(benchmark::Bench& bench, int num_combo = 0) static void WalletIsMineDescriptors(benchmark::Bench& bench) { WalletIsMine(bench); } static void WalletIsMineMigratedDescriptors(benchmark::Bench& bench) { WalletIsMine(bench, /*num_combo=*/2000); } -BENCHMARK(WalletIsMineDescriptors, benchmark::PriorityLevel::LOW); -BENCHMARK(WalletIsMineMigratedDescriptors, benchmark::PriorityLevel::LOW); +BENCHMARK(WalletIsMineDescriptors); +BENCHMARK(WalletIsMineMigratedDescriptors); } // namespace wallet diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp index dffc76e1..f7c78806 100644 --- a/src/bench/wallet_loading.cpp +++ b/src/bench/wallet_loading.cpp @@ -64,5 +64,5 @@ static void WalletLoadingDescriptors(benchmark::Bench& bench) }); } -BENCHMARK(WalletLoadingDescriptors, benchmark::PriorityLevel::HIGH); +BENCHMARK(WalletLoadingDescriptors); } // namespace wallet diff --git a/src/bench/wallet_migration.cpp b/src/bench/wallet_migration.cpp index f38f2165..910ad1e9 100644 --- a/src/bench/wallet_migration.cpp +++ b/src/bench/wallet_migration.cpp @@ -74,6 +74,6 @@ static void WalletMigration(benchmark::Bench& bench) }); } -BENCHMARK(WalletMigration, benchmark::PriorityLevel::LOW); +BENCHMARK(WalletMigration); } // namespace wallet diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 91c5639e..ae215c19 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -57,7 +57,7 @@ class TestValidationInterface : public ValidationInterface std::optional m_expected_valid_block = std::nullopt; - void BlockChecked(const Block block, const BlockValidationState state) override + void BlockChecked(Block block, BlockValidationStateView state) override { auto mode{state.GetValidationMode()}; switch (mode) { @@ -144,16 +144,18 @@ class TestKernelNotifications : public KernelNotifications int main(int argc, char* argv[]) { // SETUP: Argument parsing and handling - if (argc != 2) { + const bool has_regtest_flag{argc == 3 && std::string(argv[1]) == "-regtest"}; + if (argc < 2 || argc > 3 || (argc == 3 && !has_regtest_flag)) { std::cerr - << "Usage: " << argv[0] << " DATADIR" << std::endl + << "Usage: " << argv[0] << " [-regtest] DATADIR" << std::endl << "Display DATADIR information, and process hex-encoded blocks on standard input." << std::endl + << "Uses mainnet parameters by default, regtest with -regtest flag" << std::endl << std::endl << "IMPORTANT: THIS EXECUTABLE IS EXPERIMENTAL, FOR TESTING ONLY, AND EXPECTED TO" << std::endl << " BREAK IN FUTURE VERSIONS. DO NOT USE ON YOUR ACTUAL DATADIR." << std::endl; return 1; } - std::filesystem::path abs_datadir{std::filesystem::absolute(argv[1])}; + std::filesystem::path abs_datadir{std::filesystem::absolute(argv[argc-1])}; std::filesystem::create_directories(abs_datadir); btck_LoggingOptions logging_options = { @@ -169,7 +171,7 @@ int main(int argc, char* argv[]) Logger logger{std::make_unique()}; ContextOptions options{}; - ChainParams params{ChainType::MAINNET}; + ChainParams params{has_regtest_flag ? ChainType::REGTEST : ChainType::MAINNET}; options.SetChainParams(params); options.SetNotifications(std::make_shared()); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 88d0665e..724620aa 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -452,6 +452,7 @@ class NetinfoRequestHandler : public BaseRequestHandler if (conn_type == "block-relay-only") return "block"; if (conn_type == "manual" || conn_type == "feeler") return conn_type; if (conn_type == "addr-fetch") return "addr"; + if (conn_type == "private-broadcast") return "priv"; return ""; } std::string FormatServices(const UniValue& services) @@ -703,6 +704,7 @@ class NetinfoRequestHandler : public BaseRequestHandler " \"manual\" - peer we manually added using RPC addnode or the -addnode/-connect config options\n" " \"feeler\" - short-lived connection for testing addresses\n" " \"addr\" - address fetch; short-lived connection for requesting addresses\n" + " \"priv\" - private broadcast; short-lived connection for broadcasting our transactions\n" " net Network the peer connected through (\"ipv4\", \"ipv6\", \"onion\", \"i2p\", \"cjdns\", or \"npr\" (not publicly routable))\n" " serv Services offered by the peer\n" " \"n\" - NETWORK: peer can serve the full block chain\n" diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 49900482..fd528309 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -192,40 +192,44 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector< { if (header.IsNull()) return READ_STATUS_INVALID; - uint256 hash = header.GetHash(); block = header; block.vtx.resize(txn_available.size()); - unsigned int tx_missing_size = 0; size_t tx_missing_offset = 0; for (size_t i = 0; i < txn_available.size(); i++) { if (!txn_available[i]) { - if (vtx_missing.size() <= tx_missing_offset) + if (tx_missing_offset >= vtx_missing.size()) { return READ_STATUS_INVALID; + } block.vtx[i] = vtx_missing[tx_missing_offset++]; - tx_missing_size += block.vtx[i]->GetTotalSize(); - } else + } else { block.vtx[i] = std::move(txn_available[i]); + } } // Make sure we can't call FillBlock again. header.SetNull(); txn_available.clear(); - if (vtx_missing.size() != tx_missing_offset) + if (vtx_missing.size() != tx_missing_offset) { return READ_STATUS_INVALID; + } // Check for possible mutations early now that we have a seemingly good block IsBlockMutatedFn check_mutated{m_check_block_mutated_mock ? m_check_block_mutated_mock : IsBlockMutated}; - if (check_mutated(/*block=*/block, - /*check_witness_root=*/segwit_active)) { + if (check_mutated(/*block=*/block, /*check_witness_root=*/segwit_active)) { return READ_STATUS_FAILED; // Possible Short ID collision } - LogDebug(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %u txn prefilled, %u txn from mempool (incl at least %u from extra pool) and %u txn (%u bytes) requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size(), tx_missing_size); - if (vtx_missing.size() < 5) { - for (const auto& tx : vtx_missing) { - LogDebug(BCLog::CMPCTBLOCK, "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString()); + if (LogAcceptCategory(BCLog::CMPCTBLOCK, BCLog::Level::Debug)) { + const uint256 hash{block.GetHash()}; + uint32_t tx_missing_size{0}; + for (const auto& tx : vtx_missing) tx_missing_size += tx->ComputeTotalSize(); + LogDebug(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %u txn prefilled, %u txn from mempool (incl at least %u from extra pool) and %u txn (%u bytes) requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size(), tx_missing_size); + if (vtx_missing.size() < 5) { + for (const auto& tx : vtx_missing) { + LogDebug(BCLog::CMPCTBLOCK, "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString()); + } } } diff --git a/src/chain.cpp b/src/chain.cpp index 64ea44bb..46a51ac8 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -118,12 +118,12 @@ void CBlockIndex::BuildSkip() pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); } -arith_uint256 GetBlockProof(const CBlockIndex& block) +arith_uint256 GetBitsProof(uint32_t bits) { arith_uint256 bnTarget; bool fNegative; bool fOverflow; - bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); + bnTarget.SetCompact(bits, &fNegative, &fOverflow); if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 diff --git a/src/chain.h b/src/chain.h index 466276c0..eb4ff719 100644 --- a/src/chain.h +++ b/src/chain.h @@ -299,7 +299,15 @@ class CBlockIndex CBlockIndex& operator=(CBlockIndex&&) = delete; }; -arith_uint256 GetBlockProof(const CBlockIndex& block); +/** Compute how much work an nBits value corresponds to. */ +arith_uint256 GetBitsProof(uint32_t bits); + +/** Compute how much work a block index entry corresponds to. */ +inline arith_uint256 GetBlockProof(const CBlockIndex& block) { return GetBitsProof(block.nBits); } + +/** Compute how much work a block header corresponds to. */ +inline arith_uint256 GetBlockProof(const CBlockHeader& header) { return GetBitsProof(header.nBits); } + /** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&); /** Find the forking point between two chain tips. */ diff --git a/src/chainparams.h b/src/chainparams.h index 571e9e17..732949e8 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -15,7 +15,7 @@ class ArgsManager; /** * Creates and returns a std::unique_ptr of the chosen chain. */ -std::unique_ptr CreateChainParams(const ArgsManager& args, const ChainType chain); +std::unique_ptr CreateChainParams(const ArgsManager& args, ChainType chain); /** * Return the currently selected parameters. This won't change after app @@ -26,6 +26,6 @@ const CChainParams &Params(); /** * Sets the params returned by Params() to those for the given chain type. */ -void SelectParams(const ChainType chain); +void SelectParams(ChainType chain); #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 37e69b32..1407f196 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -35,7 +35,7 @@ class CBaseChainParams /** * Creates and returns a std::unique_ptr of the chosen chain. */ -std::unique_ptr CreateBaseChainParams(const ChainType chain); +std::unique_ptr CreateBaseChainParams(ChainType chain); /** *Set the arguments for chainparams @@ -49,7 +49,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman); const CBaseChainParams& BaseParams(); /** Sets the params returned by Params() to those for the given chain. */ -void SelectBaseParams(const ChainType chain); +void SelectBaseParams(ChainType chain); /** List of possible chain / network names */ #define LIST_CHAIN_NAMES "main, test, testnet4, signet, regtest" diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h index d65e61d4..8be16625 100644 --- a/src/cluster_linearize.h +++ b/src/cluster_linearize.h @@ -38,7 +38,7 @@ class DepGraph /** All descendants of the transaction (including itself). */ SetType descendants; - /** Equality operator (primarily for for testing purposes). */ + /** Equality operator (primarily for testing purposes). */ friend bool operator==(const Entry&, const Entry&) noexcept = default; /** Construct an empty entry. */ @@ -479,7 +479,7 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: * feerate, each individually sorted in an arbitrary but topological (= no child before parent) * way. * - * We define three quality properties the state can have, each being stronger than the previous: + * We define four quality properties the state can have: * * - acyclic: The state is acyclic whenever no cycle of active dependencies exists within the * graph, ignoring the parent/child direction. This is equivalent to saying that within @@ -529,7 +529,19 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: * satisfied. Thus, the state being optimal is more a "the eventual output is *known* * to be optimal". * - * The algorithm terminates whenever an optimal state is reached. + * - minimal: We say the state is minimal when it is: + * - acyclic + * - topological, except that inactive dependencies between equal-feerate chunks are + * allowed as long as they do not form a loop. + * - like optimal, no active dependencies whose top feerate is strictly higher than + * the bottom feerate are allowed. + * - no chunk contains a proper non-empty subset which includes all its own in-chunk + * dependencies of the same feerate as the chunk itself. + * + * A minimal state effectively corresponds to an optimal state, where every chunk has + * been split into its minimal equal-feerate components. + * + * The algorithm terminates whenever a minimal state is reached. * * * This leads to the following high-level algorithm: @@ -539,6 +551,10 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: * - Loop until optimal (no dependencies with higher-feerate top than bottom), or time runs out: * - Deactivate a violating dependency, potentially making the state non-topological. * - Activate other dependencies to make the state topological again. + * - If there is time left and the state is optimal: + * - Attempt to split chunks into equal-feerate parts without mutual dependencies between them. + * When this succeeds, recurse into them. + * - If no such chunks can be found, the state is minimal. * - Output the chunks from high to low feerate, each internally sorted topologically. * * When merging, we always either: @@ -558,6 +574,7 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: * - Deactivate D, causing the chunk it is in to split into top T and bottom B. * - Do an upwards merge of T, if possible. If so, repeat the same with the merged result. * - Do a downwards merge of B, if possible. If so, repeat the same with the merged result. + * - Split chunks further to obtain a minimal state, see below. * - Output the chunks from high to low feerate, each internally sorted topologically. * * Instead of performing merges arbitrarily to make the initial state topological, it is possible @@ -569,6 +586,21 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: * - Do an upwards merge of C, if possible. If so, repeat the same with the merged result. * No downwards merges are needed in this case. * + * After reaching an optimal state, it can be transformed into a minimal state by attempting to + * split chunks further into equal-feerate parts. To do so, pick a specific transaction in each + * chunk (the pivot), and rerun the above split-then-merge procedure again: + * - first, while pretending the pivot transaction has an infinitesimally higher (or lower) fee + * than it really has. If a split exists with the pivot in the top part (or bottom part), this + * will find it. + * - if that fails to split, repeat while pretending the pivot transaction has an infinitesimally + * lower (or higher) fee. If a split exists with the pivot in the bottom part (or top part), this + * will find it. + * - if either succeeds, repeat the procedure for the newly found chunks to split them further. + * If not, the chunk is already minimal. + * If the chunk can be split into equal-feerate parts, then the pivot must exist in either the top + * or bottom part of that potential split. By trying both with the same pivot, if a split exists, + * it will be found. + * * What remains to be specified are a number of heuristics: * * - How to decide which chunks to merge: @@ -644,10 +676,30 @@ class SpanningForestState std::vector m_dep_data; /** A FIFO of chunk representatives of chunks that may be improved still. */ VecDeque m_suboptimal_chunks; + /** A FIFO of chunk representatives with a pivot transaction in them, and a flag to indicate + * their status: + * - bit 1: currently attempting to move the pivot down, rather than up. + * - bit 2: this is the second stage, so we have already tried moving the pivot in the other + * direction. + */ + VecDeque> m_nonminimal_chunks; /** The number of updated transactions in activations/deactivations. */ uint64_t m_cost{0}; + /** Pick a random transaction within a set (which must be non-empty). */ + TxIdx PickRandomTx(const SetType& tx_idxs) noexcept + { + Assume(tx_idxs.Any()); + unsigned pos = m_rng.randrange(tx_idxs.Count()); + for (auto tx_idx : tx_idxs) { + if (pos == 0) return tx_idx; + --pos; + } + Assume(false); + return TxIdx(-1); + } + /** Update a chunk: * - All transactions have their chunk representative set to `chunk_rep`. * - All dependencies which have `query` in their top_setinfo get `dep_change` added to it @@ -769,8 +821,9 @@ class SpanningForestState /*chunk_rep=*/bottom_rep, /*dep_change=*/top_part); } - /** Activate a dependency from the chunk represented by bottom_rep to the chunk represented by - * top_rep, which must exist. Return the representative of the merged chunk. */ + /** Activate a dependency from the chunk represented by bottom_idx to the chunk represented by + * top_idx. Return the representative of the merged chunk, or TxIdx(-1) if no merge is + * possible. */ TxIdx MergeChunks(TxIdx top_rep, TxIdx bottom_rep) noexcept { auto& top_chunk = m_tx_data[top_rep]; @@ -783,7 +836,7 @@ class SpanningForestState auto& tx_data = m_tx_data[tx]; num_deps += (tx_data.children & bottom_chunk.chunk_setinfo.transactions).Count(); } - Assume(num_deps > 0); + if (num_deps == 0) return TxIdx(-1); // Uniformly randomly pick one of them and activate it. TxIdx pick = m_rng.randrange(num_deps); for (auto tx : top_chunk.chunk_setinfo.transactions) { @@ -1068,6 +1121,119 @@ class SpanningForestState return false; } + /** Initialize data structure for minimizing the chunks. Can only be called if state is known + * to be optimal. OptimizeStep() cannot be called anymore afterwards. */ + void StartMinimizing() noexcept + { + m_nonminimal_chunks.clear(); + m_nonminimal_chunks.reserve(m_transaction_idxs.Count()); + // Gather all chunks, and for each, add it with a random pivot in it, and a random initial + // direction, to m_nonminimal_chunks. + for (auto tx : m_transaction_idxs) { + auto& tx_data = m_tx_data[tx]; + if (tx_data.chunk_rep == tx) { + TxIdx pivot_idx = PickRandomTx(tx_data.chunk_setinfo.transactions); + m_nonminimal_chunks.emplace_back(tx, pivot_idx, m_rng.randbits<1>()); + // Randomize the initial order of nonminimal chunks in the queue. + TxIdx j = m_rng.randrange(m_nonminimal_chunks.size()); + if (j != m_nonminimal_chunks.size() - 1) { + std::swap(m_nonminimal_chunks.back(), m_nonminimal_chunks[j]); + } + } + } + } + + /** Try to reduce a chunk's size. Returns false if all chunks are minimal, true otherwise. */ + bool MinimizeStep() noexcept + { + // If the queue of potentially-non-minimal chunks is empty, we are done. + if (m_nonminimal_chunks.empty()) return false; + // Pop an entry from the potentially-non-minimal chunk queue. + auto [chunk_rep, pivot_idx, flags] = m_nonminimal_chunks.front(); + m_nonminimal_chunks.pop_front(); + auto& chunk_data = m_tx_data[chunk_rep]; + Assume(chunk_data.chunk_rep == chunk_rep); + /** Whether to move the pivot down rather than up. */ + bool move_pivot_down = flags & 1; + /** Whether this is already the second stage. */ + bool second_stage = flags & 2; + + // Find a random dependency whose top and bottom set feerates are equal, and which has + // pivot in bottom set (if move_pivot_down) or in top set (if !move_pivot_down). + DepIdx candidate_dep = DepIdx(-1); + uint64_t candidate_tiebreak{0}; + bool have_any = false; + // Iterate over all transactions. + for (auto tx_idx : chunk_data.chunk_setinfo.transactions) { + const auto& tx_data = m_tx_data[tx_idx]; + // Iterate over all active child dependencies of the transaction. + for (auto dep_idx : tx_data.child_deps) { + auto& dep_data = m_dep_data[dep_idx]; + // Skip inactive child dependencies. + if (!dep_data.active) continue; + // Skip if this dependency does not have equal top and bottom set feerates. Note + // that the top cannot have higher feerate than the bottom, or OptimizeSteps would + // have dealt with it. + if (dep_data.top_setinfo.feerate << chunk_data.chunk_setinfo.feerate) continue; + have_any = true; + // Skip if this dependency does not have pivot in the right place. + if (move_pivot_down == dep_data.top_setinfo.transactions[pivot_idx]) continue; + // Remember this as our chosen dependency if it has a better tiebreak. + uint64_t tiebreak = m_rng.rand64() | 1; + if (tiebreak > candidate_tiebreak) { + candidate_tiebreak = tiebreak; + candidate_dep = dep_idx; + } + } + } + // If no dependencies have equal top and bottom set feerate, this chunk is minimal. + if (!have_any) return true; + // If all found dependencies have the pivot in the wrong place, try moving it in the other + // direction. If this was the second stage already, we are done. + if (candidate_tiebreak == 0) { + // Switch to other direction, and to second phase. + flags ^= 3; + if (!second_stage) m_nonminimal_chunks.emplace_back(chunk_rep, pivot_idx, flags); + return true; + } + + // Otherwise, deactivate the dependency that was found. + Deactivate(candidate_dep); + auto& dep_data = m_dep_data[candidate_dep]; + auto parent_chunk_rep = m_tx_data[dep_data.parent].chunk_rep; + auto child_chunk_rep = m_tx_data[dep_data.child].chunk_rep; + // Try to activate a dependency between the new bottom and the new top (opposite from the + // dependency that was just deactivated). + auto merged_chunk_rep = MergeChunks(child_chunk_rep, parent_chunk_rep); + if (merged_chunk_rep != TxIdx(-1)) { + // A self-merge happened. + // Re-insert the chunk into the queue, in the same direction. Note that the chunk_rep + // will have changed. + m_nonminimal_chunks.emplace_back(merged_chunk_rep, pivot_idx, flags); + } else { + // No self-merge happens, and thus we have found a way to split the chunk. Create two + // smaller chunks, and add them to the queue. The one that contains the current pivot + // gets to continue with it in the same direction, to minimize the number of times we + // alternate direction. If we were in the second phase already, the newly created chunk + // inherits that too, because we know no split with the pivot on the other side is + // possible already. The new chunk without the current pivot gets a new randomly-chosen + // one. + if (move_pivot_down) { + auto parent_pivot_idx = PickRandomTx(m_tx_data[parent_chunk_rep].chunk_setinfo.transactions); + m_nonminimal_chunks.emplace_back(parent_chunk_rep, parent_pivot_idx, m_rng.randbits<1>()); + m_nonminimal_chunks.emplace_back(child_chunk_rep, pivot_idx, flags); + } else { + auto child_pivot_idx = PickRandomTx(m_tx_data[child_chunk_rep].chunk_setinfo.transactions); + m_nonminimal_chunks.emplace_back(parent_chunk_rep, pivot_idx, flags); + m_nonminimal_chunks.emplace_back(child_chunk_rep, child_pivot_idx, m_rng.randbits<1>()); + } + if (m_rng.randbool()) { + std::swap(m_nonminimal_chunks.back(), m_nonminimal_chunks[m_nonminimal_chunks.size() - 2]); + } + } + return true; + } + /** Construct a topologically-valid linearization from the current forest state. Must be * topological. */ std::vector GetLinearization() noexcept @@ -1182,6 +1348,10 @@ class SpanningForestState * After an OptimizeStep(), the diagram will always be at least as good as before. Once * OptimizeStep() returns false, the diagram will be equivalent to that produced by * GetLinearization(), and optimal. + * + * After a MinimizeStep(), the diagram cannot change anymore (in the CompareChunks() sense), + * but its number of segments can increase still. Once MinimizeStep() returns false, the number + * of chunks of the produced linearization will match the number of segments in the diagram. */ std::vector GetDiagram() const noexcept { @@ -1328,6 +1498,19 @@ class SpanningForestState auto tx_idx = m_suboptimal_chunks[i]; assert(m_transaction_idxs[tx_idx]); } + + // + // Verify m_nonminimal_chunks. + // + SetType nonminimal_reps; + for (size_t i = 0; i < m_nonminimal_chunks.size(); ++i) { + auto [chunk_rep, pivot, flags] = m_nonminimal_chunks[i]; + assert(m_tx_data[chunk_rep].chunk_rep == chunk_rep); + assert(m_tx_data[pivot].chunk_rep == chunk_rep); + assert(!nonminimal_reps[chunk_rep]); + nonminimal_reps.Set(chunk_rep); + } + assert(nonminimal_reps.IsSubsetOf(m_transaction_idxs)); } }; @@ -1338,32 +1521,42 @@ class SpanningForestState * @param[in] rng_seed A random number seed to control search order. This prevents peers * from predicting exactly which clusters would be hard for us to * linearize. - * @param[in] old_linearization An existing linearization for the cluster (which must be - * topologically valid), or empty. + * @param[in] old_linearization An existing linearization for the cluster, or empty. + * @param[in] is_topological (Only relevant if old_linearization is not empty) Whether + * old_linearization is topologically valid. * @return A tuple of: * - The resulting linearization. It is guaranteed to be at least as * good (in the feerate diagram sense) as old_linearization. * - A boolean indicating whether the result is guaranteed to be - * optimal. + * optimal with minimal chunks. * - How many optimization steps were actually performed. */ template -std::tuple, bool, uint64_t> Linearize(const DepGraph& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span old_linearization = {}) noexcept +std::tuple, bool, uint64_t> Linearize(const DepGraph& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span old_linearization = {}, bool is_topological = true) noexcept { /** Initialize a spanning forest data structure for this cluster. */ SpanningForestState forest(depgraph, rng_seed); if (!old_linearization.empty()) { forest.LoadLinearization(old_linearization); + if (!is_topological) forest.MakeTopological(); } else { forest.MakeTopological(); } // Make improvement steps to it until we hit the max_iterations limit, or an optimal result // is found. - bool optimal = false; if (forest.GetCost() < max_iterations) { forest.StartOptimizing(); do { - if (!forest.OptimizeStep()) { + if (!forest.OptimizeStep()) break; + } while (forest.GetCost() < max_iterations); + } + // Make chunk minimization steps until we hit the max_iterations limit, or all chunks are + // minimal. + bool optimal = false; + if (forest.GetCost() < max_iterations) { + forest.StartMinimizing(); + do { + if (!forest.MinimizeStep()) { optimal = true; break; } @@ -1573,38 +1766,6 @@ void PostLinearize(const DepGraph& depgraph, std::span l } } -/** Make linearization topological, retaining its ordering where possible. */ -template -void FixLinearization(const DepGraph& depgraph, std::span linearization) noexcept -{ - // This algorithm can be summarized as moving every element in the linearization backwards - // until it is placed after all its ancestors. - SetType done; - const auto len = linearization.size(); - // Iterate over the elements of linearization from back to front (i is distance from back). - for (DepGraphIndex i = 0; i < len; ++i) { - /** The element at that position. */ - DepGraphIndex elem = linearization[len - 1 - i]; - /** j represents how far from the back of the linearization elem should be placed. */ - DepGraphIndex j = i; - // Figure out which elements need to be moved before elem. - SetType place_before = done & depgraph.Ancestors(elem); - // Find which position to place elem in (updating j), continuously moving the elements - // in between forward. - while (place_before.Any()) { - // j cannot be 0 here; if it was, then there was necessarily nothing earlier which - // elem needs to be placed before anymore, and place_before would be empty. - Assume(j > 0); - auto to_swap = linearization[len - 1 - (j - 1)]; - place_before.Reset(to_swap); - linearization[len - 1 - (j--)] = to_swap; - } - // Put elem in its final position and mark it as done. - linearization[len - 1 - j] = elem; - done.Set(elem); - } -} - } // namespace cluster_linearize #endif // BITCOIN_CLUSTER_LINEARIZE_H diff --git a/src/coins.cpp b/src/coins.cpp index 14381ecb..7f2ffc38 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -16,7 +16,11 @@ TRACEPOINT_SEMAPHORE(utxocache, uncache); std::optional CCoinsView::GetCoin(const COutPoint& outpoint) const { return std::nullopt; } uint256 CCoinsView::GetBestBlock() const { return uint256(); } std::vector CCoinsView::GetHeadBlocks() const { return std::vector(); } -bool CCoinsView::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) { return false; } +void CCoinsView::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) +{ + for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { } +} + std::unique_ptr CCoinsView::Cursor() const { return nullptr; } bool CCoinsView::HaveCoin(const COutPoint &outpoint) const @@ -30,7 +34,7 @@ bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base-> uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); } std::vector CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); } void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } -bool CCoinsViewBacked::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) { return base->BatchWrite(cursor, hashBlock); } +void CCoinsViewBacked::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) { base->BatchWrite(cursor, hashBlock); } std::unique_ptr CCoinsViewBacked::Cursor() const { return base->Cursor(); } size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); } @@ -183,7 +187,8 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { hashBlock = hashBlockIn; } -bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlockIn) { +void CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlockIn) +{ for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries continue; @@ -246,33 +251,27 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha } } hashBlock = hashBlockIn; - return true; } -bool CCoinsViewCache::Flush(bool will_reuse_cache) { +void CCoinsViewCache::Flush(bool will_reuse_cache) +{ auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/true)}; - bool fOk = base->BatchWrite(cursor, hashBlock); - if (fOk) { - cacheCoins.clear(); - if (will_reuse_cache) { - ReallocateCache(); - } - cachedCoinsUsage = 0; + base->BatchWrite(cursor, hashBlock); + cacheCoins.clear(); + if (will_reuse_cache) { + ReallocateCache(); } - return fOk; + cachedCoinsUsage = 0; } -bool CCoinsViewCache::Sync() +void CCoinsViewCache::Sync() { auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/false)}; - bool fOk = base->BatchWrite(cursor, hashBlock); - if (fOk) { - if (m_sentinel.second.Next() != &m_sentinel) { - /* BatchWrite must clear flags of all entries */ - throw std::logic_error("Not all unspent flagged entries were cleared"); - } + base->BatchWrite(cursor, hashBlock); + if (m_sentinel.second.Next() != &m_sentinel) { + /* BatchWrite must clear flags of all entries */ + throw std::logic_error("Not all unspent flagged entries were cleared"); } - return fOk; } void CCoinsViewCache::Uncache(const COutPoint& hash) diff --git a/src/coins.h b/src/coins.h index 8d07f7fe..6da53829 100644 --- a/src/coins.h +++ b/src/coins.h @@ -324,7 +324,7 @@ class CCoinsView //! Do a bulk modification (multiple Coin changes + BestBlock change). //! The passed cursor is used to iterate through the coins. - virtual bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock); + virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock); //! Get a cursor to iterate over the whole state virtual std::unique_ptr Cursor() const; @@ -350,7 +350,7 @@ class CCoinsViewBacked : public CCoinsView uint256 GetBestBlock() const override; std::vector GetHeadBlocks() const override; void SetBackend(CCoinsView &viewIn); - bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) override; + void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override; std::unique_ptr Cursor() const override; size_t EstimateSize() const override; }; @@ -389,7 +389,7 @@ class CCoinsViewCache : public CCoinsViewBacked bool HaveCoin(const COutPoint &outpoint) const override; uint256 GetBestBlock() const override; void SetBestBlock(const uint256 &hashBlock); - bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) override; + void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override; std::unique_ptr Cursor() const override { throw std::logic_error("CCoinsViewCache cursor iteration not supported."); } @@ -441,18 +441,16 @@ class CCoinsViewCache : public CCoinsViewBacked * to be forgotten. * If will_reuse_cache is false, the cache will retain the same memory footprint * after flushing and should be destroyed to deallocate. - * If false is returned, the state of this cache (and its backing view) will be undefined. */ - bool Flush(bool will_reuse_cache = true); + void Flush(bool will_reuse_cache = true); /** * Push the modifications applied to this cache to its base while retaining * the contents of this cache (except for spent coins, which we erase). * Failure to call this method or Flush() before destruction will cause the changes * to be forgotten. - * If false is returned, the state of this cache (and its backing view) will be undefined. */ - bool Sync(); + void Sync(); /** * Removes the UTXO with the given outpoint from the cache, if it is diff --git a/src/common/bloom.h b/src/common/bloom.h index bff96a23..97007e1f 100644 --- a/src/common/bloom.h +++ b/src/common/bloom.h @@ -61,7 +61,7 @@ class CBloomFilter * It should generally always be a random value (and is largely only exposed for unit testing) * nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK) */ - CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn); + CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn); CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {} SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); } @@ -108,7 +108,7 @@ class CBloomFilter class CRollingBloomFilter { public: - CRollingBloomFilter(const unsigned int nElements, const double nFPRate); + CRollingBloomFilter(unsigned int nElements, double nFPRate); void insert(std::span vKey); bool contains(std::span vKey) const; diff --git a/src/common/messages.h b/src/common/messages.h index 4cabdc79..60fdaa18 100644 --- a/src/common/messages.h +++ b/src/common/messages.h @@ -31,7 +31,7 @@ std::string FeeModeInfo(std::pair& mode); std::string FeeModesDetail(std::string default_info); std::string InvalidEstimateModeErrorMessage(); bilingual_str PSBTErrorString(PSBTError error); -bilingual_str TransactionErrorString(const node::TransactionError error); +bilingual_str TransactionErrorString(node::TransactionError error); bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind); bilingual_str InvalidPortErrMsg(const std::string& optname, const std::string& strPort); bilingual_str AmountHighWarn(const std::string& optname); diff --git a/src/common/signmessage.h b/src/common/signmessage.h index 4533875a..c2152f35 100644 --- a/src/common/signmessage.h +++ b/src/common/signmessage.h @@ -72,6 +72,6 @@ bool MessageSign( */ uint256 MessageHash(const std::string& message); -std::string SigningResultString(const SigningResult res); +std::string SigningResultString(SigningResult res); #endif // BITCOIN_COMMON_SIGNMESSAGE_H diff --git a/src/compat/compat.h b/src/compat/compat.h index b7fe6b98..3f0e1276 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -38,6 +38,18 @@ typedef u_short sa_family_t; #endif +// Brace style in the IN6ADDR_*_INIT macros differs across platforms. +#if defined(__illumos__) +#define COMPAT_IN6ADDR_ANY_INIT {{IN6ADDR_ANY_INIT}} +#else +#define COMPAT_IN6ADDR_ANY_INIT IN6ADDR_ANY_INIT +#endif +#if defined(__illumos__) || defined(_MSC_VER) +#define COMPAT_IN6ADDR_LOOPBACK_INIT {{IN6ADDR_LOOPBACK_INIT}} +#else +#define COMPAT_IN6ADDR_LOOPBACK_INIT IN6ADDR_LOOPBACK_INIT +#endif + // We map Linux / BSD error functions and codes, to the equivalent // Windows definitions, and use the WSA* names throughout our code. // Note that glibc defines EWOULDBLOCK as EAGAIN (see errno.h). diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 84ff352d..c6ae81c6 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -66,9 +66,9 @@ uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated) { uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) { std::vector leaves; - leaves.resize(block.vtx.size()); + leaves.reserve((block.vtx.size() + 1) & ~1ULL); // capacity rounded up to even for (size_t s = 0; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetHash().ToUint256(); + leaves.push_back(block.vtx[s]->GetHash().ToUint256()); } return ComputeMerkleRoot(std::move(leaves), mutated); } @@ -76,10 +76,10 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) uint256 BlockWitnessMerkleRoot(const CBlock& block) { std::vector leaves; - leaves.resize(block.vtx.size()); - leaves[0].SetNull(); // The witness hash of the coinbase is 0. + leaves.reserve((block.vtx.size() + 1) & ~1ULL); // capacity rounded up to even + leaves.emplace_back(); // The witness hash of the coinbase is 0. for (size_t s = 1; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetWitnessHash().ToUint256(); + leaves.push_back(block.vtx[s]->GetWitnessHash().ToUint256()); } return ComputeMerkleRoot(std::move(leaves)); } diff --git a/src/core_write.cpp b/src/core_io.cpp similarity index 54% rename from src/core_write.cpp rename to src/core_io.cpp index e4f23458..a4b726cd 100644 --- a/src/core_write.cpp +++ b/src/core_io.cpp @@ -4,25 +4,286 @@ #include -#include +#include +#include #include #include #include +#include #include +// IWYU incorrectly suggests replacing this header +// with forward declarations. +// See https://github.com/include-what-you-use/include-what-you-use/issues/1886. +#include // IWYU pragma: keep +#include #include