Compare commits

..

121 Commits

Author SHA1 Message Date
merge-script
4d7d5f6b79 Merge bitcoin/bitcoin#34229: [30.2] Backports & Final
04a996b1a7 doc: update manual pages for v30.2 (fanquake)
ed355b8f57 build: bump version to v30.2 (fanquake)
6c98d68be1 doc: update release notes for v30.2 (fanquake)
6d86b32e78 guix: Fix `osslsigncode` tests (Hennadii Stepanov)
1dae0027cd wallet: test: Failed migration cleanup (David Gumberg)
9e59047a7e test: migration, avoid backup name mismatch in default_wallet_failure (furszy)

Pull request description:

  Backports:
  * #34221
  * #34226
  * #34227

ACKs for top commit:
  hebasto:
    ACK 04a996b1a7, I have reviewed the code and it looks OK.
  willcl-ark:
    ACK 04a996b1a7
  marcofleon:
    ACK 04a996b1a7

Tree-SHA512: 3389b9b629dcb920186b383353fd386bb757967d224e0267501b5e2083dc1e6cba051df6ef646de05c0e58fd43c9f549b9175eefb77fed1fe9ab7d1648b2d9e7
2026-01-09 14:04:54 +00:00
fanquake
04a996b1a7 doc: update manual pages for v30.2 2026-01-09 11:23:01 +00:00
fanquake
ed355b8f57 build: bump version to v30.2 2026-01-09 11:17:00 +00:00
fanquake
6c98d68be1 doc: update release notes for v30.2 2026-01-09 11:16:32 +00:00
Hennadii Stepanov
6d86b32e78 guix: Fix osslsigncode tests
Github-Pull: #34227
Rebased-From: 194114daf3
2026-01-09 11:15:58 +00:00
David Gumberg
1dae0027cd wallet: test: Failed migration cleanup
Refactor a common way to perform the failed migration test that exists
for default wallets, and add relative-path wallets and absolute-path
wallets.

Github-Pull: #34226
Rebased-From: eeaf28dbe0
2026-01-09 10:11:19 +00:00
furszy
9e59047a7e test: migration, avoid backup name mismatch in default_wallet_failure
The test calls migrate_and_get_rpc(), which sets mock time internally.
The caller caches a mock time value and later relies on it to predict the
backup filename, so setting the mock time again could cause a naming
mismatch.

Fix this by calling the migration RPC directly. Since the test expects the
migration to fail, migrate_and_get_rpc() is unnecessary here.

Github-Pull: #34221
Rebased-From: cbf0bd35bb
2026-01-08 10:21:49 +00:00
merge-script
abb6ae2ec5 Merge bitcoin/bitcoin#34209: [30.x]: Final backports & 30.2rc1
483d158f53 doc: update manual pages for v30.2rc1 (fanquake)
747a863f5b build: bump version to v30.2rc1 (fanquake)
cc3cdbe921 doc: update release notes for v30.2rc1 (fanquake)
c4082a45e6 wallettool: do not use fs::remove_all in createfromdump cleanup (Ava Chow)
185ca0e391 test: coverage for migration failure when last sync is beyond prune height (furszy)
bc71372c0e wallet: migration, fix watch-only and solvables wallets names (furszy)
bef4b1fdee wallet: improve post-migration logging (furszy)
ac940ac2ca test: restorewallet, coverage for existing dirs, unnamed wallet and prune failure (furszy)
8e5c02a77f test: add coverage for unnamed wallet migration failure (furszy)
ac4d0956cc wallet: fix unnamed wallet migration failure (furszy)
454ac8e7db wallet: RestoreWallet failure, erase only what was created (furszy)

Pull request description:

  Backports:
  * #34156
  * #34215

ACKs for top commit:
  darosior:
    ACK 483d158f53
  willcl-ark:
    tACK 483d158f53
  janb84:
    ACK 483d158f53
  w0xlt:
    ACK 483d158f53
  marcofleon:
    lgtm ACK 483d158f53

Tree-SHA512: b43485a8745a663d3a031113a6a266af699b3e70b77f72a0e69ea1986adcaa0ee0d4ce51aacd0fde91611cb4bdba9b6be52e5dca59ff8b12135715b8b1ed5ef2
2026-01-07 15:44:56 +00:00
fanquake
483d158f53 doc: update manual pages for v30.2rc1 2026-01-07 14:34:29 +00:00
fanquake
747a863f5b build: bump version to v30.2rc1 2026-01-07 14:34:28 +00:00
fanquake
cc3cdbe921 doc: update release notes for v30.2rc1 2026-01-07 14:34:24 +00:00
Ava Chow
c4082a45e6 wallettool: do not use fs::remove_all in createfromdump cleanup
Github-Pull: #34215
Rebased-From: f78f6f1dc8
2026-01-07 14:33:39 +00:00
furszy
185ca0e391 test: coverage for migration failure when last sync is beyond prune height
Github-Pull: #34156
Rebased-From: b7c34d08dd
2026-01-07 11:20:07 +00:00
furszy
bc71372c0e wallet: migration, fix watch-only and solvables wallets names
Because the default wallet has no name, the watch-only and solvables
wallets created during migration end up having no name either.

This fixes it by applying the same prefix name we use for the backup
file for an unnamed default wallet.

Before: watch-only wallet named "_watchonly"
After:  watch-only wallet named "default_wallet_watchonly"

Github-Pull: #34156
Rebased-From: 82caa8193a
2026-01-07 11:20:04 +00:00
furszy
bef4b1fdee wallet: improve post-migration logging
Right now, after migration the last message users see is "migration completed",
but the migration isn't actually finished yet. We still need to load the new wallets
to ensure consistency, and if that fails, the migration will be rolled back. This
can be confusing for users.

This change logs the post-migration loading step and if a wallet fails to load and
the migration will be rolled back.

Github-Pull: #34156
Rebased-From: d70b159c42
2026-01-07 11:20:00 +00:00
furszy
ac940ac2ca test: restorewallet, coverage for existing dirs, unnamed wallet and prune failure
The first test verifies that restoring into an existing empty directory
or a directory with no .dat db files succeeds, while restoring into a
dir with a .dat file fails.

The second test covers restoring into the default unnamed wallet
(wallet.dat), which also implicitly exercises the recovery path used
after a failed migration.

The third test covers failure during restore on a prune node. When
the wallet last sync was beyond the pruning height.

Github-Pull: #34156
Rebased-From: f011e0f068
2026-01-07 11:19:57 +00:00
furszy
8e5c02a77f test: add coverage for unnamed wallet migration failure
Verifies that a failed migration of the unnamed (default) wallet
does not erase the main /wallets/ directory, and also that the
backup file exists.

Github-Pull: #34156
Rebased-From: 36093bde63
2026-01-07 11:19:39 +00:00
furszy
ac4d0956cc wallet: fix unnamed wallet migration failure
When migrating any legacy unnamed wallet, a failed migration would
cause the cleanup logic to remove its parent directory. Since this
type of legacy wallet lives directly in the main '/wallets/' folder,
this resulted in unintentionally erasing all wallets, including the
backup file.

To be fully safe, we will no longer call `fs::remove_all`. Instead,
we only erase the individual db files we have created, leaving
everything else intact. The created wallets parent directories are
erased only if they are empty.
As part of this last change, `RestoreWallet` was modified to allow
an existing directory as the destination, since we no longer remove
the original wallet directory (we only remove the files we created
inside it). This also fixes the restore of top-level default wallets
during failures, which were failing due to the directory existence
check that always returns true for the /wallets/ directory.

This bug started after:
f6ee59b6e2
Previously, the `fs::copy_file` call was failing for top-level wallets,
which prevented the `fs::remove_all` call from being reached.

Github-Pull: #34156
Rebased-From: f4c7e28e80
2026-01-07 11:19:35 +00:00
furszy
454ac8e7db wallet: RestoreWallet failure, erase only what was created
Track what RestoreWallet creates so only those files and directories
are removed during a failure and nothing else. Preexisting paths
must be left untouched.

Note:
Using fs::remove_all() instead of fs::remove() in RestoreWallet does
not cause any problems currently, but the change is necessary for the
next commit which extends RestoreWallet to work with existing directories,
which may contain files that must not be deleted.

Github-Pull: #34156
Rebased-From: 4ed0693a3f
2026-01-07 11:18:38 +00:00
merge-script
e9f73b8149 Merge bitcoin/bitcoin#34192: [30.x] Backports
f22122bc27 doc: update release notes for v30.x (fanquake)
7568bc3ab0 test: Avoid hard time.sleep(1) in feature_init.py (MarcoFalke)
c065bcd2d7 init: Signal m_tip_block_cv on Ctrl-C (Ryan Ofsky)
6983c7d769 test: Test SIGTERM handling during waitforblockheight call (Ryan Ofsky)
8769c718f4 doc: Update OpenBSD Build Guide (Hennadii Stepanov)
ed0774bd08 doc: update copyright year (fanquake)
f620dde411 fuzz: doc: remove any mention to address_deserialize_v2 (brunoerg)
b734c4026b guix: reduce allowed exported symbols (fanquake)
7ea855fd55 build: Update minimum required Boost version (Hennadii Stepanov)

Pull request description:

  Backports:
  * #33511
  * #33950
  * #34091
  * #34107
  * #34137
  * #34174
  * #34182

ACKs for top commit:
  willcl-ark:
    ACK f22122bc27
  marcofleon:
    ACK f22122bc27

Tree-SHA512: a4486d331ce8fef07e611188098a965348cdfb081b81e5a2c700e119b1cf3c28cddbeca883ab512a510f6aaa5fc14bf896f70823fa63afcdd0762d9fbda0118b
2026-01-05 17:27:19 +00:00
fanquake
f22122bc27 doc: update release notes for v30.x 2026-01-05 12:09:33 +00:00
MarcoFalke
7568bc3ab0 test: Avoid hard time.sleep(1) in feature_init.py
Github-Pull: #34137
Rebased-From: fa727e3ec9
2026-01-05 12:09:02 +00:00
Ryan Ofsky
c065bcd2d7 init: Signal m_tip_block_cv on Ctrl-C
Signal m_tip_block_cv when Ctrl-C is pressed or SIGTERM is received, the same
way it is currently signalled when the `stop` RPC is called. This lets RPC
calls like `waitforblockheight` and IPC calls like `waitTipChanged` be
interrupted, instead of waiting for their original timeouts and delaying
shutdown.

Historical notes:

- The behavior where `stop` RPC signals `m_tip_block_cv`, but CTRL-C does not,
  has been around since the condition variable was introduced in #30409
  (7eccdaf160).
- The signaling was later moved without changing behavior in #30967
  (5ca28ef28b). This commit moves it again to
  the Interrupt() function, which is probably the place it should have been
  added initially, so it works for Ctrl-C shutdowns as well as `stop`
  shutdowns.
- A Qt shutdown bug calling wait methods was fixed previously in #18452
  (da73f1513a), and this change updates that
  fix to avoid the hang happening again in Qt.

Github-Pull: #33511
Rebased-From: c25a5e670b
2026-01-05 12:07:02 +00:00
Ryan Ofsky
6983c7d769 test: Test SIGTERM handling during waitforblockheight call
Currently when CTRL-C is pressed and there is an active `waitforblockheight`,
or `waitforblock`, or `waitfornewblock` RPC call, or a mining interface
`waitTipChanged` IPC call with a long timeout, the node will not shut down
right away, and will wait for the timeout to be reached before exiting.

This behavior is not ideal and only happens when the node is stopped with
CTRL-C or SIGTERM. When the node is stopped with `bitcoin-cli stop`, the wait
calls are interrupted and the node does shut down right away.

The next commit improves node behavior. This commit just adds test coverage to
simplify the next commit and clarify the change in behavior there.

Github-Pull: #33511
Rebased-From: 6a29f79006
2026-01-05 12:06:57 +00:00
Hennadii Stepanov
8769c718f4 doc: Update OpenBSD Build Guide
Github-Pull: #34182
Rebased-From: 84d8c52662
2026-01-05 11:58:47 +00:00
fanquake
ed0774bd08 doc: update copyright year
Github-Pull: #34174
Rebased-From: b23b901363
2026-01-05 11:41:23 +00:00
brunoerg
f620dde411 fuzz: doc: remove any mention to address_deserialize_v2
Github-Pull: #34091
Rebased-From: caf4843a59
2025-12-31 12:30:48 +00:00
fanquake
b734c4026b guix: reduce allowed exported symbols
Github-Pull: #33950
Rebased-From: 7b90b4f5bb
2025-12-31 12:27:29 +00:00
Hennadii Stepanov
7ea855fd55 build: Update minimum required Boost version
Building with Boost 1.73.0 is broken.

Github-Pull: #34107
Rebased-From: f480c1e717
2025-12-31 12:22:49 +00:00
merge-script
dd47caee82 Merge bitcoin/bitcoin#34092: [30.x] Finalise v30.1
2a21824b11 doc: update manual pages for v30.1 (fanquake)
57264431ff build: bump version to v30.1 (fanquake)
26294d627e doc: update release notes for v30.1 (fanquake)

Pull request description:

  Finalise `v30.1`.

ACKs for top commit:
  waketraindev:
    ACK 2a21824b11
  hebasto:
    ACK 2a21824b11, I have reviewed the code and it looks OK.
  brunoerg:
    code review ACK 2a21824b11
  janb84:
    ACK 2a21824b11
  w0xlt:
    Code Review ACK 2a21824b11

Tree-SHA512: 622d289db49c793fcb7b415d5113495eb824dc87780b082ccd5c43e37d116dca5a606340979a77cad1bfdbfac2c5fd5f18262746ed0e492d9e87bb0d802386ee
2025-12-18 15:54:33 +00:00
fanquake
2a21824b11 doc: update manual pages for v30.1 2025-12-17 15:40:17 +00:00
fanquake
57264431ff build: bump version to v30.1 2025-12-17 15:29:05 +00:00
fanquake
26294d627e doc: update release notes for v30.1 2025-12-17 15:27:46 +00:00
merge-script
b1499ddf8b Merge bitcoin/bitcoin#33997: [30.x] Backports & 30.1rc1
d59ebac718 doc: update manual pages for v30.1rc1 (fanquake)
b83d4f7c57 build: bump version to v30.1rc1 (fanquake)
b26c93a9df doc: update release notes for v30.1rc1 (fanquake)
18f3ada037 Remove unreliable seed from chainparams.cpp, and the associated README (SatsAndSports)
187e3b89b5 [test] wallet send 3 generation TRUC (glozow)
ab58b2c0f8 [wallet] never try to spend from unconfirmed TRUC that already has ancestors (glozow)
d872277db5 contrib: fix manpage generation (fanquake)
2256f8965e contrib: rename gen-sdk to gen-sdk.py (fanquake)
5408e85145 macdeploy: disable compression in macOS gen-sdk script (fanquake)
338570de5c contrib: more selectively pick files for macOS SDK (fanquake)

Pull request description:

  Backports:
  * #32009
  * #33528
  * #33723
  * #33996

  Prior `30.x` backports in #33609.

ACKs for top commit:
  hebasto:
    re-ACK d59ebac718.
  marcofleon:
    ACK d59ebac718

Tree-SHA512: 41656dc7c2e7a023325b288ff38cf95877a3c223ed5c6defc1c0939b725fb5423455583881f283aff14821bc4fea5a4d4d0ac458cab6450eb9b1bc7730fc027c
2025-12-05 14:44:42 +00:00
fanquake
d59ebac718 doc: update manual pages for v30.1rc1 2025-12-05 09:46:37 +00:00
fanquake
b83d4f7c57 build: bump version to v30.1rc1 2025-12-05 09:46:37 +00:00
fanquake
b26c93a9df doc: update release notes for v30.1rc1 2025-12-05 09:46:37 +00:00
SatsAndSports
18f3ada037 Remove unreliable seed from chainparams.cpp, and the associated README
Github-Pull: #33723
Rebased-From: b0c706795c
2025-12-05 09:46:37 +00:00
glozow
187e3b89b5 [test] wallet send 3 generation TRUC
Github-Pull: #33528
Rebased-From: dcd42d6d8f
2025-12-05 09:46:37 +00:00
glozow
ab58b2c0f8 [wallet] never try to spend from unconfirmed TRUC that already has ancestors
Github-Pull: #33528
Rebased-From: e753fadfd0
2025-12-05 09:46:32 +00:00
fanquake
d872277db5 contrib: fix manpage generation
0972f55040 from #33229 broke manpage
generation, because the assumption that the last word in the line
containing the version number, was the version number, no-longer holds
for some binaries. i.e bitcoind.

Github-Pull: #33996
Rebased-From: e9536faaee
2025-12-03 11:20:36 +00:00
fanquake
2256f8965e contrib: rename gen-sdk to gen-sdk.py
This puts it in scope for the Python linters.

Github-Pull: #32009
Rebased-From: 3e01b5d0e7
2025-12-02 12:14:53 +00:00
fanquake
5408e85145 macdeploy: disable compression in macOS gen-sdk script
Starting with Python 3.11, Pythons gzip might delegate to zlib.
Depending on the OS, i.e Ubuntu vs Fedora, the underlying zlib
implementation might differ, resulting in different output.

For now, or until a better solution exists, disable compression. This
results in the SDK increasing in size to ~157mb. Which is not
unreasonable, to regain determinism (and would be significantly worse
without the previous commit).

See: https://docs.python.org/3/library/gzip.html#gzip.compress

Co-authored-by: stickies-v <stickies-v@protonmail.com>

Github-Pull: #32009
Rebased-From: c1213a35ab
2025-12-02 12:14:31 +00:00
fanquake
338570de5c contrib: more selectively pick files for macOS SDK
Only include what we really need. Skip 100s of mb of manpages,
swiftmodules, modulemaps.
Note that System/Library is only needed for the Qt build.

Github-Pull: #32009
Rebased-From: a33d034545
2025-12-02 12:13:59 +00:00
merge-script
72675b8f55 Merge bitcoin/bitcoin#33609: [30.x] Backports
b2cb203af0 doc: update release notes for 30.x (fanquake)
39d53dd8bf interfaces: add interruptWait method (ismaelsadeeq)
577ddf6f5d depends: Add patch for Windows11Style plugin (Hennadii Stepanov)
a0a2b07701 scripted-diff: Remove obsolete comment (Hennadii Stepanov)
e2c71c4fca doc: Correct `pkgin` command usage on NetBSD (Hennadii Stepanov)
c0d851e6c6 qt: Modernize custom filtering (Hennadii Stepanov)
34576c4574 ci: fix configure docker action inputs (will)
8f8c7cf7fa ci: fix lint docker caching (will)
049bf100f1 qt: add createwallet, createwalletdescriptor, and migratewallet to history filter (WakeTrainDev)
3afd5a9729 miner: fix empty mempool case for waitNext() (Sjors Provoost)
23ac752d09 bitcoin: Make wrapper not require -m (Ryan Ofsky)
cd7937ce2d test: add tool_bitcoin to test bitcoin wrapper behavior (Ryan Ofsky)
42d4847fdf init: add exe name to bitcoind, bitcoin-node -version output to be able to distinguish these in tests (Ryan Ofsky)
96110f8846 [doc] correct topology requirements in submitpackage helptext (glozow)
729e4c2abd multiprocess: align our logging with libmultiprocess's (Cory Fields)
f8db6f6ce7 multiprocess: update multiprocess EventLoop construction to use options (Cory Fields)
5e389959b9 test: change log rate limit version gate from 299900 to 290100 (Eugene Siegel)
c48d3a6ad8 ci: expose all ACTIONS_* vars (willcl-ark)
73ed57a35e depends: Use $(package)_file_name when downloading from the fallback (Ava Chow)
72d1141bd8 ci: Use native platform for win-cross task (MarcoFalke)
c9fa661131 ci: Properly include $FILE_ENV in DEPENDS_HASH (Ava Chow)

Pull request description:

  Backports:
  * #33229
  * #33508
  * #33517
  * #33558
  * #33566
  * #33580
  * #33581
  * #33612
  * #33630
  * #33676
  * #33744
  * #33826
  * #33827
  * #33906
  * https://github.com/bitcoin-core/gui/pull/899
  * https://github.com/bitcoin-core/gui/pull/901

ACKs for top commit:
  willcl-ark:
    ACK b2cb203af0
  marcofleon:
    Lgtm, ACK b2cb203af0

Tree-SHA512: cde3584c7ad9bc6034a54527c1f5e84f0c5e314520109342a5cbb3c6c703286e2bed26f2b24fbf0ba7bcc9cbc140d79921e9d63def6b5c4782fd2e208f51948a
2025-12-02 10:15:15 +00:00
fanquake
b2cb203af0 doc: update release notes for 30.x 2025-12-01 14:59:27 +00:00
ismaelsadeeq
39d53dd8bf interfaces: add interruptWait method
- This method can be used to cancel a running
  waitNext().

- This commit also adds a test case for interruptWait method

Github-Pull: #33676
Rebased-From: dcb56fd4cb
2025-11-26 16:49:06 +00:00
Hennadii Stepanov
577ddf6f5d depends: Add patch for Windows11Style plugin
Github-Pull: #33906
Rebased-From: 8558902e57
2025-11-25 17:12:56 +00:00
Hennadii Stepanov
a0a2b07701 scripted-diff: Remove obsolete comment
The removed comment become obsolete after bitcoin/bitcoin#32697 and
bitcoin/bitcoin#32881.

-BEGIN VERIFY SCRIPT-

sed -i "s/ Some tests are disabled if Python 3 is not available.//g" \
$( git grep -l " Some tests are disabled if Python 3 is not available." ./doc/ )

-END VERIFY SCRIPT-

Github-Pull: #33826
Rebased-From: 36724205fc
2025-11-10 11:00:58 +00:00
Hennadii Stepanov
e2c71c4fca doc: Correct pkgin command usage on NetBSD
Github-Pull: #33827
Rebased-From: 0698c6b494
2025-11-10 10:32:55 +00:00
Hennadii Stepanov
c0d851e6c6 qt: Modernize custom filtering
In `QSortFilterProxyModel`, `invalidateFilter()` is scheduled for
deprecation in Qt 6.13.
`beginFilterChange()` was introduced in Qt 6.9.
`endFilterChange()` was introduced in Qt 6.10.

Github-Pull: gui#899
Rebased-From: e15e8cbada
2025-11-05 09:52:41 +00:00
will
34576c4574 ci: fix configure docker action inputs
The options used were wrong in two ways: firstly they were not enforced
as a "choice" (i.e. invalid input valudes could be provided without
error) and one of the options was listed as `gh` when we passed it as
`gha` from ci.yml.

"Fix" this by removing the choice altogether but sanity-testing the
input value against an expected list using a GHA "warning" to notify of
unknown inputs.

Github-Pull: #33744
Rebased-From: 7632e0ba31
2025-11-04 11:42:20 +00:00
will
8f8c7cf7fa ci: fix lint docker caching
Fixes: 33735

Correct runner type selection for the lint job.

This was erroneously left-out during refactor of the runner selection
mechanism in #33302 causing the lint job to run on GH hosts (and
therefore not be able to acces local cirrus caches).

Github-Pull: #33744
Rebased-From: 0b3b8a3be1
2025-11-04 11:42:15 +00:00
WakeTrainDev
049bf100f1 qt: add createwallet, createwalletdescriptor, and migratewallet to history filter
Github-Pull: #gui901
Rebased-From: 4e352efa2c
2025-11-04 11:40:15 +00:00
Sjors Provoost
3afd5a9729 miner: fix empty mempool case for waitNext()
Block template fees are calculated by looping over new_tmpl->vTxFees
and return (early) once the fee_threshold is exceeded.

This left an edge case when the mempool is empty, which this commit
fixes and adds a test for. It does so by using std::accumulate instead
of manual loops.

Also update interface_ipc.py to account for the new behavior.

Co-authored-by: Raimo33 <claudio.raimondi@protonmail.com>

Github-Pull: #33566
Rebased-From: 8f7673257a
2025-10-23 15:36:56 +02:00
Ryan Ofsky
23ac752d09 bitcoin: Make wrapper not require -m
Choose the right binary by default if an IPC option is specified

Github-Pull: #33229
Rebased-From: 453b0fa286
2025-10-17 15:43:25 +01:00
Ryan Ofsky
cd7937ce2d test: add tool_bitcoin to test bitcoin wrapper behavior
Github-Pull: #33229
Rebased-From: 29e836fae6
2025-10-17 15:43:22 +01:00
Ryan Ofsky
42d4847fdf init: add exe name to bitcoind, bitcoin-node -version output to be able to distinguish these in tests
Github-Pull: #33229
Rebased-From: 0972f55040
2025-10-17 15:43:18 +01:00
glozow
96110f8846 [doc] correct topology requirements in submitpackage helptext
Github-Pull: #33630
Rebased-From: 3d22282564
2025-10-17 15:17:37 +01:00
Cory Fields
729e4c2abd multiprocess: align our logging with libmultiprocess's
Without this change, logging (even if unused) may account for a
substantial portion of bitcoin-node's and/or client's runtime cpu usage, due
to libmultiprocess's expensive message serialization.

This (along with some recent upstream changes) avoids the overhead by opting
out of log handling for messages that we're not interested in.

Info, Warning, and Error are logged unconditionally to match our behavior
elsewhere. See BCLog::Logger::GetCategoryLogLevel .

Github-Pull: #33517
Rebased-From: 0626b90f50
2025-10-16 09:55:12 +01:00
Cory Fields
f8db6f6ce7 multiprocess: update multiprocess EventLoop construction to use options
This uses the constructors recently added upstream.

Github-Pull: #33517
Rebased-From: 9d068225ee
2025-10-16 09:55:09 +01:00
Eugene Siegel
5e389959b9 test: change log rate limit version gate from 299900 to 290100
Github-Pull: #33612
Rebased-From: 7b544341c0
2025-10-16 09:53:44 +01:00
willcl-ark
c48d3a6ad8 ci: expose all ACTIONS_* vars
When using `docker buildx build` in conjunction with the `gha` backend
cache type, it's important to specify the URL and TOKEN needed to
authenticate.

On Cirrus runners this is working with only `ACTIONS_CACHE_URL` and
`ACTIONS_RUNTIME_TOKEN`, but this is not enough for the GitHub backend.

Fix this by exporting all `ACTIONS_*` variables.

This fixes cache restore/save on forks or where GH-hosted runners are
being used.

Github-Pull: #33508
Rebased-From: bc706955d7
2025-10-16 09:53:44 +01:00
Ava Chow
73ed57a35e depends: Use $(package)_file_name when downloading from the fallback
Github-Pull: #33580
Rebased-From: 671b774d1b
2025-10-16 09:53:44 +01:00
MarcoFalke
72d1141bd8 ci: Use native platform for win-cross task
Github-Pull: #33558
Rebased-From: fa6fd16f36
2025-10-16 09:53:44 +01:00
Ava Chow
c9fa661131 ci: Properly include $FILE_ENV in DEPENDS_HASH
$FILE_ENV has a full relative path already, prepending with ci/test/
results in a non-existent path which means that DEPENDS_HASH was not
actually committing to the test's environment file.

Github-Pull: #33581
Rebased-From: ceeb53adcd
2025-10-16 09:53:44 +01:00
merge-script
a14e7b9dee Merge bitcoin/bitcoin#33519: Update libmultiprocess subtree in 30.x branch
abcd4c4ff9 Squashed 'src/ipc/libmultiprocess/' changes from 13424cf2ecc1..a4f929696490 (Ryan Ofsky)

