reth_cli_commands/init_state/
without_evm.rsuse alloy_primitives::{BlockNumber, B256, U256};
use alloy_rlp::Decodable;
use alloy_consensus::{BlockHeader, Header};
use reth_codecs::Compact;
use reth_node_builder::NodePrimitives;
use reth_primitives::{SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment};
use reth_provider::{
providers::StaticFileProvider, BlockWriter, StageCheckpointWriter, StaticFileProviderFactory,
StaticFileWriter, StorageLocation,
};
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,
header: SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
total_difficulty: U256,
) -> Result<(), eyre::Error>
where
Provider: StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader = Header>>
+ StageCheckpointWriter
+ BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>,
{
info!(target: "reth::cli", "Setting up dummy EVM chain before importing state.");
let static_file_provider = provider_rw.static_file_provider();
append_dummy_chain(&static_file_provider, header.number() - 1)?;
info!(target: "reth::cli", "Appending first valid block.");
append_first_block(provider_rw, &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>(
provider_rw: &Provider,
header: &SealedHeader<<Provider::Primitives as NodePrimitives>::BlockHeader>,
total_difficulty: U256,
) -> Result<(), eyre::Error>
where
Provider: BlockWriter<Block = <Provider::Primitives as NodePrimitives>::Block>
+ StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>,
{
provider_rw.insert_block(
SealedBlockWithSenders::new(SealedBlock::new(header.clone(), Default::default()), vec![])
.expect("no senders or txes"),
StorageLocation::Database,
)?;
let sf_provider = provider_rw.static_file_provider();
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<N: NodePrimitives<BlockHeader = Header>>(
sf_provider: &StaticFileProvider<N>,
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(())
}