Skip to content

Commit

Permalink
fix(checker): Add MissingRouterViolation when config misses enrolled …
Browse files Browse the repository at this point in the history
…routers (#5391)

### Description

- In response to an error thrown when there are actual enrolled routers
that are not present in the config, this was encountered running the
warp checker against a route not managed by AW.

Here is the violation output

![image](https://github.com/user-attachments/assets/67d6b428-c669-4e27-9278-bf3404129473)

### Testing

Manual
  • Loading branch information
Mo-Hussain authored Feb 9, 2025
1 parent db832b8 commit d93a38c
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-bags-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---

Add MissingRouterViolation when config misses enrolled routers
2 changes: 1 addition & 1 deletion typescript/infra/src/govern/HyperlaneICAChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class HyperlaneICAChecker extends InterchainAccountChecker {

const violation: RouterViolation = {
chain,
type: RouterViolationType.EnrolledRouter,
type: RouterViolationType.MisconfiguredEnrolledRouter,
contract: router,
actual: currentRouters,
expected: expectedRouters,
Expand Down
2 changes: 1 addition & 1 deletion typescript/infra/src/govern/ProxiedRouterGovernor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class ProxiedRouterGovernor<
switch (violation.type) {
case ConnectionClientViolationType.InterchainSecurityModule:
return this.handleIsmViolation(violation as ConnectionClientViolation);
case RouterViolationType.EnrolledRouter:
case RouterViolationType.MisconfiguredEnrolledRouter:
return this.handleEnrolledRouterViolation(violation as RouterViolation);
case ViolationType.Owner:
return this.handleOwnerViolation(violation as OwnerViolation);
Expand Down
43 changes: 35 additions & 8 deletions typescript/sdk/src/router/HyperlaneRouterChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { RouterApp } from './RouterApps.js';
import {
ClientViolation,
ClientViolationType,
MissingRouterViolation,
RouterConfig,
RouterViolation,
RouterViolationType,
Expand Down Expand Up @@ -125,17 +126,27 @@ export class HyperlaneRouterChecker<

async checkEnrolledRouters(chain: ChainName): Promise<void> {
const router = this.app.router(this.app.getContracts(chain));
const remoteChains = await this.app.remoteChains(chain);
const actualRemoteChains = await this.app.remoteChains(chain);

const currentRouters: ChainMap<string> = {};
const expectedRouters: ChainMap<string> = {};
const routerDiff: ChainMap<{

const misconfiguredRouterDiff: ChainMap<{
actual: AddressBytes32;
expected: AddressBytes32;
}> = {};
const missingRouterDomains: ChainName[] = [];

await Promise.all(
remoteChains.map(async (remoteChain) => {
const remoteRouterAddress = this.app.routerAddress(remoteChain);
actualRemoteChains.map(async (remoteChain) => {
let remoteRouterAddress: string;
try {
remoteRouterAddress = this.app.routerAddress(remoteChain);
} catch {
// failed to read remote router address from the config
missingRouterDomains.push(remoteChain);
return;
}
const remoteDomainId = this.multiProvider.getDomainId(remoteChain);
const actualRouter = await router.routers(remoteDomainId);
const expectedRouter = addressToBytes32(remoteRouterAddress);
Expand All @@ -144,25 +155,41 @@ export class HyperlaneRouterChecker<
expectedRouters[remoteChain] = expectedRouter;

if (actualRouter !== expectedRouter) {
routerDiff[remoteChain] = {
misconfiguredRouterDiff[remoteChain] = {
actual: actualRouter,
expected: expectedRouter,
};
}
}),
);

if (Object.keys(routerDiff).length > 0) {
const expectedRouterChains = actualRemoteChains.filter(
(chain) => !missingRouterDomains.includes(chain),
);

if (Object.keys(misconfiguredRouterDiff).length > 0) {
const violation: RouterViolation = {
chain,
type: RouterViolationType.EnrolledRouter,
type: RouterViolationType.MisconfiguredEnrolledRouter,
contract: router,
actual: currentRouters,
expected: expectedRouters,
routerDiff,
routerDiff: misconfiguredRouterDiff,
description: `Routers for some domains are missing or not enrolled correctly`,
};
this.addViolation(violation);
}

if (missingRouterDomains.length > 0) {
const violation: MissingRouterViolation = {
chain,
type: RouterViolationType.MissingRouter,
contract: router,
actual: actualRemoteChains.join(','),
expected: expectedRouterChains.join(','),
description: `Routers for some domains are missing from the config`,
};
this.addViolation(violation);
}
}
}
11 changes: 9 additions & 2 deletions typescript/sdk/src/router/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ export interface ClientViolation extends CheckerViolation {
}

export enum RouterViolationType {
EnrolledRouter = 'EnrolledRouter',
MisconfiguredEnrolledRouter = 'MisconfiguredEnrolledRouter',
MissingRouter = 'MissingRouter',
}

export interface RouterViolation extends CheckerViolation {
type: RouterViolationType.EnrolledRouter;
type: RouterViolationType.MisconfiguredEnrolledRouter;
contract: Router;
routerDiff: ChainMap<{
actual: AddressBytes32;
Expand All @@ -61,6 +62,12 @@ export interface RouterViolation extends CheckerViolation {
description?: string;
}

export interface MissingRouterViolation extends CheckerViolation {
type: RouterViolationType.MissingRouter;
contract: Router;
description?: string;
}

export type RemoteRouters = z.infer<typeof RemoteRoutersSchema>;
export type DestinationGas = z.infer<typeof DestinationGasSchema>;

Expand Down

0 comments on commit d93a38c

Please sign in to comment.