///|
/// This result does not authenticate the supplied snapshots.
pub(all) enum Verification {
Verified
Rejected(String)
NoPriorHistory
} derive(Eq, Debug)
///|
pub extend Verification with Eq::{equal, not_equal}
///|
pub extend Verification with @debug.Debug::{to_repr}
///|
pub fn Verification::is_verified(self : Verification) -> Bool {
self is Verified
}
///|
pub fn Verification::code(self : Verification) -> String {
match self {
Verified => "VERIFIED"
Rejected(code) => code
NoPriorHistory => "NO_PRIOR_HISTORY"
}
}
///|
/// The expected snapshot and index must come from the caller, not the proof.
pub fn verify_inclusion(
trusted : Snapshot,
index : UInt64,
leaf : Bytes,
proof : InclusionProof,
) -> Verification {
if proof.count != trusted.count || proof.index != index {
return Rejected("METADATA_MISMATCH")
}
if trusted.count == 0UL || index >= trusted.count {
return Rejected("INDEX_OUT_OF_RANGE")
}
if leaf.length() > 67108864 {
return Rejected("LEAF_TOO_LARGE")
}
let mut position = index
let mut last = trusted.count - 1UL
let mut current = hash_leaf(leaf)
for sibling in proof.path {
if last == 0UL {
return Rejected("PATH_LENGTH")
}
if (position & 1UL) == 1UL || position == last {
current = hash_node(sibling, current)
while position != 0UL && (position & 1UL) == 0UL {
position = position >> 1
last = last >> 1
}
} else {
current = hash_node(current, sibling)
}
position = position >> 1
last = last >> 1
}
if last != 0UL {
Rejected("PATH_LENGTH")
} else if current != trusted.digest {
Rejected("ROOT_MISMATCH")
} else {
Verified
}
}