Skip to content

refactor: reduce ostringstream usage, set UniValue variable to object during construction, reduce GetHash() usage #6635

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

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

kwvg
Copy link
Collaborator

@kwvg kwvg commented Apr 20, 2025

Additional Information

  • Dependency for refactor: section off masternode network information to MnNetInfo, set some groundwork for managing multiple entries  #6627

  • We use std::ostringstream in masternodelist to pad values using std::setw (source) for consistency, this was fine because we didn't plan on removing anything from the stream after it was added.

    But in dash#6627, we intend to print multiple addresses and need to remove excess padding after the last entry, which can be trivially done with a pop_back() (source) but that cannot be done with a std::ostringstream. The best that can be done is rewinding the cursor but that doesn't change its contents and at most lets you overwrite it (source), which is fine when you do have something to overwrite it with but this isn't always the case.

    To get around this, PadString() has been implemented and std::ostringstream usage has been replaced with constructing a string with strprintf.

Breaking Changes

None expected.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas (note: N/A)
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation (note: N/A)
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg marked this pull request as ready for review April 28, 2025 00:58
Copy link

coderabbitai bot commented Apr 28, 2025

Walkthrough

This set of changes primarily focuses on code simplification, modernization, and minor test and utility enhancements across several source files. Many updates replace multi-step or manual constructions of objects and strings with more concise and idiomatic alternatives. Specifically, numerous instances of UniValue JSON object initialization are streamlined by using direct constructors instead of separate initialization and setup calls. String formatting and logging throughout the governance, masternode, and network-related modules are refactored to use strprintf instead of manual std::ostringstream concatenation, often incorporating function name macros for consistent error and log messages. Conditional checks for empty strings are updated to use the .empty() method for clarity. Additionally, a new PadString utility function is introduced, accompanied by a dedicated test case to verify its behavior. In the transaction mempool, repeated hash computations are cached in local variables to avoid redundancy. No public API signatures are altered except for the addition of the new utility function and test case.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (13)
src/llmq/commitment.h (1)

124-124: Code simplification: direct UniValue object initialization.

Replaced two-step initialization with a more concise direct constructor call. This makes the code more readable while maintaining identical functionality.

This change is part of a consistent pattern across multiple files to standardize UniValue initialization.

src/netfulfilledman.cpp (1)

90-90: Improved string formatting using strprintf.

Replaced ostringstream usage with the more concise strprintf function, which improves readability and is more consistent with the codebase's string formatting practices.

This change aligns with the PR's goal of reducing ostringstream usage throughout the codebase in favor of more direct string formatting.

src/governance/exceptions.cpp (1)

36-38: Improved constructor implementation with modern C++ initialization

Good refactoring to use uniform initialization and strprintf instead of stream-based string construction. This makes the code more maintainable and potentially more efficient.

Note that the pipeline indicates a clang format issue on line 30 (unrelated to your changes). Consider running clang-format on the file to fix this issue.

src/governance/object.cpp (1)

69-71: Improved string formatting with strprintf and func

Good refactoring to replace manual string stream construction with strprintf for log and error messages. Using __func__ to dynamically include the function name is a better practice than hardcoding function names, as it ensures messages stay accurate if function names change.

The replacement of std::ostringstream with strprintf likely improves both readability and performance.

The pipeline indicates a formatting issue in lines 75-156. Consider running clang-format on the file to ensure consistent styling.

Also applies to: 77-79, 87-89, 93-96, 104-106, 111-121, 129-133, 143-147, 153-157

src/governance/governance.cpp (1)

1134-1144: Improved string formatting with strprintf and func

Good refactoring to use strprintf with __func__ for log messages instead of hardcoding function names. This approach ensures that log messages stay accurate even if function names change, and generally leads to more readable and maintainable code.

The pipeline indicates formatting issues in lines 1132-1168. Consider running clang-format on the file to address these style inconsistencies.

