github.com/theQRL/go-zond@v0.2.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  // length returns the current number of entries in the journal.
    76  func (j *journal) length() int {
    77  	return len(j.entries)
    78  }
    79  
    80  type (
    81  	// Changes to the account trie.
    82  	createObjectChange struct {
    83  		account *common.Address
    84  	}
    85  	resetObjectChange struct {
    86  		account      *common.Address
    87  		prev         *stateObject
    88  		prevdestruct bool
    89  		prevAccount  []byte
    90  		prevStorage  map[common.Hash][]byte
    91  
    92  		prevAccountOriginExist bool
    93  		prevAccountOrigin      []byte
    94  		prevStorageOrigin      map[common.Hash][]byte
    95  	}
    96  
    97  	// Changes to individual accounts.
    98  	balanceChange struct {
    99  		account *common.Address
   100  		prev    *big.Int
   101  	}
   102  	nonceChange struct {
   103  		account *common.Address
   104  		prev    uint64
   105  	}
   106  	storageChange struct {
   107  		account       *common.Address
   108  		key, prevalue common.Hash
   109  	}
   110  	codeChange struct {
   111  		account            *common.Address
   112  		prevcode, prevhash []byte
   113  	}
   114  
   115  	// Changes to other state values.
   116  	refundChange struct {
   117  		prev uint64
   118  	}
   119  	addLogChange struct {
   120  		txhash common.Hash
   121  	}
   122  	addPreimageChange struct {
   123  		hash common.Hash
   124  	}
   125  	touchChange struct {
   126  		account *common.Address
   127  	}
   128  	// Changes to the access list
   129  	accessListAddAccountChange struct {
   130  		address *common.Address
   131  	}
   132  	accessListAddSlotChange struct {
   133  		address *common.Address
   134  		slot    *common.Hash
   135  	}
   136  )
   137  
   138  func (ch createObjectChange) revert(s *StateDB) {
   139  	delete(s.stateObjects, *ch.account)
   140  	delete(s.stateObjectsDirty, *ch.account)
   141  }
   142  
   143  func (ch createObjectChange) dirtied() *common.Address {
   144  	return ch.account
   145  }
   146  
   147  func (ch resetObjectChange) revert(s *StateDB) {
   148  	s.setStateObject(ch.prev)
   149  	if !ch.prevdestruct {
   150  		delete(s.stateObjectsDestruct, ch.prev.address)
   151  	}
   152  	if ch.prevAccount != nil {
   153  		s.accounts[ch.prev.addrHash] = ch.prevAccount
   154  	}
   155  	if ch.prevStorage != nil {
   156  		s.storages[ch.prev.addrHash] = ch.prevStorage
   157  	}
   158  	if ch.prevAccountOriginExist {
   159  		s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
   160  	}
   161  	if ch.prevStorageOrigin != nil {
   162  		s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
   163  	}
   164  }
   165  
   166  func (ch resetObjectChange) dirtied() *common.Address {
   167  	return ch.account
   168  }
   169  
   170  func (ch touchChange) revert(s *StateDB) {
   171  }
   172  
   173  func (ch touchChange) dirtied() *common.Address {
   174  	return ch.account
   175  }
   176  
   177  func (ch balanceChange) revert(s *StateDB) {
   178  	s.getStateObject(*ch.account).setBalance(ch.prev)
   179  }
   180  
   181  func (ch balanceChange) dirtied() *common.Address {
   182  	return ch.account
   183  }
   184  
   185  func (ch nonceChange) revert(s *StateDB) {
   186  	s.getStateObject(*ch.account).setNonce(ch.prev)
   187  }
   188  
   189  func (ch nonceChange) dirtied() *common.Address {
   190  	return ch.account
   191  }
   192  
   193  func (ch codeChange) revert(s *StateDB) {
   194  	s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
   195  }
   196  
   197  func (ch codeChange) dirtied() *common.Address {
   198  	return ch.account
   199  }
   200  
   201  func (ch storageChange) revert(s *StateDB) {
   202  	s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
   203  }
   204  
   205  func (ch storageChange) dirtied() *common.Address {
   206  	return ch.account
   207  }
   208  
   209  func (ch refundChange) revert(s *StateDB) {
   210  	s.refund = ch.prev
   211  }
   212  
   213  func (ch refundChange) dirtied() *common.Address {
   214  	return nil
   215  }
   216  
   217  func (ch addLogChange) revert(s *StateDB) {
   218  	logs := s.logs[ch.txhash]
   219  	if len(logs) == 1 {
   220  		delete(s.logs, ch.txhash)
   221  	} else {
   222  		s.logs[ch.txhash] = logs[:len(logs)-1]
   223  	}
   224  	s.logSize--
   225  }
   226  
   227  func (ch addLogChange) dirtied() *common.Address {
   228  	return nil
   229  }
   230  
   231  func (ch addPreimageChange) revert(s *StateDB) {
   232  	delete(s.preimages, ch.hash)
   233  }
   234  
   235  func (ch addPreimageChange) dirtied() *common.Address {
   236  	return nil
   237  }
   238  
   239  func (ch accessListAddAccountChange) revert(s *StateDB) {
   240  	/*
   241  		One important invariant here, is that whenever a (addr, slot) is added, if the
   242  		addr is not already present, the add causes two journal entries:
   243  		- one for the address,
   244  		- one for the (address,slot)
   245  		Therefore, when unrolling the change, we can always blindly delete the
   246  		(addr) at this point, since no storage adds can remain when come upon
   247  		a single (addr) change.
   248  	*/
   249  	s.accessList.DeleteAddress(*ch.address)
   250  }
   251  
   252  func (ch accessListAddAccountChange) dirtied() *common.Address {
   253  	return nil
   254  }
   255  
   256  func (ch accessListAddSlotChange) revert(s *StateDB) {
   257  	s.accessList.DeleteSlot(*ch.address, *ch.slot)
   258  }
   259  
   260  func (ch accessListAddSlotChange) dirtied() *common.Address {
   261  	return nil
   262  }