Skip to content

Commit 53755a6

Browse files
committed
graph, chain/ethereum: Use AnyNetwork with concrete AlloyProvider type
1 parent 7344266 commit 53755a6

File tree

9 files changed

+279
-93
lines changed

9 files changed

+279
-93
lines changed

chain/ethereum/src/adapter.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use anyhow::Error;
22
use graph::abi;
33
use graph::blockchain::ChainIdentifier;
4+
use graph::components::ethereum::AnyBlock;
45
use graph::components::subgraph::MappingError;
56
use graph::data::store::ethereum::call;
67
use graph::data_source::common::ContractCall;
78
use graph::firehose::CallToFilter;
89
use graph::firehose::CombinedFilter;
910
use graph::firehose::LogFilter;
1011
use graph::prelude::alloy::primitives::{Address, B256};
11-
use graph::prelude::alloy::rpc::types::Block as AlloyBlock;
1212
use graph::prelude::alloy::rpc::types::Log;
1313
use graph::prelude::alloy::transports::{RpcError, TransportErrorKind};
1414
use itertools::Itertools;
@@ -1118,19 +1118,19 @@ pub trait EthereumAdapter: Send + Sync + 'static {
11181118
&self,
11191119
logger: &Logger,
11201120
block_hash: B256,
1121-
) -> Result<Option<AlloyBlock>, Error>;
1121+
) -> Result<Option<AnyBlock>, Error>;
11221122

11231123
async fn block_by_number(
11241124
&self,
11251125
logger: &Logger,
11261126
block_number: BlockNumber,
1127-
) -> Result<Option<AlloyBlock>, Error>;
1127+
) -> Result<Option<AnyBlock>, Error>;
11281128

11291129
/// Load full information for the specified `block` (in particular, transaction receipts).
11301130
async fn load_full_block(
11311131
&self,
11321132
logger: &Logger,
1133-
block: AlloyBlock,
1133+
block: AnyBlock,
11341134
) -> Result<EthereumBlock, bc::IngestorError>;
11351135

11361136
/// Finds the hash and number of the lowest non-null block with height greater than or equal to

chain/ethereum/src/codec.rs

Lines changed: 108 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ use graph::{
77
blockchain::{
88
self, Block as BlockchainBlock, BlockPtr, BlockTime, ChainStoreBlock, ChainStoreData,
99
},
10+
components::ethereum::{AnyBlock, AnyHeader, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope},
1011
prelude::{
1112
alloy::{
1213
self,
13-
consensus::{ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType},
14+
consensus::{ReceiptWithBloom, TxEnvelope, TxType},
15+
network::AnyReceiptEnvelope,
1416
primitives::{aliases::B2048, Address, Bloom, Bytes, LogData, B256, U256},
15-
rpc::types::{
16-
AccessList, AccessListItem, Block as AlloyBlock, Transaction,
17-
TransactionReceipt as AlloyTransactionReceipt,
18-
},
17+
rpc::types::{self as alloy_rpc_types, AccessList, AccessListItem, Transaction},
18+
serde::WithOtherFields,
1919
},
2020
BlockNumber, Error, EthereumBlock, EthereumBlockWithCalls, EthereumCall,
2121
LightEthereumBlock,
@@ -142,18 +142,21 @@ impl<'a> TransactionTraceAt<'a> {
142142
}
143143
}
144144

145-
impl<'a> TryInto<Transaction> for TransactionTraceAt<'a> {
145+
impl<'a> TryInto<Transaction<AnyTxEnvelope>> for TransactionTraceAt<'a> {
146146
type Error = Error;
147147

148-
fn try_into(self) -> Result<Transaction, Self::Error> {
148+
fn try_into(self) -> Result<Transaction<AnyTxEnvelope>, Self::Error> {
149149
use alloy::{
150150
consensus::transaction::Recovered,
151151
consensus::{
152152
Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip7702, TxLegacy,
153153
},
154+
network::{AnyTxEnvelope, AnyTxType, UnknownTxEnvelope, UnknownTypedTransaction},
154155
primitives::{Bytes, TxKind, U256},
155156
rpc::types::Transaction as AlloyTransaction,
157+
serde::OtherFields,
156158
};
159+
use std::collections::BTreeMap;
157160

158161
// Extract data from trace and block
159162
let block_hash = self.block.hash.try_decode_proto("transaction block hash")?;
@@ -172,20 +175,77 @@ impl<'a> TryInto<Transaction> for TransactionTraceAt<'a> {
172175
let gas_limit = self.trace.gas_limit;
173176
let input = Bytes::from(self.trace.input.clone());
174177

175-
let tx_type = u64::try_from(self.trace.r#type).map_err(|_| {
178+
let tx_type_u64 = u64::try_from(self.trace.r#type).map_err(|_| {
176179
format_err!(
177180
"Invalid transaction type value {} in transaction trace. Transaction type must be a valid u64.",
178181
self.trace.r#type
179182
)
180183
})?;
181184

182-
let tx_type = TxType::try_from(tx_type).map_err(|_| {
183-
format_err!(
184-
"Unsupported transaction type {} in transaction trace. Only standard Ethereum transaction types (Legacy=0, EIP-2930=1, EIP-1559=2, EIP-4844=3, EIP-7702=4) are supported.",
185-
tx_type
186-
)
187-
})?;
185+
// Try to convert to known Ethereum transaction type
186+
let tx_type_result = TxType::try_from(tx_type_u64);
187+
188+
// If this is an unknown transaction type, create an UnknownTxEnvelope
189+
if tx_type_result.is_err() {
190+
let mut fields_map = BTreeMap::new();
191+
192+
fields_map.insert(
193+
"nonce".to_string(),
194+
jsonrpc_core::serde_json::json!(format!("0x{:x}", self.trace.nonce)),
195+
);
196+
fields_map.insert(
197+
"from".to_string(),
198+
jsonrpc_core::serde_json::json!(format!("{:?}", from_address)),
199+
);
200+
if let Some(to_addr) = to {
201+
fields_map.insert(
202+
"to".to_string(),
203+
jsonrpc_core::serde_json::json!(format!("{:?}", to_addr)),
204+
);
205+
}
206+
fields_map.insert(
207+
"value".to_string(),
208+
jsonrpc_core::serde_json::json!(format!("0x{:x}", value)),
209+
);
210+
fields_map.insert(
211+
"gas".to_string(),
212+
jsonrpc_core::serde_json::json!(format!("0x{:x}", gas_limit)),
213+
);
214+
fields_map.insert(
215+
"gasPrice".to_string(),
216+
jsonrpc_core::serde_json::json!(format!("0x{:x}", gas_price)),
217+
);
218+
fields_map.insert(
219+
"input".to_string(),
220+
jsonrpc_core::serde_json::json!(format!("0x{}", hex::encode(&input))),
221+
);
222+
223+
let fields = OtherFields::new(fields_map);
224+
let unknown_tx = UnknownTypedTransaction {
225+
ty: AnyTxType(tx_type_u64 as u8),
226+
fields,
227+
memo: Default::default(),
228+
};
229+
230+
let tx_hash = self.trace.hash.try_decode_proto("transaction hash")?;
231+
let unknown_envelope = UnknownTxEnvelope {
232+
hash: tx_hash,
233+
inner: unknown_tx,
234+
};
235+
236+
let any_envelope = AnyTxEnvelope::Unknown(unknown_envelope);
237+
let recovered = Recovered::new_unchecked(any_envelope, from_address);
238+
239+
return Ok(AlloyTransaction {
240+
inner: recovered,
241+
block_hash: Some(block_hash),
242+
block_number: Some(block_number),
243+
transaction_index,
244+
effective_gas_price: if gas_price > 0 { Some(gas_price) } else { None },
245+
});
246+
}
188247

248+
let tx_type = tx_type_result.unwrap();
189249
let nonce = self.trace.nonce;
190250

191251
// Extract EIP-1559 fee fields from trace
@@ -358,7 +418,8 @@ impl<'a> TryInto<Transaction> for TransactionTraceAt<'a> {
358418
}
359419
};
360420

361-
let recovered = Recovered::new_unchecked(envelope, from_address);
421+
let any_envelope = AnyTxEnvelope::Ethereum(envelope);
422+
let recovered = Recovered::new_unchecked(any_envelope, from_address);
362423

363424
Ok(AlloyTransaction {
364425
inner: recovered,
@@ -378,10 +439,10 @@ impl TryInto<BlockFinality> for &Block {
378439
}
379440
}
380441

381-
impl TryInto<AlloyBlock> for &Block {
442+
impl TryInto<AnyBlock> for &Block {
382443
type Error = Error;
383444

384-
fn try_into(self) -> Result<AlloyBlock, Self::Error> {
445+
fn try_into(self) -> Result<AnyBlock, Self::Error> {
385446
let header = self.header();
386447

387448
let block_hash = self.hash.try_decode_proto("block hash")?;
@@ -458,27 +519,39 @@ impl TryInto<AlloyBlock> for &Block {
458519
.transaction_traces
459520
.iter()
460521
.map(|t| TransactionTraceAt::new(t, self).try_into())
461-
.collect::<Result<Vec<Transaction>, Error>>()?;
522+
.collect::<Result<Vec<Transaction<AnyTxEnvelope>>, Error>>()?;
462523

463524
let uncles = self
464525
.uncles
465526
.iter()
466527
.map(|u| u.hash.try_decode_proto("uncle hash"))
467528
.collect::<Result<Vec<B256>, _>>()?;
468529

469-
Ok(AlloyBlock::new(
470-
rpc_header,
471-
alloy::rpc::types::BlockTransactions::Full(transactions),
472-
)
473-
.with_uncles(uncles))
530+
use alloy::rpc::types::Block;
531+
532+
let any_header: AnyRpcHeader = rpc_header.map(AnyHeader::from);
533+
534+
let any_transactions: Vec<AnyRpcTransaction> = transactions
535+
.into_iter()
536+
.map(|tx| AnyRpcTransaction::new(WithOtherFields::new(tx)))
537+
.collect();
538+
539+
let any_block = Block {
540+
header: any_header,
541+
transactions: alloy::rpc::types::BlockTransactions::Full(any_transactions),
542+
uncles,
543+
withdrawals: None,
544+
};
545+
546+
Ok(AnyBlock::new(WithOtherFields::new(any_block)))
474547
}
475548
}
476549

477550
impl TryInto<EthereumBlockWithCalls> for &Block {
478551
type Error = Error;
479552

480553
fn try_into(self) -> Result<EthereumBlockWithCalls, Self::Error> {
481-
let alloy_block: AlloyBlock = self.try_into()?;
554+
let alloy_block: AnyBlock = self.try_into()?;
482555

483556
let transaction_receipts = self
484557
.transaction_traces
@@ -494,7 +567,7 @@ impl TryInto<EthereumBlockWithCalls> for &Block {
494567
#[allow(unreachable_code)]
495568
let block = EthereumBlockWithCalls {
496569
ethereum_block: EthereumBlock {
497-
block: Arc::new(LightEthereumBlock::new(alloy_block.into())),
570+
block: Arc::new(LightEthereumBlock::new(alloy_block)),
498571
transaction_receipts,
499572
},
500573
// Comment (437a9f17-67cc-478f-80a3-804fe554b227): This Some() will avoid calls in the triggers_in_block
@@ -521,7 +594,7 @@ impl TryInto<EthereumBlockWithCalls> for &Block {
521594
fn transaction_trace_to_alloy_txn_reciept(
522595
t: &TransactionTrace,
523596
block: &Block,
524-
) -> Result<Option<AlloyTransactionReceipt<ReceiptEnvelope<alloy::rpc::types::Log>>>, Error> {
597+
) -> Result<Option<alloy::network::AnyTransactionReceipt>, Error> {
525598
use alloy::consensus::{Eip658Value, Receipt};
526599
let r = t.receipt.as_ref();
527600

@@ -588,27 +661,19 @@ fn transaction_trace_to_alloy_txn_reciept(
588661

589662
let receipt_with_bloom = ReceiptWithBloom::new(core_receipt, logs_bloom);
590663

591-
let tx_type = TxType::try_from(u64::try_from(t.r#type).map_err(|_| {
664+
let tx_type_u64 = u64::try_from(t.r#type).map_err(|_| {
592665
format_err!(
593666
"Invalid transaction type value {} in transaction receipt. Transaction type must be a valid u64.",
594667
t.r#type
595668
)
596-
})?).map_err(|_| {
597-
format_err!(
598-
"Unsupported transaction type {} in transaction receipt. Only standard Ethereum transaction types (Legacy=0, EIP-2930=1, EIP-1559=2, EIP-4844=3, EIP-7702=4) are supported.",
599-
t.r#type
600-
)
601669
})?;
602670

603-
let envelope = match tx_type {
604-
TxType::Legacy => ReceiptEnvelope::Legacy(receipt_with_bloom),
605-
TxType::Eip2930 => ReceiptEnvelope::Eip2930(receipt_with_bloom),
606-
TxType::Eip1559 => ReceiptEnvelope::Eip1559(receipt_with_bloom),
607-
TxType::Eip4844 => ReceiptEnvelope::Eip4844(receipt_with_bloom),
608-
TxType::Eip7702 => ReceiptEnvelope::Eip7702(receipt_with_bloom),
671+
let any_envelope = AnyReceiptEnvelope {
672+
inner: receipt_with_bloom,
673+
r#type: tx_type_u64 as u8,
609674
};
610675

611-
Ok(Some(AlloyTransactionReceipt {
676+
let receipt = alloy_rpc_types::TransactionReceipt {
612677
transaction_hash: t.hash.try_decode_proto("transaction hash")?,
613678
transaction_index: Some(t.index as u64),
614679
block_hash: Some(block.hash.try_decode_proto("transaction block hash")?),
@@ -626,8 +691,10 @@ fn transaction_trace_to_alloy_txn_reciept(
626691
let val: U256 = x.into();
627692
val.to::<u128>()
628693
}),
629-
inner: envelope,
630-
}))
694+
inner: any_envelope,
695+
};
696+
697+
Ok(Some(WithOtherFields::new(receipt)))
631698
}
632699

633700
impl BlockHeader {

0 commit comments

Comments
 (0)