use hex;
use sha2::{Digest, Sha256};
use std::{fs::File, io};
fn filehash(path: &str) -> String {
let mut file = File::open(path).unwrap();
let mut hasher = Sha256::new();
io::copy(&mut file, &mut hasher);
hex::encode(hasher.finalize())
}
#[derive(Clone)]
struct MerkleTree {
hashvalue: String,
left: Option<Box<MerkleTree>>,
right: Option<Box<MerkleTree>>,
}
impl MerkleTree {
fn createmerkle(paths: &Vec<String>) -> Box<MerkleTree> {
let length = paths.len();
let mut leaves: Vec<MerkleTree> = Vec::with_capacity(length);
for i in 0..length {
leaves[i] = MerkleTree{hashvalue : filehash(&paths[i][..]),left : None,right : None};
}
MerkleTree::buildmerkle(leaves)
}
fn buildmerkle(mut nodes: Vec<MerkleTree>) -> Box<MerkleTree> {
let mut length = nodes.len();
let mut is_even = false;
if length % 2 == 0 {
is_even = true;
}
length = (length + 1) / 2;
if length != 1 {
let mut upperlayer: Vec<MerkleTree> = Vec::with_capacity(length);
if is_even {
for i in (length - 1)..=0 {
upperlayer[i].right = Some(Box::new(nodes[2*i +1].clone()));
upperlayer[i].left = Some(Box::new(nodes[2*i].clone()));
MerkleTree::combinehash(&mut upperlayer[i]);
}
} else {
nodes.push(nodes.last().unwrap().clone());
for i in (length - 1)..=0 {
upperlayer[i].right = Some(Box::new(nodes[2*i +1].clone()));
upperlayer[i].left = Some(Box::new(nodes[2*i].clone()));
MerkleTree::combinehash(&mut upperlayer[i]);
}
}
drop(nodes);
MerkleTree::buildmerkle(upperlayer)
} else {
Box::new(nodes[0].clone())
}
}
fn combinehash(node: & mut MerkleTree) {
let mut hasher = Sha256::new();
hasher.update(node.left.as_ref().unwrap().hashvalue.clone());
hasher.update(node.right.as_ref().unwrap().hashvalue.clone());
node.hashvalue = hex::encode(hasher.finalize());
}
fn display(root : Box<MerkleTree>)
{
match root.left
{
Some(left) => {
MerkleTree::display(left);
println!("{}",root.hashvalue);
},
None => ()
}
match root.right
{
Some(right) => {
MerkleTree::display(right);
println!("{}",root.hashvalue);
},
None => ()
}
}
}
fn main() {
let mut paths : Vec<String> = Vec::with_capacity(8);
let mut path = String::with_capacity(16);
println!("Enter X to complete file upload");
loop{
println!("enter the path for the file");
path = String::from("");
io::stdin().read_line(&mut path).expect("sorry input failed");
path = path.trim().to_string();
match &path[..]
{
"X" | "x" => {
break;
}
_ => {
paths.push(path);
}
}
}
let merkleroot = MerkleTree::createmerkle(&paths);
MerkleTree::display(merkleroot);
}
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', src\main.rs:28:13
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\/library\std\src\panicking.rs:515
1: core::panicking::panic_fmt
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\/library\core\src\panicking.rs:92
2: core::panicking::panic_bounds_check
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\/library\core\src\panicking.rs:69
3: core::slice::index::impl$2::index_mut<play::MerkleTree>
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\library\core\src\slice\index.rs:190
4: core::slice::index::impl$1::index_mut<play::MerkleTree,usize>
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\library\core\src\slice\index.rs:26
5: alloc::vec::impl$15::index_mut<play::MerkleTree,usize,alloc::alloc::Global>
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\library\alloc\src\vec\mod.rs:2444
6: play::MerkleTree::createmerkle
at .\src\main.rs:28
7: play::main
at .\src\main.rs:126
8: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b\library\core\src\ops\function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\play.exe` (exit code: 101)
I'm trying to create a Merkle Tree but i'm not understanding why is this throwing error