|
14 | 14 | // You should have received a copy of the GNU Affero General Public License |
15 | 15 | // along with this program. If not, see <https://www.gnu.org/licenses/>. |
16 | 16 |
|
17 | | -use ccrypto::blake256; |
| 17 | +use ccrypto::{blake256, BLAKE_NULL_RLP}; |
18 | 18 | use hashdb::HashDB; |
19 | 19 | use primitives::H256; |
20 | 20 |
|
@@ -108,7 +108,22 @@ impl<'db> TrieDB<'db> { |
108 | 108 |
|
109 | 109 | /// Check if every leaf of the trie exists |
110 | 110 | pub fn is_complete(&self) -> bool { |
111 | | - unimplemented!() |
| 111 | + *self.root == BLAKE_NULL_RLP || self.is_complete_aux(self.root) |
| 112 | + } |
| 113 | + |
| 114 | + /// Check if every leaf of the trie starting from `hash` exists |
| 115 | + pub fn is_complete_aux(&self, hash: &H256) -> bool { |
| 116 | + if let Some(node_rlp) = self.db.get(hash) { |
| 117 | + match RlpNode::decoded(node_rlp.as_ref()) { |
| 118 | + Some(RlpNode::Branch(.., children)) => { |
| 119 | + children.iter().flatten().all(|child| self.is_complete_aux(child)) |
| 120 | + } |
| 121 | + Some(RlpNode::Leaf(..)) => true, |
| 122 | + None => false, |
| 123 | + } |
| 124 | + } else { |
| 125 | + false |
| 126 | + } |
112 | 127 | } |
113 | 128 | } |
114 | 129 |
|
@@ -146,4 +161,33 @@ mod tests { |
146 | 161 | assert_eq!(t.get(b"B"), Ok(Some(DBValue::from_slice(b"ABCBA")))); |
147 | 162 | assert_eq!(t.get(b"C"), Ok(None)); |
148 | 163 | } |
| 164 | + |
| 165 | + #[test] |
| 166 | + fn is_complete_success() { |
| 167 | + let mut memdb = MemoryDB::new(); |
| 168 | + let mut root = H256::new(); |
| 169 | + { |
| 170 | + let mut t = TrieDBMut::new(&mut memdb, &mut root); |
| 171 | + t.insert(b"A", b"ABC").unwrap(); |
| 172 | + t.insert(b"B", b"ABCBA").unwrap(); |
| 173 | + } |
| 174 | + |
| 175 | + let t = TrieDB::try_new(&memdb, &root).unwrap(); |
| 176 | + assert!(t.is_complete()); |
| 177 | + } |
| 178 | + |
| 179 | + #[test] |
| 180 | + fn is_complete_fail() { |
| 181 | + let mut memdb = MemoryDB::new(); |
| 182 | + let mut root = H256::new(); |
| 183 | + { |
| 184 | + let mut t = TrieDBMut::new(&mut memdb, &mut root); |
| 185 | + t.insert(b"A", b"ABC").unwrap(); |
| 186 | + t.insert(b"B", b"ABCBA").unwrap(); |
| 187 | + } |
| 188 | + memdb.remove(memdb.keys().keys().next().unwrap()); |
| 189 | + |
| 190 | + let t = TrieDB::try_new(&memdb, &root).unwrap(); |
| 191 | + assert!(!t.is_complete()); |
| 192 | + } |
149 | 193 | } |
0 commit comments