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
@@ -105,6 +105,26 @@ impl<'db> TrieDB<'db> {
105105 None => Ok ( None ) ,
106106 }
107107 }
108+
109+ /// Check if every leaf of the trie exists
110+ pub fn is_complete ( & self ) -> bool {
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+ 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+ }
127+ }
108128}
109129
110130impl < ' db > Trie for TrieDB < ' db > {
@@ -126,6 +146,19 @@ mod tests {
126146 use crate :: * ;
127147 use memorydb:: * ;
128148
149+ fn delete_any_child ( db : & mut MemoryDB , root : & H256 ) {
150+ let node_rlp = db. get ( root) . unwrap ( ) ;
151+ match RlpNode :: decoded ( & node_rlp) . unwrap ( ) {
152+ RlpNode :: Leaf ( ..) => {
153+ db. remove ( root) ;
154+ }
155+ RlpNode :: Branch ( .., children) => {
156+ let first_child = children. iter ( ) . find ( |c| c. is_some ( ) ) . unwrap ( ) . unwrap ( ) ;
157+ db. remove ( & first_child) ;
158+ }
159+ }
160+ }
161+
129162 #[ test]
130163 fn get ( ) {
131164 let mut memdb = MemoryDB :: new ( ) ;
@@ -141,4 +174,33 @@ mod tests {
141174 assert_eq ! ( t. get( b"B" ) , Ok ( Some ( b"ABCBA" . to_vec( ) ) ) ) ;
142175 assert_eq ! ( t. get( b"C" ) , Ok ( None ) ) ;
143176 }
177+
178+ #[ test]
179+ fn is_complete_success ( ) {
180+ let mut memdb = MemoryDB :: new ( ) ;
181+ let mut root = H256 :: new ( ) ;
182+ {
183+ let mut t = TrieDBMut :: new ( & mut memdb, & mut root) ;
184+ t. insert ( b"A" , b"ABC" ) . unwrap ( ) ;
185+ t. insert ( b"B" , b"ABCBA" ) . unwrap ( ) ;
186+ }
187+
188+ let t = TrieDB :: try_new ( & memdb, & root) . unwrap ( ) ;
189+ assert ! ( t. is_complete( ) ) ;
190+ }
191+
192+ #[ test]
193+ fn is_complete_fail ( ) {
194+ let mut memdb = MemoryDB :: new ( ) ;
195+ let mut root = H256 :: new ( ) ;
196+ {
197+ let mut t = TrieDBMut :: new ( & mut memdb, & mut root) ;
198+ t. insert ( b"A" , b"ABC" ) . unwrap ( ) ;
199+ t. insert ( b"B" , b"ABCBA" ) . unwrap ( ) ;
200+ }
201+ delete_any_child ( & mut memdb, & root) ;
202+
203+ let t = TrieDB :: try_new ( & memdb, & root) . unwrap ( ) ;
204+ assert ! ( !t. is_complete( ) ) ;
205+ }
144206}
0 commit comments