From 940cc04670924511777d9d3ef627a5ce3f528792 Mon Sep 17 00:00:00 2001 From: Andrey Khmuro Date: Fri, 18 Oct 2024 00:27:50 +0300 Subject: [PATCH] feat: add `Smt::is_empty` (#337) --- CHANGELOG.md | 1 + src/merkle/smt/full/mod.rs | 7 +++++++ src/merkle/smt/full/tests.rs | 10 ++++++++++ src/merkle/smt/mod.rs | 3 +++ src/merkle/smt/simple/mod.rs | 7 +++++++ src/merkle/smt/simple/tests.rs | 17 +++++++++++++++++ 6 files changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd17037..acc6a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added `Smt::compute_mutations()` and `Smt::apply_mutations()` for validation-checked insertions (#327). - [BREAKING] Changed return value of the `Mmr::verify()` and `MerklePath::verify()` from `bool` to `Result<>` (#). +- Added `is_empty()` functions to the `SimpleSmt` and `Smt` structures. Added `EMPTY_ROOT` constant to the `SparseMerkleTree` trait (#337). ## 0.10.1 (2024-09-13) diff --git a/src/merkle/smt/full/mod.rs b/src/merkle/smt/full/mod.rs index 9c64002..6fe8534 100644 --- a/src/merkle/smt/full/mod.rs +++ b/src/merkle/smt/full/mod.rs @@ -130,6 +130,12 @@ impl Smt { >::open(self, key) } + /// Returns a boolean value indicating whether the SMT is empty. + pub fn is_empty(&self) -> bool { + debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT); + self.root == Self::EMPTY_ROOT + } + // ITERATORS // -------------------------------------------------------------------------------------------- @@ -252,6 +258,7 @@ impl SparseMerkleTree for Smt { type Opening = SmtProof; const EMPTY_VALUE: Self::Value = EMPTY_WORD; + const EMPTY_ROOT: RpoDigest = *EmptySubtreeRoots::entry(SMT_DEPTH, 0); fn root(&self) -> RpoDigest { self.root diff --git a/src/merkle/smt/full/tests.rs b/src/merkle/smt/full/tests.rs index 1613c8f..03eb382 100644 --- a/src/merkle/smt/full/tests.rs +++ b/src/merkle/smt/full/tests.rs @@ -516,6 +516,16 @@ fn test_smt_entries() { assert!(entries.next().is_none()); } +/// Tests that `EMPTY_ROOT` constant generated in the `Smt` equals to the root of the empty tree of +/// depth 64 +#[test] +fn test_smt_check_empty_root_constant() { + // get the root of the empty tree of depth 64 + let empty_root_64_depth = EmptySubtreeRoots::empty_hashes(64)[0]; + + assert_eq!(empty_root_64_depth, Smt::EMPTY_ROOT); +} + // SMT LEAF // -------------------------------------------------------------------------------------------- diff --git a/src/merkle/smt/mod.rs b/src/merkle/smt/mod.rs index 0b7ceb9..056c221 100644 --- a/src/merkle/smt/mod.rs +++ b/src/merkle/smt/mod.rs @@ -56,6 +56,9 @@ pub(crate) trait SparseMerkleTree { /// The default value used to compute the hash of empty leaves const EMPTY_VALUE: Self::Value; + /// The root of the empty tree with provided DEPTH + const EMPTY_ROOT: RpoDigest; + // PROVIDED METHODS // --------------------------------------------------------------------------------------------- diff --git a/src/merkle/smt/simple/mod.rs b/src/merkle/smt/simple/mod.rs index 1744430..819b6f7 100644 --- a/src/merkle/smt/simple/mod.rs +++ b/src/merkle/smt/simple/mod.rs @@ -158,6 +158,12 @@ impl SimpleSmt { >::open(self, key) } + /// Returns a boolean value indicating whether the SMT is empty. + pub fn is_empty(&self) -> bool { + debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT); + self.root == Self::EMPTY_ROOT + } + // ITERATORS // -------------------------------------------------------------------------------------------- @@ -298,6 +304,7 @@ impl SparseMerkleTree for SimpleSmt { type Opening = ValuePath; const EMPTY_VALUE: Self::Value = EMPTY_WORD; + const EMPTY_ROOT: RpoDigest = *EmptySubtreeRoots::entry(DEPTH, 0); fn root(&self) -> RpoDigest { self.root diff --git a/src/merkle/smt/simple/tests.rs b/src/merkle/smt/simple/tests.rs index 2f59ae6..b1dd28d 100644 --- a/src/merkle/smt/simple/tests.rs +++ b/src/merkle/smt/simple/tests.rs @@ -444,6 +444,23 @@ fn test_simplesmt_set_subtree_entire_tree() { assert_eq!(tree.root(), *EmptySubtreeRoots::entry(DEPTH, 0)); } +/// Tests that `EMPTY_ROOT` constant generated in the `SimpleSmt` equals to the root of the empty +/// tree of depth 64 +#[test] +fn test_simplesmt_check_empty_root_constant() { + // get the root of the empty tree of depth 64 + let empty_root_64_depth = EmptySubtreeRoots::empty_hashes(64)[0]; + assert_eq!(empty_root_64_depth, SimpleSmt::<64>::EMPTY_ROOT); + + // get the root of the empty tree of depth 32 + let empty_root_32_depth = EmptySubtreeRoots::empty_hashes(32)[0]; + assert_eq!(empty_root_32_depth, SimpleSmt::<32>::EMPTY_ROOT); + + // get the root of the empty tree of depth 0 + let empty_root_1_depth = EmptySubtreeRoots::empty_hashes(1)[0]; + assert_eq!(empty_root_1_depth, SimpleSmt::<1>::EMPTY_ROOT); +} + // HELPER FUNCTIONS // --------------------------------------------------------------------------------------------