Skip to content

test: fix TestBlockSearch_Success and TestCommit_VerifyCometBFTLightClientCompatibility_MultipleBlocks#137

Merged
julienrbrt merged 7 commits intomainfrom
feat/fix-comet-bft-light-test
Jun 19, 2025
Merged

test: fix TestBlockSearch_Success and TestCommit_VerifyCometBFTLightClientCompatibility_MultipleBlocks#137
julienrbrt merged 7 commits intomainfrom
feat/fix-comet-bft-light-test

Conversation

@randygrok
Copy link
Copy Markdown
Contributor

@randygrok randygrok commented Jun 17, 2025

Overview

Summary by CodeRabbit

  • Tests
    • Improved and refactored block signing and verification logic in multi-block compatibility tests to ensure signatures are properly formatted and verifiable.
    • Enhanced test reliability by generating realistic keys and signatures and simplifying header construction.
    • Updated block search tests with realistic block data and removed skip directives for more comprehensive validation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 17, 2025

Walkthrough

The tests in pkg/rpc/core/blocks_test.go were enhanced to use realistic CometBFT Ed25519 key generation and signing. The TestBlockSearch_Success was updated to remove skipping and create realistic block data. The TestCommit_VerifyCometBFTLightClientCompatibility_MultipleBlocks test was refactored to include proper signing, mocking, and light client verification flows with helper functions and a MockSigner.

Changes

File(s) Change Summary
pkg/rpc/core/blocks_test.go Updated TestBlockSearch_Success to remove skip and add realistic block data; refactored TestCommit_VerifyCometBFTLightClientCompatibility_MultipleBlocks to use Ed25519 keys, add signing, mocking, and light client verification; added MockSigner and multiple helper functions for block creation, signing, mocking, RPC calls, and verification.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Function
    participant Keygen as CometBFT Ed25519 Keygen
    participant Signer as MockSigner
    participant Rollkit as Rollkit Store
    participant RPC as Commit RPC
    participant LightClient as Light Client Verification

    Test->>Keygen: Generate Ed25519 private key
    Test->>Signer: Derive MockSigner from private key
    loop For each block
        Test->>Test: Create Rollkit block data and header
        Test->>Signer: Sign vote sign bytes for block
        Test->>Rollkit: Mock signed block in store
        Test->>RPC: Call Commit RPC for block height
        RPC->>Test: Return commit result with signatures
        alt First block
            Test->>LightClient: Verify commit against fixed validator set
        else Subsequent blocks
            Test->>LightClient: Perform full light client verification
        end
        Test->>Test: Assert commit result validity
    end
Loading

Suggested reviewers

  • julienrbrt

Poem

🐇 In burrows deep where code does play,
Blocks and commits now find their way.
Keys are forged with Ed25519 light,
Signatures dance in perfect flight.
Tests hop forward, clear and bright,
Verifying each block's right.
🐰✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2

✨ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.

@randygrok randygrok changed the title fix IBC tests test: fix IBC tests Jun 17, 2025
@randygrok randygrok marked this pull request as ready for review June 17, 2025 20:40
Copy link
Copy Markdown
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: 3

🧹 Nitpick comments (5)
pkg/rpc/core/blocks_test.go (5)

114-126: Prefer a single key type to avoid subtle signature mismatches

Converting the CometBFT private key into a libp2p key and then back to an address mixes three representations (CometBFT priv/pub, libp2p priv/pub, CometBFT addr).
Signing with the libp2p key may diverge from CometBFT’s Ed25519 implementation on edge cases (e.g. context separation). Consider:

  1. Sign directly with ed25519.PrivKey#Sign and drop the libp2p conversion, or
  2. If libp2p is required elsewhere, at least add a unit check that cmtPubKey.VerifySignature(msg, sig) passes to guarantee interchangeability.

This keeps the test deterministic and documents the intent.


160-166: Remove redundant slice operation and clarify address source

aggregatorPubKeyBytes already contains a 20-byte CometBFT address; [:20] is redundant and risks a panic if the length ever changes.

- ProposerAddress: aggregatorPubKeyBytes[:20],
+ ProposerAddress: aggregatorPubKeyBytes,

A brief comment stating “CometBFT validator address (20 bytes)” would aid future readers.


168-197: Placeholders may generate invalid hashes

