Skip to content

Use permanent node index from NodeRegistry contract#4783

Open
begmaroman wants to merge 11 commits into
mainfrom
begmaroman/use-node-id-from-node-registry-contract
Open

Use permanent node index from NodeRegistry contract#4783
begmaroman wants to merge 11 commits into
mainfrom
begmaroman/use-node-id-from-node-registry-contract

Conversation

@begmaroman

Copy link
Copy Markdown
Contributor

No description provided.

@begmaroman begmaroman self-assigned this Dec 31, 2025
@vercel

vercel Bot commented Dec 31, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
river-sample-app Ready Ready Preview, Comment Jan 13, 2026 2:27pm

Base automatically changed from begmaroman/introduce-inc-node-id-in-node-registry-contract to main January 13, 2026 13:04
…d-from-node-registry-contract

# Conflicts:
#	packages/contracts/src/river/registry/facets/node/NodeRegistry.sol
#	packages/contracts/test/river/registry/node/NodeRegistry.t.sol
@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Replaces in-memory auto-increment permanentIndex with contract-supplied permanentIndex across node registry: addNodeLocked accepts a permanentIndex, LoadNodeRegistry and OnNodeAdded propagate node.PermanentIndex from the contract, and nextPermanentIndexLocked is removed.

Changes

Cohort / File(s) Summary
Node registry permanentIndex changes
core/node/nodes/node_registry.go
addNodeLocked now accepts and stores a provided permanentIndex; nextPermanentIndexLocked removed; LoadNodeRegistry and CloneWithClients updated to stop using internal counter; OnNodeAdded fetches permanentIndex via NodeRegistry.GetNode and passes it into addNodeLocked; added bind import for contract calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • bas-vk
🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No description was provided by the author; this is a lenient check that only fails if completely off-topic, which cannot be assessed without content. Add a brief description explaining why this change is necessary and how the permanentIndex is now sourced from the contract.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: replacing auto-increment permanentIndex logic with values fetched from the NodeRegistry contract.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch begmaroman/use-node-id-from-node-registry-contract

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/node/nodes/node_registry.go (1)

49-53: Dead field: nextPermanentIndexLocked is no longer used.

The field at line 53 is still declared but never initialized or referenced after this refactor. Remove it to avoid confusion.

Proposed fix
 	mu                       sync.RWMutex
 	nodesLocked              map[common.Address]*NodeRecord
 	nodesByIndexLocked       map[int32]*NodeRecord
 	appliedBlockNumLocked    blockchain.BlockNumber
-	nextPermanentIndexLocked int
🧹 Nitpick comments (1)
core/node/nodes/node_registry.go (1)

195-206: Consider specifying block number for contract call consistency.

The GetNode call reads from the latest block, while the event was emitted at e.Raw.BlockNumber. For immutable fields like PermanentIndex, this is likely fine, but for consistency, consider using BlockNumber: big.NewInt(int64(e.Raw.BlockNumber)) in CallOpts.

Also, if this call fails, the node isn't added until a restart. Ensure this is acceptable behavior.

Optional: Specify block number
-	node, err := n.contract.NodeRegistry.GetNode(&bind.CallOpts{Context: ctx}, e.NodeAddress)
+	node, err := n.contract.NodeRegistry.GetNode(&bind.CallOpts{
+		Context:     ctx,
+		BlockNumber: new(big.Int).SetUint64(e.Raw.BlockNumber),
+	}, e.NodeAddress)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3eaa018 and 9c37fb9.

📒 Files selected for processing (1)
  • core/node/nodes/node_registry.go
🧰 Additional context used
📓 Path-based instructions (3)
core/**/*.go

📄 CodeRabbit inference engine (core/AGENTS.md)

core/**/*.go: Format all modified Go files using ./fmt.sh from the /core directory before committing
Run the linter using ./lint.sh from the /core directory to check code quality, which runs both golangci-lint and staticcheck
Use RiverError type from node/base/error.go for structured errors
Use RiverErrorWithBase to construct a river error derived from an error of arbitrary or unknown type
Wrap blockchain errors with context using crypto/ utilities
Log errors with structured fields using zap logger
Use node/crypto/blockchain.go for Ethereum client operations
Use node/crypto/chain_monitor.go for transaction monitoring
Use xchain/entitlement/ for cross-chain entitlement checks
Do not run ./fmt.sh and ./lint.sh at the same time; run them as separate commands
Use go.uber.org/zap for structured logging with custom extensions from node/logging/
Use go.opentelemetry.io for distributed tracing across the application
Use prometheus for OpenMetrics in application metrics collection

