From cd7a263eb6eb7bfb3b771c16cba94c3351640790 Mon Sep 17 00:00:00 2001
From: Lee <6251863+ltyu@users.noreply.github.com>
Date: Tue, 22 Oct 2024 17:41:08 -0400
Subject: [PATCH 01/61] fix: revert concurrency in Modules (#4730)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
### Description
Reverts https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4720
Reasons:
- Many of the public RPCs don't allow concurrency reads. The ones that
do don't tell us how much they allow so no point in defaulting to some
assumed number (20)
- retryAsync doesn't do anything here as the SmartProvider knows what to
do if a provider fails (retries with cooldown). SmartProvider has it's
own retryAsync
- Concurrency is configurable in the metadata. so configure for each
provider, as intended.
---
.changeset/fresh-donkeys-smile.md | 6 --
typescript/cli/src/utils/files.ts | 7 +-
typescript/sdk/src/consts/concurrency.ts | 2 +-
typescript/sdk/src/hook/EvmHookReader.ts | 127 +++++++++++------------
typescript/sdk/src/ism/EvmIsmReader.ts | 97 +++++++++--------
5 files changed, 113 insertions(+), 126 deletions(-)
delete mode 100644 .changeset/fresh-donkeys-smile.md
diff --git a/.changeset/fresh-donkeys-smile.md b/.changeset/fresh-donkeys-smile.md
deleted file mode 100644
index 23339249a4..0000000000
--- a/.changeset/fresh-donkeys-smile.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@hyperlane-xyz/cli': minor
-'@hyperlane-xyz/sdk': minor
----
-
-Enable concurrency for IsmModule
diff --git a/typescript/cli/src/utils/files.ts b/typescript/cli/src/utils/files.ts
index 17b115a989..9c7cb6216e 100644
--- a/typescript/cli/src/utils/files.ts
+++ b/typescript/cli/src/utils/files.ts
@@ -15,7 +15,6 @@ import { objMerge } from '@hyperlane-xyz/utils';
import { log } from '../logger.js';
export const MAX_READ_LINE_OUTPUT = 250;
-export const MAX_ALIAS_YAML = 100_000; // Used for yaml maxAliasCount. Ref: https://eemeli.org/yaml/#tojs-options
export type FileFormat = 'yaml' | 'json';
@@ -93,9 +92,7 @@ export function mergeJson>(
}
export function readYaml(filepath: string): T {
- return yamlParse(readFileAtPath(filepath), {
- maxAliasCount: MAX_ALIAS_YAML,
- }) as T;
+ return yamlParse(readFileAtPath(filepath)) as T;
}
export function tryReadYamlAtPath(filepath: string): T | null {
@@ -253,7 +250,7 @@ export function logYamlIfUnderMaxLines(
): void {
const asYamlString = yamlStringify(obj, null, margin);
const lineCounter = new LineCounter();
- parse(asYamlString, { lineCounter, maxAliasCount: MAX_ALIAS_YAML });
+ parse(asYamlString, { lineCounter });
log(lineCounter.lineStarts.length < maxLines ? asYamlString : '');
}
diff --git a/typescript/sdk/src/consts/concurrency.ts b/typescript/sdk/src/consts/concurrency.ts
index 62e6c801cc..d9cc8fa7c6 100644
--- a/typescript/sdk/src/consts/concurrency.ts
+++ b/typescript/sdk/src/consts/concurrency.ts
@@ -1 +1 @@
-export const DEFAULT_CONTRACT_READ_CONCURRENCY = 20;
+export const DEFAULT_CONTRACT_READ_CONCURRENCY = 1;
diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts
index a98e72b1ba..518b63e585 100644
--- a/typescript/sdk/src/hook/EvmHookReader.ts
+++ b/typescript/sdk/src/hook/EvmHookReader.ts
@@ -22,7 +22,6 @@ import {
concurrentMap,
eqAddress,
getLogLevel,
- retryAsync,
rootLogger,
} from '@hyperlane-xyz/utils';
@@ -116,72 +115,72 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
`Cache miss for HookConfig on chain ${this.chain} at: ${address}`,
);
- return retryAsync(async () => {
- let onchainHookType: OnchainHookType | undefined = undefined;
- let derivedHookConfig: DerivedHookConfig;
- try {
- const hook = IPostDispatchHook__factory.connect(address, this.provider);
-
- // Temporarily turn off SmartProvider logging
- // Provider errors are expected because deriving will call methods that may not exist in the Bytecode
- this.setSmartProviderLogLevel('silent');
- onchainHookType = await hook.hookType();
-
- switch (onchainHookType) {
- case OnchainHookType.ROUTING:
- derivedHookConfig = await this.deriveDomainRoutingConfig(address);
- break;
- case OnchainHookType.AGGREGATION:
- derivedHookConfig = await this.deriveAggregationConfig(address);
- break;
- case OnchainHookType.MERKLE_TREE:
- derivedHookConfig = await this.deriveMerkleTreeConfig(address);
- break;
- case OnchainHookType.INTERCHAIN_GAS_PAYMASTER:
- derivedHookConfig = await this.deriveIgpConfig(address);
- break;
- case OnchainHookType.FALLBACK_ROUTING:
- derivedHookConfig = await this.deriveFallbackRoutingConfig(address);
- break;
- case OnchainHookType.PAUSABLE:
- derivedHookConfig = await this.derivePausableConfig(address);
- break;
- case OnchainHookType.PROTOCOL_FEE:
- derivedHookConfig = await this.deriveProtocolFeeConfig(address);
- break;
- // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook
- // For now assume it's OP_STACK
- case OnchainHookType.ID_AUTH_ISM:
- derivedHookConfig = await this.deriveOpStackConfig(address);
- break;
- case OnchainHookType.ARB_L2_TO_L1:
- derivedHookConfig = await this.deriveArbL2ToL1Config(address);
- break;
- default:
- throw new Error(
- `Unsupported HookType: ${OnchainHookType[onchainHookType]}`,
- );
- }
- } catch (e: any) {
- let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`;
- if (
- !onchainHookType &&
- e.message.includes('Invalid response from provider')
- ) {
- customMessage = customMessage.concat(
- ` [The provided hook contract might be outdated and not support hookType()]`,
+ let onchainHookType: OnchainHookType | undefined = undefined;
+ let derivedHookConfig: DerivedHookConfig;
+
+ try {
+ const hook = IPostDispatchHook__factory.connect(address, this.provider);
+ this.logger.debug('Deriving HookConfig:', { address });
+
+ // Temporarily turn off SmartProvider logging
+ // Provider errors are expected because deriving will call methods that may not exist in the Bytecode
+ this.setSmartProviderLogLevel('silent');
+ onchainHookType = await hook.hookType();
+
+ switch (onchainHookType) {
+ case OnchainHookType.ROUTING:
+ derivedHookConfig = await this.deriveDomainRoutingConfig(address);
+ break;
+ case OnchainHookType.AGGREGATION:
+ derivedHookConfig = await this.deriveAggregationConfig(address);
+ break;
+ case OnchainHookType.MERKLE_TREE:
+ derivedHookConfig = await this.deriveMerkleTreeConfig(address);
+ break;
+ case OnchainHookType.INTERCHAIN_GAS_PAYMASTER:
+ derivedHookConfig = await this.deriveIgpConfig(address);
+ break;
+ case OnchainHookType.FALLBACK_ROUTING:
+ derivedHookConfig = await this.deriveFallbackRoutingConfig(address);
+ break;
+ case OnchainHookType.PAUSABLE:
+ derivedHookConfig = await this.derivePausableConfig(address);
+ break;
+ case OnchainHookType.PROTOCOL_FEE:
+ derivedHookConfig = await this.deriveProtocolFeeConfig(address);
+ break;
+ // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook
+ // For now assume it's OP_STACK
+ case OnchainHookType.ID_AUTH_ISM:
+ derivedHookConfig = await this.deriveOpStackConfig(address);
+ break;
+ case OnchainHookType.ARB_L2_TO_L1:
+ derivedHookConfig = await this.deriveArbL2ToL1Config(address);
+ break;
+ default:
+ throw new Error(
+ `Unsupported HookType: ${OnchainHookType[onchainHookType]}`,
);
- this.logger.info(`${customMessage}:\n\t${e}`);
- } else {
- this.logger.debug(`${customMessage}:\n\t${e}`);
- }
- throw new Error(`${customMessage}:\n\t${e}`);
- } finally {
- this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger
}
+ } catch (e: any) {
+ let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`;
+ if (
+ !onchainHookType &&
+ e.message.includes('Invalid response from provider')
+ ) {
+ customMessage = customMessage.concat(
+ ` [The provided hook contract might be outdated and not support hookType()]`,
+ );
+ this.logger.info(`${customMessage}:\n\t${e}`);
+ } else {
+ this.logger.debug(`${customMessage}:\n\t${e}`);
+ }
+ throw new Error(`${customMessage}:\n\t${e}`);
+ } finally {
+ this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger
+ }
- return derivedHookConfig;
- });
+ return derivedHookConfig;
}
async deriveMerkleTreeConfig(
diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts
index 6448cede41..c7d766e8ca 100644
--- a/typescript/sdk/src/ism/EvmIsmReader.ts
+++ b/typescript/sdk/src/ism/EvmIsmReader.ts
@@ -17,7 +17,6 @@ import {
assert,
concurrentMap,
getLogLevel,
- retryAsync,
rootLogger,
} from '@hyperlane-xyz/utils';
@@ -72,57 +71,55 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader {
}
async deriveIsmConfig(address: Address): Promise {
- return retryAsync(async () => {
- let moduleType: ModuleType | undefined = undefined;
- let derivedIsmConfig: DerivedIsmConfig;
- try {
- const ism = IInterchainSecurityModule__factory.connect(
- address,
- this.provider,
- );
- this.logger.debug('Deriving IsmConfig:', { address });
-
- // Temporarily turn off SmartProvider logging
- // Provider errors are expected because deriving will call methods that may not exist in the Bytecode
- this.setSmartProviderLogLevel('silent');
- moduleType = await ism.moduleType();
-
- switch (moduleType) {
- case ModuleType.UNUSED:
- throw new Error('UNUSED does not have a corresponding IsmType');
- case ModuleType.ROUTING:
- // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig
- derivedIsmConfig = await this.deriveRoutingConfig(address);
- break;
- case ModuleType.AGGREGATION:
- derivedIsmConfig = await this.deriveAggregationConfig(address);
- break;
- case ModuleType.LEGACY_MULTISIG:
- throw new Error('LEGACY_MULTISIG is deprecated and not supported');
- case ModuleType.MERKLE_ROOT_MULTISIG:
- case ModuleType.MESSAGE_ID_MULTISIG:
- derivedIsmConfig = await this.deriveMultisigConfig(address);
- break;
- case ModuleType.NULL:
- derivedIsmConfig = await this.deriveNullConfig(address);
- break;
- case ModuleType.CCIP_READ:
- throw new Error('CCIP_READ does not have a corresponding IsmType');
- case ModuleType.ARB_L2_TO_L1:
- return this.deriveArbL2ToL1Config(address);
- default:
- throw new Error(`Unknown ISM ModuleType: ${moduleType}`);
- }
- } catch (e: any) {
- const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`;
- this.logger.debug(errorMessage);
- throw new Error(errorMessage);
- } finally {
- this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger
+ let moduleType: ModuleType | undefined = undefined;
+ let derivedIsmConfig: DerivedIsmConfig;
+ try {
+ const ism = IInterchainSecurityModule__factory.connect(
+ address,
+ this.provider,
+ );
+ this.logger.debug('Deriving IsmConfig:', { address });
+
+ // Temporarily turn off SmartProvider logging
+ // Provider errors are expected because deriving will call methods that may not exist in the Bytecode
+ this.setSmartProviderLogLevel('silent');
+ moduleType = await ism.moduleType();
+
+ switch (moduleType) {
+ case ModuleType.UNUSED:
+ throw new Error('UNUSED does not have a corresponding IsmType');
+ case ModuleType.ROUTING:
+ // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig
+ derivedIsmConfig = await this.deriveRoutingConfig(address);
+ break;
+ case ModuleType.AGGREGATION:
+ derivedIsmConfig = await this.deriveAggregationConfig(address);
+ break;
+ case ModuleType.LEGACY_MULTISIG:
+ throw new Error('LEGACY_MULTISIG is deprecated and not supported');
+ case ModuleType.MERKLE_ROOT_MULTISIG:
+ case ModuleType.MESSAGE_ID_MULTISIG:
+ derivedIsmConfig = await this.deriveMultisigConfig(address);
+ break;
+ case ModuleType.NULL:
+ derivedIsmConfig = await this.deriveNullConfig(address);
+ break;
+ case ModuleType.CCIP_READ:
+ throw new Error('CCIP_READ does not have a corresponding IsmType');
+ case ModuleType.ARB_L2_TO_L1:
+ return this.deriveArbL2ToL1Config(address);
+ default:
+ throw new Error(`Unknown ISM ModuleType: ${moduleType}`);
}
+ } catch (e: any) {
+ const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`;
+ this.logger.debug(errorMessage);
+ throw new Error(errorMessage);
+ } finally {
+ this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger
+ }
- return derivedIsmConfig;
- });
+ return derivedIsmConfig;
}
async deriveRoutingConfig(
From c3e9268f1e2a4f69bd430e85a889a128957ca9fe Mon Sep 17 00:00:00 2001
From: Alexander Pastushenka
Date: Wed, 23 Oct 2024 15:09:56 +0400
Subject: [PATCH 02/61] feat: Add block tag support in `reorgPeriod` parameter
(#4629)
### Description
Allows setting an arbitrary string in `reorgPeriod`, which is used as a
block tag to get the finalized block. Currently, only the Ethereum
connector supports this feature with the following tags:
- finalized
- safe
- pending
- latest
- earliest
This is currently useful for EVM-compatible chains that don't have a
fixed reorganization period, but instead rely on the block tag
`Finalized` to indicate finality. For such chains, you should set
`reorgPeriod` to `finalized` instead of a number of blocks.
### Drive-by changes
### Related issues
### Backward compatibility
Yes
### Testing
---------
Co-authored-by: Daniel Savu <23065004+daniel-savu@users.noreply.github.com>
---
.changeset/strange-beers-buy.md | 7 ++
rust/main/agents/validator/src/settings.rs | 12 +-
rust/main/agents/validator/src/submit.rs | 26 ++--
rust/main/agents/validator/src/validator.rs | 17 ++-
.../hyperlane-cosmos/src/mailbox/contract.rs | 9 +-
.../hyperlane-cosmos/src/merkle_tree_hook.rs | 22 ++--
.../main/chains/hyperlane-cosmos/src/utils.rs | 25 ++--
.../chains/hyperlane-ethereum/src/config.rs | 34 +++++-
.../src/contracts/interchain_gas.rs | 28 ++---
.../src/contracts/mailbox.rs | 37 +++---
.../src/contracts/merkle_tree_hook.rs | 51 ++++----
.../hyperlane-ethereum/src/contracts/mod.rs | 2 +
.../hyperlane-ethereum/src/contracts/utils.rs | 35 +++++-
rust/main/chains/hyperlane-ethereum/src/tx.rs | 24 ++--
.../main/chains/hyperlane-fuel/src/mailbox.rs | 9 +-
.../chains/hyperlane-sealevel/src/mailbox.rs | 10 +-
.../src/merkle_tree_hook.rs | 18 +--
.../hyperlane-base/src/settings/chains.rs | 42 ++++---
.../src/settings/checkpoint_syncer.rs | 8 +-
.../hyperlane-base/src/settings/parser/mod.rs | 6 +-
rust/main/hyperlane-core/src/chain.rs | 114 +++++++++++++++++-
rust/main/hyperlane-core/src/error.rs | 9 +-
.../main/hyperlane-core/src/traits/mailbox.rs | 7 +-
.../src/traits/merkle_tree_hook.rs | 14 +--
rust/main/hyperlane-core/src/types/reorg.rs | 6 +-
rust/main/hyperlane-test/src/mocks/mailbox.rs | 12 +-
typescript/cli/src/config/chain.ts | 13 +-
typescript/infra/config/registry.ts | 2 +-
.../infra/src/config/agent/validator.ts | 4 +-
.../sdk/src/metadata/chainMetadata.test.ts | 10 ++
.../sdk/src/metadata/chainMetadataTypes.ts | 11 +-
31 files changed, 421 insertions(+), 203 deletions(-)
create mode 100644 .changeset/strange-beers-buy.md
diff --git a/.changeset/strange-beers-buy.md b/.changeset/strange-beers-buy.md
new file mode 100644
index 0000000000..3ad5bc57ec
--- /dev/null
+++ b/.changeset/strange-beers-buy.md
@@ -0,0 +1,7 @@
+---
+'@hyperlane-xyz/infra': minor
+'@hyperlane-xyz/cli': minor
+'@hyperlane-xyz/sdk': minor
+---
+
+Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block.
diff --git a/rust/main/agents/validator/src/settings.rs b/rust/main/agents/validator/src/settings.rs
index 02dc87cb13..d464be5a92 100644
--- a/rust/main/agents/validator/src/settings.rs
+++ b/rust/main/agents/validator/src/settings.rs
@@ -15,7 +15,9 @@ use hyperlane_base::{
CheckpointSyncerConf, Settings, SignerConf,
},
};
-use hyperlane_core::{cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol};
+use hyperlane_core::{
+ cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol, ReorgPeriod,
+};
use serde::Deserialize;
use serde_json::Value;
@@ -36,8 +38,8 @@ pub struct ValidatorSettings {
pub validator: SignerConf,
/// The checkpoint syncer configuration
pub checkpoint_syncer: CheckpointSyncerConf,
- /// The reorg_period in blocks
- pub reorg_period: u64,
+ /// The reorg configuration
+ pub reorg_period: ReorgPeriod,
/// How frequently to check for new checkpoints
pub interval: Duration,
}
@@ -122,8 +124,8 @@ impl FromRawConf for ValidatorSettings {
.get_key(origin_chain_name)
.get_opt_key("blocks")
.get_opt_key("reorgPeriod")
- .parse_u64()
- .unwrap_or(1);
+ .parse_value("Invalid reorgPeriod")
+ .unwrap_or(ReorgPeriod::from_blocks(1));
cfg_unwrap_all!(cwp, err: [base, origin_chain, validator, checkpoint_syncer]);
diff --git a/rust/main/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs
index 94d5964673..954b8d0d95 100644
--- a/rust/main/agents/validator/src/submit.rs
+++ b/rust/main/agents/validator/src/submit.rs
@@ -1,4 +1,3 @@
-use std::num::NonZeroU64;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::vec;
@@ -14,13 +13,13 @@ use hyperlane_core::{
accumulator::incremental::IncrementalMerkle, Checkpoint, CheckpointWithMessageId,
HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSignerExt,
};
-use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent};
+use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent, ReorgPeriod};
use hyperlane_ethereum::SingletonSignerHandle;
#[derive(Clone)]
pub(crate) struct ValidatorSubmitter {
interval: Duration,
- reorg_period: Option,
+ reorg_period: ReorgPeriod,
signer: SingletonSignerHandle,
merkle_tree_hook: Arc,
checkpoint_syncer: Arc,
@@ -31,7 +30,7 @@ pub(crate) struct ValidatorSubmitter {
impl ValidatorSubmitter {
pub(crate) fn new(
interval: Duration,
- reorg_period: u64,
+ reorg_period: ReorgPeriod,
merkle_tree_hook: Arc,
signer: SingletonSignerHandle,
checkpoint_syncer: Arc,
@@ -39,7 +38,7 @@ impl ValidatorSubmitter {
metrics: ValidatorSubmitterMetrics,
) -> Self {
Self {
- reorg_period: NonZeroU64::new(reorg_period),
+ reorg_period,
interval,
merkle_tree_hook,
signer,
@@ -94,7 +93,8 @@ impl ValidatorSubmitter {
// Lag by reorg period because this is our correctness checkpoint.
let latest_checkpoint = call_and_retry_indefinitely(|| {
let merkle_tree_hook = self.merkle_tree_hook.clone();
- Box::pin(async move { merkle_tree_hook.latest_checkpoint(self.reorg_period).await })
+ let reorg_period = self.reorg_period.clone();
+ Box::pin(async move { merkle_tree_hook.latest_checkpoint(&reorg_period).await })
})
.await;
@@ -211,7 +211,7 @@ impl ValidatorSubmitter {
correctness_checkpoint.root,
checkpoint.index,
chrono::Utc::now().timestamp() as u64,
- self.reorg_period.map(|x| x.get()).unwrap_or(0),
+ self.reorg_period.clone(),
);
error!(
?checkpoint,
@@ -486,9 +486,9 @@ mod test {
#[async_trait]
impl MerkleTreeHook for MerkleTreeHook {
- async fn tree(&self, lag: Option) -> ChainResult;
- async fn count(&self, lag: Option) -> ChainResult;
- async fn latest_checkpoint(&self, lag: Option) -> ChainResult;
+ async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult;
+ async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult;
+ async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult;
}
}
@@ -532,7 +532,7 @@ mod test {
expected_local_merkle_tree: &IncrementalMerkle,
mock_onchain_merkle_tree: &IncrementalMerkle,
unix_timestamp: u64,
- expected_reorg_period: u64,
+ expected_reorg_period: ReorgPeriod,
) {
assert_eq!(
reorg_event.canonical_merkle_root,
@@ -617,7 +617,7 @@ mod test {
&expected_local_merkle_tree,
&mock_onchain_merkle_tree_clone,
unix_timestamp,
- expected_reorg_period,
+ ReorgPeriod::from_blocks(expected_reorg_period),
);
Ok(())
});
@@ -625,7 +625,7 @@ mod test {
// instantiate the validator submitter
let validator_submitter = ValidatorSubmitter::new(
Duration::from_secs(1),
- expected_reorg_period,
+ ReorgPeriod::from_blocks(expected_reorg_period),
Arc::new(mock_merkle_tree_hook),
dummy_singleton_handle(),
Arc::new(mock_checkpoint_syncer),
diff --git a/rust/main/agents/validator/src/validator.rs b/rust/main/agents/validator/src/validator.rs
index 31fe809b48..2d09bd93ff 100644
--- a/rust/main/agents/validator/src/validator.rs
+++ b/rust/main/agents/validator/src/validator.rs
@@ -1,4 +1,4 @@
-use std::{num::NonZeroU64, sync::Arc, time::Duration};
+use std::{sync::Arc, time::Duration};
use crate::server as validator_server;
use async_trait::async_trait;
@@ -19,8 +19,8 @@ use hyperlane_base::{
use hyperlane_core::{
Announcement, ChainResult, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSigner,
- HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, TxOutcome, ValidatorAnnounce,
- H256, U256,
+ HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, TxOutcome,
+ ValidatorAnnounce, H256, U256,
};
use hyperlane_ethereum::{SingletonSigner, SingletonSignerHandle};
@@ -44,7 +44,7 @@ pub struct Validator {
signer: SingletonSignerHandle,
// temporary holder until `run` is called
signer_instance: Option>,
- reorg_period: u64,
+ reorg_period: ReorgPeriod,
interval: Duration,
checkpoint_syncer: Arc,
core_metrics: Arc,
@@ -184,12 +184,10 @@ impl BaseAgent for Validator {
// announce the validator after spawning the signer task
self.announce().await.expect("Failed to announce validator");
- let reorg_period = NonZeroU64::new(self.reorg_period);
-
// Ensure that the merkle tree hook has count > 0 before we begin indexing
// messages or submitting checkpoints.
loop {
- match self.merkle_tree_hook.count(reorg_period).await {
+ match self.merkle_tree_hook.count(&self.reorg_period).await {
Ok(0) => {
info!("Waiting for first message in merkle tree hook");
sleep(self.interval).await;
@@ -241,7 +239,7 @@ impl Validator {
async fn run_checkpoint_submitters(&self) -> Vec>> {
let submitter = ValidatorSubmitter::new(
self.interval,
- self.reorg_period,
+ self.reorg_period.clone(),
self.merkle_tree_hook.clone(),
self.signer.clone(),
self.checkpoint_syncer.clone(),
@@ -249,10 +247,9 @@ impl Validator {
ValidatorSubmitterMetrics::new(&self.core.metrics, &self.origin_chain),
);
- let reorg_period = NonZeroU64::new(self.reorg_period);
let tip_tree = self
.merkle_tree_hook
- .tree(reorg_period)
+ .tree(&self.reorg_period)
.await
.expect("failed to get merkle tree");
// This function is only called after we have already checked that the
diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs
index 9c793c93e4..5a998aac5a 100644
--- a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs
+++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs
@@ -8,7 +8,7 @@ use tracing::instrument;
use hyperlane_core::{
utils::bytes_to_hex, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract,
HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Mailbox, RawHyperlaneMessage,
- TxCostEstimate, TxOutcome, H256, U256,
+ ReorgPeriod, TxCostEstimate, TxOutcome, H256, U256,
};
use crate::grpc::WasmProvider;
@@ -17,7 +17,7 @@ use crate::payloads::mailbox::{
GeneralMailboxQuery, ProcessMessageRequest, ProcessMessageRequestInner,
};
use crate::types::tx_response_to_outcome;
-use crate::utils::get_block_height_for_lag;
+use crate::utils::get_block_height_for_reorg_period;
use crate::{payloads, ConnectionConf, CosmosAddress, CosmosProvider, Signer};
#[derive(Clone, Debug)]
@@ -82,8 +82,9 @@ impl HyperlaneChain for CosmosMailbox {
impl Mailbox for CosmosMailbox {
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
- async fn count(&self, lag: Option) -> ChainResult {
- let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
+ async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult {
+ let block_height =
+ get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
self.nonce_at_block(block_height).await
}
diff --git a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs
index c9e48c59f2..b9acdd3571 100644
--- a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs
+++ b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs
@@ -10,15 +10,15 @@ use hyperlane_core::accumulator::incremental::IncrementalMerkle;
use hyperlane_core::{
ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain,
HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta,
- MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512,
+ MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, SequenceAwareIndexer, H256, H512,
};
use crate::grpc::WasmProvider;
use crate::payloads::{general, merkle_tree_hook};
use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider};
use crate::utils::{
- execute_and_parse_log_futures, get_block_height_for_lag, parse_logs_in_range, parse_logs_in_tx,
- CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64,
+ execute_and_parse_log_futures, get_block_height_for_reorg_period, parse_logs_in_range,
+ parse_logs_in_tx, CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64,
};
use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError, Signer};
@@ -76,12 +76,13 @@ impl MerkleTreeHook for CosmosMerkleTreeHook {
/// Return the incremental merkle tree in storage
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
- async fn tree(&self, lag: Option) -> ChainResult {
+ async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult {
let payload = merkle_tree_hook::MerkleTreeRequest {
tree: general::EmptyStruct {},
};
- let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
+ let block_height =
+ get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
let data = self
.provider
@@ -110,23 +111,26 @@ impl MerkleTreeHook for CosmosMerkleTreeHook {
}
/// Gets the current leaf count of the merkle tree
- async fn count(&self, lag: Option) -> ChainResult {
+ async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult {
let payload = merkle_tree_hook::MerkleTreeCountRequest {
count: general::EmptyStruct {},
};
- let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
+ let block_height =
+ get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
self.count_at_block(block_height).await
}
+
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
- async fn latest_checkpoint(&self, lag: Option) -> ChainResult {
+ async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult {
let payload = merkle_tree_hook::CheckPointRequest {
check_point: general::EmptyStruct {},
};
- let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
+ let block_height =
+ get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
let data = self
.provider
diff --git a/rust/main/chains/hyperlane-cosmos/src/utils.rs b/rust/main/chains/hyperlane-cosmos/src/utils.rs
index 74cb75a279..f792090e67 100644
--- a/rust/main/chains/hyperlane-cosmos/src/utils.rs
+++ b/rust/main/chains/hyperlane-cosmos/src/utils.rs
@@ -11,7 +11,7 @@ use tendermint::Hash;
use tokio::task::JoinHandle;
use tracing::warn;
-use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, H256};
+use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, ReorgPeriod, H256};
use crate::grpc::{WasmGrpcProvider, WasmProvider};
use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider};
@@ -24,20 +24,25 @@ pub(crate) const CONTRACT_ADDRESS_ATTRIBUTE_KEY: &str = "_contract_address";
pub(crate) static CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64: Lazy =
Lazy::new(|| BASE64.encode(CONTRACT_ADDRESS_ATTRIBUTE_KEY));
-/// Given a lag, returns the block height at the moment.
-/// If the lag is None, a block height of None is given, indicating that the
-/// tip directly can be used.
-pub(crate) async fn get_block_height_for_lag(
+/// Given a `reorg_period`, returns the block height at the moment.
+/// If the `reorg_period` is None, a block height of None is given,
+/// indicating that the tip directly can be used.
+pub(crate) async fn get_block_height_for_reorg_period(
provider: &WasmGrpcProvider,
- lag: Option,
+ reorg_period: &ReorgPeriod,
) -> ChainResult