Compare commits

...

80 Commits

Author SHA1 Message Date
merge-script
2d6426c296 Merge bitcoin/bitcoin#33551: [29.x] Finalise 29.2
46d9b9091b doc: update manual pages for v29.2 (fanquake)
b2026fa290 build: bump version to v29.2 (fanquake)
3226616493 doc: update release notes for 29.2 (fanquake)

Pull request description:

  I'm optimistic that 29.2 wont need an `rc3`.

ACKs for top commit:
  instagibbs:
    ACK 46d9b9091b
  stickies-v:
    ACK 46d9b9091b
  glozow:
    ACK 46d9b9091b

Tree-SHA512: f515d2dfbbe60dc145f79425cb2e8ef7a443e69dab208b9acdf357dae7cca3f566f7d013a85c6d4330d8931da060320159a3a9d8dae0ea3ff18bba5aeb282722
2025-10-10 11:51:54 -04:00
fanquake
46d9b9091b doc: update manual pages for v29.2 2025-10-08 10:40:37 +01:00
fanquake
b2026fa290 build: bump version to v29.2 2025-10-08 10:40:37 +01:00
fanquake
3226616493 doc: update release notes for 29.2 2025-10-08 10:40:37 +01:00
merge-script
8bcb90d7e3 Merge bitcoin/bitcoin#33563: [29.x] build: fix depends Qt download link
abf4a6eeae build: fix depends Qt download link (fanquake)

Pull request description:

  Fix Qt download path, so we wont always hit the fallback.

ACKs for top commit:
  hebasto:
    ACK abf4a6eeae.

Tree-SHA512: 1157528983ede46c60810eae5c73f4bd81640afcae9afd9aad14c30104e90c52f8e97755f22314a5514bc1de3a92d864398087fe826f1980acc772fd32535a9f
2025-10-07 14:04:27 +01:00
fanquake
abf4a6eeae build: fix depends Qt download link 2025-10-07 13:31:04 +01:00
merge-script
398c176ea8 Merge bitcoin/bitcoin#33534: [29.x] Finalise 29.2rc2
d82fc69829 doc: update release notes for 29.2rc2 (fanquake)
513cef75ee doc: update manual pages for v29.2rc2 (fanquake)
eea16f7de7 build: bump version to v29.2rc2 (fanquake)
6b3c1dbc5c contrib: fix using macdploy script without translations. (amisha)

Pull request description:

  It's been 2 weeks since rc1: https://github.com/bitcoin/bitcoin/releases/tag/v29.2rc1.
  We've backported more changes:
  * #33403
  * #33474
  * #33482

  Lets do `rc2`.

ACKs for top commit:
  davidgumberg:
    reACK d82fc69
  glozow:
    ACK d82fc69829
  darosior:
    utACK d82fc69829. Changes look good to me, but i have not been through the process of regenerating the doc myself.

Tree-SHA512: c829efe89f86c9c76767ffe60a3779ece902ee9e3c8f6b4203562aaf257019484bfa49916ddfabdcabbd1478368d9b80a3f0a15057778aa1984852ea245283a6
2025-10-03 14:01:58 -04:00
fanquake
d82fc69829 doc: update release notes for 29.2rc2 2025-10-03 18:07:20 +01:00
fanquake
513cef75ee doc: update manual pages for v29.2rc2 2025-10-03 16:26:09 +01:00
fanquake
eea16f7de7 build: bump version to v29.2rc2 2025-10-03 16:26:09 +01:00
amisha
6b3c1dbc5c contrib: fix using macdploy script without translations.
QT translations are optional, but the script would error when
'translations_dir' falls back to its default value NULL.

This PR fixes it by moving the set-up of QT translations under
the check for 'translations_dir' presence.

Github-Pull: #33482
Rebased-From: 7b5261f7ef
2025-10-03 16:26:09 +01:00
merge-script
d1b5d4e9ca Merge bitcoin/bitcoin#33474: [29.x] Backports
2d7ebd2d91 doc: update release notes for 29.x (fanquake)
a8bb76b61f test: add more TRUC reorg coverge (Greg Sanders)
666aec7d49 Mempool: Do not enforce TRUC checks on reorg (Greg Sanders)
6f23ead4a2 fuzz: don't bypass_limits for most mempool harnesses (Greg Sanders)
9d9baafc6f doc: rpc: fix case typo in `finalizepsbt` help (final_scriptwitness) (Sebastian Falbesoner)
22ab141243 rpc: fix getblock(header) returns target for tip (Sjors Provoost)
118abf4c30 test: add block 2016 to mock mainnet (Sjors Provoost)

Pull request description:

  Backports:
  * #33446
  * #33484
  * #33504

ACKs for top commit:
  luke-jr:
    ACK 2d7ebd2d91
  dergoegge:
    ACK 2d7ebd2d91
  marcofleon:
    ACK 2d7ebd2d91

Tree-SHA512: 27b852177d8502d6c703cb0eeb1e4df9d651c9c8add5fbf6ae4eeb4b8aefc145471f38f9794c0ed276bf7ebba1844ecbaf5a84cb5913ca7d0a546f5216ea3b2d
2025-10-03 14:21:52 +01:00
fanquake
2d7ebd2d91 doc: update release notes for 29.x 2025-10-02 15:18:36 +01:00
Greg Sanders
a8bb76b61f test: add more TRUC reorg coverge
Github-Pull: #33504
Rebased-From: 06df14ba75
2025-10-02 15:17:34 +01:00
Greg Sanders
666aec7d49 Mempool: Do not enforce TRUC checks on reorg
Not enforcing TRUC topology on reorg was the intended
behavior, but the appropriate bypass argument was not
checked.

This mistake means we could potentially invalidate a long
chain of perfectly incentive-compatible transactions that
were made historically, including subsequent non-TRUC
transactions, all of which may have been very high feerate.

Lastly, it wastes CPU cycles doing topology checks since
this behavior cannot actually enforce the topology in
general for the reorg setting.

Github-Pull: #33504
Rebased-From: 26e71c237d
2025-10-02 15:17:31 +01:00
Greg Sanders
6f23ead4a2 fuzz: don't bypass_limits for most mempool harnesses
Using bypass_limits=true is essentially fuzzing part of a
reorg only, and results in TRUC invariants unable to be
checked. Remove most instances of bypassing limits, leaving
one harness able to do so.

Github-Pull: #33504
Rebased-From: bbe8e9063c
2025-10-02 15:17:10 +01:00
Sebastian Falbesoner
9d9baafc6f doc: rpc: fix case typo in finalizepsbt help (final_scriptwitness)
Github-Pull: #33484
Rebased-From: ff05bebcc4
2025-09-29 15:56:02 -04:00
Sjors Provoost
22ab141243 rpc: fix getblock(header) returns target for tip
A target field was added to the getblock and getblockheader RPC calls in bitcoin#31583, but it mistakingly always used the tip value.

Because regtest does not have difficulty adjustment, a test is added for mainnet instead.

Github-Pull: #33446
Rebased-From: bf7996cbc3
2025-09-24 10:34:21 -04:00
Sjors Provoost
118abf4c30 test: add block 2016 to mock mainnet
The next commit requires an additional mainnet block which changes the difficulty.

Also fix a few minor mistakes in the test (suite):
- rename the create_coinbase retarger_period argument to halving_period. Before bitcoin#31583 this was hardcoded for regtest where these values are the same.
- drop unused fees argument from mine helper

Finally the CPU miner instructions for generating the alternative mainnet chain are expanded.

Github-Pull: #33446
Rebased-From: 4c3c1f42cf
2025-09-24 10:25:02 -04:00
merge-script
f6d49d0a09 Merge bitcoin/bitcoin#33403: Backport Cirrus runners to 29.x
5750355139 ci: link against -lstdc++ in native fuzz with msan job (fanquake)
78d93effd0 ci: Checkout latest merged pulls (MarcoFalke)
4a034cbeb4 ci: reduce runner sizes on various jobs (will)
6ded1fe117 ci: remove un-needed lint_run*.sh files (willcl-ark)
4e8b64b181 ci: fix annoying docker warning (will)
773e4cda94 ci: add ccache hit-rate warning when < 75% (will)
4339787379 doc: Detail configuration of hosted CI runners (will)
c7f290b826 ci: dynamically match makejobs with cores (will)
a08c3cc51c ci: remove .cirrus.yml (will)
06424fb004 ci: port lint (will)
0f0378fe3c ci: port msan-depends (will)
643385b22d ci: port tsan-depends (will)
3b2dcc8b9a ci: port tidy (will)
b4286cf354 ci: port centos-depends-gui (will)
5057b9a6ff ci: port previous-releases-depends-debug (will)
85ec6c6882 ci: port fuzzer-address-undefined-integer-nodepends (will)
544f902b2a ci: port i686-multiprocess-DEBUG (will)
e826c3daa5 ci: port nowallet-libbitcoinkernel (will)
835b5b8bb1 ci: port mac-cross-gui-notests (will)
a91567a980 ci: force reinstall of kernel headers in asan (will)
819ee09af3 ci: update asan-lsan-ubsan (will)
894a3cbe42 ci: update windows-cross job (will)
82c60a3151 ci: port arm 32-bit job (will)
849993377d ci: add job to determine runner type (will)
f9f3e8b686 ci: add Cirrus cache host (will)
af086431e8 ci: have base install run in right dir (will)
0a649d07c9 ci: use docker build cache arg directly (will)
f3089fb2cf ci: use buildx in ci (will)
1faf918a16 ci: add configure-docker action (will)
954c1a55e4 ci: add REPO_USE_CIRRUS_RUNNERS (will)
301aa5d814 ci: add caching actions (will)
f63b8e960d ci: add configure environment action (will)

Pull request description:

  Backports #32989 to the 29.x branch

ACKs for top commit:
  m3dwards:
    ACK 5750355139

Tree-SHA512: c0509903043acd1c1e62f6382d9373a5c7a51377a76cbe6ea0cacf83cb03b10e658b8fd0dc2080acb9d6361f0a7883feb0134acd9bc53d164561364d42e111e7
2025-09-24 10:18:19 -04:00
fanquake
5750355139 ci: link against -lstdc++ in native fuzz with msan job
Github-Pull: #33425
Rebased-From: b77137a564
2025-09-23 15:26:11 +01:00
MarcoFalke
78d93effd0 ci: Checkout latest merged pulls
Github-Pull: #33303
Rebased-From: fa8f081af3
2025-09-23 15:26:10 +01:00
will
4a034cbeb4 ci: reduce runner sizes on various jobs
Github-Pull: #33319
Rebased-From: 5eeb2facbb

These jobs can use reduced runner size to avoid wasting CPU, as much of
the long-running part of the job is single-threaded.

Suggested in: https://github.com/bitcoin/bitcoin/pull/32989#discussion_r2321775620

Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
2025-09-23 15:26:09 +01:00
willcl-ark
6ded1fe117 ci: remove un-needed lint_run*.sh files
Github-Pull: #32989
Rebased-From: 3c5da69a23

ci/lint_run_all.sh: Only used in .cirrus.yml. Refer to test/lint/README.md on how to run locally.
2025-09-23 15:26:08 +01:00
will
4e8b64b181 ci: fix annoying docker warning
Github-Pull: #32989
Rebased-From: 2aa288efdd

Docker currently warns that we are missing a default value.

Set this to scratch which will error if an appropriate image tag is not
passed in to silence the warning.
2025-09-23 15:26:07 +01:00
will
773e4cda94 ci: add ccache hit-rate warning when < 75%
Github-Pull: #32989
Rebased-From: dd1c5903e8

Print the ccache hit-rate for the job using a GitHub annotation if it
was below 75%.
2025-09-23 15:26:06 +01:00
will
4339787379 doc: Detail configuration of hosted CI runners
Github-Pull: #32989
Rebased-From: f427284483
2025-09-23 15:26:06 +01:00
will
c7f290b826 ci: dynamically match makejobs with cores
Github-Pull: #32989
Rebased-From: 3f339e99e0

Previously jobs were running on a large multi-core server where 10 jobs
as default made sense (or may even have been on the low side).

Using hosted runners with fixed (and lower) numbers of vCPUs we should
adapt compilation to match the number of cpus we have dynamically.

This is cross-platform compatible with macos and linux only.
2025-09-23 15:26:05 +01:00
will
a08c3cc51c ci: remove .cirrus.yml
Github-Pull: #32989
Rebased-From: 4393ffdd83

Removed as unused.
2025-09-23 15:26:04 +01:00
will
06424fb004 ci: port lint
Github-Pull: #32989
Rebased-From: bc41848d00

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:26:03 +01:00
will
0f0378fe3c ci: port msan-depends
Github-Pull: #32989
Rebased-From: d290a8e6ea

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:26:02 +01:00
will
643385b22d ci: port tsan-depends
Github-Pull: #32989
Rebased-From: 9bbae61e3b

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:26:01 +01:00
will
3b2dcc8b9a ci: port tidy
Github-Pull: #32989
Rebased-From: bf7d536452

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:26:00 +01:00
will
b4286cf354 ci: port centos-depends-gui
Github-Pull: #32989
Rebased-From: 549074bc64

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:59 +01:00
will
5057b9a6ff ci: port previous-releases-depends-debug
Github-Pull: #32989
Rebased-From: 58e38c3a04

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:58 +01:00
will
85ec6c6882 ci: port fuzzer-address-undefined-integer-nodepends
Github-Pull: #32989
Rebased-From: 341196d75c

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:57 +01:00
will
544f902b2a ci: port i686-multiprocess-DEBUG
Github-Pull: #32989
Rebased-From: f2068f26c1

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:56 +01:00
will
e826c3daa5 ci: port nowallet-libbitcoinkernel
Github-Pull: #32989
Rebased-From: 2a00b12d73

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:55 +01:00
will
835b5b8bb1 ci: port mac-cross-gui-notests
Github-Pull: #32989
Rebased-From: 9c2514de53

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:54 +01:00
will
a91567a980 ci: force reinstall of kernel headers in asan
Github-Pull: #32989
Rebased-From: 2c990d84a3

When using hosted runners in combination with cached docker images,
there is the possibility that the host runner image is updated,
rendering the linux-headers package (stored in the cached docker image)
incompatible.

Fix this by doing a re-install of the headers package in
03_test_script.sh.

If the underlying runner kernel has not changed thie has no effect, but
prevents the job from failing if it has.
2025-09-23 15:25:53 +01:00
will
819ee09af3 ci: update asan-lsan-ubsan
Github-Pull: #32989
Rebased-From: 884251441b

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:52 +01:00
will
894a3cbe42 ci: update windows-cross job
Github-Pull: #32989
Rebased-From: 04e7bfbceb

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:51 +01:00
will
82c60a3151 ci: port arm 32-bit job
Github-Pull: #32989
Rebased-From: f253031cb8

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:50 +01:00
will
849993377d ci: add job to determine runner type
Github-Pull: #32989
Rebased-From: cc1735d777

To remove multiple occurances of the respository name, against which we
compare `${{ github.repository }}` to check if we should use Cirrus
Runners, introduce a helper job which can check a single environment
variable and output this as an input to subsequent jobs.