Files:

  • core/node/nodes/node_registry.go
**/core/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/core/**/*.go: Format all Go files using the fmt.sh script from the /core directory
Run the linter using the lint.sh script from the /core directory for all Go code changes
Use structured logging with zap for Go development
Implement proper error handling with RiverError types in Go code
Implement proper context cancellation for graceful shutdowns in Go code

Files:

  • core/node/nodes/node_registry.go
**/core/node/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use structured logging with zap in Go backend River nodes for observability

Files:

  • core/node/nodes/node_registry.go
🧠 Learnings (8)
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use node/crypto/blockchain.go for Ethereum client operations

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/node/crypto/**/*.go : Use github.com/ethereum/go-ethereum for blockchain integration

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/node/rpc/**/*.go : Use connectrpc.com/connect (Connect protocol) for HTTP/gRPC compatibility in service implementations

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Wrap blockchain errors with context using crypto/ utilities

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use xchain/entitlement/ for cross-chain entitlement checks

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-11-25T08:47:37.754Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/node/rpc/AGENTS.md:0-0
Timestamp: 2025-11-25T08:47:37.754Z
Learning: Applies to core/node/rpc/**/*_test.go : Create authenticated clients using protocolconnect service clients with the service address and HTTP client, and use `authenticateBS()` to add authentication to requests

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use node/crypto/chain_monitor.go for transaction monitoring

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-11-25T08:48:08.084Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/node/storage/AGENTS.md:0-0
Timestamp: 2025-11-25T08:48:08.084Z
Learning: Applies to core/node/storage/storage/**/*_test.go : Use standard imports in storage tests: context, testing, github.com/ethereum/go-ethereum/common, github.com/stretchr/testify/require, and relevant River protocol packages

Applied to files:

  • core/node/nodes/node_registry.go
🧬 Code graph analysis (1)
core/node/nodes/node_registry.go (2)
core/node/registries/river_registry_contract.go (1)
  • NodeRecord (729-729)
