@@ -96,8 +96,11 @@ enum AccountState {
9696/// Account entry can contain existing (`Some`) or non-existing
9797/// account (`None`)
9898struct AccountEntry {
99+ /// Account entry. `None` if account known to be non-existant.
99100 account : Option < Account > ,
100- clean_balance : Option < U256 > ,
101+ /// Unmodified account balance.
102+ old_balance : Option < U256 > ,
103+ /// Entry state.
101104 state : AccountState ,
102105}
103106
@@ -126,16 +129,16 @@ impl AccountEntry {
126129 /// basic account data and modified storage keys.
127130 fn clone_dirty ( & self ) -> AccountEntry {
128131 AccountEntry {
132+ old_balance : self . old_balance ,
129133 account : self . account . as_ref ( ) . map ( Account :: clone_dirty) ,
130134 state : self . state ,
131- clean_balance : self . clean_balance ,
132135 }
133136 }
134137
135138 // Create a new account entry and mark it as dirty.
136139 fn new_dirty ( account : Option < Account > ) -> AccountEntry {
137140 AccountEntry {
138- clean_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
141+ old_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
139142 account : account,
140143 state : AccountState :: Dirty ,
141144 }
@@ -144,7 +147,7 @@ impl AccountEntry {
144147 // Create a new account entry and mark it as clean.
145148 fn new_clean ( account : Option < Account > ) -> AccountEntry {
146149 AccountEntry {
147- clean_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
150+ old_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
148151 account : account,
149152 state : AccountState :: CleanFresh ,
150153 }
@@ -153,7 +156,7 @@ impl AccountEntry {
153156 // Create a new account entry and mark it as clean and cached.
154157 fn new_clean_cached ( account : Option < Account > ) -> AccountEntry {
155158 AccountEntry {
156- clean_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
159+ old_balance : account. as_ref ( ) . map ( |a| a. balance ( ) . clone ( ) ) ,
157160 account : account,
158161 state : AccountState :: CleanCached ,
159162 }
@@ -549,7 +552,7 @@ impl<B: Backend> State<B> {
549552 if is_value_transfer || ( cleanup_mode == CleanupMode :: ForceCreate && !self . exists ( a) ?) {
550553 self . require ( a, false ) ?. add_balance ( incr) ;
551554 } else if cleanup_mode == CleanupMode :: KillEmpty && self . exists ( a) ? {
552- self . require ( a , false ) ?;
555+ self . touch ( a ) ?;
553556 }
554557
555558 Ok ( ( ) )
@@ -625,6 +628,11 @@ impl<B: Backend> State<B> {
625628 Executive :: new ( self , env_info, engine, & vm_factory) . transact ( t, options)
626629 }
627630
631+ fn touch ( & mut self , a : & Address ) -> trie:: Result < ( ) > {
632+ self . require ( a, false ) ?;
633+ Ok ( ( ) )
634+ }
635+
628636 /// Commits our cached account changes into the trie.
629637 #[ cfg_attr( feature="dev" , allow( match_ref_pats) ) ]
630638 #[ cfg_attr( feature="dev" , allow( needless_borrow) ) ]
@@ -681,11 +689,11 @@ impl<B: Backend> State<B> {
681689 pub fn kill_garbage ( & mut self , remove_empty_touched : bool , min_balance : & Option < U256 > , kill_contracts : bool ) -> trie:: Result < ( ) > {
682690 let to_kill: HashSet < _ > = {
683691 self . cache . borrow ( ) . iter ( ) . filter_map ( |( address, ref entry) |
684- if ( entry. is_dirty ( ) || address == & RIPEMD_BUILTIN ) &&
685- ( ( remove_empty_touched && entry. is_null ( ) )
686- || min_balance. map_or ( false , |ref balance| entry. account . as_ref ( ) . map_or ( false , |account|
687- ( account. is_basic ( ) || kill_contracts)
688- && account. balance ( ) < balance && entry. clean_balance . as_ref ( ) . map_or ( false , |b| account. balance ( ) < b) ) ) ) {
692+ if ( entry. is_dirty ( ) || address == & RIPEMD_BUILTIN ) && // Check any modified accounts and 0x3 additionally.
693+ ( ( remove_empty_touched && entry. is_null ( ) ) // Remove all empty touched accounts.
694+ || min_balance. map_or ( false , |ref balance| entry. account . as_ref ( ) . map_or ( false , |account|
695+ ( account. is_basic ( ) || kill_contracts) // Remove all basic and optionally contract accounts where balance has been decreased.
696+ && account. balance ( ) < balance && entry. old_balance . as_ref ( ) . map_or ( false , |b| account. balance ( ) < b) ) ) ) {
689697
690698 Some ( address. clone ( ) )
691699 } else { None } ) . collect ( )
0 commit comments