github.com/annchain/OG@v0.0.9/arefactor_core/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 og_types "github.com/annchain/OG/arefactor/og_interface" 21 "github.com/annchain/OG/common/math" 22 ) 23 24 const TokenNotDirtied int32 = -1 25 26 // journalEntry is a modification entry in the state change journal that can be 27 // reverted on demand. 28 type JournalEntry interface { 29 // revert undoes the changes introduced by this journal entry. 30 Revert(db *StateDB) 31 32 // dirtied returns the address modified by this journal entry. 33 Dirtied() og_types.Address 34 35 // TokenDirtied returns the Token ID modified by this journal entry. 36 TokenDirtied() int32 37 } 38 39 // journal contains the list of state modifications applied since the last state 40 // commit. These are tracked to be able to be reverted in case of an execution 41 // exception or revertal request. 42 type journal struct { 43 entries []JournalEntry // Current changes tracked by the journal 44 dirties map[og_types.Address]int // Dirty accounts and the number of changes 45 tokenDirties map[int32]int // Dirty tokens and the number of changes. 46 } 47 48 // newJournal create a new initialized journal. 49 func newJournal() *journal { 50 return &journal{ 51 dirties: make(map[og_types.Address]int), 52 tokenDirties: make(map[int32]int), 53 } 54 } 55 56 // append inserts a new modification entry to the end of the change journal. 57 func (j *journal) append(entry JournalEntry) { 58 j.entries = append(j.entries, entry) 59 if addr := entry.Dirtied(); addr != nil { 60 j.dirties[addr]++ 61 } 62 if tokenID := entry.TokenDirtied(); tokenID > TokenNotDirtied { 63 j.tokenDirties[tokenID]++ 64 } 65 } 66 67 // revert undoes a batch of journalled modifications along with any reverted 68 // dirty handling too. 69 func (j *journal) revert(statedb *StateDB, snapshot int) { 70 for i := len(j.entries) - 1; i >= snapshot; i-- { 71 // Undo the changes made by the operation 72 j.entries[i].Revert(statedb) 73 74 // Drop any dirty tracking induced by the change 75 if addr := j.entries[i].Dirtied(); addr != nil { 76 if j.dirties[addr]--; j.dirties[addr] == 0 { 77 delete(j.dirties, addr) 78 } 79 } 80 if tokenID := j.entries[i].TokenDirtied(); tokenID > TokenNotDirtied { 81 if j.tokenDirties[tokenID]--; j.tokenDirties[tokenID] == 0 { 82 delete(j.tokenDirties, tokenID) 83 } 84 } 85 } 86 j.entries = j.entries[:snapshot] 87 } 88 89 // dirty explicitly sets an address to dirty, even if the change entries would 90 // otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD 91 // precompile consensus exception. 92 // func (j *journal) dirty(addr common.Address) { 93 // j.dirties[addr]++ 94 // } 95 96 // func (j *journal) tokenDirty(tokenID int32) { 97 // j.tokenDirties[tokenID]++ 98 // } 99 100 // length returns the current number of entries in the journal. 101 func (j *journal) length() int { 102 return len(j.entries) 103 } 104 105 type ( 106 // Changes to the account trie. 107 createObjectChange struct { 108 account og_types.Address 109 } 110 resetObjectChange struct { 111 account og_types.Address 112 prev *StateObject 113 } 114 suicideChange struct { 115 account og_types.Address 116 prev bool // whether account had already suicided 117 prevbalance BalanceSet 118 } 119 120 // Changes to individual accounts. 121 balanceChange struct { 122 account og_types.Address 123 tokenID int32 124 prev *math.BigInt 125 } 126 nonceChange struct { 127 account og_types.Address 128 prev uint64 129 } 130 storageChange struct { 131 account og_types.Address 132 key, prevalue og_types.Hash 133 } 134 codeChange struct { 135 account og_types.Address 136 prevcode, prevhash []byte 137 } 138 139 // Changes to other state values. 140 refundChange struct { 141 prev uint64 142 } 143 addLogChange struct { 144 txhash og_types.Hash 145 } 146 addPreimageChange struct { 147 hash og_types.Hash 148 } 149 touchChange struct { 150 account og_types.Address 151 prev bool 152 prevDirty bool 153 } 154 155 // Changes to token 156 createTokenChange struct { 157 prevLatestTokenID int32 158 tokenID int32 159 } 160 resetTokenChange struct { 161 tokenID int32 162 prev *TokenObject 163 } 164 reIssueChange struct { 165 tokenID int32 166 } 167 destroyChange struct { 168 tokenID int32 169 prevDestroyed bool 170 } 171 ) 172 173 func (ch createObjectChange) Revert(s *StateDB) { 174 delete(s.states, ch.account.AddressKey()) 175 delete(s.dirtyset, ch.account.AddressKey()) 176 } 177 178 func (ch createObjectChange) Dirtied() og_types.Address { 179 return ch.account 180 } 181 182 func (ch createObjectChange) TokenDirtied() int32 { 183 return TokenNotDirtied 184 } 185 186 func (ch resetObjectChange) Revert(s *StateDB) { 187 if ch.prev == nil { 188 delete(s.states, ch.account.AddressKey()) 189 } else { 190 s.states[ch.prev.address.AddressKey()] = ch.prev 191 } 192 } 193 194 func (ch resetObjectChange) Dirtied() og_types.Address { 195 return ch.prev.address 196 } 197 198 func (ch resetObjectChange) TokenDirtied() int32 { 199 return TokenNotDirtied 200 } 201 202 func (ch suicideChange) Revert(s *StateDB) { 203 stobj := s.getStateObject(ch.account) 204 if stobj != nil { 205 stobj.suicided = ch.prev 206 for k, v := range ch.prevbalance { 207 stobj.SetBalance(k, v) 208 } 209 } 210 } 211 212 func (ch suicideChange) Dirtied() og_types.Address { 213 return ch.account 214 } 215 216 func (ch suicideChange) TokenDirtied() int32 { 217 return TokenNotDirtied 218 } 219 220 func (ch touchChange) Revert(s *StateDB) { 221 } 222 223 func (ch touchChange) Dirtied() og_types.Address { 224 return ch.account 225 } 226 227 func (ch touchChange) TokenDirtied() int32 { 228 return TokenNotDirtied 229 } 230 231 func (ch balanceChange) Revert(s *StateDB) { 232 stobj := s.getStateObject(ch.account) 233 if stobj != nil { 234 stobj.setBalance(ch.tokenID, ch.prev) 235 } 236 } 237 238 func (ch balanceChange) Dirtied() og_types.Address { 239 return ch.account 240 } 241 242 func (ch balanceChange) TokenDirtied() int32 { 243 return TokenNotDirtied 244 } 245 246 func (ch nonceChange) Revert(s *StateDB) { 247 stobj := s.getStateObject(ch.account) 248 if stobj != nil { 249 stobj.setNonce(ch.prev) 250 } 251 } 252 253 func (ch nonceChange) Dirtied() og_types.Address { 254 return ch.account 255 } 256 257 func (ch nonceChange) TokenDirtied() int32 { 258 return TokenNotDirtied 259 } 260 261 func (ch codeChange) Revert(s *StateDB) { 262 stobj := s.getStateObject(ch.account) 263 if stobj != nil { 264 stobj.setCode(og_types.BytesToHash32(ch.prevhash), ch.prevcode) 265 } 266 } 267 268 func (ch codeChange) Dirtied() og_types.Address { 269 return ch.account 270 } 271 272 func (ch codeChange) TokenDirtied() int32 { 273 return TokenNotDirtied 274 } 275 276 func (ch storageChange) Revert(s *StateDB) { 277 stobj := s.getStateObject(ch.account) 278 if stobj != nil { 279 stobj.setState(ch.key, ch.prevalue) 280 } 281 } 282 283 func (ch storageChange) Dirtied() og_types.Address { 284 return ch.account 285 } 286 287 func (ch storageChange) TokenDirtied() int32 { 288 return TokenNotDirtied 289 } 290 291 func (ch refundChange) Revert(s *StateDB) { 292 s.refund = ch.prev 293 } 294 295 func (ch refundChange) Dirtied() og_types.Address { 296 return nil 297 } 298 299 func (ch refundChange) TokenDirtied() int32 { 300 return TokenNotDirtied 301 } 302 303 func (ch addLogChange) Revert(s *StateDB) { 304 // TODO 305 // Log not implemented yet. To avoid the error, comment 306 // this function. 307 308 // logs := s.logs[ch.txhash] 309 // if len(logs) == 1 { 310 // delete(s.logs, ch.txhash) 311 // } else { 312 // s.logs[ch.txhash] = logs[:len(logs)-1] 313 // } 314 // s.logSize-- 315 } 316 317 func (ch addLogChange) Dirtied() og_types.Address { 318 return nil 319 } 320 321 func (ch addLogChange) TokenDirtied() int32 { 322 return TokenNotDirtied 323 } 324 325 func (ch addPreimageChange) Revert(s *StateDB) { 326 // TODO 327 // preimage not implemented yet, comment temporarily this function 328 // to avoid compile error. 329 330 // delete(s.preimages, ch.hash) 331 } 332 333 func (ch addPreimageChange) Dirtied() og_types.Address { 334 return nil 335 } 336 337 func (ch addPreimageChange) TokenDirtied() int32 { 338 return TokenNotDirtied 339 } 340 341 func (ch createTokenChange) Revert(s *StateDB) { 342 s.latestTokenID = ch.prevLatestTokenID 343 delete(s.tokens, ch.tokenID) 344 delete(s.dirtyTokens, ch.tokenID) 345 } 346 347 func (ch createTokenChange) Dirtied() og_types.Address { 348 return nil 349 } 350 351 func (ch createTokenChange) TokenDirtied() int32 { 352 return ch.tokenID 353 } 354 355 func (ch resetTokenChange) Revert(s *StateDB) { 356 if ch.prev == nil { 357 delete(s.tokens, ch.tokenID) 358 } else { 359 s.tokens[ch.prev.TokenID] = ch.prev 360 } 361 } 362 363 func (ch resetTokenChange) Dirtied() og_types.Address { 364 return nil 365 } 366 367 func (ch resetTokenChange) TokenDirtied() int32 { 368 return ch.prev.TokenID 369 } 370 371 func (ch reIssueChange) Revert(s *StateDB) { 372 tkObj := s.getTokenObject(ch.tokenID) 373 if tkObj != nil { 374 tkObj.Issues = tkObj.Issues[:len(tkObj.Issues)-1] 375 } 376 } 377 378 func (ch reIssueChange) Dirtied() og_types.Address { 379 return nil 380 } 381 382 func (ch reIssueChange) TokenDirtied() int32 { 383 return ch.tokenID 384 } 385 386 func (ch destroyChange) Revert(s *StateDB) { 387 tkObj := s.getTokenObject(ch.tokenID) 388 if tkObj != nil { 389 tkObj.Destroyed = ch.prevDestroyed 390 } 391 } 392 393 func (ch destroyChange) Dirtied() og_types.Address { 394 return nil 395 } 396 397 func (ch destroyChange) TokenDirtied() int32 { 398 return ch.tokenID 399 }