Skip to content

Commit 7d5fd0e

Browse files
remagpieforiequal0
authored andcommitted
Implement TrieDB::is_complete
1 parent e68dbd0 commit 7d5fd0e

File tree

1 file changed

+64
-1
lines changed

1 file changed

+64
-1
lines changed

util/merkle/src/triedb.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// You should have received a copy of the GNU Affero General Public License
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

17-
use ccrypto::blake256;
17+
use ccrypto::{blake256, BLAKE_NULL_RLP};
1818
use hashdb::HashDB;
1919
use primitives::H256;
2020

@@ -103,6 +103,27 @@ impl<'db> TrieDB<'db> {
103103
None => Ok(None),
104104
}
105105
}
106+
107+
/// Check if every leaf of the trie exists
108+
#[allow(dead_code)]
109+
pub fn is_complete(&self) -> bool {
110+
*self.root == BLAKE_NULL_RLP || self.is_complete_aux(self.root)
111+
}
112+
113+
/// Check if every leaf of the trie starting from `hash` exists
114+
fn is_complete_aux(&self, hash: &H256) -> bool {
115+
if let Some(node_rlp) = self.db.get(hash) {
116+
match RlpNode::decoded(node_rlp.as_ref()) {
117+
Some(RlpNode::Branch(.., children)) => {
118+
children.iter().flatten().all(|child| self.is_complete_aux(child))
119+
}
120+
Some(RlpNode::Leaf(..)) => true,
121+
None => false,
122+
}
123+
} else {
124+
false
125+
}
126+
}
106127
}
107128

108129
impl<'db> Trie for TrieDB<'db> {
@@ -124,6 +145,19 @@ mod tests {
124145
use crate::*;
125146
use memorydb::*;
126147

148+
fn delete_any_child(db: &mut MemoryDB, root: &H256) {
149+
let node_rlp = db.get(root).unwrap();
150+
match RlpNode::decoded(&node_rlp).unwrap() {
151+
RlpNode::Leaf(..) => {
152+
db.remove(root);
153+
}
154+
RlpNode::Branch(.., children) => {
155+
let first_child = children.iter().find(|c| c.is_some()).unwrap().unwrap();
156+
db.remove(&first_child);
157+
}
158+
}
159+
}
160+
127161
#[test]
128162
fn get() {
129163
let mut memdb = MemoryDB::new();
@@ -139,4 +173,33 @@ mod tests {
139173
assert_eq!(t.get(b"B"), Ok(Some(b"ABCBA".to_vec())));
140174
assert_eq!(t.get(b"C"), Ok(None));
141175
}
176+
177+
#[test]
178+
fn is_complete_success() {
179+
let mut memdb = MemoryDB::new();
180+
let mut root = H256::new();
181+
{
182+
let mut t = TrieDBMut::new(&mut memdb, &mut root);
183+
t.insert(b"A", b"ABC").unwrap();
184+
t.insert(b"B", b"ABCBA").unwrap();
185+
}
186+
187+
let t = TrieDB::try_new(&memdb, &root).unwrap();
188+
assert!(t.is_complete());
189+
}
190+
191+
#[test]
192+
fn is_complete_fail() {
193+
let mut memdb = MemoryDB::new();
194+
let mut root = H256::new();
195+
{
196+
let mut t = TrieDBMut::new(&mut memdb, &mut root);
197+
t.insert(b"A", b"ABC").unwrap();
198+
t.insert(b"B", b"ABCBA").unwrap();
199+
}
200+
delete_any_child(&mut memdb, &root);
201+
202+
let t = TrieDB::try_new(&memdb, &root).unwrap();
203+
assert!(!t.is_complete());
204+
}
142205
}

0 commit comments

Comments
 (0)