src/rpc/masternode.cpp (8)

265-269: Use idiomatic emptiness check and consider caching
You've replaced strFilter != "" with !strFilter.empty() in both loop branches, which is clearer and more efficient. As an optional refactor, you could hoist bool hasFilter = !strFilter.empty() before the loops to avoid repeated method calls.

Also applies to: 271-277


569-571: Apply .empty() check in 'addr' mode
Switching to !strFilter.empty() for the address filter is more idiomatic. For performance, you might cache this boolean before entering the loop.


627-630: Use .empty() in 'lastpaidblock' filter
Switching to !strFilter.empty() is more idiomatic. As a possible enhancement, consider filtering on the block height string itself if that’s a user use-case.


631-633: Apply .empty() check in 'lastpaidtime' mode
Good adoption of !strFilter.empty(). You may cache the result outside the loop to shave off a few function calls.


634-637: Refactor filter in 'payee' mode
Using .empty() here is spot-on. Optionally, you could also filter on the payeeStr and outpoint uniformly by caching hasFilter.


638-640: Enhance filter in 'owneraddress' mode
Currently only the outpoint is filtered. It may be more intuitive to also match strFilter against the owner address string returned.


641-643: Improve filter in 'pubkeyoperator' mode
For consistency, consider adding a check against the operator public key string in addition to the outpoint.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 567-643: Clang format differences found. Code formatting does not match the expected style.


649-651: Extend filter in 'votingaddress' mode
You currently filter only on the outpoint. For parity with other modes, consider matching strFilter against the voting address as well.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d80378 and d779b80.

