Repository navigation
fix(wallet): authenticate unlock deadline extensions - #7838
PastaPastaPasta merged 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review. Walkthrough
Priority: ⬆️ High Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to No actionable merge-blocking risk is established; the change is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
✅ Final review complete — no blockers (commit 86ba039) · triage: low · Phase 2 only (queue backlog) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 1 + Phase 2
At head d2bd1a2, the wallet change authenticates unlock extensions before returning success and preserves the existing mixing-mode and RPC timer behavior. No blocking defect was identified; one non-blocking concern remains about the new regression test's real-time timing margins. Verification was static only: the supplied CI snapshot shows successful formatting and metadata checks, but container builds remain queued and no completed build or test results are available.
🟡 1 suggestion(s)
Review provenance
Source: reviewer 1: glm-5.3-flash (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — The diff is a small, contained change to CWallet::Unlock passphrase authentication with focused regression tests, not a large or intricate key-handling change meeting the critical bar. - Phase 1 reviewers:
glm-5.3-flash— general (completed, effort high); agentphase1-reviewer - Phase 1 model:
glm-5.3-flash— zai quota: 5h 90% left, weekly 94% left; passed overgemini-3.8-flash-high(antigravity below 15% reserve: weekly 15% left, 5h 100% left) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/functional/wallet_encryption.py`:
- [SUGGESTION] test/functional/wallet_encryption.py:36-51: Give the new real-time relock assertions more scheduling margin
The initial 3-second unlock must cover two wrong-passphrase key derivations, several RPC round trips, and the first signing operation. The extension scenario then sleeps for 3 seconds against a 5-second timer, leaving less than 2 seconds for the successful signing RPC. These timers use real libevent time, and --timeout-factor does not scale either the wallet deadlines or these sleeps, so a loaded or instrumented worker can relock the wallet before an operation that the test expects to succeed. The expiry assertions also allow only about one second for the timer callback to run. Increase the unlock durations and corresponding sleeps together, preserving the checks on both sides of the original and replacement deadlines. This is a scheduling robustness concern, not an observed failure in this review; repository history in 7513a30d87 independently confirms sanitizer-related wallet timeout flakes.
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Verified the complete diff at 13e6e8e, including wallet unlock callers, master-key validation, RPC timer handling, and functional-test timeout scaling; no blocking correctness issues were found. The prior scheduling-margin concern is fixed, and the only remaining suggestion is to consolidate the test correction into its introducing commit. This was a static review without builds or test execution; build and validation checks were still queued or pending in the supplied CI snapshot.
🟡 1 suggestion(s)
1 finding(s) not shown inline (the lines are not part of this PR's diff)
🟡 Suggestion: Fold the regression timing correction into the original fix
<commit:13e6e8ed49>:1
Commit 13e6e8e only changes timeout scaling, unlock windows, and expiry waits in test_unlock_authentication, introduced immediately beforehand by d2bd1a2. It revises the same regression scenario rather than adding independently scoped coverage. CONTRIBUTING.md's "Squashing Commits" section identifies repeated changes to the same lines as fixup commits suitable for consolidation. Fold this follow-up into d2bd1a2 so the permanent history presents the authentication fix with its final regression test instead of an intermediate test followed by its timing correction. This is a non-blocking history suggestion, not a defect in the final code.
source: gpt-6.1-sol (phase2-reviewer: dash-core-commit-history)
Review provenance
Source: reviewer 1: glm-5.3-flash (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — The diff is a small, contained authentication fix in CWallet::Unlock with focused regression coverage, not a large or intricate change despite touching key handling. - Phase 1 reviewers:
glm-5.3-flash— general (completed, effort high); agentphase1-reviewer - Phase 1 model:
glm-5.3-flash— zai quota: 5h 88% left, weekly 89% left; passed overgemini-3.8-flash-high(antigravity below 15% reserve: weekly 15% left, 5h 100% left) - Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `<commit:13e6e8ed49>`:
- [SUGGESTION] <commit:13e6e8ed49>:1: Fold the regression timing correction into the original fix
Commit 13e6e8ed49 only changes timeout scaling, unlock windows, and expiry waits in test_unlock_authentication, introduced immediately beforehand by d2bd1a2673. It revises the same regression scenario rather than adding independently scoped coverage. CONTRIBUTING.md's "Squashing Commits" section identifies repeated changes to the same lines as fixup commits suitable for consolidation. Fold this follow-up into d2bd1a2673 so the permanent history presents the authentication fix with its final regression test instead of an intermediate test followed by its timing correction. This is a non-blocking history suggestion, not a defect in the final code.
|
The timing concern is resolved at 🤖 Posted autonomously by Codex on behalf of pasta. |
CWallet::Unlock(SecureString) returned true without checking the passphrase when the wallet was already fully unlocked. walletpassphrase treats that as authentication and replaces the relock timer, so any nonempty wrong passphrase could keep a full unlock alive past the owner's deadline. Derive and decrypt on every request, as Bitcoin Core does. When a master key is already held, also require the decrypted candidate to match it. The already-unlocked path skips CheckDecryptionKey, which a blank wallet passes trivially, so a wrong passphrase that happens to produce valid padding would otherwise succeed. An authenticated request on a fully unlocked wallet stays a no-op. The RPC timer and mixing-mode handling are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
13e6e8e to
86ba039
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 2 only (queue backlog)
At exact head 86ba039, the complete diff correctly authenticates encrypted-wallet unlock requests before accepting deadline updates, while preserving authenticated no-op success, mixing-only upgrades, and unencrypted-wallet behavior; no actionable in-scope defects were found. Both prior suggestions are addressed: the range contains one cohesive commit, and the replacement regression checks wrong-passphrase rejection and deadline preservation without the added real-time expiry scenarios. This was static verification only; the supplied exact-head CI snapshot shows successful formatting and merge checks, with container builds and title checks still queued.
🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — The diff is a small, contained authentication fix in CWallet::Unlock with a focused regression test, not a large or intricate change despite touching key handling. - Phase 1 reviewers: not run (skipped for throughput: 12 PRs queued, above the 10 limit)
- Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.
No unresolved findings remain from the prior review on this head.
…ollow-up fixes for lately added tests. 99cdb0b test: follow-up for #7812: use less fixture to test quorum dkgstatus (Konstantin Akimov) 0288ca9 docs: be more explicit about "scope", "scenario", "case" when writing tests. (Konstantin Akimov) 8a620db test: follow-up for #7838: replace brand new scenario to extra check (Konstantin Akimov) 4a19742 test: follow-up for #7821: check if wallet is locked after failed upgrade instead creating brand-new scenario (Konstantin Akimov) 1435bef test: follow-up for #7829: replace brand-new scenario to just extra check for mixing-unlock (Konstantin Akimov) 8a67e4d test: RPC importelectrumwallet have functional tests, removed an exception (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented #7829, #7821, #7838, #7812, added brand-new scenarious to functional tests while it could tested by extra check in existing scenarious. ## What was done? Updated guidance for agents about writing new tests. Follow-up fixes for #7829, #7821, #7838 by replacing scenarious to single check. Removed an exception for `importelectrumwallet` from list of un-tested RPCs For #7812: - Rotation test. The existing check after the DKG finishes now asserts 0 for each masternode. It no longer sums the stale debug sessions. The PR's two added scenarios are removed. - rpc_quorum.py. It now mines to the next DKG start block while the DKG spork is still off. Then it asserts the masternode's active_dkgs is above 0, before turning the spork on. The PR's separate scenario is removed. - test_framework.py. The helper that only the removed scenarios used is gone. ## How Has This Been Tested? Run functional tests. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ Top commit has no ACKs. Tree-SHA512: 625e2792ad4a848fa9a70dc65109846dae822e87fe0a8a116c7ce8bac224c7a35179bde6751915391d2d1b1bcab32eb1e28eaeaa4e54a5ff777d5c3f997924ba
Issue being fixed or feature implemented
CWallet::Unlock(SecureString)returnedtruewithout checking the passphrase whenever the encrypted wallet was already fully unlocked.walletpassphrasetreats that result as authentication and replaces the relock deadline and timer. So while a wallet is fully unlocked, a caller allowed to usewalletpassphrasecould keep it unlocked past the owner's deadline with any nonempty wrong passphrase. Spending or exporting keys after the original deadline still needs those RPC permissions too. A locked or mixing-only wallet cannot be unlocked this way, and RPC authentication is not bypassed.The early return is Dash-specific (added in 78c5ca5, blocked in 0.12.1, reintroduced by ff5540b in 0.16.0.0). Bitcoin Core decrypts the master key on every
Unlock.What was done?
TimingResistantEqual. A mismatch moves on to the next master-key entry.CheckDecryptionKey, and a blank wallet passes that check trivially. Without the comparison, a wrong passphrase that happens to produce valid padding would still be accepted.How Has This Been Tested?
macOS arm64, depends build.
wallet_encryption.pynow ends with one deterministic check under the mocktime the test already sets: with the wallet fully unlocked for 100 seconds,walletpassphrasewith a wrong passphrase and a 1000-second timeout fails with-14, andunlocked_untildoes not change. Against an unpatchedwallet.cppthe check fails ("No exception raised"). With the fix it passes.wallet_encryption.py --legacy-walletandwallet_encryption.py --descriptorsboth pass.test_dash --run_test=bip39_tests,wallet_crypto_testspasses, andlint-python.pyis clean.Unlock(SecureString)callers were checked: Qt unlock dialog and wallet controller, createwallet, EncryptWallet, migration and upgradetohd.Limits:
Breaking Changes
None.
Checklist:
🤖 Generated with Claude Code