reth_cli_commands/init_state/
without_evm.rsuse alloy_primitives::{BlockNumber, B256, U256};
use alloy_rlp::Decodable;
use alloy_consensus::Header;
use reth_primitives::{
BlockBody, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment,
};
use reth_provider::{
providers::StaticFileProvider, BlockWriter, StageCheckpointWriter, StaticFileWriter,
};
use reth_stages::{StageCheckpoint, StageId};
use std::{fs::File, io::Read, path::PathBuf};
use tracing::info;
pub(crate) fn read_header_from_file(path: PathBuf) -> Result<Header, eyre::Error> {
let mut file = File::open(path)?;
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
let header = Header::decode(&mut &buf[..])?;
Ok(header)
}
pub fn setup_without_evm<Provider>(
provider_rw: &Provider,
static_file_provider: &StaticFileProvider,
header: SealedHeader,
total_difficulty: U256,
) -> Result<(), eyre::Error>
where
Provider: StageCheckpointWriter + BlockWriter,
{
info!(target: "reth::cli", "Setting up dummy EVM chain before importing state.");
append_dummy_chain(static_file_provider, header.number - 1)?;
info!(target: "reth::cli", "Appending first valid block.");
append_first_block(provider_rw, static_file_provider, &header, total_difficulty)?;
for stage in StageId::ALL {
provider_rw.save_stage_checkpoint(stage, StageCheckpoint::new(header.number))?;
}
info!(target: "reth::cli", "Set up finished.");
Ok(())
}
fn append_first_block(
provider_rw: impl BlockWriter,
sf_provider: &StaticFileProvider,
header: &SealedHeader,
total_difficulty: U256,
) -> Result<(), eyre::Error> {
provider_rw.insert_block(
SealedBlockWithSenders::new(SealedBlock::new(header.clone(), BlockBody::default()), vec![])
.expect("no senders or txes"),
)?;
sf_provider.latest_writer(StaticFileSegment::Headers)?.append_header(
header,
total_difficulty,
&header.hash(),
)?;
sf_provider.latest_writer(StaticFileSegment::Receipts)?.increment_block(header.number)?;
sf_provider.latest_writer(StaticFileSegment::Transactions)?.increment_block(header.number)?;
Ok(())
}
fn append_dummy_chain(
sf_provider: &StaticFileProvider,
target_height: BlockNumber,
) -> Result<(), eyre::Error> {
let (tx, rx) = std::sync::mpsc::channel();
for segment in [StaticFileSegment::Transactions, StaticFileSegment::Receipts] {
let tx_clone = tx.clone();
let provider = sf_provider.clone();
std::thread::spawn(move || {
let result = provider.latest_writer(segment).and_then(|mut writer| {
for block_num in 1..=target_height {
writer.increment_block(block_num)?;
}
Ok(())
});
tx_clone.send(result).unwrap();
});
}
let provider = sf_provider.clone();
std::thread::spawn(move || {
let mut empty_header = Header::default();
let result = provider.latest_writer(StaticFileSegment::Headers).and_then(|mut writer| {
for block_num in 1..=target_height {
empty_header.number = block_num;
writer.append_header(&empty_header, U256::ZERO, &B256::ZERO)?;
}
Ok(())
});
tx.send(result).unwrap();
});
while let Ok(r) = rx.recv() {
r?;
}
for segment in
[StaticFileSegment::Headers, StaticFileSegment::Receipts, StaticFileSegment::Transactions]
{
assert_eq!(
sf_provider.latest_writer(segment)?.user_header().block_end(),
Some(target_height),
"Static file segment {segment} was unsuccessful advancing its block height."
);
}
Ok(())
}