📒 Files selected for processing (18)
  • src/evo/deterministicmns.cpp (1 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/mnhftx.h (1 hunks)
  • src/evo/simplifiedmns.cpp (2 hunks)
  • src/governance/classes.cpp (3 hunks)
  • src/governance/exceptions.cpp (2 hunks)
  • src/governance/governance.cpp (1 hunks)
  • src/governance/object.cpp (3 hunks)
  • src/governance/vote.cpp (1 hunks)
  • src/llmq/commitment.h (1 hunks)
  • src/llmq/snapshot.cpp (2 hunks)
  • src/masternode/meta.cpp (1 hunks)
  • src/netfulfilledman.cpp (1 hunks)
  • src/rpc/evo.cpp (4 hunks)
  • src/rpc/masternode.cpp (4 hunks)
  • src/test/util_tests.cpp (1 hunks)
  • src/txmempool.cpp (8 hunks)
  • src/util/string.h (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/util_tests.cpp (1)
src/util/string.h (1)
  • PadString (60-60)
src/txmempool.cpp (2)
src/txmempool.h (21)
  • tx (191-194)
  • tx (191-191)
  • tx (619-619)
  • tx (628-628)
  • tx (629-629)
  • tx (630-630)
  • tx (631-631)
  • tx (632-632)
  • tx (633-633)
  • tx (634-634)
  • tx (649-649)
  • tx (799-799)
  • tx (899-899)
  • tx (949-949)
  • tx (1007-1011)
  • tx (1007-1007)
  • newit (888-888)
  • it (731-731)
  • it (876-876)
  • it (910-910)
  • it (915-915)
test/functional/test_framework/messages.py (1)
  • COutPoint (433-451)
🪛 GitHub Actions: Clang Diff Format Check
src/governance/exceptions.cpp

[error] 30-30: Clang format differences found. Code formatting does not match the expected style.

src/governance/object.cpp

[error] 75-156: Clang format differences found. Code formatting does not match the expected style.

src/governance/vote.cpp

[error] 99-102: Clang format differences found. Code formatting does not match the expected style.

src/governance/classes.cpp

[error] 209-218: Clang format differences found. Code formatting does not match the expected style.

src/governance/governance.cpp

[error] 1132-1168: Clang format differences found. Code formatting does not match the expected style.

src/rpc/masternode.cpp

[error] 567-643: Clang format differences found. Code formatting does not match the expected style.

🔇 Additional comments (30)
src/util/string.h (1)

60-64: Well-implemented utility function for string padding.

The new PadString function provides a clean and reusable way to pad strings with spaces to reach a target length. The implementation is concise and handles both left and right padding with a clear default behavior. The [[nodiscard]] attribute appropriately encourages proper use of the return value.

src/txmempool.cpp (4)

688-689: Good optimization: caching transaction hash.

Storing the hash value in a local variable avoids redundant hash computations in the rest of the function. This is especially valuable since hash calculation can be relatively expensive.


788-789: Good optimization: caching transaction hash.

Consistent with the pattern established earlier, this change stores the hash in a local variable to avoid redundant calculations.


1020-1021: Good optimization: caching transaction hash.

Continuing the pattern of hash caching to improve performance.


1024-1025: Consistent usage of cached transaction hash in error logs.

The code consistently uses the cached hash value in logging statements, maintaining the optimization approach throughout the file.

Also applies to: 1045-1046, 1058-1059, 1067-1068

src/governance/vote.cpp (1)

99-102: Code formatting mismatch
Clang-format reported differences around the updated ToString method. Please run:

clang-format -i src/governance/vote.cpp

and ensure the file matches project style to resolve the GitHub Actions failure.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 99-102: Clang format differences found. Code formatting does not match the expected style.

src/llmq/snapshot.cpp (2)

26-26: Streamlined UniValue object initialization
Good refactor: replacing two-step UniValue obj; obj.setObject(); with direct construction UniValue obj(UniValue::VOBJ); enhances consistency and readability.


45-45: Streamlined UniValue object initialization
Same improvement in CQuorumRotationInfo::ToJson(). Consistent with the rest of the codebase.

src/evo/dmnstate.cpp (2)

40-40: Streamlined UniValue object initialization
Replaced default construction plus setObject() with UniValue obj(UniValue::VOBJ); in CDeterministicMNState::ToJson(). Improves uniformity across JSON serializers.


71-71: Streamlined UniValue object initialization
Applied the same direct-constructor pattern in CDeterministicMNStateDiff::ToJson(). Matches project conventions.

src/evo/mnhftx.h (1)

52-52: Streamlined UniValue object initialization
Refactored MNHFTx::ToJson() to construct the UniValue object with UniValue::VOBJ directly. Aligns with other JSON serializers in the evo module.

src/evo/simplifiedmns.cpp (2)

75-75: Streamlined UniValue object initialization
Updated CSimplifiedMNListEntry::ToJson() to use UniValue obj(UniValue::VOBJ); instead of obj.clear()/obj.setObject(). Improves consistency.


241-241: Streamlined UniValue object initialization
Same pattern applied in CSimplifiedMNListDiff::ToJson(). Good uniform refactor.

src/masternode/meta.cpp (1)

132-133: Good refactoring of string formatting.

Replacing the std::ostringstream approach with strprintf makes the code cleaner and more readable while maintaining the same functionality. This aligns with the PR's goal of simplifying string handling.

src/governance/classes.cpp (3)

27-27: Well-structured error message with function context.

Good use of __func__ to include the function name in error messages, making them more informative for debugging.


177-179: Improved error messaging pattern with separate log and throw.

Consistently using strprintf to format the error message, logging it, and then throwing it as an exception is a good pattern that improves code maintainability.


32-62: Consistent error message formatting.

All error messages in this block now follow a consistent pattern using strprintf with __func__ as the first parameter, improving readability and maintainability.

src/test/util_tests.cpp (1)

1831-1848: Good test coverage for the new PadString utility function.

The test case covers all the important scenarios:

  • Default left padding behavior
  • Explicit left and right padding options
  • Handling when padding size ≤ string size
  • Edge cases like empty strings

This ensures the functionality works as expected across various inputs.

src/evo/deterministicmns.cpp (1)

47-47: Improved UniValue initialization.

Using direct construction with the type (UniValue(UniValue::VOBJ)) instead of a two-step initialization process is more concise and potentially more efficient by avoiding an extra function call.

src/governance/exceptions.cpp (1)

6-6: Good addition of tinyformat.h header

Including tinyformat.h is necessary to support the subsequent use of strprintf. This is a good dependency management practice.

src/rpc/evo.cpp (5)

683-689: Improved string emptiness check

Good change to use the more idiomatic !str.empty() instead of str != "" for checking if a string is empty. This is more semantically clear and potentially more efficient as it directly checks the string's size property rather than performing a string comparison.


697-699: Improved string emptiness check

Consistent use of .empty() method for checking string emptiness. This follows modern C++ idioms.


1109-1115: Improved string emptiness check

Good continuation of the pattern to use .empty() for string emptiness checks throughout the codebase.


1119-1121: Improved string emptiness check

Consistent application of the .empty() method for string emptiness checks.


1125-1131: Improved string emptiness check

Consistent application of the .empty() method for string emptiness checks, completing the pattern throughout this file.

src/governance/governance.cpp (1)

1151-1153: Consistent use of strprintf for message formatting

This change maintains the consistent pattern of using strprintf with __func__ for log and error messages throughout the governance code.

src/rpc/masternode.cpp (4)

573-582: Replace ostringstream with strprintf + PadString in 'full' mode
The new strprintf + PadString approach is more concise and readable than manual stream formatting. Filter logic remains correct.


584-591: Streamline 'info' mode formatting
Using strprintf and PadString here cleans up the code and aligns with other modes. Filter usage is consistent.


593-607: Unify 'json/recent/evo' mode formatting and filter
The refactored construction of strInfo via strprintf improves readability, and the subsequent UniValue assembly is clear. Filter application is unchanged and correct.


644-647: Consistent .empty() check in 'status' mode
Good use of !strFilter.empty() and checking both status and outpoint.

Comment on lines 100 to 106
auto dmn = tip_mn_list.GetMNByCollateral(masternodeOutpoint);
int voteWeight = dmn != nullptr ? GetMnType(dmn->nType).voting_weight : 0;
std::ostringstream ostr;
ostr << masternodeOutpoint.ToStringShort() << ":"
<< nTime << ":"
<< CGovernanceVoting::ConvertOutcomeToString(GetOutcome()) << ":"
<< CGovernanceVoting::ConvertSignalToString(GetSignal()) << ":"
<< voteWeight;
return ostr.str();
return strprintf("%s:%s:%s:%s:%s",
masternodeOutpoint.ToStringShort(), nTime,
CGovernanceVoting::ConvertOutcomeToString(GetOutcome()), CGovernanceVoting::ConvertSignalToString(GetSignal()),
voteWeight);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Mismatched format specifiers in strprintf
The format string ("%s:%s:%s:%s:%s") uses %s for all placeholders, but nTime and voteWeight are integer types. This is undefined behavior. Please update the specifiers to the correct integer formats (for example, %lld or %" PRI64d " for nTime and %d for voteWeight), or convert these values to strings (e.g., via std::to_string) before passing them to strprintf.

Comment on lines 209 to 213
}

LogPrint(BCLog::GOBJECT, /* Continued */
"CSuperblock::ParsePaymentSchedule -- i = %d, amount string = %s, nAmount = %lld, proposalHash = %s\n",
"CSuperblock::%s -- i = %d, amount string = %s, nAmount = %lld, proposalHash = %s\n", __func__,
i, vecPaymentAmounts[i], nAmount, proposalHash.ToString());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix code formatting issues.

The Clang Diff Format Check shows formatting errors in this section, likely related to line indentation or breaks.

Please run clang-format on this file section or manually adjust the formatting to comply with the project's style guidelines.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 209-218: Clang format differences found. Code formatting does not match the expected style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant