Skip to content

Commit 01a3ed0

Browse files
authored
feat: create header proof using BeaconBlockElectra (#1800)
1 parent 07d7047 commit 01a3ed0

File tree

7 files changed

+276
-96
lines changed

7 files changed

+276
-96
lines changed

bin/e2hs-writer/src/provider.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use e2store::{
77
era1::{BlockTuple, Era1},
88
utils::{get_era1_files, get_era_files},
99
};
10-
use ethportal_api::{consensus::beacon_state::HistoricalBatch, types::network_spec::network_spec};
10+
use ethportal_api::{
11+
consensus::{beacon_block::SignedBeaconBlock, beacon_state::HistoricalBatch},
12+
types::network_spec::network_spec,
13+
};
1114
use reqwest::{
1215
header::{HeaderMap, HeaderValue, CONTENT_TYPE},
1316
Client,
@@ -46,10 +49,7 @@ pub struct MinimalEra {
4649
}
4750

4851
impl MinimalEra {
49-
pub fn get_block(
50-
&self,
51-
block_number: u64,
52-
) -> Option<(CompressedSignedBeaconBlock, &MinimalEra)> {
52+
pub fn get_block(&self, block_number: u64) -> Option<&SignedBeaconBlock> {
5353
let first_block_number = self.blocks[0].block.execution_block_number();
5454
let last_block_number = self.blocks[self.blocks.len() - 1]
5555
.block
@@ -60,7 +60,7 @@ impl MinimalEra {
6060
.iter()
6161
.find(|block| block.block.execution_block_number() == block_number)
6262
{
63-
return Some((block.clone(), self));
63+
return Some(&block.block);
6464
}
6565
}
6666
None
@@ -179,15 +179,15 @@ impl EraProvider {
179179
pub fn get_post_merge(
180180
&self,
181181
block_number: u64,
182-
) -> anyhow::Result<(CompressedSignedBeaconBlock, &MinimalEra)> {
182+
) -> anyhow::Result<(&SignedBeaconBlock, &HistoricalBatch)> {
183183
ensure!(
184184
network_spec().is_paris_active_at_block(block_number),
185185
"Invalid logic, tried to lookup era file for pre-merge block"
186186
);
187187
for sources in self.sources.iter() {
188188
if let EraSource::PostMerge(era) = sources {
189189
if let Some(block) = era.get_block(block_number) {
190-
return Ok(block);
190+
return Ok((block, &era.historical_batch));
191191
}
192192
}
193193
}

bin/e2hs-writer/src/reader.rs

+119-80
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@ use alloy::{
55
eips::eip4895::{Withdrawal, Withdrawals},
66
primitives::B256,
77
};
8-
use alloy_hardforks::{EthereumHardfork, EthereumHardforks};
8+
use alloy_hardforks::EthereumHardforks;
99
use anyhow::{anyhow, bail, ensure};
1010
use ethportal_api::{
11+
consensus::{
12+
beacon_block::{
13+
BeaconBlockBellatrix, BeaconBlockCapella, BeaconBlockDeneb, BeaconBlockElectra,
14+
SignedBeaconBlock,
15+
},
16+
beacon_state::HistoricalBatch,
17+
},
1118
types::{
1219
execution::{
1320
accumulator::EpochAccumulator,
1421
block_body::BlockBody,
1522
header_with_proof::{
1623
build_capella_historical_summaries_proof, build_deneb_historical_summaries_proof,
17-
build_historical_roots_proof, BlockHeaderProof,
18-
BlockProofHistoricalHashesAccumulator, HeaderWithProof,
24+
build_electra_historical_summaries_proof, build_historical_roots_proof,
25+
BlockHeaderProof, BlockProofHistoricalHashesAccumulator, HeaderWithProof,
1926
},
2027
},
2128
network_spec::network_spec,
@@ -32,7 +39,7 @@ use crate::{
3239
provider::EraProvider,
3340
utils::{
3441
bellatrix_execution_payload_to_header, capella_execution_payload_to_header,
35-
lookup_epoch_acc, post_deneb_execution_payload_to_header,
42+
deneb_execution_payload_to_header, electra_execution_payload_to_header, lookup_epoch_acc,
3643
},
3744
};
3845

@@ -107,6 +114,16 @@ impl EpochReader {
107114
})
108115
}
109116

117+
pub fn iter_blocks(mut self) -> impl Iterator<Item = anyhow::Result<AllBlockData>> {
118+
(self.starting_block..self.ending_block).map(move |current_block| {
119+
if network_spec().is_paris_active_at_block(current_block) {
120+
self.get_post_merge_block_data(current_block)
121+
} else {
122+
self.get_pre_merge_block_data(current_block)
123+
}
124+
})
125+
}
126+
110127
fn get_pre_merge_block_data(&self, block_number: u64) -> anyhow::Result<AllBlockData> {
111128
let tuple = self.era_provider.get_pre_merge(block_number)?;
112129
let header = tuple.header.header;
@@ -129,23 +146,53 @@ impl EpochReader {
129146
})
130147
}
131148

132-
fn get_merge_to_capella_block_data(
133-
&mut self,
134-
block_number: u64,
135-
) -> anyhow::Result<AllBlockData> {
136-
let (block, era) = self.era_provider.get_post_merge(block_number)?;
137-
let block = block
138-
.block
139-
.message_merge()
140-
.map_err(|e| anyhow!("Unable to decode merge block: {e:?}"))?;
141-
let execution_payload = &block.body.execution_payload;
142-
let transactions = decode_transactions(&execution_payload.transactions)?;
149+
fn get_post_merge_block_data(&mut self, block_number: u64) -> anyhow::Result<AllBlockData> {
150+
let (block, historical_batch) = self.era_provider.get_post_merge(block_number)?;
151+
ensure!(
152+
block.execution_block_number() == block_number,
153+
"Post-merge block data is for wrong block! Expected: {block_number}, actual: {}",
154+
block.execution_block_number()
155+
);
156+
157+
let (header_with_proof, body) = match &block {
158+
SignedBeaconBlock::Bellatrix(beacon_block) => {
159+
self.get_merge_to_capella_header_and_body(&beacon_block.message, historical_batch)?
160+
}
161+
SignedBeaconBlock::Capella(beacon_block) => {
162+
self.get_capella_to_deneb_header_and_body(&beacon_block.message, historical_batch)?
163+
}
164+
SignedBeaconBlock::Deneb(beacon_block) => {
165+
self.get_deneb_to_electra_header_and_body(&beacon_block.message, historical_batch)?
166+
}
167+
SignedBeaconBlock::Electra(beacon_block) => {
168+
self.get_post_electra_header_and_body(&beacon_block.message, historical_batch)?
169+
}
170+
};
171+
172+
let receipts = self.get_receipts(block_number, header_with_proof.header.receipts_root)?;
173+
174+
Ok(AllBlockData {
175+
block_number,
176+
header_with_proof,
177+
body,
178+
receipts,
179+
})
180+
}
181+
182+
fn get_merge_to_capella_header_and_body(
183+
&self,
184+
block: &BeaconBlockBellatrix,
185+
historical_batch: &HistoricalBatch,
186+
) -> anyhow::Result<(HeaderWithProof, BlockBody)> {
187+
let payload = &block.body.execution_payload;
188+
189+
let transactions = decode_transactions(&payload.transactions)?;
143190

144191
let header_with_proof = HeaderWithProof {
145-
header: bellatrix_execution_payload_to_header(execution_payload, &transactions)?,
192+
header: bellatrix_execution_payload_to_header(payload, &transactions)?,
146193
proof: BlockHeaderProof::HistoricalRoots(build_historical_roots_proof(
147194
block.slot,
148-
&era.historical_batch,
195+
historical_batch,
149196
block,
150197
)),
151198
};
@@ -154,25 +201,17 @@ impl EpochReader {
154201
ommers: vec![],
155202
withdrawals: None,
156203
});
157-
let receipts = self.get_receipts(block_number, header_with_proof.header.receipts_root)?;
158-
Ok(AllBlockData {
159-
block_number,
160-
header_with_proof,
161-
body,
162-
receipts,
163-
})
204+
205+
Ok((header_with_proof, body))
164206
}
165207

166-
fn get_capella_to_deneb_block_data(
167-
&mut self,
168-
block_number: u64,
169-
) -> anyhow::Result<AllBlockData> {
170-
let (block, era) = self.era_provider.get_post_merge(block_number)?;
171-
let block = block
172-
.block
173-
.message_capella()
174-
.map_err(|e| anyhow!("Unable to decode capella block: {e:?}"))?;
208+
fn get_capella_to_deneb_header_and_body(
209+
&self,
210+
block: &BeaconBlockCapella,
211+
historical_batch: &HistoricalBatch,
212+
) -> anyhow::Result<(HeaderWithProof, BlockBody)> {
175213
let payload = &block.body.execution_payload;
214+
176215
let transactions = decode_transactions(&payload.transactions)?;
177216
let withdrawals: Vec<Withdrawal> =
178217
payload.withdrawals.iter().map(Withdrawal::from).collect();
@@ -182,7 +221,7 @@ impl EpochReader {
182221
proof: BlockHeaderProof::HistoricalSummariesCapella(
183222
build_capella_historical_summaries_proof(
184223
block.slot,
185-
&era.historical_batch.block_roots,
224+
&historical_batch.block_roots,
186225
block,
187226
),
188227
),
@@ -192,28 +231,23 @@ impl EpochReader {
192231
ommers: vec![],
193232
withdrawals: Some(Withdrawals::new(withdrawals)),
194233
});
195-
let receipts = self.get_receipts(block_number, header_with_proof.header.receipts_root)?;
196-
Ok(AllBlockData {
197-
block_number,
198-
header_with_proof,
199-
body,
200-
receipts,
201-
})
234+
235+
Ok((header_with_proof, body))
202236
}
203237

204-
fn get_deneb_block_data(&mut self, block_number: u64) -> anyhow::Result<AllBlockData> {
205-
let (block, era) = self.era_provider.get_post_merge(block_number)?;
206-
let block = block
207-
.block
208-
.message_deneb()
209-
.map_err(|e| anyhow!("Unable to decode deneb block: {e:?}"))?;
238+
fn get_deneb_to_electra_header_and_body(
239+
&self,
240+
block: &BeaconBlockDeneb,
241+
historical_batch: &HistoricalBatch,
242+
) -> anyhow::Result<(HeaderWithProof, BlockBody)> {
210243
let payload = &block.body.execution_payload;
244+
211245
let transactions = decode_transactions(&payload.transactions)?;
212246
let withdrawals: Vec<Withdrawal> =
213247
payload.withdrawals.iter().map(Withdrawal::from).collect();
214248

215249
let header_with_proof = HeaderWithProof {
216-
header: post_deneb_execution_payload_to_header(
250+
header: deneb_execution_payload_to_header(
217251
payload,
218252
block.parent_root,
219253
&transactions,
@@ -222,7 +256,7 @@ impl EpochReader {
222256
proof: BlockHeaderProof::HistoricalSummariesDeneb(
223257
build_deneb_historical_summaries_proof(
224258
block.slot,
225-
&era.historical_batch.block_roots,
259+
&historical_batch.block_roots,
226260
block,
227261
),
228262
),
@@ -232,39 +266,44 @@ impl EpochReader {
232266
ommers: vec![],
233267
withdrawals: Some(Withdrawals::new(withdrawals)),
234268
});
235-
let receipts = self.get_receipts(block_number, header_with_proof.header.receipts_root)?;
236-
Ok(AllBlockData {
237-
block_number,
238-
header_with_proof,
239-
body,
240-
receipts,
241-
})
269+
270+
Ok((header_with_proof, body))
242271
}
243272

244-
pub fn iter_blocks(mut self) -> impl Iterator<Item = anyhow::Result<AllBlockData>> {
245-
(self.starting_block..self.ending_block).map(move |current_block| {
246-
if current_block
247-
< EthereumHardfork::Paris
248-
.activation_block(network_spec().network().into())
249-
.expect("Paris should be available")
250-
{
251-
self.get_pre_merge_block_data(current_block)
252-
} else if current_block
253-
< EthereumHardfork::Shanghai
254-
.activation_block(network_spec().network().into())
255-
.expect("Shanghai should be available")
256-
{
257-
self.get_merge_to_capella_block_data(current_block)
258-
} else if current_block
259-
< EthereumHardfork::Cancun
260-
.activation_block(network_spec().network().into())
261-
.expect("Cancun should be available")
262-
{
263-
self.get_capella_to_deneb_block_data(current_block)
264-
} else {
265-
self.get_deneb_block_data(current_block)
266-
}
267-
})
273+
fn get_post_electra_header_and_body(
274+
&self,
275+
block: &BeaconBlockElectra,
276+
historical_batch: &HistoricalBatch,
277+
) -> anyhow::Result<(HeaderWithProof, BlockBody)> {
278+
let payload = &block.body.execution_payload;
279+
280+
let transactions = decode_transactions(&payload.transactions)?;
281+
let withdrawals: Vec<Withdrawal> =
282+
payload.withdrawals.iter().map(Withdrawal::from).collect();
283+
284+
let header_with_proof = HeaderWithProof {
285+
header: electra_execution_payload_to_header(
286+
payload,
287+
block.parent_root,
288+
&transactions,
289+
&withdrawals,
290+
&block.body.execution_requests,
291+
)?,
292+
proof: BlockHeaderProof::HistoricalSummariesDeneb(
293+
build_electra_historical_summaries_proof(
294+
block.slot,
295+
&historical_batch.block_roots,
296+
block,
297+
),
298+
),
299+
};
300+
let body = BlockBody(AlloyBlockBody {
301+
transactions,
302+
ommers: vec![],
303+
withdrawals: Some(Withdrawals::new(withdrawals)),
304+
});
305+
306+
Ok((header_with_proof, body))
268307
}
269308

270309
/// Returns the receipts for a given block number and receipts root.

0 commit comments

Comments
 (0)