diff --git a/wvm-apps/wvm-exexed/crates/precompiles/src/inner/wevm_block_precompile.rs b/wvm-apps/wvm-exexed/crates/precompiles/src/inner/wevm_block_precompile.rs index bfa1a8aca42a..7c76f284fdc4 100644 --- a/wvm-apps/wvm-exexed/crates/precompiles/src/inner/wevm_block_precompile.rs +++ b/wvm-apps/wvm-exexed/crates/precompiles/src/inner/wevm_block_precompile.rs @@ -13,6 +13,7 @@ use reth::primitives::{ }; use revm_primitives::{PrecompileError, PrecompileErrors}; use wevm_borsh::block::BorshSealedBlockWithSenders; +use crate::inner::graphql_util::Edge; pub const WVM_BLOCK_PC: Precompile = Precompile::Standard(wevm_read_block_pc); @@ -34,6 +35,35 @@ pub fn parse_req_input(input: &str) -> (String, String, String) { (endpoint, second_part, third_part) } +async fn send_and_get_edge(gateway: &str, query: &str) -> Option { + let data = send_graphql(gateway, query).await; + + match data { + Ok(res) => { + let resp = res.data.transactions.edges.get(0); + if let Some(&ref tx) = resp { + Some(tx.clone()) + } else { + None + } + } + Err(e) => { + println!("{}", e); + None + } + } +} + +async fn fetch_with_fallback(primary_gateway: &str, fallback_gateway: &str, query: &str) -> Option { + // Try the primary gateway first + if let Some(edge) = send_and_get_edge(primary_gateway, query).await { + return Some(edge); + } + + // If the primary gateway fails, try the fallback gateway + send_and_get_edge(fallback_gateway, query).await +} + fn wevm_read_block_pc(input: &Bytes, gas_limit: u64) -> PrecompileResult { let data_size = input.len(); let gas_used: u64 = (WVM_BLOCK_PC_READ_BASE as usize + data_size * 3) as u64; @@ -69,29 +99,14 @@ fn wevm_read_block_pc(input: &Bytes, gas_limit: u64) -> PrecompileResult { None, Some(&[("Block-Number".to_string(), vec![block_id.to_string()])]), Some(&WVM_DATA_PUBLISHERS.map(|i| i.to_string())), - Some("DESC".to_string()), + None, false, ); query }; - let data = send_graphql(clean_gateway.as_str(), query.as_str()).await; - - let edge = match data { - Ok(res) => { - let resp = res.data.transactions.edges.get(0); - if let Some(&ref tx) = resp { - Some(tx.clone()) - } else { - None - } - } - Err(e) => { - println!("{}", e); - None - } - }; + let edge = fetch_with_fallback(clean_gateway.as_str(), "https://arweave.mainnet.irys.xyz", query.as_str()).await; if let Some(edge) = edge { let tags = edge.node.tags.unwrap(); @@ -233,4 +248,17 @@ mod arweave_read_pc_tests { .to_vec() ); } + + #[test] + pub fn test_read_wvm_block_arweave_fallback() { + let input = Bytes::from("https://arweave.net;1127975;hash".as_bytes()); + let PrecompileOutput { gas_used, bytes } = wevm_read_block_pc(&input, 100_000).unwrap(); + assert_eq!(bytes.len(), 66); + assert_eq!( + bytes.to_vec(), + "0xe0201f1e284fbe6fa0c90e811194a11a694a08d240f4691996b9182f2e767fee" + .as_bytes() + .to_vec() + ); + } } diff --git a/wvm-apps/wvm-exexed/crates/reth-exexed/src/main.rs b/wvm-apps/wvm-exexed/crates/reth-exexed/src/main.rs index 1c83a099c30c..4c03ba8899e4 100644 --- a/wvm-apps/wvm-exexed/crates/reth-exexed/src/main.rs +++ b/wvm-apps/wvm-exexed/crates/reth-exexed/src/main.rs @@ -61,7 +61,7 @@ async fn exex_etl_processor( let blk_str_hash = sealed_block_with_senders.block.hash().to_string(); let block_hash = blk_str_hash.as_str(); - let does_block_exist = check_block_existence(block_hash).await; + let does_block_exist = check_block_existence(block_hash, false).await; if !does_block_exist { let arweave_id = IrysRequest::new() diff --git a/wvm-apps/wvm-exexed/crates/reth-exexed/src/util.rs b/wvm-apps/wvm-exexed/crates/reth-exexed/src/util.rs index 33e304ac2993..742a94c41e80 100644 --- a/wvm-apps/wvm-exexed/crates/reth-exexed/src/util.rs +++ b/wvm-apps/wvm-exexed/crates/reth-exexed/src/util.rs @@ -5,8 +5,8 @@ use precompiles::{ pub const AR_GRAPHQL_GATEWAY: &str = "https://arweave.mainnet.irys.xyz"; -pub(crate) async fn check_block_existence(block_hash: &str) -> bool { - let query = build_transaction_query( +pub(crate) async fn check_block_existence(block_hash: &str, irys: bool) -> bool { + let mut query = build_transaction_query( None, Some(&[ ("Block-Hash".to_string(), vec![block_hash.to_string()]), @@ -17,12 +17,26 @@ pub(crate) async fn check_block_existence(block_hash: &str) -> bool { false, ); - let data = send_graphql(AR_GRAPHQL_GATEWAY, query.as_str()).await; + let gateway = { + if !irys { + query = query.replace("order:", "sort:"); + query = query.replace("DESC", "HEIGHT_DESC"); + String::from("https://arweave.net") + } else { + String::from(AR_GRAPHQL_GATEWAY) + } + }; + + let data = send_graphql(gateway.as_str(), query.as_str()).await; if let Ok(data) = data { let resp = data.data.transactions.edges.get(0); resp.is_some() } else { - false + if !irys { + Box::pin(check_block_existence(block_hash, true)).await + } else { + false + } } } @@ -34,10 +48,12 @@ mod tests { async fn test_check_block_existence() { let block_1 = check_block_existence( "0x2685fbb2e5b93cea32e7e51334d3cc746e1a6790b901eddb3df8214be18899a1", + false, ) .await; let block_2 = check_block_existence( "0x2685fbb2e5b93cea32e7e51334d3cc746e1a6790b901eddb3df8214be18899a2", + false, ) .await; assert!(block_1);