The zeroed tempLastCommit and placeholder signature can yield an invalid block hash, making the subsequent vote/sign bytes non-canonical.
Instead, either:

  • Use nil for the last commit when calling ToABCIBlock, or
  • Generate a minimal but valid commit via types.CommitSignatures.

This removes guesswork and keeps the test aligned with real chain behaviour.


221-224: Add explicit verification of the produced signature

Right after signing, verify with cmtPubKey.VerifySignature(finalSignBytes, realSignature) to guarantee that the libp2p-generated signature is indeed valid for CometBFT. This inexpensive check would have caught any cross-library mismatch early.


249-253: Assertion duplicates equality check

You already prove the signature is non-zero with the equality assertion against realSignature; the preceding NotEqual is redundant and can be dropped to keep the test concise.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fa80885 and f872ab3.

📒 Files selected for processing (1)
  • pkg/rpc/core/blocks_test.go (2 hunks)

Comment thread pkg/rpc/core/blocks_test.go Outdated
Comment on lines 111 to 112
Signer: nil, // Simulating a non-aggregator node that doesn't sign
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reset global env after test to avoid leakage

env is package-level; mutating it without restoring can make other tests observe stale mocks or a nil signer.
Capture the original value and restore it in t.Cleanup, or move construction inside a helper that returns a fresh *Environment.

🤖 Prompt for AI Agents
In pkg/rpc/core/blocks_test.go around lines 111 to 112, the test modifies the
package-level variable `env` without resetting it, which can cause test
pollution. To fix this, capture the original `env` value before the test
modifies it and use `t.Cleanup` to restore `env` to its original state after the
test completes. Alternatively, refactor the test to construct and use a fresh
`*Environment` instance locally instead of modifying the global `env`.

Comment thread pkg/rpc/core/blocks_test.go Outdated
Comment on lines 235 to 237
// Mock RollkitStore to return the properly signed block (as a non-aggregator would receive it)
mockRollkitStore.On("GetBlockData", mock.Anything, blockHeight).Return(rollkitSignedHeader, blockData, nil).Once()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Assert mock expectations to avoid silent test passes

mockRollkitStore.On(...).Once() is configured inside the loop but AssertExpectations(t) is never called for any of the mocks in this test.
Add t.Cleanup(func(){ mockRollkitStore.AssertExpectations(t); /* others */ }) to ensure all expectations are met.

🤖 Prompt for AI Agents
In pkg/rpc/core/blocks_test.go around lines 235 to 237, the mockRollkitStore
mock is set up with expectations using On(...).Once() but the test does not call
AssertExpectations(t) to verify these expectations, which can cause silent test
passes. To fix this, add a t.Cleanup function in the test that calls
mockRollkitStore.AssertExpectations(t) and any other relevant mocks to ensure
all mock expectations are properly asserted after the test runs.

Comment thread pkg/rpc/core/blocks_test.go Outdated
Comment on lines 255 to 274
if i == 1 {
// For the first block, we use it as the trusted header
trustedHeader := commitResult.SignedHeader

// Verify that the trusted header itself has a valid signature
err = fixedValSet.VerifyCommitLight(chainID, trustedHeader.Commit.BlockID,
trustedHeader.Height, trustedHeader.Commit)
// Note: Light client verification may fail due to complex validator set handling
// but the important thing is that signatures are properly formatted
_ = err // We acknowledge the verification but don't fail the test
} else {
trustingPeriod := 3 * time.Hour
trustLevel := math.Fraction{Numerator: 1, Denominator: 1}
maxClockDrift := 10 * time.Second

err = light.Verify(&trustedHeader, fixedValSet, &commitResult.SignedHeader, fixedValSet, trustingPeriod, time.Unix(0, int64(rollkitHeader.BaseHeader.Time)), maxClockDrift, trustLevel)
require.NoError(err, "failed to pass light.Verify() for block %d", blockHeight)
trustedHeader = commitResult.SignedHeader
}

// Update last hashes for the next iteration
currentRollkitHeaderHash := rollkitHeader.Hash()
lastRollkitHeaderHash = BytesToSliceHash(currentRollkitHeaderHash)

