Add ValidatorAnnounce to HyperlaneCoreDeploy (#1560)

submodules-1.0.0
Asa Oines 2 years ago committed by GitHub
parent 63376c0ffb
commit c0e2c512ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      rust/agents/validator/src/submit.rs
  2. 17
      rust/config/test/test_config.json
  3. 4
      rust/hyperlane-base/src/traits/checkpoint_syncer.rs
  4. 8
      rust/hyperlane-base/src/types/local_storage.rs
  5. 12
      rust/hyperlane-base/src/types/s3_storage.rs
  6. 14
      rust/hyperlane-core/src/types/announcement.rs
  7. 25
      rust/utils/run-locally/src/main.rs
  8. 42
      typescript/infra/hardhat.config.ts
  9. 1
      typescript/infra/package.json
  10. 1
      typescript/infra/src/config/agent.ts
  11. 17
      typescript/infra/src/core/deploy.ts
  12. 27
      typescript/sdk/src/consts/environments/test.json
  13. 4
      typescript/sdk/src/core/contracts.ts
  14. 20
      typescript/sdk/src/deploy/core/HyperlaneCoreDeployer.ts

@ -46,9 +46,10 @@ impl ValidatorSubmitter {
async fn main_task(self) -> Result<()> {
// Sign and post the validator announcement
let announcement = Announcement {
validator: self.signer.eth_address(),
mailbox_address: self.mailbox.address(),
mailbox_domain: self.mailbox.domain().id(),
storage_metadata: self.checkpoint_syncer.announcement_metadata(),
storage_location: self.checkpoint_syncer.announcement_location(),
};
let signed_announcement = self.signer.sign(announcement).await?;
self.checkpoint_syncer

@ -6,7 +6,8 @@
"domain": "13371",
"addresses": {
"mailbox": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"interchainGasPaymaster": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707"
"interchainGasPaymaster": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"validatorAnnounce": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"
},
"signer": null,
"protocol": "ethereum",
@ -23,8 +24,9 @@
"name": "test2",
"domain": "13372",
"addresses": {
"mailbox": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"interchainGasPaymaster": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82"
"mailbox": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"interchainGasPaymaster": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"validatorAnnounce": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE"
},
"signer": null,
"protocol": "ethereum",
@ -34,15 +36,16 @@
"url": ""
},
"index": {
"from": "12"
"from": "13"
}
},
"test3": {
"name": "test3",
"domain": "13373",
"addresses": {
"mailbox": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"interchainGasPaymaster": "0x59b670e9fA9D0A427751Af201D676719a970857b"
"mailbox": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"interchainGasPaymaster": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"validatorAnnounce": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F"
},
"signer": null,
"protocol": "ethereum",
@ -52,7 +55,7 @@
"url": ""
},
"index": {
"from": "20"
"from": "23"
}
}
},

@ -16,6 +16,6 @@ pub trait CheckpointSyncer: Debug + Send + Sync {
async fn write_checkpoint(&self, signed_checkpoint: &SignedCheckpoint) -> Result<()>;
/// Write the signed announcement to this syncer
async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()>;
/// Return the announcement storage metadata for this syncer
fn announcement_metadata(&self) -> String;
/// Return the announcement storage location for this syncer
fn announcement_location(&self) -> String;
}

@ -101,9 +101,9 @@ impl CheckpointSyncer for LocalStorage {
Ok(())
}
fn announcement_metadata(&self) -> String {
let mut metadata: String = "file://".to_owned();
metadata.push_str(self.announcement_file_path().as_ref());
metadata
fn announcement_location(&self) -> String {
let mut location: String = "file://".to_owned();
location.push_str(self.announcement_file_path().as_ref());
location
}
}

@ -188,11 +188,11 @@ impl CheckpointSyncer for S3Storage {
.await?;
Ok(())
}
fn announcement_metadata(&self) -> String {
let mut metadata: String = "s3://".to_owned();
metadata.push_str(self.bucket.as_ref());
metadata.push('/');
metadata.push_str(self.region.name());
metadata
fn announcement_location(&self) -> String {
let mut location: String = "s3://".to_owned();
location.push_str(self.bucket.as_ref());
location.push('/');
location.push_str(self.region.name());
location
}
}

@ -2,25 +2,27 @@ use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use sha3::{digest::Update, Digest, Keccak256};
use crate::{utils::domain_hash, Signable, SignedType, H256};
use crate::{utils::domain_hash, Signable, SignedType, H160, H256};
/// An Hyperlane checkpoint
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Announcement {
/// The validator address
pub validator: H160,
/// The mailbox address
pub mailbox_address: H256,
/// The mailbox chain
pub mailbox_domain: u32,
/// The checkpointed root
pub storage_metadata: String,
/// The location of signed checkpoints
pub storage_location: String,
}
impl std::fmt::Display for Announcement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Announcement(domain: {}, mailbox: {:x}, metadata: {})",
self.mailbox_domain, self.mailbox_address, self.storage_metadata
"Announcement(domain: {}, mailbox: {:x}, location: {})",
self.mailbox_domain, self.mailbox_address, self.storage_location
)
}
}
@ -33,7 +35,7 @@ impl Signable for Announcement {
H256::from_slice(
Keccak256::new()
.chain(domain_hash(self.mailbox_address, self.mailbox_domain))
.chain(&self.storage_metadata)
.chain(&self.storage_location)
.finalize()
.as_slice(),
)

@ -313,6 +313,31 @@ fn main() -> ExitCode {
}));
state.validator = Some(validator);
// Rebuild the SDK to pick up the deployed contracts
println!("Rebuilding sdk...");
build_cmd(
&["yarn", "build"],
&build_log,
log_all,
Some("../typescript/sdk"),
);
// Register the validator announcement
println!("Announcing validator...");
let mut announce = Command::new("yarn");
announce.arg("announce");
announce.args([
"--checkpointsdir",
checkpoints_dir.path().to_str().unwrap(),
"--chain",
"test1",
]);
announce
.current_dir("../typescript/infra")
.stdout(Stdio::piped())
.spawn()
.expect("Failed to announce validator");
println!("Setup complete! Agents running in background...");
println!("Ctrl+C to end execution...");

