managed_state.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package state
  2. import (
  3. "sync"
  4. "github.com/ethereum/go-ethereum/common"
  5. )
  6. type account struct {
  7. stateObject *StateObject
  8. nstart uint64
  9. nonces []bool
  10. }
  11. type ManagedState struct {
  12. *StateDB
  13. mu sync.RWMutex
  14. accounts map[string]*account
  15. }
  16. // ManagedState returns a new managed state with the statedb as it's backing layer
  17. func ManageState(statedb *StateDB) *ManagedState {
  18. return &ManagedState{
  19. StateDB: statedb,
  20. accounts: make(map[string]*account),
  21. }
  22. }
  23. // SetState sets the backing layer of the managed state
  24. func (ms *ManagedState) SetState(statedb *StateDB) {
  25. ms.mu.Lock()
  26. defer ms.mu.Unlock()
  27. ms.StateDB = statedb
  28. }
  29. // RemoveNonce removed the nonce from the managed state and all future pending nonces
  30. func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) {
  31. if ms.hasAccount(addr) {
  32. ms.mu.Lock()
  33. defer ms.mu.Unlock()
  34. account := ms.getAccount(addr)
  35. if n-account.nstart <= uint64(len(account.nonces)) {
  36. reslice := make([]bool, n-account.nstart)
  37. copy(reslice, account.nonces[:n-account.nstart])
  38. account.nonces = reslice
  39. }
  40. }
  41. }
  42. // NewNonce returns the new canonical nonce for the managed account
  43. func (ms *ManagedState) NewNonce(addr common.Address) uint64 {
  44. ms.mu.Lock()
  45. defer ms.mu.Unlock()
  46. account := ms.getAccount(addr)
  47. for i, nonce := range account.nonces {
  48. if !nonce {
  49. return account.nstart + uint64(i)
  50. }
  51. }
  52. account.nonces = append(account.nonces, true)
  53. return uint64(len(account.nonces)-1) + account.nstart
  54. }
  55. // GetNonce returns the canonical nonce for the managed or unmanged account
  56. func (ms *ManagedState) GetNonce(addr common.Address) uint64 {
  57. ms.mu.RLock()
  58. defer ms.mu.RUnlock()
  59. if ms.hasAccount(addr) {
  60. account := ms.getAccount(addr)
  61. return uint64(len(account.nonces)) + account.nstart
  62. } else {
  63. return ms.StateDB.GetNonce(addr)
  64. }
  65. }
  66. // SetNonce sets the new canonical nonce for the managed state
  67. func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) {
  68. ms.mu.Lock()
  69. defer ms.mu.Unlock()
  70. so := ms.GetOrNewStateObject(addr)
  71. so.SetNonce(nonce)
  72. ms.accounts[addr.Str()] = newAccount(so)
  73. }
  74. // HasAccount returns whether the given address is managed or not
  75. func (ms *ManagedState) HasAccount(addr common.Address) bool {
  76. ms.mu.RLock()
  77. defer ms.mu.RUnlock()
  78. return ms.hasAccount(addr)
  79. }
  80. func (ms *ManagedState) hasAccount(addr common.Address) bool {
  81. _, ok := ms.accounts[addr.Str()]
  82. return ok
  83. }
  84. // populate the managed state
  85. func (ms *ManagedState) getAccount(addr common.Address) *account {
  86. straddr := addr.Str()
  87. if account, ok := ms.accounts[straddr]; !ok {
  88. so := ms.GetOrNewStateObject(addr)
  89. ms.accounts[straddr] = newAccount(so)
  90. } else {
  91. // Always make sure the state account nonce isn't actually higher
  92. // than the tracked one.
  93. so := ms.StateDB.GetStateObject(addr)
  94. if so != nil && uint64(len(account.nonces))+account.nstart < so.nonce {
  95. ms.accounts[straddr] = newAccount(so)
  96. }
  97. }
  98. return ms.accounts[straddr]
  99. }
  100. func newAccount(so *StateObject) *account {
  101. return &account{so, so.nonce, nil}
  102. }