github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/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 MiningReward, 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/insight-chain/inb-go/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 case of an execution 37 // exception or revertal request. 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 create 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 prev *stateObject 94 } 95 suicideChange struct { 96 account *common.Address 97 prev bool // whether account had already suicided 98 prevbalance *big.Int 99 } 100 101 // Changes to individual accounts. 102 balanceChange struct { 103 account *common.Address 104 prev *big.Int 105 } 106 resChange struct { 107 account *common.Address 108 Used *big.Int 109 Usable *big.Int 110 StakingValue *big.Int 111 } 112 //Resource by zc 113 nonceChange struct { 114 account *common.Address 115 prev uint64 116 } 117 118 //achilles0718 regular mortgagtion 119 stakingChange struct { 120 account *common.Address 121 stakings []Staking 122 } 123 unStakingChange struct { 124 account *common.Address 125 unStaking UnStaking 126 } 127 dateChange struct { 128 account *common.Address 129 prev *big.Int 130 } 131 132 storageChange struct { 133 account *common.Address 134 key, prevalue common.Hash 135 } 136 codeChange struct { 137 account *common.Address 138 prevcode, prevhash []byte 139 } 140 141 // Changes to other state values. 142 refundChange struct { 143 prev uint64 144 } 145 addLogChange struct { 146 txhash common.Hash 147 } 148 addPreimageChange struct { 149 hash common.Hash 150 } 151 touchChange struct { 152 account *common.Address 153 prev bool 154 prevDirty bool 155 } 156 ) 157 158 //achilles0722 redeem t+3 159 func (ch unStakingChange) revert(s *StateDB) { 160 s.getStateObject(*ch.account).setUnStaking(ch.unStaking) 161 } 162 163 func (ch unStakingChange) dirtied() *common.Address { 164 return ch.account 165 } 166 167 func (ch stakingChange) revert(s *StateDB) { 168 s.getStateObject(*ch.account).setStakings(ch.stakings) 169 } 170 171 func (ch stakingChange) dirtied() *common.Address { 172 return ch.account 173 } 174 175 func (ch dateChange) revert(s *StateDB) { 176 s.getStateObject(*ch.account).SetDate(ch.prev) 177 } 178 179 func (ch dateChange) dirtied() *common.Address { 180 return ch.account 181 } 182 183 func (ch createObjectChange) revert(s *StateDB) { 184 delete(s.stateObjects, *ch.account) 185 delete(s.stateObjectsDirty, *ch.account) 186 } 187 188 func (ch createObjectChange) dirtied() *common.Address { 189 return ch.account 190 } 191 192 func (ch resetObjectChange) revert(s *StateDB) { 193 s.setStateObject(ch.prev) 194 } 195 196 //Resource by zc 197 func (ch resChange) revert(s *StateDB) { 198 s.getStateObject(*ch.account).setRes(ch.Used, ch.Usable, ch.StakingValue) 199 } 200 201 func (ch resChange) dirtied() *common.Address { 202 return ch.account 203 } 204 205 //Resource by zc 206 207 func (ch resetObjectChange) dirtied() *common.Address { 208 return nil 209 } 210 211 func (ch suicideChange) revert(s *StateDB) { 212 obj := s.getStateObject(*ch.account) 213 if obj != nil { 214 obj.suicided = ch.prev 215 obj.setBalance(ch.prevbalance) 216 } 217 } 218 219 func (ch suicideChange) dirtied() *common.Address { 220 return ch.account 221 } 222 223 var ripemd = common.HexToAddress("0000000000000000000000000000000000000003") 224 225 func (ch touchChange) revert(s *StateDB) { 226 } 227 228 func (ch touchChange) dirtied() *common.Address { 229 return ch.account 230 } 231 232 func (ch balanceChange) revert(s *StateDB) { 233 s.getStateObject(*ch.account).setBalance(ch.prev) 234 } 235 236 func (ch balanceChange) dirtied() *common.Address { 237 return ch.account 238 } 239 240 func (ch nonceChange) revert(s *StateDB) { 241 s.getStateObject(*ch.account).setNonce(ch.prev) 242 } 243 244 func (ch nonceChange) dirtied() *common.Address { 245 return ch.account 246 } 247 248 func (ch codeChange) revert(s *StateDB) { 249 s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) 250 } 251 252 func (ch codeChange) dirtied() *common.Address { 253 return ch.account 254 } 255 256 func (ch storageChange) revert(s *StateDB) { 257 s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) 258 } 259 260 func (ch storageChange) dirtied() *common.Address { 261 return ch.account 262 } 263 264 func (ch refundChange) revert(s *StateDB) { 265 s.refund = ch.prev 266 } 267 268 func (ch refundChange) dirtied() *common.Address { 269 return nil 270 } 271 272 func (ch addLogChange) revert(s *StateDB) { 273 logs := s.logs[ch.txhash] 274 if len(logs) == 1 { 275 delete(s.logs, ch.txhash) 276 } else { 277 s.logs[ch.txhash] = logs[:len(logs)-1] 278 } 279 s.logSize-- 280 } 281 282 func (ch addLogChange) dirtied() *common.Address { 283 return nil 284 } 285 286 func (ch addPreimageChange) revert(s *StateDB) { 287 delete(s.preimages, ch.hash) 288 } 289 290 func (ch addPreimageChange) dirtied() *common.Address { 291 return nil 292 }