Forks can maintain a trivial patch of their repo name against the
`REPO_USE_CIRRUS_RUNNERS` variable in ci.yml if they have Cirrus Runners
of their own, which will then enable cache actions and docker build
cache to use Cirrus Cache.

It's not possible to use `${{ env.USE_CIRRUS_RUNNERS }}` in the
`runs-on:` directive as the context is not supported by GitHub.

If it was, this job would no longer be necessary.
2025-09-23 15:25:49 +01:00
will
f9f3e8b686 ci: add Cirrus cache host
Github-Pull: #32989
Rebased-From: 020069e6b7

Whilst the action cirruslabs/actions/cache will automatically set this
host, the docker `gha` build cache backend will not be aware of it.

Set the value here, which will later be used in the docker build args to
enable docker build cache on the cirrus cache.
2025-09-23 15:25:48 +01:00
will
af086431e8 ci: have base install run in right dir
Github-Pull: #32989
Rebased-From: 9c2b96e0d0

This sets the build dir at build time so that Apple SDK gets installed
in the correct/expected location for the runtime to find it.

Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
2025-09-23 15:25:47 +01:00
will
0a649d07c9 ci: use docker build cache arg directly
Github-Pull: #32989
Rebased-From: 18f6be09d0

Reverts: e87429a2d0

This was added in PR #31545 with the intention that self-hosted runners
might use it to save build cache.

As we are not using hosted runners with a registry build cache, the bulk
of this commit can be reverted, simply using the value of
$DOCKER_BUILD_CACHE_ARG in the script.

link: https://github.com/bitcoin/bitcoin/pull/31545
2025-09-23 15:25:46 +01:00
will
f3089fb2cf ci: use buildx in ci
Github-Pull: #32989
Rebased-From: 94a0932547

Using buildx is required to properly load the correct driver, for use
with registry caching. Neither build, nor BUILDKIT=1 currently do this
properly.

Use of `docker buildx build` is compatible with podman.
2025-09-23 15:25:45 +01:00
will
1faf918a16 ci: add configure-docker action
Github-Pull: #32989
Rebased-From: fdf64e5532

Another action to reduce boilerplate in the main ci.yml file.

This action will set up a docker builder compatible with caching build
layers to a container registry using the `gha` build driver.

It will then configure the docker build cache args.
2025-09-23 15:25:44 +01:00
will
954c1a55e4 ci: add REPO_USE_CIRRUS_RUNNERS
Github-Pull: #32989
Rebased-From: 33ba073df7

If set, Cirrus runners will be used on pushes to, and pull requests
against, this repository.

Forks can set this if they have their own cirrus runners.
2025-09-23 15:25:43 +01:00
will
301aa5d814 ci: add caching actions
Github-Pull: #32989
Rebased-From: b232b0fa5e

Add "Restore" and "Save" caching actions.

These actions reduce boilerplate in the main ci.yml configuration file.

These actions are implemented so that caches will be saved on `push`
only.

When a pull request is opened it will cache hit on the caches from the
lastest push, or in the case of depends will hit on any matching depends
hash, falling back to partial matches.

Depends caches are hashed using
`$(git ls-tree HEAD depends "ci/test/$FILE_ENV" | sha256sum | cut -d' ' -f1)`
and this hash is passed in as an input to the actions. This means we
direct cache hit in cases where depends would not be re-built, otherwise
falling back to a partial match.

Previous releases cache is hashed similarly to depends, but using the
test/get_previous_releases.py file.

The cirruslabs cache action will fallback transparently to GitHub's
cache in the case that the job is not being run on a Cirrus Runner,
making these compatible with running on forks (on free GH hardware).
2025-09-23 15:25:42 +01:00
will
f63b8e960d ci: add configure environment action
Github-Pull: #32989
Rebased-From: b8fcc9fcbc
2025-09-23 15:25:41 +01:00
merge-script
7e1eca4882 Merge bitcoin/bitcoin#33344: [29.x] Backports
f2bd79f80c doc: update manual pages for v29.2rc1 (fanquake)
461dd13faf build: bump version to v29.2rc1 (fanquake)
9bc4afb62c doc: update release notes for 29.x (fanquake)
61cdc04a83 net: Do not apply whitelist permission to onion inbounds (Martin Zumsande)
1288d44804 test: send duplicate blocktxn message in p2p_compactblocks.py (Eugene Siegel)
569ceb0df4 net: check for empty header before calling FillBlock (Eugene Siegel)
4c940d4789 p2p: remove vestigial READ_STATUS_CHECKBLOCK_FAILED (Greg Sanders)
9b95ab5e9d p2p: Add witness mutation check inside FillBlock (Greg Sanders)
e97588fc3d trace: Workaround GCC bug compiling with old systemtap (Luke Dashjr)
324caa8497 ci: always use tag for LLVM checkout (fanquake)
2717331981 Fix benchmark CSV output (Hennadii Stepanov)

Pull request description:

  Backports:
  * #32646
  * #33296
  * #33310
  * #33340
  * #33364
  * #33395

  Plus changes for 29.2rc1.

ACKs for top commit:
  darosior:
    utACK f2bd79f80c
  mzumsande:
    utACK f2bd79f80c

Tree-SHA512: 346a92032b7a069e2941056c6273ff65e360c5834832b106350a9cd42b634518cc75b807da6e51a6292e3a33342bb7b145777d3538a2792e03c63962d747a025
2025-09-17 14:00:10 -04:00
fanquake
f2bd79f80c doc: update manual pages for v29.2rc1 2025-09-17 15:54:29 +01:00
fanquake
461dd13faf build: bump version to v29.2rc1 2025-09-17 15:47:34 +01:00
fanquake
9bc4afb62c doc: update release notes for 29.x 2025-09-17 15:45:45 +01:00
Martin Zumsande
61cdc04a83 net: Do not apply whitelist permission to onion inbounds
Tor inbound connections do not reveal the peer's actual network address.
Therefore do not apply whitelist permissions to them.

Co-authored-by: Vasil Dimov <vd@FreeBSD.org>

Github-Pull: #33395
Rebased-From: f563ce9081
2025-09-17 10:12:08 +01:00
Eugene Siegel
1288d44804 test: send duplicate blocktxn message in p2p_compactblocks.py
Add test_multiple_blocktxn_response that checks that the peer is
disconnected.

Github-Pull: #33296
Rebased-From: 8b62647680
2025-09-12 15:44:07 +01:00
Eugene Siegel
569ceb0df4 net: check for empty header before calling FillBlock
Previously in debug builds, this would cause an Assume crash if
FillBlock had been called previously. This could happen when multiple
blocktxn messages were received.

Co-Authored-By: Greg Sanders <gsanders87@gmail.com>

Github-Pull: #33296
Rebased-From: 5e585a0fc4
2025-09-12 15:44:03 +01:00
Greg Sanders
4c940d4789 p2p: remove vestigial READ_STATUS_CHECKBLOCK_FAILED
Github-Pull: #32646
Rebased-From: 28299ce776
2025-09-12 15:44:00 +01:00
Greg Sanders
9b95ab5e9d p2p: Add witness mutation check inside FillBlock
Since #29412, we have not allowed mutated blocks to continue
being processed immediately the block is received, but this
is only done for the legacy BLOCK message.

Extend these checks as belt-and-suspenders to not allow
similar mutation strategies to affect relay by honest peers
by applying the check inside
PartiallyDownloadedBlock::FillBlock, immediately before
returning READ_STATUS_OK.

This also removes the extraneous CheckBlock call.

Github-Pull: #32646
Rebased-From: bac9ee4830
2025-09-12 15:43:53 +01:00
Luke Dashjr
e97588fc3d trace: Workaround GCC bug compiling with old systemtap
Github-Pull: #33310
Rebased-From: 93a29ff283
2025-09-12 11:52:26 +01:00
fanquake
324caa8497 ci: always use tag for LLVM checkout
Rather than trying to match the apt installed clang version, which is
prone to intermittent issues. i.e #33345.

Github-Pull: #33364
Rebased-From: b736052e39
2025-09-12 09:48:59 +01:00
Hennadii Stepanov
2717331981 Fix benchmark CSV output
The `SHA256AutoDetect` return output is used, among other use cases, to
name benchmarks. Using a comma breaks the CSV output.

This change replaces the comma with a semicolon, which fixes the issue.

Github-Pull: #33340
Rebased-From: 790b440197
2025-09-09 10:13:49 +01:00
merge-script
a0e438bd49 Merge bitcoin/bitcoin#33294: [29.x] *san CI backports
7c6be9acae doc: update release notes for 29.x (fanquake)
ea40fa95d9 ci: use LLVM 21 (fanquake)
5513516241 ci: remove DEBUG_LOCKORDER from TSAN job (fanquake)
f9939cdbe0 ci: instrument libc++ in TSAN job (fanquake)
0fba5ae021 ci: allow libc++ instrumentation other than msan (fanquake)
10cbf2255d ci: Use APT_LLVM_V in msan task (MarcoFalke)

Pull request description:

  Backports:
  * #32999
  * #33099 (added `ninja-build`)
  * #33258

ACKs for top commit:
  marcofleon:
    ACK 7c6be9acae, looks okay to me

Tree-SHA512: 928882d505ed8101a6d4123947252a84d40bd350383408926b5c37aed56dc3359067d1d14c443c51351a6958a8dd9e141bb7713665295ff1f1ad86c5f8a36df0
2025-09-08 17:16:58 +01:00
fanquake
7c6be9acae doc: update release notes for 29.x 2025-09-05 12:04:09 +01:00
fanquake
ea40fa95d9 ci: use LLVM 21
Github-Pull: #33258
Rebased-From: 4cf0ae474b
2025-09-03 16:51:18 +01:00
fanquake
5513516241 ci: remove DEBUG_LOCKORDER from TSAN job
Github-Pull: #33099
Rebased-From: 7aa5b67132
2025-09-03 16:51:18 +01:00
fanquake
f9939cdbe0 ci: instrument libc++ in TSAN job
Qt is disabled, as the build is now taking a very long time.

Github-Pull: #33099
Rebased-From: b09af2ce50
2025-09-03 16:51:14 +01:00
fanquake
0fba5ae021 ci: allow libc++ instrumentation other than msan
Github-Pull: #33099
Rebased-From: 6653cafd0b
2025-09-03 16:16:08 +01:00
MarcoFalke
10cbf2255d ci: Use APT_LLVM_V in msan task
Also, use update-alternatives to avoid having to manually specify
clang-${APT_LLVM_V} or llvm-symbolizer-${APT_LLVM_V} everywhere.

Github-Pull: #32999
Rebased-From: fad040a578
2025-09-03 16:14:25 +01:00
merge-script
fd784f2774 Merge bitcoin/bitcoin#33271: [29.x] finalise v29.1
084c95a18c doc: update manual pages for v29.1 (fanquake)
37d115c67e build: bump version to v29.1 final (fanquake)
b0d88bcc50 doc: finalise release notes for 29.1 (fanquake)
99ab2e70e7 ci: return to using dash in CentOS job (fanquake)
6448ebb5a7 doc: Remove wrong and redundant doxygen tag (MarcoFalke)

Pull request description:

  Backports:
  * #33236
  * #33261

  Since `rc2`, #33212 was also backported in #33251.

ACKs for top commit:
  glozow:
    ACK 084c95a18c
  willcl-ark:
    ACK 084c95a18c

Tree-SHA512: 0698e5b2d12f7328bf5af8dbbd92b0049de401c0a4af27fda2209f9aab35d827c5ac65eb9268aa1fae241e3adf0d3dd89324bb288655ead8af2b5584aae1f6d2
2025-09-03 10:49:29 -04:00
fanquake
084c95a18c doc: update manual pages for v29.1 2025-09-03 13:41:57 +01:00
fanquake
37d115c67e build: bump version to v29.1 final 2025-09-03 13:23:31 +01:00
fanquake
b0d88bcc50 doc: finalise release notes for 29.1 2025-09-03 13:22:28 +01:00
fanquake
99ab2e70e7 ci: return to using dash in CentOS job
Github-Pull: #33261
Rebased-From: 509ffea40a
2025-09-03 11:51:12 +01:00
MarcoFalke
6448ebb5a7 doc: Remove wrong and redundant doxygen tag
Remove it in feerate.

Fix it in the other places.

Github-Pull: #33236
Rebased-From: 966666de9a
2025-08-29 14:53:02 +01:00
merge-script
162c009c1d Merge bitcoin/bitcoin#33251: [29.x] backport #33212
fcac8022d8 test: index with an unclean restart after a reorg (Martin Zumsande)
16b1710d97 index: don't commit state in BaseIndex::Rewind (Martin Zumsande)

Pull request description:

  Backports #33212 to 29.x

ACKs for top commit:
  achow101:
    ACK fcac8022d8
  stickies-v:
    ACK fcac8022d8
  mzumsande:
    Code Review ACK fcac8022d8

Tree-SHA512: eeb9213f03bbb1d48c3ccb12121a6e475f436895d314b5171007e7e4ee457c74b312fa7f0d1808d6221dc22b192700a93ea21c4e9e04689da7dde7e1f79e9569
2025-08-27 09:46:59 +01:00
Martin Zumsande
fcac8022d8 test: index with an unclean restart after a reorg
This test fails without the previous commit.

Github-Pull: #33212
Rebased-From: a602f6fb7b
2025-08-24 22:51:07 +01:00
Martin Zumsande
16b1710d97 index: don't commit state in BaseIndex::Rewind
The committed state of an index should never
be ahead of the flushed chainstate. Otherwise, in the case
of an unclean shutdown, the blocks necessary to revert
from the prematurely committed state would not be
available, which would corrupt the coinstatsindex in particular.
Instead, the index state will be committed with the next
ChainStateFlushed notification.

Github-Pull: #33212
Rebased-From: 01b95ac6f4
2025-08-24 22:48:09 +01:00
58 changed files with 727 additions and 693 deletions

View File