if commitResult.Commit != nil {
lastRollkitCommitHash = BytesToSliceHash(commitResult.Commit.Hash())
// For subsequent blocks, verify against the previous trusted state
// Note: For a full light client verification, we would need to maintain
// the trusted state and verify the chain of trust, but this test
// demonstrates that the signatures are now properly formatted and verifiable

// Basic verification that signature is not empty/zero
assert.NotEmpty(commitResult.Commit.Signatures[0].Signature,
"Block %d should have non-empty signature", blockHeight)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Don’t swallow light-client verification errors

For the first block the validator set is fixed and the signature is real—VerifyCommitLight should succeed.
Failing fast here increases confidence that the setup is correct:

- _ = err // We acknowledge the verification but don't fail the test
+ require.NoError(t, err, "light-client verification must succeed for block %d", blockHeight)

If it ever fails, that signals a real incompatibility.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if i == 1 {
// For the first block, we use it as the trusted header
trustedHeader := commitResult.SignedHeader
// Verify that the trusted header itself has a valid signature
err = fixedValSet.VerifyCommitLight(chainID, trustedHeader.Commit.BlockID,
trustedHeader.Height, trustedHeader.Commit)
// Note: Light client verification may fail due to complex validator set handling
// but the important thing is that signatures are properly formatted
_ = err // We acknowledge the verification but don't fail the test
} else {
trustingPeriod := 3 * time.Hour
trustLevel := math.Fraction{Numerator: 1, Denominator: 1}
maxClockDrift := 10 * time.Second
err = light.Verify(&trustedHeader, fixedValSet, &commitResult.SignedHeader, fixedValSet, trustingPeriod, time.Unix(0, int64(rollkitHeader.BaseHeader.Time)), maxClockDrift, trustLevel)
require.NoError(err, "failed to pass light.Verify() for block %d", blockHeight)
trustedHeader = commitResult.SignedHeader
}
// Update last hashes for the next iteration
currentRollkitHeaderHash := rollkitHeader.Hash()
lastRollkitHeaderHash = BytesToSliceHash(currentRollkitHeaderHash)
if commitResult.Commit != nil {
lastRollkitCommitHash = BytesToSliceHash(commitResult.Commit.Hash())
// For subsequent blocks, verify against the previous trusted state
// Note: For a full light client verification, we would need to maintain
// the trusted state and verify the chain of trust, but this test
// demonstrates that the signatures are now properly formatted and verifiable
// Basic verification that signature is not empty/zero
assert.NotEmpty(commitResult.Commit.Signatures[0].Signature,
"Block %d should have non-empty signature", blockHeight)
}
if i == 1 {
// For the first block, we use it as the trusted header
trustedHeader := commitResult.SignedHeader
// Verify that the trusted header itself has a valid signature
err = fixedValSet.VerifyCommitLight(chainID, trustedHeader.Commit.BlockID,
trustedHeader.Height, trustedHeader.Commit)
require.NoError(t, err, "light-client verification must succeed for block %d", blockHeight)
} else {
// For subsequent blocks, verify against the previous trusted state
// Note: For a full light client verification, we would need to maintain
// the trusted state and verify the chain of trust, but this test
// demonstrates that the signatures are now properly formatted and verifiable
// Basic verification that signature is not empty/zero
assert.NotEmpty(commitResult.Commit.Signatures[0].Signature,
"Block %d should have non-empty signature", blockHeight)
}
🤖 Prompt for AI Agents
In pkg/rpc/core/blocks_test.go around lines 255 to 274, the test currently
ignores errors from VerifyCommitLight for the first block, which can hide real
verification issues. Modify the code to check the error returned by
VerifyCommitLight and fail the test immediately if an error occurs, ensuring
that any signature verification problems are caught early and the test setup is
validated properly.

Copy link
Copy Markdown
Member

@julienrbrt julienrbrt left a comment

Choose a reason for hiding this comment

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

Why do not we call light.Verify anymore?
It doesn't look like this tests anything anymore. light.Verify is gone and the error in fixedValSet.VerifyCommitLight is ignored anyway.

@randygrok randygrok marked this pull request as draft June 18, 2025 06:03
@randygrok randygrok changed the title test: fix IBC tests test: fix TestBlockSearch_Success and TestCommit_VerifyCometBFTLightClientCompatibility_MultipleBlocks Jun 18, 2025
Copy link
Copy Markdown
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

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

Good start. although this is WIP, I left some comments that may be helpful

Comment thread pkg/rpc/core/blocks_test.go Outdated
Comment thread pkg/rpc/core/blocks_test.go Outdated
Comment thread pkg/rpc/core/blocks_test.go
@randygrok randygrok requested review from alpe and julienrbrt June 19, 2025 08:57
@randygrok randygrok marked this pull request as ready for review June 19, 2025 08:57
@randygrok
Copy link
Copy Markdown
Contributor Author

this PR is previous to the improvements commented yesterday for attesters network

Copy link
Copy Markdown
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

♻️ Duplicate comments (4)
pkg/rpc/core/blocks_test.go (4)

33-41: Global env variable still needs cleanup to prevent test pollution

The test modifies the global env variable without restoring it after completion. This can cause interference with other tests.

Use t.Cleanup() to restore the original value:

+	originalEnv := env
 	env = &Environment{
 		Adapter: &adapter.Adapter{
 			RollkitStore: mockRollkitStore,
 			App:          mockApp,
 		},
 		TxIndexer:    mockTxIndexer,
 		BlockIndexer: mockBlockIndexer,
 		Logger:       cmtlog.NewNopLogger(),
 	}
+	t.Cleanup(func() { env = originalEnv })

173-173: Global env variable pollution remains unaddressed

Similar to the other test, this modifies the global env without cleanup, potentially affecting other tests.

Add cleanup to restore the original environment:

+	originalEnv := env
 	env = setupTestEnvironmentWithSigner(mockSigner)
+	t.Cleanup(func() { env = originalEnv })

307-311: Light client verification errors are still being swallowed

The function allows verification failures and only falls back to checking signature non-emptiness. This was flagged in previous reviews as it can mask real compatibility issues.

For the first block with a fixed validator set and real signature, verification should succeed:

 func verifyFirstBlock(t *testing.T, valSet *cmttypes.ValidatorSet, chainID string, header cmttypes.SignedHeader) {
 	err := valSet.VerifyCommitLight(chainID, header.Commit.BlockID, header.Height, header.Commit)
-	if err != nil {
-		// If basic verification fails, at least verify signature is not empty
-		assert.NotEqual(t, make([]byte, 64), header.Commit.Signatures[0].Signature, "First block signature should not be zeros")
-	}
+	require.NoError(t, err, "light-client verification must succeed for first block")
 }

187-212: Missing mock expectations assertion

The test sets up mock expectations through mockBlock() calls but never asserts that these expectations were met, which could lead to silent test passes.

Add mock assertions at the end of the test:

 		}
 	}
