src/torrent/create_metadata.rs
pub fn metadata_from_file(file_path: &str, difficulty: u32, block_hash: &str) {
// get the torrent path from settings
let settings = Settings::load().expect("Failed to load settings");
let out_path = settings.torrent_path;
let out_path_path = Path::new(&out_path);
let parent_dir = out_path_path.parent().unwrap();
if !parent_dir.exists() {
if let Err(err) = fs::create_dir_all(parent_dir) {
eprintln!("Failed to create parent directory: {}", err);
return;
}
}
if !out_path_path.exists() {
if let Err(err) = fs::create_dir(out_path_path) {
eprintln!("Failed to create directory: {}", err);
return;
}
}
// open the block file
let mut file = File::open(file_path).expect("Failed to open file");
let mut content = Vec::new();
file.read_to_end(&mut content).expect("Failed to read file content");
// generate piece lengths based on size of the block
let piece_length: usize;
if content.len() > 0 && content.len() < 1000 {
piece_length = 100;
} else if content.len() >= 1000 && content.len() < 100000 {
piece_length = 1000;
} else if content.len() >= 100000 && content.len() < 1000000 {
piece_length = 50000;
} else {
piece_length = 1000000;
}
// hash each piece of the block
let sha256_hash = Sha256::digest(&content);
let piece_hashes: Vec<(usize, String)> = content
.chunks(piece_length)
.enumerate()
.map(|(index, piece)| {
let mut hasher = Sha256::new();
hasher.update(piece);
(index + 1, encode(hasher.finalize()))
})
.collect();
// generate the metadata for the torrent
let metadata = format!(
r#" {{
"info": {{
"length": {},
"name": "{}",
"difficulty": {},
"block_hash": "{}",
"piece length": {},
"info_hash": {:?},
"pieces": [
{}
]
}},
"created by": "Contractless Blockchain"
}}"#,
//set values for the metadata
content.len(),
Path::new(file_path).file_name().and_then(|f| f.to_str()).unwrap_or_default(),
difficulty,
block_hash,
piece_length,
hex::encode(sha256_hash),
piece_hashes
.iter()
.map(|(index, hash)| format!(r#"{{"{}": "{}"}}"#, index, hash))
.collect::<Vec<String>>()
.join(",\n ")
);
// save the torrent file
create_torrent_file(out_path, file_path, &metadata);
}
// save the torrent function
fn create_torrent_file(out_path: String, file_path: &str, metadata: &str) {
let file_name = Path::new(file_path).file_stem().unwrap().to_str().unwrap();
let torrent_file_path = Path::new(&out_path).join(format!("{}.torrent", file_name));
let mut torrent_file = File::create(&torrent_file_path).expect("Failed to create torrent file");
write!(torrent_file, "{}", metadata).expect("Failed to write to torrent file");
}