Skip to content

Commit

Permalink
fix: dedup eth logs (#3108)
Browse files Browse the repository at this point in the history
### Description

Deduplicates ethereum logs by collecting them into a HashSet before
returning a Vec. I couldn't find a way to deduplicate using an ethers
config, but since `fetch_logs` is only called once in hyperlane-base,
I'm doing the deduplication there "globally". I also noted in doc
comments that duplicates may be returned.

### Related issues

- Fixes #3070

### Backward compatibility

Yes

### Testing

Will rely on e2e passing but haven't added unit tests for this scenario
  • Loading branch information
daniel-savu authored Jan 2, 2024
1 parent 3f88aa6 commit cdbaf9e
Show file tree
Hide file tree
Showing 8 changed files with 12 additions and 6 deletions.
1 change: 1 addition & 0 deletions rust/chains/hyperlane-ethereum/src/interchain_gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl<M> Indexer<InterchainGasPayment> for EthereumInterchainGasPaymasterIndexer<
where
M: Middleware + 'static,
{
/// Note: This call may return duplicates depending on the provider used
#[instrument(err, skip(self))]
async fn fetch_logs(
&self,
Expand Down
2 changes: 2 additions & 0 deletions rust/chains/hyperlane-ethereum/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ where
self.get_finalized_block_number().await
}

/// Note: This call may return duplicates depending on the provider used
#[instrument(err, skip(self))]
async fn fetch_logs(
&self,
Expand Down Expand Up @@ -168,6 +169,7 @@ where
self.get_finalized_block_number().await
}

/// Note: This call may return duplicates depending on the provider used
#[instrument(err, skip(self))]
async fn fetch_logs(&self, range: RangeInclusive<u32>) -> ChainResult<Vec<(H256, LogMeta)>> {
Ok(self
Expand Down
1 change: 1 addition & 0 deletions rust/chains/hyperlane-ethereum/src/merkle_tree_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl<M> Indexer<MerkleTreeInsertion> for EthereumMerkleTreeHookIndexer<M>
where
M: Middleware + 'static,
{
/// Note: This call may return duplicates depending on the provider used
#[instrument(err, skip(self))]
async fn fetch_logs(
&self,
Expand Down
6 changes: 4 additions & 2 deletions rust/hyperlane-base/src/contract_sync/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt::Debug, marker::PhantomData, sync::Arc};
use std::{collections::HashSet, fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc};

use cursor::*;
use derive_new::new;
Expand Down Expand Up @@ -31,7 +31,7 @@ pub struct ContractSync<T, D: HyperlaneLogStore<T>, I: Indexer<T>> {

impl<T, D, I> ContractSync<T, D, I>
where
T: Debug + Send + Sync + Clone + 'static,
T: Debug + Send + Sync + Clone + Eq + Hash + 'static,
D: HyperlaneLogStore<T> + 'static,
I: Indexer<T> + Clone + 'static,
{
Expand Down Expand Up @@ -67,6 +67,8 @@ where
debug!(?range, "Looking for for events in index range");

let logs = self.indexer.fetch_logs(range.clone()).await?;
let deduped_logs = HashSet::<_>::from_iter(logs);
let logs = Vec::from_iter(deduped_logs);

info!(
?range,
Expand Down
2 changes: 1 addition & 1 deletion rust/hyperlane-core/src/types/log_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{H256, H512, U256};
/// A close clone of the Ethereum `LogMeta`, this is designed to be a more
/// generic metadata that we can use for other blockchains later. Some changes
/// may be required in the future.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, Hash)]
pub struct LogMeta {
/// Address from which this log originated
pub address: H256,
Expand Down
2 changes: 1 addition & 1 deletion rust/hyperlane-core/src/types/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::io::{Read, Write};
use crate::{Decode, Encode, HyperlaneProtocolError, Sequenced, H256};

/// Merkle Tree Hook insertion event
#[derive(Debug, Copy, Clone, new, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, new, Eq, PartialEq, Hash)]
pub struct MerkleTreeInsertion {
leaf_index: u32,
message_id: H256,
Expand Down
2 changes: 1 addition & 1 deletion rust/hyperlane-core/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl From<&HyperlaneMessage> for RawHyperlaneMessage {
}

/// A full Hyperlane message between chains
#[derive(Clone, Eq, PartialEq)]
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct HyperlaneMessage {
/// 1 Hyperlane version number
pub version: u8,
Expand Down
2 changes: 1 addition & 1 deletion rust/hyperlane-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub struct GasPaymentKey {
}

/// A payment of a message's gas costs.
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
pub struct InterchainGasPayment {
/// Id of the message
pub message_id: H256,
Expand Down

0 comments on commit cdbaf9e

Please sign in to comment.