@@ -1,214 +0,0 @@
env: # Global defaults
CIRRUS_CLONE_DEPTH: 1
CIRRUS_LOG_TIMESTAMP: true
MAKEJOBS: "-j10"
TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache
CI_FAILFAST_TEST_LEAVE_DANGLING: "1" # Cirrus CI does not care about dangling processes and setting this variable avoids killing the CI script itself on error
# A self-hosted machine(s) can be used via Cirrus CI. It can be configured with
# multiple users to run tasks in parallel. No sudo permission is required.
#
# https://cirrus-ci.org/guide/persistent-workers/
#
# Generally, a persistent worker must run Ubuntu 23.04+ or Debian 12+.
#
# The following specific types should exist, with the following requirements:
# - small: For an x86_64 machine, with at least 2 vCPUs and 8 GB of memory.
# - medium: For an x86_64 machine, with at least 4 vCPUs and 16 GB of memory.
# - arm64: For an aarch64 machine, with at least 2 vCPUs and 8 GB of memory.
#
# CI jobs for the latter configuration can be run on x86_64 hardware
# by installing qemu-user-static, which works out of the box with
# podman or docker. Background: https://stackoverflow.com/a/72890225/313633
#
# The above machine types are matched to each task by their label. Refer to the
# Cirrus CI docs for more details.
#
# When a contributor maintains a fork of the repo, any pull request they make
# to their own fork, or to the main repository, will trigger two CI runs:
# one for the branch push and one for the pull request.
# This can be avoided by setting SKIP_BRANCH_PUSH=true as a custom env variable
# in Cirrus repository settings, accessible from
# https://cirrus-ci.com/github/my-organization/my-repository
#
# On machines that are persisted between CI jobs, RESTART_CI_DOCKER_BEFORE_RUN=1
# ensures that previous containers and artifacts are cleared before each run.
# This requires installing Podman instead of Docker.
#
# Futhermore:
# - podman-docker-4.1+ is required due to the bugfix in 4.1
# (https://github.com/bitcoin/bitcoin/pull/21652#issuecomment-1657098200)
# - The ./ci/ dependencies (with cirrus-cli) should be installed. One-liner example
# for a single user setup with sudo permission:
#
# ```
# apt update && apt install git screen python3 bash podman-docker uidmap slirp4netns curl -y && curl -L -o cirrus "https://github.com/cirruslabs/cirrus-cli/releases/latest/download/cirrus-linux-$(dpkg --print-architecture)" && mv cirrus /usr/local/bin/cirrus && chmod +x /usr/local/bin/cirrus
# ```
#
# - There are no strict requirements on the hardware. Having fewer CPU threads
# than recommended merely causes the CI script to run slower.
# To avoid rare and intermittent OOM due to short memory usage spikes,
# it is recommended to add (and persist) swap:
#
# ```
# fallocate -l 16G /swapfile_ci && chmod 600 /swapfile_ci && mkswap /swapfile_ci && swapon /swapfile_ci && ( echo '/swapfile_ci none swap sw 0 0' | tee -a /etc/fstab )
# ```
#
# - To register the persistent worker, open a `screen` session and run:
#
# ```
# RESTART_CI_DOCKER_BEFORE_RUN=1 screen cirrus worker run --labels type=todo_fill_in_type --token todo_fill_in_token
# ```
# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
filter_template: &FILTER_TEMPLATE
# Allow forks to specify SKIP_BRANCH_PUSH=true and skip CI runs when a branch is pushed,
# but still run CI when a PR is created.
# https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution
skip: $SKIP_BRANCH_PUSH == "true" && $CIRRUS_PR == ""
stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks
base_template: &BASE_TEMPLATE
<< : *FILTER_TEMPLATE
merge_base_script:
# Require git (used in fingerprint_script).
- git --version || ( apt-get update && apt-get install -y git )
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
- git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
# Also, the merge commit is used to lint COMMIT_RANGE="HEAD~..HEAD"
main_template: &MAIN_TEMPLATE
timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
ci_script:
- ./ci/test_run_all.sh
global_task_template: &GLOBAL_TASK_TEMPLATE
<< : *BASE_TEMPLATE
<< : *MAIN_TEMPLATE
compute_credits_template: &CREDITS_TEMPLATE
# https://cirrus-ci.org/pricing/#compute-credits
# Only use credits for pull requests to the main repo
use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'bitcoin/bitcoin' && $CIRRUS_PR != ""
task:
name: 'lint'
<< : *BASE_TEMPLATE
container:
image: debian:bookworm
cpu: 1
memory: 1G
# For faster CI feedback, immediately schedule the linters
<< : *CREDITS_TEMPLATE
test_runner_cache:
folder: "/lint_test_runner"
fingerprint_script: echo $CIRRUS_TASK_NAME $(git rev-parse HEAD:test/lint/test_runner)
python_cache:
folder: "/python_build"
fingerprint_script: cat .python-version /etc/os-release
unshallow_script:
- git fetch --unshallow --no-tags
lint_script:
- ./ci/lint_run_all.sh
task:
name: 'tidy'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: medium
env:
FILE_ENV: "./ci/test/00_setup_env_native_tidy.sh"
task:
name: 'ARM, unit tests, no functional tests'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: arm64 # Use arm64 worker to sidestep qemu and avoid a slow CI: https://github.com/bitcoin/bitcoin/pull/28087#issuecomment-1649399453
env:
FILE_ENV: "./ci/test/00_setup_env_arm.sh"
task:
name: 'Win64-cross'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
env:
FILE_ENV: "./ci/test/00_setup_env_win64.sh"
task:
name: 'CentOS, depends, gui'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
env:
FILE_ENV: "./ci/test/00_setup_env_native_centos.sh"
task:
name: 'previous releases, depends DEBUG'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
env:
FILE_ENV: "./ci/test/00_setup_env_native_previous_releases.sh"
task:
name: 'TSan, depends, gui'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: medium
env:
FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh"
task:
name: 'MSan, depends'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
timeout_in: 300m # Use longer timeout for the *rare* case where a full build (llvm + msan + depends + ...) needs to be done.
env:
FILE_ENV: "./ci/test/00_setup_env_native_msan.sh"
task:
name: 'fuzzer,address,undefined,integer, no depends'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: medium
timeout_in: 240m # larger timeout, due to the high CPU demand
env:
FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh"
task:
name: 'multiprocess, i686, DEBUG'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: medium
env:
FILE_ENV: "./ci/test/00_setup_env_i686_multiprocess.sh"
task:
name: 'no wallet, libbitcoinkernel'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
env:
FILE_ENV: "./ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh"
task:
name: 'macOS-cross, gui, no tests'
<< : *GLOBAL_TASK_TEMPLATE
persistent_worker:
labels:
type: small
env:
FILE_ENV: "./ci/test/00_setup_env_mac_cross.sh"

View File

@@ -0,0 +1,52 @@
name: 'Configure Docker'
description: 'Set up Docker build driver and configure build cache args'
inputs:
use-cirrus:
description: 'Use cirrus cache'
required: true
runs:
using: 'composite'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
# Use host network to allow access to cirrus gha cache running on the host
driver-opts: |
network=host
# This is required to allow buildkit to access the actions cache
- name: Expose actions cache variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL'])
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN'])
- name: Construct docker build cache args
shell: bash
run: |
# Configure docker build cache backend
#
# On forks the gha cache will work but will use Github's cache backend.
# Docker will check for variables $ACTIONS_CACHE_URL, $ACTIONS_RESULTS_URL and $ACTIONS_RUNTIME_TOKEN
# which are set automatically when running on GitHub infra: https://docs.docker.com/build/cache/backends/gha/#synopsis
# Use cirrus cache host
if [[ ${{ inputs.use-cirrus }} == 'true' ]]; then
url_args="url=${CIRRUS_CACHE_HOST},url_v2=${CIRRUS_CACHE_HOST}"
else
url_args=""
fi
# Always optimistically --cachefrom in case a cache blob exists
args=(--cache-from "type=gha${url_args:+,${url_args}},scope=${CONTAINER_NAME}")
# If this is a push to the default branch, also add --cacheto to save the cache
if [[ ${{ github.event_name }} == "push" && ${{ github.ref_name }} == ${{ github.event.repository.default_branch }} ]]; then
args+=(--cache-to "type=gha${url_args:+,${url_args}},mode=max,ignore-error=true,scope=${CONTAINER_NAME}")
fi
# Always `--load` into docker images (needed when using the `docker-container` build driver).
args+=(--load)
echo "DOCKER_BUILD_CACHE_ARG=${args[*]}" >> $GITHUB_ENV

View File

@@ -0,0 +1,27 @@
name: 'Configure environment'
description: 'Configure CI, cache and container name environment variables'
runs:
using: 'composite'
steps:
- name: Set CI and cache directories
shell: bash
run: |
echo "BASE_ROOT_DIR=${{ runner.temp }}" >> "$GITHUB_ENV"
echo "BASE_BUILD_DIR=${{ runner.temp }}/build" >> "$GITHUB_ENV"
echo "CCACHE_DIR=${{ runner.temp }}/ccache_dir" >> $GITHUB_ENV
echo "DEPENDS_DIR=${{ runner.temp }}/depends" >> "$GITHUB_ENV"
echo "BASE_CACHE=${{ runner.temp }}/depends/built" >> $GITHUB_ENV
echo "SOURCES_PATH=${{ runner.temp }}/depends/sources" >> $GITHUB_ENV
echo "PREVIOUS_RELEASES_DIR=${{ runner.temp }}/previous_releases" >> $GITHUB_ENV
- name: Set cache hashes
shell: bash
run: |
echo "DEPENDS_HASH=$(git ls-tree HEAD depends "ci/test/$FILE_ENV" | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
echo "PREVIOUS_RELEASES_HASH=$(git ls-tree HEAD test/get_previous_releases.py | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Get container name
shell: bash
run: |
source $FILE_ENV
echo "CONTAINER_NAME=$CONTAINER_NAME" >> "$GITHUB_ENV"

View File

@@ -0,0 +1,47 @@
name: 'Restore Caches'
description: 'Restore ccache, depends sources, and built depends caches'
runs:
using: 'composite'
steps:
- name: Restore Ccache cache
id: ccache-cache
uses: cirruslabs/cache/restore@v4
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ env.CONTAINER_NAME }}-${{ github.run_id }}
restore-keys: |
ccache-${{ env.CONTAINER_NAME }}-
- name: Restore depends sources cache
id: depends-sources
uses: cirruslabs/cache/restore@v4
with:
path: ${{ env.SOURCES_PATH }}
key: depends-sources-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }}
restore-keys: |
depends-sources-${{ env.CONTAINER_NAME }}-
- name: Restore built depends cache
id: depends-built
uses: cirruslabs/cache/restore@v4
with:
path: ${{ env.BASE_CACHE }}
key: depends-built-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }}
restore-keys: |
depends-built-${{ env.CONTAINER_NAME }}-
- name: Restore previous releases cache
id: previous-releases
uses: cirruslabs/cache/restore@v4
with:
path: ${{ env.PREVIOUS_RELEASES_DIR }}
key: previous-releases-${{ env.CONTAINER_NAME }}-${{ env.PREVIOUS_RELEASES_HASH }}
restore-keys: |
previous-releases-${{ env.CONTAINER_NAME }}-
- name: export cache hits
shell: bash
run: |
echo "depends-sources-cache-hit=${{ steps.depends-sources.outputs.cache-hit }}" >> $GITHUB_ENV
echo "depends-built-cache-hit=${{ steps.depends-built.outputs.cache-hit }}" >> $GITHUB_ENV
echo "previous-releases-cache-hit=${{ steps.previous-releases.outputs.cache-hit }}" >> $GITHUB_ENV

39
.github/actions/save-caches/action.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: 'Save Caches'
description: 'Save ccache, depends sources, and built depends caches'
runs:
using: 'composite'
steps:
- name: debug cache hit inputs
shell: bash
run: |
echo "depends sources direct cache hit to primary key: ${{ env.depends-sources-cache-hit }}"
echo "depends built direct cache hit to primary key: ${{ env.depends-built-cache-hit }}"
echo "previous releases direct cache hit to primary key: ${{ env.previous-releases-cache-hit }}"
- name: Save Ccache cache
uses: cirruslabs/cache/save@v4
if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) }}
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ env.CONTAINER_NAME }}-${{ github.run_id }}
- name: Save depends sources cache
uses: cirruslabs/cache/save@v4
if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.depends-sources-cache-hit != 'true') }}
with:
path: ${{ env.SOURCES_PATH }}
key: depends-sources-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }}
- name: Save built depends cache
uses: cirruslabs/cache/save@v4
if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.depends-built-cache-hit != 'true' )}}
with:
path: ${{ env.BASE_CACHE }}
key: depends-built-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }}
- name: Save previous releases cache
uses: cirruslabs/cache/save@v4
if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.previous-releases-cache-hit != 'true' )}}
with:
path: ${{ env.PREVIOUS_RELEASES_DIR }}
key: previous-releases-${{ env.CONTAINER_NAME }}-${{ env.PREVIOUS_RELEASES_HASH }}

View File

