github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/state/managed_state.go (about) 1 package state 2 3 import ( 4 "sync" 5 6 "github.com/quickchainproject/quickchain/common" 7 ) 8 9 type account struct { 10 stateObject *stateObject 11 nstart uint64 12 nonces []bool 13 } 14 15 type ManagedState struct { 16 *StateDB 17 18 mu sync.RWMutex 19 20 accounts map[common.Address]*account 21 } 22 23 // ManagedState returns a new managed state with the statedb as it's backing layer 24 func ManageState(statedb *StateDB) *ManagedState { 25 return &ManagedState{ 26 StateDB: statedb.Copy(), 27 accounts: make(map[common.Address]*account), 28 } 29 } 30 31 // SetState sets the backing layer of the managed state 32 func (ms *ManagedState) SetState(statedb *StateDB) { 33 ms.mu.Lock() 34 defer ms.mu.Unlock() 35 ms.StateDB = statedb 36 } 37 38 // RemoveNonce removed the nonce from the managed state and all future pending nonces 39 func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { 40 if ms.hasAccount(addr) { 41 ms.mu.Lock() 42 defer ms.mu.Unlock() 43 44 account := ms.getAccount(addr) 45 if n-account.nstart <= uint64(len(account.nonces)) { 46 reslice := make([]bool, n-account.nstart) 47 copy(reslice, account.nonces[:n-account.nstart]) 48 account.nonces = reslice 49 } 50 } 51 } 52 53 // NewNonce returns the new canonical nonce for the managed account 54 func (ms *ManagedState) NewNonce(addr common.Address) uint64 { 55 ms.mu.Lock() 56 defer ms.mu.Unlock() 57 58 account := ms.getAccount(addr) 59 for i, nonce := range account.nonces { 60 if !nonce { 61 return account.nstart + uint64(i) 62 } 63 } 64 account.nonces = append(account.nonces, true) 65 66 return uint64(len(account.nonces)-1) + account.nstart 67 } 68 69 // GetNonce returns the canonical nonce for the managed or unmanaged account. 70 // 71 // Because GetNonce mutates the DB, we must take a write lock. 72 func (ms *ManagedState) GetNonce(addr common.Address) uint64 { 73 ms.mu.Lock() 74 defer ms.mu.Unlock() 75 76 if ms.hasAccount(addr) { 77 account := ms.getAccount(addr) 78 return uint64(len(account.nonces)) + account.nstart 79 } else { 80 return ms.StateDB.GetNonce(addr) 81 } 82 } 83 84 // SetNonce sets the new canonical nonce for the managed state 85 func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { 86 ms.mu.Lock() 87 defer ms.mu.Unlock() 88 89 so := ms.GetOrNewStateObject(addr) 90 so.SetNonce(nonce) 91 92 ms.accounts[addr] = newAccount(so) 93 } 94 95 // HasAccount returns whether the given address is managed or not 96 func (ms *ManagedState) HasAccount(addr common.Address) bool { 97 ms.mu.RLock() 98 defer ms.mu.RUnlock() 99 return ms.hasAccount(addr) 100 } 101 102 func (ms *ManagedState) hasAccount(addr common.Address) bool { 103 _, ok := ms.accounts[addr] 104 return ok 105 } 106 107 // populate the managed state 108 func (ms *ManagedState) getAccount(addr common.Address) *account { 109 if account, ok := ms.accounts[addr]; !ok { 110 so := ms.GetOrNewStateObject(addr) 111 ms.accounts[addr] = newAccount(so) 112 } else { 113 // Always make sure the state account nonce isn't actually higher 114 // than the tracked one. 115 so := ms.StateDB.getStateObject(addr) 116 if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() { 117 ms.accounts[addr] = newAccount(so) 118 } 119 120 } 121 122 return ms.accounts[addr] 123 } 124 125 func newAccount(so *stateObject) *account { 126 return &account{so, so.Nonce(), nil} 127 }