From a067d179e734ce7629482cf12d93bf6266feb6d2 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 26 Oct 2023 12:34:32 -0400 Subject: [PATCH 1/5] Ensure validator writes latest index to checkpoint syncer --- rust/agents/validator/src/submit.rs | 4 ++++ rust/hyperlane-base/src/traits/checkpoint_syncer.rs | 2 ++ rust/hyperlane-base/src/types/local_storage.rs | 8 ++++++++ rust/hyperlane-base/src/types/s3_storage.rs | 11 +++++++++-- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/rust/agents/validator/src/submit.rs b/rust/agents/validator/src/submit.rs index 284dd4205c..1197a42134 100644 --- a/rust/agents/validator/src/submit.rs +++ b/rust/agents/validator/src/submit.rs @@ -136,6 +136,10 @@ impl ValidatorSubmitter { self.submit_checkpoints_until_correctness_checkpoint(&mut tree, &latest_checkpoint) .await?; + self.checkpoint_syncer + .write_latest_index(latest_checkpoint.index) + .await?; + self.metrics .latest_checkpoint_processed .set(latest_checkpoint.index as i64); diff --git a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs index e017b3f5aa..d1d8ed7c70 100644 --- a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs +++ b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs @@ -10,6 +10,8 @@ use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; pub trait CheckpointSyncer: Debug + Send + Sync { /// Read the highest index of this Syncer async fn latest_index(&self) -> Result>; + /// Writes the highest index of this Syncer + async fn write_latest_index(&self, index: u32) -> Result<()>; /// Attempt to fetch the signed (checkpoint, messageId) tuple at this index async fn fetch_checkpoint(&self, index: u32) -> Result>; /// Write the signed (checkpoint, messageId) tuple to this syncer diff --git a/rust/hyperlane-base/src/types/local_storage.rs b/rust/hyperlane-base/src/types/local_storage.rs index 76c02a38cd..38397c1bf6 100644 --- a/rust/hyperlane-base/src/types/local_storage.rs +++ b/rust/hyperlane-base/src/types/local_storage.rs @@ -62,6 +62,14 @@ impl CheckpointSyncer for LocalStorage { } } + async fn write_latest_index(&self, index: u32) -> Result<()> { + let path = self.latest_index_file_path(); + tokio::fs::write(&path, index.to_string()) + .await + .with_context(|| format!("Writing index to {path:?}"))?; + Ok(()) + } + async fn fetch_checkpoint(&self, index: u32) -> Result> { let Ok(data) = tokio::fs::read(self.checkpoint_file_path(index)).await else { return Ok(None); diff --git a/rust/hyperlane-base/src/types/s3_storage.rs b/rust/hyperlane-base/src/types/s3_storage.rs index cfce7ff3e5..2d09a18a86 100644 --- a/rust/hyperlane-base/src/types/s3_storage.rs +++ b/rust/hyperlane-base/src/types/s3_storage.rs @@ -131,7 +131,7 @@ impl S3Storage { format!("checkpoint_{index}_with_id.json") } - fn index_key() -> String { + fn latest_index_key() -> String { "checkpoint_latest_index.json".to_owned() } @@ -144,7 +144,7 @@ impl S3Storage { impl CheckpointSyncer for S3Storage { async fn latest_index(&self) -> Result> { let ret = self - .anonymously_read_from_bucket(S3Storage::index_key()) + .anonymously_read_from_bucket(S3Storage::latest_index_key()) .await? .map(|data| serde_json::from_slice(&data)) .transpose() @@ -159,6 +159,13 @@ impl CheckpointSyncer for S3Storage { ret } + async fn write_latest_index(&self, index: u32) -> Result<()> { + let serialized_index = serde_json::to_string(&index)?; + self.write_to_bucket(S3Storage::latest_index_key(), &serialized_index) + .await?; + Ok(()) + } + async fn fetch_checkpoint(&self, index: u32) -> Result> { self.anonymously_read_from_bucket(S3Storage::checkpoint_key(index)) .await? From b141aece73e6ec910c6d2d3294edad008d6db3df Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 26 Oct 2023 12:35:07 -0400 Subject: [PATCH 2/5] Make e2e tests 2/2 aggregation of multisig variants --- typescript/infra/config/environments/test/aggregationIsm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/test/aggregationIsm.ts b/typescript/infra/config/environments/test/aggregationIsm.ts index 0e0d140afc..55a84a255d 100644 --- a/typescript/infra/config/environments/test/aggregationIsm.ts +++ b/typescript/infra/config/environments/test/aggregationIsm.ts @@ -9,6 +9,6 @@ export const aggregationIsm = (validatorKey: string): AggregationIsmConfig => { merkleRootMultisig(validatorKey), messageIdMultisig(validatorKey), ], - threshold: 1, + threshold: 2, }; }; From 201ee02761d37b1f0e9c952f84da52256509b96e Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 2 Nov 2023 13:37:33 -0400 Subject: [PATCH 3/5] Revert "Make e2e tests 2/2 aggregation of multisig variants" This reverts commit b141aece73e6ec910c6d2d3294edad008d6db3df. --- typescript/infra/config/environments/test/aggregationIsm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/test/aggregationIsm.ts b/typescript/infra/config/environments/test/aggregationIsm.ts index 55a84a255d..0e0d140afc 100644 --- a/typescript/infra/config/environments/test/aggregationIsm.ts +++ b/typescript/infra/config/environments/test/aggregationIsm.ts @@ -9,6 +9,6 @@ export const aggregationIsm = (validatorKey: string): AggregationIsmConfig => { merkleRootMultisig(validatorKey), messageIdMultisig(validatorKey), ], - threshold: 2, + threshold: 1, }; }; From 6bc331a1fbd4d1701c6923c956162682141fcb5e Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 2 Nov 2023 13:56:36 -0400 Subject: [PATCH 4/5] Add update_latest_index to checkpoint_syncer --- rust/agents/validator/src/submit.rs | 4 ++-- rust/hyperlane-base/src/traits/checkpoint_syncer.rs | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/rust/agents/validator/src/submit.rs b/rust/agents/validator/src/submit.rs index da8fb786f8..7741f7936f 100644 --- a/rust/agents/validator/src/submit.rs +++ b/rust/agents/validator/src/submit.rs @@ -137,7 +137,7 @@ impl ValidatorSubmitter { .await?; self.checkpoint_syncer - .write_latest_index(latest_checkpoint.index) + .update_latest_index(latest_checkpoint.index) .await?; self.metrics @@ -171,7 +171,7 @@ impl ValidatorSubmitter { // // tree.index() will panic if the tree is empty, so we use tree.count() instead // and convert the correctness_checkpoint.index to a count by adding 1. - while correctness_checkpoint.index + 1 > tree.count() as u32 { + while tree.count() as u32 <= correctness_checkpoint.index { if let Some(insertion) = self .message_db .retrieve_merkle_tree_insertion_by_leaf_index(&(tree.count() as u32))? diff --git a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs index d1d8ed7c70..9f7112bd9a 100644 --- a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs +++ b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs @@ -12,6 +12,14 @@ pub trait CheckpointSyncer: Debug + Send + Sync { async fn latest_index(&self) -> Result>; /// Writes the highest index of this Syncer async fn write_latest_index(&self, index: u32) -> Result<()>; + /// Update the highest index of this Syncer if the new index is higher + async fn update_latest_index(&self, index: u32) -> Result<()> { + let curr = self.latest_index().await?.unwrap_or(0); + if index > curr { + self.write_latest_index(index).await?; + } + Ok(()) + } /// Attempt to fetch the signed (checkpoint, messageId) tuple at this index async fn fetch_checkpoint(&self, index: u32) -> Result>; /// Write the signed (checkpoint, messageId) tuple to this syncer From 13812ebe7b626840aa3150ad686139a31da50669 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 2 Nov 2023 14:36:03 -0400 Subject: [PATCH 5/5] Move update_latest_index into submit_checkpoints --- rust/agents/validator/src/submit.rs | 12 ++++++++---- rust/hyperlane-base/src/traits/checkpoint_syncer.rs | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/rust/agents/validator/src/submit.rs b/rust/agents/validator/src/submit.rs index 7741f7936f..683e38afc9 100644 --- a/rust/agents/validator/src/submit.rs +++ b/rust/agents/validator/src/submit.rs @@ -136,10 +136,6 @@ impl ValidatorSubmitter { self.submit_checkpoints_until_correctness_checkpoint(&mut tree, &latest_checkpoint) .await?; - self.checkpoint_syncer - .update_latest_index(latest_checkpoint.index) - .await?; - self.metrics .latest_checkpoint_processed .set(latest_checkpoint.index as i64); @@ -243,6 +239,8 @@ impl ValidatorSubmitter { &self, checkpoints: Vec, ) -> Result<()> { + let last_checkpoint = checkpoints.as_slice()[checkpoints.len() - 1]; + for queued_checkpoint in checkpoints { let existing = self .checkpoint_syncer @@ -265,9 +263,15 @@ impl ValidatorSubmitter { "Signed and submitted checkpoint" ); + // TODO: move these into S3 implementations // small sleep before signing next checkpoint to avoid rate limiting sleep(Duration::from_millis(100)).await; } + + self.checkpoint_syncer + .update_latest_index(last_checkpoint.index) + .await?; + Ok(()) } } diff --git a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs index 9f7112bd9a..abec982c7d 100644 --- a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs +++ b/rust/hyperlane-base/src/traits/checkpoint_syncer.rs @@ -12,7 +12,7 @@ pub trait CheckpointSyncer: Debug + Send + Sync { async fn latest_index(&self) -> Result>; /// Writes the highest index of this Syncer async fn write_latest_index(&self, index: u32) -> Result<()>; - /// Update the highest index of this Syncer if the new index is higher + /// Update the latest index of this syncer if necessary async fn update_latest_index(&self, index: u32) -> Result<()> { let curr = self.latest_index().await?.unwrap_or(0); if index > curr {