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  }