feat: Merkle tree list hashing
This commit is contained in:
parent
27e5aaa777
commit
d4f07b4f04
2 changed files with 37 additions and 0 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"hasher",
|
||||
"Merkle",
|
||||
"Precertificate"
|
||||
],
|
||||
|
|
|
@ -1 +1,37 @@
|
|||
use sha2::{Digest, Sha256};
|
||||
|
||||
use super::types::MerkleTreeLeaf;
|
||||
|
||||
pub enum MerkleTreeNode<'a> {
|
||||
Leaf(MerkleTreeLeaf<'a>),
|
||||
Intermediate(String)
|
||||
}
|
||||
|
||||
/// Hashes a merkle leaf list. This takes in a slice of u8 slices, each
|
||||
/// representing the binary form of a merkle tree leaf. This implementation is
|
||||
/// not optimized for extra-long lists as its implementation is recursive,
|
||||
/// however, the current-largest CT log as of 11/5/24 would theoretically only
|
||||
/// go 32 levels deep.
|
||||
pub fn hash_merkle_leaf_list(leaves: &[&[u8]]) -> [u8; 32] {
|
||||
let mut hasher = Sha256::default();
|
||||
|
||||
// The hash of an empty list is the empty hash, no branch necessary
|
||||
if leaves.len() == 1 {
|
||||
// The hash of one element is 0x00 + the hash of its data
|
||||
hasher.update([0x00u8]);
|
||||
hasher.update(leaves[0]);
|
||||
} else if leaves.len() > 1 {
|
||||
// For n > 1, let k be the largest power of two smaller than n (i.e., k < n <=
|
||||
// 2k)
|
||||
// MTH(D[n]) = SHA-256(0x01 || MTH(D[0:k]) || MTH(D[k:n]))
|
||||
|
||||
// This can be calculated by taking log_2(n), flooring it, then taking 2
|
||||
// to the power of it again
|
||||
let k = 2usize.pow(leaves.len().ilog2());
|
||||
hasher.update([0x01u8]);
|
||||
hasher.update(hash_merkle_leaf_list(&leaves[0..k]));
|
||||
hasher.update(hash_merkle_leaf_list(&leaves[k..leaves.len()]));
|
||||
}
|
||||
|
||||
return hasher.finalize().into();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue