Skip to content

Conversation

@mkysel
Copy link
Collaborator

@mkysel mkysel commented May 22, 2025

Implement parameter registry ABI and SetMaxCanonical method to set maximum canonical nodes in the node registry using SettlementChainParameterRegistry contract

Adds support for the SettlementChainParameterRegistry contract by:

📍Where to Start

Start with the SetMaxCanonical method implementation in registryAdmin.go which shows how the parameter registry contract is used to set the maximum canonical nodes parameter.


Macroscope summarized ae54a96.

Summary by CodeRabbit

  • New Features
    • Added support for interacting with the Settlement Chain Parameter Registry contract, enabling management of chain parameters through the application.
    • Introduced a new configuration option to specify the Parameter Registry contract address.
  • Bug Fixes
    • Enhanced error handling and logging when updating the maximum canonical nodes limit.
  • Tests
    • Added tests to verify correct behavior when setting the maximum canonical nodes limit, including repeated calls with the same value.
  • Chores
    • Updated environment variables and configuration defaults to include the Parameter Registry contract address.

@mkysel mkysel requested a review from a team as a code owner May 22, 2025 17:18
@graphite-app
Copy link

graphite-app bot commented May 22, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • Queue - adds this PR to the back of the merge queue
  • Hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@mkysel mkysel changed the title mkysel/paramreg Add parameter registry ABI and implement set maxcanonical May 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 22, 2025

Walkthrough

A new Ethereum smart contract binding for SettlementChainParameterRegistry was introduced, along with corresponding configuration, environment variable, and test updates. The blockchain registry admin logic was updated to interact with this new contract for setting parameters, and a new test verifies this functionality. Configuration structures and test utilities were extended to support the parameter registry address.

Changes

File(s) Change Summary
pkg/abi/settlementchainparameterregistry/SettlementChainParameterRegistry.go Added a comprehensive Go binding for the SettlementChainParameterRegistry Ethereum smart contract, including deployment, function calls, event filters/watchers/parsers, and session handling.
pkg/blockchain/registryAdmin.go Integrated the new SettlementChainParameterRegistry contract into the nodeRegistryAdmin struct and logic. Updated the constructor to instantiate both nodeContract and parameterContract. Modified SetMaxCanonical to set the parameter in the new contract before updating the node registry, with enhanced error handling and logging.
pkg/blockchain/registryAdmin_test.go Added TestSetMaxCanonical to test setting the max canonical nodes parameter via the new registry admin logic, including idempotency verification.
pkg/config/options.go Added ParameterRegistryAddress field to the SettlementChainOptions struct, with metadata for command-line flag, environment variable, and description.
pkg/testutils/config.go Introduced PARAMETER_REGISTRY_ADDRESS constant and updated NewContractsOptions to set the new address in the SettlementChainOptions struct.
dev/local.env Added XMTPD_SETTLEMENT_CHAIN_PARAMETER_REGISTRY_ADDRESS environment variable with the new contract address.

Sequence Diagram(s)

sequenceDiagram
    participant Admin as nodeRegistryAdmin
    participant ParamReg as SettlementChainParameterRegistry
    participant NodeReg as NodeRegistry

    Admin->>ParamReg: Set0(key, value) (set max canonical nodes parameter)
    Note right of ParamReg: Emits ParameterSet event
    Admin->>NodeReg: UpdateMaxCanonicalNodes(limit)
    alt NoChange error
        Admin->>Admin: Log "no update needed"
    else Success
        Note right of NodeReg: Emits MaxCanonicalNodesUpdated event
    end
Loading
sequenceDiagram
    participant Test as TestSetMaxCanonical
    participant Admin as nodeRegistryAdmin

    Test->>Admin: SetMaxCanonical(ctx, 16)
    Admin-->>Test: nil (success)
    Test->>Admin: SetMaxCanonical(ctx, 16)
    Admin-->>Test: nil (idempotent success)
Loading

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.

Comment on lines +239 to +241
var value [32]byte
// store uint8 in the last byte for big-endian compatibility
value[31] = limit
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

FYI @deluca-mike. This is the endian-ness we need

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: 1

🧹 Nitpick comments (6)
pkg/blockchain/registryAdmin.go (5)

22-24: Consider shortening / hashing the parameter‐key to avoid oversized topic hashing

NODE_REGISTRY_MAX_CANONICAL_NODES_KEY is 35 bytes long ("xmtp.nodeRegistry.maxCanonicalNodes").
Although bytes is allowed as the indexed event parameter in SettlementChainParameterRegistry, the ABI encoder will hash the entire value to fit into a single topic (32 bytes).
Long keys therefore provide no extra distinguishability on-chain, but incur extra gas when used elsewhere (e.g. as storage keys or map look-ups).

If backwards-compatibility isn’t required, think about:

-const NODE_REGISTRY_MAX_CANONICAL_NODES_KEY = "xmtp.nodeRegistry.maxCanonicalNodes"
+// keccak256("xmtp.nodeRegistry.maxCanonicalNodes") truncated / encoded
+var nodeRegistryMaxCanonicalKey = crypto.Keccak256([]byte("xmtp.nodeRegistry.maxCanonicalNodes"))

…and re-using the nodeRegistryMaxCanonicalKey byte slice everywhere.


