Skip to content

fix(smart-router): extract policy validation from ParseMsg#2244

Merged
nimrod-teich merged 6 commits into
mainfrom
fix/smart-router-skip-policy-verification
Mar 23, 2026
Merged

fix(smart-router): extract policy validation from ParseMsg#2244
nimrod-teich merged 6 commits into
mainfrom
fix/smart-router-skip-policy-verification

Conversation

@nimrod-teich

@nimrod-teich nimrod-teich commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

  • Extract validation from ParseMsg: The smart-router uses static providers without on-chain pairing, so addon policy validation in ParseMsg was rejecting addon requests unless operators passed --skip-policy-verification. Instead of adding a skip flag, validation is extracted into an explicit ValidateMessage() step — consumer and provider call ParseAndValidateMessage(), smart-router calls ParseMsg directly.
  • Consolidate extension/addon patterns: Move allowedExtensions from ExtensionParser to BaseChainParser so isExtension matches the isAddon pattern (direct map lookup). Remove dead AllowedExtension method and skip parameter.

Changes

  • ParseMsg now only parses — no longer validates against consumer policy
  • New ValidateMessage(ChainMessage) error on ChainParser interface, called via ParseAndValidateMessage convenience function
  • Consumer and provider use ParseAndValidateMessage; smart-router uses ParseMsg directly
  • Removed global: SkipPolicyVerification
  • Removed CLI flag: --skip-policy-verification
  • Removed flag constant: SkipPolicyVerificationFlag

Test plan

  • go build ./protocol/... compiles cleanly
  • go test ./protocol/chainlib/ passes
  • go test ./protocol/rpcprovider/ passes
  • Lint passes (golangci-lint)
  • No remaining references to SkipPolicyVerification
  • Verify smart-router accepts addon requests without any extra flags
  • Verify rpcconsumer rejects disallowed addons as before

🤖 Generated with Claude Code


Generated description

Below is a concise technical summary of the changes proposed in this PR:
Refactor the parsing flow so ParseMsg focuses on decoding and ParseAndValidateMessage enforces the consumer policy through the new ValidateMessage hook on ChainParser, allowing consumers/providers to reject disallowed addons while the smart router still reuses the raw parser. Align BaseChainParser’s policy state with the extension system so addon/extension checks use the same allowance maps and the CLI no longer exposes a policy-skip flag.

TopicDetails
Validation Flow Apply the new ParseAndValidateMessage helper, ValidateMessage interface, and parser changes so consumers/providers validate addon policy after parsing while smart-router keeps calling ParseMsg, updating mocks and tests plus removing the obsolete skip flag and flag constant.
Modified files (12)
  • protocol/chainlib/base_chain_parser.go
  • protocol/chainlib/chainlib.go
  • protocol/chainlib/chainlib_mock.go
  • protocol/chainlib/grpc.go
  • protocol/chainlib/jsonRPC.go
  • protocol/chainlib/rest.go
  • protocol/chainlib/tendermintRPC.go
  • protocol/common/cobra_common.go
  • protocol/rpcconsumer/rpcconsumer_server.go
  • protocol/rpcprovider/consistency_test.go
  • protocol/rpcprovider/rpcprovider_server.go
  • protocol/rpcsmartrouter/rpcsmartrouter.go
Latest Contributors(2)
UserCommitDate
NadavLevifeat-smart-router-impl...March 11, 2026
anna@magmadevs.comfeat-provideroptimizer...February 22, 2026
Extension Allowance Centralize allowed-extension tracking inside BaseChainParser and simplify ExtensionParser so isExtension uses the shared map, updating the parser constructor and tests accordingly.
Modified files (3)
  • protocol/chainlib/base_chain_parser.go
  • protocol/chainlib/base_chain_parser_test.go
  • protocol/chainlib/extensionslib/extension_parser.go
