Skip to content

Commit

Permalink
feat: Retrieve gas payments by sequence for scraping Sealevel (#4942)
Browse files Browse the repository at this point in the history
### Description

- Retrieve gas payment by origin, interchain_gas_paymaster and sequence
- Add Sealevel to Scraper in E2E Ethereum and Sealevel tests

### Related issues

- Contributes into
#4271

### Backward compatibility

Yes (after backfill of origin, destination, interchain_gas_paymaster)

### Testing

E2E Ethereum and Sealevel tests (including scraping Sealevel)

---------

Co-authored-by: Danil Nemirovsky <[email protected]>
  • Loading branch information
ameten and ameten authored Dec 6, 2024
1 parent a96448f commit 4b280cd
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,22 @@ const DOMAINS: &[RawDomain] = &[
is_test_net: true,
is_deprecated: false,
},
RawDomain {
name: "sealeveltest1",
token: "SOL",
domain: 13375,
chain_id: 13375,
is_test_net: true,
is_deprecated: false,
},
RawDomain {
name: "sealeveltest2",
token: "SOL",
domain: 13376,
chain_id: 13376,
is_test_net: true,
is_deprecated: false,
},
];

#[derive(DeriveMigrationName)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::borrow::BorrowMut as _;

use sea_orm::ConnectionTrait;
use sea_orm_migration::prelude::*;

