-
Notifications
You must be signed in to change notification settings - Fork 1.2k
backport: bitcoin#24836, #25379, #25773, #25957, #25986, #26158, #26294, #26349, #26388, #26404, #26424, #26625, #27350 #7085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
|
…r descriptor wallets 0582932 test: add test for fast rescan using block filters (top-up detection) (Sebastian Falbesoner) ca48a46 rpc: doc: mention rescan speedup using `blockfilterindex=1` in affected wallet RPCs (Sebastian Falbesoner) 3449880 wallet: fast rescan: show log message for every non-skipped block (Sebastian Falbesoner) 935c6c4 wallet: take use of `FastWalletRescanFilter` (Sebastian Falbesoner) 70b3513 wallet: add `FastWalletRescanFilter` class for speeding up rescans (Sebastian Falbesoner) c051026 wallet: add method for retrieving the end range for a ScriptPubKeyMan (Sebastian Falbesoner) 8452791 wallet: support fetching scriptPubKeys with minimum descriptor range index (Sebastian Falbesoner) 088e38d add chain interface methods for using BIP 157 block filters (Sebastian Falbesoner) Pull request description: ## Description This PR is another take of using BIP 157 block filters (enabled by `-blockfilterindex=1`) for faster wallet rescans and is a modern revival of bitcoin#15845. For reviewers new to this topic I can highly recommend to read the corresponding PR review club (https://bitcoincore.reviews/15845). The basic idea is to skip blocks for deeper inspection (i.e. looking at every single tx for matches) if our block filter doesn't match any of the block's spent or created UTXOs are relevant for our wallet. Note that there can be false-positives (see https://bitcoincore.reviews/15845#l-199 for a PR review club discussion about false-positive rates), but no false-negatives, i.e. it is safe to skip blocks if the filter doesn't match; if the filter *does* match even though there are no wallet-relevant txs in the block, no harm is done, only a little more time is spent extra. In contrast to bitcoin#15845, this solution only supports descriptor wallets, which are way more widespread now than back in the time >3 years ago. With that approach, we don't have to ever derive the relevant scriptPubKeys ourselves from keys before populating the filter, and can instead shift the full responsibility to that to the `DescriptorScriptPubKeyMan` which already takes care of that automatically. Compared to legacy wallets, the `IsMine` logic for descriptor wallets is as trivial as checking if a scriptPubKey is included in the ScriptPubKeyMan's set of scriptPubKeys (`m_map_script_pub_keys`): https://github.com/bitcoin/bitcoin/blob/e191fac4f3c37820f0618f72f0a8e8b524531ab8/src/wallet/scriptpubkeyman.cpp#L1703-L1710 One of the unaddressed issues of bitcoin#15845 was that [the filter was only created once outside the loop](bitcoin#15845 (comment)) and as such didn't take into account possible top-ups that have happened. This is solved here by keeping a state of ranged `DescriptorScriptPubKeyMan`'s descriptor end ranges and check at each iteration whether that range has increased since last time. If yes, we update the filter with all scriptPubKeys that have been added since the last filter update with a range index equal or higher than the last end range. Note that finding new scriptPubKeys could be made more efficient than linearly iterating through the whole `m_script_pub_keys` map (e.g. by introducing a bidirectional map), but this would mean introducing additional complexity and state and it's probably not worth it at this time, considering that the performance gain is already significant. Output scripts from non-ranged `DescriptorScriptPubKeyMan`s (i.e. ones with a fixed set of output scripts that is never extended) are added only once when the filter is created first. ## Benchmark results Obviously, the speed-up indirectly correlates with the wallet tx frequency in the scanned range: the more blocks contain wallet-related transactions, the less blocks can be skipped due to block filter detection. In a [simple benchmark](https://github.com/theStack/bitcoin/blob/fast_rescan_functional_test_benchmark/test/functional/pr25957_benchmark.py), a regtest chain with 1008 blocks (corresponding to 1 week) is mined with 20000 scriptPubKeys contained (25 txs * 800 outputs) each. The blocks each have a weight of ~2500000 WUs and hence are about 62.5% full. A global constant `WALLET_TX_BLOCK_FREQUENCY` defines how often wallet-related txs are included in a block. The created descriptor wallet (default setting of `keypool=1000`, we have 8*1000 = 8000 scriptPubKeys at the start) is backuped via the `backupwallet` RPC before the mining starts and imported via `restorewallet` RPC after. The measured time for taking this import process (which involves a rescan) once with block filters (`-blockfilterindex=1`) and once without block filters (`-blockfilterindex=0`) yield the relevant result numbers for the benchmark. The following table lists the results, sorted from worst-case (all blocks contain wallte-relevant txs, 0% can be skipped) to best-case (no blocks contain walltet-relevant txs, 100% can be skipped) where the frequencies have been picked arbitrarily: wallet-related tx frequency; 1 tx per... | ratio of irrelevant blocks | w/o filters | with filters | speed gain --------------------------------------------|-----------------------------|-------------|--------------|------------- ~ 10 minutes (every block) | 0% | 56.806s | 63.554s | ~0.9x ~ 20 minutes (every 2nd block) | 50% (1/2) | 58.896s | 36.076s | ~1.6x ~ 30 minutes (every 3rd block) | 66.67% (2/3) | 56.781s | 25.430s | ~2.2x ~ 1 hour (every 6th block) | 83.33% (5/6) | 58.193s | 15.786s | ~3.7x ~ 6 hours (every 36th block) | 97.22% (35/36) | 57.500s | 6.935s | ~8.3x ~ 1 day (every 144th block) | 99.31% (143/144) | 68.881s | 6.107s | ~11.3x (no txs) | 100% | 58.529s | 5.630s | ~10.4x Since even the (rather unrealistic) worst-case scenario of having wallet-related txs in _every_ block of the rescan range obviously doesn't take significantly longer, I'd argue it's reasonable to always take advantage of block filters if they are available and there's no need to provide an option for the user. Feedback about the general approach (but also about details like naming, where I struggled a lot) would be greatly appreciated. Thanks fly out to furszy for discussing this subject and patiently answering basic question about descriptor wallets! ACKs for top commit: achow101: ACK 0582932 Sjors: re-utACK 0582932 aureleoules: ACK 0582932 - minor changes, documentation and updated test since last review w0xlt: re-ACK bitcoin@0582932 Tree-SHA512: 3289ba6e4572726e915d19f3e8b251d12a4cec8c96d041589956c484b5575e3708b14f6e1e121b05fe98aff1c8724de4564a5a9123f876967d33343cbef242e1
…mework BACKPORT NOTE: missing changes are in: - src/bench/addrman.cpp - src/bench/verify_script.cpp - src/bench/chacha_poly_aead.cpp - src/bench/descriptors.cpp - src/bench/chacha20.cpp - src/bench/crypto_hash.cpp But backport is not partial because adding these files without these changes will cause compilation error 3e9d0be build: only run high priority benchmarks in 'make check' (furszy) 466b54b bench: surround main() execution with try/catch (furszy) 3da7cd2 bench: explicitly make all current benchmarks "high" priority (furszy) 05b8c76 bench: add "priority level" to the benchmark framework (furszy) f159378 bench: place benchmark implementation inside benchmark namespace (furszy) Pull request description: This is from today's meeting, a simple "priority level" for the benchmark framework. Will allow us to run certain benchmarks while skip non-prioritized ones in `make check`. By default, `bench_bitcoin` will run all the benchmarks. `make check`will only run the high priority ones, and have marked all the existent benchmarks as "high priority" to retain the current behavior. Could test it by modifying any benchmark priority to something different from "high", and run `bench_bitcoin -priority-level=high` and/or `bench_bitcoin -priority-level=medium,low` (the first command will skip the modified bench while the second one will include it). Note: the second commit could be avoided by having a default arg value for the priority level but.. an explicit set in every `BENCHMARK` macro call makes it less error-prone. ACKs for top commit: kouloumos: re-ACK 3e9d0be achow101: ACK 3e9d0be theStack: re-ACK 3e9d0be stickies-v: re-ACK bitcoin@3e9d0be Tree-SHA512: ece59bf424c5fc1db335f84caa507476fb8ad8c6151880f1f8289562e17023aae5b5e7de03e8cbba6337bf09215f9be331e9ef51c791c43bce43f7446813b054 fixup bench
…cOS native" task da16893 ci: Use `macos-ventura-xcode:14.1` image for "macOS native" task (Hennadii Stepanov) 7028365 ci: Make `getopt` path architecture agnostic (Hennadii Stepanov) Pull request description: The "macOS native" CI task always uses the recent OS image. This PR updates it up to the recent macOS release. Cirrus Labs [stopped](bitcoin#25160 (comment)) updating macOS images for `x86_64`, therefore, an `arm64` image been used. Also `make test-security-check` has been dropped as it ["isn't even expected to pass"](bitcoin#26386 (comment)) on `arm64` in CI. ACKs for top commit: Sjors: utACK da16893 Tree-SHA512: 36785d33b7f11b3cdbc53bcfbf97d88bf821fad248c825982dd9f8e3413809a4ef11190eaf950e60fdf479b62ff66920c35d9ea42d534723f015742eec7e19b6
…tions, sinceblock}` response eb679a7 rpc: make `address` field optional (w0xlt) Pull request description: Close bitcoin#26338. This PR makes optional the `address` field in the response of `listtransactions` and `listsinceblock` RPC. And adds two tests that fail on master, but not on this branch. ACKs for top commit: achow101: ACK eb679a7 aureleoules: ACK eb679a7 Tree-SHA512: b267439626e2ec3134ae790c849949a4c40ef0cebd20092e8187be3db0a61941b2da10bbbba92ca880b8369f46c1aaa806d057eaa5159325f65cbec7cb33c52f
…ompeer.py 8a9f1e4 test: fix intermittent failure in rpc_getblockfrompeer.py (Martin Zumsande) Pull request description: Fixes an intermittent failure in `rpc_getblockfrompeer.py` observed in https://cirrus-ci.com/task/6610115527704576 by adding a sync to make sure the node has processed the header we sent it before we query it for the corresponding block. Fixes bitcoin#26412 ACKs for top commit: jonatack: ACK 8a9f1e4 Tree-SHA512: f6188ab3cfd863034e44e9806d0d99a8781462bec94141501aefc71589153481ffb144e126326ab81807c2b2c93de7f4aac5d09dbcf26c4512a176e06fc6e5f8
0f38524 doc: correct deriveaddresses RPC name (Bitcoin Hodler) Pull request description: There never was a `deriveaddress` RPC, from what I can tell. It was always called `deriveaddresses` (plural). ACKs for top commit: theStack: ACK 0f38524 Zero-1729: ACK 0f38524 Tree-SHA512: 3f405f5479a0d39cf150fd80b4d854ffe4eef718a358202c619e34a08d98c1252b82fc70d106cdf2215dc5a50c6f6cd5e26fe7ed87156f6b08f8e97d963affb7
3a0b352 refactor: move url.h/cpp from lib util to lib common (fanquake) 058eb69 build: add missing event cflags to libbitcoin_util (fanquake) Pull request description: Move `util/url` to `common/url`. Also add missing `event_*` flags to `libbitcoin_util`. bitcoin#26293 + the commit dropping boost cppflags from `libbitcoin_util` shows this issue. i.e: ```bash CXX util/libbitcoin_util_a-url.o util/url.cpp:7:10: fatal error: 'event2/http.h' file not found #include <event2/http.h> ^~~~~~~~~~~~~~~ 1 error generated. ``` ACKs for top commit: hebasto: ACK 3a0b352 ryanofsky: Code review ACK 3a0b352 Tree-SHA512: 600a76fd334267a02d332df9b67891a38d3fd7f5baf8a82b2447879b3bc65eab2552d2c081c0a5f1ec927bf80df7fc1f0cbbdda4cb76994b46dadf260b8e1cb3
e866f0d [functional test] submitrawpackage RPC (glozow) fa07651 [rpc] add new submitpackage RPC (glozow) Pull request description: It would be nice for LN/wallet/app devs to test out package policy, package RBF, etc., but the only interface to do so right now is through unit tests. This PR adds a `-regtest` only RPC interface so people can test by submitting raw transaction data. It is regtest-only, as it would be unsafe/confusing to create an actual mainnet interface while package relay doesn't exist. Note that the functional tests are there to ensure the RPC interface is working properly; they aren't for testing policy itself. See src/test/txpackage_tests.cpp. ACKs for top commit: t-bast: Tested ACK against eclair bitcoin@e866f0d ariard: Code Review ACK e866f0d instagibbs: code review ACK e866f0d Tree-SHA512: 824a26b10d2240e0fd85e5dd25bf499ee3dd9ba8ef4f522533998fcf767ddded9f001f7a005fe3ab07ec95e696448484e26599803e6034ed2733125c8c376c84
…_limits.py tests f2f6068 test: MiniWallet: add `send_self_transfer_chain` to create chain of txns (Andreas Kouloumos) 1d6b438 test: use MiniWallet to simplify mempool_package_limits.py tests (Andreas Kouloumos) Pull request description: While `wallet.py` includes the MiniWallet class and some helper methods, it also includes some methods that have been moved there without having any direct relation with the MiniWallet class. Specifically `make_chain`, `create_child_with_parents` and `create_raw_chain` methods that were extracted from `rpc_packages.py` at f8253d6 in order to be used on both `mempool_package_limits.py` and `rpc_packages.py`. Since that change, due to the introduction of additional methods in MiniWallet, the functionality of those methods can now be replicated with the existing MiniWallet methods and simultaneously simplify those tests by using the MiniWallet. This PR's goals are - to simplify the `mempool_package_limits.py` functional tests with usage of the MiniWallet. - to make progress towards the removal of the `make_chain`, `create_child_with_parents` and `create_raw_chain` methods of `wallet.py`. For the purpose of the aforementioned goals, a helper method `MiniWallet.send_self_transfer_chain` is introduced and method `bulk_transaction` has been integrated in `create_self_transfer*` methods using an optional `target_weight` option. ACKs for top commit: MarcoFalke: ACK f2f6068 👜 Tree-SHA512: 3ddfa0046168cbf7904ec6b1ca233b3fdd4f30db6aefae108b6d7fb69f34ef6fb2cf4fa7cef9473ce1434a0cc8149d236441a685352fef35359a2b7ba0d951eb
Otherwise this error appears:
test_framework.authproxy.JSONRPCException: min relay fee not met, 25500 < 30332 (-26)
fa2537c test: Target exact weight in MiniWallet _bulk_tx (MacroFake) Pull request description: Seems better to target the exact weight than a weight that is up to more than 2000 WU larger. Also, replace a broad `-acceptnonstdtxn=1` with `-datacarriersize=100000` to document the test assumptions better. ACKs for top commit: theStack: Code-review ACK fa2537c Tree-SHA512: cf02c3082a13195b8aa730866aeaf2575ce01974ae2b0244739d8cfc12e60c66312729ed703bb3214651744166a3b560bfaa8dc302ef46ed79fc4d1fe7fcc214
…let` 17cad44 test: refactor `RPCPackagesTest` to use `MiniWallet` (w0xlt) Pull request description: This PR refactors `RPCPackagesTest` to use `MiniWallet` and removes `create_child_with_parents`, `make_chain`, and `create_raw_chain` from `test_framework/wallet`, as requested in bitcoin#25965. Close bitcoin#25965. ACKs for top commit: glozow: ACK 17cad44 pablomartin4btc: tested ACK 17cad44; went thru all changes and recommendations from @kouloumos & @glozow; also went up to bitcoin#20833 to get a bit of background of the origin and purpose of these tests. kouloumos: ACK 17cad44 Tree-SHA512: 9228c532afaecedd577019dbc56f8749046d66f904dd69eb23e7ca3d7806e2132d90af29be276c7635fefb37ef348ae781eb3b225cd6741b20300e6f381041c3
fa6b402 test: Run mempool_packages.py with MiniWallet (MarcoFalke) fa448c2 test: Return fee from MiniWallet (MarcoFalke) faec09f test: Return chain of MiniWallet txs from MiniWallet chain method (MarcoFalke) faa12d4 test: Refactor MiniWallet sign_tx (MarcoFalke) fa2d821 test: Return wtxid from create_self_transfer_multi (MarcoFalke) Pull request description: This allows to run the test even when no wallet is compiled in. Also, it is a lot nicer to read now. ACKs for top commit: glozow: reACK fa6b402 Tree-SHA512: de0338068fd51db01d64ce270f94fd2982a63a6de597325cd1e1f11127e9075bd4aeacace0ed76d09a2db8b962b27237cf11edb4c1fe1a01134d397f8a11bd05
…subtests via decorator e669833 test: dedup package limit checks via decorator in mempool_package_limits.py (Sebastian Falbesoner) 72f25e2 test: refactor: use Satoshis for fees in mempool_package_limits.py (Sebastian Falbesoner) Pull request description: The subtests in the functional test mempool_package_limits.py all follow the same pattern: 1. first, check that the mempool is currently empty 2. create and submit certain single txs to the mempool, prepare list of hex transactions 3. check that `testmempoolaccept` on the package hex fails with a "package-mempool-limits" error on each tx result 4. after mining a block, check that submitting the package succeeds Note that steps 1,3,4 are identical for each of the subtests and only step 2 varies, so this might be a nice opportunity to deduplicate code by using a newly introduced decorator which executes the necessary before and after the essential part of the subtest. This also makes it easier to add new subtests without having to copy-paste those parts once again. In addition, the first commit switches the fee unit from BTC to Satoshis, which allows to get rid of some imports (`COIN` and `Decimal`) and a comment for the `test_desc_size_limits` subtest is fixed (s/25KvB/21KvB/). ACKs for top commit: ismaelsadeeq: ACK e669833 glozow: utACK e669833 Tree-SHA512: 84a85e739de7387391c13bd46aeb015a74302ea7c6f0ca3d4e2b1b487d38df390dc118eb5b1c11d3e4206bff316a4dab60ef6b25d8feced672345d4e36ffd205
WalkthroughThis pull request introduces block filter-based wallet fast rescanning, a new Sequence Diagram(s)sequenceDiagram
participant Node as Node/Wallet
participant ChainImpl as ChainImpl
participant FilterIdx as BlockFilterIndex
participant Filter as GCSFilter
Note over Node,Filter: Block Filter Matching Request
Node->>ChainImpl: blockFilterMatchesAny(filter_type, block_hash, element_set)
ChainImpl->>FilterIdx: GetBlockFilterIndex(filter_type)
alt Index exists
FilterIdx-->>ChainImpl: BlockFilterIndex instance
ChainImpl->>ChainImpl: LookupFilter(block_hash)
alt Filter found
ChainImpl->>Filter: MatchAny(element_set)
Filter-->>ChainImpl: bool (match result)
ChainImpl-->>Node: std::optional<bool> (match result)
else Filter not found
ChainImpl-->>Node: std::nullopt
end
else Index not available
FilterIdx-->>ChainImpl: nullptr
ChainImpl-->>Node: std::nullopt
end
sequenceDiagram
participant Wallet as Wallet::Rescan
participant BlockFilter as FastWalletRescanFilter
participant ChainImpl as ChainImpl
participant Node as Node/Block
Note over Wallet,Node: Fast Rescan with Block Filters (Descriptor Wallet)
Wallet->>BlockFilter: Create (from all DescriptorScriptPubKeyMans)
BlockFilter-->>BlockFilter: Build GCS filter set
loop For each block in range
Wallet->>BlockFilter: UpdateIfNeeded() [detect descriptor top-ups]
Wallet->>BlockFilter: MatchesBlock(block_hash)
alt Filter indicates match
BlockFilter-->>Wallet: true
Wallet->>Node: Fetch and inspect block
Node-->>Wallet: Block data & transactions
Wallet->>Wallet: Process transactions
else Filter indicates no match
BlockFilter-->>Wallet: false
Wallet->>Wallet: Skip block (update scan state only)
else Filter cannot determine (nullopt)
BlockFilter-->>Wallet: std::nullopt
Wallet->>Wallet: Log warning, inspect block as fallback
end
end
Wallet-->>Wallet: Rescan complete (fast or slow variant logged)
sequenceDiagram
participant RPC as submitpackage RPC
participant Mempool as Mempool
participant Validation as Validation
participant Net as Network
Note over RPC,Net: submitpackage RPC Execution
RPC->>RPC: Decode hex transactions array
RPC->>Validation: Parse & validate each transaction
loop For each transaction
alt Valid
Validation-->>RPC: Transaction object
else Invalid
Validation-->>RPC: Error (rejected)
RPC->>RPC: Record failure with reason
end
end
RPC->>Mempool: Process package through mempool
alt Package policy valid
Mempool->>Validation: Validate individual transactions
loop For each tx in package
alt Accepted
Mempool-->>RPC: txid, size, fees
Net->>Net: Broadcast transaction
else Rejected
Mempool-->>RPC: Failure reason
end
end
RPC-->>RPC: Return per-tx results with package-feerate
else Package policy invalid
Mempool-->>RPC: Package error
RPC-->>RPC: Return error response
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Fix all issues with AI Agents 🤖
In @test/functional/mempool_packages.py:
- Around line 231-239: The comparison currently uses identity instead of
equality: replace the identity check `if utxo['txid'] is parent_transaction`
with an equality check against the txid string (i.e., compare utxo['txid'] ==
parent_transaction) so tx_children is populated reliably when the utxo txid
matches parent_transaction; update the condition in the loop that builds
chain/tx_children accordingly.
In @test/functional/rpc_packages.py:
- Around line 268-293: In test_submit_child_with_parents, replace uses of the
internal integer tx.hash with the hex txid string package_txn["txid"]: change
the loop membership check and lookup against submitpackage_result["tx-results"]
to use package_txn["txid"] (both the assert and tx_result assignment), and
change the peer.wait_for_broadcast call to pass a list of package_txn["txid"]
strings instead of tx["tx"].hash so wait_for_broadcast receives hex txid
strings.
- Around line 295-323: In test_submit_cpfp the child transaction is being
referenced by tx_child["tx"].hash and wait_for_broadcast is passed integer
hashes, which is inconsistent with the parent lookups (tx_rich/tx_poor using
"txid") and P2PTxInvStore API; change the child lookup to use
submitpackage_result["tx-results"][tx_child["txid"]] and pass txid strings to
peer.wait_for_broadcast by using [tx["txid"] for tx in package_txns] so all
indexing and broadcast checking consistently use txid strings (update references
to tx_child, package_txns, submitpackage_result, and peer.wait_for_broadcast
accordingly).
🧹 Nitpick comments (4)
test/functional/wallet_listsinceblock.py (1)
404-416: Consider usingnext()for safer list filtering.The test logic correctly verifies that OP_RETURN outputs don't include an address field. However, the list comprehension with
[0]indexing could raiseIndexErrorif no matching transaction is found.🔎 Safer alternative using next()
- op_ret_tx = [tx for tx in self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"] if tx['txid'] == tx_id][0] + op_ret_tx = next(tx for tx in self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"] if tx['txid'] == tx_id)This will raise
StopIterationwith a clearer error message if the transaction isn't found, or you can provide a default value:op_ret_tx = next((tx for tx in self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"] if tx['txid'] == tx_id), None) assert op_ret_tx is not None, "Transaction not found"test/functional/wallet_listtransactions.py (1)
170-179: Consider usingnext()for safer list filtering.The test correctly verifies that OP_RETURN outputs don't include an address field in
listtransactions. However, using[0]on the filtered list could raiseIndexErrorif no matching transaction is found.🔎 Safer alternative using next()
- op_ret_tx = [tx for tx in self.nodes[0].listtransactions() if tx['txid'] == tx_id][0] + op_ret_tx = next(tx for tx in self.nodes[0].listtransactions() if tx['txid'] == tx_id)This will raise
StopIterationwith a clearer error message if the transaction isn't found, or you can provide a default value with explicit error handling:op_ret_tx = next((tx for tx in self.nodes[0].listtransactions() if tx['txid'] == tx_id), None) assert op_ret_tx is not None, "Transaction not found in listtransactions"test/functional/wallet_fast_rescan.py (2)
47-47: Replaceprint()withself.log.info()for consistency.This appears to be leftover debug output. All other logging in this test uses
self.log.info().🔎 Proposed fix
- print(w.importdescriptors([{"desc": descsum_create(f"wpkh({fixed_key.privkey})"), "timestamp": "now"}])) + self.log.info(w.importdescriptors([{"desc": descsum_create(f"wpkh({fixed_key.privkey})"), "timestamp": "now"}]))
52-52: Remove extraneous f-string prefix.Static analysis correctly identifies this f-string has no placeholders. This is a minor style issue.
🔎 Proposed fix
- self.log.info(f"Create txs sending to end range address of each descriptor, triggering top-ups") + self.log.info("Create txs sending to end range address of each descriptor, triggering top-ups")
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (81)
ci/dash/lint-tidy.shci/test/00_setup_env_mac_native_arm64.shci/test/04_install.shdoc/descriptors.mdsrc/Makefile.amsrc/bench/addrman.cppsrc/bench/base58.cppsrc/bench/bech32.cppsrc/bench/bench.hsrc/bench/bip324_ecdh.cppsrc/bench/block_assemble.cppsrc/bench/bls.cppsrc/bench/bls_dkg.cppsrc/bench/bls_pubkey_agg.cppsrc/bench/ccoins_caching.cppsrc/bench/chacha20.cppsrc/bench/checkblock.cppsrc/bench/checkqueue.cppsrc/bench/coin_selection.cppsrc/bench/crypto_hash.cppsrc/bench/duplicate_inputs.cppsrc/bench/ecdsa.cppsrc/bench/ellswift.cppsrc/bench/examples.cppsrc/bench/gcs_filter.cppsrc/bench/hashpadding.cppsrc/bench/load_external.cppsrc/bench/lockedpool.cppsrc/bench/logging.cppsrc/bench/mempool_eviction.cppsrc/bench/mempool_stress.cppsrc/bench/merkle_root.cppsrc/bench/peer_eviction.cppsrc/bench/poly1305.cppsrc/bench/pool.cppsrc/bench/pow_hash.cppsrc/bench/prevector.cppsrc/bench/rollingbloom.cppsrc/bench/rpc_blockchain.cppsrc/bench/rpc_mempool.cppsrc/bench/strencodings.cppsrc/bench/string_cast.cppsrc/bench/util_time.cppsrc/bench/verify_script.cppsrc/bench/wallet_balance.cppsrc/bench/wallet_create.cppsrc/bench/wallet_loading.cppsrc/bitcoin-cli.cppsrc/bitcoin-wallet.cppsrc/bitcoind.cppsrc/common/url.cppsrc/common/url.hsrc/interfaces/chain.hsrc/logging.cppsrc/logging.hsrc/node/interfaces.cppsrc/qt/main.cppsrc/rpc/client.cppsrc/rpc/mempool.cppsrc/test/fuzz/rpc.cppsrc/test/fuzz/string.cppsrc/test/util/setup_common.cppsrc/util/error.cppsrc/util/error.hsrc/wallet/rpc/backup.cppsrc/wallet/rpc/transactions.cppsrc/wallet/rpc/util.cppsrc/wallet/rpc/wallet.cppsrc/wallet/scriptpubkeyman.cppsrc/wallet/scriptpubkeyman.hsrc/wallet/wallet.cpptest/functional/mempool_package_limits.pytest/functional/mempool_packages.pytest/functional/rpc_getblockfrompeer.pytest/functional/rpc_packages.pytest/functional/test_framework/util.pytest/functional/test_framework/wallet.pytest/functional/test_runner.pytest/functional/wallet_fast_rescan.pytest/functional/wallet_listsinceblock.pytest/functional/wallet_listtransactions.py
💤 Files with no reviewable changes (1)
- test/functional/test_framework/util.py
🧰 Additional context used
📓 Path-based instructions (8)
src/**/*.{cpp,h,hpp,cc}
📄 CodeRabbit inference engine (CLAUDE.md)
Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Files:
src/wallet/rpc/util.cppsrc/bench/strencodings.cppsrc/bench/bip324_ecdh.cppsrc/bench/coin_selection.cppsrc/bench/hashpadding.cppsrc/bench/mempool_stress.cppsrc/bench/merkle_root.cppsrc/bench/bls_pubkey_agg.cppsrc/common/url.hsrc/wallet/scriptpubkeyman.hsrc/bench/pool.cppsrc/bench/wallet_create.cppsrc/bench/duplicate_inputs.cppsrc/bench/rollingbloom.cppsrc/wallet/rpc/backup.cppsrc/util/error.cppsrc/bench/gcs_filter.cppsrc/bench/load_external.cppsrc/bench/logging.cppsrc/bench/checkqueue.cppsrc/test/fuzz/rpc.cppsrc/bench/addrman.cppsrc/bench/rpc_blockchain.cppsrc/util/error.hsrc/bench/checkblock.cppsrc/bench/ecdsa.cppsrc/bench/mempool_eviction.cppsrc/bench/bench.hsrc/bench/ccoins_caching.cppsrc/interfaces/chain.hsrc/bench/pow_hash.cppsrc/bench/wallet_loading.cppsrc/bench/examples.cppsrc/bench/bls_dkg.cppsrc/bench/chacha20.cppsrc/bench/string_cast.cppsrc/logging.hsrc/bench/base58.cppsrc/wallet/rpc/wallet.cppsrc/bench/bls.cppsrc/bench/poly1305.cppsrc/bench/util_time.cppsrc/bitcoin-wallet.cppsrc/bench/lockedpool.cppsrc/wallet/wallet.cppsrc/logging.cppsrc/wallet/rpc/transactions.cppsrc/bench/rpc_mempool.cppsrc/bench/wallet_balance.cppsrc/test/fuzz/string.cppsrc/bitcoin-cli.cppsrc/node/interfaces.cppsrc/wallet/scriptpubkeyman.cppsrc/bench/block_assemble.cppsrc/bitcoind.cppsrc/bench/ellswift.cppsrc/rpc/client.cppsrc/common/url.cppsrc/bench/prevector.cppsrc/bench/verify_script.cppsrc/bench/crypto_hash.cppsrc/bench/bech32.cppsrc/bench/peer_eviction.cppsrc/rpc/mempool.cppsrc/qt/main.cppsrc/test/util/setup_common.cpp
src/wallet/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Wallet implementation must use Berkeley DB and SQLite
Files:
src/wallet/rpc/util.cppsrc/wallet/scriptpubkeyman.hsrc/wallet/rpc/backup.cppsrc/wallet/rpc/wallet.cppsrc/wallet/wallet.cppsrc/wallet/rpc/transactions.cppsrc/wallet/scriptpubkeyman.cpp
src/bench/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Performance benchmarks in src/bench/ must use the nanobench library
Files:
src/bench/strencodings.cppsrc/bench/bip324_ecdh.cppsrc/bench/coin_selection.cppsrc/bench/hashpadding.cppsrc/bench/mempool_stress.cppsrc/bench/merkle_root.cppsrc/bench/bls_pubkey_agg.cppsrc/bench/pool.cppsrc/bench/wallet_create.cppsrc/bench/duplicate_inputs.cppsrc/bench/rollingbloom.cppsrc/bench/gcs_filter.cppsrc/bench/load_external.cppsrc/bench/logging.cppsrc/bench/checkqueue.cppsrc/bench/addrman.cppsrc/bench/rpc_blockchain.cppsrc/bench/checkblock.cppsrc/bench/ecdsa.cppsrc/bench/mempool_eviction.cppsrc/bench/bench.hsrc/bench/ccoins_caching.cppsrc/bench/pow_hash.cppsrc/bench/wallet_loading.cppsrc/bench/examples.cppsrc/bench/bls_dkg.cppsrc/bench/chacha20.cppsrc/bench/string_cast.cppsrc/bench/base58.cppsrc/bench/bls.cppsrc/bench/poly1305.cppsrc/bench/util_time.cppsrc/bench/lockedpool.cppsrc/bench/rpc_mempool.cppsrc/bench/wallet_balance.cppsrc/bench/block_assemble.cppsrc/bench/ellswift.cppsrc/bench/prevector.cppsrc/bench/verify_script.cppsrc/bench/crypto_hash.cppsrc/bench/bech32.cppsrc/bench/peer_eviction.cpp
{guix-build*,releases,**/guix-build*,releases/**,.github/**,depends/**,ci/**,contrib/**,doc/**}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not make changes to build system files (guix-build*), release artifacts, or avoid changes to .github, depends, ci, contrib, and doc directories unless specifically prompted
Files:
ci/test/00_setup_env_mac_native_arm64.shci/test/04_install.shdoc/descriptors.mdci/dash/lint-tidy.sh
test/functional/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node
Files:
test/functional/wallet_listtransactions.pytest/functional/mempool_packages.pytest/functional/wallet_fast_rescan.pytest/functional/test_framework/wallet.pytest/functional/mempool_package_limits.pytest/functional/rpc_getblockfrompeer.pytest/functional/rpc_packages.pytest/functional/wallet_listsinceblock.pytest/functional/test_runner.py
src/{test,wallet/test}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework
Files:
src/test/fuzz/rpc.cppsrc/test/fuzz/string.cppsrc/test/util/setup_common.cpp
src/node/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
NodeContext must be extended with Dash-specific managers for each subsystem during initialization
Files:
src/node/interfaces.cpp
src/qt/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
GUI implementation in src/qt/ must use Qt 5
Files:
src/qt/main.cpp
🧠 Learnings (31)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.
Applied to files:
src/wallet/rpc/util.cppsrc/bench/wallet_create.cppsrc/wallet/rpc/backup.cppsrc/bench/wallet_loading.cpptest/functional/mempool_packages.pysrc/wallet/rpc/wallet.cppsrc/bitcoin-wallet.cppsrc/wallet/rpc/transactions.cppsrc/bitcoin-cli.cpptest/functional/rpc_packages.pysrc/rpc/client.cppsrc/rpc/mempool.cpp
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: The univalue library (in src/univalue/) is no longer a vendored external dependency but is now part of the Bitcoin Core codebase and can be modified as needed during backports.
Applied to files:
src/wallet/rpc/util.cppsrc/common/url.hsrc/bitcoin-wallet.cppsrc/bitcoind.cpp
📚 Learning: 2025-02-14T15:19:17.218Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6529
File: src/wallet/rpcwallet.cpp:3002-3003
Timestamp: 2025-02-14T15:19:17.218Z
Learning: The `GetWallet()` function calls in `src/wallet/rpcwallet.cpp` are properly validated with null checks that throw appropriate RPC errors, making additional validation unnecessary.
Applied to files:
src/wallet/rpc/util.cppsrc/wallet/rpc/wallet.cppsrc/wallet/rpc/transactions.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/wallet/**/*.{cpp,h} : Wallet implementation must use Berkeley DB and SQLite
Applied to files:
src/wallet/rpc/util.cppsrc/bench/wallet_create.cppsrc/bench/wallet_loading.cppsrc/wallet/rpc/wallet.cppsrc/bitcoin-wallet.cppsrc/wallet/wallet.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/bench/**/*.{cpp,h} : Performance benchmarks in src/bench/ must use the nanobench library
Applied to files:
src/bench/strencodings.cppsrc/bench/coin_selection.cppsrc/bench/hashpadding.cppsrc/bench/mempool_stress.cppsrc/bench/bls_pubkey_agg.cppsrc/bench/pool.cppsrc/bench/rollingbloom.cppsrc/bench/gcs_filter.cppsrc/bench/load_external.cppsrc/bench/logging.cppsrc/bench/checkqueue.cppsrc/bench/addrman.cppsrc/bench/rpc_blockchain.cppsrc/bench/checkblock.cppsrc/bench/ecdsa.cppsrc/bench/mempool_eviction.cppsrc/bench/bench.hsrc/bench/ccoins_caching.cppsrc/bench/pow_hash.cppsrc/bench/wallet_loading.cppsrc/bench/examples.cppsrc/bench/bls_dkg.cppsrc/bench/chacha20.cppsrc/bench/string_cast.cppsrc/bench/base58.cppsrc/bench/poly1305.cppsrc/bench/util_time.cppsrc/bench/lockedpool.cppsrc/bench/wallet_balance.cppsrc/bench/block_assemble.cppsrc/bench/prevector.cppsrc/bench/verify_script.cppsrc/bench/crypto_hash.cppsrc/bench/bech32.cppsrc/bench/peer_eviction.cpp
📚 Learning: 2025-01-02T08:33:26.751Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6516
File: ci/test/00_setup_env_mac.sh:11-11
Timestamp: 2025-01-02T08:33:26.751Z
Learning: The removal of DMG support in the macOS packaging process eliminates the need for python-based scripts or python3-setuptools in the build environment. The PACKAGES variable in ci/test/00_setup_env_mac.sh is vestigial due to the use of a general-purpose Docker container defined in contrib/containers/ci/Dockerfile.
Applied to files:
ci/test/00_setup_env_mac_native_arm64.shci/test/04_install.sh
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs
Applied to files:
src/bench/coin_selection.cppsrc/wallet/wallet.cppsrc/node/interfaces.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq}/**/*.{cpp,h} : BLS integration must be used for cryptographic foundation of advanced masternode features
Applied to files:
src/bench/bls_pubkey_agg.cppsrc/wallet/rpc/wallet.cppsrc/bench/bls.cppsrc/node/interfaces.cppsrc/rpc/mempool.cppsrc/test/util/setup_common.cpp
📚 Learning: 2025-12-22T15:42:48.595Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7068
File: src/qt/guiutil_font.h:68-77
Timestamp: 2025-12-22T15:42:48.595Z
Learning: In C++/Qt codebases, use fail-fast asserts in setters to enforce invariants (e.g., ensuring internal maps contain necessary keys). Prefer assert() for programmer errors that should be caught in development and debugging, rather than defensive runtime checks with fallbacks. This helps catch invariant violations early during development. Apply to header and source files where invariant-driven state mutations occur, especially in setters like SetWeightBold/SetWeightNormal that assume established relationships or preconditions.
Applied to files:
src/common/url.hsrc/wallet/scriptpubkeyman.hsrc/util/error.hsrc/bench/bench.hsrc/interfaces/chain.hsrc/logging.h
📚 Learning: 2025-12-17T13:58:26.891Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:26.891Z
Learning: In Dash Qt wallet code, when leveraging upstream Bitcoin Core wallet capabilities (especially for operations like rescanning), prefer using the inherited signal-based mechanisms (e.g., ShowProgress signals) over adding explicit Qt progress dialogs to minimize upstream deviation and simplify future backports.
Applied to files:
src/wallet/rpc/backup.cppsrc/wallet/wallet.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Applied to files:
src/bench/rpc_blockchain.cppsrc/bench/checkblock.cppsrc/Makefile.amsrc/interfaces/chain.htest/functional/mempool_packages.pysrc/wallet/rpc/wallet.cppsrc/bitcoin-wallet.cppsrc/wallet/wallet.cppsrc/wallet/rpc/transactions.cppsrc/bench/rpc_mempool.cppsrc/bitcoin-cli.cppsrc/node/interfaces.cppci/dash/lint-tidy.shsrc/rpc/mempool.cpp
📚 Learning: 2025-09-02T07:34:28.226Z
Learnt from: knst
Repo: dashpay/dash PR: 6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
Applied to files:
doc/descriptors.md
📚 Learning: 2025-07-23T09:30:34.631Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.h:5-6
Timestamp: 2025-07-23T09:30:34.631Z
Learning: Dash Core uses BITCOIN_ prefix for header guards as the standard convention, inherited from Bitcoin Core. Only a few BLS-specific files in src/bls/ use DASH_ prefix. The vast majority of files (385+) use BITCOIN_ prefix.
Applied to files:
src/Makefile.amsrc/logging.hsrc/bench/crypto_hash.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Dash extends Bitcoin Core through composition with minimal changes to the Bitcoin Core foundation
Applied to files:
src/Makefile.am
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : ChainLocks implementation must prevent reorganizations and provide block finality through 51% attack prevention
Applied to files:
src/interfaces/chain.hsrc/rpc/mempool.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing
Applied to files:
src/interfaces/chain.hsrc/node/interfaces.cppsrc/rpc/mempool.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/node/chainstate.{cpp,h} : Chainstate initialization must be separated into dedicated src/node/chainstate.* files
Applied to files:
src/interfaces/chain.hsrc/bitcoin-wallet.cppsrc/bitcoind.cppsrc/rpc/mempool.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Applied to files:
src/bench/wallet_loading.cppsrc/node/interfaces.cppsrc/bench/crypto_hash.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Applied to files:
test/functional/mempool_packages.pytest/functional/mempool_package_limits.pytest/functional/rpc_packages.py
📚 Learning: 2025-06-20T23:32:16.225Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6726
File: test/functional/rpc_createmultisig.py:120-120
Timestamp: 2025-06-20T23:32:16.225Z
Learning: In the rpc_createmultisig.py test, the checkbalances() function correctly excludes 9 blocks from the balance calculation: 8 blocks from do_multisig() calls (2 blocks per call × 4 calls) plus 1 block from checkbalances() itself.
Applied to files:
test/functional/mempool_packages.py
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : LLMQ quorums must support multiple configurations (50/60, 400/60, 400/85) for different services (ChainLocks, InstantSend, governance voting)
Applied to files:
src/bench/bls_dkg.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : InstantSend implementation must provide distributed key generation for secure transaction locking with quorum consensus
Applied to files:
src/bench/bls_dkg.cpp
📚 Learning: 2025-11-04T18:23:28.175Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/governance/classes.cpp:147-154
Timestamp: 2025-11-04T18:23:28.175Z
Learning: In src/governance/classes.cpp, CSuperblock::GetPaymentsLimit intentionally uses synthetic difficulty constants (nBits = 1 for mainnet, powLimit for networks with min difficulty) and simple height-based V20 activation checks instead of actual chain block data. This is by design because superblocks themselves are "synthetic" governance payment blocks, not regular mined blocks.
Applied to files:
src/wallet/wallet.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Applied to files:
src/node/interfaces.cpp
📚 Learning: 2025-12-01T18:13:21.314Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 7018
File: test/lint/lint-github-actions.py:1-9
Timestamp: 2025-12-01T18:13:21.314Z
Learning: In the Dash repository, the file test/util/data/non-backported.txt should only include C++ files (.cpp or .h) because it is used for running clang-format. Other file types (such as Python files, .ui files, etc.) should not be added to this list.
Applied to files:
ci/dash/lint-tidy.sh
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/**/*.{cpp,h,hpp,cc} : Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Applied to files:
ci/dash/lint-tidy.sh
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{test,wallet/test}/**/*.{cpp,h} : Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework
Applied to files:
ci/dash/lint-tidy.sh
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h} : Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Applied to files:
src/bench/crypto_hash.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/qt/**/*.{cpp,h} : GUI implementation in src/qt/ must use Qt 5
Applied to files:
src/qt/main.cpp
📚 Learning: 2025-12-17T13:58:19.813Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:19.813Z
Learning: In Dash Qt wallet code, prefer using existing Qt signals/slots (e.g., ShowProgress signals) for long-running operations instead of adding explicit QProgressDialog dialogs. This minimizes upstream deviations and simplifies backports. Apply this pattern to wallet-related Qt components (e.g., operations like rescanning) and rely on signal-based progress updates rather than bespoke dialogs.
Applied to files:
src/qt/main.cpp
🧬 Code graph analysis (8)
src/common/url.h (1)
src/common/url.cpp (2)
urlDecode(12-22)urlDecode(12-12)
src/wallet/scriptpubkeyman.h (1)
src/wallet/scriptpubkeyman.cpp (6)
GetScriptPubKeys(2516-2519)GetScriptPubKeys(2516-2516)GetScriptPubKeys(2521-2531)GetScriptPubKeys(2521-2521)GetEndRange(2533-2536)GetEndRange(2533-2533)
src/interfaces/chain.h (2)
src/node/interfaces.cpp (14)
filter_type(1072-1075)filter_type(1072-1072)filter_type(1076-1085)filter_type(1076-1076)block_hash(1056-1062)block_hash(1056-1056)block_hash(1124-1134)block_hash(1124-1124)block_hash(1135-1143)block_hash(1135-1135)block_hash(1159-1163)block_hash(1159-1159)block_hash(1164-1182)block_hash(1164-1164)src/wallet/wallet.cpp (2)
block_hash(319-322)block_hash(319-319)
test/functional/mempool_packages.py (3)
test/functional/test_framework/test_framework.py (1)
is_specified_wallet_compiled(1114-1120)test/functional/test_framework/p2p.py (1)
wait_for_broadcast(1019-1026)test/functional/test_framework/messages.py (1)
get_vsize(593-594)
test/functional/test_framework/wallet.py (1)
test/functional/test_framework/util.py (2)
assert_greater_than_or_equal(82-84)assert_equal(69-74)
test/functional/mempool_package_limits.py (1)
test/functional/test_framework/wallet.py (6)
MiniWallet(74-366)send_self_transfer_chain(357-366)create_self_transfer(315-335)create_self_transfer_multi(260-313)send_self_transfer(226-230)sendrawtransaction(337-340)
test/functional/rpc_packages.py (5)
test/functional/test_framework/messages.py (1)
tx_from_hex(230-232)test/functional/test_framework/p2p.py (2)
P2PTxInvStore(1001-1026)wait_for_broadcast(1019-1026)test/functional/test_framework/util.py (2)
assert_fee_amount(44-52)assert_raises_rpc_error(132-148)test/functional/test_framework/wallet.py (5)
MiniWallet(74-366)create_self_transfer(315-335)create_self_transfer_chain(342-355)create_self_transfer_multi(260-313)get_utxo(192-212)test/functional/test_framework/test_node.py (1)
get_deterministic_priv_key(191-194)
src/rpc/mempool.cpp (2)
src/wallet/rpc/spend.cpp (1)
tx(983-983)src/core_write.cpp (2)
ValueFromAmount(36-47)ValueFromAmount(36-36)
🪛 Cppcheck (2.19.0)
src/bench/bls_pubkey_agg.cpp
[error] 95-95: failed to evaluate #if condition, undefined function-like macro invocation
(syntaxError)
src/node/interfaces.cpp
[error] 22-22: failed to evaluate #if condition, undefined function-like macro invocation
(syntaxError)
src/bench/peer_eviction.cpp
[error] 148-148: Buffer is accessed out of bounds
(bufferAccessOutOfBounds)
src/test/util/setup_common.cpp
[error] 10-10: failed to evaluate #if condition, undefined function-like macro invocation
(syntaxError)
🪛 Flake8 (7.3.0)
test/functional/wallet_fast_rescan.py
[error] 52-52: f-string is missing placeholders
(F541)
test/functional/rpc_packages.py
[error] 51-51: continuation line over-indented for hanging indent
(E126)
[error] 56-56: continuation line under-indented for hanging indent
(E121)
[error] 101-101: continuation line under-indented for visual indent
(E128)
🪛 Ruff (0.14.10)
test/functional/wallet_listtransactions.py
177-177: Prefer next(...) over single element slice
Replace with next(...)
(RUF015)
test/functional/wallet_fast_rescan.py
52-52: f-string without any placeholders
Remove extraneous f prefix
(F541)
test/functional/test_framework/wallet.py
290-290: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
test/functional/rpc_packages.py
120-120: Consider [tx_high_fee["hex"], *self.independent_txns_hex] instead of concatenation
Replace with [tx_high_fee["hex"], *self.independent_txns_hex]
(RUF005)
197-197: Consider [*package_hex, child_tx['hex']] instead of concatenation
Replace with [*package_hex, child_tx['hex']]
(RUF005)
202-202: Consider [*package_hex, child_tx["hex"]] instead of concatenation
Replace with [*package_hex, child_tx["hex"]]
(RUF005)
245-245: Unnecessary key check before dictionary access
Replace with dict.get
(RUF019)
260-260: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
test/functional/wallet_listsinceblock.py
413-413: Prefer next(...) over single element slice
Replace with next(...)
(RUF015)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: linux64_multiprocess-build / Build source
- GitHub Check: linux64_tsan-build / Build source
- GitHub Check: linux64_sqlite-build / Build source
- GitHub Check: linux64_fuzz-build / Build source
- GitHub Check: linux64-build / Build source
- GitHub Check: linux64_ubsan-build / Build source
- GitHub Check: mac-build / Build source
- GitHub Check: win64-build / Build source
- GitHub Check: arm-linux-build / Build source
- GitHub Check: linux64_nowallet-build / Build source
| for _ in range(DEFAULT_DESCENDANT_LIMIT - 1): | ||
| utxo = transaction_package.pop(0) | ||
| (txid, sent_value) = chain_transaction(self.nodes[0], [utxo['txid']], [utxo['vout']], utxo['amount'], fee, 10) | ||
| new_tx = self.wallet.send_self_transfer_multi(from_node=self.nodes[0], num_outputs=10, utxos_to_spend=[utxo]) | ||
| txid = new_tx["txid"] | ||
| chain.append(txid) | ||
| if utxo['txid'] is parent_transaction: | ||
| tx_children.append(txid) | ||
| for j in range(10): | ||
| transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) | ||
| transaction_package.extend(new_tx["new_utxos"]) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use equality (==) instead of identity (is) for txid comparison
Here:
if utxo['txid'] is parent_transaction:
tx_children.append(txid)is checks object identity, not string equality, and will be unreliable for txid strings. This can cause tx_children to be incomplete or empty and break the descendant/spentby checks.
Consider switching to ==:
Proposed fix
- if utxo['txid'] is parent_transaction:
+ if utxo['txid'] == parent_transaction:
tx_children.append(txid)🤖 Prompt for AI Agents
In @test/functional/mempool_packages.py around lines 231-239, The comparison
currently uses identity instead of equality: replace the identity check `if
utxo['txid'] is parent_transaction` with an equality check against the txid
string (i.e., compare utxo['txid'] == parent_transaction) so tx_children is
populated reliably when the utxo txid matches parent_transaction; update the
condition in the loop that builds chain/tx_children accordingly.
| # Check that each result is present, with the correct size and fees | ||
| for package_txn in package_txns: | ||
| tx = package_txn["tx"] | ||
| assert tx.hash in submitpackage_result["tx-results"] | ||
| tx_result = submitpackage_result["tx-results"][tx.hash] | ||
| assert_equal(tx_result, { | ||
| "txid": package_txn["txid"], | ||
| "size": tx.get_vsize(), | ||
| "fees": { | ||
| "base": DEFAULT_FEE, | ||
| } | ||
| }) | ||
|
|
||
| # submitpackage result should be consistent with testmempoolaccept and getmempoolentry | ||
| self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result) | ||
|
|
||
| # Package feerate is calculated for the remaining transactions after deduplication and | ||
| # individual submission. If only 0 or 1 transaction is left, e.g. because all transactions | ||
| # had high-feerates or were already in the mempool, no package feerate is provided. | ||
| # In this case, since all of the parents have high fees, each is accepted individually. | ||
| assert "package-feerate" not in submitpackage_result | ||
|
|
||
| # The node should announce each transaction. No guarantees for propagation. | ||
| self.bump_mocktime(30) | ||
| peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns]) | ||
| self.generate(node, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
submitpackage result indexing and broadcast wait should use txids, not tx.hash
In test_submit_child_with_parents:
for package_txn in package_txns:
tx = package_txn["tx"]
assert tx.hash in submitpackage_result["tx-results"]
tx_result = submitpackage_result["tx-results"][tx.hash]
...
...
peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns])Two problems:
-
submitpackage_result["tx-results"]is keyed by txid strings, whiletx.hashis an internal integer hash. The membership test and lookup are therefore unreliable and can fail with a KeyError. -
P2PTxInvStore.wait_for_broadcastexpects a list of hex txid strings and callsint(tx, 16)on each. Passing integer hashes (tx.hash) will raise aTypeError.
Both places should use the hex txid string (package_txn["txid"]).
Proposed fix
- for package_txn in package_txns:
- tx = package_txn["tx"]
- assert tx.hash in submitpackage_result["tx-results"]
- tx_result = submitpackage_result["tx-results"][tx.hash]
+ for package_txn in package_txns:
+ tx = package_txn["tx"]
+ assert package_txn["txid"] in submitpackage_result["tx-results"]
+ tx_result = submitpackage_result["tx-results"][package_txn["txid"]]
assert_equal(tx_result, {
"txid": package_txn["txid"],
"size": tx.get_vsize(),
"fees": {
"base": DEFAULT_FEE,
}
})
@@
- self.bump_mocktime(30)
- peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns])
+ self.bump_mocktime(30)
+ peer.wait_for_broadcast([tx["txid"] for tx in package_txns])🤖 Prompt for AI Agents
In @test/functional/rpc_packages.py around lines 268-293, In
test_submit_child_with_parents, replace uses of the internal integer tx.hash
with the hex txid string package_txn["txid"]: change the loop membership check
and lookup against submitpackage_result["tx-results"] to use package_txn["txid"]
(both the assert and tx_result assignment), and change the
peer.wait_for_broadcast call to pass a list of package_txn["txid"] strings
instead of tx["tx"].hash so wait_for_broadcast receives hex txid strings.
| def test_submit_cpfp(self): | ||
| node = self.nodes[0] | ||
| peer = node.add_p2p_connection(P2PTxInvStore()) | ||
|
|
||
| tx_poor = self.wallet.create_self_transfer(fee=0, fee_rate=0) | ||
| tx_rich = self.wallet.create_self_transfer(fee=DEFAULT_FEE) | ||
| package_txns = [tx_rich, tx_poor] | ||
| coins = [tx["new_utxo"] for tx in package_txns] | ||
| tx_child = self.wallet.create_self_transfer_multi(utxos_to_spend=coins, fee_per_output=10000) #DEFAULT_FEE | ||
| package_txns.append(tx_child) | ||
|
|
||
| submitpackage_result = node.submitpackage([tx["hex"] for tx in package_txns]) | ||
|
|
||
| rich_parent_result = submitpackage_result["tx-results"][tx_rich["txid"]] | ||
| poor_parent_result = submitpackage_result["tx-results"][tx_poor["txid"]] | ||
| child_result = submitpackage_result["tx-results"][tx_child["tx"].hash] | ||
| assert_equal(rich_parent_result["fees"]["base"], DEFAULT_FEE) | ||
| assert_equal(poor_parent_result["fees"]["base"], 0) | ||
| assert_equal(child_result["fees"]["base"], DEFAULT_FEE) | ||
| # Package feerate is calculated for the remaining transactions after deduplication and | ||
| # individual submission. Since this package had a 0-fee parent, package feerate must have | ||
| # been used and returned. | ||
| assert "package-feerate" in submitpackage_result | ||
| assert_fee_amount(DEFAULT_FEE, rich_parent_result["size"] + child_result["size"], submitpackage_result["package-feerate"]) | ||
|
|
||
| # The node will broadcast each transaction, still abiding by its peer's fee filter | ||
| self.bump_mocktime(30) | ||
| peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns]) | ||
| self.generate(node, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same txid vs hash issue in CPFP submitpackage test
test_submit_cpfp has the same tx.hash vs txid and broadcast argument issue:
rich_parent_result = submitpackage_result["tx-results"][tx_rich["txid"]]
poor_parent_result = submitpackage_result["tx-results"][tx_poor["txid"]]
child_result = submitpackage_result["tx-results"][tx_child["tx"].hash]
...
peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns])Indexing the child result via tx_child["tx"].hash and passing integer hashes to wait_for_broadcast are inconsistent with the parent lookups and with P2PTxInvStore’s API.
Suggestion:
Proposed fix
- child_result = submitpackage_result["tx-results"][tx_child["tx"].hash]
+ child_result = submitpackage_result["tx-results"][tx_child["txid"]]
@@
- self.bump_mocktime(30)
- peer.wait_for_broadcast([tx["tx"].hash for tx in package_txns])
+ self.bump_mocktime(30)
+ peer.wait_for_broadcast([tx["txid"] for tx in package_txns])This keeps all indexing and broadcast waiting consistently based on txid strings.
🤖 Prompt for AI Agents
In @test/functional/rpc_packages.py around lines 295-323, In test_submit_cpfp
the child transaction is being referenced by tx_child["tx"].hash and
wait_for_broadcast is passed integer hashes, which is inconsistent with the
parent lookups (tx_rich/tx_poor using "txid") and P2PTxInvStore API; change the
child lookup to use submitpackage_result["tx-results"][tx_child["txid"]] and
pass txid strings to peer.wait_for_broadcast by using [tx["txid"] for tx in
package_txns] so all indexing and broadcast checking consistently use txid
strings (update references to tx_child, package_txns, submitpackage_result, and
peer.wait_for_broadcast accordingly).
What was done?
Regular backports from bitcoin core v25
How Has This Been Tested?
Run unit & functional tests
Breaking Changes
N/A
Checklist: