Skip to content

Conversation

@lklimek
Copy link
Collaborator

@lklimek lklimek commented Feb 11, 2025

Issue being fixed or feature implemented

For single-node development environments, we need a way to change number of votes (voting threshold) in order to allow single-node networks to pass voting with 1 vote.

We also want this to be documented in the blockchain, as we want some accountability in case someone tries to change the threshold on a running network (like mainnet).

What was done?

  • added voting threshold to ConsensusParams.ValidatorParams.VotingPowerThreshold
  • fixed bug in gogoproto that causes panic for optional fields

How Has This Been Tested?

  • covered with unit test
  • implemented the threshold in e2e tests

Breaking Changes

New field added to ConsensusParams, affecting ABCI protocol. ABCI protocol version bumped.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced an explicit voting power threshold for validators to enhance consensus decisions.
    • Improved genesis state configuration with flexible validator set settings.
    • Added configuration parameter voting_power_threshold in the test network setup.
    • Enhanced testing framework with comprehensive checks for voting behavior related to thresholds.
    • New field VotingPowerThreshold added to the Manifest and Testnet structs for better management of voting power thresholds.
    • Upgraded the ABCI version to 1.3.0, incorporating these consensus enhancements.
  • Chores

    • Updated build and dependency processes to ensure compatibility with revised installation methods.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2025

Walkthrough

This update revises dependency installation in CI/CD (workflow and Makefile) and systematically updates how validator sets are created. Most changes add an extra parameter (often nil) in calls to the NewValidatorSet function across consensus, evidence, state, and testing modules. New fields for voting power thresholds are introduced in protobuf messages and core types, accompanied by enhanced validation logic. Additionally, minor adjustments to context naming and test setups have been made, and the semantic version has been bumped from 1.2.0 to 1.3.0.

Changes

File(s) Change Summary
.github/workflows/check-generated.yml
Makefile
Updated CI workflows and Makefile dependency management: replaced the direct installation command for the gogoproto plugin with commands to clone a specific fork containing a fix; updated repository paths and error messages.
internal/consensus/... (replay_test.go, replayer.go, replayer_test.go, height_proposer_test.go) Revised consensus initialization and test functions: added a nil parameter in various NewValidatorSet calls and modified handshake and validator update flows.
internal/evidence/... (pool_test.go, reactor_test.go, verify_test.go) Adjusted evidence tests: renamed unused context parameters and updated NewValidatorSet invocations to include an extra parameter.
internal/state/... (current_round_state.go, state.go, state_test.go) Enhanced state initialization and validation: incorporated an additional parameter into validator set creation and added validation for voting power thresholds.
internal/test/factory/validator_set.go
light/... (helpers_test.go, provider/http/http.go)
Refined test utilities and light module functionality: NewValidatorSet calls now include an extra nil argument.
proto/tendermint/types/*.proto Extended protobuf definitions: added a new field for voting_power_threshold in both ValidatorParams and ValidatorSet messages.
rpc/client/...
test/e2e/...
Updated evidence and end-to-end tests: modified NewValidatorSet calls to include an additional parameter for consistency.
types/... (evidence.go, evidence_test.go, generator.go, params.go, params_test.go, protobuf.go, protobuf_test.go, validation_test.go, validator_set.go, validator_set_test.go, vote_set_test.go) Systematic update across core types: new NewValidatorSet signature now accepts an extra parameter; added fields and validations for voting power thresholds; corresponding test cases and helper functions were updated.
version/version.go Bumped the ABCI semantic version from "1.2.0" to "1.3.0".

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Application/Tests
    participant VSFactory as ValidatorSet Factory
    participant VS as ValidatorSet

    Caller->>VSFactory: Call NewValidatorSet(validators, pubKey, llmqType, quorumHash, hasPublicKeys, additionalParam)
    VSFactory-->>Caller: Returns ValidatorSet instance (with voting_power_threshold set)
    Note over VS: Validates and assigns voting power threshold if provided.
Loading

Suggested reviewers

  • QuantumExplorer
  • shumkov

Poem

I hopped across the code so grand,
Adjusted tests and workflows by hand,
With validator sets now extra wise,
Thresholds bloom under springtime skies,
A bunny cheers with a joyful heart—
CodeRabbit leaps, a work of art!
🐰🌸

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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.

@lklimek
Copy link
Collaborator Author

lklimek commented Feb 18, 2025

@coderabbitai review all

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2025

@lklimek I'll review all the changes in the PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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: 6

🧹 Nitpick comments (9)
Makefile (1)

20-22: Update GOGOPROTO_PATH to Use the Patched Repository

The change updates the GOGOPROTO_PATH to point to github.com/lklimek/gogoproto pinned to a specific commit (564fd924f58c5d076b0ad8e3f1c6fb54d065cbbe), replacing the old Cosmos version. This ensures that builds leverage the fixed version of the plugin for the gogoproto bug.

Note: There is an extra space in "go list" which may be harmless but could be tidied for consistency.

types/validator_set.go (1)

160-181: Enforce the TODO check for alignment between vals.VotingPowerThreshold and ValidatorParams.

You have a TODO (line 160) to confirm vals.VotingPowerThreshold matches the ValidatorParams. This helps detect any mismatch in threshold usage.

Would you like guidance or a patch to perform that check automatically?

internal/consensus/versioned/selectproposer/height_proposer_test.go (1)

31-31: Consider setting an explicit voting power threshold.

While passing nil works, consider setting an explicit voting power threshold to better reflect real-world validator set configurations.

-	}, bls12381.GenPrivKey().PubKey(), btcjson.LLMQType_5_60, crypto.RandQuorumHash(), true, nil)
+	}, bls12381.GenPrivKey().PubKey(), btcjson.LLMQType_5_60, crypto.RandQuorumHash(), true, types.DefaultVotingPowerThreshold)
test/e2e/tests/validator_test.go (1)

189-189: Consider setting an explicit voting power threshold in test setup.

While passing nil works for test setup, consider setting an explicit voting power threshold for better test coverage.

-	vs := types.NewValidatorSet(makeVals(valMap), thresholdPublicKey, quorumType, quorumHash, true, nil)
+	vs := types.NewValidatorSet(makeVals(valMap), thresholdPublicKey, quorumType, quorumHash, true, types.DefaultVotingPowerThreshold)
internal/state/state.go (1)

384-389: Consider adding validation for validator parameters.

The new valParams variable is correctly initialized from genDoc.ConsensusParams, but it might be beneficial to add validation for the voting power threshold if it's present.

Consider adding validation before using the validator parameters:

 var valParams *types.ValidatorParams
 if genDoc.ConsensusParams != nil {
     valParams = &genDoc.ConsensusParams.Validator
+    if valParams.VotingPowerThreshold != nil {
+        // Ensure the threshold is within valid bounds
+        if *valParams.VotingPowerThreshold == 0 {
+            return State{}, fmt.Errorf("voting power threshold cannot be zero")
+        }
+    }
 }

Also applies to: 390-392

internal/consensus/replayer.go (1)

354-357: Consider documenting the commented-out code.

The commented-out code suggests a potential feature for updating the voting threshold of an existing validator set. Consider adding a TODO comment explaining why this code is commented out and when it might be enabled.

-// } else if valParams != nil && valParams.VotingPowerThreshold != nil {
-// 	// we update the existing validator set with the new voting threshold
-// 	state.Validators.VotingPowerThreshold = *valParams.VotingPowerThreshold
+// TODO(#issue): Enable updating voting threshold of existing validator set
+// } else if valParams != nil && valParams.VotingPowerThreshold != nil {
+// 	// we update the existing validator set with the new voting threshold
+// 	state.Validators.VotingPowerThreshold = *valParams.VotingPowerThreshold
types/params.go (2)

72-73: Consider documenting the VotingPowerThreshold field.

The new field would benefit from documentation explaining its purpose, valid values, and when it should be used.

 type ValidatorParams struct {
 	PubKeyTypes          []string `json:"pub_key_types"`
+	// VotingPowerThreshold is an optional parameter that defines the minimum voting power
+	// required for validator set decisions. When nil, the default threshold is used.
+	// Must be greater than 0 when set.
 	VotingPowerThreshold *uint64  `json:"threshold,omitempty"`
 }

244-280: Consider adding validation in ToProto and ValidatorParamsFromProto.

The conversion methods should validate the voting power threshold to ensure it's greater than 0 when set.

 func (val *ValidatorParams) ToProto() *tmproto.ValidatorParams {
 	if val == nil {
 		return nil
 	}
+
+	if val.VotingPowerThreshold != nil && *val.VotingPowerThreshold == 0 {
+		panic("voting power threshold cannot be zero")
+	}

 	params := tmproto.ValidatorParams{
 		PubKeyTypes: val.PubKeyTypes,
 	}
 func ValidatorParamsFromProto(pbValParams *tmproto.ValidatorParams) ValidatorParams {
 	var params = ValidatorParams{
 		PubKeyTypes: []string{},
 	}

 	if pbValParams != nil {
 		if pbValParams.XVotingPowerThreshold != nil {
 			val := pbValParams.GetVotingPowerThreshold()
+			if val == 0 {
+				panic("voting power threshold cannot be zero")
+			}
 			params.VotingPowerThreshold = &val
 		}
proto/tendermint/types/params.proto (1)

61-79: Consider adding examples to validation rules and clarify nullable behavior.

The validation rules are well-documented, but consider:

  1. Adding examples to illustrate the threshold calculation for different validator set sizes.
  2. Clarifying whether the field should be nullable since it's marked as optional but doesn't use the gogoproto.nullable annotation.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 414d46d and 0f37594.

⛔ Files ignored due to path filters (23)
  • abci/types/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/blocksync/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/consensus/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/consensus/wal.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/crypto/keys.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/crypto/proof.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/libs/bits/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/mempool/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/p2p/conn.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/p2p/pex.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/p2p/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/privval/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/state/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/statesync/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/block.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/canonical.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/dash.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/events.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/evidence.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/params.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/types.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/types/validator.pb.go is excluded by !**/*.pb.go
  • proto/tendermint/version/types.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (33)
  • .github/workflows/check-generated.yml (1 hunks)
  • Makefile (2 hunks)
  • internal/consensus/replay_test.go (1 hunks)
  • internal/consensus/replayer.go (2 hunks)
  • internal/consensus/replayer_test.go (1 hunks)
  • internal/consensus/versioned/selectproposer/height_proposer_test.go (1 hunks)
  • internal/evidence/pool_test.go (2 hunks)
  • internal/evidence/reactor_test.go (2 hunks)
  • internal/evidence/verify_test.go (1 hunks)
  • internal/state/current_round_state.go (2 hunks)
  • internal/state/state.go (2 hunks)
  • internal/state/state_test.go (1 hunks)
  • internal/test/factory/validator_set.go (1 hunks)
  • light/helpers_test.go (1 hunks)
  • light/provider/http/http.go (1 hunks)
  • proto/tendermint/types/dash_test.go (3 hunks)
  • proto/tendermint/types/params.proto (1 hunks)
  • proto/tendermint/types/validator.proto (1 hunks)
  • rpc/client/evidence_test.go (1 hunks)
  • test/e2e/runner/evidence.go (1 hunks)
  • test/e2e/tests/validator_test.go (2 hunks)
  • types/evidence.go (3 hunks)
  • types/evidence_test.go (1 hunks)
  • types/generator.go (1 hunks)
  • types/params.go (6 hunks)
  • types/params_test.go (1 hunks)
  • types/protobuf.go (3 hunks)
  • types/protobuf_test.go (1 hunks)
  • types/validation_test.go (1 hunks)
  • types/validator_set.go (7 hunks)
  • types/validator_set_test.go (5 hunks)
  • types/vote_set_test.go (4 hunks)
  • version/version.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
internal/consensus/versioned/selectproposer/height_proposer_test.go (1)
Learnt from: lklimek
PR: dashpay/tenderdash#959
File: internal/consensus/versioned/selectproposer/height_proposer.go:93-93
Timestamp: 2024-11-12T14:56:12.333Z
Learning: The fix in `height_proposer.go` eliminates the `validator set hash mismatch` error during quorum rotation, so no additional error handling is required in the `/validators` endpoint.
🪛 GitHub Check: golangci-lint
internal/evidence/reactor_test.go

[failure] 102-102:
unused-parameter: parameter 'chdesc' seems to be unused, consider removing or renaming it to match ^_ (revive)

types/validator_set.go

[failure] 429-429:
G115: integer overflow conversion uint64 -> int64 (gosec)

🪛 GitHub Actions: Golang Linter
types/validator_set.go

[error] 429-429: G115: integer overflow conversion uint64 -> int64 (gosec)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: test_apps
  • GitHub Check: test_abci_cli
  • GitHub Check: tests (03)
  • GitHub Check: e2e-test (rotate)
  • GitHub Check: e2e-test (dashcore)
  • GitHub Check: Super linter
🔇 Additional comments (39)
.github/workflows/check-generated.yml (1)

78-86: Forked gogoproto Installation Update

