diff --git a/.changeset/cold-dingos-give.md b/.changeset/cold-dingos-give.md new file mode 100644 index 00000000000..d9eaf08d3d9 --- /dev/null +++ b/.changeset/cold-dingos-give.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Optimize HyperlaneRelayer routing config derivation diff --git a/typescript/sdk/src/core/HyperlaneRelayer.ts b/typescript/sdk/src/core/HyperlaneRelayer.ts index 27341a773fa..cb0ba570e90 100644 --- a/typescript/sdk/src/core/HyperlaneRelayer.ts +++ b/typescript/sdk/src/core/HyperlaneRelayer.ts @@ -75,12 +75,18 @@ export class HyperlaneRelayer { async getHookConfig( chain: ChainName, hook: Address, + messageContext?: DispatchedMessage, ): Promise { let config: DerivedHookConfig | undefined; if (this.cache?.hook[chain]?.[hook]) { config = this.cache.hook[chain][hook] as DerivedHookConfig | undefined; } else { - const evmHookReader = new EvmHookReader(this.multiProvider, chain); + const evmHookReader = new EvmHookReader( + this.multiProvider, + chain, + undefined, + messageContext, + ); config = await evmHookReader.deriveHookConfig(hook); } @@ -98,12 +104,18 @@ export class HyperlaneRelayer { async getIsmConfig( chain: ChainName, ism: Address, + messageContext?: DispatchedMessage, ): Promise { let config: DerivedIsmConfig | undefined; if (this.cache?.ism[chain]?.[ism]) { config = this.cache.ism[chain][ism] as DerivedIsmConfig | undefined; } else { - const evmIsmReader = new EvmIsmReader(this.multiProvider, chain); + const evmIsmReader = new EvmIsmReader( + this.multiProvider, + chain, + undefined, + messageContext, + ); config = await evmIsmReader.deriveIsmConfig(ism); } @@ -124,7 +136,7 @@ export class HyperlaneRelayer { ): Promise { const originChain = this.core.getOrigin(message); const hook = await this.core.getSenderHookAddress(message); - return this.getHookConfig(originChain, hook); + return this.getHookConfig(originChain, hook, message); } async getRecipientIsmConfig( @@ -132,7 +144,7 @@ export class HyperlaneRelayer { ): Promise { const destinationChain = this.core.getDestination(message); const ism = await this.core.getRecipientIsmAddress(message); - return this.getIsmConfig(destinationChain, ism); + return this.getIsmConfig(destinationChain, ism, message); } async relayMessage( diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index 518b63e5850..1ed1f42ab79 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -26,6 +26,7 @@ import { } from '@hyperlane-xyz/utils'; import { DEFAULT_CONTRACT_READ_CONCURRENCY } from '../consts/concurrency.js'; +import { DispatchedMessage } from '../core/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { ChainNameOrId } from '../types.js'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; @@ -96,6 +97,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { protected readonly concurrency: number = multiProvider.tryGetRpcConcurrency( chain, ) ?? DEFAULT_CONTRACT_READ_CONCURRENCY, + protected readonly messageContext?: DispatchedMessage, ) { super(multiProvider, chain); } @@ -379,6 +381,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { address: Address, ): Promise> { const hook = DomainRoutingHook__factory.connect(address, this.provider); + this.assertHookType(await hook.hookType(), OnchainHookType.ROUTING); const owner = await hook.owner(); @@ -403,6 +406,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { address, this.provider, ); + this.assertHookType( await hook.hookType(), OnchainHookType.FALLBACK_ROUTING, @@ -430,7 +434,9 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { private async fetchDomainHooks( hook: DomainRoutingHook | FallbackDomainRoutingHook, ): Promise { - const domainIds = this.multiProvider.getKnownDomainIds(); + const domainIds = this.messageContext + ? [this.messageContext.parsed.destination] + : this.multiProvider.getKnownDomainIds(); const domainHooks: RoutingHookConfig['domains'] = {}; await concurrentMap(this.concurrency, domainIds, async (domainId) => { diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index c7d766e8cab..47e58d2b76d 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -1,4 +1,4 @@ -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { ArbL2ToL1Ism__factory, @@ -21,6 +21,7 @@ import { } from '@hyperlane-xyz/utils'; import { DEFAULT_CONTRACT_READ_CONCURRENCY } from '../consts/concurrency.js'; +import { DispatchedMessage } from '../core/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { ChainNameOrId } from '../types.js'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; @@ -66,6 +67,7 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { protected readonly concurrency: number = multiProvider.tryGetRpcConcurrency( chain, ) ?? DEFAULT_CONTRACT_READ_CONCURRENCY, + protected readonly messageContext?: DispatchedMessage, ) { super(multiProvider, chain); } @@ -129,11 +131,14 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { address, this.provider, ); + const owner = await ism.owner(); this.assertModuleType(await ism.moduleType(), ModuleType.ROUTING); + const domainIds = this.messageContext + ? [BigNumber.from(this.messageContext.parsed.origin)] + : await ism.domains(); const domains: RoutingIsmConfig['domains'] = {}; - const domainIds = await ism.domains(); await concurrentMap(this.concurrency, domainIds, async (domainId) => { const chainName = this.multiProvider.tryGetChainName(domainId.toNumber());