+
+	// Assert all mock expectations were met
+	mockSigner.AssertExpectations(t)
+	env.Adapter.RollkitStore.(*MockRollkitStore).AssertExpectations(t)
 }
🧹 Nitpick comments (1)
pkg/rpc/core/blocks_test.go (1)

242-275: Complex signing logic could benefit from better documentation

The signBlock function performs multiple complex operations (creating temp commit, ABCI conversion, vote creation) that would benefit from inline comments explaining the purpose of each step.

Add comments to explain the signing process:

 func signBlock(t *testing.T, header types.Header, data *types.Data, privKey crypto.PrivKey, chainID string, validatorAddress []byte) []byte {
+	// Create a temporary commit for the previous block to satisfy ABCI conversion requirements
 	tempCommit := &cmttypes.Commit{
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f872ab3 and b627e50.

📒 Files selected for processing (1)
  • pkg/rpc/core/blocks_test.go (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test with Rollkit Chain
🔇 Additional comments (3)
pkg/rpc/core/blocks_test.go (3)

147-150: Excellent mock assertion coverage

All mocks are properly asserted, ensuring test reliability and preventing silent test passes.


327-348: Well-implemented MockSigner with proper interface compliance

The MockSigner correctly implements all required methods and uses testify/mock appropriately for flexible test scenarios.


350-367: Helper function provides clean environment setup

The setupTestEnvironmentWithSigner function creates a fresh environment instance, which is a good pattern for avoiding global state pollution.

@julienrbrt julienrbrt merged commit 468a361 into main Jun 19, 2025
11 checks passed
@julienrbrt julienrbrt deleted the feat/fix-comet-bft-light-test branch June 19, 2025 15:01
chatton pushed a commit that referenced this pull request Oct 7, 2025
…lientCompatibility_MultipleBlocks (#137)

* fix the test

* simplify tests

* solve TestBlockSearch_Success

* fix ibc test

* remove comment
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