1use std::cmp::min;
19use std::io;
20
21use hashes::Hash;
22use consensus::encode::Encodable;
23
24pub fn bitcoin_merkle_root_inline<T>(data: &mut [T]) -> T
29 where T: Hash + Encodable,
30 <T as Hash>::Engine: io::Write,
31{
32 if data.is_empty() {
34 return Default::default();
35 }
36 if data.len() < 2 {
37 return T::from_inner(data[0].into_inner());
38 }
39 for idx in 0..((data.len() + 1) / 2) {
41 let idx1 = 2 * idx;
42 let idx2 = min(idx1 + 1, data.len() - 1);
43 let mut encoder = T::engine();
44 data[idx1].consensus_encode(&mut encoder).unwrap();
45 data[idx2].consensus_encode(&mut encoder).unwrap();
46 data[idx] = T::from_engine(encoder);
47 }
48 let half_len = data.len() / 2 + data.len() % 2;
49 bitcoin_merkle_root_inline(&mut data[0..half_len])
50}
51
52pub fn bitcoin_merkle_root<T, I>(mut iter: I) -> T
54 where T: Hash + Encodable,
55 <T as Hash>::Engine: io::Write,
56 I: ExactSizeIterator<Item = T>,
57{
58 if iter.len() == 0 {
60 return Default::default();
61 }
62 if iter.len() == 1 {
63 return T::from_inner(iter.next().unwrap().into_inner());
64 }
65 let half_len = iter.len() / 2 + iter.len() % 2;
67 let mut alloc = Vec::with_capacity(half_len);
68 while let Some(hash1) = iter.next() {
69 let hash2 = iter.next().unwrap_or(hash1);
71 let mut encoder = T::engine();
72 hash1.consensus_encode(&mut encoder).unwrap();
73 hash2.consensus_encode(&mut encoder).unwrap();
74 alloc.push(T::from_engine(encoder));
75 }
76 bitcoin_merkle_root_inline(&mut alloc)
77}