reth_cli_commands/init_state/
without_evm.rs1use alloy_primitives::{BlockNumber, B256, U256};
2use alloy_rlp::Decodable;
3
4use alloy_consensus::{BlockHeader, Header};
5use reth_codecs::Compact;
6use reth_node_builder::NodePrimitives;
7use reth_primitives::{SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment};
8use reth_provider::{
9 providers::StaticFileProvider, BlockWriter, StageCheckpointWriter, StaticFileProviderFactory,
10 StaticFileWriter, StorageLocation,
11};
12use reth_stages::{StageCheckpoint, StageId};
13
14use std::{fs::File, io::Read, path::PathBuf};
15use tracing::info;
16
17pub(crate) fn read_header_from_file(path: PathBuf) -> Result<Header, eyre::Error> {
19 let mut file = File::open(path)?;
20 let mut buf = Vec::new();
21 file.read_to_end(&mut buf)?;
22
23 let header = Header::decode(&mut &buf[..])?;
24 Ok(header)
25}
26
27pub fn setup_without_evm<Provider>(
30 provider_rw: &Provider,
31 header: SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
32 total_difficulty: U256,
33) -> Result<(), eyre::Error>
34where
35 Provider: StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader = Header>>
36 + StageCheckpointWriter
37 + BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>,
38{
39 info!(target: "reth::cli", "Setting up dummy EVM chain before importing state.");
40
41 let static_file_provider = provider_rw.static_file_provider();
42 append_dummy_chain(&static_file_provider, header.number() - 1)?;
44
45 info!(target: "reth::cli", "Appending first valid block.");
46
47 append_first_block(provider_rw, &header, total_difficulty)?;
48
49 for stage in StageId::ALL {
50 provider_rw.save_stage_checkpoint(stage, StageCheckpoint::new(header.number()))?;
51 }
52
53 info!(target: "reth::cli", "Set up finished.");
54
55 Ok(())
56}
57
58fn append_first_block<Provider>(
63 provider_rw: &Provider,
64 header: &SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
65 total_difficulty: U256,
66) -> Result<(), eyre::Error>
67where
68 Provider: BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>
69 + StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>,
70{
71 provider_rw.insert_block(
72 SealedBlockWithSenders::new(SealedBlock::new(header.clone(), Default::default()), vec![])
73 .expect("no senders or txes"),
74 StorageLocation::Database,
75 )?;
76
77 let sf_provider = provider_rw.static_file_provider();
78
79 sf_provider.latest_writer(StaticFileSegment::Headers)?.append_header(
80 header,
81 total_difficulty,
82 &header.hash(),
83 )?;
84
85 sf_provider.latest_writer(StaticFileSegment::Receipts)?.increment_block(header.number())?;
86
87 sf_provider.latest_writer(StaticFileSegment::Transactions)?.increment_block(header.number())?;
88
89 Ok(())
90}
91
92fn append_dummy_chain<N: NodePrimitives<BlockHeader = Header>>(
98 sf_provider: &StaticFileProvider<N>,
99 target_height: BlockNumber,
100) -> Result<(), eyre::Error> {
101 let (tx, rx) = std::sync::mpsc::channel();
102
103 for segment in [StaticFileSegment::Transactions, StaticFileSegment::Receipts] {
105 let tx_clone = tx.clone();
106 let provider = sf_provider.clone();
107 std::thread::spawn(move || {
108 let result = provider.latest_writer(segment).and_then(|mut writer| {
109 for block_num in 1..=target_height {
110 writer.increment_block(block_num)?;
111 }
112 Ok(())
113 });
114
115 tx_clone.send(result).unwrap();
116 });
117 }
118
119 let provider = sf_provider.clone();
121 std::thread::spawn(move || {
122 let mut empty_header = Header::default();
123 let result = provider.latest_writer(StaticFileSegment::Headers).and_then(|mut writer| {
124 for block_num in 1..=target_height {
125 empty_header.number = block_num;
127 writer.append_header(&empty_header, U256::ZERO, &B256::ZERO)?;
128 }
129 Ok(())
130 });
131
132 tx.send(result).unwrap();
133 });
134
135 while let Ok(r) = rx.recv() {
137 r?;
138 }
139
140 for segment in
143 [StaticFileSegment::Headers, StaticFileSegment::Receipts, StaticFileSegment::Transactions]
144 {
145 assert_eq!(
146 sf_provider.latest_writer(segment)?.user_header().block_end(),
147 Some(target_height),
148 "Static file segment {segment} was unsuccessful advancing its block height."
149 );
150 }
151
152 Ok(())
153}