reth_cli_commands/init_state/
without_evm.rs1use alloy_consensus::BlockHeader;
2use alloy_primitives::{BlockNumber, B256, U256};
3use alloy_rlp::Decodable;
4use reth_codecs::Compact;
5use reth_node_builder::NodePrimitives;
6use reth_primitives_traits::{SealedBlock, SealedHeader, SealedHeaderFor};
7use reth_provider::{
8 providers::StaticFileProvider, BlockWriter, ProviderResult, StageCheckpointWriter,
9 StaticFileProviderFactory, StaticFileWriter,
10};
11use reth_stages::{StageCheckpoint, StageId};
12use reth_static_file_types::StaticFileSegment;
13use std::{fs::File, io::Read, path::PathBuf};
14use tracing::info;
15pub(crate) fn read_header_from_file<H>(path: PathBuf) -> Result<H, eyre::Error>
17where
18 H: Decodable,
19{
20 let mut file = File::open(path)?;
21 let mut buf = Vec::new();
22 file.read_to_end(&mut buf)?;
23
24 let header = H::decode(&mut &buf[..])?;
25 Ok(header)
26}
27
28pub fn setup_without_evm<Provider, F>(
31 provider_rw: &Provider,
32 header: SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
33 total_difficulty: U256,
34 header_factory: F,
35) -> ProviderResult<()>
36where
37 Provider: StaticFileProviderFactory
38 + StageCheckpointWriter
39 + BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>,
40 F: Fn(BlockNumber) -> <Provider::Primitives as NodePrimitives>::BlockHeader
41 + Send
42 + Sync
43 + 'static,
44{
45 info!(target: "reth::cli", new_tip = ?header.num_hash(), "Setting up dummy EVM chain before importing state.");
46
47 let static_file_provider = provider_rw.static_file_provider();
48 append_dummy_chain(&static_file_provider, header.number() - 1, header_factory)?;
50
51 info!(target: "reth::cli", "Appending first valid block.");
52
53 append_first_block(provider_rw, &header, total_difficulty)?;
54
55 for stage in StageId::ALL {
56 provider_rw.save_stage_checkpoint(stage, StageCheckpoint::new(header.number()))?;
57 }
58
59 info!(target: "reth::cli", "Set up finished.");
60
61 Ok(())
62}
63
64fn append_first_block<Provider>(
69 provider_rw: &Provider,
70 header: &SealedHeaderFor<Provider::Primitives>,
71 total_difficulty: U256,
72) -> ProviderResult<()>
73where
74 Provider: BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>
75 + StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>,
76{
77 provider_rw.insert_block(
78 SealedBlock::<<Provider::Primitives as NodePrimitives>::Block>::from_sealed_parts(
79 header.clone(),
80 Default::default(),
81 )
82 .try_recover()
83 .expect("no senders or txes"),
84 )?;
85
86 let sf_provider = provider_rw.static_file_provider();
87
88 sf_provider.latest_writer(StaticFileSegment::Headers)?.append_header(
89 header,
90 total_difficulty,
91 &header.hash(),
92 )?;
93
94 sf_provider.latest_writer(StaticFileSegment::Receipts)?.increment_block(header.number())?;
95
96 sf_provider.latest_writer(StaticFileSegment::Transactions)?.increment_block(header.number())?;
97
98 Ok(())
99}
100
101fn append_dummy_chain<N, F>(
107 sf_provider: &StaticFileProvider<N>,
108 target_height: BlockNumber,
109 header_factory: F,
110) -> ProviderResult<()>
111where
112 N: NodePrimitives,
113 F: Fn(BlockNumber) -> N::BlockHeader + Send + Sync + 'static,
114{
115 let (tx, rx) = std::sync::mpsc::channel();
116
117 for segment in [StaticFileSegment::Transactions, StaticFileSegment::Receipts] {
119 let tx_clone = tx.clone();
120 let provider = sf_provider.clone();
121 std::thread::spawn(move || {
122 let result = provider.latest_writer(segment).and_then(|mut writer| {
123 for block_num in 1..=target_height {
124 writer.increment_block(block_num)?;
125 }
126 Ok(())
127 });
128
129 tx_clone.send(result).unwrap();
130 });
131 }
132
133 let provider = sf_provider.clone();
135 std::thread::spawn(move || {
136 let result = provider.latest_writer(StaticFileSegment::Headers).and_then(|mut writer| {
137 for block_num in 1..=target_height {
138 let header = header_factory(block_num);
140 writer.append_header(&header, U256::ZERO, &B256::ZERO)?;
141 }
142 Ok(())
143 });
144
145 tx.send(result).unwrap();
146 });
147
148 while let Ok(append_result) = rx.recv() {
150 if let Err(err) = append_result {
151 tracing::error!(target: "reth::cli", "Error appending dummy chain: {err}");
152 return Err(err)
153 }
154 }
155
156 for segment in
159 [StaticFileSegment::Headers, StaticFileSegment::Receipts, StaticFileSegment::Transactions]
160 {
161 assert_eq!(
162 sf_provider.latest_writer(segment)?.user_header().block_end(),
163 Some(target_height),
164 "Static file segment {segment} was unsuccessful advancing its block height."
165 );
166 }
167
168 Ok(())
169}