@ -1,7 +1,10 @@
import '@nomiclabs/hardhat-etherscan';
import '@nomiclabs/hardhat-waffle';
import { ethers } from 'ethers';
import { readFileSync } from 'fs';
import { task } from 'hardhat/config';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import * as path from 'path';
import { TestSendReceiver__factory } from '@hyperlane-xyz/core';
import {
@ -35,6 +38,45 @@ const chainSummary = async <Chain extends ChainName>(
return summary;
};
task('announce', 'Registers validator announcement')
.addParam('checkpointsdir', 'Directory containing announcement json file')
.addParam('chain', 'Chain to announce on')
.setAction(
async (
taskArgs: { checkpointsdir: string; chain: ChainName },
hre: HardhatRuntimeEnvironment,
) => {
const environment = 'test';
const config = getCoreEnvironmentConfig(environment);
const [signer] = await hre.ethers.getSigners();
const multiProvider = getTestMultiProvider(
signer,
config.transactionConfigs,
);
const core = HyperlaneCore.fromEnvironment(environment, multiProvider);
const announcementFilepath = path.join(
taskArgs.checkpointsdir,
'announcement.json',
);
const announcement = JSON.parse(
readFileSync(announcementFilepath, 'utf-8'),
);
const signature = ethers.utils.hexConcat([
announcement.signature.r,
announcement.signature.s,
ethers.utils.hexValue(announcement.signature.v),
]);
const tx = await core
.getContracts(taskArgs.chain)
.validatorAnnounce.announce(
announcement.announcement.validator,
announcement.announcement.storage_location,
signature,
);
await tx.wait();
},
);
task('kathy', 'Dispatches random hyperlane messages')
.addParam(
'rounds',

@ -62,6 +62,7 @@
"clean": "rm -rf ./dist ./cache",
"check": "tsc --noEmit",
"kathy": "hardhat kathy --network localhost",
"announce": "hardhat announce --network localhost",
"node": "hardhat node",
"prettier": "prettier --write *.ts ./src ./config ./scripts ./test",
"test": "hardhat test"

@ -251,6 +251,7 @@ export type RustConnection =
export type RustCoreAddresses = {
mailbox: types.Address;
interchainGasPaymaster: types.Address;
validatorAnnounce: types.Address;
};
export type RustChainSetup = {

@ -4,6 +4,7 @@ import {
InterchainGasPaymaster,
Mailbox,
ProxyAdmin,
ValidatorAnnounce,
} from '@hyperlane-xyz/core';
import {
ChainMap,
@ -70,6 +71,19 @@ export class HyperlaneCoreInfraDeployer<
);
}
async deployValidatorAnnounce<LocalChain extends Chain>(
chain: LocalChain,
mailboxAddress: types.Address,
): Promise<ValidatorAnnounce> {
const deployOpts = {
create2Salt: ethers.utils.solidityKeccak256(
['string', 'string', 'uint8'],
[this.environment, 'validatorAnnounce', 1],
),
};
return super.deployValidatorAnnounce(chain, mailboxAddress, deployOpts);
}
writeRustConfigs(directory: string) {
const rustConfig: RustConfig<Chain> = {
environment: this.environment,
@ -88,7 +102,7 @@ export class HyperlaneCoreInfraDeployer<
contracts == undefined ||
contracts.mailbox == undefined ||
contracts.interchainGasPaymaster == undefined ||
contracts.multisigIsm == undefined
contracts.validatorAnnounce == undefined
) {
return;
}
@ -99,6 +113,7 @@ export class HyperlaneCoreInfraDeployer<
addresses: {
mailbox: contracts.mailbox.contract.address,
interchainGasPaymaster: contracts.interchainGasPaymaster.address,
validatorAnnounce: contracts.validatorAnnounce.address,
},
signer: null,
protocol: 'ethereum',

@ -1,5 +1,6 @@
{
"test1": {
"validatorAnnounce": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
"proxyAdmin": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"interchainGasPaymaster": {
"kind": "Transparent",
@ -14,31 +15,33 @@
"multisigIsm": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"test2": {
"proxyAdmin": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"validatorAnnounce": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"proxyAdmin": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"interchainGasPaymaster": {
"kind": "Transparent",
"proxy": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"implementation": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
"proxy": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"implementation": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82"
},
"mailbox": {
"kind": "Transparent",
"proxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"implementation": "0x9A676e781A523b5d0C0e43731313A708CB607508"
"proxy": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"implementation": "0x0B306BF915C4d645ff596e518fAf3F9669b97016"
},
"multisigIsm": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"
"multisigIsm": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"
},
"test3": {
"proxyAdmin": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"validatorAnnounce": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
"proxyAdmin": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"interchainGasPaymaster": {
"kind": "Transparent",
"proxy": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"implementation": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"
"proxy": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"implementation": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1"
},
"mailbox": {
"kind": "Transparent",
"proxy": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"implementation": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1"
"proxy": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"implementation": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f"
},
"multisigIsm": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1"
"multisigIsm": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed"
}
}

@ -10,6 +10,8 @@ import {
MultisigIsm__factory,
ProxyAdmin,
ProxyAdmin__factory,
ValidatorAnnounce,
ValidatorAnnounce__factory,
} from '@hyperlane-xyz/core';
import { ProxiedContract, TransparentProxyAddresses } from '../proxy';
@ -25,11 +27,13 @@ export type CoreContracts = ConnectionClientContracts & {
mailbox: ProxiedContract<Mailbox, TransparentProxyAddresses>;
multisigIsm: MultisigIsm;
proxyAdmin: ProxyAdmin;
validatorAnnounce: ValidatorAnnounce;
};
export const coreFactories = {
interchainAccountRouter: new InterchainAccountRouter__factory(),
interchainQueryRouter: new InterchainQueryRouter__factory(),
validatorAnnounce: new ValidatorAnnounce__factory(),
create2Factory: new Create2Factory__factory(),
proxyAdmin: new ProxyAdmin__factory(),
interchainGasPaymaster: new InterchainGasPaymaster__factory(),

@ -7,6 +7,7 @@ import {
MultisigIsm,
Ownable,
ProxyAdmin,
ValidatorAnnounce,
} from '@hyperlane-xyz/core';
import type { types } from '@hyperlane-xyz/utils';
@ -79,6 +80,20 @@ export class HyperlaneCoreDeployer<
return mailbox;
}
async deployValidatorAnnounce<LocalChain extends Chain>(
chain: LocalChain,
mailboxAddress: string,
deployOpts?: DeployOptions,
): Promise<ValidatorAnnounce> {
const validatorAnnounce = await this.deployContract(
chain,
'validatorAnnounce',
[mailboxAddress],
deployOpts,
);
return validatorAnnounce;
}
async deployMultisigIsm<LocalChain extends Chain>(
chain: LocalChain,
): Promise<MultisigIsm> {
@ -173,11 +188,16 @@ export class HyperlaneCoreDeployer<
multisigIsm.address,
proxyAdmin,
);
const validatorAnnounce = await this.deployValidatorAnnounce(
chain,
mailbox.address,
);
// Mailbox ownership is transferred upon initialization.
const ownables: Ownable[] = [multisigIsm, proxyAdmin];
await this.transferOwnershipOfContracts(chain, ownables);
return {
validatorAnnounce,
proxyAdmin,
interchainGasPaymaster,
mailbox,

Loading…
Cancel
Save