Skip to main content

clvm_fuzzing/
node_eq.rs

1use clvmr::{Allocator, NodePtr, SExp};
2use std::collections::HashSet;
3
4/// compare two CLVM trees. Returns true if they are identical, false otherwise
5pub fn node_eq(allocator: &Allocator, lhs: NodePtr, rhs: NodePtr) -> bool {
6    let mut stack = vec![(lhs, rhs)];
7    let mut visited = HashSet::<NodePtr>::new();
8
9    while let Some((l, r)) = stack.pop() {
10        match (allocator.sexp(l), allocator.sexp(r)) {
11            (SExp::Pair(ll, lr), SExp::Pair(rl, rr)) => {
12                if !visited.insert(l) {
13                    continue;
14                }
15                stack.push((lr, rr));
16                stack.push((ll, rl));
17            }
18            (SExp::Atom, SExp::Atom) => {
19                if !allocator.atom_eq(l, r) {
20                    return false;
21                }
22            }
23            _ => {
24                return false;
25            }
26        }
27    }
28    true
29}
30
31/// Compare two CLVM trees that may belong to different allocators.
32/// Returns true if they are structurally identical, false otherwise.
33pub fn node_eq_two(
34    lhs_allocator: &Allocator,
35    lhs: NodePtr,
36    rhs_allocator: &Allocator,
37    rhs: NodePtr,
38) -> bool {
39    let mut stack = vec![(lhs, rhs)];
40
41    while let Some((l, r)) = stack.pop() {
42        match (lhs_allocator.sexp(l), rhs_allocator.sexp(r)) {
43            (SExp::Pair(ll, lr), SExp::Pair(rl, rr)) => {
44                stack.push((lr, rr));
45                stack.push((ll, rl));
46            }
47            (SExp::Atom, SExp::Atom) => {
48                if lhs_allocator.atom(l).as_ref() != rhs_allocator.atom(r).as_ref() {
49                    return false;
50                }
51            }
52            _ => {
53                return false;
54            }
55        }
56    }
57    true
58}