github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/core/state/managed_state.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package state 13 14 import ( 15 "sync" 16 17 "github.com/Sberex/go-sberex/common" 18 ) 19 20 type account struct { 21 stateObject *stateObject 22 nstart uint64 23 nonces []bool 24 } 25 26 type ManagedState struct { 27 *StateDB 28 29 mu sync.RWMutex 30 31 accounts map[common.Address]*account 32 } 33 34 // ManagedState returns a new managed state with the statedb as it's backing layer 35 func ManageState(statedb *StateDB) *ManagedState { 36 return &ManagedState{ 37 StateDB: statedb.Copy(), 38 accounts: make(map[common.Address]*account), 39 } 40 } 41 42 // SetState sets the backing layer of the managed state 43 func (ms *ManagedState) SetState(statedb *StateDB) { 44 ms.mu.Lock() 45 defer ms.mu.Unlock() 46 ms.StateDB = statedb 47 } 48 49 // RemoveNonce removed the nonce from the managed state and all future pending nonces 50 func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { 51 if ms.hasAccount(addr) { 52 ms.mu.Lock() 53 defer ms.mu.Unlock() 54 55 account := ms.getAccount(addr) 56 if n-account.nstart <= uint64(len(account.nonces)) { 57 reslice := make([]bool, n-account.nstart) 58 copy(reslice, account.nonces[:n-account.nstart]) 59 account.nonces = reslice 60 } 61 } 62 } 63 64 // NewNonce returns the new canonical nonce for the managed account 65 func (ms *ManagedState) NewNonce(addr common.Address) uint64 { 66 ms.mu.Lock() 67 defer ms.mu.Unlock() 68 69 account := ms.getAccount(addr) 70 for i, nonce := range account.nonces { 71 if !nonce { 72 return account.nstart + uint64(i) 73 } 74 } 75 account.nonces = append(account.nonces, true) 76 77 return uint64(len(account.nonces)-1) + account.nstart 78 } 79 80 // GetNonce returns the canonical nonce for the managed or unmanaged account. 81 // 82 // Because GetNonce mutates the DB, we must take a write lock. 83 func (ms *ManagedState) GetNonce(addr common.Address) uint64 { 84 ms.mu.Lock() 85 defer ms.mu.Unlock() 86 87 if ms.hasAccount(addr) { 88 account := ms.getAccount(addr) 89 return uint64(len(account.nonces)) + account.nstart 90 } else { 91 return ms.StateDB.GetNonce(addr) 92 } 93 } 94 95 // SetNonce sets the new canonical nonce for the managed state 96 func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { 97 ms.mu.Lock() 98 defer ms.mu.Unlock() 99 100 so := ms.GetOrNewStateObject(addr) 101 so.SetNonce(nonce) 102 103 ms.accounts[addr] = newAccount(so) 104 } 105 106 // HasAccount returns whether the given address is managed or not 107 func (ms *ManagedState) HasAccount(addr common.Address) bool { 108 ms.mu.RLock() 109 defer ms.mu.RUnlock() 110 return ms.hasAccount(addr) 111 } 112 113 func (ms *ManagedState) hasAccount(addr common.Address) bool { 114 _, ok := ms.accounts[addr] 115 return ok 116 } 117 118 // populate the managed state 119 func (ms *ManagedState) getAccount(addr common.Address) *account { 120 if account, ok := ms.accounts[addr]; !ok { 121 so := ms.GetOrNewStateObject(addr) 122 ms.accounts[addr] = newAccount(so) 123 } else { 124 // Always make sure the state account nonce isn't actually higher 125 // than the tracked one. 126 so := ms.StateDB.getStateObject(addr) 127 if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() { 128 ms.accounts[addr] = newAccount(so) 129 } 130 131 } 132 133 return ms.accounts[addr] 134 } 135 136 func newAccount(so *stateObject) *account { 137 return &account{so, so.Nonce(), nil} 138 }