@@ -19,9 +19,26 @@ concurrency:
env:
CI_FAILFAST_TEST_LEAVE_DANGLING: 1 # GHA does not care about dangling processes and setting this variable avoids killing the CI script itself on error
MAKEJOBS: '-j10'
CIRRUS_CACHE_HOST: http://127.0.0.1:12321/ # When using Cirrus Runners this host can be used by the docker `gha` build cache type.
REPO_USE_CIRRUS_RUNNERS: 'bitcoin/bitcoin' # Use cirrus runners and cache for this repo, instead of falling back to the slow GHA runners
jobs:
runners:
name: 'determine runners'
runs-on: ubuntu-latest
outputs:
use-cirrus-runners: ${{ steps.runners.outputs.use-cirrus-runners }}
steps:
- id: runners
run: |
if [[ "${REPO_USE_CIRRUS_RUNNERS}" == "${{ github.repository }}" ]]; then
echo "use-cirrus-runners=true" >> "$GITHUB_OUTPUT"
echo "::notice title=Runner Selection::Using Cirrus Runners"
else
echo "use-cirrus-runners=false" >> "$GITHUB_OUTPUT"
echo "::notice title=Runner Selection::Using GitHub-hosted runners"
fi
test-each-commit:
name: 'test each commit'
runs-on: ubuntu-24.04
@@ -106,8 +123,12 @@ jobs:
BASE_ROOT_DIR: ${{ github.workspace }}
steps:
- name: Checkout
uses: actions/checkout@v4
- &CHECKOUT
name: Checkout
uses: actions/checkout@v5
with:
# Ensure the latest merged pull request state is used, even on re-runs.
ref: &CHECKOUT_REF_TMPL ${{ github.event_name == 'pull_request' && github.ref || '' }}
- name: Clang version
run: |
@@ -175,8 +196,7 @@ jobs:
job-name: 'Win64 native fuzz, VS 2022'
steps:
- name: Checkout
uses: actions/checkout@v4
- *CHECKOUT
- name: Configure Developer Command Prompt for Microsoft Visual C++
# Using microsoft/setup-msbuild is not enough.
@@ -265,44 +285,151 @@ jobs:
run: |
py -3 test\fuzz\test_runner.py --par %NUMBER_OF_PROCESSORS% --loglevel DEBUG %RUNNER_TEMP%\qa-assets\fuzz_corpora
asan-lsan-ubsan-integer-no-depends-usdt:
name: 'ASan + LSan + UBSan + integer, no depends, USDT'
runs-on: ubuntu-24.04 # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools
ci-matrix:
name: ${{ matrix.name }}
needs: runners
runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && matrix.cirrus-runner || matrix.fallback-runner }}
if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
timeout-minutes: 120
timeout-minutes: ${{ matrix.timeout-minutes }}
env:
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
DANGER_CI_ON_HOST_FOLDERS: 1
FILE_ENV: ${{ matrix.file-env }}
strategy:
fail-fast: false
matrix:
include:
- name: '32 bit ARM, unit tests, no functional tests'
cirrus-runner: 'ubuntu-24.04-arm' # Cirrus' Arm runners are Apple (with virtual Linux aarch64), which doesn't support 32-bit mode
fallback-runner: 'ubuntu-24.04-arm'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_arm.sh'
- name: 'win64 Cross'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_win64.sh'
- name: 'ASan + LSan + UBSan + integer, no depends, USDT'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_asan.sh'
- name: 'macOS-cross, gui, no tests'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_mac_cross.sh'
- name: 'No wallet, libbitcoinkernel'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh'
- name: 'i686, multiprocess, DEBUG'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_i686_multiprocess.sh'
- name: 'fuzzer,address,undefined,integer, no depends'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 240
file-env: './ci/test/00_setup_env_native_fuzz.sh'
- name: 'previous releases, depends DEBUG'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_previous_releases.sh'
- name: 'CentOS, depends, gui'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_centos.sh'
- name: 'tidy'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_tidy.sh'
- name: 'TSan, depends, no gui'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_tsan.sh'
- name: 'MSan, depends'
cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg'
fallback-runner: 'ubuntu-24.04'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_native_msan.sh'
steps:
- name: Checkout
uses: actions/checkout@v4
- *CHECKOUT
- name: Set CI directories
run: |
echo "CCACHE_DIR=${{ runner.temp }}/ccache_dir" >> "$GITHUB_ENV"
echo "BASE_ROOT_DIR=${{ runner.temp }}" >> "$GITHUB_ENV"
echo "BASE_BUILD_DIR=${{ runner.temp }}/build-asan" >> "$GITHUB_ENV"
- name: Configure environment
uses: ./.github/actions/configure-environment
- name: Restore Ccache cache
id: ccache-cache
uses: actions/cache/restore@v4
- name: Restore caches
id: restore-cache
uses: ./.github/actions/restore-caches
- name: Configure Docker
uses: ./.github/actions/configure-docker
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ github.job }}-ccache-${{ github.run_id }}
restore-keys: ${{ github.job }}-ccache-
use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }}
- name: Enable bpfcc script
if: ${{ env.CONTAINER_NAME == 'ci_native_asan' }}
# In the image build step, no external environment variables are available,
# so any settings will need to be written to the settings env file:
run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh
- name: Set mmap_rnd_bits
if: ${{ env.CONTAINER_NAME == 'ci_native_tsan' || env.CONTAINER_NAME == 'ci_native_msan' }}
# Prevents crashes due to high ASLR entropy
run: sudo sysctl -w vm.mmap_rnd_bits=28
- name: CI script
run: ./ci/test_run_all.sh
- name: Save Ccache cache
uses: actions/cache/save@v4
if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true'
- name: Save caches
uses: ./.github/actions/save-caches
lint:
name: 'lint'
needs: runners
runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xs' || 'ubuntu-24.04' }}
if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
timeout-minutes: 20
env:
CONTAINER_NAME: "bitcoin-linter"
steps:
- name: Checkout
uses: actions/checkout@v5
with:
path: ${{ env.CCACHE_DIR }}
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache
key: ${{ github.job }}-ccache-${{ github.run_id }}
ref: *CHECKOUT_REF_TMPL
fetch-depth: 0
- name: Configure Docker
uses: ./.github/actions/configure-docker
with:
use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }}
- name: CI script
run: |
set -o xtrace
docker buildx build -t "$CONTAINER_NAME" $DOCKER_BUILD_CACHE_ARG --file "./ci/lint_imagefile" .
CIRRUS_PR_FLAG=""
if [ "${{ github.event_name }}" = "pull_request" ]; then
CIRRUS_PR_FLAG="-e CIRRUS_PR=1"
fi
docker run --rm $CIRRUS_PR_FLAG -v "$(pwd)":/bitcoin "$CONTAINER_NAME"

View File

@@ -28,9 +28,9 @@ get_directory_property(precious_variables CACHE_VARIABLES)
#=============================
set(CLIENT_NAME "Bitcoin Core")
set(CLIENT_VERSION_MAJOR 29)
set(CLIENT_VERSION_MINOR 1)
set(CLIENT_VERSION_MINOR 2)
set(CLIENT_VERSION_BUILD 0)
set(CLIENT_VERSION_RC 2)
set(CLIENT_VERSION_RC 0)
set(CLIENT_VERSION_IS_RELEASE "true")
set(COPYRIGHT_YEAR "2025")

View File

@@ -1,8 +1,8 @@
## CI Scripts
# CI Scripts
This directory contains scripts for each build step in each build stage.
### Running a Stage Locally
## Running a Stage Locally
Be aware that the tests will be built and run in-place, so please run at your own risk.
If the repository is not a fresh git clone, you might have to clean files from previous builds or test runs first.
@@ -27,7 +27,7 @@ with a specific configuration,
env -i HOME="$HOME" PATH="$PATH" USER="$USER" bash -c 'FILE_ENV="./ci/test/00_setup_env_arm.sh" ./ci/test_run_all.sh'
```
### Configurations
## Configurations
The test files (`FILE_ENV`) are constructed to test a wide range of
configurations, rather than a single pass/fail. This helps to catch build
@@ -49,8 +49,32 @@ env -i HOME="$HOME" PATH="$PATH" USER="$USER" bash -c 'MAKEJOBS="-j1" FILE_ENV="
The files starting with `0n` (`n` greater than 0) are the scripts that are run
in order.
### Cache
## Cache
In order to avoid rebuilding all dependencies for each build, the binaries are
cached and reused when possible. Changes in the dependency-generator will
trigger cache-invalidation and rebuilds as necessary.
## Configuring a repository for CI
### Primary repository
To configure the primary repository, follow these steps:
1. Register with [Cirrus Runners](https://cirrus-runners.app/) and purchase runners.
2. Install the Cirrus Runners GitHub app against the GitHub organization.
3. Enable organisation-level runners to be used in public repositories:
1. `Org settings -> Actions -> Runner Groups -> Default -> Allow public repos`
4. Permit the following actions to run:
1. cirruslabs/cache/restore@\*
1. cirruslabs/cache/save@\*
1. docker/setup-buildx-action@\*
1. actions/github-script@\*
### Forked repositories
When used in a fork the CI will run on GitHub's free hosted runners by default.
In this case, due to GitHub's 10GB-per-repo cache size limitations caches will be frequently evicted and missed, but the workflows will run (slowly).
It is also possible to use your own Cirrus Runners in your own fork with an appropriate patch to the `REPO_USE_CIRRUS_RUNNERS` variable in ../.github/workflows/ci.yml
NB that Cirrus Runners only work at an organisation level, therefore in order to use your own Cirrus Runners, *the fork must be within your own organisation*.

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019-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.
export LC_ALL=C.UTF-8
# Only used in .cirrus.yml. Refer to test/lint/README.md on how to run locally.
cp "./ci/retry/retry" "/ci_retry"
cp "./.python-version" "/.python-version"
mkdir --parents "/test/lint"
cp --recursive "./test/lint/test_runner" "/test/lint/"
set -o errexit; source ./ci/lint/04_install.sh
set -o errexit
./ci/lint/06_script.sh

View File

@@ -35,7 +35,7 @@ fi
echo "Fallback to default values in env (if not yet set)"
# The number of parallel jobs to pass down to make and test_runner.py
export MAKEJOBS=${MAKEJOBS:--j4}
export MAKEJOBS=${MAKEJOBS:--j$(if command -v nproc > /dev/null 2>&1; then nproc; else sysctl -n hw.logicalcpu; fi)}
# Whether to prefer BusyBox over GNU utilities
export USE_BUSY_BOX=${USE_BUSY_BOX:-false}

View File

@@ -8,6 +8,7 @@ export LC_ALL=C.UTF-8
# Homebrew's python@3.12 is marked as externally managed (PEP 668).
# Therefore, `--break-system-packages` is needed.
export CONTAINER_NAME="ci_mac_native" # macos does not use a container, but the env var is needed for logging
export PIP_PACKAGES="--break-system-packages zmq"
export GOAL="install"
export CMAKE_GENERATOR="Ninja"

View File

@@ -6,6 +6,7 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME="ci_mac_native_fuzz" # macos does not use a container, but the env var is needed for logging
export CMAKE_GENERATOR="Ninja"
export BITCOIN_CONFIG="-DBUILD_FOR_FUZZING=ON"
export CI_OS_NAME="macos"

View File

@@ -19,15 +19,15 @@ else
fi
export CONTAINER_NAME=ci_native_asan
export APT_LLVM_V="20"
export APT_LLVM_V="21"
export PACKAGES="systemtap-sdt-dev clang-${APT_LLVM_V} llvm-${APT_LLVM_V} libclang-rt-${APT_LLVM_V}-dev python3-zmq qtbase5-dev qttools5-dev qttools5-dev-tools libevent-dev libboost-dev libdb5.3++-dev libzmq3-dev libqrencode-dev libsqlite3-dev ${BPFCC_PACKAGE}"
export NO_DEPENDS=1
export GOAL="install"
export BITCOIN_CONFIG="\
-DWITH_USDT=ON -DWITH_ZMQ=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF -DBUILD_GUI=ON \
-DSANITIZERS=address,float-divide-by-zero,integer,undefined \
-DCMAKE_C_COMPILER=clang-${APT_LLVM_V} \
-DCMAKE_CXX_COMPILER=clang++-${APT_LLVM_V} \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS='-ftrivial-auto-var-init=pattern' \
-DCMAKE_CXX_FLAGS='-ftrivial-auto-var-init=pattern -Wno-error=deprecated-declarations' \
-DAPPEND_CXXFLAGS='-std=c++23' \

View File

@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_centos
export CI_IMAGE_NAME_TAG="quay.io/centos/centos:stream10"
export CI_BASE_PACKAGES="gcc-c++ glibc-devel libstdc++-devel ccache make git python3 python3-pip which patch xz procps-ng ksh rsync coreutils bison e2fsprogs cmake"
export CI_BASE_PACKAGES="gcc-c++ glibc-devel libstdc++-devel ccache make git python3 python3-pip which patch xz procps-ng rsync coreutils bison e2fsprogs cmake dash"
export PIP_PACKAGES="pyzmq"
export DEP_OPTS="DEBUG=1" # Temporarily enable a DEBUG=1 build to check for GCC-bug-117966 regressions. This can be removed once the minimum GCC version is bumped to 12 in the previous releases task, see https://github.com/bitcoin/bitcoin/issues/31436#issuecomment-2530717875
export GOAL="install"

View File

@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
export CONTAINER_NAME=ci_native_fuzz
export APT_LLVM_V="20"
export APT_LLVM_V="21"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} libclang-rt-${APT_LLVM_V}-dev libevent-dev libboost-dev libsqlite3-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
@@ -19,9 +19,8 @@ export CI_CONTAINER_CAP="--cap-add SYS_PTRACE" # If run with (ASan + LSan), the
export BITCOIN_CONFIG="\
-DBUILD_FOR_FUZZING=ON \
-DSANITIZERS=fuzzer,address,undefined,float-divide-by-zero,integer \
-DCMAKE_C_COMPILER=clang-${APT_LLVM_V} \
-DCMAKE_CXX_COMPILER=clang++-${APT_LLVM_V} \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS='-ftrivial-auto-var-init=pattern' \
-DCMAKE_CXX_FLAGS='-ftrivial-auto-var-init=pattern' \
"
export LLVM_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-${APT_LLVM_V}"

View File

@@ -7,14 +7,16 @@
export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
LIBCXX_DIR="/msan/cxx_build/"
export APT_LLVM_V="21"
LIBCXX_DIR="/cxx_build/"
export MSAN_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O1 -fno-optimize-sibling-calls"
LIBCXX_FLAGS="-nostdinc++ -nostdlib++ -isystem ${LIBCXX_DIR}include/c++/v1 -L${LIBCXX_DIR}lib -Wl,-rpath,${LIBCXX_DIR}lib -lc++ -lc++abi -lpthread -Wno-unused-command-line-argument"
# -lstdc++ to resolve link issues due to upstream packaging
LIBCXX_FLAGS="-nostdinc++ -nostdlib++ -isystem ${LIBCXX_DIR}include/c++/v1 -L${LIBCXX_DIR}lib -Wl,-rpath,${LIBCXX_DIR}lib -lc++ -lc++abi -lpthread -Wno-unused-command-line-argument -lstdc++"
export MSAN_AND_LIBCXX_FLAGS="${MSAN_FLAGS} ${LIBCXX_FLAGS}"
export CONTAINER_NAME="ci_native_fuzz_msan"
export PACKAGES="ninja-build"
# BDB generates false-positives and will be removed in future
export PACKAGES="ninja-build clang-${APT_LLVM_V} llvm-${APT_LLVM_V} llvm-${APT_LLVM_V}-dev libclang-${APT_LLVM_V}-dev libclang-rt-${APT_LLVM_V}-dev"
export DEP_OPTS="DEBUG=1 NO_BDB=1 NO_QT=1 CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}'"
export GOAL="all"
# Setting CMAKE_{C,CXX}_FLAGS_DEBUG flags to an empty string ensures that the flags set in MSAN_FLAGS remain unaltered.
@@ -27,7 +29,7 @@ export BITCOIN_CONFIG="\
-DSANITIZERS=fuzzer,memory \
-DAPPEND_CPPFLAGS='-DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE -U_FORTIFY_SOURCE' \
"
export USE_MEMORY_SANITIZER="true"
export USE_INSTRUMENTED_LIBCPP="MemoryWithOrigins"
export RUN_UNIT_TESTS="false"
export RUN_FUNCTIONAL_TESTS="false"
export RUN_FUZZ_TESTS=true

View File

@@ -7,13 +7,14 @@
export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
LIBCXX_DIR="/msan/cxx_build/"
export APT_LLVM_V="21"
LIBCXX_DIR="/cxx_build/"
export MSAN_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O1 -fno-optimize-sibling-calls"
LIBCXX_FLAGS="-nostdinc++ -nostdlib++ -isystem ${LIBCXX_DIR}include/c++/v1 -L${LIBCXX_DIR}lib -Wl,-rpath,${LIBCXX_DIR}lib -lc++ -lc++abi -lpthread -Wno-unused-command-line-argument"
export MSAN_AND_LIBCXX_FLAGS="${MSAN_FLAGS} ${LIBCXX_FLAGS}"
export CONTAINER_NAME="ci_native_msan"
export PACKAGES="ninja-build"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} llvm-${APT_LLVM_V}-dev libclang-${APT_LLVM_V}-dev libclang-rt-${APT_LLVM_V}-dev ninja-build"
# BDB generates false-positives and will be removed in future
export DEP_OPTS="DEBUG=1 NO_BDB=1 NO_QT=1 CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}'"
export GOAL="install"
@@ -26,4 +27,4 @@ export BITCOIN_CONFIG="\
-DSANITIZERS=memory \
-DAPPEND_CPPFLAGS='-U_FORTIFY_SOURCE' \
"
export USE_MEMORY_SANITIZER="true"
export USE_INSTRUMENTED_LIBCPP="MemoryWithOrigins"

View File

@@ -8,9 +8,12 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_tsan
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
export APT_LLVM_V="20"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} libclang-rt-${APT_LLVM_V}-dev libc++abi-${APT_LLVM_V}-dev libc++-${APT_LLVM_V}-dev python3-zmq"
export DEP_OPTS="CC=clang-${APT_LLVM_V} CXX='clang++-${APT_LLVM_V} -stdlib=libc++'"
export APT_LLVM_V="21"
LIBCXX_DIR="/cxx_build/"
LIBCXX_FLAGS="-fsanitize=thread -nostdinc++ -nostdlib++ -isystem ${LIBCXX_DIR}include/c++/v1 -L${LIBCXX_DIR}lib -Wl,-rpath,${LIBCXX_DIR}lib -lc++ -lc++abi -lpthread -Wno-unused-command-line-argument"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} llvm-${APT_LLVM_V}-dev libclang-${APT_LLVM_V}-dev libclang-rt-${APT_LLVM_V}-dev python3-zmq ninja-build"
export DEP_OPTS="CC=clang CXX=clang++ CXXFLAGS='${LIBCXX_FLAGS}' NO_QT=1"
export GOAL="install"
export BITCOIN_CONFIG="-DWITH_ZMQ=ON -DSANITIZERS=thread \
-DAPPEND_CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER -DDEBUG_LOCKCONTENTION -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES'"
-DAPPEND_CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKCONTENTION -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES'"
export USE_INSTRUMENTED_LIBCPP="Thread"

View File

@@ -43,32 +43,24 @@ elif [ "$CI_OS_NAME" != "macos" ]; then
${CI_RETRY_EXE} bash -c "apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $CI_BASE_PACKAGES"
fi
if [ -n "${APT_LLVM_V}" ]; then
update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-${APT_LLVM_V}" 100
update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-${APT_LLVM_V}" 100
update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer "/usr/bin/llvm-symbolizer-${APT_LLVM_V}" 100
fi
if [ -n "$PIP_PACKAGES" ]; then
# shellcheck disable=SC2086
${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-20.1.0" /msan/llvm-project
if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then
${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-21.1.1" /llvm-project
cmake -G Ninja -B /msan/clang_build/ \
-DLLVM_ENABLE_PROJECTS="clang" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_TARGETS_TO_BUILD=Native \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" \
-S /msan/llvm-project/llvm
ninja -C /msan/clang_build/ "$MAKEJOBS"
ninja -C /msan/clang_build/ install-runtimes
update-alternatives --install /usr/bin/clang++ clang++ /msan/clang_build/bin/clang++ 100
update-alternatives --install /usr/bin/clang clang /msan/clang_build/bin/clang 100
update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /msan/clang_build/bin/llvm-symbolizer 100
cmake -G Ninja -B /msan/cxx_build/ \
cmake -G Ninja -B /cxx_build/ \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_USE_SANITIZER=MemoryWithOrigins \
-DLLVM_USE_SANITIZER="${USE_INSTRUMENTED_LIBCPP}" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_TARGETS_TO_BUILD=Native \
@@ -76,13 +68,13 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
-DLIBCXX_ABI_DEFINES="_LIBCPP_ABI_BOUNDED_ITERATORS;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR;_LIBCPP_ABI_BOUNDED_UNIQUE_PTR" \
-DLIBCXX_HARDENING_MODE=debug \
-S /msan/llvm-project/runtimes
-S /llvm-project/runtimes
ninja -C /msan/cxx_build/ "$MAKEJOBS"
ninja -C /cxx_build/ "$MAKEJOBS"
# Clear no longer needed source folder
du -sh /msan/llvm-project
rm -rf /msan/llvm-project
du -sh /llvm-project
rm -rf /llvm-project
fi
if [[ "${RUN_TIDY}" == "true" ]]; then

View File

@@ -23,34 +23,14 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
fi
echo "Creating $CI_IMAGE_NAME_TAG container to run in"
DOCKER_BUILD_CACHE_ARG=""
DOCKER_BUILD_CACHE_TEMPDIR=""
DOCKER_BUILD_CACHE_OLD_DIR=""
DOCKER_BUILD_CACHE_NEW_DIR=""
# If set, use an `docker build` cache directory on the CI host
# to cache docker image layers for the CI container image.
# This cache can be multiple GB in size. Prefixed with DANGER
# as setting it removes (old cache) files from the host.
if [ "$DANGER_DOCKER_BUILD_CACHE_HOST_DIR" ]; then
# Directory where the current cache for this run could be. If not existing
# or empty, "docker build" will warn, but treat it as cache-miss and continue.
DOCKER_BUILD_CACHE_OLD_DIR="${DANGER_DOCKER_BUILD_CACHE_HOST_DIR}/${CONTAINER_NAME}"
# Temporary directory for a newly created cache. We can't write the new
# cache into OLD_DIR directly, as old cache layers would not be removed.
# The NEW_DIR contents are moved to OLD_DIR after OLD_DIR has been cleared.
# This happens after `docker build`. If a task fails or is aborted, the
# DOCKER_BUILD_CACHE_TEMPDIR might be retained on the host. If the host isn't
# ephemeral, it has to take care of cleaning old TEMPDIR's up.
DOCKER_BUILD_CACHE_TEMPDIR="$(mktemp --directory ci-docker-build-cache-XXXXXXXXXX)"
DOCKER_BUILD_CACHE_NEW_DIR="${DOCKER_BUILD_CACHE_TEMPDIR}/${CONTAINER_NAME}"
DOCKER_BUILD_CACHE_ARG="--cache-from type=local,src=${DOCKER_BUILD_CACHE_OLD_DIR} --cache-to type=local,dest=${DOCKER_BUILD_CACHE_NEW_DIR},mode=max"
fi
# Use buildx unconditionally
# Using buildx is required to properly load the correct driver, for use with registry caching. Neither build, nor BUILDKIT=1 currently do this properly
# shellcheck disable=SC2086
DOCKER_BUILDKIT=1 docker build \
docker buildx build \
--file "${BASE_READ_ONLY_DIR}/ci/test_imagefile" \
--build-arg "CI_IMAGE_NAME_TAG=${CI_IMAGE_NAME_TAG}" \
--build-arg "FILE_ENV=${FILE_ENV}" \
--build-arg "BASE_ROOT_DIR=${BASE_ROOT_DIR}" \
$MAYBE_CPUSET \
--platform="${CI_IMAGE_PLATFORM}" \
--label="${CI_IMAGE_LABEL}" \
@@ -58,15 +38,6 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
$DOCKER_BUILD_CACHE_ARG \
"${BASE_READ_ONLY_DIR}"
if [ "$DANGER_DOCKER_BUILD_CACHE_HOST_DIR" ]; then
if [ -e "${DOCKER_BUILD_CACHE_NEW_DIR}/index.json" ]; then
echo "Removing the existing docker build cache in ${DOCKER_BUILD_CACHE_OLD_DIR}"
rm -rf "${DOCKER_BUILD_CACHE_OLD_DIR}"
echo "Moving the contents of ${DOCKER_BUILD_CACHE_NEW_DIR} to ${DOCKER_BUILD_CACHE_OLD_DIR}"
mv "${DOCKER_BUILD_CACHE_NEW_DIR}" "${DOCKER_BUILD_CACHE_OLD_DIR}"
fi
fi
docker volume create "${CONTAINER_NAME}_ccache" || true
docker volume create "${CONTAINER_NAME}_depends" || true
docker volume create "${CONTAINER_NAME}_depends_sources" || true

View File

@@ -24,6 +24,14 @@ fi
echo "Free disk space:"
df -h
# We force an install of linux-headers again here via $PACKAGES to fix any
# kernel mismatch between a cached docker image and the underlying host.
# This can happen occasionally on hosted runners if the runner image is updated.
if [[ "$CONTAINER_NAME" == "ci_native_asan" ]]; then
$CI_RETRY_EXE apt-get update
${CI_RETRY_EXE} bash -c "apt-get install --no-install-recommends --no-upgrade -y $PACKAGES"
fi
# What host to compile for. See also ./depends/README.md
# Tests that need cross-compilation export the appropriate HOST.
# Tests that run natively guess the host
@@ -92,7 +100,7 @@ fi
if [ -z "$NO_DEPENDS" ]; then
if [[ $CI_IMAGE_NAME_TAG == *centos* ]]; then
SHELL_OPTS="CONFIG_SHELL=/bin/ksh" # Temporarily use ksh instead of dash, until https://bugzilla.redhat.com/show_bug.cgi?id=2335416 is fixed.
SHELL_OPTS="CONFIG_SHELL=/bin/dash"
else
SHELL_OPTS="CONFIG_SHELL="
fi
@@ -129,6 +137,12 @@ bash -c "cmake -S $BASE_ROOT_DIR $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (cat $
bash -c "cmake --build . $MAKEJOBS --target all $GOAL" || ( echo "Build failure. Verbose build follows." && cmake --build . --target all "$GOAL" --verbose ; false )
bash -c "${PRINT_CCACHE_STATISTICS}"
if [ "$CI" = "true" ]; then
hit_rate=$(ccache -s | grep "Hits:" | head -1 | sed 's/.*(\(.*\)%).*/\1/')
if [ "${hit_rate%.*}" -lt 75 ]; then
echo "::notice title=low ccache hitrate::Ccache hit-rate in $CONTAINER_NAME was $hit_rate%"
fi
fi
du -sh "${DEPENDS_DIR}"/*/
du -sh "${PREVIOUS_RELEASES_DIR}"

View File

@@ -4,12 +4,16 @@
# See ci/README.md for usage.
ARG CI_IMAGE_NAME_TAG
# We never want scratch, but default arg silences a Warning
ARG CI_IMAGE_NAME_TAG=scratch
FROM ${CI_IMAGE_NAME_TAG}
ARG FILE_ENV
ENV FILE_ENV=${FILE_ENV}
ARG BASE_ROOT_DIR
ENV BASE_ROOT_DIR=${BASE_ROOT_DIR}
COPY ./ci/retry/retry /usr/bin/retry
COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh /ci_container_base/ci/test/

View File

@@ -36,6 +36,10 @@ if(USDT_INCLUDE_DIR)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${USDT_INCLUDE_DIR})
check_cxx_source_compiles("
#if defined(__arm__)
# define STAP_SDT_ARG_CONSTRAINT g
#endif
// Setting SDT_USE_VARIADIC lets systemtap (sys/sdt.h) know that we want to use
// the optional variadic macros to define tracepoints.
#define SDT_USE_VARIADIC 1

View File

@@ -465,18 +465,18 @@ if config.translations_dir:
sys.stderr.write(f"Error: Could not find translation dir \"{config.translations_dir[0]}\"\n")
sys.exit(1)
print("+ Adding Qt translations +")
print("+ Adding Qt translations +")
translations = Path(config.translations_dir[0])
translations = Path(config.translations_dir[0])
regex = re.compile('qt_[a-z]*(.qm|_[A-Z]*.qm)')
regex = re.compile('qt_[a-z]*(.qm|_[A-Z]*.qm)')
lang_files = [x for x in translations.iterdir() if regex.match(x.name)]
lang_files = [x for x in translations.iterdir() if regex.match(x.name)]
for file in lang_files:
if verbose:
print(file.as_posix(), "->", os.path.join(applicationBundle.resourcesPath, file.name))
shutil.copy2(file.as_posix(), os.path.join(applicationBundle.resourcesPath, file.name))
for file in lang_files:
if verbose:
print(file.as_posix(), "->", os.path.join(applicationBundle.resourcesPath, file.name))
shutil.copy2(file.as_posix(), os.path.join(applicationBundle.resourcesPath, file.name))
# ------------------------------------------------

View File

@@ -1,6 +1,6 @@
package=qt
$(package)_version=5.15.16
$(package)_download_path=https://download.qt.io/official_releases/qt/5.15/$($(package)_version)/submodules
$(package)_download_path=https://download.qt.io/archive/qt/5.15/$($(package)_version)/submodules
$(package)_suffix=everywhere-opensource-src-$($(package)_version).tar.xz
$(package)_file_name=qtbase-$($(package)_suffix)
$(package)_sha256_hash=b04815058c18058b6ba837206756a2c87d1391f07a0dcb0dd314f970fd041592

View File

@@ -30,7 +30,7 @@ Bitcoin Core requires one of the following compilers.
| [Fontconfig](../depends/packages/fontconfig.mk) (gui) | [link](https://www.freedesktop.org/wiki/Software/fontconfig/) | [2.12.6](https://github.com/bitcoin/bitcoin/pull/23495) | 2.6 | Yes |
| [FreeType](../depends/packages/freetype.mk) (gui) | [link](https://freetype.org) | [2.11.0](https://github.com/bitcoin/bitcoin/commit/01544dd78ccc0b0474571da854e27adef97137fb) | 2.3.0 | Yes |
| [qrencode](../depends/packages/qrencode.mk) (gui) | [link](https://fukuchi.org/works/qrencode/) | [4.1.1](https://github.com/bitcoin/bitcoin/pull/27312) | N/A | No |
| [Qt](../depends/packages/qt.mk) (gui) | [link](https://download.qt.io/official_releases/qt/) | [5.15.16](https://github.com/bitcoin/bitcoin/pull/30774) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No |
| [Qt](../depends/packages/qt.mk) (gui) | [link](https://download.qt.io/archive/qt/) | [5.15.16](https://github.com/bitcoin/bitcoin/pull/30774) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No |
| [ZeroMQ](../depends/packages/zeromq.mk) (notifications) | [link](https://github.com/zeromq/libzmq/releases) | [4.3.4](https://github.com/bitcoin/bitcoin/pull/23956) | 4.0.0 | No |
| [Berkeley DB](../depends/packages/bdb.mk) (legacy wallet) | [link](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.30 | 4.8.x | No |
| [SQLite](../depends/packages/sqlite.mk) (wallet) | [link](https://sqlite.org) | [3.38.5](https://github.com/bitcoin/bitcoin/pull/25378) | [3.7.17](https://github.com/bitcoin/bitcoin/pull/19077) | No |

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-CLI "1" "August 2025" "bitcoin-cli v29.1.0rc2" "User Commands"
.TH BITCOIN-CLI "1" "October 2025" "bitcoin-cli v29.2.0" "User Commands"
.SH NAME
bitcoin-cli \- manual page for bitcoin-cli v29.1.0rc2
bitcoin-cli \- manual page for bitcoin-cli v29.2.0
.SH SYNOPSIS
.B bitcoin-cli
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR]
@@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v29.1.0rc2
.B bitcoin-cli
[\fI\,options\/\fR] \fI\,help <command>\/\fR
.SH DESCRIPTION
Bitcoin Core RPC client version v29.1.0rc2
Bitcoin Core RPC client version v29.2.0
.PP
The bitcoin\-cli utility provides a command line interface to interact with a Bitcoin Core RPC server.
.PP

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-QT "1" "August 2025" "bitcoin-qt v29.1.0rc2" "User Commands"
.TH BITCOIN-QT "1" "October 2025" "bitcoin-qt v29.2.0" "User Commands"
.SH NAME
bitcoin-qt \- manual page for bitcoin-qt v29.1.0rc2
bitcoin-qt \- manual page for bitcoin-qt v29.2.0
.SH SYNOPSIS
.B bitcoin-qt
[\fI\,options\/\fR] [\fI\,URI\/\fR]
.SH DESCRIPTION
Bitcoin Core version v29.1.0rc2
Bitcoin Core version v29.2.0
.PP
The bitcoin\-qt application provides a graphical interface for interacting with Bitcoin Core.
.PP

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-TX "1" "August 2025" "bitcoin-tx v29.1.0rc2" "User Commands"
.TH BITCOIN-TX "1" "October 2025" "bitcoin-tx v29.2.0" "User Commands"
.SH NAME
bitcoin-tx \- manual page for bitcoin-tx v29.1.0rc2
bitcoin-tx \- manual page for bitcoin-tx v29.2.0
.SH SYNOPSIS
.B bitcoin-tx
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR]
@@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v29.1.0rc2
.B bitcoin-tx
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR]
.SH DESCRIPTION
Bitcoin Core bitcoin\-tx utility version v29.1.0rc2
Bitcoin Core bitcoin\-tx utility version v29.2.0
.PP
The bitcoin\-tx tool is used for creating and modifying bitcoin transactions.
.PP

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-UTIL "1" "August 2025" "bitcoin-util v29.1.0rc2" "User Commands"
.TH BITCOIN-UTIL "1" "October 2025" "bitcoin-util v29.2.0" "User Commands"
.SH NAME
bitcoin-util \- manual page for bitcoin-util v29.1.0rc2
bitcoin-util \- manual page for bitcoin-util v29.2.0
.SH SYNOPSIS
.B bitcoin-util
[\fI\,options\/\fR] [\fI\,command\/\fR]
@@ -9,7 +9,7 @@ bitcoin-util \- manual page for bitcoin-util v29.1.0rc2
.B bitcoin-util
[\fI\,options\/\fR] \fI\,grind <hex-block-header>\/\fR
.SH DESCRIPTION
Bitcoin Core bitcoin\-util utility version v29.1.0rc2
Bitcoin Core bitcoin\-util utility version v29.2.0
.PP
The bitcoin\-util tool provides bitcoin related functionality that does not rely on the ability to access a running node. Available [commands] are listed below.
.SH OPTIONS

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-WALLET "1" "August 2025" "bitcoin-wallet v29.1.0rc2" "User Commands"
.TH BITCOIN-WALLET "1" "October 2025" "bitcoin-wallet v29.2.0" "User Commands"
.SH NAME
bitcoin-wallet \- manual page for bitcoin-wallet v29.1.0rc2
bitcoin-wallet \- manual page for bitcoin-wallet v29.2.0
.SH SYNOPSIS
.B bitcoin-wallet
[\fI\,options\/\fR] \fI\,<command>\/\fR
.SH DESCRIPTION
Bitcoin Core bitcoin\-wallet utility version v29.1.0rc2
Bitcoin Core bitcoin\-wallet utility version v29.2.0
.PP
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
.PP

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIND "1" "August 2025" "bitcoind v29.1.0rc2" "User Commands"
.TH BITCOIND "1" "October 2025" "bitcoind v29.2.0" "User Commands"
.SH NAME
bitcoind \- manual page for bitcoind v29.1.0rc2
bitcoind \- manual page for bitcoind v29.2.0
.SH SYNOPSIS
.B bitcoind
[\fI\,options\/\fR]
.SH DESCRIPTION
Bitcoin Core daemon version v29.1.0rc2
Bitcoin Core daemon version v29.2.0
.PP
The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses.
.PP

View File

@@ -1,6 +1,6 @@
Bitcoin Core version 29.1rc2 is now available from:
Bitcoin Core version 29.2 is now available from:
<https://bitcoincore.org/bin/bitcoin-core-29.1/test.rc2/>
<https://bitcoincore.org/bin/bitcoin-core-29.2/>
This release includes various bug fixes and performance
improvements, as well as updated translations.
@@ -37,186 +37,55 @@ unsupported systems.
Notable changes
===============
### Mempool Policy
### P2P
- The maximum number of potentially executed legacy signature operations in a
single standard transaction is now limited to 2500. Signature operations in all
previous output scripts, in all input scripts, as well as all P2SH redeem
scripts (if there are any) are counted toward the limit. The new limit is
assumed to not affect any known typically formed standard transactions. The
change was done to prepare for a possible BIP54 deployment in the future.
- #32646 p2p: Add witness mutation check inside FillBlock
- #33296 net: check for empty header before calling FillBlock
- #33395 net: do not apply whitelist permissions to onion inbounds
- #32521 policy: make pathological transactions packed with legacy sigops non-standard
### Mempool
- The minimum block feerate (`-blockmintxfee`) has been changed to 1 satoshi per kvB. It can still be changed using the
configuration option.
- The default minimum relay feerate (`-minrelaytxfee`) and incremental relay feerate (`-incrementalrelayfee`) have been
changed to 100 satoshis per kvB. They can still be changed using their respective configuration options, but it is
recommended to change both together if you decide to do so.
- Other minimum feerates (e.g. the dust feerate, the minimum returned by the fee estimator, and all feerates used by
the wallet) remain unchanged. The mempool minimum feerate still changes in response to high volume.
- Note that unless these lower defaults are widely adopted across the network, transactions created with lower fee
rates are not guaranteed to propagate or confirm. The wallet feerates remain unchanged; `-mintxfee` must be changed
before attempting to create transactions with lower feerates using the wallet.
- #33106 policy: lower the default blockmintxfee, incrementalrelayfee, minrelaytxfee
### Logging
Unconditional logging to disk is now rate limited by giving each source location
a quota of 1MiB per hour. Unconditional logging is any logging with a log level
higher than debug, that is `info`, `warning`, and `error`. All logs will be
prefixed with `[*]` if there is at least one source location that is currently
being suppressed. (#32604)
When `-logsourcelocations` is enabled, the log output now contains the entire
function signature instead of just the function name. (#32604)
- #33504 mempool: Do not enforce TRUC checks on reorg
### RPC
- The `dumptxoutset` RPC now requires a `type` parameter to be specified. To maintain pre
v29.0 behavior, use the `latest` parameter. Documenting this change was missed in the v29.0
release notes. (#30808)
### Updated Settings
- The `-maxmempool` and `-dbcache` startup parameters are now capped on
32-bit systems to 500MB and 1GiB respectively.
- #32530 node: cap -maxmempool and -dbcache values for 32-bit
### Wallet
- #31757 wallet: fix crash on double block disconnection
- #32553 wallet: Fix logging of wallet version
### P2P
- #32826 p2p: add more bad ports
### Test
- #32069 test: fix intermittent failure in wallet_reorgsrestore.py
- #32286 test: Handle empty string returned by CLI as None in RPC tests
- #32312 test: Fix feature_pruning test after nTime typo fix
- #32336 test: Suppress upstream -Wduplicate-decl-specifier in bpfcc
- #32463 test: fix an incorrect feature_fee_estimation.py subtest
- #32483 test: fix two intermittent failures in wallet_basic.py
- #32630 test: fix sync function in rpc_psbt.py
- #32765 test: Fix list index out of range error in feature_bip68_sequence.py
- #32742 test: fix catchup loop in outbound eviction functional test
- #32823 test: Fix wait_for_getheaders() call in test_outbound_eviction_blocks_relay_only()
- #32833 test: Add msgtype to msg_generic slots
- #32841 feature_taproot: sample tx version border values more
- #32850 test: check P2SH sigop count for coinbase tx
- #32859 test: correctly detect nonstd TRUC tx vsize in feature_taproot
- #33001 test: Do not pass tests on unhandled exceptions
### Util
- #32248 Remove support for RNDR/RNDRRS for aarch64
### Build
- #32356 cmake: Respect user-provided configuration-specific flags
- #32437 crypto: disable ASan for sha256_sse4 with Clang
- #32469 cmake: Allow WITH_DBUS on all Unix-like systems
- #32439 guix: accomodate migration to codeberg
- #32551 cmake: Add missed SSE41_CXXFLAGS
- #32568 depends: use "mkdir -p" when installing xproto
- #32678 guix: warn and abort when SOURCE_DATE_EPOCH is set
- #32690 depends: fix SHA256SUM command on OpenBSD (use GNU mode output)
- #32716 depends: Override host compilers for FreeBSD and OpenBSD
- #32760 depends: capnp 1.2.0
- #32798 build: add root dir to CMAKE_PREFIX_PATH in toolchain
- #32805 cmake: Use HINTS instead of PATHS in find_* commands
- #32814 cmake: Explicitly specify Boost_ROOT for Homebrew's package
- #32837 depends: fix libevent _WIN32_WINNT usage
- #32943 depends: Force CMAKE_EXPORT_NO_PACKAGE_REGISTRY=TRUE
- #32954 cmake: Drop no longer necessary "cmakeMinimumRequired" object
- #33073 guix: warn SOURCE_DATE_EPOCH set in guix-codesign
### Gui
- #864 Crash fix, disconnect numBlocksChanged() signal during shutdown
- #868 Replace stray tfm::format to cerr with qWarning
### Doc
- #32333 doc: Add missing top-level description to pruneblockchain RPC
- #32353 doc: Fix fuzz test_runner.py path
- #32389 doc: Fix test_bitcoin path
- #32607 rpc: Note in fundrawtransaction doc, fee rate is for package
- #32679 doc: update tor docs to use bitcoind binary from path
- #32693 depends: fix cmake compatibility error for freetype
- #32696 doc: make -DWITH_ZMQ=ON explicit on build-unix.md
- #32708 rpc, doc: update listdescriptors RCP help
- #32711 doc: add missing packages for BSDs (cmake, gmake, curl) to depends/README.md
- #32719 doc, windows: CompanyName "Bitcoin" => "Bitcoin Core project"
- #32776 doc: taproot became always active in v24.0
- #32777 doc: fix Transifex 404s
- #32846 doc: clarify that the "-j N" goes after the "--build build" part
- #32858 doc: Add workaround for vcpkg issue with paths with embedded spaces
- #33070 doc/zmq: fix unix socket path example
- #33088 doc: move cmake -B build -LH up in Unix build docs
- #33133 rpc: fix getpeerinfo ping duration unit docs
- #33119 rpc: Fix 'getdescriptoractivity' RPCHelpMan, add test to verify fix
- #33446 rpc: fix getblock(header) returns target for tip
### CI
- #32184 ci: Add workaround for vcpkg's libevent package
- #32989 ci: Migrate CI to hosted Cirrus Runners
- #32999 ci: Use APT_LLVM_V in msan task
- #33099 ci: allow for any libc++ intrumentation & use it for TSAN
- #33258 ci: use LLVM 21
- #33364 ci: always use tag for LLVM checkout
### Doc
- #33484 doc: rpc: fix case typo in `finalizepsbt` help
### Misc
- #32187 refactor: Remove spurious virtual from final ~CZMQNotificationInterface
- #32454 tracing: fix invalid argument in mempool_monitor
- #32771 contrib: tracing: Fix read of pmsg_type in p2p_monitor.py
- #33086 contrib: [tracing] fix pointer argument handling in mempool_monitor.py
- #33310 trace: Workaround GCC bug compiling with old systemtap
- #33340 Fix benchmark CSV output
- #33482 contrib: fix macOS deployment with no translations
Credits
=======
Thanks to everyone who directly contributed to this release:
- 0xB10C
- achow101
- Antoine Poinsot
- benthecarman
- bigspider
- Brandon Odiwuor
- brunoerg
- Bufo
- Christewart
- Crypt-iQ
- davidgumberg
- deadmanoz
- dergoegge
- enirox001
- Amisha Chhajed
- Eugene Siegel
- fanquake
- furszy
- glozow
- instagibbs
- Greg Sanders
- Hennadii Stepanov
- hodlinator
- ismaelsadeeq
- jb55
- jlopp
- josibake
- laanwj
- luisschwab
- Luke Dashjr
- MarcoFalke
- Martin Zumsande
- monlovesmango
- nervana21
- pablomartin4btc
- rkrux
- romanz
- ryanofsky
- Sjors
- theStack
- willcl-ark
- zaidmstrr
- Sebastian Falbesoner
- Sjors Provoost
- Vasil Dimov
- Will Clark
As well as to everyone that helped with translations on
[Transifex](https://explore.transifex.com/bitcoin/bitcoin/).

View File

@@ -180,7 +180,7 @@ bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const
return txn_available[index] != nullptr;
}
ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing)
ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing, bool segwit_active)
{
if (header.IsNull()) return READ_STATUS_INVALID;
@@ -205,16 +205,11 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
if (vtx_missing.size() != tx_missing_offset)
return READ_STATUS_INVALID;
BlockValidationState state;
CheckBlockFn check_block = m_check_block_mock ? m_check_block_mock : CheckBlock;
if (!check_block(block, state, Params().GetConsensus(), /*fCheckPoW=*/true, /*fCheckMerkleRoot=*/true)) {
// TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
// check its own merkle root and cache that check.
if (state.GetResult() == BlockValidationResult::BLOCK_MUTATED)
return READ_STATUS_FAILED; // Possible Short ID collision
return READ_STATUS_CHECKBLOCK_FAILED;
// 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)) {
return READ_STATUS_FAILED; // Possible Short ID collision
}
LogDebug(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool (incl at least %lu from extra pool) and %lu txn requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size());

View File

@@ -84,8 +84,6 @@ typedef enum ReadStatus_t
READ_STATUS_OK,
READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap
READ_STATUS_FAILED, // Failed to process object
READ_STATUS_CHECKBLOCK_FAILED, // Used only by FillBlock to indicate a
// failure in CheckBlock.
} ReadStatus;
class CBlockHeaderAndShortTxIDs {
@@ -141,15 +139,16 @@ public:
CBlockHeader header;
// Can be overridden for testing
using CheckBlockFn = std::function<bool(const CBlock&, BlockValidationState&, const Consensus::Params&, bool, bool)>;
CheckBlockFn m_check_block_mock{nullptr};
using IsBlockMutatedFn = std::function<bool(const CBlock&, bool)>;
IsBlockMutatedFn m_check_block_mutated_mock{nullptr};
explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}
// extra_txn is a list of extra orphan/conflicted/etc transactions to look at
ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<CTransactionRef>& extra_txn);
bool IsTxAvailable(size_t index) const;
ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing);
// segwit_active enforces witness mutation checks just before reporting a healthy status
ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing, bool segwit_active);
};
#endif // BITCOIN_BLOCKENCODINGS_H

View File

@@ -627,7 +627,7 @@ std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implem
Transform = sha256_x86_shani::Transform;
TransformD64 = TransformD64Wrapper<sha256_x86_shani::Transform>;
TransformD64_2way = sha256d64_x86_shani::Transform_2way;
ret = "x86_shani(1way,2way)";
ret = "x86_shani(1way;2way)";
have_sse4 = false; // Disable SSE4/AVX2;
have_avx2 = false;
}
@@ -641,14 +641,14 @@ std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implem
#endif
#if defined(ENABLE_SSE41)
TransformD64_4way = sha256d64_sse41::Transform_4way;
ret += ",sse41(4way)";
ret += ";sse41(4way)";
#endif
}
#if defined(ENABLE_AVX2)
if (have_avx2 && have_avx && enabled_avx) {
TransformD64_8way = sha256d64_avx2::Transform_8way;
ret += ",avx2(8way)";
ret += ";avx2(8way)";
}
#endif
#endif // defined(HAVE_GETCPUID)
@@ -682,7 +682,7 @@ std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implem
Transform = sha256_arm_shani::Transform;
TransformD64 = TransformD64Wrapper<sha256_arm_shani::Transform>;
TransformD64_2way = sha256d64_arm_shani::Transform_2way;
ret = "arm_shani(1way,2way)";
ret = "arm_shani(1way;2way)";
}
#endif
#endif // DISABLE_OPTIMIZED_SHA256

View File

@@ -253,18 +253,13 @@ bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_ti
return false;
}
// In the case of a reorg, ensure persisted block locator is not stale.
// Don't commit here - the committed index state must never be ahead of the
// flushed chainstate, otherwise unclean restarts would lead to index corruption.
// Pruning has a minimum of 288 blocks-to-keep and getting the index
// out of sync may be possible but a users fault.
// In case we reorg beyond the pruned depth, ReadBlock would
// throw and lead to a graceful shutdown
SetBestBlockIndex(new_tip);
if (!Commit()) {
// If commit fails, revert the best block index to avoid corruption.
SetBestBlockIndex(current_tip);
return false;
}
return true;
}

View File

@@ -575,9 +575,9 @@ void CNode::CloseSocketDisconnect()
m_i2p_sam_session.reset();
}
void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr, const std::vector<NetWhitelistPermissions>& ranges) const {
void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional<CNetAddr> addr, const std::vector<NetWhitelistPermissions>& ranges) const {
for (const auto& subnet : ranges) {
if (subnet.m_subnet.Match(addr)) {
if (addr.has_value() && subnet.m_subnet.Match(addr.value())) {
NetPermissions::AddFlag(flags, subnet.m_flags);
}
}
@@ -1767,7 +1767,11 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
{
int nInbound = 0;
AddWhitelistPermissionFlags(permission_flags, addr, vWhitelistedRangeIncoming);
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
// Tor inbound connections do not reveal the peer's actual network address.
// Therefore do not apply address-based whitelist permissions to them.
AddWhitelistPermissionFlags(permission_flags, inbound_onion ? std::optional<CNetAddr>{} : addr, vWhitelistedRangeIncoming);
{
LOCK(m_nodes_mutex);
@@ -1822,7 +1826,6 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
// The V2Transport transparently falls back to V1 behavior when an incoming V1 connection is
// detected, so use it whenever we signal NODE_P2P_V2.
ServiceFlags local_services = GetLocalServices();

View File

@@ -1364,7 +1364,7 @@ private:
bool AttemptToEvictConnection();
CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr, const std::vector<NetWhitelistPermissions>& ranges) const;
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional<CNetAddr> addr, const std::vector<NetWhitelistPermissions>& ranges) const;
void DeleteNode(CNode* pnode);

View File

@@ -3314,7 +3314,21 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
}
PartiallyDownloadedBlock& partialBlock = *range_flight.first->second.second->partialBlock;
ReadStatus status = partialBlock.FillBlock(*pblock, block_transactions.txn);
if (partialBlock.header.IsNull()) {
// It is possible for the header to be empty if a previous call to FillBlock wiped the header, but left
// the PartiallyDownloadedBlock pointer around (i.e. did not call RemoveBlockRequest). In this case, we
// should not call LookupBlockIndex below.
RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId());
Misbehaving(peer, "previous compact block reconstruction attempt failed");
LogDebug(BCLog::NET, "Peer %d sent compact block transactions multiple times", pfrom.GetId());
return;
}
// We should not have gotten this far in compact block processing unless it's attached to a known header
const CBlockIndex* prev_block{Assume(m_chainman.m_blockman.LookupBlockIndex(partialBlock.header.hashPrevBlock))};
ReadStatus status = partialBlock.FillBlock(*pblock, block_transactions.txn,
/*segwit_active=*/DeploymentActiveAfter(prev_block, m_chainman, Consensus::DEPLOYMENT_SEGWIT));
if (status == READ_STATUS_INVALID) {
RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
Misbehaving(peer, "invalid compact block/non-matching block transactions");
@@ -3322,6 +3336,9 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
} else if (status == READ_STATUS_FAILED) {
if (first_in_flight) {
// Might have collided, fall back to getdata now :(
// We keep the failed partialBlock to disallow processing another compact block announcement from the same
// peer for the same block. We let the full block download below continue under the same m_downloading_since
// timer.
std::vector<CInv> invs;
invs.emplace_back(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash);
MakeAndPushMessage(pfrom, NetMsgType::GETDATA, invs);
@@ -3331,23 +3348,7 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
return;
}
} else {
// Block is either okay, or possibly we received
// READ_STATUS_CHECKBLOCK_FAILED.
// Note that CheckBlock can only fail for one of a few reasons:
// 1. bad-proof-of-work (impossible here, because we've already
// accepted the header)
// 2. merkleroot doesn't match the transactions given (already
// caught in FillBlock with READ_STATUS_FAILED, so
// impossible here)
// 3. the block is otherwise invalid (eg invalid coinbase,
// block is too big, too many legacy sigops, etc).
// So if CheckBlock failed, #3 is the only possibility.
// Under BIP 152, we don't discourage the peer unless proof of work is
// invalid (we don't require all the stateless checks to have
// been run). This is handled below, so just treat this as
// though the block was successfully read, and rely on the
// handling in ProcessNewBlock to ensure the block index is
// updated, etc.
// Block is okay for further processing
RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId()); // it is now an empty pointer
fBlockRead = true;
// mapBlockSource is used for potentially punishing peers and
@@ -4462,7 +4463,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
std::vector<CTransactionRef> dummy;
status = tempBlock.FillBlock(*pblock, dummy);
const CBlockIndex* prev_block{Assume(m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock))};
status = tempBlock.FillBlock(*pblock, dummy,
/*segwit_active=*/DeploymentActiveAfter(prev_block, m_chainman, Consensus::DEPLOYMENT_SEGWIT));
if (status == READ_STATUS_OK) {
fBlockReconstructed = true;
}

View File

@@ -44,9 +44,6 @@ public:
/**
* Construct a fee rate from a fee in satoshis and a vsize in vB.
*
* param@[in] nFeePaid The fee paid by a transaction, in satoshis
* param@[in] num_bytes The vsize of a transaction, in vbytes
*/
CFeeRate(const CAmount& nFeePaid, uint32_t num_bytes);

View File

@@ -164,7 +164,7 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
result.pushKV("mediantime", blockindex.GetMedianTimePast());
result.pushKV("nonce", blockindex.nNonce);
result.pushKV("bits", strprintf("%08x", blockindex.nBits));
result.pushKV("target", GetTarget(tip, pow_limit).GetHex());
result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex.nChainWork.GetHex());
result.pushKV("nTx", blockindex.nTx);

View File

@@ -1494,7 +1494,7 @@ static RPCHelpMan finalizepsbt()
return RPCHelpMan{"finalizepsbt",
"Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
"network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
"created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n"
"created which has the final_scriptSig and final_scriptwitness fields filled for inputs that are complete.\n"
"Implements the Finalizer and Extractor roles.\n",
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},

View File

@@ -95,21 +95,21 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
CBlock block2;
{
PartiallyDownloadedBlock tmp = partialBlock;
BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
BOOST_CHECK(partialBlock.FillBlock(block2, {}, /*segwit_active=*/true) == READ_STATUS_INVALID); // No transactions
partialBlock = tmp;
}
// Wrong transaction
{
PartiallyDownloadedBlock tmp = partialBlock;
partialBlock.FillBlock(block2, {block.vtx[2]}); // Current implementation doesn't check txn here, but don't require that
partialBlock.FillBlock(block2, {block.vtx[2]}, /*segwit_active=*/true); // Current implementation doesn't check txn here, but don't require that
partialBlock = tmp;
}
bool mutated;
BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
CBlock block3;
BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK);
BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}, /*segwit_active=*/true) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
BOOST_CHECK(!mutated);
@@ -182,14 +182,14 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
CBlock block2;
{
PartiallyDownloadedBlock tmp = partialBlock;
BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
BOOST_CHECK(partialBlock.FillBlock(block2, {}, /*segwit_active=*/true) == READ_STATUS_INVALID); // No transactions
partialBlock = tmp;
}
// Wrong transaction
{
PartiallyDownloadedBlock tmp = partialBlock;
partialBlock.FillBlock(block2, {block.vtx[1]}); // Current implementation doesn't check txn here, but don't require that
partialBlock.FillBlock(block2, {block.vtx[1]}, /*segwit_active=*/true); // Current implementation doesn't check txn here, but don't require that
partialBlock = tmp;
}
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 2); // +2 because of partialBlock and block2
@@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
CBlock block3;
PartiallyDownloadedBlock partialBlockCopy = partialBlock;
BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK);
BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}, /*segwit_active=*/true) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
BOOST_CHECK(!mutated);
@@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
CBlock block2;
PartiallyDownloadedBlock partialBlockCopy = partialBlock;
BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK);
BOOST_CHECK(partialBlock.FillBlock(block2, {}, /*segwit_active=*/true) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
bool mutated;
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
@@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
CBlock block2;
std::vector<CTransactionRef> vtx_missing;
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing, /*segwit_active=*/true) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
BOOST_CHECK(!mutated);

View File

@@ -324,7 +324,7 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool)
return ProcessNewPackage(chainstate, tx_pool, txs, /*test_accept=*/single_submit, /*client_maxfeerate=*/{}));
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, txs.back(), GetTime(),
/*bypass_limits=*/fuzzed_data_provider.ConsumeBool(), /*test_accept=*/!single_submit));
/*bypass_limits=*/false, /*test_accept=*/!single_submit));
if (!single_submit && result_package.m_state.GetResult() != PackageValidationResult::PCKG_POLICY) {
// We don't know anything about the validity since transactions were randomly generated, so

View File

@@ -32,14 +32,10 @@ void initialize_pdb()
g_setup = testing_setup.get();
}
PartiallyDownloadedBlock::CheckBlockFn FuzzedCheckBlock(std::optional<BlockValidationResult> result)
PartiallyDownloadedBlock::IsBlockMutatedFn FuzzedIsBlockMutated(bool result)
{
return [result](const CBlock&, BlockValidationState& state, const Consensus::Params&, bool, bool) {
if (result) {
return state.Invalid(*result);
}
return true;
return [result](const CBlock& block, bool) {
return result;
};
}
@@ -111,36 +107,22 @@ FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
skipped_missing |= (!pdb.IsTxAvailable(i) && skip);
}
// Mock CheckBlock
bool fail_check_block{fuzzed_data_provider.ConsumeBool()};
auto validation_result =
fuzzed_data_provider.PickValueInArray(
{BlockValidationResult::BLOCK_RESULT_UNSET,
BlockValidationResult::BLOCK_CONSENSUS,
BlockValidationResult::BLOCK_CACHED_INVALID,
BlockValidationResult::BLOCK_INVALID_HEADER,
BlockValidationResult::BLOCK_MUTATED,
BlockValidationResult::BLOCK_MISSING_PREV,
BlockValidationResult::BLOCK_INVALID_PREV,
BlockValidationResult::BLOCK_TIME_FUTURE,
BlockValidationResult::BLOCK_CHECKPOINT,
BlockValidationResult::BLOCK_HEADER_LOW_WORK});
pdb.m_check_block_mock = FuzzedCheckBlock(
fail_check_block ?
std::optional<BlockValidationResult>{validation_result} :
std::nullopt);
bool segwit_active{fuzzed_data_provider.ConsumeBool()};
// Mock IsBlockMutated
bool fail_block_mutated{fuzzed_data_provider.ConsumeBool()};
pdb.m_check_block_mutated_mock = FuzzedIsBlockMutated(fail_block_mutated);
CBlock reconstructed_block;
auto fill_status{pdb.FillBlock(reconstructed_block, missing)};
auto fill_status{pdb.FillBlock(reconstructed_block, missing, segwit_active)};
switch (fill_status) {
case READ_STATUS_OK:
assert(!skipped_missing);
assert(!fail_check_block);
assert(!fail_block_mutated);
assert(block->GetHash() == reconstructed_block.GetHash());
break;
case READ_STATUS_CHECKBLOCK_FAILED: [[fallthrough]];
case READ_STATUS_FAILED:
assert(fail_check_block);
assert(fail_block_mutated);
break;
case READ_STATUS_INVALID:
break;

View File

@@ -295,7 +295,6 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
std::set<CTransactionRef> added;
auto txr = std::make_shared<TransactionsDelta>(removed, added);
node.validation_signals->RegisterSharedValidationInterface(txr);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
// Make sure ProcessNewPackage on one transaction works.
// The result is not guaranteed to be the same as what is returned by ATMP.
@@ -310,7 +309,7 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
it->second.m_result_type == MempoolAcceptResult::ResultType::INVALID);
}
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), /*bypass_limits=*/false, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
node.validation_signals->SyncWithValidationInterfaceQueue();
node.validation_signals->UnregisterSharedValidationInterface(txr);
@@ -393,6 +392,9 @@ FUZZ_TARGET(tx_pool, .init = initialize_tx_pool)
chainstate.SetMempool(&tx_pool);
// If we ever bypass limits, do not do TRUC invariants checks
bool ever_bypassed_limits{false};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
{
const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids);
@@ -411,13 +413,17 @@ FUZZ_TARGET(tx_pool, .init = initialize_tx_pool)
tx_pool.PrioritiseTransaction(txid.ToUint256(), delta);
}
const bool bypass_limits{fuzzed_data_provider.ConsumeBool()};
ever_bypassed_limits |= bypass_limits;
const auto tx = MakeTransactionRef(mut_tx);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
if (accepted) {
txids.push_back(tx->GetHash());
CheckMempoolTRUCInvariants(tx_pool);
if (!ever_bypassed_limits) {
CheckMempoolTRUCInvariants(tx_pool);
}
}
}
Finish(fuzzed_data_provider, tx_pool, chainstate);

View File

@@ -9,6 +9,13 @@
#ifdef ENABLE_TRACING
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103395
// systemtap 4.6 on 32-bit ARM triggers internal compiler error
// (this workaround is included in systemtap 4.7+)
#if defined(__arm__)
# define STAP_SDT_ARG_CONSTRAINT g
#endif
// Setting SDT_USE_VARIADIC lets systemtap (sys/sdt.h) know that we want to use
// the optional variadic macros to define tracepoints.
#define SDT_USE_VARIADIC 1

View File

@@ -1025,26 +1025,28 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Even though just checking direct mempool parents for inheritance would be sufficient, we
// check using the full ancestor set here because it's more convenient to use what we have
// already calculated.
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
// Single transaction contexts only.
if (args.m_allow_sibling_eviction && err->second != nullptr) {
// We should only be considering where replacement is considered valid as well.
Assume(args.m_allow_replacement);
if (!args.m_bypass_limits) {
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
// Single transaction contexts only.
if (args.m_allow_sibling_eviction && err->second != nullptr) {
// We should only be considering where replacement is considered valid as well.
Assume(args.m_allow_replacement);
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
// included in RBF checks.
ws.m_conflicts.insert(err->second->GetHash());
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
ws.m_iters_conflicting.insert(m_pool.GetIter(err->second->GetHash()).value());
ws.m_sibling_eviction = true;
// The sibling will be treated as part of the to-be-replaced set in ReplacementChecks.
// Note that we are not checking whether it opts in to replaceability via BIP125 or TRUC
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
} else {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
// included in RBF checks.
ws.m_conflicts.insert(err->second->GetHash());
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
ws.m_iters_conflicting.insert(m_pool.GetIter(err->second->GetHash()).value());
ws.m_sibling_eviction = true;
// The sibling will be treated as part of the to-be-replaced set in ReplacementChecks.
// Note that we are not checking whether it opts in to replaceability via BIP125 or TRUC
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
} else {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
}
}
}

View File

@@ -589,15 +589,15 @@ util::Result<SelectionResult> SelectCoinsSRD(const std::vector<OutputGroup>& utx
/** Find a subset of the OutputGroups that is at least as large as, but as close as possible to, the
* target amount; solve subset sum.
* param@[in] groups OutputGroups to choose from, sorted by value in descending order.
* param@[in] nTotalLower Total (effective) value of the UTXOs in groups.
* param@[in] nTargetValue Subset sum target, not including change.
* param@[out] vfBest Boolean vector representing the subset chosen that is closest to
* @param[in] groups OutputGroups to choose from, sorted by value in descending order.
* @param[in] nTotalLower Total (effective) value of the UTXOs in groups.
* @param[in] nTargetValue Subset sum target, not including change.
* @param[out] vfBest Boolean vector representing the subset chosen that is closest to
* nTargetValue, with indices corresponding to groups. If the ith
* entry is true, that means the ith group in groups was selected.
* param@[out] nBest Total amount of subset chosen that is closest to nTargetValue.
* paramp[in] max_selection_weight The maximum allowed weight for a selection result to be valid.
* param@[in] iterations Maximum number of tries.
* @param[out] nBest Total amount of subset chosen that is closest to nTargetValue.
* @param[in] max_selection_weight The maximum allowed weight for a selection result to be valid.
* @param[in] iterations Maximum number of tries.
*/
static void ApproximateBestSubset(FastRandomContext& insecure_rand, const std::vector<OutputGroup>& groups,
const CAmount& nTotalLower, const CAmount& nTargetValue,

View File

@@ -123,14 +123,14 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet,
* the solution (according to the waste metric) will be chosen. If a valid input cannot be found from any
* single OutputType, fallback to running `ChooseSelectionResult()` over all available coins.
*
* param@[in] chain The chain interface to get information on unconfirmed UTXOs bump fees
* param@[in] nTargetValue The target value
* param@[in] groups The grouped outputs mapped by coin eligibility filters
* param@[in] coin_selection_params Parameters for the coin selection
* param@[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType
* @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs
* @param[in] nTargetValue The target value
* @param[in] groups The grouped outputs mapped by coin eligibility filters
* @param[in] coin_selection_params Parameters for the coin selection
* @param[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType
* returns If successful, a SelectionResult containing the input set
* If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
* or (2) an specific error message if there was something particularly wrong (e.g. a selection
* or (2) a specific error message if there was something particularly wrong (e.g. a selection
* result that surpassed the tx max weight size).
*/
util::Result<SelectionResult> AttemptSelection(interfaces::Chain& chain, const CAmount& nTargetValue, OutputGroupTypeMap& groups,
@@ -141,13 +141,13 @@ util::Result<SelectionResult> AttemptSelection(interfaces::Chain& chain, const C
* Multiple coin selection algorithms will be run and the input set that produces the least waste
* (according to the waste metric) will be chosen.
*
* param@[in] chain The chain interface to get information on unconfirmed UTXOs bump fees
* param@[in] nTargetValue The target value
* param@[in] groups The struct containing the outputs grouped by script and divided by (1) positive only outputs and (2) all outputs (positive + negative).
* param@[in] coin_selection_params Parameters for the coin selection
* @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs
* @param[in] nTargetValue The target value
* @param[in] groups The struct containing the outputs grouped by script and divided by (1) positive only outputs and (2) all outputs (positive + negative).
* @param[in] coin_selection_params Parameters for the coin selection
* returns If successful, a SelectionResult containing the input set
* If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
* or (2) an specific error message if there was something particularly wrong (e.g. a selection
* or (2) a specific error message if there was something particularly wrong (e.g. a selection
* result that surpassed the tx max weight size).
*/
util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, const CAmount& nTargetValue, Groups& groups, const CoinSelectionParams& coin_selection_params);
@@ -181,10 +181,10 @@ util::Result<PreSelectedInputs> FetchSelectedInputs(const CWallet& wallet, const
/**
* Select a set of coins such that nTargetValue is met; never select unconfirmed coins if they are not ours
* param@[in] wallet The wallet which provides data necessary to spend the selected coins
* param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
* param@[in] nTargetValue The target value
* param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
* @param[in] wallet The wallet which provides data necessary to spend the selected coins
* @param[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
* @param[in] nTargetValue The target value
* @param[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
* and whether to subtract the fee from the outputs.
* returns If successful, a SelectionResult containing the selected coins
* If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")

View File

@@ -11,9 +11,10 @@ The alternate mainnet chain was generated as follows:
- restart node with a faketime 2 minutes later
```sh
for i in {1..2015}
for i in {1..2016}
do
faketime "`date -d @"$(( 1231006505 + $i * 120 ))" +'%Y-%m-%d %H:%M:%S'`" \
t=$(( 1231006505 + $i * 120 ))
faketime "`date -d @$t +'%Y-%m-%d %H:%M:%S'`" \
bitcoind -connect=0 -nocheckpoints -stopatheight=$i
done
```
@@ -21,7 +22,9 @@ done
The CPU miner is kept running as follows:
```sh
./minerd --coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r --no-stratum --algo sha256d --no-longpoll --scantime 3 --retry-pause 1
./minerd -u ... -p ... -o http://127.0.0.1:8332 --no-stratum \
--coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r \
--algo sha256d --no-longpoll --scantime 3 --retry-pause 1
```
The payout address is derived from first BIP32 test vector master key:
@@ -40,3 +43,8 @@ The timestamp was not kept constant because at difficulty 1 it's not sufficient
to only grind the nonce. Grinding the extra_nonce or version field instead
would have required additional (stratum) software. It would also make it more
complicated to reconstruct the blocks in this test.
The `getblocktemplate` RPC code needs to be patched to ignore not being connected
to any peers, and to ignore the IBD status check.
On macOS use `faketime "@$t"` instead.

View File

@@ -2014,7 +2014,8 @@
1231247971,
1231248071,
1231248198,
1231248322
1231248322,
1231248621
],
"nonces": [
2345621585,
@@ -4031,6 +4032,7 @@
3658502865,
2519048297,
1915965760,
1183846025
1183846025,
2713372123
]
}

View File

@@ -322,6 +322,21 @@ class CoinStatsIndexTest(BitcoinTestFramework):
res1 = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=None, use_index=True)
assert_equal(res["muhash"], res1["muhash"])
self.log.info("Test index with an unclean restart after a reorg")
self.restart_node(1, extra_args=self.extra_args[1])
committed_height = index_node.getblockcount()
self.generate(index_node, 2, sync_fun=self.no_op)
self.sync_index_node()
block2 = index_node.getbestblockhash()
index_node.invalidateblock(block2)
self.generatetoaddress(index_node, 1, getnewdestination()[2], sync_fun=self.no_op)
self.sync_index_node()
index_node.kill_process()
self.start_node(1, extra_args=self.extra_args[1])
self.sync_index_node()
# Because of the unclean shutdown above, indexes reset to the point we last committed them to disk.
assert_equal(index_node.getindexinfo()['coinstatsindex']['best_block_height'], committed_height)
if __name__ == '__main__':
CoinStatsIndexTest(__file__).main()

View File

@@ -164,23 +164,36 @@ class MempoolTRUC(BitcoinTestFramework):
def test_truc_reorg(self):
node = self.nodes[0]
self.log.info("Test that, during a reorg, TRUC rules are not enforced")
tx_v2_block = self.wallet.send_self_transfer(from_node=node, version=2)
tx_v3_block = self.wallet.send_self_transfer(from_node=node, version=3)
tx_v3_block2 = self.wallet.send_self_transfer(from_node=node, version=3)
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"]])
self.check_mempool([])
# Testing 2<-3 versions allowed
tx_v2_block = self.wallet.create_self_transfer(version=2)
# Testing 3<-2 versions allowed
tx_v3_block = self.wallet.create_self_transfer(version=3)
# Testing overly-large child size
tx_v3_block2 = self.wallet.create_self_transfer(version=3)
# Also create a linear chain of 3 TRUC transactions that will be directly mined, followed by one v2 in-mempool after block is made
tx_chain_1 = self.wallet.create_self_transfer(version=3)
tx_chain_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_1["new_utxo"], version=3)
tx_chain_3 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_2["new_utxo"], version=3)
tx_to_mine = [tx_v3_block["hex"], tx_v2_block["hex"], tx_v3_block2["hex"], tx_chain_1["hex"], tx_chain_2["hex"], tx_chain_3["hex"]]
block = self.generateblock(node, output="raw(42)", transactions=tx_to_mine)
block = self.generate(node, 1)
self.check_mempool([])
tx_v2_from_v3 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block["new_utxo"], version=2)
tx_v3_from_v2 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v2_block["new_utxo"], version=3)
tx_v3_child_large = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block2["new_utxo"], target_vsize=1250, version=3)
assert_greater_than(node.getmempoolentry(tx_v3_child_large["txid"])["vsize"], TRUC_CHILD_MAX_VSIZE)
self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"]])
node.invalidateblock(block[0])
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"], tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"]])
# This is needed because generate() will create the exact same block again.
node.reconsiderblock(block[0])
tx_chain_4 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_chain_3["new_utxo"], version=2)
self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_4["txid"]])
# Reorg should have all block transactions re-accepted, ignoring TRUC enforcement
node.invalidateblock(block["hash"])
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"], tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_1["txid"], tx_chain_2["txid"], tx_chain_3["txid"], tx_chain_4["txid"]])
@cleanup(extra_args=["-limitdescendantsize=10", "-datacarriersize=40000"])
def test_nondefault_package_limits(self):

View File

@@ -54,15 +54,15 @@ class MiningMainnetTest(BitcoinTestFramework):
self.add_wallet_options(parser)
def mine(self, height, prev_hash, blocks, node, fees=0):
def mine(self, height, prev_hash, blocks, node):
self.log.debug(f"height={height}")
block = CBlock()
block.nVersion = 0x20000000
block.hashPrevBlock = int(prev_hash, 16)
block.nTime = blocks['timestamps'][height - 1]
block.nBits = DIFF_1_N_BITS
block.nBits = DIFF_1_N_BITS if height < 2016 else DIFF_4_N_BITS
block.nNonce = blocks['nonces'][height - 1]
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), retarget_period=2016)]
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), halving_period=210000)]
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
block_hex = block.serialize(with_witness=False).hex()
@@ -81,12 +81,15 @@ class MiningMainnetTest(BitcoinTestFramework):
self.log.info("Load alternative mainnet blocks")
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
prev_hash = node.getbestblockhash()
blocks = None
with open(path, encoding='utf-8') as f:
blocks = json.load(f)
n_blocks = len(blocks['timestamps'])
assert_equal(n_blocks, 2015)
for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
assert_equal(n_blocks, 2016)
# Mine up to the last block of the first retarget period
for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
assert_equal(node.getblockcount(), 2015)
@@ -101,5 +104,21 @@ class MiningMainnetTest(BitcoinTestFramework):
assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS))
assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET))
# Mine first block of the second retarget period
height = 2016
prev_hash = self.mine(height, prev_hash, blocks, node)
assert_equal(node.getblockcount(), height)
mining_info = node.getmininginfo()
assert_equal(mining_info['difficulty'], 4)
self.log.info("getblock RPC should show historical target")
block_info = node.getblock(node.getblockhash(1))
assert_equal(block_info['difficulty'], 1)
assert_equal(block_info['bits'], nbits_str(DIFF_1_N_BITS))
assert_equal(block_info['target'], target_str(DIFF_1_TARGET))
if __name__ == '__main__':
MiningMainnetTest(__file__).main()

View File

@@ -566,6 +566,42 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.send_and_ping(msg_block(block))
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
# Multiple blocktxn responses will cause a node to get disconnected.
def test_multiple_blocktxn_response(self, test_node):
node = self.nodes[0]
utxo = self.utxos[0]
block = self.build_block_with_transactions(node, utxo, 2)
# Send compact block
comp_block = HeaderAndShortIDs()
comp_block.initialize_from_block(block, prefill_list=[0], use_witness=True)
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
absolute_indexes = []
with p2p_lock:
assert "getblocktxn" in test_node.last_message
absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute()
assert_equal(absolute_indexes, [1, 2])
# Send a blocktxn that does not succeed in reconstruction, triggering
# getdata fallback.
msg = msg_blocktxn()
msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[2]] + [block.vtx[1]])
test_node.send_and_ping(msg)
# Tip should not have updated
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock)
# We should receive a getdata request
test_node.wait_for_getdata([block.sha256], timeout=10)
assert test_node.last_message["getdata"].inv[0].type == MSG_BLOCK or \
test_node.last_message["getdata"].inv[0].type == MSG_BLOCK | MSG_WITNESS_FLAG
# Send the same blocktxn and assert the sender gets disconnected.
with node.assert_debug_log(['previous compact block reconstruction attempt failed']):
test_node.send_message(msg)
test_node.wait_for_disconnect()
def test_getblocktxn_handler(self, test_node):
node = self.nodes[0]
# bitcoind will not send blocktxn responses for blocks whose height is
@@ -957,6 +993,12 @@ class CompactBlocksTest(BitcoinTestFramework):
self.log.info("Testing handling of invalid compact blocks...")
self.test_invalid_tx_in_compactblock(self.segwit_node)
self.log.info("Testing handling of multiple blocktxn responses...")
self.test_multiple_blocktxn_response(self.segwit_node)
# The previous test will lead to a disconnection. Reconnect before continuing.
self.segwit_node = self.nodes[0].add_p2p_connection(TestP2PConn())
self.log.info("Testing invalid index in cmpctblock message...")
self.test_invalid_cmpctblock_message()

View File

@@ -143,7 +143,7 @@ def script_BIP34_coinbase_height(height):
return CScript([CScriptNum(height)])
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, retarget_period=REGTEST_RETARGET_PERIOD):
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, halving_period=REGTEST_RETARGET_PERIOD):
"""Create a coinbase transaction.
If pubkey is passed in, the coinbase output will be a P2PK output;
@@ -156,7 +156,7 @@ def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_scr
coinbaseoutput = CTxOut()
coinbaseoutput.nValue = nValue * COIN
if nValue == 50:
halvings = int(height / retarget_period)
halvings = int(height / halving_period)
coinbaseoutput.nValue >>= halvings
coinbaseoutput.nValue += fees
if pubkey is not None: