Skip to content

Commit 445dc99

Browse files
committed
chain/ethereum: wrap web3 block
1 parent db61bac commit 445dc99

File tree

14 files changed

+229
-137
lines changed

14 files changed

+229
-137
lines changed

chain/ethereum/src/chain.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,11 +722,11 @@ impl Block for BlockFinality {
722722
fn timestamp(&self) -> BlockTime {
723723
match self {
724724
BlockFinality::Final(block) => {
725-
let ts = i64::try_from(block.timestamp.as_u64()).unwrap();
725+
let ts = i64::try_from(block.timestamp_u64()).unwrap();
726726
BlockTime::since_epoch(ts, 0)
727727
}
728728
BlockFinality::NonFinal(block) => {
729-
let ts = i64::try_from(block.ethereum_block.block.timestamp.as_u64()).unwrap();
729+
let ts = i64::try_from(block.ethereum_block.block.timestamp_u64()).unwrap();
730730
BlockTime::since_epoch(ts, 0)
731731
}
732732
BlockFinality::Ptr(block) => block.timestamp,

chain/ethereum/src/codec.rs

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -225,62 +225,64 @@ impl TryInto<EthereumBlockWithCalls> for &Block {
225225
format_err!("block header should always be present from gRPC Firehose")
226226
})?;
227227

228+
let web3_block = web3::types::Block {
229+
hash: Some(self.hash.try_decode_proto("block hash")?),
230+
number: Some(U64::from(self.number)),
231+
author: header.coinbase.try_decode_proto("author / coinbase")?,
232+
parent_hash: header.parent_hash.try_decode_proto("parent hash")?,
233+
uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?,
234+
state_root: header.state_root.try_decode_proto("state root")?,
235+
transactions_root: header
236+
.transactions_root
237+
.try_decode_proto("transactions root")?,
238+
receipts_root: header.receipt_root.try_decode_proto("receipt root")?,
239+
gas_used: U256::from(header.gas_used),
240+
gas_limit: U256::from(header.gas_limit),
241+
base_fee_per_gas: Some(
242+
header
243+
.base_fee_per_gas
244+
.as_ref()
245+
.map_or_else(U256::default, |v| v.into()),
246+
),
247+
extra_data: Bytes::from(header.extra_data.clone()),
248+
logs_bloom: match &header.logs_bloom.len() {
249+
0 => None,
250+
_ => Some(header.logs_bloom.try_decode_proto("logs bloom")?),
251+
},
252+
timestamp: header
253+
.timestamp
254+
.as_ref()
255+
.map_or_else(U256::default, |v| U256::from(v.seconds)),
256+
difficulty: header
257+
.difficulty
258+
.as_ref()
259+
.map_or_else(U256::default, |v| v.into()),
260+
total_difficulty: Some(
261+
header
262+
.total_difficulty
263+
.as_ref()
264+
.map_or_else(U256::default, |v| v.into()),
265+
),
266+
// FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?)
267+
seal_fields: vec![],
268+
uncles: self
269+
.uncles
270+
.iter()
271+
.map(|u| u.hash.try_decode_proto("uncle hash"))
272+
.collect::<Result<Vec<H256>, _>>()?,
273+
transactions: self
274+
.transaction_traces
275+
.iter()
276+
.map(|t| TransactionTraceAt::new(t, self).try_into())
277+
.collect::<Result<Vec<web3::types::Transaction>, Error>>()?,
278+
size: Some(U256::from(self.size)),
279+
mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?),
280+
nonce: Some(H64::from_low_u64_be(header.nonce)),
281+
};
282+
228283
let block = EthereumBlockWithCalls {
229284
ethereum_block: EthereumBlock {
230-
block: Arc::new(LightEthereumBlock {
231-
hash: Some(self.hash.try_decode_proto("block hash")?),
232-
number: Some(U64::from(self.number)),
233-
author: header.coinbase.try_decode_proto("author / coinbase")?,
234-
parent_hash: header.parent_hash.try_decode_proto("parent hash")?,
235-
uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?,
236-
state_root: header.state_root.try_decode_proto("state root")?,
237-
transactions_root: header
238-
.transactions_root
239-
.try_decode_proto("transactions root")?,
240-
receipts_root: header.receipt_root.try_decode_proto("receipt root")?,
241-
gas_used: U256::from(header.gas_used),
242-
gas_limit: U256::from(header.gas_limit),
243-
base_fee_per_gas: Some(
244-
header
245-
.base_fee_per_gas
246-
.as_ref()
247-
.map_or_else(U256::default, |v| v.into()),
248-
),
249-
extra_data: Bytes::from(header.extra_data.clone()),
250-
logs_bloom: match &header.logs_bloom.len() {
251-
0 => None,
252-
_ => Some(header.logs_bloom.try_decode_proto("logs bloom")?),
253-
},
254-
timestamp: header
255-
.timestamp
256-
.as_ref()
257-
.map_or_else(U256::default, |v| U256::from(v.seconds)),
258-
difficulty: header
259-
.difficulty
260-
.as_ref()
261-
.map_or_else(U256::default, |v| v.into()),
262-
total_difficulty: Some(
263-
header
264-
.total_difficulty
265-
.as_ref()
266-
.map_or_else(U256::default, |v| v.into()),
267-
),
268-
// FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?)
269-
seal_fields: vec![],
270-
uncles: self
271-
.uncles
272-
.iter()
273-
.map(|u| u.hash.try_decode_proto("uncle hash"))
274-
.collect::<Result<Vec<H256>, _>>()?,
275-
transactions: self
276-
.transaction_traces
277-
.iter()
278-
.map(|t| TransactionTraceAt::new(t, self).try_into())
279-
.collect::<Result<Vec<web3::types::Transaction>, Error>>()?,
280-
size: Some(U256::from(self.size)),
281-
mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?),
282-
nonce: Some(H64::from_low_u64_be(header.nonce)),
283-
}),
285+
block: Arc::new(LightEthereumBlock::new(web3_block)),
284286
transaction_receipts: self
285287
.transaction_traces
286288
.iter()

chain/ethereum/src/data_source.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -747,13 +747,13 @@ impl DataSource {
747747
// See also ca0edc58-0ec5-4c89-a7dd-2241797f5e50.
748748
// There is another special case in zkSync-era, where the transaction hash in this case would be zero
749749
// See https://docs.zksync.io/zk-stack/concepts/blocks.html#fictive-l2-block-finalizing-the-batch
750-
let transaction = if log.transaction_hash == block.hash
750+
let transaction = if log.transaction_hash == block.hash_h256()
751751
|| log.transaction_hash == Some(H256::zero())
752752
{
753753
Transaction {
754754
hash: log.transaction_hash.unwrap(),
755-
block_hash: block.hash,
756-
block_number: block.number,
755+
block_hash: block.hash_h256(),
756+
block_number: block.number_web3_u64(),
757757
transaction_index: log.transaction_index,
758758
from: Some(H160::zero()),
759759
..Transaction::default()

chain/ethereum/src/ethereum_adapter.rs

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ use graph::prelude::{
4444
use graph::slog::o;
4545
use graph::tokio::sync::RwLock;
4646
use graph::tokio::time::timeout;
47-
use graph::util::conversions::alloy_block_to_web3_block;
48-
use graph::util::conversions::alloy_block_to_web3_block_arc;
47+
use graph::util::conversions::alloy_block_to_block;
48+
use graph::util::conversions::alloy_block_to_block_arc;
4949
use graph::{
5050
blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError},
5151
prelude::{
@@ -1348,7 +1348,7 @@ impl EthereumAdapterTrait for EthereumAdapter {
13481348
if block.transactions.is_empty() {
13491349
trace!(logger, "Block {} contains no transactions", block_hash);
13501350
return Ok(EthereumBlock {
1351-
block: Arc::new(alloy_block_to_web3_block(block)),
1351+
block: Arc::new(alloy_block_to_block(block)),
13521352
transaction_receipts: Vec::new(),
13531353
});
13541354
}
@@ -1367,7 +1367,7 @@ impl EthereumAdapterTrait for EthereumAdapter {
13671367
fetch_receipts_with_retry(alloy, hashes, block_hash, logger, supports_block_receipts)
13681368
.await
13691369
.map(|transaction_receipts| EthereumBlock {
1370-
block: Arc::new(alloy_block_to_web3_block(block)),
1370+
block: Arc::new(alloy_block_to_block(block)),
13711371
transaction_receipts: transaction_receipts
13721372
.into_iter()
13731373
.map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt))
@@ -1647,7 +1647,7 @@ impl EthereumAdapterTrait for EthereumAdapter {
16471647
.await?;
16481648
let upsert_blocks: Vec<_> = new_blocks
16491649
.iter()
1650-
.map(|block| BlockFinality::Final(alloy_block_to_web3_block_arc(block.clone())))
1650+
.map(|block| BlockFinality::Final(alloy_block_to_block_arc(block.clone())))
16511651
.collect();
16521652
let block_refs: Vec<_> = upsert_blocks
16531653
.iter()
@@ -1802,7 +1802,7 @@ pub(crate) async fn blocks_with_triggers(
18021802
.map(
18031803
move |block| match triggers_by_block.remove(&(block.header.number() as BlockNumber)) {
18041804
Some(triggers) => Ok(BlockWithTriggers::new(
1805-
BlockFinality::Final(alloy_block_to_web3_block_arc(block)),
1805+
BlockFinality::Final(alloy_block_to_block_arc(block)),
18061806
triggers,
18071807
&logger2,
18081808
)),
@@ -1875,9 +1875,8 @@ pub(crate) async fn get_calls(
18751875
.calls_in_block(
18761876
&logger,
18771877
subgraph_metrics.clone(),
1878-
BlockNumber::try_from(ethereum_block.block.number.unwrap().as_u64())
1879-
.unwrap(),
1880-
h256_to_b256(ethereum_block.block.hash.unwrap()),
1878+
ethereum_block.block.number(),
1879+
h256_to_b256(ethereum_block.block.hash_h256().unwrap()),
18811880
)
18821881
.await?
18831882
};
@@ -2061,7 +2060,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions(
20612060
let transactions: Vec<&Transaction> = {
20622061
match &block.block {
20632062
BlockFinality::Final(ref block) => block
2064-
.transactions
2063+
.transactions()
20652064
.iter()
20662065
.filter(|transaction| transaction_hashes.contains(&transaction.hash))
20672066
.collect(),
@@ -2626,12 +2625,14 @@ mod tests {
26262625
EthereumBlockWithCalls,
26272626
};
26282627
use graph::blockchain::BlockPtr;
2628+
use graph::components::ethereum::Block;
26292629
use graph::prelude::alloy::primitives::B256;
26302630
use graph::prelude::alloy::providers::mock::Asserter;
26312631
use graph::prelude::alloy::providers::ProviderBuilder;
26322632
use graph::prelude::tokio::{self};
2633+
use graph::prelude::web3::types::Block as Web3Block;
26332634
use graph::prelude::web3::types::U64;
2634-
use graph::prelude::web3::types::{Address, Block, Bytes, H256};
2635+
use graph::prelude::web3::types::{Address, Bytes, H256};
26352636
use graph::prelude::EthereumCall;
26362637
use jsonrpc_core::serde_json::{self, Value};
26372638
use std::collections::HashSet;
@@ -2640,13 +2641,15 @@ mod tests {
26402641

26412642
#[test]
26422643
fn parse_block_triggers_every_block() {
2644+
let web3_block = Web3Block {
2645+
hash: Some(hash(2)),
2646+
number: Some(U64::from(2)),
2647+
..Default::default()
2648+
};
2649+
26432650
let block = EthereumBlockWithCalls {
26442651
ethereum_block: EthereumBlock {
2645-
block: Arc::new(Block {
2646-
hash: Some(hash(2)),
2647-
number: Some(U64::from(2)),
2648-
..Default::default()
2649-
}),
2652+
block: Arc::new(Block::new(web3_block)),
26502653
..Default::default()
26512654
},
26522655
calls: Some(vec![EthereumCall {
@@ -2783,13 +2786,14 @@ mod tests {
27832786

27842787
#[test]
27852788
fn parse_block_triggers_specific_call_not_found() {
2789+
let web3_block = Web3Block {
2790+
hash: Some(hash(2)),
2791+
number: Some(U64::from(2)),
2792+
..Default::default()
2793+
};
27862794
let block = EthereumBlockWithCalls {
27872795
ethereum_block: EthereumBlock {
2788-
block: Arc::new(Block {
2789-
hash: Some(hash(2)),
2790-
number: Some(U64::from(2)),
2791-
..Default::default()
2792-
}),
2796+
block: Arc::new(Block::new(web3_block)),
27932797
..Default::default()
27942798
},
27952799
calls: Some(vec![EthereumCall {
@@ -2815,13 +2819,15 @@ mod tests {
28152819

28162820
#[test]
28172821
fn parse_block_triggers_specific_call_found() {
2822+
let web3_block = Web3Block {
2823+
hash: Some(hash(2)),
2824+
number: Some(U64::from(2)),
2825+
..Default::default()
2826+
};
2827+
28182828
let block = EthereumBlockWithCalls {
28192829
ethereum_block: EthereumBlock {
2820-
block: Arc::new(Block {
2821-
hash: Some(hash(2)),
2822-
number: Some(U64::from(2)),
2823-
..Default::default()
2824-
}),
2830+
block: Arc::new(Block::new(web3_block)),
28252831
..Default::default()
28262832
},
28272833
calls: Some(vec![EthereumCall {

chain/ethereum/src/tests.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ use std::sync::Arc;
22

33
use graph::{
44
blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger},
5+
components::ethereum::Block,
56
prelude::{
6-
web3::types::{Address, Bytes, Log, H160, H256, U64},
7-
EthereumCall, LightEthereumBlock,
7+
web3::{
8+
self,
9+
types::{Address, Bytes, Log, Transaction, H160, H256, U64},
10+
},
11+
EthereumCall,
812
},
913
slog::{self, o, Logger},
1014
};
@@ -92,13 +96,14 @@ fn test_trigger_ordering() {
9296

9397
let logger = Logger::root(slog::Discard, o!());
9498

95-
let mut b: LightEthereumBlock = Default::default();
99+
let mut b: web3::types::Block<Transaction> = Default::default();
96100

97101
// This is necessary because inside of BlockWithTriggers::new
98102
// there's a log for both fields. So just using Default above
99103
// gives None on them.
100104
b.number = Some(Default::default());
101105
b.hash = Some(Default::default());
106+
let b = Block::new(b);
102107

103108
// Test that `BlockWithTriggers` sorts the triggers.
104109
let block_with_triggers = BlockWithTriggers::<crate::Chain>::new(
@@ -190,13 +195,14 @@ fn test_trigger_dedup() {
190195

191196
let logger = Logger::root(slog::Discard, o!());
192197

193-
let mut b: LightEthereumBlock = Default::default();
198+
let mut b: web3::types::Block<Transaction> = Default::default();
194199

195200
// This is necessary because inside of BlockWithTriggers::new
196201
// there's a log for both fields. So just using Default above
197202
// gives None on them.
198203
b.number = Some(Default::default());
199204
b.hash = Some(Default::default());
205+
let b = Block::new(b);
200206

201207
// Test that `BlockWithTriggers` sorts the triggers.
202208
let block_with_triggers = BlockWithTriggers::<crate::Chain>::new(

0 commit comments

Comments
 (0)