github.com/ylsGit/go-ethereum@v1.6.5/core/state/journal.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"math/big"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  )
    24  
    25  type journalEntry interface {
    26  	undo(*StateDB)
    27  }
    28  
    29  type journal []journalEntry
    30  
    31  type (
    32  	// Changes to the account trie.
    33  	createObjectChange struct {
    34  		account *common.Address
    35  	}
    36  	resetObjectChange struct {
    37  		prev *stateObject
    38  	}
    39  	suicideChange struct {
    40  		account     *common.Address
    41  		prev        bool // whether account had already suicided
    42  		prevbalance *big.Int
    43  	}
    44  
    45  	// Changes to individual accounts.
    46  	balanceChange struct {
    47  		account *common.Address
    48  		prev    *big.Int
    49  	}
    50  	nonceChange struct {
    51  		account *common.Address
    52  		prev    uint64
    53  	}
    54  	storageChange struct {
    55  		account       *common.Address
    56  		key, prevalue common.Hash
    57  	}
    58  	codeChange struct {
    59  		account            *common.Address
    60  		prevcode, prevhash []byte
    61  	}
    62  
    63  	// Changes to other state values.
    64  	refundChange struct {
    65  		prev *big.Int
    66  	}
    67  	addLogChange struct {
    68  		txhash common.Hash
    69  	}
    70  	addPreimageChange struct {
    71  		hash common.Hash
    72  	}
    73  	touchChange struct {
    74  		account   *common.Address
    75  		prev      bool
    76  		prevDirty bool
    77  	}
    78  )
    79  
    80  func (ch createObjectChange) undo(s *StateDB) {
    81  	delete(s.stateObjects, *ch.account)
    82  	delete(s.stateObjectsDirty, *ch.account)
    83  }
    84  
    85  func (ch resetObjectChange) undo(s *StateDB) {
    86  	s.setStateObject(ch.prev)
    87  }
    88  
    89  func (ch suicideChange) undo(s *StateDB) {
    90  	obj := s.getStateObject(*ch.account)
    91  	if obj != nil {
    92  		obj.suicided = ch.prev
    93  		obj.setBalance(ch.prevbalance)
    94  		// if the object wasn't suicided before, remove
    95  		// it from the list of destructed objects as well.
    96  		if !obj.suicided {
    97  			delete(s.stateObjectsDestructed, *ch.account)
    98  		}
    99  	}
   100  }
   101  
   102  var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
   103  
   104  func (ch touchChange) undo(s *StateDB) {
   105  	if !ch.prev && *ch.account != ripemd {
   106  		s.getStateObject(*ch.account).touched = ch.prev
   107  		if !ch.prevDirty {
   108  			delete(s.stateObjectsDirty, *ch.account)
   109  		}
   110  	}
   111  }
   112  
   113  func (ch balanceChange) undo(s *StateDB) {
   114  	s.getStateObject(*ch.account).setBalance(ch.prev)
   115  }
   116  
   117  func (ch nonceChange) undo(s *StateDB) {
   118  	s.getStateObject(*ch.account).setNonce(ch.prev)
   119  }
   120  
   121  func (ch codeChange) undo(s *StateDB) {
   122  	s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
   123  }
   124  
   125  func (ch storageChange) undo(s *StateDB) {
   126  	s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
   127  }
   128  
   129  func (ch refundChange) undo(s *StateDB) {
   130  	s.refund = ch.prev
   131  }
   132  
   133  func (ch addLogChange) undo(s *StateDB) {
   134  	logs := s.logs[ch.txhash]
   135  	if len(logs) == 1 {
   136  		delete(s.logs, ch.txhash)
   137  	} else {
   138  		s.logs[ch.txhash] = logs[:len(logs)-1]
   139  	}
   140  }
   141  
   142  func (ch addPreimageChange) undo(s *StateDB) {
   143  	delete(s.preimages, ch.hash)
   144  }