core/node/nodes/node_record.go (1)
  • NodeRecord (13-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build_Anvil_Docker
  • GitHub Check: XChain_Integration
🔇 Additional comments (3)
core/node/nodes/node_registry.go (3)

88-97: LGTM!

Clean initialization that properly aligns with the new permanentIndex-from-contract approach.


163-189: LGTM!

Signature properly updated to accept contract-provided permanentIndex. The uint32 to int conversion is safe.


357-364: LGTM!

Clone initialization correctly updated to match the new struct layout.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 0

🧹 Nitpick comments (2)
core/node/nodes/node_registry.go (2)

167-178: Type conversion note.

uint32 to int is safe on 64-bit systems. On 32-bit systems, values > 2^31-1 would overflow. Likely not an issue in practice, but consider using int32 or int64 for permanentIndex in NodeRecord to be explicit.


194-200: Blocking contract call in event handler.

This adds latency to event processing. The TODO indicates it's temporary, but consider adding a timeout via context.WithTimeout if this persists, to avoid blocking indefinitely on RPC issues.

💡 Suggested timeout wrapper
+	callCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
+	defer cancel()
+
-	node, err := n.contract.NodeRegistry.GetNode(&bind.CallOpts{Context: ctx}, e.NodeAddress)
+	node, err := n.contract.NodeRegistry.GetNode(&bind.CallOpts{Context: callCtx}, e.NodeAddress)

Don't forget to add "time" to imports if applied.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c37fb9 and 7c8fef0.

📒 Files selected for processing (1)
  • core/node/nodes/node_registry.go
🧰 Additional context used
📓 Path-based instructions (3)
core/**/*.go

📄 CodeRabbit inference engine (core/AGENTS.md)

core/**/*.go: Format all modified Go files using ./fmt.sh from the /core directory before committing
Run the linter using ./lint.sh from the /core directory to check code quality, which runs both golangci-lint and staticcheck
Use RiverError type from node/base/error.go for structured errors
Use RiverErrorWithBase to construct a river error derived from an error of arbitrary or unknown type
Wrap blockchain errors with context using crypto/ utilities
Log errors with structured fields using zap logger
Use node/crypto/blockchain.go for Ethereum client operations
Use node/crypto/chain_monitor.go for transaction monitoring
Use xchain/entitlement/ for cross-chain entitlement checks
Do not run ./fmt.sh and ./lint.sh at the same time; run them as separate commands
Use go.uber.org/zap for structured logging with custom extensions from node/logging/
Use go.opentelemetry.io for distributed tracing across the application
Use prometheus for OpenMetrics in application metrics collection

Files:

  • core/node/nodes/node_registry.go
**/core/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/core/**/*.go: Format all Go files using the fmt.sh script from the /core directory
Run the linter using the lint.sh script from the /core directory for all Go code changes
Use structured logging with zap for Go development
Implement proper error handling with RiverError types in Go code
Implement proper context cancellation for graceful shutdowns in Go code

Files:

  • core/node/nodes/node_registry.go
**/core/node/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use structured logging with zap in Go backend River nodes for observability

Files:

  • core/node/nodes/node_registry.go
🧠 Learnings (8)
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use node/crypto/blockchain.go for Ethereum client operations

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/node/crypto/**/*.go : Use github.com/ethereum/go-ethereum for blockchain integration

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/node/rpc/**/*.go : Use connectrpc.com/connect (Connect protocol) for HTTP/gRPC compatibility in service implementations

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Wrap blockchain errors with context using crypto/ utilities

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use xchain/entitlement/ for cross-chain entitlement checks

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-11-25T08:47:37.754Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/node/rpc/AGENTS.md:0-0
Timestamp: 2025-11-25T08:47:37.754Z
Learning: Applies to core/node/rpc/**/*_test.go : Create authenticated clients using protocolconnect service clients with the service address and HTTP client, and use `authenticateBS()` to add authentication to requests

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-12-17T02:40:57.825Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/AGENTS.md:0-0
Timestamp: 2025-12-17T02:40:57.825Z
Learning: Applies to core/**/*.go : Use node/crypto/chain_monitor.go for transaction monitoring

Applied to files:

  • core/node/nodes/node_registry.go
📚 Learning: 2025-11-25T08:48:08.084Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: core/node/storage/AGENTS.md:0-0
Timestamp: 2025-11-25T08:48:08.084Z
Learning: Applies to core/node/storage/storage/**/*_test.go : Use standard imports in storage tests: context, testing, github.com/ethereum/go-ethereum/common, github.com/stretchr/testify/require, and relevant River protocol packages

Applied to files:

  • core/node/nodes/node_registry.go
🧬 Code graph analysis (1)
core/node/nodes/node_registry.go (3)
core/node/registries/river_registry_contract.go (1)
  • NodeRecord (729-729)
core/node/nodes/node_record.go (1)
  • NodeRecord (13-22)
core/blockchain/block_number.go (1)
  • BlockNumber (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Multinode_Ent_Legacy
  • GitHub Check: Multinode_Ent
  • GitHub Check: Multinode
  • GitHub Check: Go_Tests
  • GitHub Check: Common_CI
  • GitHub Check: XChain_Integration
🔇 Additional comments (5)
core/node/nodes/node_registry.go (5)

11-11: LGTM!

Import correctly added for bind.CallOpts usage in OnNodeAdded.


49-52: LGTM!

Clean removal of nextPermanentIndexLocked. Registry now correctly relies on contract-provided indices.


87-100: LGTM!

Initialization correctly simplified. Contract-provided PermanentIndex now flows through properly.


356-391: LGTM!

Clone correctly rebuilds nodesByIndexLocked from node data rather than relying on a counter.


150-152: Add code comment explaining permanentIndex > 0 check.

The condition at lines 150 and 388 excludes nodes with permanentIndex == 0 from the index lookup map. This appears intentional (likely treating 0 as "unset"), but lacks documentation. If permanentIndex can legitimately be 0, those nodes become unretrievable via GetNodeByPermanentIndex. Add a comment clarifying whether 0 is a reserved/unset value or if this is a bug.

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