diff options
44 files changed, 625 insertions, 471 deletions
diff --git a/doc/release-notes/release-notes-24.0.1.md b/doc/release-notes/release-notes-24.0.1.md new file mode 100644 index 0000000000..24920ba450 --- /dev/null +++ b/doc/release-notes/release-notes-24.0.1.md @@ -0,0 +1,391 @@ +24.0.1 Release Notes +==================== + +Due to last-minute issues (#26616), 24.0, although tagged, was never fully +announced or released. + +Bitcoin Core version 24.0.1 is now available from: + + <https://bitcoincore.org/bin/bitcoin-core-24.0.1/> + +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 extensively tested on operating systems +using the Linux kernel, macOS 10.15+, and Windows 7 and newer. 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. + +Notice of new option for transaction replacement policies +========================================================= + +This version of Bitcoin Core adds a new `mempoolfullrbf` configuration +option which allows users to change the policy their individual node +will use for relaying and mining unconfirmed transactions. The option +defaults to the same policy that was used in previous releases and no +changes to node policy will occur if everyone uses the default. + +Some Bitcoin services today expect that the first version of an +unconfirmed transaction that they see will be the version of the +transaction that ultimately gets confirmed---a transaction acceptance +policy sometimes called "first-seen". + +The Bitcoin Protocol does not, and cannot, provide any assurance that +the first version of an unconfirmed transaction seen by a particular +node will be the version that gets confirmed. If there are multiple +versions of the same unconfirmed transaction available, only the miner +who includes one of those transactions in a block gets to decide which +version of the transaction gets confirmed. + +Despite this lack of assurance, multiple merchants and services today +still make this assumption. + +There are several benefits to users from removing this *first-seen* +simplification. One key benefit, the ability for the sender of a +transaction to replace it with an alternative version paying higher +fees, was realized in [Bitcoin Core 0.12.0][] (February 2016) with the +introduction of [BIP125][] opt-in Replace By Fee (RBF). + +Since then, there has been discussion about completely removing the +first-seen simplification and allowing users to replace any of their +older unconfirmed transactions with newer transactions, a feature called +*full-RBF*. This release includes a `mempoolfullrbf` configuration +option that allows enabling full-RBF, although it defaults to off +(allowing only opt-in RBF). + +Several alternative node implementations have already enabled full-RBF by +default for years, and several contributors to Bitcoin Core are +advocating for enabling full-RBF by default in a future version of +Bitcoin Core. + +As more nodes that participate in relay and mining begin enabling +full-RBF, replacement of unconfirmed transactions by ones offering higher +fees may rapidly become more reliable. + +Contributors to this project strongly recommend that merchants and services +not accept unconfirmed transactions as final, and if they insist on doing so, +to take the appropriate steps to ensure they have some recourse or plan for +when their assumptions do not hold. + +[Bitcoin Core 0.12.0]: https://bitcoincore.org/en/releases/0.12.0/#opt-in-replace-by-fee-transactions +[bip125]: https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki + +Notable changes +=============== + +P2P and network changes +----------------------- + +- To address a potential denial-of-service, the logic to download headers from peers + has been reworked. This is particularly relevant for nodes starting up for the + first time (or for nodes which are starting up after being offline for a long time). + + Whenever headers are received from a peer that have a total chainwork that is either + less than the node's `-minimumchainwork` value or is sufficiently below the work at + the node's tip, a "presync" phase will begin, in which the node will download the + peer's headers and verify the cumulative work on the peer's chain, prior to storing + those headers permanently. Once that cumulative work is verified to be sufficiently high, + the headers will be redownloaded from that peer and fully validated and stored. + + This may result in initial headers sync taking longer for new nodes starting up for + the first time, both because the headers will be downloaded twice, and because the effect + of a peer disconnecting during the presync phase (or while the node's best headers chain has less + than `-minimumchainwork`), will result in the node needing to use the headers presync mechanism + with the next peer as well (downloading the headers twice, again). (#25717) + +- With I2P connections, a new, transient address is used for each outbound + connection if `-i2pacceptincoming=0`. (#25355) + +Updated RPCs +------------ + +- The `-deprecatedrpc=softforks` configuration option has been removed. The + RPC `getblockchaininfo` no longer returns the `softforks` field, which was + previously deprecated in 23.0. (#23508) Information on soft fork status is + now only available via the `getdeploymentinfo` RPC. + +- The `deprecatedrpc=exclude_coinbase` configuration option has been removed. + The `receivedby` RPCs (`listreceivedbyaddress`, `listreceivedbylabel`, + `getreceivedbyaddress` and `getreceivedbylabel`) now always return results + accounting for received coins from coinbase outputs, without an option to + change that behaviour. Excluding coinbases was previously deprecated in 23.0. + (#25171) + +- The `deprecatedrpc=fees` configuration option has been removed. The top-level + fee fields `fee`, `modifiedfee`, `ancestorfees` and `descendantfees` are no + longer returned by RPCs `getmempoolentry`, `getrawmempool(verbose=true)`, + `getmempoolancestors(verbose=true)` and `getmempooldescendants(verbose=true)`. + The same fee fields can be accessed through the `fees` object in the result. + The top-level fee fields were previously deprecated in 23.0. (#25204) + +- The `getpeerinfo` RPC has been updated with a new `presynced_headers` field, + indicating the progress on the presync phase mentioned in the + "P2P and network changes" section above. + +Changes to wallet related RPCs can be found in the Wallet section below. + +New RPCs +-------- + +- The `sendall` RPC spends specific UTXOs to one or more recipients + without creating change. By default, the `sendall` RPC will spend + every UTXO in the wallet. `sendall` is useful to empty wallets or to + create a changeless payment from select UTXOs. When creating a payment + from a specific amount for which the recipient incurs the transaction + fee, continue to use the `subtractfeefromamount` option via the + `send`, `sendtoaddress`, or `sendmany` RPCs. (#24118) + +- A new `gettxspendingprevout` RPC has been added, which scans the mempool to find + transactions spending any of the given outpoints. (#24408) + +- The `simulaterawtransaction` RPC iterates over the inputs and outputs of the given + transactions, and tallies up the balance change for the given wallet. This can be + useful e.g. when verifying that a coin join like transaction doesn't contain unexpected + inputs that the wallet will then sign for unintentionally. (#22751) + +Updated REST APIs +----------------- + +- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use + a query parameter instead of path parameter to specify the result count. The + count parameter is now optional, and defaults to 5 for both endpoints. The old + endpoints are still functional, and have no documented behaviour change. + + For `/headers`, use + `GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>` + instead of + `GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated) + + For `/blockfilterheaders/`, use + `GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>` + instead of + `GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated) + + (#24098) + +Build System +------------ + +- Guix builds are now reproducible across architectures (x86_64 & aarch64). (#21194) + +New settings +------------ + +- A new `mempoolfullrbf` option has been added, which enables the mempool to + accept transaction replacement without enforcing BIP125 replaceability + signaling. (#25353) + +Wallet +------ + +- The `-walletrbf` startup option will now default to `true`. The + wallet will now default to opt-in RBF on transactions that it creates. (#25610) + +- The `replaceable` option for the `createrawtransaction` and + `createpsbt` RPCs will now default to `true`. Transactions created + with these RPCs will default to having opt-in RBF enabled. (#25610) + +- The `wsh()` output descriptor was extended with Miniscript support. You can import Miniscript + descriptors for P2WSH in a watchonly wallet to track coins, but you can't spend from them using + the Bitcoin Core wallet yet. + You can find more about Miniscript on the [reference website](https://bitcoin.sipa.be/miniscript/). (#24148) + +- The `tr()` output descriptor now supports multisig scripts through the `multi_a()` and + `sortedmulti_a()` functions. (#24043) + +- To help prevent fingerprinting transactions created by the Bitcoin Core wallet, change output + amounts are now randomized. (#24494) + +- The `listtransactions`, `gettransaction`, and `listsinceblock` + RPC methods now include a wtxid field (hash of serialized transaction, + including witness data) for each transaction. (#24198) + +- The `listsinceblock`, `listtransactions` and `gettransaction` output now contain a new + `parent_descs` field for every "receive" entry. (#25504) + +- A new optional `include_change` parameter was added to the `listsinceblock` command. + +- RPC `getreceivedbylabel` now returns an error, "Label not found + in wallet" (-4), if the label is not in the address book. (#25122) + +Migrating Legacy Wallets to Descriptor Wallets +--------------------------------------------- + +An experimental RPC `migratewallet` has been added to migrate Legacy (non-descriptor) wallets to +Descriptor wallets. More information about the migration process is available in the +[documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/managing-wallets.md#migrating-legacy-wallets-to-descriptor-wallets). + +GUI changes +----------- + +- A new menu item to restore a wallet from a backup file has been added (gui#471). + +- Configuration changes made in the bitcoin GUI (such as the pruning setting, +proxy settings, UPNP preferences) are now saved to `<datadir>/settings.json` +file rather than to the Qt settings backend (windows registry or unix desktop +config files), so these settings will now apply to bitcoind, instead of being +ignored. (#15936, gui#602) + +- Also, the interaction between GUI settings and `bitcoin.conf` settings is +simplified. Settings from `bitcoin.conf` are now displayed normally in the GUI +settings dialog, instead of in a separate warning message ("Options set in this +dialog are overridden by the configuration file: -setting=value"). And these +settings can now be edited because `settings.json` values take precedence over +`bitcoin.conf` values. (#15936) + +Low-level changes +================= + +RPC +--- + +- The `deriveaddresses`, `getdescriptorinfo`, `importdescriptors` and `scantxoutset` commands now + accept Miniscript expression within a `wsh()` descriptor. (#24148) + +- The `getaddressinfo`, `decodescript`, `listdescriptors` and `listunspent` commands may now output + a Miniscript descriptor inside a `wsh()` where a `wsh(raw())` descriptor was previously returned. (#24148) + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- /dev/fd0 +- 0xb10c +- Adam Jonas +- akankshakashyap +- Ali Sherief +- amadeuszpawlik +- Andreas Kouloumos +- Andrew Chow +- Anthony Towns +- Antoine Poinsot +- Antoine Riard +- Aurèle Oulès +- avirgovi +- Ayush Sharma +- Baas +- Ben Woosley +- BrokenProgrammer +- brunoerg +- brydinh +- Bushstar +- Calvin Kim +- CAnon +- Carl Dong +- chinggg +- Cory Fields +- Daniel Kraft +- Daniela Brozzoni +- darosior +- Dave Scotese +- David Bakin +- dergoegge +- dhruv +- Dimitri +- dontbyte +- Duncan Dean +- eugene +- Eunoia +- Fabian Jahr +- furszy +- Gleb Naumenko +- glozow +- Greg Weber +- Gregory Sanders +- gruve-p +- Hennadii Stepanov +- hiago +- Igor Bubelov +- ishaanam +- Jacob P. +- Jadi +- James O'Beirne +- Janna +- Jarol Rodriguez +- Jeremy Rand +- Jeremy Rubin +- jessebarton +- João Barbosa +- John Newbery +- Jon Atack +- Josiah Baker +- Karl-Johan Alm +- KevinMusgrave +- Kiminuo +- klementtan +- Kolby Moroz +- kouloumos +- Kristaps Kaupe +- Larry Ruane +- Luke Dashjr +- MarcoFalke +- Marnix +- Martin Leitner-Ankerl +- Martin Zumsande +- Michael Dietz +- Michael Folkson +- Michael Ford +- Murch +- mutatrum +- muxator +- Oskar Mendel +- Pablo Greco +- pasta +- Patrick Strateman +- Pavol Rusnak +- Peter Bushnell +- phyBrackets +- Pieter Wuille +- practicalswift +- randymcmillan +- Robert Spigler +- Russell Yanofsky +- S3RK +- Samer Afach +- Sebastian Falbesoner +- Seibart Nedor +- Shashwat +- Sjors Provoost +- Smlep +- sogoagain +- Stacie +- Stéphan Vuylsteke +- Suhail Saqan +- Suhas Daftuar +- t-bast +- TakeshiMusgrave +- Vasil Dimov +- W. J. van der Laan +- w0xlt +- whiteh0rse +- willcl-ark +- William Casarin +- Yancy Ribbens + +As well as to everyone that helped with translations on +[Transifex](https://www.transifex.com/bitcoin/bitcoin/). diff --git a/doc/release-notes/release-notes-24.0.md b/doc/release-notes/release-notes-24.0.md index a9240567d7..a0227aa17f 100644 --- a/doc/release-notes/release-notes-24.0.md +++ b/doc/release-notes/release-notes-24.0.md @@ -1,388 +1,4 @@ -24.0 Release Notes -================== +Due to last-minute issues (#26616), 24.0, although tagged, was never fully +announced or released. -Bitcoin Core version 24.0 is now available from: - - <https://bitcoincore.org/bin/bitcoin-core-24.0/> - -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 extensively tested on operating systems -using the Linux kernel, macOS 10.15+, and Windows 7 and newer. 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. - -Notice of new option for transaction replacement policies -========================================================= - -This version of Bitcoin Core adds a new `mempoolfullrbf` configuration -option which allows users to change the policy their individual node -will use for relaying and mining unconfirmed transactions. The option -defaults to the same policy that was used in previous releases and no -changes to node policy will occur if everyone uses the default. - -Some Bitcoin services today expect that the first version of an -unconfirmed transaction that they see will be the version of the -transaction that ultimately gets confirmed---a transaction acceptance -policy sometimes called "first-seen". - -The Bitcoin Protocol does not, and cannot, provide any assurance that -the first version of an unconfirmed transaction seen by a particular -node will be the version that gets confirmed. If there are multiple -versions of the same unconfirmed transaction available, only the miner -who includes one of those transactions in a block gets to decide which -version of the transaction gets confirmed. - -Despite this lack of assurance, multiple merchants and services today -still make this assumption. - -There are several benefits to users from removing this *first-seen* -simplification. One key benefit, the ability for the sender of a -transaction to replace it with an alternative version paying higher -fees, was realized in [Bitcoin Core 0.12.0][] (February 2016) with the -introduction of [BIP125][] opt-in Replace By Fee (RBF). - -Since then, there has been discussion about completely removing the -first-seen simplification and allowing users to replace any of their -older unconfirmed transactions with newer transactions, a feature called -*full-RBF*. This release includes a `mempoolfullrbf` configuration -option that allows enabling full-RBF, although it defaults to off -(allowing only opt-in RBF). - -Several alternative node implementations have already enabled full-RBF by -default for years, and several contributors to Bitcoin Core are -advocating for enabling full-RBF by default in a future version of -Bitcoin Core. - -As more nodes that participate in relay and mining begin enabling -full-RBF, replacement of unconfirmed transactions by ones offering higher -fees may rapidly become more reliable. - -Contributors to this project strongly recommend that merchants and services -not accept unconfirmed transactions as final, and if they insist on doing so, -to take the appropriate steps to ensure they have some recourse or plan for -when their assumptions do not hold. - -[Bitcoin Core 0.12.0]: https://bitcoincore.org/en/releases/0.12.0/#opt-in-replace-by-fee-transactions -[bip125]: https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki - -Notable changes -=============== - -P2P and network changes ------------------------ - -- To address a potential denial-of-service, the logic to download headers from peers - has been reworked. This is particularly relevant for nodes starting up for the - first time (or for nodes which are starting up after being offline for a long time). - - Whenever headers are received from a peer that have a total chainwork that is either - less than the node's `-minimumchainwork` value or is sufficiently below the work at - the node's tip, a "presync" phase will begin, in which the node will download the - peer's headers and verify the cumulative work on the peer's chain, prior to storing - those headers permanently. Once that cumulative work is verified to be sufficiently high, - the headers will be redownloaded from that peer and fully validated and stored. - - This may result in initial headers sync taking longer for new nodes starting up for - the first time, both because the headers will be downloaded twice, and because the effect - of a peer disconnecting during the presync phase (or while the node's best headers chain has less - than `-minimumchainwork`), will result in the node needing to use the headers presync mechanism - with the next peer as well (downloading the headers twice, again). (#25717) - -- With I2P connections, a new, transient address is used for each outbound - connection if `-i2pacceptincoming=0`. (#25355) - -Updated RPCs ------------- - -- The `-deprecatedrpc=softforks` configuration option has been removed. The - RPC `getblockchaininfo` no longer returns the `softforks` field, which was - previously deprecated in 23.0. (#23508) Information on soft fork status is - now only available via the `getdeploymentinfo` RPC. - -- The `deprecatedrpc=exclude_coinbase` configuration option has been removed. - The `receivedby` RPCs (`listreceivedbyaddress`, `listreceivedbylabel`, - `getreceivedbyaddress` and `getreceivedbylabel`) now always return results - accounting for received coins from coinbase outputs, without an option to - change that behaviour. Excluding coinbases was previously deprecated in 23.0. - (#25171) - -- The `deprecatedrpc=fees` configuration option has been removed. The top-level - fee fields `fee`, `modifiedfee`, `ancestorfees` and `descendantfees` are no - longer returned by RPCs `getmempoolentry`, `getrawmempool(verbose=true)`, - `getmempoolancestors(verbose=true)` and `getmempooldescendants(verbose=true)`. - The same fee fields can be accessed through the `fees` object in the result. - The top-level fee fields were previously deprecated in 23.0. (#25204) - -- The `getpeerinfo` RPC has been updated with a new `presynced_headers` field, - indicating the progress on the presync phase mentioned in the - "P2P and network changes" section above. - -Changes to wallet related RPCs can be found in the Wallet section below. - -New RPCs --------- - -- The `sendall` RPC spends specific UTXOs to one or more recipients - without creating change. By default, the `sendall` RPC will spend - every UTXO in the wallet. `sendall` is useful to empty wallets or to - create a changeless payment from select UTXOs. When creating a payment - from a specific amount for which the recipient incurs the transaction - fee, continue to use the `subtractfeefromamount` option via the - `send`, `sendtoaddress`, or `sendmany` RPCs. (#24118) - -- A new `gettxspendingprevout` RPC has been added, which scans the mempool to find - transactions spending any of the given outpoints. (#24408) - -- The `simulaterawtransaction` RPC iterates over the inputs and outputs of the given - transactions, and tallies up the balance change for the given wallet. This can be - useful e.g. when verifying that a coin join like transaction doesn't contain unexpected - inputs that the wallet will then sign for unintentionally. (#22751) - -Updated REST APIs ------------------ - -- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use - a query parameter instead of path parameter to specify the result count. The - count parameter is now optional, and defaults to 5 for both endpoints. The old - endpoints are still functional, and have no documented behaviour change. - - For `/headers`, use - `GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>` - instead of - `GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated) - - For `/blockfilterheaders/`, use - `GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>` - instead of - `GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated) - - (#24098) - -Build System ------------- - -- Guix builds are now reproducible across architectures (x86_64 & aarch64). (#21194) - -New settings ------------- - -- A new `mempoolfullrbf` option has been added, which enables the mempool to - accept transaction replacement without enforcing BIP125 replaceability - signaling. (#25353) - -Wallet ------- - -- The `-walletrbf` startup option will now default to `true`. The - wallet will now default to opt-in RBF on transactions that it creates. (#25610) - -- The `replaceable` option for the `createrawtransaction` and - `createpsbt` RPCs will now default to `true`. Transactions created - with these RPCs will default to having opt-in RBF enabled. (#25610) - -- The `wsh()` output descriptor was extended with Miniscript support. You can import Miniscript - descriptors for P2WSH in a watchonly wallet to track coins, but you can't spend from them using - the Bitcoin Core wallet yet. - You can find more about Miniscript on the [reference website](https://bitcoin.sipa.be/miniscript/). (#24148) - -- The `tr()` output descriptor now supports multisig scripts through the `multi_a()` and - `sortedmulti_a()` functions. (#24043) - -- To help prevent fingerprinting transactions created by the Bitcoin Core wallet, change output - amounts are now randomized. (#24494) - -- The `listtransactions`, `gettransaction`, and `listsinceblock` - RPC methods now include a wtxid field (hash of serialized transaction, - including witness data) for each transaction. (#24198) - -- The `listsinceblock`, `listtransactions` and `gettransaction` output now contain a new - `parent_descs` field for every "receive" entry. (#25504) - -- A new optional `include_change` parameter was added to the `listsinceblock` command. - -- RPC `getreceivedbylabel` now returns an error, "Label not found - in wallet" (-4), if the label is not in the address book. (#25122) - -Migrating Legacy Wallets to Descriptor Wallets ---------------------------------------------- - -An experimental RPC `migratewallet` has been added to migrate Legacy (non-descriptor) wallets to -Descriptor wallets. More information about the migration process is available in the -[documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/managing-wallets.md#migrating-legacy-wallets-to-descriptor-wallets). - -GUI changes ------------ - -- A new menu item to restore a wallet from a backup file has been added (gui#471). - -- Configuration changes made in the bitcoin GUI (such as the pruning setting, -proxy settings, UPNP preferences) are now saved to `<datadir>/settings.json` -file rather than to the Qt settings backend (windows registry or unix desktop -config files), so these settings will now apply to bitcoind, instead of being -ignored. (#15936, gui#602) - -- Also, the interaction between GUI settings and `bitcoin.conf` settings is -simplified. Settings from `bitcoin.conf` are now displayed normally in the GUI -settings dialog, instead of in a separate warning message ("Options set in this -dialog are overridden by the configuration file: -setting=value"). And these -settings can now be edited because `settings.json` values take precedence over -`bitcoin.conf` values. (#15936) - -Low-level changes -================= - -RPC ---- - -- The `deriveaddresses`, `getdescriptorinfo`, `importdescriptors` and `scantxoutset` commands now - accept Miniscript expression within a `wsh()` descriptor. (#24148) - -- The `getaddressinfo`, `decodescript`, `listdescriptors` and `listunspent` commands may now output - a Miniscript descriptor inside a `wsh()` where a `wsh(raw())` descriptor was previously returned. (#24148) - -Credits -======= - -Thanks to everyone who directly contributed to this release: - -- /dev/fd0 -- 0xb10c -- Adam Jonas -- akankshakashyap -- Ali Sherief -- amadeuszpawlik -- Andreas Kouloumos -- Andrew Chow -- Anthony Towns -- Antoine Poinsot -- Antoine Riard -- Aurèle Oulès -- avirgovi -- Ayush Sharma -- Baas -- Ben Woosley -- BrokenProgrammer -- brunoerg -- brydinh -- Bushstar -- Calvin Kim -- CAnon -- Carl Dong -- chinggg -- Cory Fields -- Daniel Kraft -- Daniela Brozzoni -- darosior -- Dave Scotese -- David Bakin -- dergoegge -- dhruv -- Dimitri -- dontbyte -- Duncan Dean -- eugene -- Eunoia -- Fabian Jahr -- furszy -- Gleb Naumenko -- glozow -- Greg Weber -- Gregory Sanders -- gruve-p -- Hennadii Stepanov -- hiago -- Igor Bubelov -- ishaanam -- Jacob P. -- Jadi -- James O'Beirne -- Janna -- Jarol Rodriguez -- Jeremy Rand -- Jeremy Rubin -- jessebarton -- João Barbosa -- John Newbery -- Jon Atack -- Josiah Baker -- Karl-Johan Alm -- KevinMusgrave -- Kiminuo -- klementtan -- Kolby Moroz -- kouloumos -- Kristaps Kaupe -- Larry Ruane -- Luke Dashjr -- MarcoFalke -- Marnix -- Martin Leitner-Ankerl -- Martin Zumsande -- Michael Dietz -- Michael Folkson -- Michael Ford -- Murch -- mutatrum -- muxator -- Oskar Mendel -- Pablo Greco -- pasta -- Patrick Strateman -- Pavol Rusnak -- Peter Bushnell -- phyBrackets -- Pieter Wuille -- practicalswift -- randymcmillan -- Robert Spigler -- Russell Yanofsky -- S3RK -- Samer Afach -- Sebastian Falbesoner -- Seibart Nedor -- Shashwat -- Sjors Provoost -- Smlep -- sogoagain -- Stacie -- Stéphan Vuylsteke -- Suhail Saqan -- Suhas Daftuar -- t-bast -- TakeshiMusgrave -- Vasil Dimov -- W. J. van der Laan -- w0xlt -- whiteh0rse -- willcl-ark -- William Casarin -- Yancy Ribbens - -As well as to everyone that helped with translations on -[Transifex](https://www.transifex.com/bitcoin/bitcoin/). +See the release notes for 24.0.1 instead. diff --git a/src/Makefile.am b/src/Makefile.am index 2e2da54b2d..cff194b0fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -177,6 +177,7 @@ BITCOIN_CORE_H = \ kernel/checks.h \ kernel/coinstats.h \ kernel/context.h \ + kernel/mempool_entry.h \ kernel/mempool_limits.h \ kernel/mempool_options.h \ kernel/mempool_persist.h \ @@ -263,7 +264,6 @@ BITCOIN_CORE_H = \ torcontrol.h \ txdb.h \ txmempool.h \ - txmempool_entry.h \ txorphanage.h \ txrequest.h \ undo.h \ diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index 29feb42528..2b133f58f4 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -3,10 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> +#include <kernel/mempool_entry.h> #include <policy/policy.h> #include <test/util/setup_common.h> #include <txmempool.h> -#include <txmempool_entry.h> static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp index 1e40d78aa5..67564508d9 100644 --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -3,10 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> +#include <kernel/mempool_entry.h> #include <policy/policy.h> #include <test/util/setup_common.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <validation.h> #include <vector> diff --git a/src/bench/peer_eviction.cpp b/src/bench/peer_eviction.cpp index c3e3670de7..d83342be93 100644 --- a/src/bench/peer_eviction.cpp +++ b/src/bench/peer_eviction.cpp @@ -40,7 +40,7 @@ static void EvictionProtection0Networks250Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 250 /* num_candidates */, + /*num_candidates=*/250, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_network = NET_IPV4; @@ -51,7 +51,7 @@ static void EvictionProtection1Networks250Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 250 /* num_candidates */, + /*num_candidates=*/250, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_is_local = false; @@ -67,7 +67,7 @@ static void EvictionProtection2Networks250Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 250 /* num_candidates */, + /*num_candidates=*/250, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_is_local = false; @@ -85,7 +85,7 @@ static void EvictionProtection3Networks050Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 50 /* num_candidates */, + /*num_candidates=*/50, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_is_local = (c.id == 28 || c.id == 47); // 2 localhost @@ -103,7 +103,7 @@ static void EvictionProtection3Networks100Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 100 /* num_candidates */, + /*num_candidates=*/100, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_is_local = (c.id >= 55 && c.id < 60); // 5 localhost @@ -121,7 +121,7 @@ static void EvictionProtection3Networks250Candidates(benchmark::Bench& bench) { EvictionProtectionCommon( bench, - 250 /* num_candidates */, + /*num_candidates=*/250, [](NodeEvictionCandidate& c) { c.m_connected = std::chrono::seconds{c.id}; c.m_is_local = (c.id >= 140 && c.id < 160); // 20 localhost diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index 5ae4829d16..6bac6419e5 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -4,10 +4,10 @@ #include <bench/bench.h> #include <chainparamsbase.h> +#include <kernel/mempool_entry.h> #include <rpc/mempool.h> #include <test/util/setup_common.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <univalue.h> diff --git a/src/init.cpp b/src/init.cpp index 2fdc2717c9..f31a45aa9f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1571,7 +1571,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) { - g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /* cache size */ 0, false, fReindex); + g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, fReindex); if (!g_coin_stats_index->Start()) { return false; } diff --git a/src/txmempool_entry.h b/src/kernel/mempool_entry.h index dd71833200..e1ba4296ef 100644 --- a/src/txmempool_entry.h +++ b/src/kernel/mempool_entry.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TXMEMPOOL_ENTRY_H -#define BITCOIN_TXMEMPOOL_ENTRY_H +#ifndef BITCOIN_KERNEL_MEMPOOL_ENTRY_H +#define BITCOIN_KERNEL_MEMPOOL_ENTRY_H #include <consensus/amount.h> #include <consensus/validation.h> @@ -171,4 +171,4 @@ public: mutable Epoch::Marker m_epoch_marker; //!< epoch when last touched, useful for graph algorithms }; -#endif // BITCOIN_TXMEMPOOL_ENTRY_H +#endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp index d7061b89e0..e31ca81a08 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -16,6 +16,7 @@ #include <hash.h> #include <headerssync.h> #include <index/blockfilterindex.h> +#include <kernel/mempool_entry.h> #include <merkleblock.h> #include <netbase.h> #include <netmessagemaker.h> @@ -34,7 +35,6 @@ #include <timedata.h> #include <tinyformat.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <txorphanage.h> #include <txrequest.h> #include <util/check.h> // For NDEBUG compile time check diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 212780b259..c2c9adadbb 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -15,17 +15,18 @@ #include <interfaces/handler.h> #include <interfaces/node.h> #include <interfaces/wallet.h> +#include <kernel/chain.h> +#include <kernel/mempool_entry.h> #include <mapport.h> #include <net.h> #include <net_processing.h> #include <netaddress.h> #include <netbase.h> #include <node/blockstorage.h> -#include <kernel/chain.h> #include <node/coin.h> #include <node/context.h> -#include <node/transaction.h> #include <node/interface_ui.h> +#include <node/transaction.h> #include <policy/feerate.h> #include <policy/fees.h> #include <policy/policy.h> @@ -39,7 +40,6 @@ #include <support/allocators/secure.h> #include <sync.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <uint256.h> #include <univalue.h> #include <util/check.h> diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 899adc70ca..1cd9624000 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -8,6 +8,7 @@ #include <clientversion.h> #include <consensus/amount.h> #include <fs.h> +#include <kernel/mempool_entry.h> #include <logging.h> #include <policy/feerate.h> #include <primitives/transaction.h> @@ -16,7 +17,6 @@ #include <streams.h> #include <sync.h> #include <tinyformat.h> -#include <txmempool_entry.h> #include <uint256.h> #include <util/serfloat.h> #include <util/system.h> diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index 994e13dd56..3a347b41ed 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -5,12 +5,12 @@ #include <policy/rbf.h> #include <consensus/amount.h> +#include <kernel/mempool_entry.h> #include <policy/feerate.h> #include <primitives/transaction.h> #include <sync.h> #include <tinyformat.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <uint256.h> #include <util/moneystr.h> #include <util/rbf.h> diff --git a/src/psbt.h b/src/psbt.h index 37bf142366..b636f0348b 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -875,7 +875,7 @@ struct PSBTOutput throw std::ios_base::failure("Output Taproot tree has a leaf with an invalid leaf version"); } m_tap_tree.push_back(std::make_tuple(depth, leaf_ver, script)); - builder.Add((int)depth, script, (int)leaf_ver, true /* track */); + builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true); } if (!builder.IsComplete()) { throw std::ios_base::failure("Output Taproot tree is malformed"); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index bd9a90a890..3bedbf29d8 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -477,7 +477,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel * nBytes -= 34; // Fee - nPayFee = model->wallet().getMinimumFee(nBytes, m_coin_control, nullptr /* returned_target */, nullptr /* reason */); + nPayFee = model->wallet().getMinimumFee(nBytes, m_coin_control, /*returned_target=*/nullptr, /*reason=*/nullptr); if (nPayAmount > 0) { diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp index 333766ce21..afffae0784 100644 --- a/src/qt/psbtoperationsdialog.cpp +++ b/src/qt/psbtoperationsdialog.cpp @@ -56,7 +56,7 @@ void PSBTOperationsDialog::openWithPSBT(PartiallySignedTransaction psbtx) bool complete = FinalizePSBT(psbtx); // Make sure all existing signatures are fully combined before checking for completeness. if (m_wallet_model) { size_t n_could_sign; - TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, &n_could_sign, m_transaction_data, complete); + TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, &n_could_sign, m_transaction_data, complete); if (err != TransactionError::OK) { showStatus(tr("Failed to load transaction: %1") .arg(QString::fromStdString(TransactionErrorString(err).translated)), @@ -80,7 +80,7 @@ void PSBTOperationsDialog::signTransaction() WalletModel::UnlockContext ctx(m_wallet_model->requestUnlock()); - TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, true /* sign */, true /* bip32derivs */, &n_signed, m_transaction_data, complete); + TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/true, /*bip32derivs=*/true, &n_signed, m_transaction_data, complete); if (err != TransactionError::OK) { showStatus(tr("Failed to sign transaction: %1") @@ -245,7 +245,7 @@ size_t PSBTOperationsDialog::couldSignInputs(const PartiallySignedTransaction &p size_t n_signed; bool complete; - TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, false /* bip32derivs */, &n_signed, m_transaction_data, complete); + TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/false, &n_signed, m_transaction_data, complete); if (err != TransactionError::OK) { return 0; diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp index 6fc7a52435..a5cef9a1bb 100644 --- a/src/qt/test/apptests.cpp +++ b/src/qt/test/apptests.cpp @@ -72,7 +72,7 @@ void AppTests::appTests() qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo"); m_app.parameterSetup(); - QVERIFY(m_app.createOptionsModel(true /* reset settings */)); + QVERIFY(m_app.createOptionsModel(/*resetSettings=*/true)); QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().NetworkIDString())); m_app.setupPlatformStyle(); m_app.createWindow(style.data()); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 846fa519ee..3f582e7cf6 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -79,8 +79,6 @@ int main(int argc, char* argv[]) setenv("QT_QPA_PLATFORM", "minimal", 0 /* overwrite */); #endif - // Don't remove this, it's needed to access - // QApplication:: and QCoreApplication:: in the tests BitcoinApplication app; app.setApplicationName("Bitcoin-Qt-test"); app.createNode(*init); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index b71dfb0e9f..c32525b607 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -210,17 +210,17 @@ void TestGUI(interfaces::Node& node) // Send two transactions, and verify they are added to transaction list. TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); QCOMPARE(transactionTableModel->rowCount({}), 105); - uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, false /* rbf */); - uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, true /* rbf */); + uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false); + uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, /*rbf=*/true); QCOMPARE(transactionTableModel->rowCount({}), 107); QVERIFY(FindTx(*transactionTableModel, txid1).isValid()); QVERIFY(FindTx(*transactionTableModel, txid2).isValid()); // Call bumpfee. Test disabled, canceled, enabled, then failing cases. - BumpFee(transactionView, txid1, true /* expect disabled */, "not BIP 125 replaceable" /* expected error */, false /* cancel */); - BumpFee(transactionView, txid2, false /* expect disabled */, {} /* expected error */, true /* cancel */); - BumpFee(transactionView, txid2, false /* expect disabled */, {} /* expected error */, false /* cancel */); - BumpFee(transactionView, txid2, true /* expect disabled */, "already bumped" /* expected error */, false /* cancel */); + BumpFee(transactionView, txid1, /*expectDisabled=*/true, /*expectError=*/"not BIP 125 replaceable", /*cancel=*/false); + BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true); + BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/false); + BumpFee(transactionView, txid2, /*expectDisabled=*/true, /*expectError=*/"already bumped", /*cancel=*/false); // Check current balance on OverviewPage OverviewPage overviewPage(platformStyle.get()); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index c6f3f5b00c..ed0602594b 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -217,7 +217,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact int nChangePosRet = -1; auto& newTx = transaction.getWtx(); - const auto& res = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired); + const auto& res = m_wallet->createTransaction(vecSend, coinControl, /*sign=*/!wallet().privateKeysDisabled(), nChangePosRet, nFeeRequired); newTx = res ? *res : nullptr; transaction.setTransactionFee(nFeeRequired); if (fSubtractFeeFromAmount && newTx) @@ -258,7 +258,7 @@ void WalletModel::sendCoins(WalletModelTransaction& transaction) } auto& newTx = transaction.getWtx(); - wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm)); + wallet().commitTransaction(newTx, /*value_map=*/{}, std::move(vOrderForm)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << *newTx; @@ -542,7 +542,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash) if (retval == QMessageBox::Save) { PartiallySignedTransaction psbtx(mtx); bool complete = false; - const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, nullptr, psbtx, complete); + const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete); if (err != TransactionError::OK || complete) { QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't draft transaction.")); return false; diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 039a4328e3..7a0c361ae0 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -10,6 +10,7 @@ #include <chainparams.h> #include <core_io.h> #include <fs.h> +#include <kernel/mempool_entry.h> #include <node/mempool_persist_args.h> #include <policy/rbf.h> #include <policy/settings.h> @@ -18,7 +19,6 @@ #include <rpc/server_util.h> #include <rpc/util.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <univalue.h> #include <util/moneystr.h> #include <util/time.h> diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index f57133f75b..80a22ff8ca 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -103,7 +103,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& { UniValue unused_result; if (setDone.insert(pcmd->unique_id).second) - pcmd->actor(jreq, unused_result, true /* last_handler */); + pcmd->actor(jreq, unused_result, /*last_handler=*/true); } catch (const std::exception& e) { diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp index 3788c36455..17c340695f 100644 --- a/src/test/fuzz/policy_estimator.cpp +++ b/src/test/fuzz/policy_estimator.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <kernel/mempool_entry.h> #include <policy/fees.h> #include <policy/fees_args.h> #include <primitives/transaction.h> @@ -11,7 +12,6 @@ #include <test/fuzz/util/mempool.h> #include <test/util/setup_common.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <cstdint> #include <optional> diff --git a/src/test/fuzz/util/mempool.cpp b/src/test/fuzz/util/mempool.cpp index c6a6943603..4baca5ec77 100644 --- a/src/test/fuzz/util/mempool.cpp +++ b/src/test/fuzz/util/mempool.cpp @@ -4,11 +4,11 @@ #include <consensus/amount.h> #include <consensus/consensus.h> +#include <kernel/mempool_entry.h> #include <primitives/transaction.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/util.h> #include <test/fuzz/util/mempool.h> -#include <txmempool_entry.h> #include <cassert> #include <cstdint> diff --git a/src/test/fuzz/util/mempool.h b/src/test/fuzz/util/mempool.h index ada657d970..31b578dc4b 100644 --- a/src/test/fuzz/util/mempool.h +++ b/src/test/fuzz/util/mempool.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_TEST_FUZZ_UTIL_MEMPOOL_H #define BITCOIN_TEST_FUZZ_UTIL_MEMPOOL_H -#include <txmempool_entry.h> +#include <kernel/mempool_entry.h> #include <validation.h> class CTransaction; diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp index 55c2c5108d..e1270a362b 100644 --- a/src/test/sync_tests.cpp +++ b/src/test/sync_tests.cpp @@ -107,12 +107,12 @@ BOOST_AUTO_TEST_CASE(potential_deadlock_detected) #ifdef DEBUG_LOCKORDER BOOST_AUTO_TEST_CASE(double_lock_mutex) { - TestDoubleLock<Mutex>(true /* should throw */); + TestDoubleLock<Mutex>(/*should_throw=*/true); } BOOST_AUTO_TEST_CASE(double_lock_recursive_mutex) { - TestDoubleLock<RecursiveMutex>(false /* should not throw */); + TestDoubleLock<RecursiveMutex>(/*should_throw=*/false); } #endif /* DEBUG_LOCKORDER */ diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index a7ca97222a..c97f400137 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -17,6 +17,7 @@ #include <init.h> #include <init/common.h> #include <interfaces/chain.h> +#include <kernel/mempool_entry.h> #include <net.h> #include <net_processing.h> #include <node/blockstorage.h> @@ -41,7 +42,6 @@ #include <timedata.h> #include <txdb.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <util/strencodings.h> #include <util/string.h> #include <util/thread.h> diff --git a/src/txmempool.h b/src/txmempool.h index d48327e5dc..dd28a84c23 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -20,12 +20,12 @@ #include <coins.h> #include <consensus/amount.h> #include <indirectmap.h> +#include <kernel/mempool_entry.h> #include <policy/feerate.h> #include <policy/packages.h> #include <primitives/transaction.h> #include <random.h> #include <sync.h> -#include <txmempool_entry.h> #include <util/epochguard.h> #include <util/hasher.h> diff --git a/src/validation.cpp b/src/validation.cpp index 8fdb4d0b47..2380c5b925 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -22,6 +22,7 @@ #include <flatfile.h> #include <fs.h> #include <hash.h> +#include <kernel/mempool_entry.h> #include <logging.h> #include <logging/timer.h> #include <node/blockstorage.h> @@ -42,7 +43,6 @@ #include <tinyformat.h> #include <txdb.h> #include <txmempool.h> -#include <txmempool_entry.h> #include <uint256.h> #include <undo.h> #include <util/check.h> // For NDEBUG compile time check diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp index b889d31928..ba1d60fe44 100644 --- a/src/wallet/coinselection.cpp +++ b/src/wallet/coinselection.cpp @@ -5,6 +5,7 @@ #include <wallet/coinselection.h> #include <consensus/amount.h> +#include <consensus/consensus.h> #include <policy/feerate.h> #include <util/check.h> #include <util/system.h> @@ -354,6 +355,10 @@ void OutputGroup::Insert(const COutput& output, size_t ancestors, size_t descend // descendants is the count as seen from the top ancestor, not the descendants as seen from the // coin itself; thus, this value is counted as the max, not the sum m_descendants = std::max(m_descendants, descendants); + + if (output.input_bytes > 0) { + m_weight += output.input_bytes * WITNESS_SCALE_FACTOR; + } } bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const @@ -436,18 +441,25 @@ void SelectionResult::Clear() { m_selected_inputs.clear(); m_waste.reset(); + m_weight = 0; } void SelectionResult::AddInput(const OutputGroup& group) { util::insert(m_selected_inputs, group.m_outputs); m_use_effective = !group.m_subtract_fee_outputs; + + m_weight += group.m_weight; } void SelectionResult::AddInputs(const std::set<COutput>& inputs, bool subtract_fee_outputs) { util::insert(m_selected_inputs, inputs); m_use_effective = !subtract_fee_outputs; + + m_weight += std::accumulate(inputs.cbegin(), inputs.cend(), 0, [](int sum, const auto& coin) { + return sum + std::max(coin.input_bytes, 0) * WITNESS_SCALE_FACTOR; + }); } void SelectionResult::Merge(const SelectionResult& other) @@ -462,6 +474,8 @@ void SelectionResult::Merge(const SelectionResult& other) } util::insert(m_selected_inputs, other.m_selected_inputs); assert(m_selected_inputs.size() == expected_count); + + m_weight += other.m_weight; } const std::set<COutput>& SelectionResult::GetInputSet() const diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h index 2ab4061a9b..ecfc5bfd6b 100644 --- a/src/wallet/coinselection.h +++ b/src/wallet/coinselection.h @@ -6,6 +6,7 @@ #define BITCOIN_WALLET_COINSELECTION_H #include <consensus/amount.h> +#include <consensus/consensus.h> #include <policy/feerate.h> #include <primitives/transaction.h> #include <random.h> @@ -223,6 +224,8 @@ struct OutputGroup /** Indicate that we are subtracting the fee from outputs. * When true, the value that is used for coin selection is the UTXO's real value rather than effective value */ bool m_subtract_fee_outputs{false}; + /** Total weight of the UTXOs in this group. */ + int m_weight{0}; OutputGroup() {} OutputGroup(const CoinSelectionParams& params) : @@ -295,6 +298,8 @@ private: bool m_use_effective{false}; /** The computed waste */ std::optional<CAmount> m_waste; + /** Total weight of the selected inputs */ + int m_weight{0}; public: explicit SelectionResult(const CAmount target, SelectionAlgorithm algo) @@ -353,6 +358,8 @@ public: CAmount GetTarget() const { return m_target; } SelectionAlgorithm GetAlgo() const { return m_algo; } + + int GetWeight() const { return m_weight; } }; std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change); diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp index f7fee443d0..2e46cf5454 100644 --- a/src/wallet/dump.cpp +++ b/src/wallet/dump.cpp @@ -201,7 +201,7 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs:: // dummy chain interface bool ret = true; - std::shared_ptr<CWallet> wallet(new CWallet(nullptr /* chain */, name, gArgs, std::move(database)), WalletToolReleaseWallet); + std::shared_ptr<CWallet> wallet(new CWallet(/*chain=*/nullptr, name, gArgs, std::move(database)), WalletToolReleaseWallet); { LOCK(wallet->cs_wallet); DBErrors load_wallet_ret = wallet->LoadWallet(); diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 3514d018b7..3e442a3f5f 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -84,7 +84,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr CFeeRate GetDiscardRate(const CWallet& wallet) { unsigned int highest_target = wallet.chain().estimateMaxBlocks(); - CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */); + CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, /*conservative=*/false); // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate); // Discard rate must be at least dust relay feerate diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 9cf2b677e6..557c85ab55 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -481,7 +481,7 @@ public: CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; } void remove() override { - RemoveWallet(m_context, m_wallet, false /* load_on_start */); + RemoveWallet(m_context, m_wallet, /*load_on_start=*/false); } bool isLegacy() override { return m_wallet->IsLegacy(); } std::unique_ptr<Handler> handleUnload(UnloadFn fn) override diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp index 1d2d7d2a10..ddf10cae15 100644 --- a/src/wallet/rpc/backup.cpp +++ b/src/wallet/rpc/backup.cpp @@ -184,7 +184,7 @@ RPCHelpMan importprivkey() // Add the wpkh script for this key if possible if (pubkey.IsCompressed()) { - pwallet->ImportScripts({GetScriptForDestination(WitnessV0KeyHash(vchAddress))}, 0 /* timestamp */); + pwallet->ImportScripts({GetScriptForDestination(WitnessV0KeyHash(vchAddress))}, /*timestamp=*/0); } } } @@ -273,19 +273,19 @@ RPCHelpMan importaddress() pwallet->MarkDirty(); - pwallet->ImportScriptPubKeys(strLabel, {GetScriptForDestination(dest)}, false /* have_solving_data */, true /* apply_label */, 1 /* timestamp */); + pwallet->ImportScriptPubKeys(strLabel, {GetScriptForDestination(dest)}, /*have_solving_data=*/false, /*apply_label=*/true, /*timestamp=*/1); } else if (IsHex(request.params[0].get_str())) { std::vector<unsigned char> data(ParseHex(request.params[0].get_str())); CScript redeem_script(data.begin(), data.end()); std::set<CScript> scripts = {redeem_script}; - pwallet->ImportScripts(scripts, 0 /* timestamp */); + pwallet->ImportScripts(scripts, /*timestamp=*/0); if (fP2SH) { scripts.insert(GetScriptForDestination(ScriptHash(redeem_script))); } - pwallet->ImportScriptPubKeys(strLabel, scripts, false /* have_solving_data */, true /* apply_label */, 1 /* timestamp */); + pwallet->ImportScriptPubKeys(strLabel, scripts, /*have_solving_data=*/false, /*apply_label=*/true, /*timestamp=*/1); } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); } @@ -464,9 +464,9 @@ RPCHelpMan importpubkey() pwallet->MarkDirty(); - pwallet->ImportScriptPubKeys(strLabel, script_pub_keys, true /* have_solving_data */, true /* apply_label */, 1 /* timestamp */); + pwallet->ImportScriptPubKeys(strLabel, script_pub_keys, /*have_solving_data=*/true, /*apply_label=*/true, /*timestamp=*/1); - pwallet->ImportPubKeys({pubKey.GetID()}, {{pubKey.GetID(), pubKey}} , {} /* key_origins */, false /* add_keypool */, false /* internal */, 1 /* timestamp */); + pwallet->ImportPubKeys({pubKey.GetID()}, {{pubKey.GetID(), pubKey}} , /*key_origins=*/{}, /*add_keypool=*/false, /*internal=*/false, /*timestamp=*/1); } if (fRescan) { @@ -625,7 +625,7 @@ RPCHelpMan importwallet() pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI } pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI - RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */); + RescanWallet(*pwallet, reserver, nTimeBegin, /*update=*/false); pwallet->MarkDirty(); if (!fGood) @@ -1399,7 +1399,7 @@ RPCHelpMan importmulti() } } if (fRescan && fRunScan && requests.size()) { - int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */); + int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, /*update=*/true); pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true); if (pwallet->IsAbortingRescan()) { @@ -1691,7 +1691,7 @@ RPCHelpMan importdescriptors() // Rescan the blockchain using the lowest timestamp if (rescan) { - int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver, true /* update */); + int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver, /*update=*/true); pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true); if (pwallet->IsAbortingRescan()) { diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index 0fa693e7e7..7ab4044bf5 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -161,7 +161,7 @@ UniValue SendMoney(CWallet& wallet, const CCoinControl &coin_control, std::vecto throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, util::ErrorString(res).original); } const CTransactionRef& tx = res->tx; - wallet.CommitTransaction(tx, std::move(map_value), {} /* orderForm */); + wallet.CommitTransaction(tx, std::move(map_value), /*orderForm=*/{}); if (verbose) { UniValue entry(UniValue::VOBJ); entry.pushKV("txid", tx->GetHash().GetHex()); @@ -1083,7 +1083,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) } else { PartiallySignedTransaction psbtx(mtx); bool complete = false; - const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, false /* sign */, true /* bip32derivs */); + const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true); CHECK_NONFATAL(err == TransactionError::OK); CHECK_NONFATAL(!complete); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp index 3c10b47082..667cd929d1 100644 --- a/src/wallet/rpc/transactions.cpp +++ b/src/wallet/rpc/transactions.cpp @@ -614,7 +614,7 @@ RPCHelpMan listsinceblock() blockId = ParseHashV(request.params[0], "blockhash"); height = int{}; altheight = int{}; - if (!wallet.chain().findCommonAncestor(blockId, wallet.GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) { + if (!wallet.chain().findCommonAncestor(blockId, wallet.GetLastBlockHash(), /*ancestor_out=*/FoundBlock().height(*height), /*block1_out=*/FoundBlock().height(*altheight))) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } } @@ -642,7 +642,7 @@ RPCHelpMan listsinceblock() const CWalletTx& tx = pairWtx.second; if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) { - ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */, /*include_change=*/include_change); + ListTransactions(wallet, tx, 0, true, transactions, filter, /*filter_label=*/nullptr, /*include_change=*/include_change); } } @@ -659,7 +659,7 @@ RPCHelpMan listsinceblock() if (it != wallet.mapWallet.end()) { // We want all transactions regardless of confirmation count to appear here, // even negative confirmation ones, hence the big negative. - ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */, /*include_change=*/include_change); + ListTransactions(wallet, it->second, -100000000, true, removed, filter, /*filter_label=*/nullptr, /*include_change=*/include_change); } } blockId = block.hashPrevBlock; @@ -777,7 +777,7 @@ RPCHelpMan gettransaction() WalletTxToJSON(*pwallet, wtx, entry); UniValue details(UniValue::VARR); - ListTransactions(*pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */); + ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/nullptr); entry.pushKV("details", details); std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags()); diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index c6c6ec0b89..3ced3ebeb5 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -2,9 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <algorithm> #include <consensus/amount.h> #include <consensus/validation.h> #include <interfaces/chain.h> +#include <numeric> #include <policy/policy.h> #include <script/signingprovider.h> #include <util/check.h> @@ -555,14 +557,24 @@ std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, cons results.push_back(*srd_result); } - if (results.size() == 0) { + if (results.empty()) { // No solution found return std::nullopt; } + std::vector<SelectionResult> eligible_results; + std::copy_if(results.begin(), results.end(), std::back_inserter(eligible_results), [coin_selection_params](const SelectionResult& result) { + const auto initWeight{coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR}; + return initWeight + result.GetWeight() <= static_cast<int>(MAX_STANDARD_TX_WEIGHT); + }); + + if (eligible_results.empty()) { + return std::nullopt; + } + // Choose the result with the least waste // If the waste is the same, choose the one which spends more inputs. - auto& best_result = *std::min_element(results.begin(), results.end()); + auto& best_result = *std::min_element(eligible_results.begin(), eligible_results.end()); return best_result; } @@ -651,7 +663,7 @@ std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coi // If partial groups are allowed, relax the requirement of spending OutputGroups (groups // of UTXOs sent to the same address, which are obviously controlled by a single wallet) // in their entirety. - if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */), + if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, /*include_partial=*/true), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) { return r6; } @@ -659,7 +671,7 @@ std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coi // received from other wallets. if (coin_control.m_include_unsafe_inputs) { if (auto r7{AttemptSelection(wallet, value_to_select, - CoinEligibilityFilter(0 /* conf_mine */, 0 /* conf_theirs */, max_ancestors-1, max_descendants-1, true /* include_partial_groups */), + CoinEligibilityFilter(/*conf_mine=*/0, /*conf_theirs=*/0, max_ancestors-1, max_descendants-1, /*include_partial=*/true), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) { return r7; } @@ -669,7 +681,7 @@ std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coi // OutputGroups use heuristics that may overestimate ancestor/descendant counts. if (!fRejectLongChains) { if (auto r8{AttemptSelection(wallet, value_to_select, - CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */), + CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), /*include_partial=*/true), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) { return r8; } @@ -867,19 +879,16 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal( const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size); coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust); + // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size) + coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count + // vouts to the payees - if (!coin_selection_params.m_subtract_fee_outputs) { - coin_selection_params.tx_noinputs_size = 10; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size) - coin_selection_params.tx_noinputs_size += GetSizeOfCompactSize(vecSend.size()); // bytes for output count - } for (const auto& recipient : vecSend) { CTxOut txout(recipient.nAmount, recipient.scriptPubKey); // Include the fee cost for outputs. - if (!coin_selection_params.m_subtract_fee_outputs) { - coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION); - } + coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION); if (IsDust(txout, wallet.chain().relayDustFee())) { return util::Error{_("Transaction amount too small")}; @@ -888,7 +897,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal( } // Include the fees for things that aren't inputs, excluding the change output - const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.tx_noinputs_size); + const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.m_subtract_fee_outputs ? 0 : coin_selection_params.tx_noinputs_size); CAmount selection_target = recipients_sum + not_input_fees; // Fetch manually selected coins diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index c764264cd7..ce875d5442 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -4,6 +4,7 @@ #include <consensus/amount.h> #include <node/context.h> +#include <policy/policy.h> #include <primitives/transaction.h> #include <random.h> #include <test/util/setup_common.h> @@ -930,6 +931,124 @@ BOOST_AUTO_TEST_CASE(effective_value_test) BOOST_CHECK_EQUAL(output5.GetEffectiveValue(), nValue); // The effective value should be equal to the absolute value if input_bytes is -1 } +static std::optional<SelectionResult> select_coins(const CAmount& target, const CoinSelectionParams& cs_params, const CCoinControl& cc, std::function<CoinsResult(CWallet&)> coin_setup, interfaces::Chain* chain, const ArgsManager& args) +{ + std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(chain, "", args, CreateMockWalletDatabase()); + wallet->LoadWallet(); + LOCK(wallet->cs_wallet); + wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); + wallet->SetupDescriptorScriptPubKeyMans(); + + auto available_coins = coin_setup(*wallet); + + const auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params); + if (result) { + const auto signedTxSize = 10 + 34 + 68 * result->GetInputSet().size(); // static header size + output size + inputs size (P2WPKH) + BOOST_CHECK_LE(signedTxSize * WITNESS_SCALE_FACTOR, MAX_STANDARD_TX_WEIGHT); + + BOOST_CHECK_GE(result->GetSelectedValue(), target); + } + return result; +} + +static bool has_coin(const CoinSet& set, CAmount amount) +{ + return std::any_of(set.begin(), set.end(), [&](const auto& coin) { return coin.GetEffectiveValue() == amount; }); +} + +BOOST_AUTO_TEST_CASE(check_max_weight) +{ + const CAmount target = 49.5L * COIN; + CCoinControl cc; + + FastRandomContext rand; + CoinSelectionParams cs_params{ + rand, + /*change_output_size=*/34, + /*change_spend_size=*/68, + /*min_change_target=*/CENT, + /*effective_feerate=*/CFeeRate(0), + /*long_term_feerate=*/CFeeRate(0), + /*discard_feerate=*/CFeeRate(0), + /*tx_noinputs_size=*/10 + 34, // static header size + output size + /*avoid_partial=*/false, + }; + + auto chain{m_node.chain.get()}; + + { + // Scenario 1: + // The actor starts with 1x 50.0 BTC and 1515x 0.033 BTC (~100.0 BTC total) unspent outputs + // Then tries to spend 49.5 BTC + // The 50.0 BTC output should be selected, because the transaction would otherwise be too large + + // Perform selection + + const auto result = select_coins( + target, cs_params, cc, [&](CWallet& wallet) { + CoinsResult available_coins; + for (int j = 0; j < 1515; ++j) { + add_coin(available_coins, wallet, CAmount(0.033 * COIN), CFeeRate(0), 144, false, 0, true); + } + + add_coin(available_coins, wallet, CAmount(50 * COIN), CFeeRate(0), 144, false, 0, true); + return available_coins; + }, + chain, m_args); + + BOOST_CHECK(result); + BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(50 * COIN))); + } + + { + // Scenario 2: + + // The actor starts with 400x 0.0625 BTC and 2000x 0.025 BTC (75.0 BTC total) unspent outputs + // Then tries to spend 49.5 BTC + // A combination of coins should be selected, such that the created transaction is not too large + + // Perform selection + const auto result = select_coins( + target, cs_params, cc, [&](CWallet& wallet) { + CoinsResult available_coins; + for (int j = 0; j < 400; ++j) { + add_coin(available_coins, wallet, CAmount(0.0625 * COIN), CFeeRate(0), 144, false, 0, true); + } + for (int j = 0; j < 2000; ++j) { + add_coin(available_coins, wallet, CAmount(0.025 * COIN), CFeeRate(0), 144, false, 0, true); + } + return available_coins; + }, + chain, m_args); + + BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.0625 * COIN))); + BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.025 * COIN))); + } + + { + // Scenario 3: + + // The actor starts with 1515x 0.033 BTC (49.995 BTC total) unspent outputs + // No results should be returned, because the transaction would be too large + + // Perform selection + const auto result = select_coins( + target, cs_params, cc, [&](CWallet& wallet) { + CoinsResult available_coins; + for (int j = 0; j < 1515; ++j) { + add_coin(available_coins, wallet, CAmount(0.033 * COIN), CFeeRate(0), 144, false, 0, true); + } + return available_coins; + }, + chain, m_args); + + // No results + // 1515 inputs * 68 bytes = 103,020 bytes + // 103,020 bytes * 4 = 412,080 weight, which is above the MAX_STANDARD_TX_WEIGHT of 400,000 + BOOST_CHECK(!result); + } +} + BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test) { // Test that the effective value is used to check whether preset inputs provide sufficient funds when subtract_fee_outputs is not used. diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp index 81a8883f85..40756fedfb 100644 --- a/src/wallet/test/spend_tests.cpp +++ b/src/wallet/test/spend_tests.cpp @@ -26,7 +26,7 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup) // leftover input amount which would have been change to the recipient // instead of the miner. auto check_tx = [&wallet](CAmount leftover_input_amount) { - CRecipient recipient{GetScriptForRawPubKey({}), 50 * COIN - leftover_input_amount, true /* subtract fee */}; + CRecipient recipient{GetScriptForRawPubKey({}), 50 * COIN - leftover_input_amount, /*subtract_fee=*/true}; constexpr int RANDOM_CHANGE_POSITION = -1; CCoinControl coin_control; coin_control.m_feerate.emplace(10000); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 60fdbde71b..0f703b7d00 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -587,7 +587,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup) // returns the coin associated with the change address underneath the // coinbaseKey pubkey, even though the change address has a different // pubkey. - AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */}); + AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, /*subtract_fee=*/false}); { LOCK(wallet->cs_wallet); list = ListCoins(*wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 58ba378f4b..5e8c775b63 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1411,7 +1411,7 @@ void CWallet::blockConnected(const interfaces::BlockInfo& block) m_last_block_processed = block.hash; for (size_t index = 0; index < block.data->vtx.size(); index++) { SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)}); - transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */); + transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK, /*mempool_sequence=*/0); } } @@ -2463,7 +2463,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) util::Result<CTxDestination> CWallet::GetNewDestination(const OutputType type, const std::string label) { LOCK(cs_wallet); - auto spk_man = GetScriptPubKeyMan(type, false /* internal */); + auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false); if (!spk_man) { return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))}; } diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index e991bc0814..9ed2a7c18b 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -58,7 +58,7 @@ static const std::shared_ptr<CWallet> MakeWallet(const std::string& name, const } // dummy chain interface - std::shared_ptr<CWallet> wallet_instance{new CWallet(nullptr /* chain */, name, args, std::move(database)), WalletToolReleaseWallet}; + std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, args, std::move(database)), WalletToolReleaseWallet}; DBErrors load_wallet_ret; try { load_wallet_ret = wallet_instance->LoadWallet(); diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 6874154f35..bf218bfee9 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -987,7 +987,7 @@ class RawTransactionsTest(BitcoinTestFramework): outputs[recipient.getnewaddress()] = 0.1 wallet.sendmany("", outputs) self.generate(self.nodes[0], 10) - assert_raises_rpc_error(-4, "Transaction too large", recipient.fundrawtransaction, rawtx) + assert_raises_rpc_error(-4, "Insufficient funds", recipient.fundrawtransaction, rawtx) self.nodes[0].unloadwallet("large") def test_external_inputs(self): |