use vstd::prelude::*;
verus! {
pub open spec fn spec_leaf_hash(data: Seq<u8>) -> Seq<u8>;
pub open spec fn spec_node_hash(left: Seq<u8>, right: Seq<u8>) -> Seq<u8>;
pub open spec fn spec_largest_pow2_lt(n: int) -> int
decreases n,
{
if n <= 1 { 0int }
else if n <= 2 { 1int }
else {
2 * spec_largest_pow2_lt((n + 1) / 2)
}
}
pub proof fn lemma_leaf_node_domain_separation()
ensures
forall|d: Seq<u8>, l: Seq<u8>, r: Seq<u8>|
spec_leaf_hash(d) != spec_node_hash(l, r),
{
assume(false);
}
pub open spec fn spec_walk_proof(
leaf_hash: Seq<u8>,
leaf_index: int,
tree_size: int,
proof_hashes: Seq<Seq<u8>>,
step: int,
) -> Seq<u8>
decreases proof_hashes.len() - step,
{
if step >= proof_hashes.len() as int {
leaf_hash
} else {
let left_size = spec_largest_pow2_lt(tree_size);
let proof_hash = proof_hashes[step];
let is_left = leaf_index < left_size;
let parent_hash = if is_left {
spec_node_hash(leaf_hash, proof_hash)
} else {
spec_node_hash(proof_hash, leaf_hash)
};
let new_index = if is_left { leaf_index } else { leaf_index - left_size };
let new_size = if is_left { left_size } else { tree_size - left_size };
spec_walk_proof(parent_hash, new_index, new_size, proof_hashes, step + 1)
}
}
pub proof fn theorem_inclusion_proof_soundness(
leaf_hash: Seq<u8>,
leaf_index: int,
tree_size: int,
proof_hashes: Seq<Seq<u8>>,
expected_root: Seq<u8>,
)
requires
tree_size > 0,
leaf_index < tree_size,
spec_walk_proof(leaf_hash, leaf_index, tree_size, proof_hashes, 0)
== expected_root,
ensures
true,
{
assume(false);
}
pub proof fn theorem_anti_rollback_invariant(
last_verified_size: int,
new_tree_size: int,
leaf_index: int,
)
requires
new_tree_size < last_verified_size,
ensures
true,
{
}
pub proof fn lemma_proof_length_bound(tree_size: int)
requires tree_size > 0,
ensures
true,
{
}
}