chore: enroll validators for megabatch + infra deployer fixes (#4383)

chore: enroll validators for megabatch

- ~~also includes some of the verifier fixes in
https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4381~~
- drive-by: passing the timeout through to the core deployer
- drive-by: fixing artifact write-back in infra deploy (resolves
https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4351)
- drive-by: adds a script to solely check for validator announcements
and print a nice table

![image](https://github.com/user-attachments/assets/ced42cf2-71af-4cff-b573-23b55a080a0a)

---------

Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com>
pull/4391/head
Paul Balaji 3 months ago committed by GitHub
parent 330d302a61
commit 44588c31d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .changeset/giant-items-suffer.md
  2. 41
      typescript/infra/scripts/check-validator-announce.ts
  3. 1
      typescript/infra/scripts/deploy.ts
  4. 24
      typescript/infra/scripts/print-balances.ts
  5. 17
      typescript/infra/scripts/verify-validators.ts
  6. 21
      typescript/infra/src/deployment/deploy.ts
  7. 106
      typescript/sdk/src/consts/multisigIsm.ts
  8. 3
      typescript/sdk/src/core/HyperlaneCoreDeployer.ts

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---
Enroll new validators for cyber degenchain kroma lisk lukso merlin metis mint proofofplay real sanko tangle xai taiko

@ -0,0 +1,41 @@
import { defaultMultisigConfigs } from '@hyperlane-xyz/sdk';
import { eqAddress } from '@hyperlane-xyz/utils';
import { isEthereumProtocolChain } from '../src/utils/utils.js';
import { getArgs, withChains } from './agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js';
async function main() {
const { environment, chains } = await withChains(getArgs()).argv;
const config = getEnvironmentConfig(environment);
const { core } = await getHyperlaneCore(environment);
const targetNetworks = (
chains && chains.length > 0 ? chains : config.supportedChainNames
).filter(isEthereumProtocolChain);
const results = await Promise.all(
targetNetworks.map(async (chain) => {
const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
const announcedValidators =
await validatorAnnounce.getAnnouncedValidators();
const validators = defaultMultisigConfigs[chain].validators || [];
const missingValidators = validators.filter(
(validator) =>
!announcedValidators.some((x) => eqAddress(x, validator)),
);
return {
chain,
status:
missingValidators.length === 0 ? '✅' : missingValidators.join(', '),
};
}),
);
console.table(results);
}
main().catch(console.error);

@ -126,6 +126,7 @@ async function main() {
ismFactory,
contractVerifier,
concurrentDeploy,
60 * 60 * 1000, // 60 minutes
);
} else if (module === Modules.WARP) {
if (!warpRouteId) {

@ -12,6 +12,11 @@ import {
} from './agent-utils.js';
import { getEnvironmentConfig } from './core-utils.js';
const MainnetDeployer = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba';
const MainnetRelayer = '0x74Cae0ECC47B02Ed9B9D32E000Fd70B9417970C5';
const TestnetDeployer = '0xfaD1C94469700833717Fa8a3017278BC1cA8031C';
const TestnetRelayer = '0x16626cd24fd1f228a031e48b77602ae25f8930db';
async function main() {
const {
context = Contexts.Hyperlane,
@ -38,10 +43,25 @@ async function main() {
const { decimals, symbol } = await multiProvider.getNativeToken(chain);
const roleBalances = await Promise.all(
roles.map(async (role) => {
// Fetch key
const keys = await envConfig.getKeys(context, role as Role);
await Promise.all(Object.values(keys).map((key) => key.fetch()));
if (keys[chain]) {
const balance = await provider.getBalance(keys[chain].address);
// Default to known deployer/relayer addresses if not found
let address = keys[chain]?.address;
if (!address) {
if (role === Role.Deployer) {
address =
environment === 'mainnet3' ? MainnetDeployer : TestnetDeployer;
} else if (role === Role.Relayer) {
address =
environment === 'mainnet3' ? MainnetRelayer : TestnetRelayer;
}
}
// Fetch balance
if (address) {
const balance = await provider.getBalance(address);
const formattedBalance = formatUnits(balance, decimals);
return Number(formattedBalance).toFixed(3);
}

@ -1,17 +1,26 @@
import { objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { CoreConfig } from '@hyperlane-xyz/sdk';
import { objFilter, objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { InfraS3Validator } from '../src/agents/aws/validator.js';
import { getArgs, getValidatorsByChain } from './agent-utils.js';
import { getArgs, getValidatorsByChain, withChains } from './agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js';
async function main() {
const { environment } = await getArgs().argv;
const { environment, chains } = await withChains(getArgs()).argv;
const config = getEnvironmentConfig(environment);
const { core } = await getHyperlaneCore(environment);
// Filter the config map to only check the given networks if supplied
const filteredConfig =
chains && chains.length > 0
? objFilter(config.core, (chain, _): _ is CoreConfig =>
(chains ?? []).includes(chain),
)
: config.core;
await promiseObjAll(
objMap(getValidatorsByChain(config.core), async (chain, set) => {
objMap(getValidatorsByChain(filteredConfig), async (chain, set) => {
const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
const storageLocations =
await validatorAnnounce.getAnnouncedStorageLocations([...set]);

@ -36,14 +36,6 @@ export async function deployWithArtifacts<Config extends object>({
deployer.cacheAddressesMap(addressesMap);
}
process.on('SIGINT', async () => {
// Call the post deploy hook to write the addresses and verification
await postDeploy(deployer, cache);
console.log('\nCaught (Ctrl+C), gracefully exiting...');
process.exit(0); // Exit the process
});
// Filter the config map to only deploy the target networks
let targetConfigMap = configMap;
if (targetNetworks.length > 0) {
@ -52,6 +44,18 @@ export async function deployWithArtifacts<Config extends object>({
);
}
const handleExit = async () => {
console.log('Running post-deploy steps');
await postDeploy(deployer, cache);
console.log('Post-deploy completed');
};
// Handle Ctrl+C
process.on('SIGINT', handleExit);
// One final post-deploy before exit to ensure
// deployments exceeding the timeout are still written
process.on('beforeExit', handleExit);
// Deploy the contracts
try {
await deployer.deploy(targetConfigMap);
@ -63,6 +67,7 @@ export async function deployWithArtifacts<Config extends object>({
}
}
// Call the post-deploy hook to write artifacts
await postDeploy(deployer, cache);
}

@ -133,13 +133,21 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
cyber: {
threshold: 1,
validators: ['0x94d7119ceeb802173b6924e6cc8c4cd731089a27'],
threshold: 2,
validators: [
'0x94d7119ceeb802173b6924e6cc8c4cd731089a27',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
degenchain: {
threshold: 1,
validators: ['0x433e311f19524cd64fb2123ad0aa1579a4e1fc83'],
threshold: 2,
validators: [
'0x433e311f19524cd64fb2123ad0aa1579a4e1fc83',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
eclipse: {
@ -239,8 +247,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
kroma: {
threshold: 1,
validators: ['0x71b83c21342787d758199e4b8634d3a15f02dc6e'],
threshold: 2,
validators: [
'0x71b83c21342787d758199e4b8634d3a15f02dc6e',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
linea: {
@ -253,13 +265,20 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
lisk: {
threshold: 1,
validators: ['0xc0b282aa5bac43fee83cf71dc3dd1797c1090ea5'],
threshold: 2,
validators: [
'0xc0b282aa5bac43fee83cf71dc3dd1797c1090ea5',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
lukso: {
threshold: 1,
validators: ['0xa5e953701dcddc5b958b5defb677a829d908df6d'],
threshold: 2,
validators: [
'0xa5e953701dcddc5b958b5defb677a829d908df6d',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
],
},
mantapacific: {
@ -285,18 +304,30 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
merlin: {
threshold: 1,
validators: ['0xc1d6600cb9326ed2198cc8c4ba8d6668e8671247'],
threshold: 2,
validators: [
'0xc1d6600cb9326ed2198cc8c4ba8d6668e8671247',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
metis: {
threshold: 1,
validators: ['0xc4a3d25107060e800a43842964546db508092260'],
threshold: 2,
validators: [
'0xc4a3d25107060e800a43842964546db508092260',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
mint: {
threshold: 1,
validators: ['0xfed01ccdd7a65e8a6ad867b7fb03b9eb47777ac9'],
threshold: 2,
validators: [
'0xfed01ccdd7a65e8a6ad867b7fb03b9eb47777ac9',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x0230505530b80186f8cdccfaf9993eb97aebe98a', // mint
],
},
mode: {
@ -381,13 +412,21 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
proofofplay: {
threshold: 1,
validators: ['0xcda40baa71970a06e5f55e306474de5ca4e21c3b'],
threshold: 2,
validators: [
'0xcda40baa71970a06e5f55e306474de5ca4e21c3b',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
real: {
threshold: 1,
validators: ['0xaebadd4998c70b05ce8715cf0c3cb8862fe0beec'],
threshold: 2,
validators: [
'0xaebadd4998c70b05ce8715cf0c3cb8862fe0beec',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
redstone: {
@ -399,8 +438,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
sanko: {
threshold: 1,
validators: ['0x795c37d5babbc44094b084b0c89ed9db9b5fae39'],
threshold: 2,
validators: [
'0x795c37d5babbc44094b084b0c89ed9db9b5fae39',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
scroll: {
@ -480,17 +523,22 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
taiko: {
threshold: 2,
threshold: 3,
validators: [
'0xa930073c8f2d0b2f7423ea32293e0d1362e65d79',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
'0x2F007c82672F2Bb97227D4e3F80Ac481bfB40A2a', // luganodes
],
},
tangle: {
threshold: 1,
validators: ['0x1ee52cbbfacd7dcb0ba4e91efaa6fbc61602b15b'],
threshold: 2,
validators: [
'0x1ee52cbbfacd7dcb0ba4e91efaa6fbc61602b15b',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0xe271ef9a6e312540f099a378865432fa73f26689', // tangle
],
},
viction: {
@ -512,8 +560,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
xai: {
threshold: 1,
validators: ['0xe993f01fea86eb64cda45ae5af1d5be40ac0c7e9'],
threshold: 2,
validators: [
'0xe993f01fea86eb64cda45ae5af1d5be40ac0c7e9',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
xlayer: {

@ -34,10 +34,11 @@ export class HyperlaneCoreDeployer extends HyperlaneDeployer<
readonly ismFactory: HyperlaneIsmFactory,
contractVerifier?: ContractVerifier,
concurrentDeploy: boolean = false,
chainTimeoutMs: number = 1000 * 60 * 10, // 10 minutes
) {
super(multiProvider, coreFactories, {
logger: rootLogger.child({ module: 'CoreDeployer' }),
chainTimeoutMs: 1000 * 60 * 10, // 10 minutes
chainTimeoutMs,
ismFactory,
contractVerifier,
concurrentDeploy,

Loading…
Cancel
Save