github.com/4000d/go-ethereum@v1.8.2-0.20180223170251-423c8bb1d821/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 uint64
    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  	}
    95  }
    96  
    97  var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
    98  
    99  func (ch touchChange) undo(s *StateDB) {
   100  	if !ch.prev && *ch.account != ripemd {
   101  		s.getStateObject(*ch.account).touched = ch.prev
   102  		if !ch.prevDirty {
   103  			delete(s.stateObjectsDirty, *ch.account)
   104  		}
   105  	}
   106  }
   107  
   108  func (ch balanceChange) undo(s *StateDB) {
   109  	s.getStateObject(*ch.account).setBalance(ch.prev)
   110  }
   111  
   112  func (ch nonceChange) undo(s *StateDB) {
   113  	s.getStateObject(*ch.account).setNonce(ch.prev)
   114  }
   115  
   116  func (ch codeChange) undo(s *StateDB) {
   117  	s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
   118  }
   119  
   120  func (ch storageChange) undo(s *StateDB) {
   121  	s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
   122  }
   123  
   124  func (ch refundChange) undo(s *StateDB) {
   125  	s.refund = ch.prev
   126  }
   127  
   128  func (ch addLogChange) undo(s *StateDB) {
   129  	logs := s.logs[ch.txhash]
   130  	if len(logs) == 1 {
   131  		delete(s.logs, ch.txhash)
   132  	} else {
   133  		s.logs[ch.txhash] = logs[:len(logs)-1]
   134  	}
   135  	s.logSize--
   136  }
   137  
   138  func (ch addPreimageChange) undo(s *StateDB) {
   139  	delete(s.preimages, ch.hash)
   140  }