Skip to content

Commit 32479e1

Browse files
authored
feat: introduce alt-VM interface (#7141)
1 parent 70354d6 commit 32479e1

81 files changed

Lines changed: 4248 additions & 2911 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/pink-ladybugs-arrive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperlane-xyz/cosmos-sdk": major
3+
---
4+
5+
feat: implement cosmos-sdk for new AltVM interface

.changeset/rich-glasses-dress.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperlane-xyz/utils": major
3+
---
4+
5+
feat: add AltVM interface

.changeset/soft-seals-sell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperlane-xyz/widgets": major
3+
---
4+
5+
feat: use new AltVM providers

.changeset/twenty-lemons-double.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperlane-xyz/cli": major
3+
---
4+
5+
feat: register AltVM signer & provider factories

.changeset/wet-rabbits-stare.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperlane-xyz/sdk": major
3+
---
4+
5+
feat: implement new AltVM modules and readers

typescript/cli/src/commands/warp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ export const check: CommandModuleWithContext<SelectWarpRouteBuilder> = {
390390

391391
let expandedWarpDeployConfig = await expandWarpDeployConfig({
392392
multiProvider: context.multiProvider,
393-
multiProtocolProvider: context.multiProtocolProvider,
393+
altVmProvider: context.altVmProvider,
394394
warpDeployConfig,
395395
deployedRoutersAddresses,
396396
expandedOnChainWarpConfig,

typescript/cli/src/config/protocols.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

typescript/cli/src/consts.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
1-
import { ProtocolType } from '@hyperlane-xyz/utils';
1+
import { MinimumRequiredGasByAction } from '@hyperlane-xyz/utils';
22

3-
export const MINIMUM_CORE_DEPLOY_GAS = {
4-
[ProtocolType.Ethereum]: (1e8).toString(),
5-
[ProtocolType.CosmosNative]: (1e6).toString(),
6-
};
7-
export const MINIMUM_WARP_DEPLOY_GAS = {
8-
[ProtocolType.Ethereum]: (3e7).toString(),
9-
[ProtocolType.CosmosNative]: (3e6).toString(),
10-
};
11-
export const MINIMUM_TEST_SEND_GAS = {
12-
[ProtocolType.Ethereum]: (3e5).toString(),
13-
[ProtocolType.CosmosNative]: (3e5).toString(),
14-
};
15-
export const MINIMUM_AVS_GAS = {
16-
[ProtocolType.Ethereum]: (3e6).toString(),
17-
[ProtocolType.CosmosNative]: (3e6).toString(),
3+
export const ETHEREUM_MINIMUM_GAS: MinimumRequiredGasByAction = {
4+
CORE_DEPLOY_GAS: BigInt(1e8),
5+
WARP_DEPLOY_GAS: BigInt(3e7),
6+
TEST_SEND_GAS: BigInt(3e5),
7+
AVS_GAS: BigInt(3e6),
188
};
199

2010
export const PROXY_DEPLOYED_URL = 'https://proxy.hyperlane.xyz';
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
import { password } from '@inquirer/prompts';
2+
3+
import {
4+
CosmosNativeProvider,
5+
CosmosNativeSigner,
6+
} from '@hyperlane-xyz/cosmos-sdk';
7+
import {
8+
AltVMJsonRpcTxSubmitter,
9+
AnyProtocolReceipt,
10+
AnyProtocolTransaction,
11+
ChainMap,
12+
ChainMetadataManager,
13+
MultiProvider,
14+
ProtocolMap,
15+
SubmitterFactory,
16+
SubmitterMetadata,
17+
TxSubmitterType,
18+
isJsonRpcSubmitterConfig,
19+
} from '@hyperlane-xyz/sdk';
20+
import {
21+
AltVM,
22+
type MinimumRequiredGasByAction,
23+
ProtocolType,
24+
assert,
25+
} from '@hyperlane-xyz/utils';
26+
27+
import { ExtendedChainSubmissionStrategy } from '../submitters/types.js';
28+
29+
import { SignerKeyProtocolMap } from './types.js';
30+
31+
// ### ALL Alt VM PROTOCOLS ARE REGISTERED HERE ###
32+
const ALT_VM_SUPPORTED_PROTOCOLS: AltVMProtocol = {
33+
[ProtocolType.CosmosNative]: {
34+
provider: CosmosNativeProvider,
35+
signer: CosmosNativeSigner,
36+
gas: {
37+
CORE_DEPLOY_GAS: BigInt(1e6),
38+
WARP_DEPLOY_GAS: BigInt(3e6),
39+
TEST_SEND_GAS: BigInt(3e5),
40+
AVS_GAS: BigInt(3e6),
41+
},
42+
},
43+
// [NEW PROTOCOL]: {...}
44+
};
45+
46+
type AltVMProtocol = ProtocolMap<{
47+
provider: AltVM.IProviderConnect;
48+
signer: AltVM.ISignerConnect<AnyProtocolTransaction, AnyProtocolReceipt>;
49+
gas: MinimumRequiredGasByAction;
50+
}>;
51+
52+
class AltVMSupportedProtocols implements AltVM.ISupportedProtocols {
53+
public getSupportedProtocols(): ProtocolType[] {
54+
return Object.keys(ALT_VM_SUPPORTED_PROTOCOLS) as ProtocolType[];
55+
}
56+
57+
public supports(protocol: ProtocolType) {
58+
return !!ALT_VM_SUPPORTED_PROTOCOLS[protocol];
59+
}
60+
61+
public getMinGas(protocol: ProtocolType) {
62+
const protocolDefinition = ALT_VM_SUPPORTED_PROTOCOLS[protocol];
63+
64+
if (!protocolDefinition) {
65+
throw new Error(`Protocol type ${protocol} not supported in AltVM`);
66+
}
67+
68+
return protocolDefinition.gas;
69+
}
70+
}
71+
72+
export class AltVMProviderFactory
73+
extends AltVMSupportedProtocols
74+
implements AltVM.IProviderFactory
75+
{
76+
private readonly metadataManager: ChainMetadataManager;
77+
78+
constructor(metadataManager: ChainMetadataManager) {
79+
super();
80+
81+
this.metadataManager = metadataManager;
82+
}
83+
84+
public async get(chain: string): Promise<AltVM.IProvider> {
85+
const metadata = this.metadataManager.getChainMetadata(chain);
86+
const protocolDefinition = ALT_VM_SUPPORTED_PROTOCOLS[metadata.protocol];
87+
88+
if (!protocolDefinition) {
89+
throw new Error(
90+
`Chain ${chain} with protocol type ${metadata.protocol} not supported in AltVM`,
91+
);
92+
}
93+
94+
return protocolDefinition.provider.connect(
95+
metadata.rpcUrls.map((rpc) => rpc.http),
96+
);
97+
}
98+
}
99+
100+
export class AltVMSignerFactory
101+
extends AltVMSupportedProtocols
102+
implements AltVM.ISignerFactory<AnyProtocolTransaction, AnyProtocolReceipt>
103+
{
104+
private readonly metadataManager: ChainMetadataManager;
105+
private readonly chains: ChainMap<
106+
AltVM.ISigner<AnyProtocolTransaction, AnyProtocolReceipt>
107+
>;
108+
109+
private constructor(
110+
metadataManager: ChainMetadataManager,
111+
chains: ChainMap<AltVM.ISigner<AnyProtocolTransaction, AnyProtocolReceipt>>,
112+
) {
113+
super();
114+
115+
this.metadataManager = metadataManager;
116+
this.chains = chains;
117+
}
118+
119+
public get(
120+
chain: string,
121+
): AltVM.ISigner<AnyProtocolTransaction, AnyProtocolReceipt> {
122+
const protocol = this.metadataManager.getProtocol(chain);
123+
124+
if (!this.supports(protocol)) {
125+
throw new Error(
126+
`Chain ${chain} with protocol type ${protocol} not supported in AltVM`,
127+
);
128+
}
129+
130+
if (!this.chains[chain]) {
131+
throw new Error(`AltVM was not initialized with chain ${chain}`);
132+
}
133+
134+
return this.chains[chain];
135+
}
136+
137+
private static async loadPrivateKey(
138+
keyByProtocol: SignerKeyProtocolMap,
139+
strategyConfig: Partial<ExtendedChainSubmissionStrategy>,
140+
protocol: ProtocolType,
141+
chain: string,
142+
): Promise<string> {
143+
// 1. First try to get private key from --key.{protocol} flag
144+
if (keyByProtocol[protocol]) {
145+
return keyByProtocol[protocol]!;
146+
}
147+
148+
// 2. If no key flag was provided we check if a strategy config
149+
// was provided for our chain where we can read our private key
150+
if (strategyConfig[chain]) {
151+
const rawConfig = strategyConfig[chain]!.submitter;
152+
if (!isJsonRpcSubmitterConfig(rawConfig)) {
153+
throw new Error(
154+
`found unknown submitter in strategy config for chain ${chain}`,
155+
);
156+
}
157+
158+
if (!rawConfig.privateKey) {
159+
throw new Error(
160+
`missing private key in strategy config for chain ${chain}`,
161+
);
162+
}
163+
164+
return rawConfig.privateKey;
165+
}
166+
167+
// 3. Finally, if no key flag or strategy was provided we prompt the user
168+
// for the private key. We save it in the keyByProtocol map so that we can
169+
// reuse it if another chain is of the same protocol
170+
keyByProtocol[protocol] = await password({
171+
message: `Please enter the private key for chain ${chain} (will be re-used for other chains with the same protocol type)`,
172+
});
173+
174+
return keyByProtocol[protocol]!;
175+
}
176+
177+
public static async createSigners(
178+
metadataManager: ChainMetadataManager,
179+
chains: string[],
180+
keyByProtocol: SignerKeyProtocolMap,
181+
strategyConfig: Partial<ExtendedChainSubmissionStrategy>,
182+
) {
183+
const signers: ChainMap<
184+
AltVM.ISigner<AnyProtocolTransaction, AnyProtocolReceipt>
185+
> = {};
186+
187+
for (const chain of chains) {
188+
const metadata = metadataManager.getChainMetadata(chain);
189+
190+
if (metadata.protocol === ProtocolType.Ethereum) {
191+
continue;
192+
}
193+
194+
if (metadata.protocol === ProtocolType.Sealevel) {
195+
continue;
196+
}
197+
198+
const protocol = ALT_VM_SUPPORTED_PROTOCOLS[metadata.protocol];
199+
200+
if (!protocol) {
201+
throw new Error(
202+
`Chain ${chain} with protocol type ${metadata.protocol} not supported in AltVM`,
203+
);
204+
}
205+
206+
const privateKey = await AltVMSignerFactory.loadPrivateKey(
207+
keyByProtocol,
208+
strategyConfig,
209+
metadata.protocol,
210+
chain,
211+
);
212+
213+
signers[chain] = await protocol.signer.connectWithSigner(
214+
metadata.rpcUrls.map((rpc) => rpc.http),
215+
privateKey,
216+
{
217+
metadata,
218+
},
219+
);
220+
}
221+
222+
return new AltVMSignerFactory(metadataManager, signers);
223+
}
224+
225+
public submitterFactories(): ProtocolMap<Record<string, SubmitterFactory>> {
226+
const factories: ProtocolMap<Record<string, SubmitterFactory>> = {};
227+
228+
for (const protocol of this.getSupportedProtocols()) {
229+
factories[protocol] = {
230+
[TxSubmitterType.JSON_RPC]: (
231+
multiProvider: MultiProvider,
232+
metadata: SubmitterMetadata,
233+
) => {
234+
// Used to type narrow metadata
235+
assert(
236+
metadata.type === TxSubmitterType.JSON_RPC,
237+
`Invalid metadata type: ${metadata.type}, expected ${TxSubmitterType.JSON_RPC}`,
238+
);
239+
return new AltVMJsonRpcTxSubmitter(multiProvider, this, metadata);
240+
},
241+
};
242+
}
243+
244+
return factories;
245+
}
246+
}

typescript/cli/src/context/context.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { readChainSubmissionStrategyConfig } from '../config/strategy.js';
1818
import { detectAndConfirmOrPrompt } from '../utils/input.js';
1919
import { getSigner } from '../utils/keys.js';
2020

21+
import { AltVMProviderFactory, AltVMSignerFactory } from './altvm.js';
2122
import { ChainResolverFactory } from './strategies/chain/ChainResolverFactory.js';
2223
import { MultiProtocolSignerManager } from './strategies/signer/MultiProtocolSignerManager.js';
2324
import {
@@ -77,7 +78,16 @@ export async function signerMiddleware(argv: Record<string, any>) {
7778
* @notice Attaches signers to MultiProvider and assigns it to argv.multiProvider
7879
*/
7980
argv.context.multiProvider = await multiProtocolSigner.getMultiProvider();
80-
argv.context.multiProtocolSigner = multiProtocolSigner;
81+
82+
/**
83+
* Creates AltVM signers
84+
*/
85+
argv.context.altVmSigner = await AltVMSignerFactory.createSigners(
86+
argv.context.multiProvider,
87+
chains,
88+
key,
89+
strategyConfig,
90+
);
8191

8292
return argv;
8393
}
@@ -109,13 +119,20 @@ export async function getContext({
109119

110120
const multiProvider = await getMultiProvider(registry);
111121
const multiProtocolProvider = await getMultiProtocolProvider(registry);
122+
const altVmProvider = new AltVMProviderFactory(multiProvider);
123+
const supportedProtocols = [
124+
ProtocolType.Ethereum,
125+
...altVmProvider.getSupportedProtocols(),
126+
];
112127

113128
return {
114129
registry,
115130
requiresKey,
116131
chainMetadata: multiProvider.metadata,
117132
multiProvider,
118133
multiProtocolProvider,
134+
altVmProvider,
135+
supportedProtocols,
119136
key: keyMap,
120137
skipConfirmation: !!skipConfirmation,
121138
signerAddress: ethereumSignerAddress,

0 commit comments

Comments
 (0)