create_fs_file/
create.rs

1#![expect(
2    unused_crate_dependencies,
3    reason = "binary shares same Cargo.toml as library"
4)]
5
6use std::fs::write;
7
8use clap::Parser;
9use tower::{Service, ServiceExt};
10
11use cuprate_blockchain::{
12    config::ConfigBuilder, cuprate_database::DbResult, service::BlockchainReadHandle,
13};
14use cuprate_hex::Hex;
15use cuprate_types::{
16    blockchain::{BlockchainReadRequest, BlockchainResponse},
17    Chain,
18};
19
20use cuprate_fast_sync::FAST_SYNC_BATCH_LEN;
21
22async fn read_batch(
23    handle: &mut BlockchainReadHandle,
24    height_from: usize,
25) -> DbResult<Vec<[u8; 32]>> {
26    let request = BlockchainReadRequest::BlockHashInRange(
27        height_from..(height_from + FAST_SYNC_BATCH_LEN),
28        Chain::Main,
29    );
30    let response_channel = handle.ready().await?.call(request);
31    let response = response_channel.await?;
32
33    let BlockchainResponse::BlockHashInRange(block_ids) = response else {
34        unreachable!()
35    };
36
37    Ok(block_ids)
38}
39
40#[derive(Parser)]
41#[command(version, about, long_about = None)]
42struct Args {
43    #[arg(long)]
44    height: usize,
45}
46
47#[tokio::main]
48async fn main() {
49    let args = Args::parse();
50    let height_target = args.height;
51
52    let config = ConfigBuilder::new().build();
53
54    let (mut read_handle, _, _) = cuprate_blockchain::service::init(config).unwrap();
55
56    let mut hashes_of_hashes = Vec::new();
57
58    let mut height = 0_usize;
59
60    while (height + FAST_SYNC_BATCH_LEN) < height_target {
61        if let Ok(block_ids) = read_batch(&mut read_handle, height).await {
62            let hash = hash_of_hashes(block_ids.as_slice());
63            hashes_of_hashes.push(Hex(hash));
64        } else {
65            println!("Failed to read next batch from database");
66            break;
67        }
68        height += FAST_SYNC_BATCH_LEN;
69
70        println!("height: {height}");
71    }
72
73    drop(read_handle);
74
75    write(
76        "fast_sync_hashes.json",
77        serde_json::to_string_pretty(&hashes_of_hashes).unwrap(),
78    )
79    .unwrap();
80
81    println!("Generated hashes up to block height {height}");
82}
83
84pub fn hash_of_hashes(hashes: &[[u8; 32]]) -> [u8; 32] {
85    blake3::hash(hashes.concat().as_slice()).into()
86}