journal.go 7.2 KB

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