Latest Contributors(2)
UserCommitDate
NadavLevifeat-smart-router-impl...March 11, 2026
tenzer@clara.co.ukrefactor-lavap-split-l...November 18, 2025
This pull request is reviewed by Baz. Review like a pro on (Baz).

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Replace global policy verification flag with per-instance setting

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replace global SkipPolicyVerification bool with per-instance field on BaseChainParser
• Smart-router automatically skips policy verification at chain parser creation
• Remove --skip-policy-verification flag from smart-router command
• Update ChainParser interface and mock implementations with new method
Diagram
flowchart LR
  A["Global SkipPolicyVerification bool"] -->|"Replaced with"| B["Per-instance skipPolicyVerification field"]
  B -->|"Set via"| C["SetSkipPolicyVerification method"]
  D["Smart-router CreateSmartRouterEndpoint"] -->|"Calls"| C
  C -->|"Enables"| E["Policy verification skipped for static providers"]
Loading

Grey Divider

File Changes

1. protocol/chainlib/base_chain_parser.go 🐞 Bug fix +10/-6

Convert global flag to instance field

• Removed global SkipPolicyVerification variable
• Added skipPolicyVerification bool field to BaseChainParser struct
• Implemented SetSkipPolicyVerification() method to set the field
• Updated isExtension() and validateAddons() to use instance field instead of global

protocol/chainlib/base_chain_parser.go


2. protocol/chainlib/chainlib.go ✨ Enhancement +1/-0

Add method to ChainParser interface

• Added SetSkipPolicyVerification() method to ChainParser interface

protocol/chainlib/chainlib.go


3. protocol/chainlib/chainlib_mock.go 🧪 Tests +12/-0

Update mock with new interface method

• Implemented SetSkipPolicyVerification() mock method
• Added corresponding mock recorder method for test expectations

protocol/chainlib/chainlib_mock.go


View more (3)
4. protocol/common/cobra_common.go ⚙️ Configuration changes +0/-1

Remove unused flag constant

• Removed SkipPolicyVerificationFlag constant definition

protocol/common/cobra_common.go


5. protocol/rpcprovider/consistency_test.go 🧪 Tests +1/-0

Update fake parser for tests

• Added empty implementation of SetSkipPolicyVerification() to fakeChainParser

protocol/rpcprovider/consistency_test.go


6. protocol/rpcsmartrouter/rpcsmartrouter.go 🐞 Bug fix +2/-1

Enable policy verification skip for smart-router

• Call SetSkipPolicyVerification() on chain parser after creation in CreateSmartRouterEndpoint()
• Removed --skip-policy-verification flag registration from smart-router cobra command
• Added explanatory comment about static providers not requiring policy verification

protocol/rpcsmartrouter/rpcsmartrouter.go


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Mar 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. SetSkipPolicyVerification has extra spaces📘 Rule violation ⚙ Maintainability
Description
The newly added SetSkipPolicyVerification method contains non-gofmt formatting (double space
before {}). This violates the requirement to keep Go files gofmt/goimports formatted and may cause
formatting/lint checks to fail in CI.
Code

protocol/rpcprovider/consistency_test.go[207]

+func (fcp *fakeChainParser) SetSkipPolicyVerification()  {}
Evidence
PR Compliance ID 1 requires Go code to be gofmt/goimports clean. The added line shows a formatting
deviation (...()  {}) that gofmt would rewrite.

