fix: reject invalid extended masternode net info#7385
Conversation
`ExtNetInfo::Validate()` can return `BadInput`, `Duplicate`, and `MaxLimit` for states reachable via deserialization that bypass the in-memory builder's per-entry checks. `CheckService` previously asserted on those statuses; map them to graceful `TX_BAD_SPECIAL` rejections with stable reason strings instead. Also enforce the per-purpose `MAX_ENTRIES_EXTNETINFO` cap inside `ExtNetInfo::Validate()` so an oversized deserialized list is rejected rather than silently accepted. Adds unit coverage for the three deserialization paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
✅ Review complete (commit d818922) |
Walkthrough
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
🚥 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 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/test/evo_netinfo_tests.cpp (1)
500-561: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a test for the
CheckServicereject mapping.These cases validate
ExtNetInfo::Validate(), but the behavior change insrc/evo/specialtxman.cppis theTX_BAD_SPECIAL/reason-string translation. A typo or missing case there would still pass this suite, so please add one validation test that feeds deserialized bad netinfo through the provider-tx path and asserts the new reject reason.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/evo_netinfo_tests.cpp` around lines 500 - 561, The current `extnetinfo_validate_deser` test only checks `ExtNetInfo::Validate()` and does not cover the `CheckService` reject mapping in the provider-tx path. Add one focused test that deserializes an invalid `ExtNetInfo`, sends it through the special-tx validation flow in `specialtxman`/`CheckService`, and asserts the `TX_BAD_SPECIAL` reject reason string. Use the existing `ExtNetInfo`, `Validate()`, and provider-tx validation symbols to locate the right path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/test/evo_netinfo_tests.cpp`:
- Around line 500-561: The current `extnetinfo_validate_deser` test only checks
`ExtNetInfo::Validate()` and does not cover the `CheckService` reject mapping in
the provider-tx path. Add one focused test that deserializes an invalid
`ExtNetInfo`, sends it through the special-tx validation flow in
`specialtxman`/`CheckService`, and asserts the `TX_BAD_SPECIAL` reject reason
string. Use the existing `ExtNetInfo`, `Validate()`, and provider-tx validation
symbols to locate the right path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 0bd68d96-c614-44c3-a829-1adc6c815bee
📒 Files selected for processing (3)
src/evo/netinfo.cppsrc/evo/specialtxman.cppsrc/test/evo_netinfo_tests.cpp
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Small, well-scoped consensus-safety fix. Three previously unreachable assert(false) arms in CheckService are converted into stable TX_BAD_SPECIAL rejections, and ExtNetInfo::Validate() now enforces the per-purpose MAX_ENTRIES_EXTNETINFO cap that the in-memory builder enforces at insertion. Unit coverage exercises the three deserialization paths (duplicate entries, oversized list, domain on non-HTTPS purpose). No in-scope issues.
Note: posted as a COMMENT review because GitHub does not allow approving my own PR.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/test/evo_deterministicmns_tests.cpp (1)
724-733: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAlso assert
TX_BAD_SPECIALin this helper.Right now this only checks
state.GetRejectReason(). A regression that keeps the same string but changes the validation class would still pass, even though this PR is also locking down theTX_BAD_SPECIALmapping.Suggested test tightening
auto check_reject_reason = [&](std::shared_ptr<NetInfoInterface> net_info, const std::string& reject_reason) { TxValidationState state; { LOCK(cs_main); BOOST_CHECK(!CheckProRegTx(BuildExtNetInfoProRegTx(std::move(net_info)), chainman.ActiveChain().Tip(), dmnman, chainman.ActiveChainstate().CoinsTip(), chainman, state, /*check_sigs=*/false)); } + BOOST_CHECK_EQUAL(state.GetResult(), TxValidationResult::TX_BAD_SPECIAL); BOOST_CHECK_EQUAL(state.GetRejectReason(), reject_reason); };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/evo_deterministicmns_tests.cpp` around lines 724 - 733, The test helper check_reject_reason currently only verifies state.GetRejectReason(), so it can miss regressions where the reject string stays the same but the validation class changes. Update this helper in evo_deterministicmns_tests.cpp to also assert the TxValidationState maps to TX_BAD_SPECIAL, using the existing state object from CheckProRegTx alongside the reject reason check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/test/evo_deterministicmns_tests.cpp`:
- Around line 724-733: The test helper check_reject_reason currently only
verifies state.GetRejectReason(), so it can miss regressions where the reject
string stays the same but the validation class changes. Update this helper in
evo_deterministicmns_tests.cpp to also assert the TxValidationState maps to
TX_BAD_SPECIAL, using the existing state object from CheckProRegTx alongside the
reject reason check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c42647b0-4c12-4901-9713-b4f014910ca6
📒 Files selected for processing (1)
src/test/evo_deterministicmns_tests.cpp
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Test-only delta (0f5fd825) adds CheckProRegTx-level regression coverage for the three new TX_BAD_SPECIAL reject paths introduced by 5ba9ace (BadInput, Duplicate, MaxLimit deserialization escapes). Implementation and test coverage are correct and in scope. Only a minor test-hardening nit from CodeRabbit is worth surfacing; no carried-forward prior findings (prior PastaClaw review was clean).
💬 1 nitpick(s)
Note: GitHub does not allow me to approve my own PR, so this is posted as a COMMENT while preserving the verified nonblocking finding.
| auto check_reject_reason = [&](std::shared_ptr<NetInfoInterface> net_info, const std::string& reject_reason) { | ||
| TxValidationState state; | ||
| { | ||
| LOCK(cs_main); | ||
| BOOST_CHECK(!CheckProRegTx(BuildExtNetInfoProRegTx(std::move(net_info)), chainman.ActiveChain().Tip(), | ||
| dmnman, chainman.ActiveChainstate().CoinsTip(), chainman, state, | ||
| /*check_sigs=*/false)); | ||
| } | ||
| BOOST_CHECK_EQUAL(state.GetRejectReason(), reject_reason); | ||
| }; |
There was a problem hiding this comment.
💬 Nitpick: Also assert TxValidationResult::TX_BAD_SPECIAL in check_reject_reason
The fix in 5ba9ace deliberately maps BadInput/Duplicate/MaxLimit to TX_BAD_SPECIAL with stable reason strings. The new helper only checks the reject reason, so a future regression that keeps the same reason string but degrades the result class (e.g. TX_CONSENSUS or TX_RESULT_UNSET) would slip through. Since this test exists specifically to lock down both halves of that mapping, adding a result-class assertion costs one line and tightens the guarantee.
| auto check_reject_reason = [&](std::shared_ptr<NetInfoInterface> net_info, const std::string& reject_reason) { | |
| TxValidationState state; | |
| { | |
| LOCK(cs_main); | |
| BOOST_CHECK(!CheckProRegTx(BuildExtNetInfoProRegTx(std::move(net_info)), chainman.ActiveChain().Tip(), | |
| dmnman, chainman.ActiveChainstate().CoinsTip(), chainman, state, | |
| /*check_sigs=*/false)); | |
| } | |
| BOOST_CHECK_EQUAL(state.GetRejectReason(), reject_reason); | |
| }; | |
| auto check_reject_reason = [&](std::shared_ptr<NetInfoInterface> net_info, const std::string& reject_reason) { | |
| TxValidationState state; | |
| { | |
| LOCK(cs_main); | |
| BOOST_CHECK(!CheckProRegTx(BuildExtNetInfoProRegTx(std::move(net_info)), chainman.ActiveChain().Tip(), | |
| dmnman, chainman.ActiveChainstate().CoinsTip(), chainman, state, | |
| /*check_sigs=*/false)); | |
| } | |
| BOOST_CHECK_EQUAL(state.GetResult(), TxValidationResult::TX_BAD_SPECIAL); | |
| BOOST_CHECK_EQUAL(state.GetRejectReason(), reject_reason); | |
| }; |
source: ['coderabbit']
0f5fd82 to
d818922
Compare
|
Addressed the latest CodeRabbit test-hardening nit by adding the Validation:
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Cumulative review of PR #7385 at head d818922. The single prior nitpick (assert TxValidationResult::TX_BAD_SPECIAL in check_reject_reason) is resolved at src/test/evo_deterministicmns_tests.cpp:732. No new findings in the latest delta; the change is a one-line test hardening that strengthens coverage of deserialized ExtNetInfo rejection paths.
Note: GitHub does not allow me to approve my own PR, so this is posted as a COMMENT while preserving the verified clean result.
Summary
Issue being fixed or feature implemented
Extended masternode net info loaded from serialized transaction payloads can
contain semantic states that the in-memory builder rejects during normal
construction. Validation should reject those states explicitly instead of
relying on internal assertions.
What was done?
validation failures.
per-purpose lists, and domain entries under non-HTTPS purposes.
CheckProRegTxregression coverage for the sameinvalid deserialized net info states.
How Has This Been Tested?
Tested locally on macOS:
Pre-PR automated code review was also run for
upstream/develop..fix/extnetinfo-validationafter the transaction-levelcoverage was added and returned
ship.Breaking Changes
None.
Checklist
(for repository code-owners and collaborators only)