Pull request description:

  Includes:

  - https://github.com/bitcoin-core/libmultiprocess/pull/207
  - https://github.com/bitcoin-core/libmultiprocess/pull/208
  - https://github.com/bitcoin-core/libmultiprocess/pull/211
  - https://github.com/bitcoin-core/libmultiprocess/pull/201
  - https://github.com/bitcoin-core/libmultiprocess/pull/213
  - https://github.com/bitcoin-core/libmultiprocess/pull/214
  - https://github.com/bitcoin-core/libmultiprocess/pull/221
  - https://github.com/bitcoin-core/libmultiprocess/pull/220
  - https://github.com/bitcoin-core/libmultiprocess/pull/222
  - https://github.com/bitcoin-core/libmultiprocess/pull/224

  Corresponding to #32641 and #33518 in master.

  The changes can be verified by running `test/lint/git-subtree-check.sh src/ipc/libmultiprocess` as described in [developer notes](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#subtrees) and [lint instructions](https://github.com/bitcoin/bitcoin/tree/master/test/lint#git-subtree-checksh)

  They can also be verified by checking `src/ipc/libmultiprocess/` contents are the same in master. (See also #33439).

ACKs for top commit:
  Sjors:
    ACK ae63cc4bf2
  theuni:
    ACK ae63cc4bf2 . Verified that it's the same as what's in master.

Tree-SHA512: 6c9462d5fb9201ee8ace900d7d02bfb6d0c7aa3d2f22475dc55e55e0239e2d20ed69f572c0df233da7910375e9d8ccaf3e84bf949ae92df27b88f16adb26dd7a
2025-10-16 09:53:04 +01:00
merge-script
d0f6d9953a Merge bitcoin/bitcoin#33559: [30.x] Finalise v30.0
d615eb6998 doc: re-import release notes for v30.0 (fanquake)
f725754615 doc: update manual pages for v30.0 (fanquake)
d7c89ba74e build: bump version to v30.0 (fanquake)

Pull request description:

  Finalise `v30.0`.
  Imports the release notes from https://github.com/bitcoin-core/bitcoin-devwiki/wiki/v30.0-Release-Notes-Draft.

ACKs for top commit:
  instagibbs:
    ACK d615eb6998
  achow101:
    ACK d615eb6998
  janb84:
    ACK d615eb6998
  darosior:
    ACK d615eb6998

Tree-SHA512: 82c2879ad09a4f6ec02f63411bcb8fa4900b8af2cbc2bc588fc0f06fa622253c3ef7e7b4c642f5e7239b088acd17f97b2cca73d15513b75297c2872d3146c673
2025-10-09 16:04:52 -04:00
fanquake
d615eb6998 doc: re-import release notes for v30.0
Taken from
https://github.com/bitcoin-core/bitcoin-devwiki/wiki/v30.0-Release-Notes-Draft.
2025-10-08 10:22:50 +01:00
Ryan Ofsky
ae63cc4bf2 Merge commit 'abcd4c4ff928a7af280ca271f8a939367fc4e09a' into pr/subtree-6-v30 2025-10-07 10:12:08 -04:00
Ryan Ofsky
abcd4c4ff9 Squashed 'src/ipc/libmultiprocess/' changes from 13424cf2ecc1..a4f929696490
a4f929696490 Merge bitcoin-core/libmultiprocess#224: doc: fix typos
f4344ae87da0 Merge bitcoin-core/libmultiprocess#222: test, ci: Fix threadsanitizer errors in mptest
1434642b3804 doc: fix typos
73d22ba2e930 test: Fix tsan race in thread busy test
b74e1bba014d ci: Use tsan-instrumented cap'n proto in sanitizers job
c332774409ad test: Fix failing exception check in new thread busy test
ca3c05d56709 test: Use KJ_LOG instead of std::cout for logging
7eb1da120ab6 ci: Use tsan-instrumented libcxx in sanitizers job
ec86e4336e98 Merge bitcoin-core/libmultiprocess#220: Add log levels and advertise them to users via logging callback
515ce93ad349 Logging: Pass LogData struct to logging callback
213574ccc43d Logging: reclassify remaining log messages
e4de0412b430 Logging: Break out expensive log messages and classify them as Trace
408874a78fdc Logging: Use new logging macros
67b092d835cd Logging: Disable logging if messsage level is less than the requested level
d0a1ba7ebf21 Logging: add log levels to mirror Core's
463a8296d188 Logging: Disable moving or copying Logger
83a2e10c0b03 Logging: Add an EventLoop constructor to allow for user-specified log options
58cf47a7fc8c Merge bitcoin-core/libmultiprocess#221: test default PassField impl handles output parameters
db03a663f514 Merge bitcoin-core/libmultiprocess#214: Fix crash on simultaneous IPC calls using the same thread
afcc40b0f1e8 Merge bitcoin-core/libmultiprocess#213: util+doc: Clearer errors when attempting to run examples + polished docs
6db669628387 test In|Out parameter
29cf2ada75ea test default PassField impl handles output parameters
1238170f68e8 test: simultaneous IPC calls using same thread
eb069ab75d83 Fix crash on simultaneous IPC calls using the same thread
ec03a9639ab5 doc: Precision and typos
2b4348193551 doc: Where possible, remove links to ryanofsky/bitcoin/
286fe469c9c9 util: Add helpful error message when failing to execute file
47d79db8a552 Merge bitcoin-core/libmultiprocess#201: bug: fix mptest hang, ProxyClient<Thread> deadlock in disconnect handler
f15ae9c9b9fb Merge bitcoin-core/libmultiprocess#211: Add .gitignore
4a269b21b8c8 bug: fix ProxyClient<Thread> deadlock if disconnected as IPC call is returning
85df96482c49 Use try_emplace in SetThread instead of threads.find
ca9b380ea91a Use std::optional in ConnThreads to allow shortening locks
9b0799113557 doc: describe ThreadContext struct and synchronization requirements
d60db601ed9b proxy-io.h: add Waiter::m_mutex thread safety annotations
4e365b019a9f ci: Use -Wthread-safety not -Wthread-safety-analysis
15d7bafbb001 Add .gitignore
fe1cd8c76131 Merge bitcoin-core/libmultiprocess#208: ci: Test minimum cmake version in olddeps job
b713a0b7bfbc Merge bitcoin-core/libmultiprocess#207: ci: output CMake version in CI script
0f580397c913 ci: Test minimum cmake version in olddeps job
d603dcc0eef0 ci: output CMake version in CI script

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: a4f92969649018ca70f949a09148bccfeaecd99a
2025-10-07 10:12:08 -04:00
fanquake
f725754615 doc: update manual pages for v30.0 2025-10-07 11:18:46 +01:00
fanquake
d7c89ba74e build: bump version to v30.0 2025-10-07 11:18:43 +01:00
merge-script
d5e0077bef Merge bitcoin/bitcoin#33473: [30.x] Backports & rc3
4e869a67aa doc: update example bitcoin conf for 30.0rc3 (fanquake)
a2ac6cce57 doc: update manual pages for v30.0rc3 (fanquake)
e4b568917c build: bump version to v30.0rc3 (fanquake)
f957c2171d contrib: fix using macdploy script without translations. (amisha)
1eb578045d depends: static libxcb_cursor (fanquake)
e4f9ec2f05 test: add more TRUC reorg coverge (Greg Sanders)
3485252584 Mempool: Do not enforce TRUC checks on reorg (Greg Sanders)
a3a1dcb589 fuzz: don't bypass_limits for most mempool harnesses (Greg Sanders)
fce1c60770 datacarrier: Undeprecate configuration option (Anthony Towns)
b75afaccb8 doc: rpc: fix case typo in `finalizepsbt` help (final_scriptwitness) (Sebastian Falbesoner)
45703931e5 miner: fix `addPackageTxs` unsigned integer overflow (ismaelsadeeq)
1e348bc55a rpc: fix getblock(header) returns target for tip (Sjors Provoost)
4ec30d53ec test: add block 2016 to mock mainnet (Sjors Provoost)

Pull request description:

  Backports:
  * #33434
  * #33446
  * #33453
  * #33475
  * #33482
  * #33484
  * #33504

  Includes changes for `v30.0rc3`:
  * Version bump
  * Regen manpages
  * Regen exmaple .conf

ACKs for top commit:
  marcofleon:
    lgtm ACK 4e869a67aa
  dergoegge:
    ACK 4e869a67aa
  hebasto:
    ACK 4e869a67aa, I agree on the backported PRs. I've reproduced locally all backports, the manpages update, and the example `bitcoin.conf` updated, and obtained zero diff with this PR.
  Zero-1729:
    LGTM ACK 4e869a67aa

Tree-SHA512: 90bffbb6dfe2b512167b5e08253ea163b714505ec3ef2247d798c40b30713a7db13cf0b5486b5f9e0e5b3ba53108dfaeea47276c40816eeb81065d42bd402379
2025-10-06 10:37:26 +01:00
merge-script
2869dae5ec Merge bitcoin/bitcoin#33541: Release: 30.0rc3 translations update
71ee0163de qt: 30.0rc3 translations update (Hennadii Stepanov)

Pull request description:

  This PR updates the Polish (pl) translation and addresses [this](https://github.com/bitcoin/bitcoin/pull/33275#issuecomment-3329617679) comment.

  Updates for other languages have been skipped, as I believe the review effort would not be worthwhile at this stage of the release process.

ACKs for top commit:
  maflcko:
    Though, this lgtm ACK 71ee0163de
  janb84:
    ACK 71ee0163de

Tree-SHA512: e9ee8146542d0928f5ddaac5b2cb0c0032cd7d236fc19b38fd4ebe91e13eccdfa7d25ff279376c3f27f0bc461729b2c0574fedbb670a2555bc7a534e5ec0cd76
2025-10-06 10:24:07 +01:00
Hennadii Stepanov
71ee0163de qt: 30.0rc3 translations update 2025-10-05 11:53:45 +01:00
fanquake
4e869a67aa doc: update example bitcoin conf for 30.0rc3 2025-10-03 16:33:13 +01:00
fanquake
a2ac6cce57 doc: update manual pages for v30.0rc3 2025-10-03 16:32:40 +01:00
fanquake
e4b568917c build: bump version to v30.0rc3 2025-10-03 16:28:31 +01:00
amisha
f957c2171d 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 15:41:37 +01:00
fanquake
1eb578045d depends: static libxcb_cursor
Modern Ubuntu isn't shipping with this library installed by default.
Staticly link it to remove the need for end-users to install it.

Closes #33432.

Github-Pull: #33434
Rebased-From: eca50854e1
2025-10-03 15:27:48 +01:00
Greg Sanders
e4f9ec2f05 test: add more TRUC reorg coverge
Github-Pull: #33504
Rebased-From: 06df14ba75
2025-10-02 13:56:24 +01:00
Greg Sanders
3485252584 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 13:55:58 +01:00
Greg Sanders
a3a1dcb589 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 13:55:33 +01:00
Anthony Towns
fce1c60770 datacarrier: Undeprecate configuration option
Reverts commit 0b4048c733

Github-Pull: #33453
Rebased-From: 451ba9ada4
2025-09-30 18:37:37 -04:00
Sebastian Falbesoner
b75afaccb8 doc: rpc: fix case typo in finalizepsbt help (final_scriptwitness)
Github-Pull: #33484
Rebased-From: ff05bebcc4
2025-09-28 18:14:03 -04:00
ismaelsadeeq
45703931e5 miner: fix addPackageTxs unsigned integer overflow
Github-Pull: #33475
Rebased-From: b807dfcdc5
2025-09-25 08:19:33 -04:00
Sjors Provoost
1e348bc55a 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:09:25 -04:00
Sjors Provoost
4ec30d53ec 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:09:04 -04:00
merge-script
72c1f13c33 Merge bitcoin/bitcoin#33424: [30.0] Final changes + rc2
7ebdfa2173 ci: link against -lstdc++ in native fuzz with msan job (fanquake)
ecbcef33d6 doc: remove unrelated `bitcoin-wallet` binary from `libbitcoin_ipc` description (Sebastian Falbesoner)
8c973d6614 ci: disable cirrus cache in 32bit arm job (will)
2378bbf356 ci: refactor docker action to return provider str (will)
acf7d53ace test: split out `system_ram_tests` to signal when total ram cannot be determined (Lőrinc)
ce56548c63 system: improve handling around GetTotalRAM() (Vasil Dimov)
5226a92f28 coins: warn on oversized -dbcache (Lőrinc)
49d4ebcbfe system: add helper for fetching total system memory (Lőrinc)
0a80b1ae62 doc: update manual pages for v30.0rc2 (fanquake)
b8fb918969 build: bump version to v30.0rc2 (fanquake)
792a75ac86 build(windows): Remove lingering registry entries and shortcuts upon install (Hodlinator)
1bc3be1962 p2p: Increase tx relay rate (Anthony Towns)
4b02bc1a72 test: Avoid interface_ipc.py Duplicate ID errors (Ryan Ofsky)

Pull request description:

  Backports:
  * #28592
  * #33302
  * #33333
  * #33420
  * #33422
  * #33425
  * #33435
  * #33459

  Finalise `v30.0rc2`

ACKs for top commit:
  willcl-ark:
    ACK 7ebdfa2173
  hebasto:
    ACK 7ebdfa2173, I applied all backports locally without conflicts and obtained a zero diff with this PR branch.

Tree-SHA512: 73d641a5d783511a959e63f240453bb020705cb620b85a5a0968b32b937ac28816ef142f78bdf41976ed1c2bee431def945c5c37da33621031e3198cfdae51f3
2025-09-23 18:46:24 -04:00
fanquake
7ebdfa2173 ci: link against -lstdc++ in native fuzz with msan job
Github-Pull: #33425
Rebased-From: b77137a564
2025-09-23 10:20:07 -04:00
Sebastian Falbesoner
ecbcef33d6 doc: remove unrelated bitcoin-wallet binary from libbitcoin_ipc description
`bitcoin-wallet` as-is is merely an offline wallet inspection tool
(introduced more than 9 years ago in PR #13926) that doesn't have any
relation with IPC/multiprocess, so remove it from the list of binaries
that use `libbitcoin_ipc`.

Github-Pull: #33459
Rebased-From: fbde8d9a81
2025-09-23 10:20:07 -04:00
will
8c973d6614 ci: disable cirrus cache in 32bit arm job
Co-authored-by: Max Edwards <youwontforgetthis@gmail.com>
Add an optional matrix field allowing opt-out of configuring cirrus
GHA cache when not using cirrus runners.

This is not needed for the cirruslabs/[save|restore]-cache actions, as
they automatically fallback based on runner type.

Github-Pull: #33302
Rebased-From: 00c253d494
2025-09-23 10:20:06 -04:00
will
2378bbf356 ci: refactor docker action to return provider str
Avoid relying on future truthy evaluations of string 'false'.

Github-Pull: #33302
Rebased-From: ff18b6bbaf
2025-09-23 10:20:06 -04:00
Lőrinc
acf7d53ace test: split out system_ram_tests to signal when total ram cannot be determined
when `GetTotalRAM` returns an `std::nullopt` now we're getting:
```
The following tests did not run:
        106 - system_ram_tests (Skipped)
```

GitHub-Pull: #33435
Rebased-From: 56791b5829
2025-09-23 10:20:06 -04:00
Vasil Dimov
ce56548c63 system: improve handling around GetTotalRAM()
This patch achieves two things:
1. Fix unused variable warning (https://github.com/bitcoin/bitcoin/pull/33333#discussion_r2362493046)
2. Enable GetTotalRAM() on other platforms where it was tested to work.

Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>

Github-Pull: #33435
Rebased-From: 337a6e7386
2025-09-23 10:20:06 -04:00
Lőrinc
5226a92f28 coins: warn on oversized -dbcache
Oversized allocations can cause out-of-memory errors or [heavy swapping](https://github.com/getumbrel/umbrel-os/issues/64#issuecomment-663637321), [grinding the system to a halt](https://x.com/murchandamus/status/1964432335849607224).

`LogOversizedDbCache()` now emits a startup warning if the configured `-dbcache` exceeds a cap derived from system RAM, using the same parsing/clamping as cache sizing via CalculateDbCacheBytes(). This isn't meant as a recommended setting, rather a likely upper limit.

Note that we're not modifying the set value, just issuing a warning.
Also note that the 75% calculation is rounded for the last two numbers since we have to divide first before multiplying, otherwise we wouldn't stay inside size_t on 32-bit systems - and this was simpler than casting back and forth.

We could have chosen the remaining free memory for the warning (e.g. warn if free memory is less than 1 GiB), but this is just a heuristic, we assumed that on systems with a lot of memory, other processes are also running, while memory constrained ones run only Core.

If total RAM < 2 GiB, cap is `DEFAULT_DB_CACHE` (`450 MiB`), otherwise it's 75% of total RAM.
The threshold is chosen to be close to values commonly used in [raspiblitz](https://github.com/raspiblitz/raspiblitz/blob/dev/home.admin/_provision.setup.sh#L98-L115) for common setups:

| Total RAM | `dbcache` (MiB) | raspiblitz % | proposed cap (MiB) |
|----------:|----------------:|-------------:|-------------------:|
|     1 GiB |             512 |        50.0% |               450* |
|     2 GiB |            1536 |        75.0% |               1536 |
|     4 GiB |            2560 |        62.5% |               3072 |
|     8 GiB |            4096 |        50.0% |               6144 |
|    16 GiB |            4096 |        25.0% |              12288 |
|    32 GiB |            4096 |        12.5% |              24576 |

[Umbrel issues](https://github.com/getumbrel/umbrel-os/issues/64#issuecomment-663816367) also mention 75% being the upper limit.

Starting `bitcoind` on an 8 GiB rpi4b with a dbcache of 7 GiB:
> ./build/bin/bitcoind -dbcache=7000

warns now as follows:
```
2025-09-07T17:24:29Z [warning] A 7000 MiB dbcache may be too large for a system memory of only 7800 MiB.
2025-09-07T17:24:29Z Cache configuration:
2025-09-07T17:24:29Z * Using 2.0 MiB for block index database
2025-09-07T17:24:29Z * Using 8.0 MiB for chain state database
2025-09-07T17:24:29Z * Using 6990.0 MiB for in-memory UTXO set (plus up to 286.1 MiB of unused mempool space)
```

Besides the [godbolt](https://godbolt.org/z/EPsaE3xTj) reproducers for the new total memory method, we also tested the warnings manually on:
- [x] Apple M4 Max, macOS 15.6.1
- [x] Intel Core i9-9900K, Ubuntu 24.04.2 LTS
- [x] Raspberry Pi 4 Model B, Armbian Linux 6.12.22-current-bcm2711
- [x] Intel Xeon x64, Windows 11 Home Version 24H2, OS Build 26100.4351

Co-authored-by: stickies-v <stickies-v@protonmail.com>
Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
Co-authored-by: w0xlt <woltx@protonmail.com>

Github-Pull: #33333
Rebased-From: 168360f4ae
2025-09-23 10:20:06 -04:00
Lőrinc
49d4ebcbfe system: add helper for fetching total system memory
Added a minimal system helper to query total physical RAM on [Linux/macOS/Windows](https://stackoverflow.com/a/2513561) (on other platforms we just return an empty optional).

The added test checks if the value is roughly correct by checking if the CI platforms are returning any value and if the value is at least 1 GiB and not more than 10 TiB.

The max value is only validated on 64 bits, since it's not unreasonable for 32 bits to have max memory, but on 64 bits it's likely an error.

https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex
> ullTotalPhys The amount of actual physical memory, in bytes.

https://man7.org/linux/man-pages/man3/sysconf.3.html:
> _SC_PHYS_PAGES The number of pages of physical memory. Note that it is possible for the product of this value and the value of _SC_PAGESIZE to overflow.
> _SC_PAGESIZE Size of a page in bytes. Must not be less than 1.

See https://godbolt.org/z/ec81Tjvrj for further details

Github-Pull: #33333
Rebased-From: 6c720459be
2025-09-23 10:20:06 -04:00
fanquake
0a80b1ae62 doc: update manual pages for v30.0rc2 2025-09-23 10:20:06 -04:00
fanquake
b8fb918969 build: bump version to v30.0rc2 2025-09-23 10:20:06 -04:00
Hodlinator
792a75ac86 build(windows): Remove lingering registry entries and shortcuts upon install
Prior releases installed using these paths. Especially annoying was that the lingering registry entry for the uninstaller would show up as "Bitcoin Core (64-bit)" besides the current "Bitcoin Core" entry in the list of installed programs, and whichever was uninstalled last would fail to work as they would default to the same install directory.

Github-Pull: #33422
Rebased-From: 79752b9c0b
2025-09-23 10:20:05 -04:00
Anthony Towns
1bc3be1962 p2p: Increase tx relay rate
In the presence of smaller transactions on the network, blocks can sustain a
higher relay rate than 7tx/second. In this event, the per-peer inventory queues
can grow too large.

This commit bumps the rate up to 14 tx/s (for inbound peers), increasing the
safety margin by a factor of 2.

Outbound peers continue to receive relayed transactions at 2.5x the rate of
inbound peers, for a rate of 35tx/second.

Co-Authored-By: Suhas Daftuar <sdaftuar@gmail.com>

Github-Pull: #28592
Rebased-From: b81f37031c
2025-09-23 10:20:05 -04:00
Ryan Ofsky
4b02bc1a72 test: Avoid interface_ipc.py Duplicate ID errors
This change should fix issue https://github.com/bitcoin/bitcoin/issues/33417
reported by zaidmstrr. It's possible to reproduce the `mp/proxy.capnp:0:
failed: Duplicate ID @0xcc316e3f71a040fb` error by installing libmultiprocess
system-wide, or to one of the locations listed in the python test's `imports`
list before the local libmultiprocess subtree, and then running the test.

Github-Pull: #33420
Rebased-From: e9c52272eb
2025-09-23 10:20:05 -04:00
merge-script
52bcf62c0b Merge bitcoin/bitcoin#33452: Release: 30.0rc2 translations update
33a0d4bb5b qt: 30.0rc2 translations update (Hennadii Stepanov)

Pull request description:

  This PR updates Spanish (es) and Czech (cs) translations and addresses the following comments:
  - https://github.com/bitcoin/bitcoin/pull/33275#issuecomment-3315273628
  - https://github.com/bitcoin/bitcoin/pull/33275#issuecomment-3316206549

  Updates for other languages were skipped, as I believe the review effort would not be worthwhile at this stage of the release process.

ACKs for top commit:
  fanquake:
    ACK 33a0d4bb5b.

Tree-SHA512: 94c1c1fb4a0079f3e733c573ba1fddd149307ec39220e811d33f5bbfd929a634b24ef9adbe9e789bd0127539ce5e134dde3a241db0e233d53446abf96a4d49b6
2025-09-23 10:18:54 -04:00
Hennadii Stepanov
33a0d4bb5b qt: 30.0rc2 translations update 2025-09-21 21:38:11 +01:00
merge-script
b7a722724d Merge bitcoin/bitcoin#33356: [30.0] rc2 backports
c9f751090c cmake: Install `bitcoin` manpage (Hennadii Stepanov)
2327b2b0db net: Do not apply whitelist permission to onion inbounds (Martin Zumsande)
26208b3a0c test: Add submitblock test in interface_ipc (TheCharlatan)
3ae592537d test: Prevent disk space warning during node_init_tests (Ryan Ofsky)
5dbb1bae38 ci: Enable CI_LIMIT_STACK_SIZE=1 in i686_no_ipc task (MarcoFalke)
c7faf72ac6 test: Fix CLI_MAX_ARG_SIZE issues (MarcoFalke)
0a2afbeb77 cmake: Fix regression in `secp256k1.cmake` (Hennadii Stepanov)
75026cddea wallet: Add m_cached_from_me to cache "from me" status (Ava Chow)
bbb4e118f3 test: Add a test for anchor outputs in the wallet (Ava Chow)
b85dc7ed3a wallet: Throw an error in sendall if the tx size cannot be calculated (Ava Chow)
d2be9a22d8 wallet: Determine IsFromMe by checking for TXOs of inputs (Ava Chow)
ad6c13e041 test: Test wallet 'from me' status change (Ava Chow)
35038b03c9 trace: Workaround GCC bug compiling with old systemtap (Luke Dashjr)
f7eded1dca ci: always use tag for LLVM checkout (fanquake)
6b19ede1a5 gui: Avoid pathological QT text/markdown behavior... (David Gumberg)

Pull request description:

  Backports:
  * #33243
  * #33268
  * #33310
  * #33364
  * #33379
  * #33380
  * #33391
  * #33407
  * https://github.com/bitcoin-core/gui/pull/886

ACKs for top commit:
  darosior:
    utACK c9f751090c
  hebasto:
    ACK c9f751090c, I applied all backports locally without conflicts and obtained a zero diff with this PR branch.

Tree-SHA512: 257cc5bd0423fbf2aff62c72957faea3de8731353d809b11e18d0e5cad174c7023dca9dedd0c73e07497eb804b7c48355a055b4461db260e2f0a5712d2514ff6
2025-09-17 14:01:51 -04:00
Hennadii Stepanov
c9f751090c cmake: Install bitcoin manpage
Github-Pull: #33407
Rebased-From: 7584a4fda9
2025-09-17 09:58:49 +01:00
Martin Zumsande
2327b2b0db 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 09:58:25 +01:00
TheCharlatan
26208b3a0c test: Add submitblock test in interface_ipc
Co-Authored-By: Sjors Provoost <sjors@sprovoost.nl>

Github-Pull: #33380
Rebased-From: 0a26731c4c
2025-09-17 09:50:21 +01:00
Ryan Ofsky
3ae592537d test: Prevent disk space warning during node_init_tests
mzumsande pointed out https://github.com/bitcoin/bitcoin/pull/32345#issuecomment-3286964369 that this test was causing a warning:

   Warning: Disk space for "/tmp/test_common bitcoin/node_init_tests/init_test/bf78678cb7723a3e84b5/blocks" may not accommodate the block files. Approximately 810 GB of data will be stored in this directory.

Fix by setting regtest instead of mainnet network before running the test.

Github-Pull: #33391
Rebased-From: bdf01c6f61
2025-09-16 09:49:48 +01:00
MarcoFalke
5dbb1bae38 ci: Enable CI_LIMIT_STACK_SIZE=1 in i686_no_ipc task
Github-Pull: #33243
Rebased-From: fa96a4afea
2025-09-15 10:24:01 +01:00
MarcoFalke
c7faf72ac6 test: Fix CLI_MAX_ARG_SIZE issues
Github-Pull: #33243
Rebased-From: facfde2cdc
2025-09-15 10:23:38 +01:00
Hennadii Stepanov
0a2afbeb77 cmake: Fix regression in secp256k1.cmake
The `enable_language` command must be called in file scope, not in a
function call.

See: https://cmake.org/cmake/help/latest/command/enable_language.html

Github-Pull: #33379
Rebased-From: 9193c3e434
2025-09-15 09:52:10 +01:00
Ava Chow
75026cddea wallet: Add m_cached_from_me to cache "from me" status
m_cached_from_me is used to track whether a transaction is "from me", i.e. has
any inputs which belong to the wallet. This is held in memory only in
the same way that a transaction's balances are.

Github-Pull: #33268
Rebased-From: 113a422822
2025-09-12 14:52:45 +01:00
Ava Chow
bbb4e118f3 test: Add a test for anchor outputs in the wallet
Github-Pull: #33268
Rebased-From: 609d265ebc
2025-09-12 14:52:20 +01:00
Ava Chow
b85dc7ed3a wallet: Throw an error in sendall if the tx size cannot be calculated
Github-Pull: #33268
Rebased-From: c40dc822d7
2025-09-12 14:51:51 +01:00
Ava Chow
d2be9a22d8 wallet: Determine IsFromMe by checking for TXOs of inputs
Instead of checking whether the total amount of inputs known by the
wallet is greater than 0, we should be checking for whether the input is
known by the wallet. This enables us to determine whether a transaction
spends an of output with an amount of 0, which is necessary for marking
0-value dust outputs as spent.

Github-Pull: #33268
Rebased-From: 39a7dbdd27
2025-09-12 14:48:15 +01:00
Ava Chow
ad6c13e041 test: Test wallet 'from me' status change
If something is imported into the wallet, it can change the 'from me'
status of a transaction. This status is only visible through
gettransaction's "fee" field which is only shown for transactions that
are 'from me'.

Github-Pull: #33268
Rebased-From: e76c2f7a41
2025-09-12 14:43:30 +01:00
Luke Dashjr
35038b03c9 trace: Workaround GCC bug compiling with old systemtap
Github-Pull: #33310
Rebased-From: 93a29ff283
2025-09-12 11:50:28 +01:00
fanquake
f7eded1dca 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:47:09 +01:00
David Gumberg
6b19ede1a5 gui: Avoid pathological QT text/markdown behavior...
during text selection by only setting plaintext mime data.

Github-Pull: https://github.com/bitcoin-core/gui/pull/886
Rebased-From: 6a371b70c8
2025-09-10 12:43:27 +01:00
136 changed files with 2649 additions and 1059 deletions

View File

@@ -1,12 +1,24 @@
name: 'Configure Docker'
description: 'Set up Docker build driver and configure build cache args'
inputs:
use-cirrus:
description: 'Use cirrus cache'
cache-provider:
description: 'gha or cirrus cache provider'
required: true
runs:
using: 'composite'
steps:
- name: Check inputs
shell: bash
run: |
# We expect only gha or cirrus as inputs to cache-provider
case "${{ inputs.cache-provider }}" in
gha|cirrus)
;;
*)
echo "::warning title=Unknown input to configure docker action::Provided value was ${{ inputs.cache-provider }}"
;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
@@ -19,8 +31,12 @@ runs:
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'])
Object.keys(process.env).forEach(function (key) {
if (key.startsWith('ACTIONS_')) {
core.info(`Exporting ${key}`);
core.exportVariable(key, process.env[key]);
}
});
- name: Construct docker build cache args
shell: bash
@@ -32,7 +48,7 @@ runs:
# 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
if [[ ${{ inputs.cache-provider }} == 'cirrus' ]]; then
url_args="url=${CIRRUS_CACHE_HOST},url_v2=${CIRRUS_CACHE_HOST}"
else
url_args=""

View File

@@ -17,7 +17,7 @@ runs:
- 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 "DEPENDS_HASH=$(git ls-tree HEAD depends "$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

View File

@@ -33,15 +33,15 @@ jobs:
name: 'determine runners'
runs-on: ubuntu-latest
outputs:
use-cirrus-runners: ${{ steps.runners.outputs.use-cirrus-runners }}
provider: ${{ steps.runners.outputs.provider }}
steps:
- id: runners
run: |
if [[ "${REPO_USE_CIRRUS_RUNNERS}" == "${{ github.repository }}" ]]; then
echo "use-cirrus-runners=true" >> "$GITHUB_OUTPUT"
echo "provider=cirrus" >> "$GITHUB_OUTPUT"
echo "::notice title=Runner Selection::Using Cirrus Runners"
else
echo "use-cirrus-runners=false" >> "$GITHUB_OUTPUT"
echo "provider=gha" >> "$GITHUB_OUTPUT"
echo "::notice title=Runner Selection::Using GitHub-hosted runners"
fi
@@ -312,7 +312,7 @@ jobs:
windows-cross:
name: 'Linux->Windows cross, no tests'
needs: runners
runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' || 'ubuntu-24.04' }}
runs-on: ${{ needs.runners.outputs.provider == 'cirrus' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' || 'ubuntu-24.04' }}
if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
env:
@@ -332,7 +332,7 @@ jobs:
- name: Configure Docker
uses: ./.github/actions/configure-docker
with:
use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }}
cache-provider: ${{ needs.runners.outputs.provider }}
- name: CI script
run: ./ci/test_run_all.sh
@@ -422,7 +422,7 @@ jobs:
ci-matrix:
name: ${{ matrix.name }}
needs: runners
runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && matrix.cirrus-runner || matrix.fallback-runner }}
runs-on: ${{ needs.runners.outputs.provider == 'cirrus' && matrix.cirrus-runner || matrix.fallback-runner }}
if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
timeout-minutes: ${{ matrix.timeout-minutes }}
@@ -439,6 +439,7 @@ jobs:
fallback-runner: 'ubuntu-24.04-arm'
timeout-minutes: 120
file-env: './ci/test/00_setup_env_arm.sh'
provider: 'gha'
- 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
@@ -513,7 +514,7 @@ jobs:
- name: Configure Docker
uses: ./.github/actions/configure-docker
with:
use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }}
cache-provider: ${{ matrix.provider || needs.runners.outputs.provider }}
- name: Enable bpfcc script
if: ${{ env.CONTAINER_NAME == 'ci_native_asan' }}
@@ -535,7 +536,7 @@ jobs:
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' }}
runs-on: ${{ needs.runners.outputs.provider == 'cirrus' && '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:
@@ -550,7 +551,7 @@ jobs:
- name: Configure Docker
uses: ./.github/actions/configure-docker
with:
use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }}
cache-provider: ${{ needs.runners.outputs.provider }}
- name: CI script
run: |

View File

@@ -28,11 +28,11 @@ get_directory_property(precious_variables CACHE_VARIABLES)
#=============================
set(CLIENT_NAME "Bitcoin Core")
set(CLIENT_VERSION_MAJOR 30)
set(CLIENT_VERSION_MINOR 0)
set(CLIENT_VERSION_MINOR 2)
set(CLIENT_VERSION_BUILD 0)
set(CLIENT_VERSION_RC 1)
set(CLIENT_VERSION_RC 0)
set(CLIENT_VERSION_IS_RELEASE "true")
set(COPYRIGHT_YEAR "2025")
set(COPYRIGHT_YEAR "2026")
# During the enabling of the CXX and CXXOBJ languages, we modify
# CMake's compiler/linker invocation strings by appending the content

View File

@@ -1,7 +1,7 @@
The MIT License (MIT)
Copyright (c) 2009-2025 The Bitcoin Core developers
Copyright (c) 2009-2025 Bitcoin Developers
Copyright (c) 2009-2026 The Bitcoin Core developers
Copyright (c) 2009-2026 Bitcoin Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -13,6 +13,7 @@ export CI_IMAGE_PLATFORM="linux/amd64"
export PACKAGES="llvm clang g++-multilib"
export DEP_OPTS="DEBUG=1 NO_IPC=1"
export GOAL="install"
export CI_LIMIT_STACK_SIZE=1
export TEST_RUNNER_EXTRA="--v2transport --usecli"
export BITCOIN_CONFIG="\
-DCMAKE_BUILD_TYPE=Debug \

View File

@@ -7,12 +7,15 @@
export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
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="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_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.

View File

@@ -8,7 +8,6 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_win64
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04" # Check that https://packages.ubuntu.com/noble/g++-mingw-w64-x86-64-posix (version 13.x, similar to guix) can cross-compile
export CI_IMAGE_PLATFORM="linux/amd64"
export HOST=x86_64-w64-mingw32
export PACKAGES="g++-mingw-w64-x86-64-posix nsis"
export RUN_UNIT_TESTS=false

View File

@@ -56,25 +56,7 @@ if [ -n "$PIP_PACKAGES" ]; then
fi
if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then
if [ -n "${APT_LLVM_V}" ]; then
${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-$( clang --version | sed --silent 's@.*clang version \([0-9.]*\).*@\1@p' )" /llvm-project
else
${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-21.1.0" /llvm-project
cmake -G Ninja -B /clang_build/ \
-DLLVM_ENABLE_PROJECTS="clang" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_TARGETS_TO_BUILD=Native \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" \
-S /llvm-project/llvm
ninja -C /clang_build/ "$MAKEJOBS"
ninja -C /clang_build/ install-runtimes
update-alternatives --install /usr/bin/clang++ clang++ /clang_build/bin/clang++ 100
update-alternatives --install /usr/bin/clang clang /clang_build/bin/clang 100
update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /clang_build/bin/llvm-symbolizer 100
fi
${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-21.1.1" /llvm-project
cmake -G Ninja -B /cxx_build/ \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \
@@ -107,7 +89,7 @@ mkdir -p "${DEPENDS_DIR}/SDKs" "${DEPENDS_DIR}/sdk-sources"
OSX_SDK_BASENAME="Xcode-${XCODE_VERSION}-${XCODE_BUILD_ID}-extracted-SDK-with-libcxx-headers"
if [ -n "$XCODE_VERSION" ] && [ ! -d "${DEPENDS_DIR}/SDKs/${OSX_SDK_BASENAME}" ]; then
OSX_SDK_FILENAME="${OSX_SDK_BASENAME}.tar.gz"
OSX_SDK_FILENAME="${OSX_SDK_BASENAME}.tar"
OSX_SDK_PATH="${DEPENDS_DIR}/sdk-sources/${OSX_SDK_FILENAME}"
if [ ! -f "$OSX_SDK_PATH" ]; then
${CI_RETRY_EXE} curl --location --fail "${SDK_URL}/${OSX_SDK_FILENAME}" -o "$OSX_SDK_PATH"

View File

@@ -29,7 +29,7 @@ function(add_boost_if_needed)
endif()
endif()
find_package(Boost 1.73.0 REQUIRED CONFIG)
find_package(Boost 1.74.0 REQUIRED CONFIG)
mark_as_advanced(Boost_INCLUDE_DIR boost_headers_DIR)
# Workaround for a bug in NetBSD pkgsrc.
# See: https://github.com/NetBSD/pkgsrc/issues/167.

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

@@ -2,6 +2,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.
enable_language(C)
function(add_secp256k1 subdir)
message("")
message("Configuring secp256k1 subtree...")
@@ -30,7 +32,6 @@ function(add_secp256k1 subdir)
string(STRIP "${SECP256K1_APPEND_LDFLAGS} ${APPEND_LDFLAGS}" SECP256K1_APPEND_LDFLAGS)
set(SECP256K1_APPEND_LDFLAGS ${SECP256K1_APPEND_LDFLAGS} CACHE STRING "" FORCE)
# We want to build libsecp256k1 with the most tested RelWithDebInfo configuration.
enable_language(C)
foreach(config IN LISTS CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES)
if(config STREQUAL "")
continue()

View File

@@ -5,7 +5,7 @@ Upstream-Contact: Satoshi Nakamoto <satoshin@gmx.com>
Source: https://github.com/bitcoin/bitcoin
Files: *
Copyright: 2009-2025, Bitcoin Core Developers
Copyright: 2009-2026, Bitcoin Core Developers
License: Expat
Comment: The Bitcoin Core Developers encompasses all contributors to the
project, listed in the release notes or the git log.

View File

@@ -3,6 +3,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import os
import re
import subprocess
import sys
import tempfile
@@ -59,10 +60,11 @@ for relpath in BINARIES:
print(f'{abspath} not found or not an executable', file=sys.stderr)
sys.exit(1)
# take first line (which must contain version)
verstr = r.stdout.splitlines()[0]
# last word of line is the actual version e.g. v22.99.0-5c6b3d5b3508
verstr = verstr.split()[-1]
assert verstr.startswith('v')
output = r.stdout.splitlines()[0]
# find the version e.g. v30.99.0-ce771726f3e7
search = re.search(r"v[0-9]\S+", output)
assert search
verstr = search.group(0)
# remaining lines are copyright
copyright = r.stdout.split('\n')[1:]
assert copyright[0].startswith('Copyright (C)')

View File

@@ -37,7 +37,7 @@ You can then either point to the SDK using the `SDK_PATH` environment variable:
```sh
# Extract the SDK tarball to /path/to/parent/dir/of/extracted/SDK/Xcode-<foo>-<bar>-extracted-SDK-with-libcxx-headers
tar -C /path/to/parent/dir/of/extracted/SDK -xaf /path/to/Xcode-<foo>-<bar>-extracted-SDK-with-libcxx-headers.tar.gz
tar -C /path/to/parent/dir/of/extracted/SDK -xaf /path/to/Xcode-<foo>-<bar>-extracted-SDK-with-libcxx-headers.tar
# Indicate where to locate the SDK tarball
export SDK_PATH=/path/to/parent/dir/of/extracted/SDK

View File

@@ -2,6 +2,7 @@
((gnu packages bash) #:select (bash-minimal))
(gnu packages bison)
((gnu packages certs) #:select (nss-certs))
((gnu packages check) #:select (libfaketime))
((gnu packages cmake) #:select (cmake-minimal))
(gnu packages commencement)
(gnu packages compression)
@@ -209,7 +210,17 @@ and abstract ELF, PE and MachO formats.")
(base32
"1j47vwq4caxfv0xw68kw5yh00qcpbd56d7rq6c483ma3y7s96yyz"))))
(build-system cmake-build-system)
(inputs (list openssl))
(arguments
(list
#:phases
#~(modify-phases %standard-phases
(replace 'check
(lambda* (#:key tests? #:allow-other-keys)
(if tests?
(invoke "faketime" "-f" "@2025-01-01 00:00:00" ;; Tests fail after 2025.
"ctest" "--output-on-failure" "--no-tests=error")
(format #t "test suite not run~%")))))))
(inputs (list libfaketime openssl))
(home-page "https://github.com/mtrojnar/osslsigncode")
(synopsis "Authenticode signing and timestamping tool")
(description "osslsigncode is a small tool that implements part of the

View File

@@ -46,8 +46,7 @@ MAX_VERSIONS = {
# Ignore symbols that are exported as part of every executable
IGNORE_EXPORTS = {
'environ', '_environ', '__environ', '_fini', '_init', 'stdin',
'stdout', 'stderr',
'stdin', 'stdout', 'stderr',
}
# Expected linker-loader names can be found here:
@@ -112,7 +111,6 @@ ELF_ALLOWED_LIBRARIES = {
'libfontconfig.so.1', # font support
'libfreetype.so.6', # font parsing
'libdl.so.2', # programming interface to dynamic linker
'libxcb-cursor.so.0',
'libxcb-icccm.so.4',
'libxcb-image.so.0',
'libxcb-shm.so.0',

View File

@@ -44,15 +44,15 @@ xip -x Xcode_15.xip
### Step 2: Generating the SDK tarball from `Xcode.app`
To generate the SDK, run the script [`gen-sdk`](./gen-sdk) with the
To generate the SDK, run the script [`gen-sdk.py`](./gen-sdk.py) with the
path to `Xcode.app` (extracted in the previous stage) as the first argument.
```bash
./contrib/macdeploy/gen-sdk '/path/to/Xcode.app'
./contrib/macdeploy/gen-sdk.py '/path/to/Xcode.app'
```
The generated archive should be: `Xcode-15.0-15A240d-extracted-SDK-with-libcxx-headers.tar.gz`.
The `sha256sum` should be `c0c2e7bb92c1fee0c4e9f3a485e4530786732d6c6dd9e9f418c282aa6892f55d`.
The generated archive should be: `Xcode-15.0-15A240d-extracted-SDK-with-libcxx-headers.tar`.
The `sha256sum` should be `95b00dc41fa090747dc0a7907a5031a2fcb2d7f95c9584ba6bccdb99b6e3d498`.
## Deterministic macOS App Notes

View File

@@ -2,9 +2,7 @@
import argparse
import plistlib
import pathlib
import sys
import tarfile
import gzip
import os
import contextlib
@@ -22,12 +20,12 @@ def run():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('xcode_app', metavar='XCODEAPP', nargs=1)
parser.add_argument("-o", metavar='OUTSDKTGZ', nargs=1, dest='out_sdktgz', required=False)
parser.add_argument('xcode_app', metavar='XCODEAPP', type=pathlib.Path)
parser.add_argument("-o", metavar='OUTSDKTAR', dest='out_sdkt', type=pathlib.Path, required=False)
args = parser.parse_args()
xcode_app = pathlib.Path(args.xcode_app[0]).resolve()
xcode_app = args.xcode_app.resolve()
assert xcode_app.is_dir(), "The supplied Xcode.app path '{}' either does not exist or is not a directory".format(xcode_app)
xcode_app_plist = xcode_app.joinpath("Contents/version.plist")
@@ -47,11 +45,7 @@ def run():
out_name = "Xcode-{xcode_version}-{xcode_build_id}-extracted-SDK-with-libcxx-headers".format(xcode_version=xcode_version, xcode_build_id=xcode_build_id)
if args.out_sdktgz:
out_sdktgz_path = pathlib.Path(args.out_sdktgz_path)
else:
# Construct our own out_sdktgz if not specified on the command line
out_sdktgz_path = pathlib.Path("./{}.tar.gz".format(out_name))
out_sdkt_path = args.out_sdkt or pathlib.Path("./{}.tar".format(out_name))
def tarfp_add_with_base_change(tarfp, dir_to_add, alt_base_dir):
"""Add all files in dir_to_add to tarfp, but prepend alt_base_dir to the files'
@@ -68,6 +62,8 @@ def run():
"""
def change_tarinfo_base(tarinfo):
if tarinfo.name and tarinfo.name.endswith((".swiftmodule", ".modulemap")):
return None
if tarinfo.name and tarinfo.name.startswith("./"):
tarinfo.name = str(pathlib.Path(alt_base_dir, tarinfo.name))
if tarinfo.linkname and tarinfo.linkname.startswith("./"):
@@ -81,16 +77,17 @@ def run():
return tarinfo
with cd(dir_to_add):
# recursion already adds entries in sorted order
tarfp.add(".", recursive=True, filter=change_tarinfo_base)
tarfp.add("./usr/include", recursive=True, filter=change_tarinfo_base)
tarfp.add("./usr/lib", recursive=True, filter=change_tarinfo_base)
tarfp.add("./System/Library/Frameworks", recursive=True, filter=change_tarinfo_base)
print("Creating output .tar.gz file...")
with out_sdktgz_path.open("wb") as fp:
with gzip.GzipFile(fileobj=fp, mode='wb', compresslevel=9, mtime=0) as gzf:
with tarfile.open(mode="w", fileobj=gzf, format=tarfile.GNU_FORMAT) as tarfp:
print("Adding MacOSX SDK {} files...".format(sdk_version))
tarfp_add_with_base_change(tarfp, sdk_dir, out_name)
print("Done! Find the resulting gzipped tarball at:")
print(out_sdktgz_path.resolve())
print("Creating output .tar file...")
with out_sdkt_path.open("wb") as fp:
with tarfile.open(mode="w", fileobj=fp, format=tarfile.PAX_FORMAT) as tarfp:
print("Adding MacOSX SDK {} files...".format(sdk_version))
tarfp_add_with_base_change(tarfp, sdk_dir, out_name)
print("Done! Find the resulting tarball at:")
print(out_sdkt_path.resolve())
if __name__ == '__main__':
run()

View File

@@ -466,18 +466,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

@@ -10,14 +10,13 @@ to addrman with).
Update `MIN_BLOCKS` in `makeseeds.py` and the `-m`/`--minblocks` arguments below, as needed.
The seeds compiled into the release are created from sipa's, achow101's and luke-jr's
The seeds compiled into the release are created from sipa's and achow101's
DNS seed, virtu's crawler, and asmap community AS map data. Run the following commands
from the `/contrib/seeds` directory:
```
curl https://bitcoin.sipa.be/seeds.txt.gz | gzip -dc > seeds_main.txt
curl https://21.ninja/seeds.txt.gz | gzip -dc >> seeds_main.txt
curl https://luke.dashjr.org/programs/bitcoin/files/charts/seeds.txt >> seeds_main.txt
curl https://mainnet.achownodes.xyz/seeds.txt.gz | gzip -dc >> seeds_main.txt
curl https://signet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_signet.txt
curl https://testnet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_test.txt

View File

@@ -38,7 +38,7 @@ endef
define fetch_file
( test -f $$($(1)_source_dir)/$(4) || \
( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \
$(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5))))
$(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(4),$(4),$(5))))
endef
# Shell script to create a source tarball in $(1)_source from local directory

View File

@@ -6,7 +6,7 @@ $(package)_sha256_hash=0e9c5446dc6f3beb8af6ebfcc9e27bcc6da6fe2860f7fc07b99144dfa
$(package)_dependencies=libxcb libxcb_util_render libxcb_util_image
define $(package)_set_vars
$(package)_config_opts = --disable-static
$(package)_config_opts = --disable-shared
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking
endef

View File

@@ -16,6 +16,7 @@ $(package)_patches += qtbase_avoid_native_float16.patch
$(package)_patches += qtbase_avoid_qmain.patch
$(package)_patches += qtbase_platformsupport.patch
$(package)_patches += qtbase_plugins_cocoa.patch
$(package)_patches += qtbase_plugins_windows11style.patch
$(package)_patches += qtbase_skip_tools.patch
$(package)_patches += rcc_hardcode_timestamp.patch
$(package)_patches += qttools_skip_dependencies.patch
@@ -261,6 +262,7 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/qtbase_avoid_qmain.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_platformsupport.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_cocoa.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_windows11style.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_skip_tools.patch && \
patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch
endef

View File

@@ -0,0 +1,113 @@
QWindows11Style: Calculate Spinbox size based on CommonStyle size
Use the calculation from Commonstyle and add the increased padding and
horizontally layouted buttons to the horizontal size hint.
Fixes: QTBUG-130288
Change-Id: I7932b782e7873a0178091a51379f17453eb585fd
Upstream commits:
- Qt 6.8.1: 9107817eaceaacc968dbc767c24594566d637b8c
- Qt 6.9.0: 96d46cad43517adefa2eb7cb8819a0b2cc9241e6
--- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -2048,39 +2048,22 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
}
break;
#endif
+#if QT_CONFIG(spinbox)
case QStyle::CT_SpinBox: {
if (const auto *spinBoxOpt = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
// Add button + frame widths
- int width = 0;
-
- if (const QDateTimeEdit *spinBox = qobject_cast<const QDateTimeEdit *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->minimumDateTime().toString(spinBox->displayFormat()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->maximumDateTime().toString(spinBox->displayFormat()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- } else if (const QSpinBox *spinBox = qobject_cast<const QSpinBox *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width();
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width();
-
- } else if (const QDoubleSpinBox *spinBox = qobject_cast<const QDoubleSpinBox *>(widget)) {
- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum()));
- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum()));
- width = qMax(textSizeMin.width(),textSizeMax.width());
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width();
- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width();
- }
const qreal dpi = QStyleHelper::dpi(option);
const bool hasButtons = (spinBoxOpt->buttonSymbols != QAbstractSpinBox::NoButtons);
- const int buttonWidth = hasButtons ? 2 * qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
+ const int margins = 8;
+ const int buttonWidth = hasButtons ? qRound(QStyleHelper::dpiScaled(16, dpi)) : 0;
const int frameWidth = spinBoxOpt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth,
spinBoxOpt, widget) : 0;
- contentSize.setWidth(2 * 12 + width);
- contentSize += QSize(buttonWidth + 2 * frameWidth, 2 * frameWidth);
+
+ contentSize += QSize(2 * buttonWidth + 2 * frameWidth + 2 * margins, 2 * frameWidth);
}
break;
}
+#endif
default:
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
break;
Windows11Style: don't set minimum width for QAbstractSpinBox
There is no need to set a minimum width for QAbstractSpinBox in
QWindows11Style::polish() as this might override the user preferences.
Also the minimum size handling is now properly done within
sizeFromContents().
Change-Id: Ibc1fd7a6f862fc85e3739025b9de581aa235d74c
Upstream commits:
- Qt 6.8.3: f86da3d3f853adb1a5b823c1cc7be6db4a0265f3
- Qt 6.9.0: b93a8dfdfe6900cb542fdc587dd2682007a6ac53
- Qt 6.10.0: 2ec4c28470de115c16944653a5d4f6209452d56c
--- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -29,7 +29,6 @@ QT_BEGIN_NAMESPACE
const static int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners
const static int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners
-constexpr QLatin1StringView originalWidthProperty("_q_windows11_style_original_width");
enum WINUI3Color {
subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements
@@ -2140,13 +2139,6 @@ void QWindows11Style::polish(QWidget* widget)
pal.setColor(QPalette::ButtonText, pal.text().color());
pal.setColor(QPalette::BrightText, pal.text().color());
widget->setPalette(pal);
- } else if (widget->inherits("QAbstractSpinBox")) {
- const int minWidth = 2 * 24 + 40;
- const int originalWidth = widget->size().width();
- if (originalWidth < minWidth) {
- widget->resize(minWidth, widget->size().height());
- widget->setProperty(originalWidthProperty.constData(), originalWidth);
- }
} else if (widget->inherits("QAbstractButton") || widget->inherits("QToolButton")) {
widget->setAutoFillBackground(false);
auto pal = widget->palette();
@@ -2191,13 +2183,6 @@ void QWindows11Style::unpolish(QWidget *widget)
scrollarea->viewport()->setPalette(pal);
scrollarea->viewport()->setProperty("_q_original_background_palette", QVariant());
}
- if (widget->inherits("QAbstractSpinBox")) {
- const QVariant originalWidth = widget->property(originalWidthProperty.constData());
- if (originalWidth.isValid()) {
- widget->resize(originalWidth.toInt(), widget->size().height());
- widget->setProperty(originalWidthProperty.constData(), QVariant());
- }
- }
}
/*

View File

@@ -101,5 +101,5 @@ cmake -B build -DENABLE_WALLET=OFF
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```

View File

@@ -34,7 +34,7 @@ cmake -B build
SQLite is required for the wallet:
```bash
pkgin sqlite3
pkgin install sqlite3
```
To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`.
@@ -42,7 +42,7 @@ To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`.
Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)):
```bash
pkgin capnproto
pkgin install capnproto
```
Compile with `-DENABLE_IPC=OFF` if you do not need IPC functionality.
@@ -84,7 +84,7 @@ Otherwise, if you don't need QR encoding support, use the `-DWITH_QRENCODE=OFF`
Bitcoin Core can provide notifications via ZeroMQ. If the package is installed, support will be compiled in.
```bash
pkgin zeromq
pkgin install zeromq
```
#### Test Suite Dependencies
@@ -115,5 +115,5 @@ Build and run the tests:
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```

View File

@@ -1,6 +1,6 @@
# OpenBSD Build Guide
**Updated for OpenBSD [7.6](https://www.openbsd.org/76.html)**
**Updated for OpenBSD [7.8](https://www.openbsd.org/78.html)**
This guide describes how to build bitcoind, command-line utilities, and GUI on OpenBSD.
@@ -21,8 +21,11 @@ pkg_add sqlite3
To build Bitcoin Core without the wallet, use `-DENABLE_WALLET=OFF`.
Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md))
and can be built from source: https://capnproto.org/install.html
Cap'n Proto is needed for IPC functionality (see [multiprocess.md](multiprocess.md)):
```bash
pkg_add capnproto
```
Compile with `-DENABLE_IPC=OFF` if you do not need IPC functionality.
@@ -93,7 +96,7 @@ Run `cmake -B build -LH` to see the full list of available options.
```bash
cmake --build build # Append "-j N" for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```
## Resource limits

View File

@@ -170,7 +170,7 @@ Run the following in your terminal to compile Bitcoin Core:
``` bash
cmake --build build # Append "-j N" here for N parallel jobs.
ctest --test-dir build # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build # Append "-j N" for N parallel tests.
```
### 3. Deploy (optional)

View File

@@ -81,8 +81,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
sudo apt-get install qt6-base-dev qt6-tools-dev qt6-l10n-tools qt6-tools-dev-tools libgl-dev
For Qt 6.5 and later, the `libxcb-cursor0` package must be installed at runtime.
Additionally, to support Wayland protocol for modern desktop environments:
sudo apt install qt6-wayland
@@ -133,8 +131,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
sudo dnf install qt6-qtbase-devel qt6-qttools-devel
For Qt 6.5 and later, the `xcb-util-cursor` package must be installed at runtime.
Additionally, to support Wayland protocol for modern desktop environments:
sudo dnf install qt6-qtwayland
@@ -182,8 +178,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
apk add qt6-qtbase-dev qt6-qttools-dev
For Qt 6.5 and later, the `xcb-util-cursor` package must be installed at runtime.
The GUI will be able to encode addresses in QR codes unless this feature is explicitly disabled. To install libqrencode, run:
apk add libqrencode-dev

View File

@@ -55,7 +55,7 @@ In the following instructions, the "Debug" configuration can be specified instea
```
cmake -B build --preset vs2022-static # It might take a while if the vcpkg binary cache is unpopulated or invalidated.
cmake --build build --config Release # Append "-j N" for N parallel jobs.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests.
cmake --install build --config Release # Optional.
```
@@ -64,7 +64,7 @@ cmake --install build --config Release # Optional.
```
cmake -B build --preset vs2022 -DBUILD_GUI=OFF # It might take a while if the vcpkg binary cache is unpopulated or invalidated.
cmake --build build --config Release # Append "-j N" for N parallel jobs.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests. Some tests are disabled if Python 3 is not available.
ctest --test-dir build --build-config Release # Append "-j N" for N parallel tests.
```
### 6. vcpkg-specific Issues and Workarounds

View File

@@ -19,7 +19,7 @@ Bitcoin Core requires one of the following compilers.
| Dependency | Releases | Minimum required |
| --- | --- | --- |
| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.73.0](https://github.com/bitcoin/bitcoin/pull/29066) |
| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.74.0](https://github.com/bitcoin/bitcoin/pull/34107) |
| CMake | [link](https://cmake.org/) | [3.22](https://github.com/bitcoin/bitcoin/pull/30454) |
| [libevent](../depends/packages/libevent.mk) | [link](https://github.com/libevent/libevent/releases) | [2.1.8](https://github.com/bitcoin/bitcoin/pull/24681) |

View File

@@ -8,7 +8,7 @@
| *libbitcoin_crypto* | Hardware-optimized functions for data encryption, hashing, message authentication, and key derivation. |
| *libbitcoin_kernel* | Consensus engine and support library used for validation by *libbitcoin_node*. |
| *libbitcoinqt* | GUI functionality used by *bitcoin-qt* and *bitcoin-gui* executables. |
| *libbitcoin_ipc* | IPC functionality used by *bitcoin-node*, *bitcoin-wallet*, *bitcoin-gui* executables to communicate when [`-DENABLE_IPC=ON`](multiprocess.md) is used. |
| *libbitcoin_ipc* | IPC functionality used by *bitcoin-node* and *bitcoin-gui* executables to communicate when [`-DENABLE_IPC=ON`](multiprocess.md) is used. |
| *libbitcoin_node* | P2P and RPC server functionality used by *bitcoind* and *bitcoin-qt* executables. |
| *libbitcoin_util* | Home for common functionality shared by different executables and libraries. Similar to *libbitcoin_common*, but lower-level (see [Dependencies](#dependencies)). |
| *libbitcoin_wallet* | Wallet functionality used by *bitcoind* and *bitcoin-wallet* executables. |

View File

@@ -79,7 +79,7 @@ of the test. Just make sure to use double-dash to distinguish them from the
fuzzer's own arguments:
```sh
$ FUZZ=address_deserialize_v2 build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize_v2 --checkaddrman=5 --printtoconsole=1
$ FUZZ=address_deserialize build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize --checkaddrman=5 --printtoconsole=1
```
## Fuzzing corpora

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-CLI "1" "September 2025" "bitcoin-cli v30.0.0rc1" "User Commands"
.TH BITCOIN-CLI "1" "January 2026" "bitcoin-cli v30.2.0" "User Commands"
.SH NAME
bitcoin-cli \- manual page for bitcoin-cli v30.0.0rc1
bitcoin-cli \- manual page for bitcoin-cli v30.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 v30.0.0rc1
.B bitcoin-cli
[\fI\,options\/\fR] \fI\,help <command>\/\fR
.SH DESCRIPTION
Bitcoin Core RPC client version v30.0.0rc1
Bitcoin Core RPC client version v30.2.0
.PP
The bitcoin\-cli utility provides a command line interface to interact with a Bitcoin Core RPC server.
.PP
@@ -188,7 +188,7 @@ additional "outonly" (or "o") argument can be passed to see
outbound peers only. Pass "help" (or "h") for detailed help
documentation.
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-QT "1" "September 2025" "bitcoin-qt v30.0.0rc1" "User Commands"
.TH BITCOIN-QT "1" "January 2026" "bitcoin-qt v30.2.0" "User Commands"
.SH NAME
bitcoin-qt \- manual page for bitcoin-qt v30.0.0rc1
bitcoin-qt \- manual page for bitcoin-qt v30.2.0
.SH SYNOPSIS
.B bitcoin-qt
[\fI\,options\/\fR] [\fI\,URI\/\fR]
.SH DESCRIPTION
Bitcoin Core version v30.0.0rc1
Bitcoin Core version v30.2.0
.PP
The bitcoin\-qt application provides a graphical interface for interacting with Bitcoin Core.
.PP
@@ -695,13 +695,13 @@ Equivalent bytes per sigop in transactions for relay and mining
.HP
\fB\-datacarrier\fR
.IP
(DEPRECATED) Relay and mine data carrier transactions (default: 1)
Relay and mine data carrier transactions (default: 1)
.HP
\fB\-datacarriersize\fR
.IP
(DEPRECATED) Relay and mine transactions whose data\-carrying raw
scriptPubKeys in aggregate are of this size or less, allowing
multiple outputs (default: 100000)
Relay and mine transactions whose data\-carrying raw scriptPubKeys in
aggregate are of this size or less, allowing multiple outputs
(default: 100000)
.HP
\fB\-minrelaytxfee=\fR<amt>
.IP
@@ -839,7 +839,7 @@ Reset all settings changed in the GUI
.IP
Show splash screen on startup (default: 1)
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-TX "1" "September 2025" "bitcoin-tx v30.0.0rc1" "User Commands"
.TH BITCOIN-TX "1" "January 2026" "bitcoin-tx v30.2.0" "User Commands"
.SH NAME
bitcoin-tx \- manual page for bitcoin-tx v30.0.0rc1
bitcoin-tx \- manual page for bitcoin-tx v30.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 v30.0.0rc1
.B bitcoin-tx
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR]
.SH DESCRIPTION
Bitcoin Core bitcoin\-tx utility version v30.0.0rc1
Bitcoin Core bitcoin\-tx utility version v30.2.0
.PP
The bitcoin\-tx tool is used for creating and modifying bitcoin transactions.
.PP
@@ -146,7 +146,7 @@ set=NAME:JSON\-STRING
.IP
Set register NAME to given JSON\-STRING
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-UTIL "1" "September 2025" "bitcoin-util v30.0.0rc1" "User Commands"
.TH BITCOIN-UTIL "1" "January 2026" "bitcoin-util v30.2.0" "User Commands"
.SH NAME
bitcoin-util \- manual page for bitcoin-util v30.0.0rc1
bitcoin-util \- manual page for bitcoin-util v30.2.0
.SH SYNOPSIS
.B bitcoin-util
[\fI\,options\/\fR] [\fI\,command\/\fR]
@@ -9,7 +9,7 @@ bitcoin-util \- manual page for bitcoin-util v30.0.0rc1
.B bitcoin-util
[\fI\,options\/\fR] \fI\,grind <hex-block-header>\/\fR
.SH DESCRIPTION
Bitcoin Core bitcoin\-util utility version v30.0.0rc1
Bitcoin Core bitcoin\-util utility version v30.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
@@ -65,7 +65,7 @@ grind
.IP
Perform proof of work on hex header string
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-WALLET "1" "September 2025" "bitcoin-wallet v30.0.0rc1" "User Commands"
.TH BITCOIN-WALLET "1" "January 2026" "bitcoin-wallet v30.2.0" "User Commands"
.SH NAME
bitcoin-wallet \- manual page for bitcoin-wallet v30.0.0rc1
bitcoin-wallet \- manual page for bitcoin-wallet v30.2.0
.SH SYNOPSIS
.B bitcoin-wallet
[\fI\,options\/\fR] \fI\,<command>\/\fR
.SH DESCRIPTION
Bitcoin Core bitcoin\-wallet utility version v30.0.0rc1
Bitcoin Core bitcoin\-wallet utility version v30.2.0
.PP
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
.PP
@@ -100,7 +100,7 @@ info
.IP
Get wallet info
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN "1" "September 2025" "bitcoin v30.0.0rc1" "User Commands"
.TH BITCOIN "1" "January 2026" "bitcoin v30.2.0" "User Commands"
.SH NAME
bitcoin \- manual page for bitcoin v30.0.0rc1
bitcoin \- manual page for bitcoin v30.2.0
.SH SYNOPSIS
.B bitcoin
[\fI\,OPTIONS\/\fR] \fI\,COMMAND\/\fR...
@@ -46,7 +46,7 @@ chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bit
test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.
test\-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin\-qt [ARGS]'.
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIND "1" "September 2025" "bitcoind v30.0.0rc1" "User Commands"
.TH BITCOIND "1" "January 2026" "bitcoind v30.2.0" "User Commands"
.SH NAME
bitcoind \- manual page for bitcoind v30.0.0rc1
bitcoind \- manual page for bitcoind v30.2.0
.SH SYNOPSIS
.B bitcoind
[\fI\,options\/\fR]
.SH DESCRIPTION
Bitcoin Core daemon version v30.0.0rc1
Bitcoin Core daemon version v30.2.0 bitcoind
.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
@@ -695,13 +695,13 @@ Equivalent bytes per sigop in transactions for relay and mining
.HP
\fB\-datacarrier\fR
.IP
(DEPRECATED) Relay and mine data carrier transactions (default: 1)
Relay and mine data carrier transactions (default: 1)
.HP
\fB\-datacarriersize\fR
.IP
(DEPRECATED) Relay and mine transactions whose data\-carrying raw
scriptPubKeys in aggregate are of this size or less, allowing
multiple outputs (default: 100000)
Relay and mine transactions whose data\-carrying raw scriptPubKeys in
aggregate are of this size or less, allowing multiple outputs
(default: 100000)
.HP
\fB\-minrelaytxfee=\fR<amt>
.IP
@@ -817,7 +817,7 @@ subject to empty whitelists.
.IP
Accept command line and JSON\-RPC commands
.SH COPYRIGHT
Copyright (C) 2009-2025 The Bitcoin Core developers
Copyright (C) 2009-2026 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org/> for further information about the software.

View File

@@ -1 +1,91 @@
See https://github.com/bitcoin-core/bitcoin-devwiki/wiki/v30.0-Release-Notes-Draft.
v30.2 Release Notes
===================
Bitcoin Core version v30.2 is now available from:
<https://bitcoincore.org/bin/bitcoin-core-30.2/>
This release includes new features, various bug fixes and performance
improvements, as well as updated translations.
Please report bugs using the issue tracker at GitHub:
<https://github.com/bitcoin/bitcoin/issues>
To receive security and update notifications, please subscribe to:
<https://bitcoincore.org/en/list/announcements/join/>
How to Upgrade
==============
If you are running an older version, shut it down. Wait until it has completely
shut down (which might take a few minutes in some cases), then run the
installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS)
or `bitcoind`/`bitcoin-qt` (on Linux).
Upgrading directly from a version of Bitcoin Core that has reached its EOL is
possible, but it might take some time if the data directory needs to be migrated. Old
wallet versions of Bitcoin Core are generally supported.
Compatibility
==============
Bitcoin Core is supported and tested on operating systems using the
Linux Kernel 3.17+, macOS 13+, and Windows 10+. Bitcoin
Core should also work on most other Unix-like systems but is not as
frequently tested on them. It is not recommended to use Bitcoin Core on
unsupported systems.
Notable changes
===============
### Wallet
- #34156 wallet: fix unnamed legacy wallet migration failure
- #34215 wallettool: fix unnamed createfromdump failure walletsdir deletion
- #34221 test: migration, avoid backup name mismatch in default_wallet_failure
### IPC
- #33511 init: Fix Ctrl-C shutdown hangs during wait calls
### Build
- #33950 guix: reduce allowed exported symbols
- #34107 build: Update minimum required Boost version
- #34227 guix: Fix osslsigncode tests
### Test
- #34137 test: Avoid hard time.sleep(1) in feature_init.py
- #34226 wallet: test: Relative wallet failed migration cleanup
### Fuzz
- #34091 fuzz: doc: remove any mention to address_deserialize_v2
### Doc
- #34182 doc: Update OpenBSD Build Guide
### Misc
- #34174 doc: update copyright year to 2026
Credits
=======
Thanks to everyone who directly contributed to this release:
- Ava Chow
- brunoerg
- davidgumberg
- fanquake
- furszy
- Hennadii Stepanov
- MarcoFalke
- Ryan Ofsky
As well as to everyone that helped with translations on
[Transifex](https://explore.transifex.com/bitcoin/bitcoin/).

View File

@@ -111,7 +111,7 @@ For the period during which the notes are being edited on the wiki, the version
Generate list of authors:
git log --format='- %aN' v(current version, e.g. 25.0)..v(new version, e.g. 25.1) | grep -v 'merge-script' | sort -fiu
git log --format='- %aN' v(current version, e.g. 29.0)..v(new version, e.g. 30.0) | grep -v 'merge-script' | sort -fiu
### Setup and perform Guix builds

View File

@@ -576,12 +576,12 @@
# (default: 20)
#bytespersigop=1
# (DEPRECATED) Relay and mine data carrier transactions (default: 1)
# Relay and mine data carrier transactions (default: 1)
#datacarrier=1
# (DEPRECATED) Relay and mine transactions whose data-carrying raw
# scriptPubKeys in aggregate are of this size or less, allowing
# multiple outputs (default: 100000)
# Relay and mine transactions whose data-carrying raw scriptPubKeys in
# aggregate are of this size or less, allowing multiple outputs
# (default: 100000)
#datacarriersize=1
# Fees (in BTC/kvB) smaller than this are considered zero fee for

View File

@@ -113,6 +113,19 @@ Section -post SEC0001
WriteRegStr HKCR "@CLIENT_TARNAME@" "" "URL:Bitcoin"
WriteRegStr HKCR "@CLIENT_TARNAME@\DefaultIcon" "" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
WriteRegStr HKCR "@CLIENT_TARNAME@\shell\open\command" "" '"$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "%1"'
# Lingering since fb2b05b1259d3e69e6e675adfa30b429424c7625 which removed the suffix
DeleteRegValue HKCU "${REGKEY} (64-bit)\Components" Main
DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name) (64-bit)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name) (64-bit).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name) (64-bit).lnk"
DeleteRegValue HKCU "${REGKEY} (64-bit)" StartMenuGroup
DeleteRegValue HKCU "${REGKEY} (64-bit)" Path
DeleteRegKey /IfEmpty HKCU "${REGKEY} (64-bit)\Components"
DeleteRegKey /IfEmpty HKCU "${REGKEY} (64-bit)"
# Lingering since 77b2923f87131a407f7d4193c54db22375130403
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Bitcoin Core (testnet, 64-bit).lnk"
SectionEnd
# Macro for selecting uninstaller sections

View File

@@ -292,8 +292,8 @@ if(BUILD_BITCOIN_BIN)
add_executable(bitcoin bitcoin.cpp)
add_windows_resources(bitcoin bitcoin-res.rc)
add_windows_application_manifest(bitcoin)
target_link_libraries(bitcoin core_interface bitcoin_util)
install_binary_component(bitcoin)
target_link_libraries(bitcoin core_interface bitcoin_common bitcoin_util)
install_binary_component(bitcoin HAS_MANPAGE)
endif()
# Bitcoin Core bitcoind.

View File

@@ -5,6 +5,7 @@
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <clientversion.h>
#include <common/args.h>
#include <util/fs.h>
#include <util/exec.h>
#include <util/strencodings.h>
@@ -47,7 +48,7 @@ Run '%s help' to see additional commands (e.g. for testing and debugging).
)";
struct CommandLine {
bool use_multiprocess{false};
std::optional<bool> use_multiprocess;
bool show_version{false};
bool show_help{false};
std::string_view command;
@@ -55,6 +56,7 @@ struct CommandLine {
};
CommandLine ParseCommandLine(int argc, char* argv[]);
bool UseMultiprocess(const CommandLine& cmd);
static void ExecCommand(const std::vector<const char*>& args, std::string_view argv0);
int main(int argc, char* argv[])
@@ -78,9 +80,9 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}
} else if (cmd.command == "gui") {
args.emplace_back(cmd.use_multiprocess ? "bitcoin-gui" : "bitcoin-qt");
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-gui" : "bitcoin-qt");
} else if (cmd.command == "node") {
args.emplace_back(cmd.use_multiprocess ? "bitcoin-node" : "bitcoind");
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-node" : "bitcoind");
} else if (cmd.command == "rpc") {
args.emplace_back("bitcoin-cli");
// Since "bitcoin rpc" is a new interface that doesn't need to be
@@ -143,6 +145,30 @@ CommandLine ParseCommandLine(int argc, char* argv[])
return cmd;
}
bool UseMultiprocess(const CommandLine& cmd)
{
// If -m or -M options were explicitly specified, there is no need to
// further parse arguments to determine which to use.
if (cmd.use_multiprocess) return *cmd.use_multiprocess;
ArgsManager args;
args.SetDefaultFlags(ArgsManager::ALLOW_ANY);
std::string error_message;
auto argv{cmd.args};
argv.insert(argv.begin(), nullptr);
if (!args.ParseParameters(argv.size(), argv.data(), error_message)) {
tfm::format(std::cerr, "Warning: failed to parse subcommand command line options: %s\n", error_message);
}
if (!args.ReadConfigFiles(error_message, true)) {
tfm::format(std::cerr, "Warning: failed to parse subcommand config: %s\n", error_message);
}
args.SelectConfigNetwork(args.GetChainTypeString());
// If any -ipc* options are set these need to be processed by a
// multiprocess-capable binary.
return args.IsArgSet("-ipcbind") || args.IsArgSet("-ipcconnect") || args.IsArgSet("-ipcfd");
}
//! Execute the specified bitcoind, bitcoin-qt or other command line in `args`
//! using src, bin and libexec directory paths relative to this executable, where
//! the path to this executable is specified in `wrapper_argv0`.

View File

@@ -132,11 +132,16 @@ static bool ParseArgs(NodeContext& node, int argc, char* argv[])
return true;
}
static bool ProcessInitCommands(ArgsManager& args)
static bool ProcessInitCommands(interfaces::Init& init, ArgsManager& args)
{
// Process help and version before taking care about datadir
if (HelpRequested(args) || args.GetBoolArg("-version", false)) {
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion() + "\n";
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion();
if (const char* exe_name{init.exeName()}) {
strUsage += " ";
strUsage += exe_name;
}
strUsage += "\n";
if (args.GetBoolArg("-version", false)) {
strUsage += FormatParagraph(LicenseInfo());
@@ -277,7 +282,7 @@ MAIN_FUNCTION
ArgsManager& args = *Assert(node.args);
if (!ParseArgs(node, argc, argv)) return EXIT_FAILURE;
// Process early info return commands such as -help or -version
if (ProcessInitCommands(args)) return EXIT_SUCCESS;
if (ProcessInitCommands(*init, args)) return EXIT_SUCCESS;
// Start application
if (!AppInit(node) || !Assert(node.shutdown_signal)->wait()) {

View File

@@ -266,7 +266,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
return search->second.m_flags;
}
}
return std::nullopt;
return m_default_flags;
}
void ArgsManager::SetDefaultFlags(std::optional<unsigned int> flags)
{
LOCK(cs_args);
m_default_flags = flags;
}
fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const

View File

@@ -137,6 +137,7 @@ protected:
std::string m_network GUARDED_BY(cs_args);
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
std::optional<unsigned int> m_default_flags GUARDED_BY(cs_args){};
bool m_accept_any_command GUARDED_BY(cs_args){true};
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
std::optional<fs::path> m_config_path GUARDED_BY(cs_args);
@@ -375,10 +376,15 @@ protected:
/**
* Return Flags for known arg.
* Return nullopt for unknown arg.
* Return default flags for unknown arg.
*/
std::optional<unsigned int> GetArgFlags(const std::string& name) const;
/**
* Set default flags to return for an unknown arg.
*/
void SetDefaultFlags(std::optional<unsigned int>);
/**
* Get settings file path, or return false if read-write settings were
* disabled with -nosettings.

View File

@@ -11,19 +11,25 @@
#include <util/string.h>
#include <util/time.h>
#ifndef WIN32
#include <sys/stat.h>
#else
#include <compat/compat.h>
#ifdef WIN32
#include <codecvt>
#include <compat/compat.h>
#include <windows.h>
#else
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef HAVE_MALLOPT_ARENA_MAX
#include <malloc.h>
#endif
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <locale>
#include <optional>
#include <stdexcept>
#include <string>
#include <thread>
@@ -105,6 +111,22 @@ int GetNumCores()
return std::thread::hardware_concurrency();
}
std::optional<size_t> GetTotalRAM()
{
[[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }};
#ifdef WIN32
if (MEMORYSTATUSEX m{}; (m.dwLength = sizeof(m), GlobalMemoryStatusEx(&m))) return clamp(m.ullTotalPhys);
#elif defined(__APPLE__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__) || \
defined(__illumos__) || \
defined(__linux__)
if (long p{sysconf(_SC_PHYS_PAGES)}, s{sysconf(_SC_PAGESIZE)}; p > 0 && s > 0) return clamp(1ULL * p * s);
#endif
return std::nullopt;
}
// Obtain the application startup time (used for uptime calculation)
int64_t GetStartupTime()
{

View File

@@ -9,6 +9,7 @@
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <cstdint>
#include <optional>
#include <string>
// Application startup time (used for uptime calculation)
@@ -29,4 +30,9 @@ void runCommand(const std::string& strCommand);
*/
int GetNumCores();
/**
* Return the total RAM available on the current system, if detectable.
*/
std::optional<size_t> GetTotalRAM();
#endif // BITCOIN_COMMON_SYSTEM_H

View File

@@ -215,8 +215,6 @@ void InitContext(NodeContext& node)
node.shutdown_request = [&node] {
assert(node.shutdown_signal);
if (!(*node.shutdown_signal)()) return false;
// Wake any threads that may be waiting for the tip to change.
if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
return true;
};
}
@@ -267,6 +265,8 @@ void Interrupt(NodeContext& node)
#if HAVE_SYSTEM
ShutdownNotify(*node.args);
#endif
// Wake any threads that may be waiting for the tip to change.
if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
InterruptHTTPServer();
InterruptHTTPRPC();
InterruptRPC();
@@ -658,9 +658,9 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarrier", strprintf("(DEPRECATED) Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarriersize",
strprintf("(DEPRECATED) Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate "
strprintf("Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate "
"are of this size or less, allowing multiple outputs (default: %u)",
MAX_OP_RETURN_RELAY),
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
@@ -903,10 +903,6 @@ bool AppInitParameterInteraction(const ArgsManager& args)
InitWarning(_("Option '-checkpoints' is set but checkpoints were removed. This option has no effect."));
}
if (args.IsArgSet("-datacarriersize") || args.IsArgSet("-datacarrier")) {
InitWarning(_("Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated and are expected to be removed in a future version."));
}
// We no longer limit the orphanage based on number of transactions but keep the option to warn users who still have it in their config.
if (args.IsArgSet("-maxorphantx")) {
InitWarning(_("Option '-maxorphantx' is set but no longer has any effect (see release notes). Please remove it from your configuration."));
@@ -1733,6 +1729,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// ********************************************************* Step 7: load block chain
// cache size calculations
node::LogOversizedDbCache(args);
const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());
LogInfo("Cache configuration:");

View File

@@ -39,6 +39,7 @@ public:
// bitcoin-node accepts the option, and bitcoin-gui accepts all bitcoin-node
// options and will start the node with those options.
bool canListenIpc() override { return true; }
const char* exeName() override { return EXE_NAME; }
node::NodeContext m_node;
std::unique_ptr<interfaces::Ipc> m_ipc;
};

View File

@@ -38,6 +38,7 @@ public:
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
interfaces::Ipc* ipc() override { return m_ipc.get(); }
bool canListenIpc() override { return true; }
const char* exeName() override { return EXE_NAME; }
node::NodeContext& m_node;
std::unique_ptr<interfaces::Ipc> m_ipc;
};

View File

@@ -16,6 +16,8 @@
namespace init {
namespace {
const char* EXE_NAME = "bitcoin-qt";
class BitcoinQtInit : public interfaces::Init
{
public:
@@ -32,6 +34,7 @@ public:
return MakeWalletLoader(chain, *Assert(m_node.args));
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
const char* exeName() override { return EXE_NAME; }
node::NodeContext m_node;
};
} // namespace

View File

@@ -18,6 +18,8 @@ using node::NodeContext;
namespace init {
namespace {
const char* EXE_NAME = "bitcoind";
class BitcoindInit : public interfaces::Init
{
public:
@@ -34,6 +36,7 @@ public:
return MakeWalletLoader(chain, *Assert(m_node.args));
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
const char* exeName() override { return EXE_NAME; }
NodeContext& m_node;
};
} // namespace

View File

@@ -38,6 +38,7 @@ public:
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
virtual Ipc* ipc() { return nullptr; }
virtual bool canListenIpc() { return false; }
virtual const char* exeName() { return nullptr; }
};
//! Return implementation of Init interface for the node process. If the argv

View File

@@ -72,6 +72,11 @@ public:
* the tip is more than 20 minutes old.
*/
virtual std::unique_ptr<BlockTemplate> waitNext(const node::BlockWaitOptions options = {}) = 0;
/**
* Interrupts the current wait for the next block template.
*/
virtual void interruptWait() = 0;
};
//! Interface giving clients (RPC, Stratum v2 Template Provider in the future)

View File

@@ -33,6 +33,7 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
getCoinbaseMerklePath @8 (context: Proxy.Context) -> (result: List(Data));
submitSolution @9 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
waitNext @10 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate);
interruptWait @11() -> ();
}
struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {

View File

@@ -30,10 +30,36 @@
namespace ipc {
namespace capnp {
namespace {
void IpcLogFn(bool raise, std::string message)
BCLog::Level ConvertIPCLogLevel(mp::Log level)
{
LogDebug(BCLog::IPC, "%s\n", message);
if (raise) throw Exception(message);
switch (level) {
case mp::Log::Trace: return BCLog::Level::Trace;
case mp::Log::Debug: return BCLog::Level::Debug;
case mp::Log::Info: return BCLog::Level::Info;
case mp::Log::Warning: return BCLog::Level::Warning;
case mp::Log::Error: return BCLog::Level::Error;
case mp::Log::Raise: return BCLog::Level::Error;
} // no default case, so the compiler can warn about missing cases
// Be conservative and assume that if MP ever adds a new log level, it
// should only be shown at our most verbose level.
return BCLog::Level::Trace;
}
mp::Log GetRequestedIPCLogLevel()
{
if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Trace)) return mp::Log::Trace;
if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Debug)) return mp::Log::Debug;
// Info, Warning, and Error are logged unconditionally
return mp::Log::Info;
}
void IpcLogFn(mp::LogMessage message)
{
LogPrintLevel(BCLog::IPC, ConvertIPCLogLevel(message.level), "%s\n", message.message);
if (message.level == mp::Log::Raise) throw Exception(message.message);
}
class CapnpProtocol : public Protocol
@@ -62,7 +88,11 @@ public:
{
assert(!m_loop);
mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
m_loop.emplace(exe_name, &IpcLogFn, &m_context);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
if (ready_fn) ready_fn();
mp::ServeStream<messages::Init>(*m_loop, fd, init);
m_parent_connection = &m_loop->m_incoming_connections.back();
@@ -90,7 +120,11 @@ public:
std::promise<void> promise;
m_loop_thread = std::thread([&] {
util::ThreadRename("capnp-loop");
m_loop.emplace(exe_name, &IpcLogFn, &m_context);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
m_loop_ref.emplace(*m_loop);
promise.set_value();
m_loop->loop();

5
src/ipc/libmultiprocess/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# CMake artifacts
/*build*
# Git artifacts
*.patch

View File

@@ -2,7 +2,7 @@ CI_DESC="CI job using LLVM-based libraries and tools (clang, libc++, clang-tidy,
CI_DIR=build-llvm
NIX_ARGS=(--arg enableLibcxx true)
export CXX=clang++
export CXXFLAGS="-Werror -Wall -Wextra -Wpedantic -Wthread-safety-analysis -Wno-unused-parameter"
export CXXFLAGS="-Werror -Wall -Wextra -Wpedantic -Wthread-safety -Wno-unused-parameter"
CMAKE_ARGS=(
-G Ninja
-DMP_ENABLE_CLANG_TIDY=ON

View File

@@ -1,5 +1,5 @@
CI_DESC="CI job using old Cap'n Proto version"
CI_DESC="CI job using old Cap'n Proto and cmake versions"
CI_DIR=build-olddeps
export CXXFLAGS="-Werror -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-error=array-bounds"
NIX_ARGS=(--argstr capnprotoVersion "0.7.1")
NIX_ARGS=(--argstr capnprotoVersion "0.7.1" --argstr cmakeVersion "3.12.4")
BUILD_ARGS=(-k)

View File

@@ -1,7 +1,8 @@
CI_DESC="CI job running ThreadSanitizer"
CI_DIR=build-sanitize
NIX_ARGS=(--arg enableLibcxx true --argstr libcxxSanitizers "Thread" --argstr capnprotoSanitizers "thread")
export CXX=clang++
export CXXFLAGS="-ggdb -Werror -Wall -Wextra -Wpedantic -Wthread-safety-analysis -Wno-unused-parameter -fsanitize=thread"
export CXXFLAGS="-ggdb -Werror -Wall -Wextra -Wpedantic -Wthread-safety -Wno-unused-parameter -fsanitize=thread"
CMAKE_ARGS=()
BUILD_ARGS=(-k -j4)
BUILD_TARGETS=(mptest)

View File

@@ -17,6 +17,21 @@ fi
[ -n "${CI_CLEAN-}" ] && rm -rf "${CI_DIR}"
cmake -B "$CI_DIR" "${CMAKE_ARGS[@]+"${CMAKE_ARGS[@]}"}"
cmake --build "$CI_DIR" -t "${BUILD_TARGETS[@]}" -- "${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"}"
ctest --test-dir "$CI_DIR" --output-on-failure
cmake --version
cmake_ver=$(cmake --version | awk '/version/{print $3; exit}')
ver_ge() { [ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]; }
src_dir=$PWD
mkdir -p "$CI_DIR"
cd "$CI_DIR"
cmake "$src_dir" "${CMAKE_ARGS[@]+"${CMAKE_ARGS[@]}"}"
if ver_ge "$cmake_ver" "3.15"; then
cmake --build . -t "${BUILD_TARGETS[@]}" -- "${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"}"
else
# Older versions of cmake can only build one target at a time with --target,
# and do not support -t shortcut
for t in "${BUILD_TARGETS[@]}"; do
cmake --build . --target "$t" -- "${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"}"
done
fi
ctest --output-on-failure

View File

@@ -2,8 +2,8 @@
Given an interface description of an object with one or more methods, libmultiprocess generates:
* A C++ `ProxyClient` class with an implementation of each interface method that sends a request over a socket, waits for a response, and returns the result.
* A C++ `ProxyServer` class that listens for requests over a socket and calls a wrapped C++ object implementing the same interface to actually execute the requests.
* A C++ `ProxyClient` class template specialization with an implementation of each interface method that sends a request over a socket, waits for a response, and returns the result.
* A C++ `ProxyServer` class template specialization that listens for requests over a socket and calls a wrapped C++ object implementing the same interface to actually execute the requests.
The function call ⇆ request translation supports input and output arguments, standard types like `unique_ptr`, `vector`, `map`, and `optional`, and bidirectional calls between processes through interface pointer and `std::function` arguments.
@@ -15,7 +15,7 @@ Libmultiprocess acts as a pure wrapper or layer over the underlying protocol. Cl
### Internals
The `ProxyClient` and `ProxyServer` generated classes are not directly exposed to the user, as described in [usage.md](usage.md). Instead, they wrap c++ interfaces and appear to the user as pointers to an interface. They are first instantiated when calling `ConnectStream` and `ServeStream` respectively for creating the `InitInterface`. These methods establish connections through sockets, internally creating `Connection` objects wrapping a `capnp::RpcSystem` configured for client and server mode respectively.
The `ProxyClient` and `ProxyServer` generated classes are not directly exposed to the user, as described in [usage.md](usage.md). Instead, they wrap C++ interfaces and appear to the user as pointers to an interface. They are first instantiated when calling `ConnectStream` and `ServeStream` respectively for creating the `InitInterface`. These methods establish connections through sockets, internally creating `Connection` objects wrapping a `capnp::RpcSystem` configured for client and server mode respectively.
The `InitInterface` interface will typically have methods which return other interfaces, giving the connecting process the ability to call other functions in the serving process. Interfaces can also have methods accepting other interfaces as parameters, giving serving processes the ability to call back and invoke functions in connecting processes. Creating new interfaces does not create new connections, and typically many interface objects will share the same connection.
@@ -23,13 +23,13 @@ Both `ConnectStream` and `ServeStream` also require an instantiation of the `Eve
When a generated method on the `ProxyClient` is called, it calls `clientInvoke` with the capnp-translated types. `clientInvoke` creates a self-executing promise (`kj::TaskSet`) that drives the execution of the request and gives ownership of it to the `EventLoop`. `clientInvoke` blocks until a response is received, or until there is a call from the server that needs to run on the same client thread, using a `Waiter` object.
On the server side, the `capnp::RpcSystem` receives the capnp request and invokes the corresponding c++ method through the corresponding `ProxyServer` and the heavily templated `serverInvoke` triggering a `ServerCall`. Its return values from the actual c++ methods are copied into capnp responses by `ServerRet` and exceptions are caught and copied by `ServerExcept`. The two are connected through `ServerField`. The main method driving execution of a request is `PassField`, which is invoked through `ServerField`. Instantiated interfaces, or capabilities in capnp speak, are tracked and owned by the server's `capnp::RpcSystem`.
On the server side, the `capnp::RpcSystem` receives the capnp request and invokes the corresponding C++ method through the corresponding `ProxyServer` and the heavily templated `serverInvoke` triggering a `ServerCall`. The return values from the actual C++ methods are copied into capnp responses by `ServerRet` and exceptions are caught and copied by `ServerExcept`. The two are connected through `ServerField`. The main method driving execution of a request is `PassField`, which is invoked through `ServerField`. Instantiated interfaces, or capabilities in capnp speak, are tracked and owned by the server's `capnp::RpcSystem`.
## Interface descriptions
As explained in the [usage](usage.md) document, interface descriptions need to be consumed both by the _libmultiprocess_ code generator, and by C++ code that calls and implements the interfaces. The C++ code only needs to know about C++ arguments and return types, while the code generator only needs to know about capnp arguments and return types, but both need to know class and method names, so the corresponding `.h` and `.capnp` source files contain some of the same information, and have to be kept in sync manually when methods or parameters change. Despite the redundancy, reconciling the interface definitions is designed to be _straightforward_ and _safe_. _Straightforward_ because there is no need to write manual serialization code or use awkward intermediate types like [`UniValue`](https://github.com/bitcoin/bitcoin/blob/master/src/univalue/include/univalue.h) instead of native types. _Safe_ because if there are any inconsistencies between API and data definitions (even minor ones like using a narrow int data type for a wider int API input), there are errors at build time instead of errors or bugs at runtime.
In the future, it would be possible to combine API and data definitions together using [C++ attributes](https://en.cppreference.com/w/cpp/language/attributes). To do this we would add attributes to the API definition files, and then generate the data definitions from the API definitions and attributes. I didn't take this approach mostly because it would be extra work, but also because until c++ standardizes reflection, this would require either hooking into compiler APIs like https://github.com/RosettaCommons/binder, or parsing c++ code manually like http://www.swig.org/.
In the future, it would be possible to combine API and data definitions together using [C++ attributes](https://en.cppreference.com/w/cpp/language/attributes). To do this we would add attributes to the API definition files, and then generate the data definitions from the API definitions and attributes. I didn't take this approach mostly because it would be extra work, but also because until C++ standardizes reflection, this would require either hooking into compiler APIs like https://github.com/RosettaCommons/binder, or parsing C++ code manually like http://www.swig.org/.
## What is `kj`?
@@ -39,6 +39,6 @@ basis in this library to construct the event-loop necessary to service IPC reque
## Future directions
_libmultiprocess_ uses the [Cap'n Proto](https://capnproto.org) interface description language and protocol, but it could be extended or changed to use a different IDL/protocol like [gRPC](https://grpc.io). The nice thing about _Cap'n Proto_ compared to _gRPC_ and most other lower level protocols is that it allows interface pointers (_Services_ in gRPC parlance) to be passed as method arguments and return values, so object references and bidirectional requests work out of the box. Supporting a lower-level protocol would require writing adding maps and tracking code to proxy objects.
_libmultiprocess_ uses the [Cap'n Proto](https://capnproto.org) interface description language and protocol, but it could be extended or changed to use a different IDL/protocol like [gRPC](https://grpc.io). The nice thing about _Cap'n Proto_ compared to _gRPC_ and most other lower level protocols is that it allows interface pointers (_Services_ in gRPC parlance) to be passed as method arguments and return values, so object references and bidirectional requests work out of the box. Supporting a lower-level protocol would require adding maps and tracking code to proxy objects.
_libmultiprocess_ is currently compatible with sandboxing but could add platform-specific sandboxing support or integration with a sandboxing library like [SAPI](https://github.com/google/sandboxed-api).

View File

@@ -4,9 +4,9 @@
_libmultiprocess_ is a library and code generator that allows calling C++ class interfaces across different processes. For an interface to be available from other processes, it needs two definitions:
- An **API definition** declaring how the interface is called. Included examples: [calculator.h](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/calculator.h), [printer.h](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/printer.h), [init.h](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/init.h). Bitcoin examples: [node.h](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/interfaces/node.h), [wallet.h](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/interfaces/wallet.h), [echo.h](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/interfaces/echo.h), [init.h](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/interfaces/init.h).
- An **API definition** declaring how the interface is called. Included examples: [calculator.h](../example/calculator.h), [printer.h](../example/printer.h), [init.h](../example/init.h). Bitcoin examples: [node.h](https://github.com/bitcoin/bitcoin/blob/master/src/interfaces/node.h), [wallet.h](https://github.com/bitcoin/bitcoin/blob/master/src/interfaces/wallet.h), [echo.h](https://github.com/bitcoin/bitcoin/blob/master/src/interfaces/echo.h), [init.h](https://github.com/bitcoin/bitcoin/blob/master/src/interfaces/init.h).
- A **data definition** declaring how interface calls get sent across the wire. Included examples: [calculator.capnp](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/calculator.capnp), [printer.capnp](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/printer.capnp), [init.capnp](https://github.com/bitcoin-core/libmultiprocess/blob/master/example/init.capnp). Bitcoin examples: [node.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/node.capnp), [wallet.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/wallet.capnp), [echo.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/echo.capnp), [init.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/init.capnp).
- A **data definition** declaring how interface calls get sent across the wire. Included examples: [calculator.capnp](../example/calculator.capnp), [printer.capnp](../example/printer.capnp), [init.capnp](../example/init.capnp). Bitcoin examples: [node.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/node.capnp), [wallet.capnp](https://github.com/ryanofsky/bitcoin/blob/ipc-export/src/ipc/capnp/wallet.capnp), [echo.capnp](https://github.com/bitcoin/bitcoin/blob/master/src/ipc/capnp/echo.capnp), [init.capnp](https://github.com/bitcoin/bitcoin/blob/master/src/ipc/capnp/init.capnp).
The `*.capnp` data definition files are consumed by the _libmultiprocess_ code generator and each `X.capnp` file generates `X.capnp.c++`, `X.capnp.h`, `X.capnp.proxy-client.c++`, `X.capnp.proxy-server.c++`, `X.capnp.proxy-types.c++`, `X.capnp.proxy-types.h`, and `X.capnp.proxy.h` output files. The generated files include `mp::ProxyClient<Interface>` and `mp::ProxyServer<Interface>` class specializations for all the interfaces in the `.capnp` files. These allow methods on C++ objects in one process to be called from other processes over IPC sockets.

View File

@@ -9,6 +9,7 @@
#include <charconv>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <kj/async.h>
#include <kj/common.h>
@@ -37,6 +38,7 @@ public:
}
};
// Exercises deprecated log callback signature
static void LogPrint(bool raise, const std::string& message)
{
if (raise) throw std::runtime_error(message);

View File

@@ -35,10 +35,10 @@ static auto Spawn(mp::EventLoop& loop, const std::string& process_argv0, const s
return std::make_tuple(mp::ConnectStream<InitInterface>(loop, fd), pid);
}
static void LogPrint(bool raise, const std::string& message)
static void LogPrint(mp::LogMessage log_data)
{
if (raise) throw std::runtime_error(message);
std::ofstream("debug.log", std::ios_base::app) << message << std::endl;
if (log_data.level == mp::Log::Raise) throw std::runtime_error(log_data.message);
std::ofstream("debug.log", std::ios_base::app) << log_data.message << std::endl;
}
int main(int argc, char** argv)

View File

@@ -32,10 +32,10 @@ public:
std::unique_ptr<Printer> makePrinter() override { return std::make_unique<PrinterImpl>(); }
};
static void LogPrint(bool raise, const std::string& message)
static void LogPrint(mp::LogMessage log_data)
{
if (raise) throw std::runtime_error(message);
std::ofstream("debug.log", std::ios_base::app) << message << std::endl;
if (log_data.level == mp::Log::Raise) throw std::runtime_error(log_data.message);
std::ofstream("debug.log", std::ios_base::app) << log_data.message << std::endl;
}
int main(int argc, char** argv)

View File

@@ -66,8 +66,6 @@ struct ProxyClient<Thread> : public ProxyClientBase<Thread, ::capnp::Void>
ProxyClient(const ProxyClient&) = delete;
~ProxyClient();
void setDisconnectCallback(const std::function<void()>& fn);
//! Reference to callback function that is run if there is a sudden
//! disconnect and the Connection object is destroyed before this
//! ProxyClient<Thread> object. The callback will destroy this object and
@@ -100,36 +98,29 @@ public:
EventLoop& m_loop;
};
using LogFn = std::function<void(bool raise, std::string message)>;
class Logger
{
public:
Logger(bool raise, LogFn& fn) : m_raise(raise), m_fn(fn) {}
Logger(Logger&& logger) : m_raise(logger.m_raise), m_fn(logger.m_fn), m_buffer(std::move(logger.m_buffer)) {}
~Logger() noexcept(false)
{
if (m_fn) m_fn(m_raise, m_buffer.str());
}
template <typename T>
friend Logger& operator<<(Logger& logger, T&& value)
{
if (logger.m_fn) logger.m_buffer << std::forward<T>(value);
return logger;
}
template <typename T>
friend Logger& operator<<(Logger&& logger, T&& value)
{
return logger << std::forward<T>(value);
}
bool m_raise;
LogFn& m_fn;
std::ostringstream m_buffer;
//! Log flags. Update stringify function if changed!
enum class Log {
Trace = 0,
Debug,
Info,
Warning,
Error,
Raise,
};
kj::StringPtr KJ_STRINGIFY(Log flags);
struct LogMessage {
//! Message to be logged
std::string message;
//! The severity level of this message
Log level;
};
using LogFn = std::function<void(LogMessage)>;
struct LogOptions {
//! External logging callback.
@@ -138,8 +129,60 @@ struct LogOptions {
//! Maximum number of characters to use when representing
//! request and response structs as strings.
size_t max_chars{200};
//! Messages with a severity level less than log_level will not be
//! reported.
Log log_level{Log::Trace};
};
class Logger
{
public:
Logger(const LogOptions& options, Log log_level) : m_options(options), m_log_level(log_level) {}
Logger(Logger&&) = delete;
Logger& operator=(Logger&&) = delete;
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
~Logger() noexcept(false)
{
if (enabled()) m_options.log_fn({std::move(m_buffer).str(), m_log_level});
}
template <typename T>
friend Logger& operator<<(Logger& logger, T&& value)
{
if (logger.enabled()) logger.m_buffer << std::forward<T>(value);
return logger;
}
template <typename T>
friend Logger& operator<<(Logger&& logger, T&& value)
{
return logger << std::forward<T>(value);
}
explicit operator bool() const
{
return enabled();
}
private:
bool enabled() const
{
return m_options.log_fn && m_log_level >= m_options.log_level;
}
const LogOptions& m_options;
Log m_log_level;
std::ostringstream m_buffer;
};
#define MP_LOGPLAIN(loop, ...) if (mp::Logger logger{(loop).m_log_opts, __VA_ARGS__}; logger) logger
#define MP_LOG(loop, ...) MP_LOGPLAIN(loop, __VA_ARGS__) << "{" << LongThreadName((loop).m_exe_name) << "} "
std::string LongThreadName(const char* exe_name);
//! Event loop implementation.
@@ -170,8 +213,19 @@ std::string LongThreadName(const char* exe_name);
class EventLoop
{
public:
//! Construct event loop object.
EventLoop(const char* exe_name, LogFn log_fn, void* context = nullptr);
//! Construct event loop object with default logging options.
EventLoop(const char* exe_name, LogFn log_fn, void* context = nullptr)
: EventLoop(exe_name, LogOptions{std::move(log_fn)}, context){}
//! Construct event loop object with specified logging options.
EventLoop(const char* exe_name, LogOptions log_opts, void* context = nullptr);
//! Backwards-compatible constructor for previous (deprecated) logging callback signature
EventLoop(const char* exe_name, std::function<void(bool, std::string)> old_callback, void* context = nullptr)
: EventLoop(exe_name,
LogFn{[old_callback = std::move(old_callback)](LogMessage log_data) {old_callback(log_data.level == Log::Raise, std::move(log_data.message));}},
context){}
~EventLoop();
//! Run event loop. Does not return until shutdown. This should only be
@@ -212,15 +266,6 @@ public:
//! Check if loop should exit.
bool done() const MP_REQUIRES(m_mutex);
Logger log()
{
Logger logger(false, m_log_opts.log_fn);
logger << "{" << LongThreadName(m_exe_name) << "} ";
return logger;
}
Logger logPlain() { return {false, m_log_opts.log_fn}; }
Logger raise() { return {true, m_log_opts.log_fn}; }
//! Process name included in thread names so combined debug output from
//! multiple processes is easier to understand.
const char* m_exe_name;
@@ -283,18 +328,19 @@ struct Waiter
Waiter() = default;
template <typename Fn>
void post(Fn&& fn)
bool post(Fn&& fn)
{
const std::unique_lock<std::mutex> lock(m_mutex);
assert(!m_fn);
const Lock lock(m_mutex);
if (m_fn) return false;
m_fn = std::forward<Fn>(fn);
m_cv.notify_all();
return true;
}
template <class Predicate>
void wait(std::unique_lock<std::mutex>& lock, Predicate pred)
void wait(Lock& lock, Predicate pred)
{
m_cv.wait(lock, [&] {
m_cv.wait(lock.m_lock, [&]() MP_REQUIRES(m_mutex) {
// Important for this to be "while (m_fn)", not "if (m_fn)" to avoid
// a lost-wakeup bug. A new m_fn and m_cv notification might be sent
// after the fn() call and before the lock.lock() call in this loop
@@ -317,9 +363,9 @@ struct Waiter
//! mutexes than necessary. This mutex can be held at the same time as
//! EventLoop::m_mutex as long as Waiter::mutex is locked first and
//! EventLoop::m_mutex is locked second.
std::mutex m_mutex;
Mutex m_mutex;
std::condition_variable m_cv;
std::optional<kj::Function<void()>> m_fn;
std::optional<kj::Function<void()>> m_fn MP_GUARDED_BY(m_mutex);
};
//! Object holding network & rpc state associated with either an incoming server
@@ -544,29 +590,73 @@ void ProxyServerBase<Interface, Impl>::invokeDestroy()
CleanupRun(m_context.cleanup_fns);
}
using ConnThreads = std::map<Connection*, ProxyClient<Thread>>;
//! Map from Connection to local or remote thread handle which will be used over
//! that connection. This map will typically only contain one entry, but can
//! contain multiple if a single thread makes IPC calls over multiple
//! connections. A std::optional value type is used to avoid the map needing to
//! be locked while ProxyClient<Thread> objects are constructed, see
//! ThreadContext "Synchronization note" below.
using ConnThreads = std::map<Connection*, std::optional<ProxyClient<Thread>>>;
using ConnThread = ConnThreads::iterator;
// Retrieve ProxyClient<Thread> object associated with this connection from a
// map, or create a new one and insert it into the map. Return map iterator and
// inserted bool.
std::tuple<ConnThread, bool> SetThread(ConnThreads& threads, std::mutex& mutex, Connection* connection, const std::function<Thread::Client()>& make_thread);
std::tuple<ConnThread, bool> SetThread(GuardedRef<ConnThreads> threads, Connection* connection, const std::function<Thread::Client()>& make_thread);
//! The thread_local ThreadContext g_thread_context struct provides information
//! about individual threads and a way of communicating between them. Because
//! it's a thread local struct, each ThreadContext instance is initialized by
//! the thread that owns it.
//!
//! ThreadContext is used for any client threads created externally which make
//! IPC calls, and for server threads created by
//! ProxyServer<ThreadMap>::makeThread() which execute IPC calls for clients.
//!
//! In both cases, the struct holds information like the thread name, and a
//! Waiter object where the EventLoop can post incoming IPC requests to execute
//! on the thread. The struct also holds ConnThread maps associating the thread
//! with local and remote ProxyClient<Thread> objects.
struct ThreadContext
{
//! Identifying string for debug.
std::string thread_name;
//! Waiter object used to allow client threads blocked waiting for a server
//! response to execute callbacks made from the client's corresponding
//! server thread.
//! Waiter object used to allow remote clients to execute code on this
//! thread. For server threads created by
//! ProxyServer<ThreadMap>::makeThread(), this is initialized in that
//! function. Otherwise, for client threads created externally, this is
//! initialized the first time the thread tries to make an IPC call. Having
//! a waiter is necessary for threads making IPC calls in case a server they
//! are calling expects them to execute a callback during the call, before
//! it sends a response.
//!
//! For IPC client threads, the Waiter pointer is never cleared and the Waiter
//! just gets destroyed when the thread does. For server threads created by
//! makeThread(), this pointer is set to null in the ~ProxyServer<Thread> as
//! a signal for the thread to exit and destroy itself. In both cases, the
//! same Waiter object is used across different calls and only created and
//! destroyed once for the lifetime of the thread.
std::unique_ptr<Waiter> waiter = nullptr;
//! When client is making a request to a server, this is the
//! `callbackThread` argument it passes in the request, used by the server
//! in case it needs to make callbacks into the client that need to execute
//! while the client is waiting. This will be set to a local thread object.
ConnThreads callback_threads;
//!
//! Synchronization note: The callback_thread and request_thread maps are
//! only ever accessed internally by this thread's destructor and externally
//! by Cap'n Proto event loop threads. Since it's possible for IPC client
//! threads to make calls over different connections that could have
//! different event loops, these maps are guarded by Waiter::m_mutex in case
//! different event loop threads add or remove map entries simultaneously.
//! However, individual ProxyClient<Thread> objects in the maps will only be
//! associated with one event loop and guarded by EventLoop::m_mutex. So
//! Waiter::m_mutex does not need to be held while accessing individual
//! ProxyClient<Thread> instances, and may even need to be released to
//! respect lock order and avoid locking Waiter::m_mutex before
//! EventLoop::m_mutex.
ConnThreads callback_threads MP_GUARDED_BY(waiter->m_mutex);
//! When client is making a request to a server, this is the `thread`
//! argument it passes in the request, used to control which thread on
@@ -575,7 +665,9 @@ struct ThreadContext
//! by makeThread. If a client call is being made from a thread currently
//! handling a server request, this will be set to the `callbackThread`
//! request thread argument passed in that request.
ConnThreads request_threads;
//!
//! Synchronization note: \ref callback_threads note applies here as well.
ConnThreads request_threads MP_GUARDED_BY(waiter->m_mutex);
//! Whether this thread is a capnp event loop thread. Not really used except
//! to assert false if there's an attempt to execute a blocking operation
@@ -598,7 +690,7 @@ std::unique_ptr<ProxyClient<InitInterface>> ConnectStream(EventLoop& loop, int f
init_client = connection->m_rpc_system->bootstrap(ServerVatId().vat_id).castAs<InitInterface>();
Connection* connection_ptr = connection.get();
connection->onDisconnect([&loop, connection_ptr] {
loop.log() << "IPC client: unexpected network disconnect.";
MP_LOG(loop, Log::Warning) << "IPC client: unexpected network disconnect.";
delete connection_ptr;
});
});
@@ -621,7 +713,7 @@ void _Serve(EventLoop& loop, kj::Own<kj::AsyncIoStream>&& stream, InitImpl& init
});
auto it = loop.m_incoming_connections.begin();
it->onDisconnect([&loop, it] {
loop.log() << "IPC server: socket disconnected.";
MP_LOG(loop, Log::Info) << "IPC server: socket disconnected.";
loop.m_incoming_connections.erase(it);
});
}

View File

@@ -568,7 +568,7 @@ template <typename Client>
void clientDestroy(Client& client)
{
if (client.m_context.connection) {
client.m_context.loop->log() << "IPC client destroy " << typeid(client).name();
MP_LOG(*client.m_context.loop, Log::Info) << "IPC client destroy " << typeid(client).name();
} else {
KJ_LOG(INFO, "IPC interrupted client destroy", typeid(client).name());
}
@@ -577,7 +577,7 @@ void clientDestroy(Client& client)
template <typename Server>
void serverDestroy(Server& server)
{
server.m_context.loop->log() << "IPC server destroy " << typeid(server).name();
MP_LOG(*server.m_context.loop, Log::Info) << "IPC server destroy " << typeid(server).name();
}
//! Entry point called by generated client code that looks like:
@@ -605,7 +605,7 @@ void clientInvoke(ProxyClient& proxy_client, const GetRequest& get_request, Fiel
// declaration so the server method runs in a dedicated thread.
assert(!g_thread_context.loop_thread);
g_thread_context.waiter = std::make_unique<Waiter>();
proxy_client.m_context.loop->logPlain()
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Info)
<< "{" << g_thread_context.thread_name
<< "} IPC client first request from current thread, constructing waiter";
}
@@ -617,7 +617,7 @@ void clientInvoke(ProxyClient& proxy_client, const GetRequest& get_request, Fiel
const char* disconnected = nullptr;
proxy_client.m_context.loop->sync([&]() {
if (!proxy_client.m_context.connection) {
const std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
const Lock lock(thread_context.waiter->m_mutex);
done = true;
disconnected = "IPC client method called after disconnect.";
thread_context.waiter->m_cv.notify_all();
@@ -629,22 +629,26 @@ void clientInvoke(ProxyClient& proxy_client, const GetRequest& get_request, Fiel
using FieldList = typename ProxyClientMethodTraits<typename Request::Params>::Fields;
invoke_context.emplace(*proxy_client.m_context.connection, thread_context);
IterateFields().handleChain(*invoke_context, request, FieldList(), typename FieldObjs::BuildParams{&fields}...);
proxy_client.m_context.loop->logPlain()
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Debug)
<< "{" << thread_context.thread_name << "} IPC client send "
<< TypeName<typename Request::Params>() << " " << LogEscape(request.toString(), proxy_client.m_context.loop->m_log_opts.max_chars);
<< TypeName<typename Request::Params>();
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Trace)
<< "send data: " << LogEscape(request.toString(), proxy_client.m_context.loop->m_log_opts.max_chars);
proxy_client.m_context.loop->m_task_set->add(request.send().then(
[&](::capnp::Response<typename Request::Results>&& response) {
proxy_client.m_context.loop->logPlain()
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Debug)
<< "{" << thread_context.thread_name << "} IPC client recv "
<< TypeName<typename Request::Results>() << " " << LogEscape(response.toString(), proxy_client.m_context.loop->m_log_opts.max_chars);
<< TypeName<typename Request::Results>();
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Trace)
<< "recv data: " << LogEscape(response.toString(), proxy_client.m_context.loop->m_log_opts.max_chars);
try {
IterateFields().handleChain(
*invoke_context, response, FieldList(), typename FieldObjs::ReadResults{&fields}...);
} catch (...) {
exception = std::current_exception();
}
const std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
const Lock lock(thread_context.waiter->m_mutex);
done = true;
thread_context.waiter->m_cv.notify_all();
},
@@ -653,20 +657,20 @@ void clientInvoke(ProxyClient& proxy_client, const GetRequest& get_request, Fiel
disconnected = "IPC client method call interrupted by disconnect.";
} else {
kj_exception = kj::str("kj::Exception: ", e).cStr();
proxy_client.m_context.loop->logPlain()
MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Info)
<< "{" << thread_context.thread_name << "} IPC client exception " << kj_exception;
}
const std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
const Lock lock(thread_context.waiter->m_mutex);
done = true;
thread_context.waiter->m_cv.notify_all();
}));
});
std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
Lock lock(thread_context.waiter->m_mutex);
thread_context.waiter->wait(lock, [&done]() { return done; });
if (exception) std::rethrow_exception(exception);
if (!kj_exception.empty()) proxy_client.m_context.loop->raise() << kj_exception;
if (disconnected) proxy_client.m_context.loop->raise() << disconnected;
if (!kj_exception.empty()) MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Raise) << kj_exception;
if (disconnected) MP_LOGPLAIN(*proxy_client.m_context.loop, Log::Raise) << disconnected;
}
//! Invoke callable `fn()` that may return void. If it does return void, replace
@@ -700,8 +704,10 @@ kj::Promise<void> serverInvoke(Server& server, CallContext& call_context, Fn fn)
using Results = typename decltype(call_context.getResults())::Builds;
int req = ++server_reqs;
server.m_context.loop->log() << "IPC server recv request #" << req << " "
<< TypeName<typename Params::Reads>() << " " << LogEscape(params.toString(), server.m_context.loop->m_log_opts.max_chars);
MP_LOG(*server.m_context.loop, Log::Debug) << "IPC server recv request #" << req << " "
<< TypeName<typename Params::Reads>();
MP_LOG(*server.m_context.loop, Log::Trace) << "request data: "
<< LogEscape(params.toString(), server.m_context.loop->m_log_opts.max_chars);
try {
using ServerContext = ServerInvokeContext<Server, CallContext>;
@@ -717,14 +723,15 @@ kj::Promise<void> serverInvoke(Server& server, CallContext& call_context, Fn fn)
return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[&]() { return kj::Promise<CallContext>(kj::mv(call_context)); })
.then([&server, req](CallContext call_context) {
server.m_context.loop->log() << "IPC server send response #" << req << " " << TypeName<Results>()
<< " " << LogEscape(call_context.getResults().toString(), server.m_context.loop->m_log_opts.max_chars);
MP_LOG(*server.m_context.loop, Log::Debug) << "IPC server send response #" << req << " " << TypeName<Results>();
MP_LOG(*server.m_context.loop, Log::Trace) << "response data: "
<< LogEscape(call_context.getResults().toString(), server.m_context.loop->m_log_opts.max_chars);
});
} catch (const std::exception& e) {
server.m_context.loop->log() << "IPC server unhandled exception: " << e.what();
MP_LOG(*server.m_context.loop, Log::Error) << "IPC server unhandled exception: " << e.what();
throw;
} catch (...) {
server.m_context.loop->log() << "IPC server unhandled exception";
MP_LOG(*server.m_context.loop, Log::Error) << "IPC server unhandled exception";
throw;
}
}

View File

@@ -25,7 +25,7 @@ void CustomBuildField(TypeList<>,
// Also store the Thread::Client reference in the callback_threads map so
// future calls over this connection can reuse it.
auto [callback_thread, _]{SetThread(
thread_context.callback_threads, thread_context.waiter->m_mutex, &connection,
GuardedRef{thread_context.waiter->m_mutex, thread_context.callback_threads}, &connection,
[&] { return connection.m_threads.add(kj::heap<ProxyServer<Thread>>(thread_context, std::thread{})); })};
// Call remote ThreadMap.makeThread function so server will create a
@@ -43,12 +43,12 @@ void CustomBuildField(TypeList<>,
return request.send().getResult(); // Nonblocking due to capnp request pipelining.
}};
auto [request_thread, _1]{SetThread(
thread_context.request_threads, thread_context.waiter->m_mutex,
GuardedRef{thread_context.waiter->m_mutex, thread_context.request_threads},
&connection, make_request_thread)};
auto context = output.init();
context.setThread(request_thread->second.m_client);
context.setCallbackThread(callback_thread->second.m_client);
context.setThread(request_thread->second->m_client);
context.setCallbackThread(callback_thread->second->m_client);
}
//! PassField override for mp.Context arguments. Return asynchronously and call
@@ -89,29 +89,39 @@ auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn&
// need to update the map.
auto& thread_context = g_thread_context;
auto& request_threads = thread_context.request_threads;
auto [request_thread, inserted]{SetThread(
request_threads, thread_context.waiter->m_mutex,
server.m_context.connection,
[&] { return context_arg.getCallbackThread(); })};
ConnThread request_thread;
bool inserted;
server.m_context.loop->sync([&] {
std::tie(request_thread, inserted) = SetThread(
GuardedRef{thread_context.waiter->m_mutex, request_threads}, server.m_context.connection,
[&] { return context_arg.getCallbackThread(); });
});
// If an entry was inserted into the requests_threads map,
// If an entry was inserted into the request_threads map,
// remove it after calling fn.invoke. If an entry was not
// inserted, one already existed, meaning this must be a
// recursive call (IPC call calling back to the caller which
// makes another IPC call), so avoid modifying the map.
const bool erase_thread{inserted};
KJ_DEFER(if (erase_thread) {
std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
// Call erase here with a Connection* argument instead
// of an iterator argument, because the `request_thread`
// iterator may be invalid if the connection is closed
// during this function call. More specifically, the
// iterator may be invalid because SetThread adds a
// cleanup callback to the Connection destructor that
// erases the thread from the map, and also because the
// ProxyServer<Thread> destructor calls
// request_threads.clear().
request_threads.erase(server.m_context.connection);
// Erase the request_threads entry on the event loop
// thread with loop->sync(), so if the connection is
// broken there is not a race between this thread and
// the disconnect handler trying to destroy the thread
// client object.
server.m_context.loop->sync([&] {
// Look up the thread again without using existing
// iterator since entry may no longer be there after
// a disconnect. Destroy node after releasing
// Waiter::m_mutex, so the ProxyClient<Thread>
// destructor is able to use EventLoop::mutex
// without violating lock order.
ConnThreads::node_type removed;
{
Lock lock(thread_context.waiter->m_mutex);
removed = request_threads.extract(server.m_context.connection);
}
});
});
fn.invoke(server_context, args...);
}
@@ -140,11 +150,16 @@ auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn&
// thread.
KJ_IF_MAYBE (thread_server, perhaps) {
const auto& thread = static_cast<ProxyServer<Thread>&>(*thread_server);
server.m_context.loop->log()
MP_LOG(*server.m_context.loop, Log::Debug)
<< "IPC server post request #" << req << " {" << thread.m_thread_context.thread_name << "}";
thread.m_thread_context.waiter->post(std::move(invoke));
if (!thread.m_thread_context.waiter->post(std::move(invoke))) {
MP_LOG(*server.m_context.loop, Log::Error)
<< "IPC server error request #" << req
<< " {" << thread.m_thread_context.thread_name << "}" << ", thread busy";
throw std::runtime_error("thread busy");
}
} else {
server.m_context.loop->log()
MP_LOG(*server.m_context.loop, Log::Error)
<< "IPC server error request #" << req << ", missing thread to execute request";
throw std::runtime_error("invalid thread handle");
}

View File

@@ -182,6 +182,17 @@ public:
std::unique_lock<std::mutex> m_lock;
};
template<typename T>
struct GuardedRef
{
Mutex& mutex;
T& ref MP_GUARDED_BY(mutex);
};
// CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>
template <class U>
GuardedRef(Mutex&, U&) -> GuardedRef<U>;
//! Analog to std::lock_guard that unlocks instead of locks.
template <typename Lock>
struct UnlockGuard

View File

@@ -3,11 +3,19 @@
, enableLibcxx ? false # Whether to use libc++ toolchain and libraries instead of libstdc++
, minimal ? false # Whether to create minimal shell without extra tools (faster when cross compiling)
, capnprotoVersion ? null
, capnprotoSanitizers ? null # Optional sanitizers to build cap'n proto with
, cmakeVersion ? null
, libcxxSanitizers ? null # Optional LLVM_USE_SANITIZER value to use for libc++, see https://llvm.org/docs/CMake.html
}:
let
lib = pkgs.lib;
llvm = crossPkgs.llvmPackages_20;
llvmBase = crossPkgs.llvmPackages_21;
llvm = llvmBase // lib.optionalAttrs (libcxxSanitizers != null) {
libcxx = llvmBase.libcxx.override {
devExtraCmakeFlags = [ "-DLLVM_USE_SANITIZER=${libcxxSanitizers}" ];
};
};
capnprotoHashes = {
"0.7.0" = "sha256-Y/7dUOQPDHjniuKNRw3j8dG1NI9f/aRWpf8V0WzV9k8=";
"0.7.1" = "sha256-3cBpVmpvCXyqPUXDp12vCFCk32ZXWpkdOliNH37UwWE=";
@@ -34,15 +42,36 @@ let
} // (lib.optionalAttrs (lib.versionOlder capnprotoVersion "0.10") {
env = { }; # Drop -std=c++20 flag forced by nixpkgs
}));
capnproto = capnprotoBase.override (lib.optionalAttrs enableLibcxx { clangStdenv = llvm.libcxxStdenv; });
capnproto = (capnprotoBase.overrideAttrs (old: lib.optionalAttrs (capnprotoSanitizers != null) {
env = (old.env or { }) // {
CXXFLAGS =
lib.concatStringsSep " " [
(old.env.CXXFLAGS or "")
"-fsanitize=${capnprotoSanitizers}"
"-fno-omit-frame-pointer"
"-g"
];
};
})).override (lib.optionalAttrs enableLibcxx { clangStdenv = llvm.libcxxStdenv; });
clang = if enableLibcxx then llvm.libcxxClang else llvm.clang;
clang-tools = llvm.clang-tools.override { inherit enableLibcxx; };
cmakeHashes = {
"3.12.4" = "sha256-UlVYS/0EPrcXViz/iULUcvHA5GecSUHYS6raqbKOMZQ=";
};
cmakeBuild = if cmakeVersion == null then pkgs.cmake else (pkgs.cmake.overrideAttrs (old: {
version = cmakeVersion;
src = pkgs.fetchurl {
url = "https://cmake.org/files/v${lib.versions.majorMinor cmakeVersion}/cmake-${cmakeVersion}.tar.gz";
hash = lib.attrByPath [cmakeVersion] "" cmakeHashes;
};
patches = [];
})).override { isMinimalBuild = true; };
in crossPkgs.mkShell {
buildInputs = [
capnproto
];
nativeBuildInputs = with pkgs; [
cmake
cmakeBuild
include-what-you-use
ninja
] ++ lib.optionals (!minimal) [

View File

@@ -12,6 +12,7 @@
#include <atomic>
#include <capnp/capability.h>
#include <capnp/common.h> // IWYU pragma: keep
#include <capnp/rpc.h>
#include <condition_variable>
#include <functional>
@@ -23,9 +24,9 @@
#include <kj/debug.h>
#include <kj/function.h>
#include <kj/memory.h>
#include <kj/string.h>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <stdexcept>
#include <string>
@@ -42,7 +43,7 @@ thread_local ThreadContext g_thread_context;
void LoggingErrorHandler::taskFailed(kj::Exception&& exception)
{
KJ_LOG(ERROR, "Uncaught exception in daemonized task.", exception);
m_loop.log() << "Uncaught exception in daemonized task.";
MP_LOG(m_loop, Log::Error) << "Uncaught exception in daemonized task.";
}
EventLoopRef::EventLoopRef(EventLoop& loop, Lock* lock) : m_loop(&loop), m_lock(lock)
@@ -81,6 +82,11 @@ ProxyContext::ProxyContext(Connection* connection) : connection(connection), loo
Connection::~Connection()
{
// Connection destructor is always called on the event loop thread. If this
// is a local disconnect, it will trigger I/O, so this needs to run on the
// event loop thread, and if there was a remote disconnect, this is called
// by an onDisconnect callback directly from the event loop thread.
assert(std::this_thread::get_id() == m_loop->m_thread_id);
// Shut down RPC system first, since this will garbage collect any
// ProxyServer objects that were not freed before the connection was closed.
// Typically all ProxyServer objects associated with this connection will be
@@ -156,6 +162,9 @@ CleanupIt Connection::addSyncCleanup(std::function<void()> fn)
void Connection::removeSyncCleanup(CleanupIt it)
{
// Require cleanup functions to be removed on the event loop thread to avoid
// needing to deal with them being removed in the middle of a disconnect.
assert(std::this_thread::get_id() == m_loop->m_thread_id);
const Lock lock(m_loop->m_mutex);
m_sync_cleanup_fns.erase(it);
}
@@ -183,13 +192,13 @@ void EventLoop::addAsyncCleanup(std::function<void()> fn)
startAsyncThread();
}
EventLoop::EventLoop(const char* exe_name, LogFn log_fn, void* context)
EventLoop::EventLoop(const char* exe_name, LogOptions log_opts, void* context)
: m_exe_name(exe_name),
m_io_context(kj::setupAsyncIo()),
m_task_set(new kj::TaskSet(m_error_handler)),
m_log_opts(std::move(log_opts)),
m_context(context)
{
m_log_opts.log_fn = log_fn;
int fds[2];
KJ_SYSCALL(socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
m_wait_fd = fds[0];
@@ -243,9 +252,9 @@ void EventLoop::loop()
break;
}
}
log() << "EventLoop::loop done, cancelling event listeners.";
MP_LOG(*this, Log::Info) << "EventLoop::loop done, cancelling event listeners.";
m_task_set.reset();
log() << "EventLoop::loop bye.";
MP_LOG(*this, Log::Info) << "EventLoop::loop bye.";
wait_stream = nullptr;
KJ_SYSCALL(::close(post_fd));
const Lock lock(m_mutex);
@@ -305,29 +314,34 @@ bool EventLoop::done() const
return m_num_clients == 0 && m_async_fns->empty();
}
std::tuple<ConnThread, bool> SetThread(ConnThreads& threads, std::mutex& mutex, Connection* connection, const std::function<Thread::Client()>& make_thread)
std::tuple<ConnThread, bool> SetThread(GuardedRef<ConnThreads> threads, Connection* connection, const std::function<Thread::Client()>& make_thread)
{
const std::unique_lock<std::mutex> lock(mutex);
auto thread = threads.find(connection);
if (thread != threads.end()) return {thread, false};
thread = threads.emplace(
std::piecewise_construct, std::forward_as_tuple(connection),
std::forward_as_tuple(make_thread(), connection, /* destroy_connection= */ false)).first;
thread->second.setDisconnectCallback([&threads, &mutex, thread] {
// Note: it is safe to use the `thread` iterator in this cleanup
// function, because the iterator would only be invalid if the map entry
// was removed, and if the map entry is removed the ProxyClient<Thread>
// destructor unregisters the cleanup.
assert(std::this_thread::get_id() == connection->m_loop->m_thread_id);
ConnThread thread;
bool inserted;
{
const Lock lock(threads.mutex);
std::tie(thread, inserted) = threads.ref.try_emplace(connection);
}
if (inserted) {
thread->second.emplace(make_thread(), connection, /* destroy_connection= */ false);
thread->second->m_disconnect_cb = connection->addSyncCleanup([threads, thread] {
// Note: it is safe to use the `thread` iterator in this cleanup
// function, because the iterator would only be invalid if the map entry
// was removed, and if the map entry is removed the ProxyClient<Thread>
// destructor unregisters the cleanup.
// Connection is being destroyed before thread client is, so reset
// thread client m_disconnect_cb member so thread client destructor does not
// try to unregister this callback after connection is destroyed.
// Remove connection pointer about to be destroyed from the map
const std::unique_lock<std::mutex> lock(mutex);
thread->second.m_disconnect_cb.reset();
threads.erase(thread);
});
return {thread, true};
// Connection is being destroyed before thread client is, so reset
// thread client m_disconnect_cb member so thread client destructor does not
// try to unregister this callback after connection is destroyed.
thread->second->m_disconnect_cb.reset();
// Remove connection pointer about to be destroyed from the map
const Lock lock(threads.mutex);
threads.ref.erase(thread);
});
}
return {thread, inserted};
}
ProxyClient<Thread>::~ProxyClient()
@@ -336,17 +350,18 @@ ProxyClient<Thread>::~ProxyClient()
// cleanup callback that was registered to handle the connection being
// destroyed before the thread being destroyed.
if (m_disconnect_cb) {
m_context.connection->removeSyncCleanup(*m_disconnect_cb);
// Remove disconnect callback on the event loop thread with
// loop->sync(), so if the connection is broken there is not a race
// between this thread trying to remove the callback and the disconnect
// handler attempting to call it.
m_context.loop->sync([&]() {
if (m_disconnect_cb) {
m_context.connection->removeSyncCleanup(*m_disconnect_cb);
}
});
}
}
void ProxyClient<Thread>::setDisconnectCallback(const std::function<void()>& fn)
{
assert(fn);
assert(!m_disconnect_cb);
m_disconnect_cb = m_context.connection->addSyncCleanup(fn);
}
ProxyServer<Thread>::ProxyServer(ThreadContext& thread_context, std::thread&& thread)
: m_thread_context(thread_context), m_thread(std::move(thread))
{
@@ -364,7 +379,7 @@ ProxyServer<Thread>::~ProxyServer()
assert(m_thread_context.waiter.get());
std::unique_ptr<Waiter> waiter;
{
const std::unique_lock<std::mutex> lock(m_thread_context.waiter->m_mutex);
const Lock lock(m_thread_context.waiter->m_mutex);
//! Reset thread context waiter pointer, as shutdown signal for done
//! lambda passed as waiter->wait() argument in makeThread code below.
waiter = std::move(m_thread_context.waiter);
@@ -398,7 +413,7 @@ kj::Promise<void> ProxyServer<ThreadMap>::makeThread(MakeThreadContext context)
g_thread_context.thread_name = ThreadName(m_connection.m_loop->m_exe_name) + " (from " + from + ")";
g_thread_context.waiter = std::make_unique<Waiter>();
thread_context.set_value(&g_thread_context);
std::unique_lock<std::mutex> lock(g_thread_context.waiter->m_mutex);
Lock lock(g_thread_context.waiter->m_mutex);
// Wait for shutdown signal from ProxyServer<Thread> destructor (signal
// is just waiter getting set to null.)
g_thread_context.waiter->wait(lock, [] { return !g_thread_context.waiter; });
@@ -416,4 +431,16 @@ std::string LongThreadName(const char* exe_name)
return g_thread_context.thread_name.empty() ? ThreadName(exe_name) : g_thread_context.thread_name;
}
kj::StringPtr KJ_STRINGIFY(Log v)
{
switch (v) {
case Log::Trace: return "Trace";
case Log::Debug: return "Debug";
case Log::Info: return "Info";
case Log::Warning: return "Warning";
case Log::Error: return "Error";
case Log::Raise: return "Raise";
}
return "<Log?>";
}
} // namespace mp

View File

@@ -7,6 +7,8 @@
#include <cerrno>
#include <cstdio>
#include <filesystem>
#include <iostream>
#include <kj/common.h>
#include <kj/string-tree.h>
#include <pthread.h>
@@ -29,6 +31,8 @@
#include <pthread_np.h>
#endif // HAVE_PTHREAD_GETTHREADID_NP
namespace fs = std::filesystem;
namespace mp {
namespace {
@@ -138,6 +142,9 @@ void ExecProcess(const std::vector<std::string>& args)
argv.push_back(nullptr);
if (execvp(argv[0], argv.data()) != 0) {
perror("execvp failed");
if (errno == ENOENT && !args.empty()) {
std::cerr << "Missing executable: " << fs::weakly_canonical(args.front()) << '\n';
}
_exit(1);
}
}

View File

@@ -13,6 +13,8 @@ $Proxy.includeTypes("mp/test/foo-types.h");
interface FooInterface $Proxy.wrap("mp::test::FooImplementation") {
add @0 (a :Int32, b :Int32) -> (result :Int32);
addOut @19 (a :Int32, b :Int32) -> (ret :Int32);
addInOut @20 (x :Int32, sum :Int32) -> (sum :Int32);
mapSize @1 (map :List(Pair(Text, Text))) -> (result :Int32);
pass @2 (arg :FooStruct) -> (result :FooStruct);
raise @3 (arg :FooStruct) -> (error :FooStruct $Proxy.exception("mp::test::FooStruct"));

View File

@@ -62,6 +62,8 @@ class FooImplementation
{
public:
int add(int a, int b) { return a + b; }
void addOut(int a, int b, int& out) { out = a + b; }
void addInOut(int x, int& sum) { sum += x; }
int mapSize(const std::map<std::string, std::string>& map) { return map.size(); }
FooStruct pass(FooStruct foo) { return foo; }
void raise(FooStruct foo) { throw foo; }

View File

@@ -5,26 +5,32 @@
#include <mp/test/foo.capnp.h>
#include <mp/test/foo.capnp.proxy.h>
#include <atomic>
#include <capnp/capability.h>
#include <capnp/rpc.h>
#include <condition_variable>
#include <cstring>
#include <functional>
#include <future>
#include <iostream>
#include <kj/async.h>
#include <kj/async-io.h>
#include <kj/common.h>
#include <kj/debug.h>
#include <kj/exception.h>
#include <kj/memory.h>
#include <kj/string.h>
#include <kj/test.h>
#include <memory>
#include <mp/proxy.h>
#include <mp/proxy.capnp.h>
#include <mp/proxy-io.h>
#include <mp/util.h>
#include <optional>
#include <set>
#include <stdexcept>
#include <string>
#include <string_view>
#include <system_error>
#include <thread>
#include <utility>
#include <vector>
@@ -60,9 +66,10 @@ public:
TestSetup(bool client_owns_connection = true)
: thread{[&] {
EventLoop loop("mptest", [](bool raise, const std::string& log) {
std::cout << "LOG" << raise << ": " << log << "\n";
if (raise) throw std::runtime_error(log);
EventLoop loop("mptest", [](mp::LogMessage log) {
// Info logs are not printed by default, but will be shown with `mptest --verbose`
KJ_LOG(INFO, log.level, log.message);
if (log.level == mp::Log::Raise) throw std::runtime_error(log.message);
});
auto pipe = loop.m_io_context.provider->newTwoWayPipe();
@@ -113,6 +120,11 @@ KJ_TEST("Call FooInterface methods")
ProxyClient<messages::FooInterface>* foo = setup.client.get();
KJ_EXPECT(foo->add(1, 2) == 3);
int ret;
foo->addOut(3, 4, ret);
KJ_EXPECT(ret == 7);
foo->addInOut(3, ret);
KJ_EXPECT(ret == 10);
FooStruct in;
in.name = "name";
@@ -297,5 +309,71 @@ KJ_TEST("Calling IPC method, disconnecting and blocking during the call")
signal.set_value();
}
KJ_TEST("Make simultaneous IPC calls to trigger 'thread busy' error")
{
TestSetup setup;
ProxyClient<messages::FooInterface>* foo = setup.client.get();
std::promise<void> signal;
foo->initThreadMap();
// Use callFnAsync() to get the client to set up the request_thread
// that will be used for the test.
setup.server->m_impl->m_fn = [&] {};
foo->callFnAsync();
ThreadContext& tc{g_thread_context};
Thread::Client *callback_thread, *request_thread;
foo->m_context.loop->sync([&] {
Lock lock(tc.waiter->m_mutex);
callback_thread = &tc.callback_threads.at(foo->m_context.connection)->m_client;
request_thread = &tc.request_threads.at(foo->m_context.connection)->m_client;
});
setup.server->m_impl->m_fn = [&] {
try
{
signal.get_future().get();
}
catch (const std::future_error& e)
{
KJ_EXPECT(e.code() == std::make_error_code(std::future_errc::future_already_retrieved));
}
};
auto client{foo->m_client};
bool caught_thread_busy = false;
// NOTE: '3' was chosen because it was the lowest number
// of simultaneous calls required to reliably catch a "thread busy" error
std::atomic<size_t> running{3};
foo->m_context.loop->sync([&]
{
for (size_t i = 0; i < running; i++)
{
auto request{client.callFnAsyncRequest()};
auto context{request.initContext()};
context.setCallbackThread(*callback_thread);
context.setThread(*request_thread);
foo->m_context.loop->m_task_set->add(request.send().then(
[&](auto&& results) {
running -= 1;
tc.waiter->m_cv.notify_all();
},
[&](kj::Exception&& e) {
KJ_EXPECT(std::string_view{e.getDescription().cStr()} ==
"remote exception: std::exception: thread busy");
caught_thread_busy = true;
running -= 1;
signal.set_value();
tc.waiter->m_cv.notify_all();
}
));
}
});
{
Lock lock(tc.waiter->m_mutex);
tc.waiter->wait(lock, [&running] { return running == 0; });
}
KJ_EXPECT(caught_thread_busy);
}
} // namespace test
} // namespace mp

View File

@@ -147,7 +147,6 @@ public:
// release ASAP to avoid it where possible.
vSeeds.emplace_back("seed.bitcoin.sipa.be."); // Pieter Wuille, only supports x1, x5, x9, and xd
vSeeds.emplace_back("dnsseed.bluematt.me."); // Matt Corallo, only supports x9
vSeeds.emplace_back("dnsseed.bitcoin.dashjr-list-of-p2p-nodes.us."); // Luke Dashjr
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch."); // Jonas Schnelli, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.btc.petertodd.net."); // Peter Todd, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.bitcoin.sprovoost.nl."); // Sjors Provoost

View File

@@ -574,9 +574,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);
}
}
@@ -1768,7 +1768,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);
@@ -1823,7 +1827,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

@@ -1377,7 +1377,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

@@ -167,7 +167,7 @@ static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL{5s};
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
/** Maximum rate of inventory items to send per second.
* Limits the impact of low-fee transaction floods. */
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7;
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND{14};
/** Target number of tx inventory items to send per transmission. */
static constexpr unsigned int INVENTORY_BROADCAST_TARGET = INVENTORY_BROADCAST_PER_SECOND * count_seconds(INBOUND_INVENTORY_BROADCAST_INTERVAL);
/** Maximum number of inventory items to send per transmission. */

View File

@@ -5,9 +5,12 @@
#include <node/caches.h>
#include <common/args.h>
#include <common/system.h>
#include <index/txindex.h>
#include <kernel/caches.h>
#include <logging.h>
#include <node/interface_ui.h>
#include <tinyformat.h>
#include <util/byte_units.h>
#include <algorithm>
@@ -23,16 +26,20 @@ static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};
static constexpr size_t MAX_32BIT_DBCACHE{1024_MiB};
namespace node {
size_t CalculateDbCacheBytes(const ArgsManager& args)
{
if (auto db_cache{args.GetIntArg("-dbcache")}) {
if (*db_cache < 0) db_cache = 0;
const uint64_t db_cache_bytes{SaturatingLeftShift<uint64_t>(*db_cache, 20)};
constexpr auto max_db_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : std::numeric_limits<size_t>::max()};
return std::max<size_t>(MIN_DB_CACHE, std::min<uint64_t>(db_cache_bytes, max_db_cache));
}
return DEFAULT_DB_CACHE;
}
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
{
// Convert -dbcache from MiB units to bytes. The total cache is floored by MIN_DB_CACHE and capped by max size_t value.
size_t total_cache{DEFAULT_DB_CACHE};
if (std::optional<int64_t> db_cache = args.GetIntArg("-dbcache")) {
if (*db_cache < 0) db_cache = 0;
uint64_t db_cache_bytes = SaturatingLeftShift<uint64_t>(*db_cache, 20);
constexpr auto max_db_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : std::numeric_limits<size_t>::max()};
total_cache = std::max<size_t>(MIN_DB_CACHE, std::min<uint64_t>(db_cache_bytes, max_db_cache));
}
size_t total_cache{CalculateDbCacheBytes(args)};
IndexCacheSizes index_sizes;
index_sizes.tx_index = std::min(total_cache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE : 0);
@@ -44,4 +51,15 @@ CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
}
return {index_sizes, kernel::CacheSizes{total_cache}};
}
void LogOversizedDbCache(const ArgsManager& args) noexcept
{
if (const auto total_ram{GetTotalRAM()}) {
const size_t db_cache{CalculateDbCacheBytes(args)};
if (ShouldWarnOversizedDbCache(db_cache, *total_ram)) {
InitWarning(bilingual_str{tfm::format(_("A %zu MiB dbcache may be too large for a system memory of only %zu MiB."),
db_cache >> 20, *total_ram >> 20)});
}
}
}
} // namespace node

View File

@@ -27,6 +27,13 @@ struct CacheSizes {
kernel::CacheSizes kernel;
};
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0);
constexpr bool ShouldWarnOversizedDbCache(size_t dbcache, size_t total_ram) noexcept
{
const size_t cap{(total_ram < 2048_MiB) ? DEFAULT_DB_CACHE : (total_ram / 100) * 75};
return dbcache > cap;
}
void LogOversizedDbCache(const ArgsManager& args) noexcept;
} // namespace node
#endif // BITCOIN_NODE_CACHES_H

View File

@@ -132,7 +132,6 @@ public:
}
void appShutdown() override
{
Interrupt(*m_context);
Shutdown(*m_context);
}
void startShutdown() override
@@ -141,12 +140,7 @@ public:
if (!(Assert(ctx.shutdown_request))()) {
LogError("Failed to send shutdown signal\n");
}
// Stop RPC for clean shutdown if any of waitfor* commands is executed.
if (args().GetBoolArg("-server", false)) {
InterruptRPC();
StopRPC();
}
Interrupt(*m_context);
}
bool shutdownRequested() override { return ShutdownRequested(*Assert(m_context)); };
bool isSettingIgnored(const std::string& name) override
@@ -918,15 +912,21 @@ public:
std::unique_ptr<BlockTemplate> waitNext(BlockWaitOptions options) override
{
auto new_template = WaitAndCreateNewBlock(chainman(), notifications(), m_node.mempool.get(), m_block_template, options, m_assemble_options);
auto new_template = WaitAndCreateNewBlock(chainman(), notifications(), m_node.mempool.get(), m_block_template, options, m_assemble_options, m_interrupt_wait);
if (new_template) return std::make_unique<BlockTemplateImpl>(m_assemble_options, std::move(new_template), m_node);
return nullptr;
}
void interruptWait() override
{
InterruptWait(notifications(), m_interrupt_wait);
}
const BlockAssembler::Options m_assemble_options;
const std::unique_ptr<CBlockTemplate> m_block_template;
bool m_interrupt_wait{false};
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
KernelNotifications& notifications() { return *Assert(m_node.notifications); }
NodeContext& m_node;

View File

@@ -29,6 +29,7 @@
#include <algorithm>
#include <utility>
#include <numeric>
namespace node {
@@ -397,8 +398,8 @@ void BlockAssembler::addPackageTxs(int& nPackagesSelected, int& nDescendantsUpda
++nConsecutiveFailed;
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight >
m_options.nBlockMaxWeight - BLOCK_FULL_ENOUGH_WEIGHT_DELTA) {
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight +
BLOCK_FULL_ENOUGH_WEIGHT_DELTA > m_options.nBlockMaxWeight) {
// Give up if we're close to full and haven't succeeded in a while
break;
}
@@ -453,12 +454,20 @@ void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t
block.hashMerkleRoot = BlockMerkleRoot(block);
}
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait)
{
LOCK(kernel_notifications.m_tip_block_mutex);
interrupt_wait = true;
kernel_notifications.m_tip_block_cv.notify_all();
}
std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainman,
KernelNotifications& kernel_notifications,
CTxMemPool* mempool,
const std::unique_ptr<CBlockTemplate>& block_template,
const BlockWaitOptions& options,
const BlockAssembler::Options& assemble_options)
const BlockAssembler::Options& assemble_options,
bool& interrupt_wait)
{
// Delay calculating the current template fees, just in case a new block
// comes in before the next tick.
@@ -483,8 +492,12 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
// method on BlockTemplate and no template could have been
// generated before a tip exists.
tip_changed = Assume(tip_block) && tip_block != block_template->block.hashPrevBlock;
return tip_changed || chainman.m_interrupt;
return tip_changed || chainman.m_interrupt || interrupt_wait;
});
if (interrupt_wait) {
interrupt_wait = false;
return nullptr;
}
}
if (chainman.m_interrupt) return nullptr;
@@ -522,18 +535,13 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
// Calculate the original template total fees if we haven't already
if (current_fees == -1) {
current_fees = 0;
for (CAmount fee : block_template->vTxFees) {
current_fees += fee;
}
current_fees = std::accumulate(block_template->vTxFees.begin(), block_template->vTxFees.end(), CAmount{0});
}
CAmount new_fees = 0;
for (CAmount fee : new_tmpl->vTxFees) {
new_fees += fee;
Assume(options.fee_threshold != MAX_MONEY);
if (new_fees >= current_fees + options.fee_threshold) return new_tmpl;
}
// Check if fees increased enough to return the new template
const CAmount new_fees = std::accumulate(new_tmpl->vTxFees.begin(), new_tmpl->vTxFees.end(), CAmount{0});
Assume(options.fee_threshold != MAX_MONEY);
if (new_fees >= current_fees + options.fee_threshold) return new_tmpl;
}
now = NodeClock::now();

