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 }