Add script to verify that configured validators for an environment are consistent (#1400)

pull/1490/head
Asa Oines 2 years ago committed by GitHub
parent fb197930b4
commit 935750fff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      typescript/infra/scripts/list-validator-checkpoint-indices.ts
  2. 53
      typescript/infra/scripts/verify-validator.ts
  3. 53
      typescript/infra/scripts/verify-validators.ts
  4. 9
      typescript/infra/src/agents/aws/s3.ts
  5. 3
      typescript/infra/src/agents/aws/validator.ts

@ -32,10 +32,9 @@ async function main() {
// @ts-ignore // @ts-ignore
hyperlaneCoreAddresses[chain].mailbox, hyperlaneCoreAddresses[chain].mailbox,
// @ts-ignore // @ts-ignore
`https://${validator.checkpointSyncer.bucket!}.s3.${ validator.checkpointSyncer.bucket,
// @ts-ignore // @ts-ignore
validator.checkpointSyncer.region validator.checkpointSyncer.region,
}.amazonaws.com`,
); );
return { return {

@ -1,53 +0,0 @@
import { ethers } from 'ethers';
import yargs from 'yargs';
import {
AllChains,
ChainNameToDomainId,
hyperlaneCoreAddresses,
} from '@hyperlane-xyz/sdk';
import { S3Validator } from '../src/agents/aws/validator';
function getArgs() {
return yargs(process.argv.slice(2))
.describe('chain', 'chain of the validator to inspect')
.choices('chain', AllChains)
.demandOption('chain')
.describe('address', 'address of the validator to inspect')
.demandOption('address')
.string('address')
.describe('prospective', 'S3 bucket URL of the prospective validator')
.demandOption('prospective')
.string('prospective')
.describe('control', 'S3 bucket URL of the the known (control) validator')
.demandOption('control')
.string('control').argv;
}
async function main() {
const { address, prospective, control, chain } = await getArgs();
const localDomain = ChainNameToDomainId[chain];
const mailbox = hyperlaneCoreAddresses[chain].mailbox;
const controlValidator = new S3Validator(
ethers.constants.AddressZero,
localDomain,
mailbox,
control,
);
const prospectiveValidator = new S3Validator(
address,
localDomain,
mailbox,
prospective,
);
const metrics = await prospectiveValidator.compare(controlValidator);
console.log(JSON.stringify(metrics, null, 2));
}
main().catch(console.error);

@ -0,0 +1,53 @@
import {
ChainNameToDomainId,
hyperlaneCoreAddresses,
objMap,
} from '@hyperlane-xyz/sdk';
import { CheckpointStatus, S3Validator } from '../src/agents/aws/validator';
import { CheckpointSyncerType } from '../src/config/agent';
import { getContext, getCoreEnvironmentConfig, getEnvironment } from './utils';
async function main() {
const environment = await getEnvironment();
const coreConfig = getCoreEnvironmentConfig(environment);
const context = await getContext();
const validatorSets = coreConfig.agents[context]?.validatorSets;
if (!validatorSets)
throw Error(`No validator sets found for ${environment}:${context}`);
objMap(validatorSets, async (chain, validatorSet) => {
const domainId = ChainNameToDomainId[chain];
const mailbox = hyperlaneCoreAddresses[chain].mailbox;
const validators = validatorSet.validators.map((validator) => {
const checkpointSyncer = validator.checkpointSyncer;
if (checkpointSyncer.type == CheckpointSyncerType.S3) {
return new S3Validator(
validator.address,
domainId,
mailbox,
checkpointSyncer.bucket,
checkpointSyncer.region,
);
}
throw new Error('Cannot check non-s3 validator type');
});
const controlValidator = validators[0];
for (let i = 1; i < validators.length; i++) {
const prospectiveValidator = validators[i];
const metrics = await prospectiveValidator.compare(controlValidator);
const valid =
metrics.filter((metric) => metric.status !== CheckpointStatus.VALID)
.length === 0;
const name = validatorSet.validators[i].name;
if (!valid) {
console.log(`${name} has >=1 non-valid checkpoints for ${chain}`);
console.log(JSON.stringify(metrics, null, 2));
} else {
console.log(`${name} has valid checkpoints for ${chain}`);
}
}
});
}
main().catch(console.error);

@ -15,11 +15,14 @@ export class S3Wrapper {
private readonly client: S3Client; private readonly client: S3Client;
readonly bucket: string; readonly bucket: string;
constructor(bucketUrl: string) { static fromBucketUrl(bucketUrl: string): S3Wrapper {
const match = bucketUrl.match(S3_BUCKET_REGEX); const match = bucketUrl.match(S3_BUCKET_REGEX);
if (!match) throw new Error('Could not parse bucket url'); if (!match) throw new Error('Could not parse bucket url');
this.bucket = match[1]; return new S3Wrapper(match[1], match[2]);
const region = match[2]; }
constructor(bucket: string, region: string) {
this.bucket = bucket;
this.client = new S3Client({ region }); this.client = new S3Client({ region });
} }

@ -50,9 +50,10 @@ export class S3Validator extends BaseValidator {
localDomain: number, localDomain: number,
mailbox: string, mailbox: string,
s3Bucket: string, s3Bucket: string,
s3Region: string,
) { ) {
super(address, localDomain, mailbox); super(address, localDomain, mailbox);
this.s3Bucket = new S3Wrapper(s3Bucket); this.s3Bucket = new S3Wrapper(s3Bucket, s3Region);
} }
async getLatestCheckpointIndex() { async getLatestCheckpointIndex() {

Loading…
Cancel
Save