View File

@@ -238,6 +238,9 @@ void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& opti
/* Compute the block's merkle root, insert or replace the coinbase transaction and the merkle root into the block */
void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t version, uint32_t timestamp, uint32_t nonce);
/* Interrupt the current wait for the next block template. */
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait);
/**
* Return a new block template when fees rise to a certain threshold or after a
* new tip; return nullopt if timeout is reached.
@@ -247,7 +250,8 @@ std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainma
CTxMemPool* mempool,
const std::unique_ptr<CBlockTemplate>& block_template,
const BlockWaitOptions& options,
const BlockAssembler::Options& assemble_options);
const BlockAssembler::Options& assemble_options,
bool& interrupt_wait);
/* Locks cs_main and returns the block hash and block height of the active chain if it exists; otherwise, returns nullopt.*/
std::optional<BlockRef> GetTip(ChainstateManager& chainman);

View File

@@ -573,7 +573,7 @@
</layout>
</item>
<item>
<widget class="QTextEdit" name="messagesWidget">
<widget class="PlainCopyTextEdit" name="messagesWidget">
<property name="minimumSize">
<size>
<width>0</width>
@@ -1868,6 +1868,10 @@
<slot>clear()</slot>
</slots>
</customwidget>
<customwidget>
<class>PlainCopyTextEdit</class>
<extends>QTextEdit</extends>
</customwidget>
</customwidgets>
<resources>
<include location="../bitcoin.qrc"/>

