From b5b6ae3ca11a2dfb157c4db650470d2f51b978a5 Mon Sep 17 00:00:00 2001 From: Antony1060 Date: Thu, 23 Nov 2023 21:42:26 +0100 Subject: [PATCH 1/4] Return CCIP requests to caller method --- src/ccip.rs | 14 +++++++++++--- src/lib.rs | 8 ++++++++ src/middleware.rs | 29 +++++++++++++++++++++-------- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/ccip.rs b/src/ccip.rs index fb5dfe8..4cde4a0 100644 --- a/src/ccip.rs +++ b/src/ccip.rs @@ -11,6 +11,7 @@ use serde::Deserialize; use crate::errors::{CCIPFetchError, CCIPRequestError}; use crate::utils::truncate_str; use crate::CCIPReadMiddlewareError; +use crate::CCIPRequest; #[derive(Debug, Clone, Deserialize)] pub struct CCIPResponse { @@ -98,10 +99,10 @@ pub async fn handle_ccip( tx: &TypedTransaction, calldata: &[u8], urls: Vec, -) -> Result> { +) -> Result<(Bytes, Vec), CCIPReadMiddlewareError> { // If there are no URLs or the transaction's destination is empty, return an empty result if urls.is_empty() || tx.to().is_none() { - return Ok(Bytes::new()); + return Ok((Bytes::new(), Vec::new())); } let urls = dedup_ord(&urls); @@ -109,11 +110,18 @@ pub async fn handle_ccip( // url —> [error_message] let mut errors: HashMap> = HashMap::new(); + let mut requests = Vec::new(); + for url in urls { let result = handle_ccip_raw(client, &url, sender, calldata).await; + requests.push(CCIPRequest { + url: url.clone(), + sender: sender.clone(), + calldata: calldata.to_vec().into(), + }); match result { - Ok(result) => return Ok(result), + Ok(result) => return Ok((result, requests)), Err(err) => { errors.entry(url).or_default().push(err.to_string()); } diff --git a/src/lib.rs b/src/lib.rs index d8056df..1c2dabc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,17 @@ //! //! Provides an [ethers](https://docs.rs/ethers) compatible middleware for submitting pub use errors::CCIPReadMiddlewareError; +use ethers_core::types::{Address, Bytes}; pub use middleware::CCIPReadMiddleware; mod ccip; mod errors; mod middleware; pub mod utils; + +#[derive(Debug, Clone)] +pub struct CCIPRequest { + pub url: String, + pub sender: Address, + pub calldata: Bytes, +} diff --git a/src/middleware.rs b/src/middleware.rs index 15bc10f..cb985dc 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -19,7 +19,7 @@ use serde_json::Value; use crate::ccip::handle_ccip; use crate::utils::{build_reqwest, decode_bytes, dns_encode}; -use crate::CCIPReadMiddlewareError; +use crate::{CCIPReadMiddlewareError, CCIPRequest}; #[derive(Debug, Clone)] pub struct CCIPReadMiddleware { @@ -229,7 +229,8 @@ impl CCIPReadMiddleware { transaction: &TypedTransaction, block_id: Option, attempt: u8, - ) -> Result> { + requests_buffer: &mut Vec, + ) -> Result<(Bytes, Vec), CCIPReadMiddlewareError> { if attempt >= self.max_redirect_attempt { // may need more info return Err(CCIPReadMiddlewareError::MaxRedirectionError); @@ -258,14 +259,14 @@ impl CCIPReadMiddleware { if !matches!(block_id.unwrap_or(BlockId::Number(BlockNumber::Latest)), BlockId::Number(block) if block.is_latest()) { - return Ok(result); + return Ok((result, requests_buffer.to_vec())); } if tx_sender.is_zero() || !result.starts_with(OFFCHAIN_LOOKUP_SELECTOR) || result.len() % 32 != 4 { - return Ok(result); + return Ok((result, requests_buffer.to_vec())); } let output_types = vec![ @@ -292,7 +293,7 @@ impl CCIPReadMiddleware { decoded_data.get(4), ) else { - return Ok(result); + return Ok((result, requests_buffer.to_vec())); }; let urls: Vec = urls @@ -310,9 +311,11 @@ impl CCIPReadMiddleware { }); } - let ccip_result = + let (ccip_result, requests) = handle_ccip(&self.reqwest_client, sender, transaction, calldata, urls).await?; + requests_buffer.extend(requests); + if ccip_result.is_empty() { return Err(CCIPReadMiddlewareError::GatewayNotFoundError); } @@ -327,7 +330,17 @@ impl CCIPReadMiddleware { [callback_selector.clone(), encoded_data.clone()].concat(), )); - self._call(&callback_tx, block_id, attempt + 1).await + self._call(&callback_tx, block_id, attempt + 1, requests_buffer) + .await + } + + pub async fn call_ccip( + &self, + tx: &TypedTransaction, + block: Option, + ) -> Result<(Bytes, Vec), CCIPReadMiddlewareError> { + let mut requests = Vec::new(); + return self._call(tx, block, 0, &mut requests).await; } } @@ -353,7 +366,7 @@ where tx: &TypedTransaction, block: Option, ) -> Result { - return self._call(tx, block, 0).await; + Ok(self.call_ccip(tx, block).await?.0) } /** From a3beea98b4e29c0e52d2d13f6d76649846346dd2 Mon Sep 17 00:00:00 2001 From: Antony1060 Date: Thu, 23 Nov 2023 21:46:25 +0100 Subject: [PATCH 2/4] Fix clippy --- src/ccip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ccip.rs b/src/ccip.rs index 4cde4a0..af21c98 100644 --- a/src/ccip.rs +++ b/src/ccip.rs @@ -116,7 +116,7 @@ pub async fn handle_ccip( let result = handle_ccip_raw(client, &url, sender, calldata).await; requests.push(CCIPRequest { url: url.clone(), - sender: sender.clone(), + sender: *sender, calldata: calldata.to_vec().into(), }); From 2f52e1c144e947c31d4d80c0a1f87ec339bc02a6 Mon Sep 17 00:00:00 2001 From: Antony1060 Date: Thu, 23 Nov 2023 21:47:04 +0100 Subject: [PATCH 3/4] Fix clippy --- src/middleware.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware.rs b/src/middleware.rs index cb985dc..5fb3245 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -340,7 +340,7 @@ impl CCIPReadMiddleware { block: Option, ) -> Result<(Bytes, Vec), CCIPReadMiddlewareError> { let mut requests = Vec::new(); - return self._call(tx, block, 0, &mut requests).await; + self._call(tx, block, 0, &mut requests).await } } From 19faf4992bed2b7a12907bd2d47d08f87bcd9af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20F=2E=20=C5=A0tignjedec?= Date: Sat, 2 Dec 2023 22:05:30 +0100 Subject: [PATCH 4/4] Add comment --- src/middleware.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/middleware.rs b/src/middleware.rs index 5fb3245..062422a 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -334,6 +334,8 @@ impl CCIPReadMiddleware { .await } + /// Call the underlying middleware with the provided transaction and block, + /// returning both the result of the call and the CCIP requests made during the call pub async fn call_ccip( &self, tx: &TypedTransaction,