reth_cli_commands/init_state/
without_evm.rs
1use alloy_consensus::{BlockHeader, Header};
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, StorageLocation,
10};
11use reth_stages::{StageCheckpoint, StageId};
12use reth_static_file_types::StaticFileSegment;
13use std::{fs::File, io::Read, path::PathBuf};
14use tracing::info;
15
16pub(crate) fn read_header_from_file(path: PathBuf) -> Result<Header, eyre::Error> {
18 let mut file = File::open(path)?;
19 let mut buf = Vec::new();
20 file.read_to_end(&mut buf)?;
21
22 let header = Header::decode(&mut &buf[..])?;
23 Ok(header)
24}
25
26pub fn setup_without_evm<Provider>(
29 provider_rw: &Provider,
30 header: SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
31 total_difficulty: U256,
32) -> ProviderResult<()>
33where
34 Provider: StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader = Header>>
35 + StageCheckpointWriter
36 + BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>,
37{
38 info!(target: "reth::cli", new_tip = ?header.num_hash(), "Setting up dummy EVM chain before importing state.");
39
40 let static_file_provider = provider_rw.static_file_provider();
41 append_dummy_chain(&static_file_provider, header.number() - 1)?;
43
44 info!(target: "reth::cli", "Appending first valid block.");
45
46 append_first_block(provider_rw, &header, total_difficulty)?;
47
48 for stage in StageId::ALL {
49 provider_rw.save_stage_checkpoint(stage, StageCheckpoint::new(header.number()))?;
50 }
51
52 info!(target: "reth::cli", "Set up finished.");
53
54 Ok(())
55}
56
57fn append_first_block<Provider>(
62 provider_rw: &Provider,
63 header: &SealedHeaderFor<Provider::Primitives>,
64 total_difficulty: U256,
65) -> ProviderResult<()>
66where
67 Provider: BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>
68 + StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>,
69{
70 provider_rw.insert_block(
71 SealedBlock::<<Provider::Primitives as NodePrimitives>::Block>::from_sealed_parts(
72 header.clone(),
73 Default::default(),
74 )
75 .try_recover()
76 .expect("no senders or txes"),
77 StorageLocation::Database,
78 )?;
79
80 let sf_provider = provider_rw.static_file_provider();
81
82 sf_provider.latest_writer(StaticFileSegment::Headers)?.append_header(
83 header,
84 total_difficulty,
85 &header.hash(),
86 )?;
87
88 sf_provider.latest_writer(StaticFileSegment::Receipts)?.increment_block(header.number())?;
89
90 sf_provider.latest_writer(StaticFileSegment::Transactions)?.increment_block(header.number())?;
91
92 Ok(())
93}
94
95fn append_dummy_chain<N: NodePrimitives<BlockHeader = Header>>(
101 sf_provider: &StaticFileProvider<N>,
102 target_height: BlockNumber,
103) -> ProviderResult<()> {
104 let (tx, rx) = std::sync::mpsc::channel();
105
106 for segment in [StaticFileSegment::Transactions, StaticFileSegment::Receipts] {
108 let tx_clone = tx.clone();
109 let provider = sf_provider.clone();
110 std::thread::spawn(move || {
111 let result = provider.latest_writer(segment).and_then(|mut writer| {
112 for block_num in 1..=target_height {
113 writer.increment_block(block_num)?;
114 }
115 Ok(())
116 });
117
118 tx_clone.send(result).unwrap();
119 });
120 }
121
122 let provider = sf_provider.clone();
124 std::thread::spawn(move || {
125 let mut empty_header = Header::default();
126 let result = provider.latest_writer(StaticFileSegment::Headers).and_then(|mut writer| {
127 for block_num in 1..=target_height {
128 empty_header.number = block_num;
130 writer.append_header(&empty_header, U256::ZERO, &B256::ZERO)?;
131 }
132 Ok(())
133 });
134
135 tx.send(result).unwrap();
136 });
137
138 while let Ok(append_result) = rx.recv() {
140 if let Err(err) = append_result {
141 tracing::error!(target: "reth::cli", "Error appending dummy chain: {err}");
142 return Err(err)
143 }
144 }
145
146 for segment in
149 [StaticFileSegment::Headers, StaticFileSegment::Receipts, StaticFileSegment::Transactions]
150 {
151 assert_eq!(
152 sf_provider.latest_writer(segment)?.user_header().block_end(),
153 Some(target_height),
154 "Static file segment {segment} was unsuccessful advancing its block height."
155 );
156 }
157
158 Ok(())
159}