github.com/theQRL/go-zond@v0.1.1/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/theQRL/go-zond/common"
    23  )
    24  
    25  // journalEntry is a modification entry in the state change journal that can be
    26  // reverted on demand.
    27  type journalEntry interface {
    28  	// revert undoes the changes introduced by this journal entry.
    29  	revert(*StateDB)
    30  
    31  	// dirtied returns the Ethereum address modified by this journal entry.
    32  	dirtied() *common.Address
    33  }
    34  
    35  // journal contains the list of state modifications applied since the last state
    36  // commit. These are tracked to be able to be reverted in the case of an execution
    37  // exception or request for reversal.
    38  type journal struct {
    39  	entries []journalEntry         // Current changes tracked by the journal
    40  	dirties map[common.Address]int // Dirty accounts and the number of changes
    41  }
    42  
    43  // newJournal creates a new initialized journal.
    44  func newJournal() *journal {
    45  	return &journal{
    46  		dirties: make(map[common.Address]int),
    47  	}
    48  }
    49  
    50  // append inserts a new modification entry to the end of the change journal.
    51  func (j *journal) append(entry journalEntry) {
    52  	j.entries = append(j.entries, entry)
    53  	if addr := entry.dirtied(); addr != nil {
    54  		j.dirties[*addr]++
    55  	}
    56  }
    57  
    58  // revert undoes a batch of journalled modifications along with any reverted
    59  // dirty handling too.
    60  func (j *journal) revert(statedb *StateDB, snapshot int) {
    61  	for i := len(j.entries) - 1; i >= snapshot; i-- {
    62  		// Undo the changes made by the operation
    63  		j.entries[i].revert(statedb)
    64  
    65  		// Drop any dirty tracking induced by the change
    66  		if addr := j.entries[i].dirtied(); addr != nil {
    67  			if j.dirties[*addr]--; j.dirties[*addr] == 0 {
    68  				delete(j.dirties, *addr)
    69  			}
    70  		}
    71  	}
    72  	j.entries = j.entries[:snapshot]
    73  }
    74  
    75  // dirty explicitly sets an address to dirty, even if the change entries would
    76  // otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
    77  // precompile consensus exception.
    78  func (j *journal) dirty(addr common.Address) {
    79  	j.dirties[addr]++
    80  }
    81  
    82  // length returns the current number of entries in the journal.
    83  func (j *journal) length() int {
    84  	return len(j.entries)
    85  }
    86  
    87  type (
    88  	// Changes to the account trie.
    89  	createObjectChange struct {
    90  		account *common.Address
    91  	}
    92  	resetObjectChange struct {
    93  		account      *common.Address
    94  		prev         *stateObject
    95  		prevdestruct bool
    96  		prevAccount  []byte
    97  		prevStorage  map[common.Hash][]byte
    98  
    99  		prevAccountOriginExist bool
   100  		prevAccountOrigin      []byte
   101  		prevStorageOrigin      map[common.Hash][]byte
   102  	}
   103  	selfDestructChange struct {
   104  		account     *common.Address
   105  		prev        bool // whether account had already self-destructed
   106  		prevbalance *big.Int
   107  	}
   108  
   109  	// Changes to individual accounts.
   110  	balanceChange struct {
   111  		account *common.Address
   112  		prev    *big.Int
   113  	}
   114  	nonceChange struct {
   115  		account *common.Address
   116  		prev    uint64
   117  	}
   118  	storageChange struct {
   119  		account       *common.Address
   120  		key, prevalue common.Hash
   121  	}
   122  	codeChange struct {
   123  		account            *common.Address
   124  		prevcode, prevhash []byte
   125  	}
   126  
   127  	// Changes to other state values.
   128  	refundChange struct {
   129  		prev uint64
   130  	}
   131  	addLogChange struct {
   132  		txhash common.Hash
   133  	}
   134  	addPreimageChange struct {
   135  		hash common.Hash
   136  	}
   137  	touchChange struct {
   138  		account *common.Address
   139  	}
   140  	// Changes to the access list
   141  	accessListAddAccountChange struct {
   142  		address *common.Address
   143  	}
   144  	accessListAddSlotChange struct {
   145  		address *common.Address
   146  		slot    *common.Hash
   147  	}
   148  
   149  	transientStorageChange struct {
   150  		account       *common.Address
   151  		key, prevalue common.Hash
   152  	}
   153  )
   154  
   155  func (ch createObjectChange) revert(s *StateDB) {
   156  	delete(s.stateObjects, *ch.account)
   157  	delete(s.stateObjectsDirty, *ch.account)
   158  }
   159  
   160  func (ch createObjectChange) dirtied() *common.Address {
   161  	return ch.account
   162  }
   163  
   164  func (ch resetObjectChange) revert(s *StateDB) {
   165  	s.setStateObject(ch.prev)
   166  	if !ch.prevdestruct {
   167  		delete(s.stateObjectsDestruct, ch.prev.address)
   168  	}
   169  	if ch.prevAccount != nil {
   170  		s.accounts[ch.prev.addrHash] = ch.prevAccount
   171  	}
   172  	if ch.prevStorage != nil {
   173  		s.storages[ch.prev.addrHash] = ch.prevStorage
   174  	}
   175  	if ch.prevAccountOriginExist {
   176  		s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
   177  	}
   178  	if ch.prevStorageOrigin != nil {
   179  		s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
   180  	}
   181  }
   182  
   183  func (ch resetObjectChange) dirtied() *common.Address {
   184  	return ch.account
   185  }
   186  
   187  func (ch selfDestructChange) revert(s *StateDB) {
   188  	obj := s.getStateObject(*ch.account)
   189  	if obj != nil {
   190  		obj.selfDestructed = ch.prev
   191  		obj.setBalance(ch.prevbalance)
   192  	}
   193  }
   194  
   195  func (ch selfDestructChange) dirtied() *common.Address {
   196  	return ch.account
   197  }
   198  
   199  var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
   200  
   201  func (ch touchChange) revert(s *StateDB) {
   202  }
   203  
   204  func (ch touchChange) dirtied() *common.Address {
   205  	return ch.account
   206  }
   207  
   208  func (ch balanceChange) revert(s *StateDB) {
   209  	s.getStateObject(*ch.account).setBalance(ch.prev)
   210  }
   211  
   212  func (ch balanceChange) dirtied() *common.Address {
   213  	return ch.account
   214  }
   215  
   216  func (ch nonceChange) revert(s *StateDB) {
   217  	s.getStateObject(*ch.account).setNonce(ch.prev)
   218  }
   219  
   220  func (ch nonceChange) dirtied() *common.Address {
   221  	return ch.account
   222  }
   223  
   224  func (ch codeChange) revert(s *StateDB) {
   225  	s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
   226  }
   227  
   228  func (ch codeChange) dirtied() *common.Address {
   229  	return ch.account
   230  }
   231  
   232  func (ch storageChange) revert(s *StateDB) {
   233  	s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
   234  }
   235  
   236  func (ch storageChange) dirtied() *common.Address {
   237  	return ch.account
   238  }
   239  
   240  func (ch transientStorageChange) revert(s *StateDB) {
   241  	s.setTransientState(*ch.account, ch.key, ch.prevalue)
   242  }
   243  
   244  func (ch transientStorageChange) dirtied() *common.Address {
   245  	return nil
   246  }
   247  
   248  func (ch refundChange) revert(s *StateDB) {
   249  	s.refund = ch.prev
   250  }
   251  
   252  func (ch refundChange) dirtied() *common.Address {
   253  	return nil
   254  }
   255  
   256  func (ch addLogChange) revert(s *StateDB) {
   257  	logs := s.logs[ch.txhash]
   258  	if len(logs) == 1 {
   259  		delete(s.logs, ch.txhash)
   260  	} else {
   261  		s.logs[ch.txhash] = logs[:len(logs)-1]
   262  	}
   263  	s.logSize--
   264  }
   265  
   266  func (ch addLogChange) dirtied() *common.Address {
   267  	return nil
   268  }
   269  
   270  func (ch addPreimageChange) revert(s *StateDB) {
   271  	delete(s.preimages, ch.hash)
   272  }
   273  
   274  func (ch addPreimageChange) dirtied() *common.Address {
   275  	return nil
   276  }
   277  
   278  func (ch accessListAddAccountChange) revert(s *StateDB) {
   279  	/*
   280  		One important invariant here, is that whenever a (addr, slot) is added, if the
   281  		addr is not already present, the add causes two journal entries:
   282  		- one for the address,
   283  		- one for the (address,slot)
   284  		Therefore, when unrolling the change, we can always blindly delete the
   285  		(addr) at this point, since no storage adds can remain when come upon
   286  		a single (addr) change.
   287  	*/
   288  	s.accessList.DeleteAddress(*ch.address)
   289  }
   290  
   291  func (ch accessListAddAccountChange) dirtied() *common.Address {
   292  	return nil
   293  }
   294  
   295  func (ch accessListAddSlotChange) revert(s *StateDB) {
   296  	s.accessList.DeleteSlot(*ch.address, *ch.slot)
   297  }
   298  
   299  func (ch accessListAddSlotChange) dirtied() *common.Address {
   300  	return nil
   301  }