The new commands clone a fork of the gogoproto repository (branch fix/panic-marshalto-nil-m) and install the protoc-gen-gogofaster from that source. This change addresses a panic issue with nil marshaling. The implementation correctly cleans up the temporary clone.

Makefile (1)

118-121: Align Dependency Error Message for gogofaster Plugin

The error message under the check-proto-deps target now correctly instructs users to install the protoc-gen-gogofaster plugin from the new repository and commit. This ensures consistency with the updated dependency sources in both the workflow and the Makefile.

types/validator_set.go (4)

83-91: Good integration of voting power threshold in constructor.

The logic to set vals.VotingPowerThreshold from validatorParams.VotingPowerThreshold is clear. Just be sure all call sites are updated to provide (or omit) the parameter correctly.


107-116: Simplify usage by relying on existing constructor.

Forwarding to NewValidatorSet is a clean approach. This ensures consistent initialization in a single place.


120-120: No concerns with creating an empty validator set.

Returning a validator set with no threshold is fine as a default approach, since no voting is expected in an empty set.


937-938: Properly populating VotingPowerThreshold in proto structure.

Serializing the threshold into the proto is correct, ensuring the value is transferred consistently.

version/version.go (1)

14-14: Version bump is appropriate.

Updating ABCISemVer from “1.2.0” to “1.3.0” indicates a semver increment consistent with breaking changes (new field in ConsensusParams).

proto/tendermint/types/dash_test.go (2)

7-8: New import statement is fine.

No issues with referencing the dashpay/tenderdash/proto/tendermint/types package.


60-62: Marshaling test logic confirmed.

The test now checks marshalling of Vote objects without expecting a panic. This accurately reflects the revised code behavior.

internal/test/factory/validator_set.go (1)

47-54: LGTM! Well-structured voting power threshold calculation.

The threshold calculation is logical, multiplying the number of validators by the default voting power to determine the total threshold. This implementation aligns with the PR's objective of allowing configurable thresholds.

rpc/client/evidence_test.go (1)

42-42: LGTM! Appropriate use of nil for test context.

The update correctly adapts to the new NewValidatorSet signature while using nil for the threshold parameter, which is suitable for this test context where specific voting power thresholds aren't critical.

types/protobuf_test.go (1)

46-46: LGTM! Consistent with other test updates.

The change appropriately adds the nil threshold parameter to NewValidatorSet, maintaining consistency with other test files while focusing on the core purpose of testing ABCI validator conversion.

types/validation_test.go (1)

26-26: LGTM!

The change correctly updates the NewValidatorSet call to include the new voting power threshold parameter, using nil to maintain default behavior in tests.

types/protobuf.go (2)

163-172: Good use of test-only restriction!

The function is properly restricted to test usage with clear documentation and runtime checks.


193-193: Consistent with voting power threshold changes.

The nil parameter maintains consistency with the broader changes to support configurable voting power thresholds.

test/e2e/runner/evidence.go (1)

71-74: LGTM!

The change correctly updates the NewValidatorSet call to include the new voting power threshold parameter, maintaining default behavior in the evidence injection tests.

internal/evidence/verify_test.go (1)

42-42: LGTM!

The change correctly updates the NewValidatorSet call to include the new voting power threshold parameter, maintaining default behavior in the evidence verification tests.

internal/consensus/replayer_test.go (1)

201-203: LGTM! Good synchronization of voting power threshold.

The code correctly synchronizes the genesis validator set's voting power threshold with the one from the validator set, and the comment clearly explains the rationale.

test/e2e/tests/validator_test.go (1)

260-260: LGTM! Good use of consensus params validator settings.

The code correctly uses the validator settings from consensus params when creating a new validator set.

types/evidence_test.go (1)

167-169: LGTM!