Expand Down Expand Up @@ -41,11 +39,15 @@ impl MigrationTrait for Migration {
.big_unsigned()
.not_null(),
)
.col(ColumnDef::new(GasPayment::Origin).unsigned())
.col(ColumnDef::new(GasPayment::Destination).unsigned())
.col(ColumnDef::new(GasPayment::Origin).unsigned().not_null())
.col(
ColumnDef::new(GasPayment::Destination)
.unsigned()
.not_null(),
)
.col(
ColumnDef::new_with_type(GasPayment::InterchainGasPaymaster, Address)
.borrow_mut(),
.not_null(),
)
.col(ColumnDef::new(GasPayment::Sequence).big_integer())
.foreign_key(
Expand All @@ -63,11 +65,6 @@ impl MigrationTrait for Migration {
.from_col(GasPayment::Origin)
.to(Domain::Table, Domain::Id),
)
.foreign_key(
ForeignKey::create()
.from_col(GasPayment::Destination)
.to(Domain::Table, Domain::Id),
)
.index(
Index::create()
// don't need domain because TxId includes it
Expand All @@ -90,6 +87,19 @@ impl MigrationTrait for Migration {
)
.await?;

manager
.create_index(
Index::create()
.table(GasPayment::Table)
.name("gas_payment_origin_interchain_gas_paymaster_sequence_idx")
.col(GasPayment::Origin)
.col(GasPayment::InterchainGasPaymaster)
.col(GasPayment::Sequence)
.index_type(IndexType::BTree)
.to_owned(),
)
.await?;

manager
.get_connection()
.execute_unprepared(&format!(
Expand Down
6 changes: 3 additions & 3 deletions rust/main/agents/scraper/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl Scraper {
let sync = self
.as_ref()
.settings
.watermark_contract_sync::<Delivery, _>(
.contract_sync::<Delivery, _>(
&domain,
&metrics.clone(),
&contract_sync_metrics.clone(),
Expand Down Expand Up @@ -264,11 +264,11 @@ impl Scraper {
let sync = self
.as_ref()
.settings
.watermark_contract_sync::<InterchainGasPayment, _>(
.contract_sync::<InterchainGasPayment, _>(
&domain,
&metrics.clone(),
&contract_sync_metrics.clone(),
Arc::new(store.clone()),
Arc::new(store.clone()) as _,
true,
)
.await
Expand Down
28 changes: 28 additions & 0 deletions rust/main/agents/scraper/src/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,31 @@ pub fn u256_to_decimal(v: U256) -> BigDecimal {
v.to_little_endian(&mut buf);
BigDecimal::from(BigInt::from_bytes_le(Sign::Plus, &buf as &[u8]))
}

pub fn decimal_to_u256(v: BigDecimal) -> U256 {
let (i, _) = v.into_bigint_and_exponent();
let (_, b) = i.to_bytes_le();
U256::from_little_endian(&b)
}

#[cfg(test)]
mod tests {
use hyperlane_core::U256;

use crate::conversions::{decimal_to_u256, u256_to_decimal};

#[test]
fn test() {
// given
let u = U256::from_dec_str(
"76418673493495739447102571088210420170780567439841463646292940247514478199569",
)
.unwrap();

// when
let r = decimal_to_u256(u256_to_decimal(u));

// then
assert_eq!(u, r);
}
}
19 changes: 6 additions & 13 deletions rust/main/agents/scraper/src/db/generated/gas_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ pub struct Model {
pub gas_amount: BigDecimal,
pub tx_id: i64,
pub log_index: i64,
pub origin: Option<i32>,
pub destination: Option<i32>,
pub interchain_gas_paymaster: Option<Vec<u8>>,
pub origin: i32,
pub destination: i32,
pub interchain_gas_paymaster: Vec<u8>,
pub sequence: Option<i64>,
}

Expand Down Expand Up @@ -57,7 +57,6 @@ impl PrimaryKeyTrait for PrimaryKey {

#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
Destination,
Domain,
Origin,
Transaction,
Expand All @@ -75,12 +74,10 @@ impl ColumnTrait for Column {
Self::GasAmount => ColumnType::Decimal(Some((78u32, 0u32))).def(),
Self::TxId => ColumnType::BigInteger.def(),
Self::LogIndex => ColumnType::BigInteger.def(),
Self::Origin => ColumnType::Integer.def().null(),
Self::Destination => ColumnType::Integer.def().null(),
Self::Origin => ColumnType::Integer.def(),
Self::Destination => ColumnType::Integer.def(),
Self::InterchainGasPaymaster => {
ColumnType::Binary(sea_orm::sea_query::BlobSize::Blob(None))
.def()
.null()
ColumnType::Binary(sea_orm::sea_query::BlobSize::Blob(None)).def()
}
Self::Sequence => ColumnType::BigInteger.def().null(),
}
Expand All @@ -90,10 +87,6 @@ impl ColumnTrait for Column {
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Destination => Entity::belongs_to(super::domain::Entity)
.from(Column::Destination)
.to(super::domain::Column::Id)
.into(),
Self::Domain => Entity::belongs_to(super::domain::Entity)
.from(Column::Domain)
.to(super::domain::Column::Id)
Expand Down
63 changes: 59 additions & 4 deletions rust/main/agents/scraper/src/db/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tracing::{debug, instrument};
use hyperlane_core::{address_to_bytes, h256_to_bytes, InterchainGasPayment, LogMeta, H256};
use migration::OnConflict;

use crate::conversions::u256_to_decimal;
use crate::conversions::{decimal_to_u256, u256_to_decimal};
use crate::date_time;
use crate::db::ScraperDb;

Expand All @@ -22,6 +22,61 @@ pub struct StorablePayment<'a> {
}

impl ScraperDb {
/// Get the payment associated with a sequence.
#[instrument(skip(self))]
pub async fn retrieve_payment_by_sequence(
&self,
origin: u32,
interchain_gas_paymaster: &H256,
sequence: u32,
) -> Result<Option<InterchainGasPayment>> {
if let Some(payment) = gas_payment::Entity::find()
.filter(gas_payment::Column::Origin.eq(origin))
.filter(
gas_payment::Column::InterchainGasPaymaster
.eq(address_to_bytes(interchain_gas_paymaster)),
)
.filter(gas_payment::Column::Sequence.eq(sequence))
.one(&self.0)
.await?
{
let payment = InterchainGasPayment {
message_id: H256::from_slice(&payment.msg_id),
destination: payment.destination as u32,
payment: decimal_to_u256(payment.payment),
gas_amount: decimal_to_u256(payment.gas_amount),
};
Ok(Some(payment))
} else {
Ok(None)
}
}

/// Get the transaction id of the gas payment associated with a sequence.
#[instrument(skip(self))]
pub async fn retrieve_payment_tx_id(
&self,
origin: u32,
interchain_gas_paymaster: &H256,
sequence: u32,
) -> Result<Option<i64>> {
if let Some(payment) = gas_payment::Entity::find()
.filter(gas_payment::Column::Origin.eq(origin))
.filter(
gas_payment::Column::InterchainGasPaymaster
.eq(address_to_bytes(interchain_gas_paymaster)),
)
.filter(gas_payment::Column::Sequence.eq(sequence))
.one(&self.0)
.await?
{
let txn_id = payment.tx_id;
Ok(Some(txn_id))
} else {
Ok(None)
}
}

#[instrument(skip_all)]
pub async fn store_payments(
&self,
Expand All @@ -44,9 +99,9 @@ impl ScraperDb {
gas_amount: Set(u256_to_decimal(storable.payment.gas_amount)),
tx_id: Unchanged(storable.txn_id),
log_index: Unchanged(storable.meta.log_index.as_u64() as i64),
origin: Set(Some(domain as i32)),
destination: Set(Some(storable.payment.destination as i32)),
interchain_gas_paymaster: Set(Some(interchain_gas_paymaster.clone())),
origin: Set(domain as i32),
destination: Set(storable.payment.destination as i32),
interchain_gas_paymaster: Set(interchain_gas_paymaster.clone()),
sequence: Set(storable.sequence),
})
.collect_vec();
Expand Down
36 changes: 35 additions & 1 deletion rust/main/agents/scraper/src/store/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use eyre::Result;
use itertools::Itertools;
use tracing::debug;

use hyperlane_core::{HyperlaneLogStore, Indexed, InterchainGasPayment, LogMeta, H512};
use hyperlane_core::{
unwrap_or_none_result, HyperlaneLogStore, HyperlaneSequenceAwareIndexerStoreReader, Indexed,
InterchainGasPayment, LogMeta, H512,
};

use crate::db::StorablePayment;
use crate::store::storage::HyperlaneDbStore;
Expand Down Expand Up @@ -65,3 +68,34 @@ impl HyperlaneLogStore<InterchainGasPayment> for HyperlaneDbStore {
Ok(stored as u32)
}
}

#[async_trait]
impl HyperlaneSequenceAwareIndexerStoreReader<InterchainGasPayment> for HyperlaneDbStore {
/// Gets a gas payment by sequence
async fn retrieve_by_sequence(&self, sequence: u32) -> Result<Option<InterchainGasPayment>> {
let message = self
.db
.retrieve_payment_by_sequence(
self.domain.id(),
&self.interchain_gas_paymaster_address,
sequence,
)
.await?;
Ok(message)
}

/// Gets the block number at which the log occurred.
async fn retrieve_log_block_number_by_sequence(&self, sequence: u32) -> Result<Option<u64>> {
let tx_id = unwrap_or_none_result!(
self.db
.retrieve_payment_tx_id(
self.domain.id(),
&self.interchain_gas_paymaster_address,
sequence,
)
.await?
);
let block_id = unwrap_or_none_result!(self.db.retrieve_block_id(tx_id).await?);
Ok(self.db.retrieve_block_number(block_id).await?)
}
}
4 changes: 2 additions & 2 deletions rust/main/config/test_sealevel_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"rpcUrls": [
{
"http": "http://localhost:8899"
"http": "http://127.0.0.1:8899"
}
],
"index": {
Expand All @@ -38,7 +38,7 @@
},
"rpcUrls": [
{
"http": "http://localhost:8899"
"http": "http://127.0.0.1:8899"
}
],
"index": {
Expand Down
Loading

0 comments on commit 4b280cd

Please sign in to comment.