55-70: Avoid repeated contract instantiation logic

Both contract instances are created with almost identical boiler-plate.
Extracting a small helper function reduces duplication, centralises error handling, and simplifies future upgrades:

+func mustBind[T any](bindFn func(common.Address, *ethclient.Client) (T, error), addr string, client *ethclient.Client) (T, error) {
+    return bindFn(common.HexToAddress(addr), client)
+}
 ...
-nodeContract, err := noderegistry.NewNodeRegistry(
-    common.HexToAddress(contractsOptions.SettlementChain.NodeRegistryAddress),
-    client,
-)
+nodeContract, err := mustBind(noderegistry.NewNodeRegistry,
+    contractsOptions.SettlementChain.NodeRegistryAddress, client)
 ...
-paramContract, err := paramReg.NewSettlementChainParameterRegistry(
-    common.HexToAddress(contractsOptions.SettlementChain.ParameterRegistryAddress),
-    client,
-)
+paramContract, err := mustBind(paramReg.NewSettlementChainParameterRegistry,
+    contractsOptions.SettlementChain.ParameterRegistryAddress, client)

This keeps NewNodeRegistryAdmin readable and uniform.


231-244: Pre-allocate immutable data to save per-call allocations

key := []byte(NODE_REGISTRY_MAX_CANONICAL_NODES_KEY) allocates on every invocation.
Store the byte slice as a var alongside the constant:

var nodeRegistryMaxCanonicalKey = []byte(NODE_REGISTRY_MAX_CANONICAL_NODES_KEY)
...
key := nodeRegistryMaxCanonicalKey

This shaves a small amount of work from what may become a hot path in administration tooling.


292-300: “NoChange” error detection is brittle

String-contains checks on error text are fragile and may break with upstream changes.
Prefer a typed error or inspect the revert data directly if the bindings expose one.

If that is not available, at least compare against a constant:

const errNoChange = "NoChange"
...
if errors.Is(err, errNoChange) || strings.Contains(err.Error(), errNoChange) { ... }

266-275: Potential redundant on-chain transaction

UpdateMaxCanonicalNodes() is called unconditionally after setting the parameter, even if the parameter value hasn’t changed.
You already swallow the “NoChange” revert, but that still pays gas for a failed transaction.

Consider optimising:

  1. Call parameterContract.Get0 first to see whether limit differs.
  2. Only fire Set0 / UpdateMaxCanonicalNodes when necessary.

This preserves idempotency while avoiding wasted gas.

pkg/abi/settlementchainparameterregistry/SettlementChainParameterRegistry.go (1)

1-36: Generated file – add linter directives

Because this file is generated, linters such as staticcheck or golangci-lint may flag stylistic issues outside your control.
Add the conventional directive at the top to silence them:

// Code generated - DO NOT EDIT.
//go:build !lint
// +build !lint

(or whichever tag your tooling respects).
This keeps CI noise low and focuses reviewers on hand-written code.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2789dfd and ae54a96.

⛔ Files ignored due to path filters (1)
  • dev/gen/abi is excluded by !**/gen/**
📒 Files selected for processing (6)
  • dev/local.env (1 hunks)
  • pkg/abi/settlementchainparameterregistry/SettlementChainParameterRegistry.go (1 hunks)
  • pkg/blockchain/registryAdmin.go (10 hunks)
  • pkg/blockchain/registryAdmin_test.go (1 hunks)
  • pkg/config/options.go (1 hunks)
  • pkg/testutils/config.go (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Push Docker Images to GitHub Packages (xmtpd-cli)
  • GitHub Check: Upgrade Tests
  • GitHub Check: Test (Node)
🔇 Additional comments (6)
dev/local.env (1)

24-24: LGTM: Added new Parameter Registry address environment variable.

The addition of the XMTPD_SETTLEMENT_CHAIN_PARAMETER_REGISTRY_ADDRESS environment variable is consistent with the existing pattern for settlement chain contracts.

pkg/config/options.go (1)

49-49: LGTM: Added Parameter Registry address configuration.

The new ParameterRegistryAddress field in the SettlementChainOptions struct properly follows the established pattern for contract address configurations and correctly maps to the environment variable added in local.env.

pkg/blockchain/registryAdmin_test.go (1)

84-93: LGTM: Good test coverage for the SetMaxCanonical functionality.

The test verifies that the SetMaxCanonical method works correctly and handles repeated calls with the same value without errors. It follows the existing testing patterns in the file.

pkg/testutils/config.go (2)

21-21: LGTM: Added Parameter Registry address constant.

The new constant for the Parameter Registry address is correctly defined and follows the established naming pattern.


40-40: LGTM: Updated test configuration with Parameter Registry address.

The NewContractsOptions function is properly updated to include the Parameter Registry address in the returned configuration.

pkg/blockchain/registryAdmin.go (1)

71-77: Field ordering hint

Placing fields that are frequently accessed together next to each other (e.g. nodeContract, parameterContract) can improve cache locality and readability. Consider grouping the two contract handles.

@mkysel mkysel merged commit 464ae0f into main May 22, 2025
10 checks passed
@mkysel mkysel deleted the mkysel/paramreg branch May 22, 2025 19:04
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