github.com/dominant-strategies/go-quai@v0.28.2/core/tx_noncer.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	lru "github.com/hashicorp/golang-lru"
    21  	"sync"
    22  
    23  	"github.com/dominant-strategies/go-quai/common"
    24  	"github.com/dominant-strategies/go-quai/core/state"
    25  )
    26  
    27  const (
    28  	c_maxNonceCache = 600 //Maximum number of entries that we can hold in the nonces cahce
    29  )
    30  
    31  // txNoncer is a tiny virtual state database to manage the executable nonces of
    32  // accounts in the pool, falling back to reading from a real state database if
    33  // an account is unknown.
    34  type txNoncer struct {
    35  	fallback *state.StateDB
    36  	nonces   *lru.Cache
    37  	lock     sync.Mutex
    38  }
    39  
    40  // newTxNoncer creates a new virtual state database to track the pool nonces.
    41  func newTxNoncer(statedb *state.StateDB) *txNoncer {
    42  	n := &txNoncer{
    43  		fallback: statedb.Copy(),
    44  	}
    45  	nonces, _ := lru.New(c_maxNonceCache)
    46  	n.nonces = nonces
    47  
    48  	return n
    49  }
    50  
    51  // get returns the current nonce of an account, falling back to a real state
    52  // database if the account is unknown.
    53  func (txn *txNoncer) get(addr common.InternalAddress) uint64 {
    54  	// We use mutex for get operation is the underlying
    55  	// state will mutate db even for read access.
    56  	txn.lock.Lock()
    57  	defer txn.lock.Unlock()
    58  	txn.nonces.ContainsOrAdd(addr, txn.fallback.GetNonce(addr))
    59  	nonce, _ := txn.nonces.Get(addr)
    60  	return nonce.(uint64)
    61  }
    62  
    63  // set inserts a new virtual nonce into the virtual state database to be returned
    64  // whenever the pool requests it instead of reaching into the real state database.
    65  func (txn *txNoncer) set(addr common.InternalAddress, nonce uint64) {
    66  	txn.lock.Lock()
    67  	defer txn.lock.Unlock()
    68  	txn.nonces.Add(addr, nonce)
    69  }
    70  
    71  // setIfLower updates a new virtual nonce into the virtual state database if the
    72  // the new one is lower.
    73  func (txn *txNoncer) setIfLower(addr common.InternalAddress, nonce uint64) {
    74  	txn.lock.Lock()
    75  	defer txn.lock.Unlock()
    76  	txn.nonces.ContainsOrAdd(addr, txn.fallback.GetNonce(addr))
    77  	currentNonce, _ := txn.nonces.Peek(addr)
    78  	if currentNonce.(uint64) <= nonce {
    79  		return
    80  	}
    81  	txn.nonces.Add(addr, nonce)
    82  }