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,27 @@ impl<'db> TrieDB<'db> {
105105 None => Ok ( None ) ,
106106 }
107107 }
108+
109+ /// Check if every leaf of the trie exists
110+ #[ allow( dead_code) ]
111+ pub fn is_complete ( & self ) -> bool {
112+ * self . root == BLAKE_NULL_RLP || self . is_complete_aux ( self . root )
113+ }
114+
115+ /// Check if every leaf of the trie starting from `hash` exists
116+ fn is_complete_aux ( & self , hash : & H256 ) -> bool {
117+ if let Some ( node_rlp) = self . db . get ( hash) {
118+ match RlpNode :: decoded ( node_rlp. as_ref ( ) ) {
119+ Some ( RlpNode :: Branch ( .., children) ) => {
120+ children. iter ( ) . flatten ( ) . all ( |child| self . is_complete_aux ( child) )
121+ }
122+ Some ( RlpNode :: Leaf ( ..) ) => true ,
123+ None => false ,
124+ }
125+ } else {
126+ false
127+ }
128+ }
108129}
109130
110131impl < ' db > Trie for TrieDB < ' db > {
@@ -126,6 +147,19 @@ mod tests {
126147 use crate :: * ;
127148 use memorydb:: * ;
128149
150+ fn delete_any_child ( db : & mut MemoryDB , root : & H256 ) {
151+ let node_rlp = db. get ( root) . unwrap ( ) ;
152+ match RlpNode :: decoded ( & node_rlp) . unwrap ( ) {
153+ RlpNode :: Leaf ( ..) => {
154+ db. remove ( root) ;
155+ }
156+ RlpNode :: Branch ( .., children) => {
157+ let first_child = children. iter ( ) . find ( |c| c. is_some ( ) ) . unwrap ( ) . unwrap ( ) ;
158+ db. remove ( & first_child) ;
159+ }
160+ }
161+ }
162+
129163 #[ test]
130164 fn get ( ) {
131165 let mut memdb = MemoryDB :: new ( ) ;
@@ -141,4 +175,33 @@ mod tests {
141175 assert_eq ! ( t. get( b"B" ) , Ok ( Some ( b"ABCBA" . to_vec( ) ) ) ) ;
142176 assert_eq ! ( t. get( b"C" ) , Ok ( None ) ) ;
143177 }
178+
179+ #[ test]
180+ fn is_complete_success ( ) {
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+
189+ let t = TrieDB :: try_new ( & memdb, & root) . unwrap ( ) ;
190+ assert ! ( t. is_complete( ) ) ;
191+ }
192+
193+ #[ test]
194+ fn is_complete_fail ( ) {
195+ let mut memdb = MemoryDB :: new ( ) ;
196+ let mut root = H256 :: new ( ) ;
197+ {
198+ let mut t = TrieDBMut :: new ( & mut memdb, & mut root) ;
199+ t. insert ( b"A" , b"ABC" ) . unwrap ( ) ;
200+ t. insert ( b"B" , b"ABCBA" ) . unwrap ( ) ;
201+ }
202+ delete_any_child ( & mut memdb, & root) ;
203+
204+ let t = TrieDB :: try_new ( & memdb, & root) . unwrap ( ) ;
205+ assert ! ( !t. is_complete( ) ) ;
206+ }
144207}
0 commit comments