Skip to content

Commit

Permalink
feat: Scraper report mailbox as recipient of transactions for Sealevel (
Browse files Browse the repository at this point in the history
#4813)

### Description

Scraper reports mailbox as recipient of transactions for Sealevel

### Related issues

- Contributes into
#4272

### Backward compatibility

Yes

### Testing

Manual test of Scraper
E2E tests for Ethereum and Sealevel

---------

Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com>
  • Loading branch information
ameten and ameten authored Nov 8, 2024
1 parent fa42482 commit 8e3085a
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 9 deletions.
1 change: 1 addition & 0 deletions rust/main/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ itertools = "*"
jobserver = "=0.1.26"
jsonrpc-core = "18.0"
k256 = { version = "0.13.4", features = ["arithmetic", "std", "ecdsa"] }
lazy_static = "1.5.0"
log = "0.4"
macro_rules_attribute = "0.2"
maplit = "1.0"
Expand Down
1 change: 1 addition & 0 deletions rust/main/chains/hyperlane-sealevel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ bincode.workspace = true
borsh.workspace = true
derive-new.workspace = true
jsonrpc-core.workspace = true
lazy_static.workspace = true
num-traits.workspace = true
reqwest.workspace = true
serde.workspace = true
Expand Down
6 changes: 6 additions & 0 deletions rust/main/chains/hyperlane-sealevel/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ pub enum HyperlaneSealevelError {
/// Empty compute units consumed
#[error("received empty compute units consumed in transaction")]
EmptyComputeUnitsConsumed,
/// Too many non-native programs
#[error("transaction contains too many non-native programs, hash: {0:?}")]
TooManyNonNativePrograms(H512),
/// No non-native programs
#[error("transaction contains no non-native programs, hash: {0:?}")]
NoNonNativePrograms(H512),
}

impl From<HyperlaneSealevelError> for ChainCommunicationError {
Expand Down
72 changes: 63 additions & 9 deletions rust/main/chains/hyperlane-sealevel/src/provider.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::collections::HashSet;
use std::sync::Arc;

use async_trait::async_trait;
use lazy_static::lazy_static;
use solana_sdk::signature::Signature;
use solana_transaction_status::{
option_serializer::OptionSerializer, EncodedTransaction, EncodedTransactionWithStatusMeta,
UiMessage, UiTransaction, UiTransactionStatusMeta,
UiInstruction, UiMessage, UiParsedInstruction, UiParsedMessage, UiTransaction,
UiTransactionStatusMeta,
};
use tracing::warn;

Expand All @@ -18,6 +21,19 @@ use crate::error::HyperlaneSealevelError;
use crate::utils::{decode_h256, decode_h512, decode_pubkey};
use crate::{ConnectionConf, SealevelRpcClient};

lazy_static! {
static ref NATIVE_PROGRAMS: HashSet<String> = HashSet::from([
solana_sdk::bpf_loader_upgradeable::ID.to_string(),
solana_sdk::compute_budget::ID.to_string(),
solana_sdk::config::program::ID.to_string(),
solana_sdk::ed25519_program::ID.to_string(),
solana_sdk::secp256k1_program::ID.to_string(),
solana_sdk::stake::program::ID.to_string(),
solana_sdk::system_program::ID.to_string(),
solana_sdk::vote::program::ID.to_string(),
]);
}

/// A wrapper around a Sealevel provider to get generic blockchain information.
#[derive(Debug)]
pub struct SealevelProvider {
Expand All @@ -33,7 +49,7 @@ impl SealevelProvider {
let rpc_client = Arc::new(SealevelRpcClient::new(conf.url.to_string()));
let native_token = conf.native_token.clone();

SealevelProvider {
Self {
domain,
rpc_client,
native_token,
Expand Down Expand Up @@ -64,12 +80,7 @@ impl SealevelProvider {
}

fn sender(hash: &H512, txn: &UiTransaction) -> ChainResult<H256> {
let message = match &txn.message {
UiMessage::Parsed(m) => m,
m => Err(Into::<ChainCommunicationError>::into(
HyperlaneSealevelError::UnsupportedMessageEncoding(m.clone()),
))?,
};
let message = Self::parsed_message(txn)?;

let signer = message
.account_keys
Expand All @@ -80,6 +91,39 @@ impl SealevelProvider {
Ok(sender)
}

fn recipient(hash: &H512, txn: &UiTransaction) -> ChainResult<H256> {
let message = Self::parsed_message(txn)?;

let programs = message
.instructions
.iter()
.filter_map(|ii| {
if let UiInstruction::Parsed(iii) = ii {
Some(iii)
} else {
None
}
})
.map(|ii| match ii {
UiParsedInstruction::Parsed(iii) => &iii.program_id,
UiParsedInstruction::PartiallyDecoded(iii) => &iii.program_id,
})
.filter(|program_id| !NATIVE_PROGRAMS.contains(*program_id))
.collect::<Vec<&String>>();

if programs.len() > 1 {
Err(HyperlaneSealevelError::TooManyNonNativePrograms(*hash))?;
}

let program_id = programs
.first()
.ok_or(HyperlaneSealevelError::NoNonNativePrograms(*hash))?;

let pubkey = decode_pubkey(program_id)?;
let recipient = H256::from_slice(&pubkey.to_bytes());
Ok(recipient)
}

fn gas(meta: &UiTransactionStatusMeta) -> ChainResult<U256> {
let OptionSerializer::Some(gas) = meta.compute_units_consumed else {
Err(HyperlaneSealevelError::EmptyComputeUnitsConsumed)?
Expand Down Expand Up @@ -108,6 +152,15 @@ impl SealevelProvider {
.ok_or(HyperlaneSealevelError::EmptyMetadata)?;
Ok(meta)
}

fn parsed_message(txn: &UiTransaction) -> ChainResult<&UiParsedMessage> {
Ok(match &txn.message {
UiMessage::Parsed(m) => m,
m => Err(Into::<ChainCommunicationError>::into(
HyperlaneSealevelError::UnsupportedMessageEncoding(m.clone()),
))?,
})
}
}

impl HyperlaneChain for SealevelProvider {
Expand Down Expand Up @@ -165,6 +218,7 @@ impl HyperlaneProvider for SealevelProvider {

Self::validate_transaction(hash, txn)?;
let sender = Self::sender(hash, txn)?;
let recipient = Self::recipient(hash, txn)?;
let meta = Self::meta(txn_with_meta)?;
let gas_used = Self::gas(meta)?;
let fee = self.fee(meta)?;
Expand All @@ -189,7 +243,7 @@ impl HyperlaneProvider for SealevelProvider {
gas_price,
nonce: 0,
sender,
recipient: None,
recipient: Some(recipient),
receipt: Some(receipt),
raw_input_data: None,
})
Expand Down

0 comments on commit 8e3085a

Please sign in to comment.