Skip to content

Commit

Permalink
feat:allow full IsmConfig for CLI as an advanced config feature (#2939)
Browse files Browse the repository at this point in the history
### Description

- added `ism-advanced` config which allows you flexibility to define
your own IsmConfig shape
  - configure through `hyperlane config create ism-advanced`
- core deployments checks for both `ism-advanced.yaml` and then
`ism.yaml` (old multisig config way) ie. precedence is given to the
advanced version
- support for `Aggregation`, `Routing`, `MerkleRoot`, `MessageId`, and
`TestIsm` (with a warning)
- instead of routing over just messageId, the simpler `ism` config way
is now routing over aggregation of merkle and message matching hyperlane
V3 core deployments
- also renamed multisig option to ism to not introduce multisig
user-side and stick with consistent ism or ism- options.

### Drive-by changes

- `ism.yaml` doesn't take in a type since we provide both `merkleRoot`
and `messageId` variants by default.

### Related issues

- fixes hyperlane-xyz/issues#737

### Backward compatibility

Yes

### Testing

Manual

---------

Co-authored-by: Yorke Rhodes <[email protected]>
  • Loading branch information
aroralanuk and yorhodes authored Nov 28, 2023
1 parent 50aed86 commit df69370
Show file tree
Hide file tree
Showing 24 changed files with 832 additions and 86 deletions.
6 changes: 6 additions & 0 deletions .changeset/tiny-teachers-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperlane-xyz/cli': minor
'@hyperlane-xyz/sdk': minor
---

Add support for all ISM types in CLI interactive config creation
2 changes: 1 addition & 1 deletion typescript/cli/ci-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ yarn workspace @hyperlane-xyz/cli run hyperlane deploy core \
--targets anvil1,anvil2 \
--chains ./examples/anvil-chains.yaml \
--artifacts /tmp/empty-artifacts.json \
--ism ./examples/multisig-ism.yaml \
--ism ./examples/ism.yaml \
--hook ./examples/hook-config.yaml \
--out /tmp \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
Expand Down
33 changes: 33 additions & 0 deletions typescript/cli/examples/ism-advanced.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
anvil1:
type: domainRoutingIsm
owner: '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
domains:
anvil2:
type: staticAggregationIsm
modules:
- type: messageIdMultisigIsm
threshold: 1
validators:
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
- type: merkleRootMultisigIsm
threshold: 1
validators:
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
threshold: 1

anvil2:
type: domainRoutingIsm
owner: '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
domains:
anvil1:
type: staticAggregationIsm
modules:
- type: messageIdMultisigIsm
threshold: 1
validators:
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
- type: merkleRootMultisigIsm
threshold: 1
validators:
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
threshold: 1
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
# A config for a multisig Interchain Security Module (ISM)
# Schema: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/ism/types.ts
#
# Valid module types:
# routing
# aggregation
# merkleRootMultisig
# messageIdMultisigIsm

# ism type don't work currently (sets to messageIdMultisigIsm for all)
---
anvil1:
type: 'messageIdMultisigIsm'
threshold: 1 # Number: Signatures required to approve a message
validators: # Array: List of validator addresses
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
anvil2:
type: 'messageIdMultisigIsm'
threshold: 1
validators:
- '0xa0ee7a142d267c1f36714e4a8f75612f20a79720'
53 changes: 43 additions & 10 deletions typescript/cli/src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CommandModule } from 'yargs';
import { log, logGreen } from '../../logger.js';
import { createChainConfig, readChainConfigs } from '../config/chain.js';
import { createHookConfig } from '../config/hooks.js';
import { createIsmConfigMap, readIsmConfig } from '../config/ism.js';
import {
createMultisigConfig,
readMultisigConfig,
Expand Down Expand Up @@ -40,7 +41,7 @@ const createCommand: CommandModule = {
builder: (yargs) =>
yargs
.command(createChainConfigCommand)
.command(createMultisigConfigCommand)
.command(createIsmConfigCommand)
.command(createHookConfigCommand)
.command(createWarpConfigCommand)
.version(false)
Expand All @@ -64,20 +65,32 @@ const createChainConfigCommand: CommandModule = {
},
};

const createMultisigConfigCommand: CommandModule = {
command: 'multisig',
describe: 'Create a new Multisig ISM config',
const createIsmConfigCommand: CommandModule = {
command: 'ism',
describe: 'Create a basic or advanced ISM config for a validator set',
builder: (yargs) =>
yargs.options({
output: outputFileOption('./configs/multisig-ism.yaml'),
output: outputFileOption('./configs/ism.yaml'),
format: fileFormatOption,
chains: chainsCommandOption,
advanced: {
type: 'boolean',
describe: 'Create an advanced ISM configuration',
default: false,
},
}),
handler: async (argv: any) => {
const format: FileFormat = argv.format;
const outPath: string = argv.output;
const chainConfigPath: string = argv.chains;
await createMultisigConfig({ format, outPath, chainConfigPath });
const isAdvanced: boolean = argv.advanced;

if (isAdvanced) {
await createIsmConfigMap({ format, outPath, chainConfigPath });
} else {
await createMultisigConfig({ format, outPath, chainConfigPath });
}

process.exit(0);
},
};
Expand Down Expand Up @@ -127,7 +140,8 @@ const validateCommand: CommandModule = {
builder: (yargs) =>
yargs
.command(validateChainCommand)
.command(validateMultisigCommand)
.command(validateIsmCommand)
.command(validateIsmAdvancedCommand)
.command(validateWarpCommand)
.version(false)
.demandCommand(),
Expand All @@ -152,9 +166,9 @@ const validateChainCommand: CommandModule = {
},
};

const validateMultisigCommand: CommandModule = {
command: 'multisig',
describe: 'Validate a multisig ism config in a YAML or JSON file',
const validateIsmCommand: CommandModule = {
command: 'ism',
describe: 'Validate the basic ISM config in a YAML or JSON file',
builder: (yargs) =>
yargs.options({
path: {
Expand All @@ -171,6 +185,25 @@ const validateMultisigCommand: CommandModule = {
},
};

const validateIsmAdvancedCommand: CommandModule = {
command: 'ism-advanced',
describe: 'Validate the advanced ISM config in a YAML or JSON file',
builder: (yargs) =>
yargs.options({
path: {
type: 'string',
description: 'Input file path',
demandOption: true,
},
}),
handler: async (argv) => {
const path = argv.path as string;
readIsmConfig(path);
logGreen('Config is valid');
process.exit(0);
},
};

const validateWarpCommand: CommandModule = {
command: 'warp',
describe: 'Validate a Warp Route config in a YAML or JSON file',
Expand Down
2 changes: 1 addition & 1 deletion typescript/cli/src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const coreCommand: CommandModule = {
ism: {
type: 'string',
description:
'A path to a JSON or YAML file with ISM configs (e.g. Multisig)',
'A path to a JSON or YAML file with basic or advanced ISM configs (e.g. Multisig)',
},
hook: {
type: 'string',
Expand Down
4 changes: 2 additions & 2 deletions typescript/cli/src/config/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function presetHookConfigs(
export function readHookConfig(filePath: string) {
const config = readYamlOrJson(filePath);
if (!config) {
logRed(`No multisig config found at ${filePath}`);
logRed(`No hook config found at ${filePath}`);
return;
}
const result = HookConfigMapSchema.safeParse(config);
Expand All @@ -134,7 +134,7 @@ export function readHookConfig(filePath: string) {
type: config.default.type,
} as HookConfig),
);
logGreen(`All multisig configs in ${filePath} are valid`);
logGreen(`All hook configs in ${filePath} are valid`);
return defaultHook;
}

Expand Down
Loading

0 comments on commit df69370

Please sign in to comment.