The addition of the nil parameter for the voting power threshold maintains the existing test behavior while supporting the new feature.

light/provider/http/http.go (1)

241-241: LGTM!

The addition of the nil parameter for the voting power threshold maintains the existing light client behavior while supporting the new feature.

internal/state/current_round_state.go (3)

331-333: LGTM!

The validator set creation now correctly includes the validator parameters, allowing for custom voting power thresholds.


344-346: LGTM!

The code properly handles the optional voting power threshold by checking for nil before assignment.


349-349: Enhanced error handling with ValidateBasic check.

The function now validates the validator set before returning it, ensuring the voting power threshold and other parameters are valid.

types/params_test.go (1)

221-222: LGTM!

The addition of the VotingPowerThreshold field with a nil default value maintains backward compatibility while supporting the new feature.

internal/consensus/replayer.go (1)

345-349: LGTM! Validator parameters are correctly handled.

The implementation correctly extracts validator parameters from the response and handles the case when they are not present.

types/evidence.go (1)

494-496: LGTM! Good safety check for test-only code.

The runtime check ensures that the mock function is only used in tests, preventing accidental usage in production code.

internal/evidence/reactor_test.go (2)

102-102: Approve parameter renaming to indicate unused context.

The renaming of ctx to _ctx follows Go's convention for indicating unused parameters.

Also applies to: 109-109

🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 102-102:
unused-parameter: parameter 'chdesc' seems to be unused, consider removing or renaming it to match ^_ (revive)


547-554: LGTM! Validator set initialization updated.

The addition of the nil parameter to NewValidatorSet aligns with the broader changes to support voting power threshold configuration.

internal/evidence/pool_test.go (1)

133-133: LGTM! Validator set initialization updated.

The addition of the nil parameter to NewValidatorSet aligns with the broader changes to support voting power threshold configuration.

types/vote_set_test.go (2)

516-516: LGTM! Validator set initialization updated.

The addition of the nil parameter to NewValidatorSet aligns with the broader changes to support voting power threshold configuration.


552-639: LGTM! Comprehensive test coverage for validator threshold.

The new test function provides thorough coverage of voting threshold behavior across different network sizes, including edge cases for single-node and two-node networks.

internal/state/state_test.go (1)

357-359: LGTM! Improved test setup with proper validator initialization.

The changes enhance test reliability by:

  1. Initializing state with a proper random validator set
  2. Using the threshold public key from the validator set for consistency

Also applies to: 364-364

proto/tendermint/types/validator.proto (1)

10-18: LGTM! The field addition maintains consistency with ValidatorParams.

The new field and its relationship with ValidatorParams.voting_power_threshold are clearly documented.

types/validator_set_test.go (4)

236-236: LGTM! Consistent with other test cases.

The benchmark test correctly includes the new parameter.


281-282: LGTM! Empty validator set test is updated correctly.

The test case for empty validator set properly includes the new parameter.


313-315: LGTM! Panic test cases are updated consistently.

The test cases for validating panic conditions are properly updated with the new parameter.

Also applies to: 322-324, 334-336


27-27:

✅ Verification successful

Verify the intended behavior of passing nil for voting_power_threshold.

The test is passing nil for the new voting_power_threshold parameter. Confirm that this is the intended behavior and that it correctly tests the default threshold calculation based on LLMQ quorum type.


🏁 Script executed:

#!/bin/bash
# Search for other test files that might provide insights into the expected behavior
rg -A 5 "NewValidatorSet.*nil.*btcjson.LLMQType" --type go

Length of output: 893


Passing nil for voting_power_threshold appears to be the intended behavior.

  • The test file consistently passes nil for the new voting_power_threshold parameter in all calls to NewValidatorSet.
  • This usage suggests that the test is deliberately leveraging the default threshold calculation based on the LLMQ quorum type.
  • No conflicting tests or usage patterns were found that indicate a need for a non-nil value.
internal/consensus/replay_test.go (1)

1279-1286: LGTM! Handshake test is updated correctly.

The test case for validator set updates during handshake properly includes the new parameter.

@lklimek lklimek added this to the v1.5 milestone Mar 3, 2025
@lklimek lklimek marked this pull request as ready for review March 4, 2025 13:36
Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
types/validator_set.go (1)

998-999: Deserializing VotingPowerThreshold from proto.

