Bound the account count accepted by wallet RPC commands - #5121
Open
pwojcikdev wants to merge 3 commits into
Open
Bound the account count accepted by wallet RPC commands#5121pwojcikdev wants to merge 3 commits into
pwojcikdev wants to merge 3 commits into
Conversation
Reject counts above a shared limit in accounts_create and wallet_change_seed, and validate wallet_change_seed's count before replacing the seed.
Test Results for Commit 4b97a2dPull Request 5121: Results Test Case Results
Last updated: 2026-07-29 23:16:21 UTC |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens wallet-related RPC endpoints against abusive/overflowing count parameters by enforcing a per-request maximum and ensuring validation happens before mutating wallet state.
Changes:
- Add a shared per-request account limit (
max_accounts_per_request = 100000) and reject requests exceeding it. - Fix
wallet_change_seedto validatecount(including parse errors) before changing the wallet seed. - Add RPC tests asserting over-limit requests are rejected and do not partially apply changes.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| nano/node/json_handler.cpp | Enforces count bounds for accounts_create and wallet_change_seed; ensures wallet_change_seed validates before mutating the wallet. |
| nano/rpc_test/rpc.cpp | Adds regression tests for the new count limit and seed immutability on rejected requests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+4755
to
+4759
| // Count is the highest index to restore, so the seed yields one more account than its value | ||
| auto count (rpc_l->count_optional_impl (0)); | ||
| if (!rpc_l->ec && count > max_accounts_per_request) | ||
| { | ||
| nano::public_key account (wallet->change_seed (seed, count)); | ||
| rpc_l->response_l.put ("success", ""); | ||
| rpc_l->response_l.put ("last_restored_account", account.to_account ()); | ||
| auto index (wallet->get_deterministic_index ()); | ||
| debug_assert (index > 0); | ||
| rpc_l->response_l.put ("restored_count", std::to_string (index)); | ||
| rpc_l->ec = nano::error_common::invalid_count; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
accounts_createandwallet_change_seedboth loop over a caller-supplied count creating accounts, with no upper bound. A large count leaves the wallet unusable for the duration of the request, and the parameter accepts anything that parses into 64 bits.wallet_change_seedhad a second problem: it truncated itsuint64count into auint32, socount=4294967296became0— which selects auto-detect, a different operation than the caller asked for. Any multiple of 2^32 behaved the same way.Both handlers now reject counts above
max_accounts_per_request(100000) withinvalid_count, following the range checkaccount_createalready applies to itsindexparameter.wallet_change_seedadditionally validates before touching the wallet.count_optional_implsetsecon a malformed count, but the handler ignored it and replaced the seed anyway, surfacing the error only after the change had been made. A rejected request now leaves the existing seed in place.Tests:
accounts_create_count_limitasserts the request is rejected and no account is created.wallet_change_seed_count_rejecteddrives100001,4294967295,4294967296and12abc, asserting each is rejected and that the existing seed survives. The last two are the interesting ones:4294967296previously truncated into a ledger scan, and12abcparses as12before failing on the trailing garbage, so it previously replaced the seed and created 12 accounts while returning "Invalid count" to the caller.Verified against
developwith the malformed count in isolation — the seed is replaced despite the error response:Related to #5119, which guards the same overflow one layer down in
wallet::change_seed.🤖 Generated with Claude Code