The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/rust/chains/hyperlane-sealevel/src/utils.rs

94 lines
3.0 KiB

use base64::Engine;
use borsh::{BorshDeserialize, BorshSerialize};
use hyperlane_core::{ChainCommunicationError, ChainResult};
use serializable_account_meta::{SerializableAccountMeta, SimulationReturnData};
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{
commitment_config::CommitmentConfig,
instruction::{AccountMeta, Instruction},
message::Message,
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_transaction_status::UiReturnDataEncoding;
Sealevel igp indexing (#2585) ### Description Depends on https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2583 Indexes IGP payments related to the relayer's data pda address. Unless this address is specified in the config (`sealevel.relayer_account `), no filtering is applied and all IGP payments are stored in the local database. <!-- What's included in this PR? --> ### Drive-by changes - Sets `HYP_BASE_GASPAYMENTENFORCEMENT` in `run-locally` for the relayer, to test that it correctly indexes the IGP payment before submitting the message - A new config section (`sealevel`) is added to the relayer - The `MessageIndexer` trait is replaced with `SequenceIndexer<HyperlaneMessage>`, renaming `fetch_count_at_tip` to `sequence_at_tip`. `SequenceIndexer` is now common to both the message and igp indexers. - The `parse_addr` macro is modified so it can be reused when parsing the sealevel relayer address config too - `rust/utils/sealevel-test.bash` is included because I was using it to test locally, but I can remove it if the sealevel e2e test already does all the steps there @mattiecnvr - Performs a `try_into` conversion that can be removed once https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2610 is done ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2501 ### Backward compatibility <!-- Are these changes backward compatible? Are there any infrastructure implications, e.g. changes that would prohibit deploying older commits using this infra tooling? Yes/No --> ### Testing <!-- What kind of testing have these changes undergone? --> e2e tests but the pipeline is failing, likely fixed by https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2602 --------- Co-authored-by: Trevor Porter <trkporter@ucdavis.edu>
1 year ago
use crate::client::RpcClientWithDebug;
/// Simulates an instruction, and attempts to deserialize it into a T.
/// If no return data at all was returned, returns Ok(None).
/// If some return data was returned but deserialization was unsuccessful,
/// an Err is returned.
pub async fn simulate_instruction<T: BorshDeserialize + BorshSerialize>(
rpc_client: &RpcClient,
payer: &Keypair,
instruction: Instruction,
) -> ChainResult<Option<T>> {
let commitment = CommitmentConfig::finalized();
let (recent_blockhash, _) = rpc_client
.get_latest_blockhash_with_commitment(commitment)
.await
.map_err(ChainCommunicationError::from_other)?;
let return_data = rpc_client
.simulate_transaction(&Transaction::new_unsigned(Message::new_with_blockhash(
&[instruction],
Some(&payer.pubkey()),
&recent_blockhash,
)))
.await
.map_err(ChainCommunicationError::from_other)?
.value
.return_data;
if let Some(return_data) = return_data {
let bytes = match return_data.data.1 {
UiReturnDataEncoding::Base64 => base64::engine::general_purpose::STANDARD
.decode(return_data.data.0)
.map_err(ChainCommunicationError::from_other)?,
};
let decoded_data =
T::try_from_slice(bytes.as_slice()).map_err(ChainCommunicationError::from_other)?;
return Ok(Some(decoded_data));
}
Ok(None)
}
/// Simulates an Instruction that will return a list of AccountMetas.
pub async fn get_account_metas(
rpc_client: &RpcClient,
payer: &Keypair,
instruction: Instruction,
) -> ChainResult<Vec<AccountMeta>> {
// If there's no data at all, default to an empty vec.
let account_metas = simulate_instruction::<SimulationReturnData<Vec<SerializableAccountMeta>>>(
rpc_client,
payer,
instruction,
)
.await?
.map(|serializable_account_metas| {
serializable_account_metas
.return_data
.into_iter()
.map(|serializable_account_meta| serializable_account_meta.into())
.collect()
})
.unwrap_or_else(Vec::new);
Ok(account_metas)
}
Sealevel igp indexing (#2585) ### Description Depends on https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2583 Indexes IGP payments related to the relayer's data pda address. Unless this address is specified in the config (`sealevel.relayer_account `), no filtering is applied and all IGP payments are stored in the local database. <!-- What's included in this PR? --> ### Drive-by changes - Sets `HYP_BASE_GASPAYMENTENFORCEMENT` in `run-locally` for the relayer, to test that it correctly indexes the IGP payment before submitting the message - A new config section (`sealevel`) is added to the relayer - The `MessageIndexer` trait is replaced with `SequenceIndexer<HyperlaneMessage>`, renaming `fetch_count_at_tip` to `sequence_at_tip`. `SequenceIndexer` is now common to both the message and igp indexers. - The `parse_addr` macro is modified so it can be reused when parsing the sealevel relayer address config too - `rust/utils/sealevel-test.bash` is included because I was using it to test locally, but I can remove it if the sealevel e2e test already does all the steps there @mattiecnvr - Performs a `try_into` conversion that can be removed once https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2610 is done ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2501 ### Backward compatibility <!-- Are these changes backward compatible? Are there any infrastructure implications, e.g. changes that would prohibit deploying older commits using this infra tooling? Yes/No --> ### Testing <!-- What kind of testing have these changes undergone? --> e2e tests but the pipeline is failing, likely fixed by https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2602 --------- Co-authored-by: Trevor Porter <trkporter@ucdavis.edu>
1 year ago
pub async fn get_finalized_block_number(rpc_client: &RpcClientWithDebug) -> ChainResult<u32> {
let height = rpc_client
.get_block_height()
.await
.map_err(ChainCommunicationError::from_other)?
.try_into()
// FIXME solana block height is u64...
.expect("sealevel block height exceeds u32::MAX");
Ok(height)
}