Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions chain/ethereum/src/ethereum_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2315,13 +2315,31 @@ async fn batch_get_transaction_receipts(
Ok(results)
}

/// Fetch block receipts by hash, sending the block hash as a plain string
/// param (`["0x.."]`) rather than alloy's default EIP-1898 object
/// (`[{"blockHash":".."}]`).
///
/// `eth_getBlockReceipts` accepts both forms on most clients, but some (e.g.
/// taraxa-node) only accept the plain-string hash and reject the object with
/// `INVALID_PARAMS`. The string form is accepted by all known implementations,
/// so we always use it; alloy's typed `get_block_receipts` would always emit
/// the object form. See issue #5835.
async fn get_block_receipts_by_hash(
alloy: &AlloyProvider,
block_hash: B256,
) -> Result<Option<Vec<AnyTransactionReceiptBare>>, RpcError<TransportErrorKind>> {
alloy
.client()
.request("eth_getBlockReceipts", (block_hash,))
.await
}

pub(crate) async fn check_block_receipt_support(
alloy: Arc<AlloyProvider>,
block_hash: B256,
supports_eip_1898: bool,
call_only: bool,
) -> Result<(), Error> {
use alloy::rpc::types::BlockId;
if call_only {
return Err(anyhow!("Provider is call-only"));
}
Expand All @@ -2331,7 +2349,7 @@ pub(crate) async fn check_block_receipt_support(
}

// Fetch block receipts from the provider for the latest block.
let block_receipts_result = alloy.get_block_receipts(BlockId::from(block_hash)).await;
let block_receipts_result = get_block_receipts_by_hash(&alloy, block_hash).await;

// Determine if the provider supports block receipts based on the fetched result.
match block_receipts_result {
Expand Down Expand Up @@ -2406,15 +2424,17 @@ async fn fetch_block_receipts_with_retry(
logger: ProviderLogger,
settings: &ChainSettings,
) -> Result<Vec<Arc<AnyTransactionReceiptBare>>, IngestorError> {
use graph::prelude::alloy::rpc::types::BlockId;
let retry_log_message = format!("eth_getBlockReceipts RPC call for block {:?}", block_hash);

// Perform the retry operation
let receipts_option = retry(retry_log_message, &logger)
.redact_log_urls(true)
.limit(settings.request_retries)
.timeout_secs(settings.json_rpc_timeout.as_secs())
.run(move || alloy.get_block_receipts(BlockId::from(block_hash)).boxed())
.run(move || {
let alloy = alloy.clone();
async move { get_block_receipts_by_hash(&alloy, block_hash).await }.boxed()
})
.await
.map_err(|_timeout| -> IngestorError { anyhow!(block_hash).into() })?;

Expand Down