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 } ;
1818use hashdb:: HashDB ;
1919use 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
108129impl < ' 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