managed_state.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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.RLock()
  45. defer ms.mu.RUnlock()
  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. if ms.HasAccount(addr) {
  58. account := ms.getAccount(addr)
  59. return uint64(len(account.nonces)) + account.nstart
  60. } else {
  61. return ms.StateDB.GetNonce(addr)
  62. }
  63. }
  64. // SetNonce sets the new canonical nonce for the managed state
  65. func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) {
  66. so := ms.GetOrNewStateObject(addr)
  67. so.SetNonce(nonce)
  68. ms.accounts[addr.Str()] = newAccount(so)
  69. }
  70. // HasAccount returns whether the given address is managed or not
  71. func (ms *ManagedState) HasAccount(addr common.Address) bool {
  72. _, ok := ms.accounts[addr.Str()]
  73. return ok
  74. }
  75. // populate the managed state
  76. func (ms *ManagedState) getAccount(addr common.Address) *account {
  77. straddr := addr.Str()
  78. if account, ok := ms.accounts[straddr]; !ok {
  79. so := ms.GetOrNewStateObject(addr)
  80. ms.accounts[straddr] = newAccount(so)
  81. } else {
  82. // Always make sure the state account nonce isn't actually higher
  83. // than the tracked one.
  84. so := ms.StateDB.GetStateObject(addr)
  85. if so != nil && uint64(len(account.nonces))+account.nstart < so.nonce {
  86. ms.accounts[straddr] = newAccount(so)
  87. }
  88. }
  89. return ms.accounts[straddr]
  90. }
  91. func newAccount(so *StateObject) *account {
  92. return &account{so, so.nonce, nil}
  93. }