View File

@@ -120,7 +120,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
<translation type="unfinished">Změna hesla</translation>
<translation type="unfinished">Dialog pro zadání hesla</translation>
</message>
<message>
<source>Enter passphrase</source>
@@ -132,7 +132,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Repeat new passphrase</source>
<translation type="unfinished">Totéž heslo ještě jednou</translation>
<translation type="unfinished">Zopakujte nové heslo</translation>
</message>
<message>
<source>Show passphrase</source>
@@ -332,7 +332,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Inbound</source>
<extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
<translation type="unfinished">Sem</translation>
<translation type="unfinished">Příchozí</translation>
</message>
<message>
<source>Outbound</source>
@@ -582,7 +582,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Help</source>
<translation type="unfinished">Nápověd&amp;a</translation>
<translation type="unfinished">&amp;Nápověda</translation>
</message>
<message>
<source>Tabs toolbar</source>
@@ -686,11 +686,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Sending addresses</source>
<translation type="unfinished">Odesílací adresy</translation>
<translation type="unfinished">&amp;Odesílací adresy</translation>
</message>
<message>
<source>&amp;Receiving addresses</source>
<translation type="unfinished">Přijímací adresy</translation>
<translation type="unfinished">&amp;Přijímací adresy</translation>
</message>
<message>
<source>Open a bitcoin: URI</source>
@@ -784,11 +784,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Hide</source>
<translation type="unfinished">Skryj</translation>
<translation type="unfinished">&amp;Skryj</translation>
</message>
<message>
<source>S&amp;how</source>
<translation type="unfinished">Zobraz</translation>
<translation type="unfinished">&amp;Zobraz</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
@@ -1011,7 +1011,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Copy after fee</source>
<translation type="unfinished">Kopíruj čistou částku</translation>
<translation type="unfinished">Zkopírovat částku po odečtení poplatku</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -1100,11 +1100,11 @@ If this wallet contains any watchonly scripts, a new wallet will be created whic
If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.
The migration process will create a backup of the wallet before migrating. This backup file will be named &lt;wallet name&gt;-&lt;timestamp&gt;.legacy.bak and can be found in the directory for this wallet. In the event of an incorrect migration, the backup can be restored with the "Restore Wallet" functionality.</source>
<translation type="unfinished">Migrace peněženky povede k její přeměně na jednu nebo více deskriptorových peněženek. Bude třeba vytvořit novou zálohu peněženky.
Pokud peněženka obsahuje jakékoliv skripty, které lze pouze sledovat, bude vytvořena nová peněženka pouze pro tyto skripty.
Pokud tato peněženka obsahuje jakékoliv řešitelné skripty, které nejdou sledovat, bude vytvořena nová jiná peněženka, která bude obsahovat tyto skripty.
<translation type="unfinished">Migrace peněženky ji převede na jednu nebo více deskriptorových peněženek. Bude třeba vytvořit novou zálohu peněženky.
Pokud tato peněženka obsahuje jakékoli skripty určené pouze ke sledování, bude vytvořena nová peněženka, která bude tyto skripty obsahovat.
Pokud tato peněženka obsahuje jakékoli řešitelné, ale nesledované skripty, bude vytvořena další nová peněženka, která bude tyto skripty obsahovat.
Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se zálohou se bude nazývat &lt;wallet name&gt;-&lt;timestamp&gt;.legacy.bak a bude umístěn v adresáři s touto peněženkou. V případě nepovede migrace je možné provést obnovu prostřednitvím funkce "Obnovit peněženku".</translation>
Proces migrace vytvoří zálohu peněženky před samotnou migrací. Tento záložní soubor se bude jmenovat &lt;wallet name&gt;-&lt;timestamp&gt;.legacy.bak a bude umístěn v adresáři to peněženky. V případě chyb migrace lze zálohu obnovit pomocí funkce "Obnovit peněženku".</translation>
</message>
<message>
<source>Migrate Wallet</source>
@@ -1499,7 +1499,7 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
<translation type="unfinished">Utrácení bitcoinů, které už utratily zatím nezobrazené transakce, nebude bitcoinovou sítí umožněno.</translation>
<translation type="unfinished">Pokus o utracení bitcoinů, které jsou ovlivněny dosud nezobrazenými transakcemi, nebude sítí akceptován.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -1623,7 +1623,7 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
</message>
<message>
<source>Font in the Overview tab: </source>
<translation type="unfinished">Písmo s pevnou šířkou v panelu Přehled:</translation>
<translation type="unfinished">Písmo na kartě Přehled:</translation>
</message>
<message>
<source>Options set in this dialog are overridden by the command line:</source>
@@ -1770,7 +1770,7 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
<translation type="unfinished">&amp;Minimalizovávat do ikony v panelu</translation>
<translation type="unfinished">&amp;Minimalizovat do oznamovací oblasti místo na hlavní panel</translation>
</message>
<message>
<source>M&amp;inimize on close</source>
@@ -1816,10 +1816,6 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
<translation type="unfinished">Použít samostatnou SOCKS&amp;5 proxy ke spojení s protějšky přes skryté služby v Toru:</translation>
</message>
<message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Budiž</translation>
</message>
<message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Zrušit</translation>
@@ -2022,7 +2018,7 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
</message>
<message>
<source>Save Transaction Data</source>
<translation type="unfinished">Zachovaj procesní data</translation>
<translation type="unfinished">Uložit transakční data</translation>
</message>
<message>
<source>Partially Signed Transaction (Binary)</source>
@@ -2079,7 +2075,7 @@ Proces migrace vytvoří zálohu peněženky přes samotnou migrací. Soubor se
</message>
<message>
<source>(But this wallet does not have the right keys.)</source>
<translation type="unfinished">Ale tenhle vstup nemá správné klíče</translation>
<translation type="unfinished">(Ale tato peněženka nemá správné klíče.)</translation>
</message>
<message>
<source>Transaction is fully signed and ready for broadcast.</source>
@@ -2180,7 +2176,7 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<message>
<source>Inbound</source>
<extracomment>An Inbound Connection from a Peer.</extracomment>
<translation type="unfinished">Sem</translation>
<translation type="unfinished">Příchozí</translation>
</message>
<message>
<source>Outbound</source>
@@ -2248,7 +2244,7 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
</message>
<message>
<source>To specify a non-default location of the blocks directory use the '%1' option.</source>
<translation type="unfinished">Pro specifikaci neklasické lokace pro data použij možnost '%1'</translation>
<translation type="unfinished">Pro zadání jiného umístění adresáře s bloky použijte volbu '%1'.</translation>
</message>
<message>
<source>Startup time</source>
@@ -2360,7 +2356,7 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
</message>
<message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Mapovaný nezávislý - Autonomní Systém používaný pro rozšírení vzájemného výběru protějsků.</translation>
<translation type="unfinished">Mapovaný autonomní systém používaný ke zpestření výběru peerů.</translation>
</message>
<message>
<source>Mapped AS</source>
@@ -2394,7 +2390,7 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<message>
<source>Addresses Rate-Limited</source>
<extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Adresy s omezením počtu přijatých adres</translation>
<translation type="unfinished">Adresy omezené rychlostí</translation>
</message>
<message>
<source>User Agent</source>
@@ -2406,7 +2402,7 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
</message>
<message>
<source>Current block height</source>
<translation type="unfinished">Velikost aktuálního bloku</translation>
<translation type="unfinished">Aktuální výška bloku</translation>
</message>
<message>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
@@ -2684,7 +2680,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Ban for</source>
<translation type="unfinished">Uval klatbu na</translation>
<translation type="unfinished">Zákaz na</translation>
</message>
<message>
<source>Never</source>
@@ -2715,7 +2711,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
<translation type="unfinished">Volitelné označení, které se má přiřadit k nové adrese.</translation>
<translation type="unfinished">Volitelný štítek, který se má přiřadit k nové přijímající adrese.</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
@@ -2727,7 +2723,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source>
<translation type="unfinished">Volitelný popis který sa přidá k téjo nové přijímací adrese (pro jednoduchší identifikaci). Tenhle popis bude také přidán do výzvy k platbě.</translation>
<translation type="unfinished">Volitelný štítek k přiřazení nové přijímací adrese (použijete jej k identifikaci faktury). Je také připojen k platební žádosti.</translation>
</message>
<message>
<source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
@@ -2759,7 +2755,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Remove the selected entries from the list</source>
<translation type="unfinished">Smaž zvolené požadavky ze seznamu</translation>
<translation type="unfinished">Odstranit vybrané položky ze seznamu</translation>
</message>
<message>
<source>Remove</source>
@@ -3000,7 +2996,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Hide transaction fee settings</source>
<translation type="unfinished">Schovat nastavení poplatků transakce - transaction fee</translation>
<translation type="unfinished">Skrýt nastavení poplatků za transakci</translation>
</message>
<message>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
@@ -3012,7 +3008,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
<translation type="unfinished">Když je zde měně transakcí než místa na bloky, mineři stejně tak relay-e mohou nasadit minimální poplatky. Zaplacením pouze minimálního poplatku je v pohodě, ale mějte na paměti že toto může mít za následek nikdy neověřenou transakci pokud zde bude více bitcoinových transakcí než může síť zvládnout.</translation>
<translation type="unfinished">Když je menší objem transakcí než je místa v blocích, mohou těžaři i uzly, které transakce předávají, vyžadovat minimální poplatek. Zaplatit pouze tento minimální poplatek je v pořádku, ale mějte na paměti, že to může vést k tomu, že vaše transakce nikdy nebude potvrzena, pokud bude větší poptávka po bitcoinových transakcích, než kolik síť zvládne zpracovat.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
@@ -3036,7 +3032,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Clear &amp;All</source>
<translation type="unfinished">Všechno &amp;smaž</translation>
<translation type="unfinished">Smazat &amp;vše</translation>
</message>
<message>
<source>Balance:</source>
@@ -3064,7 +3060,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Copy after fee</source>
<translation type="unfinished">Kopíruj čistou částku</translation>
<translation type="unfinished">Zkopírovat částku po odečtení poplatku</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -3094,7 +3090,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">Vytvořit bez podpisu</translation>
<translation type="unfinished">Vytvořit &amp;bez podpisu</translation>
</message>
<message>
<source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
@@ -3128,7 +3124,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Save Transaction Data</source>
<translation type="unfinished">Zachovej procesní data</translation>
<translation type="unfinished">Uložit údaje o transakci</translation>
</message>
<message>
<source>Partially Signed Transaction (Binary)</source>
@@ -3315,7 +3311,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Zadej označení této adresy; obojí se ti pak uloží do adresáře</translation>
<translation type="unfinished">Zadej popisek pro tuto adresu, aby byla přidána do seznamu použitých adres</translation>
</message>
<message>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
@@ -3369,7 +3365,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Copy the current signature to the clipboard</source>
<translation type="unfinished">Zkopírovat právě vybraný podpis do schránky</translation>
<translation type="unfinished">Zkopírovat aktuální podpis do schránky</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
@@ -3381,11 +3377,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Reset all sign message fields</source>
<translation type="unfinished">Vymaž všechna pole formuláře pro podepsání zrávy</translation>
<translation type="unfinished">Resetuj všechna pole formuláře pro podepsání zprávy</translation>
</message>
<message>
<source>Clear &amp;All</source>
<translation type="unfinished">Všechno &amp;smaž</translation>
<translation type="unfinished">Smazat &amp;vše</translation>
</message>
<message>
<source>&amp;Verify Message</source>
@@ -3417,7 +3413,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Reset all verify message fields</source>
<translation type="unfinished">Vymaž všechna pole formuláře pro ověření zrávy</translation>
<translation type="unfinished">Resetovat všechna pole formuláře pro ověření zprávy</translation>
</message>
<message>
<source>Click "Sign Message" to generate signature</source>
@@ -3429,7 +3425,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Please check the address and try again.</source>
<translation type="unfinished">Zkontroluj ji prosím a zkus to pak znovu.</translation>
<translation type="unfinished">Zkontrolujte prosím adresu a zkuste to znovu.</translation>
</message>
<message>
<source>The entered address does not refer to a legacy (P2PKH) key. Message signing for SegWit and other non-P2PKH address types is not supported in this version of %1. Please check the address and try again.</source>
@@ -3938,7 +3934,7 @@ Přejděte do Soubor &gt; Otevřít peněženku pro načtení peněženky.
</message>
<message>
<source>Increasing transaction fee failed</source>
<translation type="unfinished">Nepodařilo se navýšeit poplatek</translation>
<translation type="unfinished">Nepodařilo se navýšit poplatek</translation>
</message>
<message>
<source>Do you want to increase the fee?</source>
@@ -3979,7 +3975,7 @@ Přejděte do Soubor &gt; Otevřít peněženku pro načtení peněženky.
</message>
<message>
<source>Could not commit transaction</source>
<translation type="unfinished">Nemohl jsem uložit transakci do peněženky</translation>
<translation type="unfinished">Nelze potvrdit transakci</translation>
</message>
<message>
<source>Signer error</source>
@@ -4038,7 +4034,7 @@ Přejděte do Soubor &gt; Otevřít peněženku pro načtení peněženky.
</message>
<message>
<source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any peer will connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
<translation type="unfinished"> %s Žádost o poslech na portu 2 %u . Tento port je považován za "špatný", a proto je nepravděpodobné, že by se k němu připojil nějaký peer. Viz doc/p2p-bad-ports.md pro podrobnosti a úplný seznam.</translation>
<translation type="unfinished"> %s Žádost o poslech na portu %u . Tento port je považován za "špatný", a proto je nepravděpodobné, že by se k němu připojil nějaký peer. Viz doc/p2p-bad-ports.md pro podrobnosti a úplný seznam.</translation>
</message>
<message>
<source>Disk space for %s may not accommodate the block files. Approximately %u GB of data will be stored in this directory.</source>
@@ -4131,7 +4127,7 @@ Ověřuji peněženku.</translation>
</message>
<message>
<source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
<translation type="unfinished">Jedná se o maximální poplatek, který zaplatíte (navíc k běžnému poplatku), aby se upřednostnila útrata z dosud nepoužitých adres oproti těm jednou použitých.</translation>
<translation type="unfinished">Jedná se o maximální poplatek, který zaplatíte (navíc k běžnému poplatku), abyste upřednostnili vyhýbání se částečnému utrácení před běžným výběrem mincí.</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
@@ -4273,11 +4269,11 @@ Ověřuji peněženku.</translation>
</message>
<message>
<source>Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated. They will be removed in a future version.</source>
<translation type="unfinished">Možnosti '-datacarrier' a '-datacarriersize' jsou nastaveny, ale jsou označené za zastaralé. V budoucí verzi budou odstraněny.</translation>
<translation type="unfinished">Možnosti '-datacarrier' nebo '-datacarriersize' jsou nastaveny, ale jsou označeny jako zastaralé. V některé z budoucích verzí budou odstraněny.</translation>
</message>
<message>
<source>Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided</source>
<translation type="unfinished">Odchozí připojení omezená na CJDNS (-onlynet=cjdns), ale -cjdnsreachable nejsou k dispozici</translation>
<translation type="unfinished">Odchozí připojení jsou omezena na CJDNS (-onlynet=cjdns), ale -cjdnsreachable ne zadán</translation>
</message>
<message>
<source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
@@ -4293,7 +4289,7 @@ Ověřuji peněženku.</translation>
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of a pruned node)</source>
<translation type="unfinished">Prořezávání: poslední synchronizace peněženky proběhla před už prořezanými daty. Je třeba provést -reindex (tedy v případě režimu prořezávání stáhnout celý blockchain znovu)</translation>
<translation type="unfinished">Prořezávání: poslední synchronizace peněženky spadá do již prořezaných dat. Je třeba provést -reindex (v případě prořezávaného uzlu se znovu stáhne celý blockchain).</translation>
</message>
<message>
<source>Rename of '%s' -&gt; '%s' failed. Cannot clean up the background chainstate leveldb directory.</source>
@@ -4367,7 +4363,7 @@ Nelze obnovit zálohu peněženky.</translation>
</message>
<message>
<source>-paytxfee is deprecated and will be fully removed in v31.0.</source>
<translation type="unfinished">Možnost -paytxfee je zastaralá a bude v příští verzi v31.0 plně odstraněna</translation>
<translation type="unfinished"> Volba -paytxfee je zastaralá a bude ve verzi 31.0 úplně odstraněna.</translation>
</message>
<message>
<source>A fatal internal error occurred, see debug.log for details: </source>
@@ -4575,7 +4571,7 @@ Nelze obnovit zálohu peněženky.</translation>
</message>
<message>
<source>Error: Unable to write data to disk for wallet %s</source>
<translation type="unfinished">Chyba: Nepodařilo se zapsat data peněženky %sna disk</translation>
<translation type="unfinished">Chyba: Nepodařilo se zapsat data na disk pro peněženku %s</translation>
</message>
<message>
<source>Error: Unable to write record to new wallet</source>
@@ -4695,7 +4691,7 @@ Nelze obnovit zálohu peněženky.</translation>
</message>
<message>
<source>Invalid amount for %s=&lt;amount&gt;: '%s' (must be at least %s)</source>
<translation type="unfinished">Neplatná částka %s=&lt;amount&gt;:'%s' (musí být alespoň%s)</translation>
<translation type="unfinished">Neplatná částka %s=&lt;amount&gt;:'%s' (musí být alespoň %s)</translation>
</message>
<message>
<source>Invalid amount for %s=&lt;amount&gt;: '%s'</source>
@@ -4999,7 +4995,7 @@ Nelze obnovit zálohu peněženky.</translation>
</message>
<message>
<source>Error loading %s: Wallet is a legacy wallet. Please migrate to a descriptor wallet using the migration tool (migratewallet RPC).</source>
<translation type="unfinished">Chyba při načítání %s: Zastaralý typ peněženky. Převeďte ji prosím na deskriptorovou pomocí převodného nástroje (migratewallet RPC)</translation>
<translation type="unfinished">Chyba při načítání %s: Zastaralý typ peněženky. Převeďte ji prosím na deskriptorovou peněženku pomocí migračního nástroje (migratewallet RPC).</translation>
</message>
<message>
<source>Error: Dumpfile specifies an unsupported database format (%s). Only sqlite database dumps are supported</source>
@@ -5011,7 +5007,7 @@ Nelze obnovit zálohu peněženky.</translation>
</message>
<message>
<source>Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input</source>
<translation type="unfinished">Transakce vyžaduje jeden cíl nenulové hodnoty, nenulový poplatek nebo předvybraný vstup</translation>
<translation type="unfinished">Transakce vyžaduje jeden cíl s nenulovou hodnotou, nenulovou sazbu poplatku nebo předem vybraný vstup</translation>
</message>
<message>
<source>Unrecognized descriptor found. Loading wallet %s
@@ -5031,7 +5027,7 @@ Zkuste prosím spustit nejnovější verzi softwaru.
</message>
<message>
<source>Error: Could not add watchonly tx %s to watchonly wallet</source>
<translation type="unfinished">Chyba: Nelze přidat pouze-sledovací tx %s do peněženky pro čtení</translation>
<translation type="unfinished">Chyba: Nelze přidat transakci pouze pro sledování %s do peněženky pouze pro sledování</translation>
</message>
<message>
<source>Error: Could not delete watchonly transactions. </source>
@@ -5055,11 +5051,11 @@ Zkuste prosím spustit nejnovější verzi softwaru.
</message>
<message>
<source>Not enough file descriptors available. %d available, %d required.</source>
<translation type="unfinished">Nedostatek volných file deskriptorů. %dvolných, %dvyžadovaných</translation>
<translation type="unfinished">Nedostatek volných souborových deskriptorů. %dvolných, %dvyžadovaných.</translation>
</message>
<message>
<source>Unrecognized network in -proxy='%s': '%s'</source>
<translation type="unfinished">Nerozeznaná síť v -proxy='%s': '%s'</translation>
<translation type="unfinished">Nerozpoznaná síť v -proxy='%s': '%s'</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>