The deserialization properly retrieves the field from the protobuf representation.

Note that unlike the QuorumVotingThresholdPower method, there's no boundary check here when deserializing. Consider adding a similar check to prevent potential overflow issues when parsing untrusted data.

- vals.VotingPowerThreshold = vp.GetVotingPowerThreshold()
+ threshold := vp.GetVotingPowerThreshold()
+ if threshold > math.MaxInt64 {
+   return nil, fmt.Errorf("voting power threshold %d exceeds maximum allowed value %d", threshold, math.MaxInt64)
+ }
+ vals.VotingPowerThreshold = threshold
test/e2e/networks/single.toml (1)

1-2: Added voting_power_threshold configuration parameter.

The configuration parameter is properly added to the single-node test network configuration with a reasonable value of 100, which matches the DefaultDashVotingPower constant.

For clarity, consider adding a comment to explain why this value is chosen for a single-node network, referencing the rules specified in the protocol documentation.

-voting_power_threshold = 100
+# For single-node networks, threshold must equal the validator's voting power (100)
+voting_power_threshold = 100
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f37594 and 2233fb4.

📒 Files selected for processing (9)
  • internal/evidence/reactor_test.go (2 hunks)
  • internal/state/state_test.go (3 hunks)
  • proto/tendermint/types/params.proto (1 hunks)
  • test/e2e/networks/single.toml (1 hunks)
  • test/e2e/pkg/manifest.go (1 hunks)
  • test/e2e/pkg/testnet.go (2 hunks)
  • test/e2e/runner/setup.go (1 hunks)
  • types/validator_set.go (7 hunks)
  • types/vote_set_test.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/state/state_test.go
  • internal/evidence/reactor_test.go
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: test_abci_cli
  • GitHub Check: test_apps
  • GitHub Check: tests (01)
  • GitHub Check: e2e-test (rotate)
  • GitHub Check: Super linter
  • GitHub Check: e2e-test (dashcore)
🔇 Additional comments (15)
proto/tendermint/types/params.proto (1)

61-79: Comprehensive documentation of new voting_power_threshold field.

The added field is well-documented with clear validation rules based on validator set size. This is excellent and helps both users and developers understand the constraints and behavior.

I have two minor suggestions:

  1. The commented-out [(gogoproto.nullable) = true] annotation may be confusing. Either remove it entirely or uncomment it if needed.
  2. Consider adding a note about which component enforces these validation rules (appears to be in ValidatorSet.ValidateBasic()).
types/vote_set_test.go (3)

514-517: Updated function signature correctly passes nil parameter.

This is a good update to ensure backward compatibility with existing calling code.


552-647: Well-structured test cases for the validator params threshold.

The new test function thoroughly tests various configurations including single-node, two-node, and larger networks with different thresholds. This comprehensive testing is excellent.

A few observations:

  1. The test case uses a threshold of 1 for a single-node network. Based on previous review comments, this might cause a panic in the bls-signatures C++ library. Has this issue been addressed elsewhere?
  2. The test correctly verifies that voting behavior respects the specified thresholds.
  3. The conditional execution based on network size in lines 625-644 is a good approach to avoid out-of-bounds errors.

742-743: Updated NewValidatorSet call with validator parameters.

The changes correctly pass the validator params parameter to the NewValidatorSet function.

types/validator_set.go (7)

68-70: New VotingPowerThreshold field with proper documentation.

The field is well-documented and properly tagged for JSON serialization.


82-91: Properly initialize VotingPowerThreshold from validatorParams.

The code correctly handles the case where validatorParams might be nil and safely dereferences the optional VotingPowerThreshold value.


103-115: Updated NewValidatorSetCheckPublicKeys with params parameter.

The function signature was updated correctly to accept the params parameter, maintaining the original behavior while adding support for the new voting power threshold.


119-121: Updated NewEmptyValidatorSet for consistency.

The nil parameter for validatorParams maintains the original behavior while supporting the new interface.


160-182: Comprehensive validation for VotingPowerThreshold.

The implementation properly validates the threshold based on validator set size, following the rules documented in the proto file. Each validator set size range has specific validation rules which are clearly implemented.


942-943: Added VotingPowerThreshold to proto serialization.

The serialization properly includes the new field in the protobuf representation.


429-435:

✅ Verification successful

Fixed potential integer overflow issue.

The implementation now includes a boundary check to prevent integer overflow when casting uint64 to int64, as identified in previous reviews. The panic is a reasonable approach for this critical error condition that should never happen in practice.


🏁 Script executed:

#!/bin/bash
# Check if there are places where VotingPowerThreshold could exceed math.MaxInt64
# Since this is a potential issue, we should verify if there are any other locations 
# where this field is used without bounds checking

rg -A 5 -B 5 "\bVotingPowerThreshold\b" --type go | grep -v "math.MaxInt64"

Length of output: 25332


Integer Overflow Boundary Check in ValidatorSet Verified

The boundary check added to prevent integer overflow when converting VotingPowerThreshold from uint64 to int64 in types/validator_set.go (function QuorumVotingThresholdPower) has been correctly implemented. Our investigation confirms that:

  • The check against math.MaxInt64 is present before performing the conversion.
  • No additional instances in the codebase require a similar safeguard, as other usages of VotingPowerThreshold either avoid direct conversion or are in generated/test files where this check isn’t applicable.

This addresses the potential overflow issue as intended.

test/e2e/runner/setup.go (1)

182-185: Implementation looks correct for handling the voting power threshold

The code correctly checks if the VotingPowerThreshold in the testnet is greater than 0, and if so, sets it in the genesis document's consensus parameters. This is a clean way to make the voting power threshold configurable.

test/e2e/pkg/manifest.go (1)

20-23: Well-documented threshold field addition

The addition of the VotingPowerThreshold field with a clear comment explaining its purpose and typical calculation is good practice. The TOML tag is properly defined for serialization.

test/e2e/pkg/testnet.go (2)

103-103: Field addition is properly placed

The VotingPowerThreshold field is appropriately placed among the other consensus-related fields in the Testnet struct.


220-220: Correct initialization from manifest

The VotingPowerThreshold field is properly initialized from the manifest value, ensuring consistent configuration flow from TOML to testnet to genesis.

@github-actions
Copy link

github-actions bot commented Apr 6, 2025

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added Stale and removed Stale labels Apr 6, 2025
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
internal/consensus/replayer.go (1)

356-358: Remove commented-out code.

The commented-out code appears to be a leftover from a previous implementation or a placeholder for future changes. Commented-out code can confuse readers and add noise to the codebase.

- 	// } else if valParams != nil && valParams.VotingPowerThreshold != nil {
- 	// 	// we update the existing validator set with the new voting threshold
- 	// 	state.Validators.VotingPowerThreshold = *valParams.VotingPowerThreshold
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d67ea30 and 2d3f935.

📒 Files selected for processing (1)
  • internal/consensus/replayer.go (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
internal/consensus/replayer.go (2)
types/params.go (3)
  • ValidatorParams (71-74)
  • ConsensusParams (37-45)
  • ValidatorParamsFromProto (264-280)
types/validator_set.go (2)
  • NewValidatorSet (82-98)
  • NewValidatorSetCheckPublicKeys (102-116)
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: test_abci_cli
  • GitHub Check: test_apps
  • GitHub Check: build
  • GitHub Check: e2e-test (rotate)
  • GitHub Check: e2e-test (dashcore)
  • GitHub Check: tests (02)
  • GitHub Check: tests (01)
  • GitHub Check: golangci-lint
  • GitHub Check: Super linter
🔇 Additional comments (3)
internal/consensus/replayer.go (3)

345-351: The new implementation correctly handles validator parameters.

The added code properly initializes valParams either from the response from the InitChain call or from the genesis document. This allows for configuring the validator set with the appropriate voting power threshold.


416-419: Good implementation for obtaining validator parameters.

This change correctly initializes validatorParams from the genesis document's consensus parameters, which is then passed to the validator set creation functions.


426-426: Effective use of the new parameter.

Passing &validatorParams to NewValidatorSetCheckPublicKeys ensures that the voting power threshold is properly incorporated during the validation process, supporting the PR's objective of enabling single-node development environments to validate with just one vote.

@lklimek lklimek merged commit f51d5c7 into v1.5-dev Apr 16, 2025
21 checks passed
@lklimek lklimek deleted the feat/consensus-param-signature-threshold branch April 16, 2025 09:30
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.

3 participants