Commit Graph

22 Commits

Author SHA1 Message Date
merge-script
142e86a65c Merge bitcoin/bitcoin#35458: qa: Avoid extra tracebacks when exception is raised
472b950b7f qa: Use custom assert_greater_than() over naked assert (Hodlinator)
f42226d526 qa: Silence socket.timeout exception when substituting it for a JSONRPCException (Hodlinator)
659671ac3d qa: Avoid cleanup when exception is raised (Hodlinator)

Pull request description:

  Clean up some cases in which we would trigger multiple tracebacks, which makes it unclear what issue is occuring (https://github.com/bitcoin/bitcoin/issues/31894#issuecomment-4616130031).

  CI log of this occurring: https://github.com/bitcoin/bitcoin/actions/runs/26907239657/job/79375388058?pr=35179

  <details><summary>Relevant log excerpt</summary>

  ```
   test  2026-06-03T19:28:28.119804Z TestFramework.node0 (DEBUG): TestNode.generate() dispatches `generate` call to `generatetoaddress`
   test  2026-06-03T19:28:28.120483Z TestFramework (ERROR): Unexpected exception:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 165, in _get_response
                                         http_response = self.__conn.getresponse()
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/http/client.py", line 1448, in getresponse
                                         response.begin()
                                       File "/usr/lib/python3.12/http/client.py", line 336, in begin
                                         version, status, reason = self._read_status()
                                                                   ^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/http/client.py", line 297, in _read_status
                                         line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/socket.py", line 707, in readinto
                                         return self._sock.recv_into(b)
                                                ^^^^^^^^^^^^^^^^^^^^^^^
                                     TimeoutError: timed out
                                     During handling of the above exception, another exception occurred:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 54, in wrapper
                                         func(self)
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 633, in test_maximal_package_protected
                                         testres = node.testmempoolaccept([large_orphan.serialize().hex()])
                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                         return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                         response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 102, in _request
                                         return self._get_response()
                                                ^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 167, in _get_response
                                         raise JSONRPCException({
                                     test_framework.util.JSONRPCException: 'testmempoolaccept' RPC took longer than 30.000000 seconds. Consider using larger timeout for calls that take longer to return. (-344)  [http_status=None]
                                     During handling of the above exception, another exception occurred:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 143, in main
                                         self.run_test()
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 837, in run_test
                                         self.test_maximal_package_protected()
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 57, in wrapper
                                         self.generate(self.nodes[0], 1)
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 666, in generate
                                         blocks = generator.generate(*args, called_by_framework=True, **kwargs)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 445, in generate
                                         return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries, **kwargs)
                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 453, in generatetoaddress
                                         return self.__getattr__('generatetoaddress')(*args, **kwargs)
                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                         return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                         response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 101, in _request
                                         self.__conn.request(method, path, postdata, headers)
                                       File "/usr/lib/python3.12/http/client.py", line 1356, in request
                                         self._send_request(method, url, body, headers, encode_chunked)
                                       File "/usr/lib/python3.12/http/client.py", line 1367, in _send_request
                                         self.putrequest(method, url, **skips)
                                       File "/usr/lib/python3.12/http/client.py", line 1193, in putrequest
                                         raise CannotSendRequest(self.__state)
                                     http.client.CannotSendRequest: Request-sent
   test  2026-06-03T19:28:28.124908Z TestFramework (DEBUG): Closing down network thread
  ```

  </details>

  Fix in authproxy.py can be verified through applying the below diff with/without PR changes and running `./build/test/functional/p2p_orphan_handling.py`:

  ```diff
  --- a/test/functional/test_framework/authproxy.py
  +++ b/test/functional/test_framework/authproxy.py
  @@ -162,6 +162,8 @@ class AuthServiceProxy():
       def _get_response(self):
           req_start_time = time.time()
           try:
  +            if AuthServiceProxy.__id_count > 55:
  +                raise socket.timeout()
               http_response = self.__conn.getresponse()
           except socket.timeout:
               raise JSONRPCException({
  ```

ACKs for top commit:
  maflcko:
    review ACK 472b950b7f 🔼
  polespinasa:
    reACK 472b950b7f

Tree-SHA512: ec1ede0340da9d1338643980e7f2e4646f0aed2e64f339f8b41a447cbbfb4da8158c1cbcb22f2d0cc383c2dd945075602d02b07a47b33b44cc6215f3292c1d46
2026-06-12 10:51:47 +02:00
Hodlinator
659671ac3d qa: Avoid cleanup when exception is raised
If an exception is raised before we get to cleanup, do not swallow it and attempt to reset the state. Doing so could trigger knock-on exceptions and extra tracebacks.
2026-06-04 10:40:03 +02:00
rkrux
9c1fcaca5c wallet, test: fix sendall anti-fee-sniping when locktime is not specified
This particular test case only needs to ensure that locktime is not
specified in the RPC request, it doesn't need to rely on the wallet optin
RBF default that causes the test to pass coincidentally.

Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
2026-05-29 18:37:17 +05:30
Ava Chow
bcc1dca77b Add psbt_version to PSBT RPCs and default to v2
walletcreatefundedpsbt, createpsbt, converttopsbt, and psbtbumpfee take
a psbt_version argument to set the version of the PSBT that they
produce. The default psbt_version is 2.
2026-04-29 15:04:22 -07:00
MarcoFalke
fa5f297748 scripted-diff: [doc] Unify stale copyright headers
-BEGIN VERIFY SCRIPT-

 sed --in-place --regexp-extended \
   's;( 20[0-2][0-9])(-20[0-2][0-9])? The Bitcoin Core developers;\1-present The Bitcoin Core developers;g' \
   $( git grep -l 'The Bitcoin Core developers' -- ':(exclude)COPYING' ':(exclude)src/ipc/libmultiprocess' ':(exclude)src/minisketch' )

-END VERIFY SCRIPT-
2025-12-16 22:21:15 +01:00
ishaanam
e07e2532b4 test: fix anti-fee-sniping off-by-one error 2025-08-01 15:50:12 -04:00
ishaanam
aac0b6dd79 test: test sendall and send do anti-fee-sniping 2025-06-25 11:56:07 -04:00
Ava Chow
c847dee148 test: remove legacy wallet functional tests
Removes all legacy wallet specific functional tests.

Also removes the --descriptor and --legacy-wallet options as these are
no longer necessary with the legacy wallet removed.
2025-04-23 12:10:30 -07:00
Hennadii Stepanov
a0473442d1 scripted-diff: Add __file__ argument to BitcoinTestFramework.init()
-BEGIN VERIFY SCRIPT-
sed -i -e 's/\s*().main\s*()/(__file__).main()/' $(git ls-files test/functional/*.py)
sed -i -e 's/def __init__(self)/def __init__(self, test_file)/' test/functional/test_framework/test_framework.py
-END VERIFY SCRIPT-
2024-07-16 22:06:47 +01:00
ishaanam
71aae72e1f test: test sendall does ancestor aware funding 2024-05-09 12:49:41 -04:00
ishaanam
544131f3fb rpc, test: test sendall spends unconfirmed change and unconfirmed inputs when specified 2024-02-10 16:38:13 -05:00
Ryan Ofsky
95d7de0964 test: Update python tests to use named parameters instead of options objects 2023-05-03 11:27:51 -05:00
ishaanam
cfe5aebc79 rpc: add minconf and maxconf options to sendall 2023-01-11 17:08:35 -05:00
kdmukai
31fdc54dba test: speed up wallet_fundrawtransaction.py and wallet_sendall.py 2022-12-19 11:12:40 -06:00
Aurèle Oulès
cb44c5923a test: Add sendall test for min-fee setting 2022-12-02 13:30:40 +01:00
MacroFake
555519d082 test: Remove wallet option from non-wallet tests
Review note: The changes are complete, because self.options.descriptors
is set to None in parse_args (test_framework.py).

A value of None implies -disablewallet, see the previous commit.

So if a call to add_wallet_options is missing, it will lead to a test
failure when the wallet is compiled in.
2022-11-10 17:19:13 +01:00
Andrew Chow
315fd4dbab test: Test for out of bounds vout in sendall 2022-10-20 13:25:13 -04:00
Andrew Chow
708b72b715 test: Test that sendall works with watchonly spending specific utxos 2022-10-20 13:21:03 -04:00
kouloumos
cc434cbf58 wallet: fix sendall creates tx that fails tx-size check
The `sendall` RPC doesn't use `CreateTransactionInternal`as the rest of
the wallet RPCs and it never checks against the tx-size mempool limit.
Add a check for tx-size as well as test coverage for that case.
2022-09-15 13:22:19 +03:00
ishaanam
6f8e3818af sendall: check if the maxtxfee has been exceeded 2022-09-13 18:12:42 -04:00
ishaanam
bb84b7145b add tests for no recipient and using send_max while inputs are specified 2022-03-29 16:37:49 -04:00
Murch
49090ec402 Add sendall RPC née sweep
_Motivation_
Currently, the wallet uses a fSubtractFeeAmount (SFFO) flag on the
recipients objects for all forms of sending calls. According to the
commit discussion, this flag was chiefly introduced to permit sweeping
without manually calculating the fees of transactions. However, the flag
leads to unintuitive behavior and makes it more complicated to test
many wallet RPCs exhaustively. We proposed to introduce a dedicated
`sendall` RPC with the intention to cover this functionality.

Since the proposal, it was discovered in further discussion that our
proposed `sendall` rpc and SFFO have subtly different scopes of
operation.
• sendall:
  Use _specific UTXOs_ to pay a destination the remainder after fees.
• SFFO:
  Use a _specific budget_ to pay an address the remainder after fees.

While `sendall` will simplify cases of spending from specific UTXOs,
emptying a wallet, or burning dust, we realized that there are some
cases in which SFFO is used to pay other parties from a limited budget,
which can often lead to the creation of change outputs. This cannot be
easily replicated using `sendall` as it would require manual computation
of the appropriate change amount.

As such, sendall cannot replace all uses of SFFO, but it still has a
different use case and will aid in simplifying some wallet calls and
numerous wallet tests.

_Sendall call details_
The proposed sendall call builds a transaction from a specific subset of
the wallet's UTXO pool (by default all of them) and assigns the funds to
one or more receivers. Receivers can either be specified with a specific
amount or receive an equal share of the remaining unassigned funds. At
least one recipient must be provided without assigned amount to collect
the remainder. The `sendall` call will never create change. The call has
a `send_max` option that changes the default behavior of spending all
UTXOs ("no UTXO left behind"), to maximizing the output amount of the
transaction by skipping uneconomic UTXOs. The `send_max` option is
incompatible with providing a specific set of inputs.
2022-03-29 16:37:47 -04:00