View File

@@ -324,7 +324,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished">Ingresa una dirección de Bitcoin (Ejemplo: %1)</translation>
<translation type="unfinished">Ingresa una dirección de Bitcoin (por ejemplo, %1)</translation>
</message>
<message>
<source>Unroutable</source>
@@ -439,7 +439,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>E&amp;xit</source>
<translation type="unfinished">S&amp;alir</translation>
<translation type="unfinished">&amp;Salir</translation>
</message>
<message>
<source>Quit application</source>
@@ -508,7 +508,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>&amp;Options…</source>
<translation type="unfinished">&amp;Opciones...</translation>
<translation type="unfinished">&amp;Opciones</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
@@ -520,15 +520,15 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
<translation type="unfinished">&amp;Realizar copia de seguridad del monedero...</translation>
<translation type="unfinished">&amp;Realizar copia de seguridad del monedero</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
<translation type="unfinished">&amp;Cambiar contraseña...</translation>
<translation type="unfinished">&amp;Cambiar frase de contraseña</translation>
</message>
<message>
<source>Sign &amp;message…</source>
<translation type="unfinished">Firmar &amp;mensaje...</translation>
<translation type="unfinished">Firmar &amp;mensaje</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
@@ -536,7 +536,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>&amp;Verify message…</source>
<translation type="unfinished">&amp;Verificar mensaje...</translation>
<translation type="unfinished">&amp;Verificar mensaje</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
@@ -687,7 +687,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>Open a wallet</source>
<translation type="unfinished">Abre un monedero</translation>
<translation type="unfinished">Abrir monedero</translation>
</message>
<message>
<source>Close wallet</source>
@@ -975,7 +975,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>&amp;Unlock unspent</source>
<translation type="unfinished">&amp;Desbloquear lo no gastado</translation>
<translation type="unfinished">&amp;Desbloquear salidas no gastadas</translation>
</message>
<message>
<source>Copy quantity</source>
@@ -987,7 +987,7 @@ Solo es posible firmar con direcciones de tipo "legacy".</translation>
</message>
<message>
<source>Copy after fee</source>
<translation type="unfinished">Copiar después de la comisión</translation>
<translation type="unfinished">Copiar importe después de comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -1129,7 +1129,7 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;</source>
<extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
<translation type="unfinished">Abriendo monedero &lt;b&gt;%1&lt;/b&gt;...</translation>
<translation type="unfinished">Abriendo monedero &lt;b&gt;%1&lt;/b&gt;</translation>
</message>
</context>
<context>
@@ -1918,11 +1918,11 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>Sign Tx</source>
<translation type="unfinished">Firmar Tx</translation>
<translation type="unfinished">Firmar transacción</translation>
</message>
<message>
<source>Broadcast Tx</source>
<translation type="unfinished">Emitir Tx</translation>
<translation type="unfinished">Transmitir transacción</translation>
</message>
<message>
<source>Copy to Clipboard</source>
@@ -1930,7 +1930,7 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>Save…</source>
<translation type="unfinished">Guardar...</translation>
<translation type="unfinished">Guardar</translation>
</message>
<message>
<source>Close</source>
@@ -1954,11 +1954,11 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>Signed %1 inputs, but more signatures are still required.</source>
<translation type="unfinished">Se han firmado %1 entradas, pero aún se requieren más firmas.</translation>
<translation type="unfinished">Se firmaron %1 entradas, pero aún se requieren más firmas.</translation>
</message>
<message>
<source>Signed transaction successfully. Transaction is ready to broadcast.</source>
<translation type="unfinished">Se ha firmado correctamente. La transacción está lista para difundirse.</translation>
<translation type="unfinished">La transacción se firmó correctamente y está lista para transmitirse.</translation>
</message>
<message>
<source>Unknown error processing transaction.</source>
@@ -1970,7 +1970,7 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>Transaction broadcast failed: %1</source>
<translation type="unfinished">Ha habido un error en la difusión de la transacción: %1</translation>
<translation type="unfinished">Error en la transmisión de la transacción: %1</translation>
</message>
<message>
<source>PSBT copied to clipboard.</source>
@@ -2019,7 +2019,7 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>Transaction is missing some information about inputs.</source>
<translation type="unfinished">Falta alguna información sobre las entradas de la transacción.</translation>
<translation type="unfinished">Falta información sobre las entradas de la transacción.</translation>
</message>
<message>
<source>Transaction still needs signature(s).</source>
@@ -2027,19 +2027,19 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
</message>
<message>
<source>(But no wallet is loaded.)</source>
<translation type="unfinished">(No existe ningún monedero cargado.)</translation>
<translation type="unfinished">(Sin embargo, no se cargó ningún monedero).</translation>
</message>
<message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Este monedero no puede firmar transacciones.)</translation>
<translation type="unfinished">(Este monedero no puede firmar transacciones).</translation>
</message>
<message>
<source>(But this wallet does not have the right keys.)</source>
<translation type="unfinished">(Este monedero no tiene las claves adecuadas.)</translation>
<translation type="unfinished">(Este monedero no tiene las claves adecuadas).</translation>
</message>
<message>
<source>Transaction is fully signed and ready for broadcast.</source>
<translation type="unfinished">La transacción se ha firmado correctamente y está lista para difundirse.</translation>
<translation type="unfinished">La transacción se firmó correctamente y está lista para transmitirse.</translation>
</message>
<message>
<source>Transaction status is unknown.</source>
@@ -2068,13 +2068,13 @@ El proceso de migración creará una copia de seguridad del monedero antes de mi
<source>Cannot process payment request because BIP70 is not supported.
Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
<translation type="unfinished">No se puede procesar la solicitud de pago debido a que no se mantiene BIP70.
Debido a los fallos de seguridad generalizados en el BIP70, se recomienda encarecidamente ignorar las instrucciones del comerciante para cambiar de monedero.
<translation type="unfinished">No se puede procesar la solicitud de pago porque no no es compatible con BIP70.
Debido a los fallos de seguridad generalizados en BIP70, se recomienda encarecidamente ignorar las instrucciones del comerciante para cambiar de monedero.
Si recibe este error, debe solicitar al comerciante que le proporcione un URI compatible con BIP21.</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">¡No se puede interpretar la URI! Esto puede deberse a una dirección Bitcoin inválida o a parámetros de URI mal formados.</translation>
<translation type="unfinished">No se puede analizar el URI. Esto puede deberse a una dirección Bitcoin inválida o a parámetros de URI con formato incorrecto.</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -2086,12 +2086,12 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<message>
<source>User Agent</source>
<extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
<translation type="unfinished">Agente del usuario</translation>
<translation type="unfinished">Agente de usuario</translation>
</message>
<message>
<source>Peer</source>
<extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
<translation type="unfinished">Pareja</translation>
<translation type="unfinished">Par</translation>
</message>
<message>
<source>Age</source>
@@ -2239,7 +2239,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Memory usage</source>
<translation type="unfinished">Memoria utilizada</translation>
<translation type="unfinished">Uso de memoria</translation>
</message>
<message>
<source>Wallet: </source>
@@ -2357,7 +2357,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>User Agent</source>
<translation type="unfinished">Agente del usuario</translation>
<translation type="unfinished">Agente de usuario</translation>
</message>
<message>
<source>Node window</source>
@@ -2543,7 +2543,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>the peer selected us for high bandwidth relay</source>
<translation type="unfinished">El par nos seleccionó para la retransmisión en ancho de banda alto</translation>
<translation type="unfinished">el par nos seleccionó para la retransmisión de gran ancho de banda</translation>
</message>
<message>
<source>no high bandwidth relay selected</source>
@@ -2702,11 +2702,11 @@ Para obtener más información sobre cómo usar esta consola, escribe %6.
</message>
<message>
<source>Clear all fields of the form.</source>
<translation type="unfinished">Borrar todos los campos del formulario.</translation>
<translation type="unfinished">Vaciar todos los campos del formulario.</translation>
</message>
<message>
<source>Clear</source>
<translation type="unfinished">Borrar</translation>
<translation type="unfinished">Vaciar</translation>
</message>
<message>
<source>Requested payments history</source>
@@ -2748,10 +2748,6 @@ Para obtener más información sobre cómo usar esta consola, escribe %6.
<source>Copy &amp;amount</source>
<translation type="unfinished">Copiar &amp;importe</translation>
</message>
<message>
<source>Base58 (Legacy)</source>
<translation type="unfinished">Base58 (Heredada)</translation>
</message>
<message>
<source>Not recommended due to higher fees and less protection against typos.</source>
<translation type="unfinished">No se recomienda debido a las altas comisiones y la poca protección contra errores tipográficos.</translation>
@@ -2995,7 +2991,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Clear &amp;All</source>
<translation type="unfinished">Borrar &amp;todo</translation>
<translation type="unfinished">Vaciar &amp;todo</translation>
</message>
<message>
<source>Balance:</source>
@@ -3023,7 +3019,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Copy after fee</source>
<translation type="unfinished">Copiar tras comisión</translation>
<translation type="unfinished">Copiar importe después de comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -3128,7 +3124,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
<message>
<source>Please, review your transaction. You can create and send this transaction or create a Partially Signed Bitcoin Transaction (PSBT), which you can save or copy and then sign with, e.g., an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
<extracomment>Text to inform a user attempting to create a transaction of their current options. At this stage, a user can send their transaction or create a PSBT. This string is displayed when both private keys and PSBT controls are enabled.</extracomment>
<translation type="unfinished">Revisa la transacción. Puedes crear y enviar esta transacción de Bitcoin parcialmente firmada (PSBT), que además puedes guardar o copiar y, luego, firmar; por ejemplo, con un monedero %1 sin conexión o un monedero de hardware compatible con PSBT.</translation>
<translation type="unfinished">Revisa la transacción. Puedes crear y enviar esta transacción o crear una transacción de Bitcoin parcialmente firmada (PSBT), que además puedes guardar o copiar y, luego, firmar; por ejemplo, con un monedero %1 sin conexión o un monedero de hardware compatible con PSBT.</translation>
</message>
<message>
<source>Please, review your transaction.</source>
@@ -3155,11 +3151,11 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>The PSBT has been copied to the clipboard. You can also save it.</source>
<translation type="unfinished">Se copió la PSBT al portapapeles. También puedes guardarla.</translation>
<translation type="unfinished">Se copió la PSBT al portapapeles. También puedes guardarla.</translation>
</message>
<message>
<source>PSBT saved to disk</source>
<translation type="unfinished"> PSBT guardada en disco</translation>
<translation type="unfinished">PSBT guardada en disco</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -3534,11 +3530,11 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Total debit</source>
<translation type="unfinished">Total débito</translation>
<translation type="unfinished">Débito total</translation>
</message>
<message>
<source>Total credit</source>
<translation type="unfinished">Total crédito</translation>
<translation type="unfinished">Crédito total</translation>
</message>
<message>
<source>Transaction fee</source>
@@ -3656,7 +3652,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Immature (%1 confirmations, will be available after %2)</source>
<translation type="unfinished">Inmadura (%1 confirmaciones; estará disponibles después de %2)</translation>
<translation type="unfinished">Inmadura (%1 confirmaciones; estará disponible después de %2)</translation>
</message>
<message>
<source>Generated but not accepted</source>
@@ -3759,7 +3755,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Range</source>
<translation type="unfinished">Intervalo...</translation>
<translation type="unfinished">Intervalo</translation>
</message>
<message>
<source>&amp;Copy address</source>
@@ -3775,7 +3771,7 @@ Nota: Dado que la comisión se calcula por byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Copy transaction &amp;ID</source>
<translation type="unfinished">Copiar &amp;identificador de transacción</translation>
<translation type="unfinished">Copiar &amp;ID de transacción</translation>
</message>
<message>
<source>Copy &amp;raw transaction</source>
@@ -3880,7 +3876,7 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
<translation type="unfinished">No se puede decodificar la PSBT desde el portapapeles (Base64 inválida)</translation>
<translation type="unfinished">No se puede decodificar la PSBT desde el portapapeles (Base64 inválida)</translation>
</message>
<message>
<source>Load Transaction Data</source>
@@ -3892,11 +3888,11 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>PSBT file must be smaller than 100 MiB</source>
<translation type="unfinished">El archivo de la PSBT debe ser inferior a 100 MiB</translation>
<translation type="unfinished">El archivo PSBT debe ser menor de 100 MiB</translation>
</message>
<message>
<source>Unable to decode PSBT</source>
<translation type="unfinished">No es posible descodificar la PSBT</translation>
<translation type="unfinished">No es posible descodificar la PSBT</translation>
</message>
</context>
<context>
@@ -3940,19 +3936,19 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Can't draft transaction.</source>
<translation type="unfinished">No se puede crear un borrador de la transacción.</translation>
<translation type="unfinished">No puede crear un borrador de la transacción.</translation>
</message>
<message>
<source>PSBT copied</source>
<translation type="unfinished"> PSBT copiada </translation>
<translation type="unfinished">PSBT copiada </translation>
</message>
<message>
<source>Fee-bump PSBT copied to clipboard</source>
<translation type="unfinished"> PSBT con incremento de comisión copiada en el portapapeles</translation>
<translation type="unfinished">PSBT con incremento de comisión copiada en el portapapeles</translation>
</message>
<message>
<source>Can't sign transaction.</source>
<translation type="unfinished">No se puede firmar la transacción.</translation>
<translation type="unfinished">No puede firmar la transacción.</translation>
</message>
<message>
<source>Could not commit transaction</source>
@@ -3964,7 +3960,7 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Can't display address</source>
<translation type="unfinished">No se puede mostrar la dirección</translation>
<translation type="unfinished">No puede mostrar la dirección</translation>
</message>
</context>
<context>
@@ -4083,15 +4079,15 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
<translation type="unfinished">Contribuya si encuentra %s de utilidad. Visite %s para más información acerca del programa.</translation>
<translation type="unfinished">Contribuye si te parece que %s es útil. Visita %s para obtener más información acerca del software.</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation type="unfinished">La poda se ha configurado por debajo del mínimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
<translation type="unfinished">La poda se configuró por debajo del mínimo de %d MiB. Usa un valor más alto.</translation>
</message>
<message>
<source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
<translation type="unfinished">El modo poda no es compatible con -reindex-chainstate. Haz uso de un -reindex completo en su lugar.</translation>
<translation type="unfinished">El modo de poda no es compatible con -reindex-chainstate. Usa -reindex completo en su lugar.</translation>
</message>
<message>
<source>Rename of '%s' -&gt; '%s' failed. You should resolve this by manually moving or deleting the invalid snapshot directory %s, otherwise you will encounter the same error again on the next startup.</source>
@@ -4099,11 +4095,11 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
<translation type="unfinished">SQLiteDatabase: versión del esquema de la monedero sqlite desconocido %d. Sólo version %d se admite</translation>
<translation type="unfinished">SQLiteDatabase: versión del esquema de monedero sqlite desconocido (%d). Solo se admite la versión %d.</translation>
</message>
<message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation type="unfinished">La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de su equipo están mal ajustados. Reconstruya la base de datos de bloques solo si está seguro de que la fecha y hora de su equipo están ajustadas correctamente.</translation>
<translation type="unfinished">La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede deberse a que la fecha y hora del equipo están mal configuradas. Reconstruye la base de datos de bloques solo tienes la certeza de que la fecha y hora del equipo están configuradas correctamente.</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
@@ -4135,7 +4131,7 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Unsupported category-specific logging level %1$s=%2$s. Expected %1$s=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %3$s. Valid loglevels: %4$s.</source>
<translation type="unfinished">El nivel de registro específico de la categoría no es compatible: %1$s=%2$s. Se esperaba %1$s=&lt;category&gt;:&lt;loglevel&gt;. Categorías válidas: %3$s. Niveles de registro válidos: %4 $s.</translation>
<translation type="unfinished">El nivel de registro específico de la categoría no es compatible: %1$s=%2$s. Se esperaba %1$s=&lt;category&gt;:&lt;loglevel&gt;. Categorías válidas: %3$s. Niveles de registro válidos: %4$s.</translation>
</message>
<message>
<source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
@@ -4167,11 +4163,11 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Cannot obtain a lock on directory %s. %s is probably already running.</source>
<translation type="unfinished">No se puede obtener un bloqueo en el directorio %s. %s probablemente ya se está ejecutando</translation>
<translation type="unfinished">No se puede obtener un bloqueo en el directorio %s. %s probablemente ya se está ejecutando.</translation>
</message>
<message>
<source>Cannot resolve -%s address: '%s'</source>
<translation type="unfinished">No se puede resolver la dirección de -%s: "%s"</translation>
<translation type="unfinished">No se puede resolver - dirección%s: "%s"</translation>
</message>
<message>
<source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
@@ -4233,11 +4229,11 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
<translation type="unfinished">Opciones incompatibles: -dnsseed=1 se especificó explicitamente, pero -onlynet impide conexiones a IPv4/IPv6</translation>
<translation type="unfinished">Opciones incompatibles: -dnsseed=1 se especificó explícitamente, pero -onlynet impide conexiones a IPv4/IPv6</translation>
</message>
<message>
<source>Invalid amount for %s=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">Importe inválido para %s=&lt;amount&gt;: '%s' (debe ser al menos la comisión mínima de retransmisión de %s para evitar transacciones atascadas)</translation>
<translation type="unfinished">Importe inválido para %s=&lt;amount&gt;: "%s" (debe ser al menos la comisión mínima de retransmisión de %s para evitar transacciones atascadas)</translation>
</message>
<message>
<source>Maximum transaction weight is less than transaction weight without inputs</source>
@@ -4249,15 +4245,15 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Option '-checkpoints' is set but checkpoints were removed. This option has no effect.</source>
<translation type="unfinished">La opción '-checkpoints' está activa pero los puntos de guardado han sido eliminados. Esta opción no tiene efecto.</translation>
<translation type="unfinished">La opción "-checkpoints" está configurada, pero se eliminaron los puntos de control. Esta opción no tiene efecto.</translation>
</message>
<message>
<source>Option '-maxorphantx' is set but no longer has any effect (see release notes). Please remove it from your configuration.</source>
<translation type="unfinished">La opción '-maxorphantx' está activada pero ya no tiene ningún efecto (mirar notas de lanzamiento) . Por favor, elimínala de su configuración.</translation>
<translation type="unfinished">La opción "-maxorphantx" está configurada, pero ya no tiene ningún efecto (consultar notas de lanzamiento). Elimínala de la configuración.</translation>
</message>
<message>
<source>Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated. They will be removed in a future version.</source>
<translation type="unfinished">Las opciones '-datacarrier' o '-datacarriersize' están activadas, pero están marcadas como obsoletas. Serán eliminadas en una futura versión. </translation>
<translation type="unfinished">Las opciones "-datacarrier" o "-datacarriersize" están configuradas, pero se marcaron como obsoletas. Se eliminarán en una futura versión.</translation>
</message>
<message>
<source>Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided</source>
@@ -4277,11 +4273,11 @@ Ir a "Archivo &gt; Abrir monedero" para cargar uno.
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of a pruned node)</source>
<translation type="unfinished">Poda: la última sincronización sobrepasa los datos podados. Tiene que -reindex (descarga toda la cadena de bloques de nuevo en caso de tener un nodo podado).</translation>
<translation type="unfinished">Poda: la última sincronización sobrepasa los datos podados. Debes ejecutar "-reindex" (descargar toda la cadena de bloques de nuevo en caso de tener un nodo podado).</translation>
</message>
<message>
<source>Rename of '%s' -&gt; '%s' failed. Cannot clean up the background chainstate leveldb directory.</source>
<translation type="unfinished">Error al cambiar el nombre de ''%s" a ''%s". No se puede limpiar el directorio leveldb del estado de la cadena de fondo.</translation>
<translation type="unfinished">Error al cambiar el nombre de ''%s" a ''%s". No se puede eliminar el directorio leveldb de chainstate en segundo plano.</translation>
</message>
<message>
<source>Specified -blockmaxweight (%d) exceeds consensus maximum block weight (%d)</source>
@@ -4351,7 +4347,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>-paytxfee is deprecated and will be fully removed in v31.0.</source>
<translation type="unfinished">-paytxfee está obsoleto y se completamente eliminado en v31.0</translation>
<translation type="unfinished">-paytxfee está obsoleto y se eliminará por completo en la versión 31.0.</translation>
</message>
<message>
<source>A fatal internal error occurred, see debug.log for details: </source>
@@ -4367,15 +4363,15 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Can't spend unconfirmed version %d pre-selected input with a version 3 tx</source>
<translation type="unfinished">No se puede gastar la versión sin confirmar %d entrada preseleccionada con una version 3 tx</translation>
<translation type="unfinished">No se puede gastar una entrada preseleccionada de versión %d sin confirmar con una transacción de versión 3</translation>
</message>
<message>
<source>Can't spend unconfirmed version 3 pre-selected input with a version %d tx</source>
<translation type="unfinished">No se puede gastar una entrada preseleccionada de la versión 3 sin confirmar con una version %d tx</translation>
<translation type="unfinished">No se puede gastar una entrada preseleccionada de versión 3 sin confirmar con una transacción de version %d</translation>
</message>
<message>
<source>Cannot add WalletDescriptor to a non-descriptor wallet</source>
<translation type="unfinished">No se puede añadir un monedero basado en descriptores a un monedero no basado en descriptores</translation>
<translation type="unfinished">No se puede añadir WalletDescriptor a un monedero no basado en descriptores</translation>
</message>
<message>
<source>Cannot write to directory '%s'; check permissions.</source>
@@ -4403,7 +4399,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Could not generate scriptPubKeys (cache is empty)</source>
<translation type="unfinished">No se ha podido generar scriptPubKeys ( la cache esta vacía)</translation>
<translation type="unfinished">No se pudo generar scriptPubKeys (la caché está vacía)</translation>
</message>
<message>
<source>Could not parse asmap file %s</source>
@@ -4487,11 +4483,11 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Error: No se pudo crear el cursor en la base de datos</translation>
<translation type="unfinished">Error: No pudo crear el cursor en la base de datos</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Error: El espacio en disco es pequeño para %s</translation>
<translation type="unfinished">Error: El espacio en disco es bajo para %s</translation>
</message>
<message>
<source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
@@ -4523,11 +4519,11 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Error: Not all address book records were migrated</source>
<translation type="unfinished">Error: No todos los registros del libro de direcciones han sido migrados</translation>
<translation type="unfinished">Error: No se migraron todos los registros de la libreta de direcciones.</translation>
</message>
<message>
<source>Error: Not all transaction records were migrated</source>
<translation type="unfinished">Error: No todos los registros de transacción han sido migrados</translation>
<translation type="unfinished">Error: No se migraron todos los registros de transacciones</translation>
</message>
<message>
<source>Error: This wallet already uses SQLite</source>
@@ -4583,15 +4579,15 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Failed to acquire rescan reserver during wallet initialization</source>
<translation type="unfinished">No se pudo adquirir la reserva de reescaneo durante la inicialización del monedero </translation>
<translation type="unfinished">No se pudo adquirir la reserva de reescaneo durante la inicialización del monedero</translation>
</message>
<message>
<source>Failed to close block undo file.</source>
<translation type="unfinished">No se ha podido cerrar el archivo undo</translation>
<translation type="unfinished">No se pudo cerrar el archivo undo de bloques.</translation>
</message>
<message>
<source>Failed to close file when writing block.</source>
<translation type="unfinished">No se ha podido cerrar el archivo mientras se escribía un bloque</translation>
<translation type="unfinished">No se pudo cerrar el archivo al escribir un bloque.</translation>
</message>
<message>
<source>Failed to connect best block (%s).</source>
@@ -4643,7 +4639,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Ignoring duplicate -wallet %s.</source>
<translation type="unfinished">Ignorar duplicación de -wallet %s.</translation>
<translation type="unfinished">Ignorando -wallet %s duplicado.</translation>
</message>
<message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
@@ -4715,7 +4711,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Loading block index</source>
<translation type="unfinished">Cargando índice de bloques...</translation>
<translation type="unfinished">Cargando índice de bloques</translation>
</message>
<message>
<source>Loading wallet</source>
@@ -4851,7 +4847,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>The %s path uses exFAT, which is known to have intermittent corruption problems on macOS. Move this directory to a different filesystem to avoid data loss.</source>
<translation type="unfinished">El %s ruta de acceso usa exFAT, el cual es conocido por tener problemas de corrupción intermitente en macOS. Mueve este directorio a un sistema de ficheros distinto para prevenir perdida de datos.</translation>
<translation type="unfinished">La ruta %s usa exFAT, que se sabe que presenta problemas de corrupción intermitente en macOS. Mueve este directorio a un sistema de archivos distinto para evitar la rdida de datos.</translation>
</message>
<message>
<source>The source code is available from %s.</source>
@@ -4983,19 +4979,19 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
</message>
<message>
<source>Unsupported logging category %s=%s.</source>
<translation type="unfinished">La categoría de registro no es compatible %s=%s. </translation>
<translation type="unfinished">La categoría de registro no es compatible %s=%s.</translation>
</message>
<message>
<source>Error loading %s: Wallet is a legacy wallet. Please migrate to a descriptor wallet using the migration tool (migratewallet RPC).</source>
<translation type="unfinished">Error cargando %s: El monedero es un monedero tipo legacy. Por favor migra a un monedero basado en descriptores usando la herramienta de migrado (migratewallet RPC).</translation>
<translation type="unfinished">Error al cargar %s: El monedero es de tipo legacy. Realiza la migración a un monedero basado en descriptores mediante la herramienta de migración (RPC migratewallet).</translation>
</message>
<message>
<source>Error: Dumpfile specifies an unsupported database format (%s). Only sqlite database dumps are supported</source>
<translation type="unfinished">Error: El archivo de volcado especifica un formato de base de datos no compatible (%s). Sólo se admiten volcados de bases de datos SQLite.</translation>
<translation type="unfinished">Error: El archivo de volcado especifica un formato de base de datos no compatible (%s). Solo se admiten volcados de bases de datos SQLite.</translation>
</message>
<message>
<source>Failed to calculate bump fees, because unconfirmed UTXOs depend on an enormous cluster of unconfirmed transactions.</source>
<translation type="unfinished">No se ha podido calcular la comisión de incremento porque las UTXO sin confirmar dependen de un grupo enorme de transacciones no confirmadas.</translation>
<translation type="unfinished">Las comisiones de incremento no se pudieron calcular, ya que los UTXO sin confirmar dependen de un enorme grupo de transacciones sin confirmar.</translation>
</message>
<message>
<source>Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input</source>
@@ -5007,7 +5003,7 @@ No se puede restaurar la copia de seguridad del monedero.</translation>
The wallet might have been created on a newer version.
Please try running the latest software version.
</source>
<translation type="unfinished">Se encontró un descriptor desconocido. Cargando monedero %s.
<translation type="unfinished">Se encontró un descriptor desconocido. Cargando monedero %s
El monedero se podría haber creado con una versión más reciente.
Intenta ejecutar la última versión del software.
@@ -5035,11 +5031,11 @@ Intenta ejecutar la última versión del software.
</message>
<message>
<source>Failed to start indexes, shutting down…</source>
<translation type="unfinished">Error al iniciar los índices, cerrando...</translation>
<translation type="unfinished">Error al iniciar los índices, cerrando</translation>
</message>
<message>
<source>Invalid -proxy address or hostname, ends with '=': '%s'</source>
<translation type="unfinished">La dirección -proxy o el nombre de host no es válido, acaba con '=':'%s'</translation>
<translation type="unfinished">La dirección -proxy o el nombre de host no son válidos; acaba con "=":"%s"</translation>
</message>
<message>
<source>Not enough file descriptors available. %d available, %d required.</source>
@@ -5047,7 +5043,7 @@ Intenta ejecutar la última versión del software.
</message>
<message>
<source>Unrecognized network in -proxy='%s': '%s'</source>
<translation type="unfinished">Red no reconocida en -proxy:'%s':'%s'</translation>
<translation type="unfinished">Red no reconocida en -proxy="%s": "%s"</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -5059,7 +5055,7 @@ Intenta ejecutar la última versión del software.
</message>
<message>
<source>Verifying wallet(s)</source>
<translation type="unfinished">Verificando monedero(s)...</translation>
<translation type="unfinished">Verificando monedero(s)</translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>

File diff suppressed because it is too large Load Diff

View File

@@ -72,6 +72,9 @@ namespace {
// don't add private key handling cmd's to the history
const QStringList historyFilter = QStringList()
<< "createwallet"
<< "createwalletdescriptor"
<< "migratewallet"
<< "signmessagewithprivkey"
<< "signrawtransactionwithkey"
<< "walletpassphrase"

View File

@@ -15,6 +15,9 @@
#include <QByteArray>
#include <QCompleter>
#include <QMimeData>
#include <QTextDocumentFragment>
#include <QTextEdit>
#include <QThread>
#include <QWidget>
@@ -191,4 +194,20 @@ private Q_SLOTS:
void updateAlerts(const QString& warnings);
};
/**
* A version of QTextEdit that only populates plaintext mime data from a
* selection, this avoids some bad behavior in QT's HTML->Markdown conversion.
*/
class PlainCopyTextEdit : public QTextEdit {
Q_OBJECT
public:
using QTextEdit::QTextEdit;
protected:
QMimeData* createMimeDataFromSelection() const override {
auto md = new QMimeData();
md->setText(textCursor().selection().toPlainText());
return md;
}
};
#endif // BITCOIN_QT_RPCCONSOLE_H

View File

@@ -52,32 +52,78 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &
void TransactionFilterProxy::setDateRange(const std::optional<QDateTime>& from, const std::optional<QDateTime>& to)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
dateFrom = from;
dateTo = to;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setSearchString(const QString &search_string)
{
if (m_search_string == search_string) return;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
m_search_string = search_string;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setTypeFilter(quint32 modes)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->typeFilter = modes;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setMinAmount(const CAmount& minimum)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->minAmount = minimum;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}
void TransactionFilterProxy::setShowInactive(bool _showInactive)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
#endif
this->showInactive = _showInactive;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
endFilterChange(QSortFilterProxyModel::Direction::Rows);
#else
invalidateFilter();
#endif
}

View File

@@ -166,7 +166,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

@@ -936,8 +936,9 @@ static RPCHelpMan submitpackage()
,
{
{"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"
"The package must solely consist of a child transaction and all of its unconfirmed parents, if any. None of the parents may depend on each other.\n"
"The package must be topologically sorted, with the child being the last element in the array.",
"The package must consist of a transaction with (some, all, or none of) its unconfirmed parents. A single transaction is permitted.\n"
"None of the parents may depend on each other. Parents that are already in mempool do not need to be present in the package.\n"
"The package must be topologically sorted, with the child being the last element in the array if there are multiple elements.",
{
{"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
},

View File

@@ -1608,7 +1608,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"},

Some files were not shown because too many files have changed in this diff Show More