github.com/amazechain/amc@v0.1.3/internal/txspool/tx_noncer.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package txspool
    18  
    19  import (
    20  	"github.com/amazechain/amc/common/types"
    21  	"sync"
    22  )
    23  
    24  // txNoncer nonce database
    25  type txNoncer struct {
    26  	fallback ReadState
    27  	nonces   map[types.Address]uint64
    28  	lock     sync.Mutex
    29  }
    30  
    31  // newTxNoncer creates a new virtual state database to track the pool nonces.
    32  func newTxNoncer(db ReadState) *txNoncer {
    33  	return &txNoncer{
    34  		fallback: db,
    35  		nonces:   make(map[types.Address]uint64),
    36  	}
    37  }
    38  
    39  // get returns the current nonce of an account, falling back to a real state
    40  // database if the account is unknown.
    41  func (txn *txNoncer) get(addr types.Address) uint64 {
    42  	// We use mutex for get operation is the underlying
    43  	// state will mutate db even for read access.
    44  	txn.lock.Lock()
    45  	defer txn.lock.Unlock()
    46  
    47  	if _, ok := txn.nonces[addr]; !ok {
    48  		txn.nonces[addr] = txn.fallback.GetNonce(addr)
    49  	}
    50  	return txn.nonces[addr]
    51  }
    52  
    53  // set inserts a new virtual nonce into the virtual state database to be returned
    54  // whenever the pool requests it instead of reaching into the real state database.
    55  func (txn *txNoncer) set(addr types.Address, nonce uint64) {
    56  	txn.lock.Lock()
    57  	defer txn.lock.Unlock()
    58  
    59  	txn.nonces[addr] = nonce
    60  }
    61  
    62  // setIfLower updates a new virtual nonce into the virtual state database if the
    63  // the new one is lower.
    64  func (txn *txNoncer) setIfLower(addr types.Address, nonce uint64) {
    65  	txn.lock.Lock()
    66  	defer txn.lock.Unlock()
    67  
    68  	if _, ok := txn.nonces[addr]; !ok {
    69  		txn.nonces[addr] = txn.fallback.GetNonce(addr)
    70  	}
    71  	if txn.nonces[addr] <= nonce {
    72  		return
    73  	}
    74  	txn.nonces[addr] = nonce
    75  }
    76  
    77  // setAll sets the nonces for all accounts to the given map.
    78  func (txn *txNoncer) setAll(all map[types.Address]uint64) {
    79  	txn.lock.Lock()
    80  	defer txn.lock.Unlock()
    81  
    82  	txn.nonces = all
    83  }