use std_shims::vec::Vec;
use rand_core::{RngCore as _, OsRng};
use crate::{primitives::keccak256, merkle::merkle_root};
fn old_merkle_root(mut leafs: Vec<[u8; 32]>) -> Option<[u8; 32]> {
match leafs.len() {
0 => None,
1 => Some(leafs[0]),
2 => Some(keccak256([leafs[0], leafs[1]].concat())),
_ => {
let mut high_pow_2 = 4; while high_pow_2 < leafs.len() {
high_pow_2 *= 2;
}
let low_pow_2 = high_pow_2 / 2;
{
let overage = leafs.len() - low_pow_2;
let mut rightmost = leafs.drain((low_pow_2 - overage) ..);
debug_assert_eq!(rightmost.len() % 2, 0);
let mut paired_hashes = Vec::with_capacity(overage);
while let Some(left) = rightmost.next() {
let right = rightmost.next().expect("rightmost is of even length");
paired_hashes.push(keccak256([left, right].concat()));
}
drop(rightmost);
leafs.extend(paired_hashes);
assert_eq!(leafs.len(), low_pow_2);
}
let mut new_hashes = Vec::with_capacity(leafs.len() / 2);
while leafs.len() > 1 {
let mut i = 0;
while i < leafs.len() {
new_hashes.push(keccak256([leafs[i], leafs[i + 1]].concat()));
i += 2;
}
leafs = new_hashes;
new_hashes = Vec::with_capacity(leafs.len() / 2);
}
Some(leafs[0])
}
}
}
#[test]
fn merkle() {
assert!(old_merkle_root(vec![]).is_none());
assert!(merkle_root(&mut []).is_none());
for i in 1 .. 513 {
let mut leaves = Vec::with_capacity(i);
for _ in 0 .. i {
let mut leaf = [0; 32];
OsRng.fill_bytes(&mut leaf);
leaves.push(leaf);
}
let old = old_merkle_root(leaves.clone()).unwrap();
let new = merkle_root(leaves).unwrap();
assert_eq!(old, new);
}
}
#[test]
fn block_202612() {
use monero_io::VarInt;
use crate::block::{BlockHeader, CORRECT_BLOCK_HASH_202612, EXISTING_BLOCK_HASH_202612};
let header = BlockHeader {
hardfork_version: 1,
hardfork_signal: 0,
previous: hex::decode("5da0a3d004c352a90cc86b00fab676695d76a4d1de16036c41ba4dd188c4d76f")
.unwrap()
.try_into()
.unwrap(),
timestamp: 1_409_804_570,
nonce: 1_073_744_198,
};
let mut transactions = include!("./block_202612_transactions.txt")
.into_iter()
.map(|hash| <[u8; 32]>::try_from(hex::decode(hash).unwrap()).unwrap())
.collect::<Vec<_>>();
let mut blob = header.serialize();
blob.extend_from_slice(&merkle_root(transactions.clone()).unwrap());
VarInt::write(&transactions.len(), &mut blob).unwrap();
let mut complete = vec![];
VarInt::write(&blob.len(), &mut complete).unwrap();
complete.extend_from_slice(&blob);
assert_eq!(keccak256(complete), CORRECT_BLOCK_HASH_202612);
let mut blob = header.serialize();
blob.extend_from_slice(&merkle_root(&mut transactions[.. 512]).unwrap());
VarInt::write(&transactions.len(), &mut blob).unwrap();
let mut complete = vec![];
VarInt::write(&blob.len(), &mut complete).unwrap();
complete.extend_from_slice(&blob);
assert_eq!(keccak256(complete), EXISTING_BLOCK_HASH_202612);
}