diff --git a/core/state/state_object.go b/core/state/state_object.go index f6c0fbbff8..9c8231e79c 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -523,9 +523,11 @@ func (s *stateObject) updateTrie() (Trie, error) { if len(value) == 0 { err := tr.DeleteStorage(s.address, key[:]) if path, ok := trie.ParseExpiredNodeErr(err); ok { - touchExpiredStorage[key] = value - if _, err = tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key); err != nil { - s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, err)) + _, reviveErr := tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key) + if reviveErr != nil { + s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, reviveErr)) + } else { + touchExpiredStorage[key] = value } } else if err != nil { s.db.setError(fmt.Errorf("updateTrie DeleteStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) @@ -535,9 +537,11 @@ func (s *stateObject) updateTrie() (Trie, error) { } else { err := tr.UpdateStorage(s.address, key[:], value) if path, ok := trie.ParseExpiredNodeErr(err); ok { - touchExpiredStorage[key] = value - if _, err = tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key); err != nil { - s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, err)) + _, reviveErr := tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key) + if reviveErr != nil { + s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, reviveErr)) + } else { + touchExpiredStorage[key] = value } } else if err != nil { s.db.setError(fmt.Errorf("updateTrie UpdateStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) @@ -550,17 +554,39 @@ func (s *stateObject) updateTrie() (Trie, error) { } // re-execute touched expired storage - for key, value := range touchExpiredStorage { - if len(value) == 0 { - if err := tr.DeleteStorage(s.address, key[:]); err != nil { - s.db.setError(fmt.Errorf("updateTrie DeleteStorage in touchExpiredStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) - } - //log.Debug("updateTrie DeleteStorage in touchExpiredStorage", "contract", s.address, "key", key, "epoch", s.db.Epoch(), "value", value, "tr.epoch", tr.Epoch(), "err", err, "tr", fmt.Sprintf("%p", tr), "ins", fmt.Sprintf("%p", s)) - } else { - if err := tr.UpdateStorage(s.address, key[:], value); err != nil { - s.db.setError(fmt.Errorf("updateTrie UpdateStorage in touchExpiredStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) + if s.db.EnableExpire() { + for len(touchExpiredStorage) > 0 { + nextRevive := make(map[common.Hash][]byte, len(touchExpiredStorage)) + for key, value := range touchExpiredStorage { + if len(value) == 0 { + err := tr.DeleteStorage(s.address, key[:]) + if path, ok := trie.ParseExpiredNodeErr(err); ok { + _, reviveErr := tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key) + if reviveErr != nil { + s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, reviveErr)) + } else { + nextRevive[key] = value + } + } else if err != nil { + s.db.setError(fmt.Errorf("updateTrie DeleteStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) + } + //log.Debug("updateTrie DeleteStorage in touchExpiredStorage", "contract", s.address, "key", key, "epoch", s.db.Epoch(), "value", value, "tr.epoch", tr.Epoch(), "err", err, "tr", fmt.Sprintf("%p", tr), "ins", fmt.Sprintf("%p", s)) + } else { + err := tr.UpdateStorage(s.address, key[:], value) + if path, ok := trie.ParseExpiredNodeErr(err); ok { + _, reviveErr := tryReviveState(s.db.expiryMeta, s.address, s.data.Root, tr, path, key) + if reviveErr != nil { + s.db.setError(fmt.Errorf("updateTrie DeleteStorage tryReviveState err, contract: %v, key: %v, path: %v, err: %v", s.address, key, path, reviveErr)) + } else { + nextRevive[key] = value + } + } else if err != nil { + s.db.setError(fmt.Errorf("updateTrie UpdateStorage err, contract: %v, key: %v, err: %v", s.address, key, err)) + } + //log.Debug("updateTrie UpdateStorage in touchExpiredStorage", "contract", s.address, "key", key, "epoch", s.db.Epoch(), "value", value, "tr.epoch", tr.Epoch(), "err", err, "tr", fmt.Sprintf("%p", tr), "ins", fmt.Sprintf("%p", s)) + } } - //log.Debug("updateTrie UpdateStorage in touchExpiredStorage", "contract", s.address, "key", key, "epoch", s.db.Epoch(), "value", value, "tr.epoch", tr.Epoch(), "err", err, "tr", fmt.Sprintf("%p", tr), "ins", fmt.Sprintf("%p", s)) + touchExpiredStorage = nextRevive } } }()