AGENTS.md
protocol/rpcprovider/consistency_test.go[207-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The added method `SetSkipPolicyVerification` is not gofmt-formatted due to an extra space before the empty body.
## Issue Context
This repository requires gofmt/goimports-clean Go code (PR Compliance ID 1).
## Fix Focus Areas
- protocol/rpcprovider/consistency_test.go[207-207]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Skip accepts invalid extensions🐞 Bug ⛨ Security
Description
RPCSmartRouter now unconditionally disables policy verification, which makes BaseChainParser treat
any unknown service string as an allowed extension. A typo/unknown entry in NodeUrl.Addons can then
prevent GetVerifications from including the default (empty-extension) verifications, and
ChainFetcher.Validate will proceed with zero verifications (warning only).
Code

protocol/rpcsmartrouter/rpcsmartrouter.go[R328-329]

+	// Smart router uses static providers without on-chain pairing, so policy verification is not applicable
+	chainParser.SetSkipPolicyVerification()
Evidence
Smart-router forces skipPolicyVerification on every created ChainParser; in skip mode,
AllowedExtension returns true for any non-empty string, so SeparateAddonsExtensions will classify
unknown strings as extensions instead of erroring. GetVerifications only includes the
empty-extension verification set when the extensions list is empty, so an “unknown extension” can
result in no verifications being returned; ChainFetcher.Validate uses NodeUrl.Addons from config and
only logs a warning when verifications are empty, weakening endpoint validation.

protocol/rpcsmartrouter/rpcsmartrouter.go[322-355]
protocol/chainlib/base_chain_parser.go[116-138]
protocol/chainlib/base_chain_parser.go[212-241]
protocol/chainlib/base_chain_parser.go[244-255]
protocol/chainlib/extensionslib/extension_parser.go[58-64]
protocol/common/endpoints.go[75-86]
protocol/chainlib/chain_fetcher.go[97-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Smart-router sets `skipPolicyVerification` to true by default. That boolean is currently passed into `ExtensionParser.AllowedExtension()`, which returns `true` for *any* non-empty string when `skip==true`. This makes `SeparateAddonsExtensions()` accept unknown/typo service names as “extensions”, which can suppress default (empty-extension) verifications in `GetVerifications()` and lead to endpoint validation running with no verifications.
### Issue Context
The intent of skipping policy verification is to bypass consumer-policy enforcement for smart-router static providers, not to disable spec-level validation of extension names.
### Fix Focus Areas
- protocol/chainlib/base_chain_parser.go[116-241]
- protocol/chainlib/extensionslib/extension_parser.go[58-64]
### Suggested approach
- Decouple “skip policy verification” from “extension name is known”.
- Ensure `SeparateAddonsExtensions()` still errors on unknown services even when policy verification is skipped.
- e.g., change `BaseChainParser.isExtension()` to validate against spec-known extensions regardless of `skipPolicyVerification` (do **not** pass `skipPolicyVerification` into `AllowedExtension`), or introduce a dedicated `IsKnownExtension()` check.
- Keep addon policy enforcement bypass in `validateAddons()` as intended for smart-router.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Mock signatures out of sync🐞 Bug ⚙ Maintainability
Description
protocol/chainlib/chainlib_mock.go is marked as MockGen output for ChainParser, but its
GetVerifications mock signature does not match the ChainParser interface, so it cannot be used as a
ChainParser mock. The PR manually edited this generated file to add SetSkipPolicyVerification,
increasing drift risk and making future regeneration overwrite changes.
Code

protocol/chainlib/chainlib_mock.go[R223-233]

+// SetSkipPolicyVerification mocks base method.
+func (m *MockChainParser) SetSkipPolicyVerification() {
+	m.ctrl.T.Helper()
+	m.ctrl.Call(m, "SetSkipPolicyVerification")
+}
+
+// SetSkipPolicyVerification indicates an expected call of SetSkipPolicyVerification.
+func (mr *MockChainParserMockRecorder) SetSkipPolicyVerification() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSkipPolicyVerification", reflect.TypeOf((*MockChainParser)(nil).SetSkipPolicyVerification))
+}
Evidence
ChainParser requires `GetVerifications(supported []string, internalPath string, apiInterface
string), but the generated mock still defines GetVerifications(supported []string)`; despite
claiming it was generated from chainlib.go, it does not match the source interface. The PR adds
another method to this generated file by hand rather than regenerating it, which compounds the
mismatch/drift.

protocol/chainlib/chainlib.go[66-88]
protocol/chainlib/chainlib_mock.go[1-23]
protocol/chainlib/chainlib_mock.go[147-160]
protocol/chainlib/chainlib_mock.go[223-233]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`protocol/chainlib/chainlib_mock.go` is declared as MockGen output for `protocol/chainlib/chainlib.go`, but it no longer matches the `ChainParser` interface (e.g., `GetVerifications` parameter list). The PR also manually edited this generated file to add `SetSkipPolicyVerification()`, which is brittle.
### Issue Context
Any tests that attempt to use `MockChainParser` as a `ChainParser` (or call `GetVerifications` with the interface signature) will not be able to rely on this mock.
### Fix Focus Areas
- protocol/chainlib/chainlib.go[66-88]
- protocol/chainlib/chainlib_mock.go[1-260]
### Suggested approach
- Regenerate `protocol/chainlib/chainlib_mock.go` using the project’s established `mockgen`/`go generate` workflow for `ChainParser`.
- Confirm the regenerated mock contains:
- `GetVerifications(supported []string, internalPath string, apiInterface string)`
- `SetSkipPolicyVerification()`
- Avoid manual edits to generated files.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. CreateSmartRouterEndpoint skip untested📘 Rule violation ⛯ Reliability
Description
The smart-router now unconditionally calls chainParser.SetSkipPolicyVerification(), changing
addon/extension verification behavior by default. There is no corresponding test update in this PR
that asserts addon requests work without policy verification, increasing regression risk.
Code

protocol/rpcsmartrouter/rpcsmartrouter.go[R328-329]

+	// Smart router uses static providers without on-chain pairing, so policy verification is not applicable
+	chainParser.SetSkipPolicyVerification()
Evidence
PR Compliance ID 5 requires adding/maintaining tests for new or changed behavior. The diff shows a
behavior change (default skipping) without an accompanying assertion-based test change validating
the new default behavior.

AGENTS.md
protocol/rpcsmartrouter/rpcsmartrouter.go[328-329]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CreateSmartRouterEndpoint` now defaults to skipping policy verification via `chainParser.SetSkipPolicyVerification()`, but the PR does not add a test that verifies addon/extension requests succeed under smart-router defaults.
## Issue Context
This change is intended to prevent addon requests from failing unless operators pass a flag. A test should cover the new default to prevent regressions.
## Fix Focus Areas
- protocol/rpcsmartrouter/rpcsmartrouter.go[328-329]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Skip flag write unlocked🐞 Bug ⛯ Reliability
Description
BaseChainParser.SetSkipPolicyVerification writes skipPolicyVerification without using rwLock while
Validate/validateAddons read it, violating the parser’s locking discipline. If
SetSkipPolicyVerification is ever called after the parser is in use, this can trigger a Go data race
and inconsistent validation behavior.
Code

protocol/chainlib/base_chain_parser.go[R116-118]

+func (bcp *BaseChainParser) SetSkipPolicyVerification() {
+	bcp.skipPolicyVerification = true
+}
Evidence
BaseChainParser has an rwLock for mutable parser state and Validate reads skipPolicyVerification
during request validation; however, SetSkipPolicyVerification writes the same field with no
synchronization. This is a classic unsynchronized read/write pattern that will be flagged by the
race detector if the setter is called concurrently with request handling.

protocol/chainlib/base_chain_parser.go[42-55]
protocol/chainlib/base_chain_parser.go[116-129]
protocol/chainlib/base_chain_parser.go[141-146]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SetSkipPolicyVerification()` writes `bcp.skipPolicyVerification` without synchronization, while validation reads it under (or alongside) the parser’s locking model.
### Issue Context
Today it’s called during smart-router initialization, but the API surface allows calling it later; keeping the locking discipline consistent prevents future races.
### Fix Focus Areas
- protocol/chainlib/base_chain_parser.go[116-146]
### Suggested approach
- Protect the write with `bcp.rwLock.Lock()/Unlock()`, or
- Store the flag in an atomic (and read atomically), and/or
- Document/enforce that it must be set before the parser becomes concurrently accessible.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread protocol/rpcprovider/consistency_test.go Outdated
Comment thread protocol/rpcsmartrouter/rpcsmartrouter.go Outdated
Comment thread protocol/chainlib/chainlib_mock.go Outdated
Comment thread protocol/rpcsmartrouter/rpcsmartrouter.go Outdated
Comment thread protocol/chainlib/chainlib.go
@pull-request-size pull-request-size Bot added size/M and removed size/S labels Mar 22, 2026
@nimrod-teich nimrod-teich changed the title fix(smart-router): skip policy verification by default fix(smart-router): extract policy validation from ParseMsg Mar 22, 2026
@github-actions

github-actions Bot commented Mar 22, 2026

Copy link
Copy Markdown

Test Results

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
7 files   ±0   0 ❌ ±0 

Results for commit 8041bba. ± Comparison against base commit 50e9a40.

♻️ This comment has been updated with latest results.

@nimrod-teich nimrod-teich force-pushed the fix/smart-router-skip-policy-verification branch from 2c6c3b1 to d983346 Compare March 22, 2026 14:16
Comment thread protocol/chainlib/base_chain_parser.go
Comment thread protocol/chainlib/extensionslib/extension_parser.go
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Mar 22, 2026
NadavLevi
NadavLevi previously approved these changes Mar 22, 2026
@codecov

codecov Bot commented Mar 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 24.24242% with 25 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
protocol/chainlib/chainlib_mock.go 0.00% 8 Missing ⚠️
protocol/chainlib/base_chain_parser.go 36.36% 7 Missing ⚠️
protocol/chainlib/chainlib.go 0.00% 7 Missing ⚠️
...rotocol/chainlib/extensionslib/extension_parser.go 0.00% 1 Missing ⚠️
protocol/rpcconsumer/rpcconsumer_server.go 0.00% 1 Missing ⚠️
protocol/rpcprovider/rpcprovider_server.go 0.00% 1 Missing ⚠️
Flag Coverage Δ
consensus 8.71% <ø> (ø)
protocol 33.16% <24.24%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
protocol/chainlib/grpc.go 45.94% <100.00%> (ø)
protocol/chainlib/jsonRPC.go 44.84% <100.00%> (ø)
protocol/chainlib/rest.go 42.99% <100.00%> (ø)
protocol/chainlib/tendermintRPC.go 40.58% <100.00%> (ø)
protocol/common/cobra_common.go 0.00% <ø> (ø)
protocol/rpcsmartrouter/rpcsmartrouter.go 2.98% <ø> (+<0.01%) ⬆️
...rotocol/chainlib/extensionslib/extension_parser.go 0.00% <0.00%> (ø)
protocol/rpcconsumer/rpcconsumer_server.go 31.83% <0.00%> (ø)
protocol/rpcprovider/rpcprovider_server.go 9.55% <0.00%> (ø)
protocol/chainlib/base_chain_parser.go 73.68% <36.36%> (-1.57%) ⬇️
... and 2 more

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nimrod-teich nimrod-teich changed the title fix(smart-router): extract policy validation from ParseMsg fix(smart-router): extract policy validation from ParseMsg, remove dead skip globals Mar 22, 2026
@nimrod-teich nimrod-teich changed the title fix(smart-router): extract policy validation from ParseMsg, remove dead skip globals fix(smart-router): extract policy validation from ParseMsg Mar 22, 2026
@nimrod-teich nimrod-teich force-pushed the fix/smart-router-skip-policy-verification branch from 01e69d0 to 8041bba Compare March 22, 2026 16:14
nimrod-teich and others added 6 commits March 23, 2026 13:23
…uiring flag

The smart-router uses static providers without on-chain pairing, so
addon/extension policy verification is not applicable. Previously this
required operators to pass --skip-policy-verification, which was a
footgun — addon requests would silently fail without it.

Replace the global SkipPolicyVerification bool with a per-instance
skipPolicyVerification field on BaseChainParser. The smart-router now
calls SetSkipPolicyVerification() on each chain parser at creation
time, removing the flag entirely.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ateMessage

Instead of adding a skip flag to BaseChainParser, move addon policy
validation out of ParseMsg entirely. Consumer and provider explicitly
call ValidateMessage after parsing; smart-router simply doesn't.

This keeps smart-router concerns out of shared chainlib code:
- Remove SkipPolicyVerification global and skipPolicyVerification field
- Remove SetSkipPolicyVerification from ChainParser interface
- Add ValidateMessage(ChainMessage) to ChainParser interface
- Remove Validate call from ParseMsg in all 4 chain parsers
- Consumer/provider call ValidateMessage after ParseMsg

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consumer and provider now call ParseAndValidateMessage instead of
separate ParseMsg + ValidateMessage calls. This makes the validated
path the obvious default and prevents callers from forgetting to
validate. Smart-router continues calling ParseMsg directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The skip parameter only existed for SkipPolicyVerification which was
removed. AllowedExtension now just does a map lookup, matching the
isAddon pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ith allowedAddons

isExtension now does a direct map lookup on BaseChainParser, matching
the isAddon pattern. Remove allowedExtensions and AllowedExtension
from ExtensionParser since it only handled configured extensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@nimrod-teich nimrod-teich force-pushed the fix/smart-router-skip-policy-verification branch from 8041bba to f36ff0a Compare March 23, 2026 11:23
@nimrod-teich nimrod-teich merged commit e824dc1 into main Mar 23, 2026
17 checks passed
@nimrod-teich nimrod-teich deleted the fix/smart-router-skip-policy-verification branch March 23, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants