1717package core
1818
1919import (
20+ "sync"
21+
2022 "github.com/XinFinOrg/XDPoSChain/common"
2123 "github.com/XinFinOrg/XDPoSChain/core/state"
2224)
@@ -27,6 +29,7 @@ import (
2729type txNoncer struct {
2830 fallback * state.StateDB
2931 nonces map [common.Address ]uint64
32+ lock sync.Mutex
3033}
3134
3235// newTxNoncer creates a new virtual state database to track the pool nonces.
@@ -40,6 +43,11 @@ func newTxNoncer(statedb *state.StateDB) *txNoncer {
4043// get returns the current nonce of an account, falling back to a real state
4144// database if the account is unknown.
4245func (txn * txNoncer ) get (addr common.Address ) uint64 {
46+ // We use mutex for get operation is the underlying
47+ // state will mutate db even for read access.
48+ txn .lock .Lock ()
49+ defer txn .lock .Unlock ()
50+
4351 if _ , ok := txn .nonces [addr ]; ! ok {
4452 txn .nonces [addr ] = txn .fallback .GetNonce (addr )
4553 }
@@ -49,5 +57,23 @@ func (txn *txNoncer) get(addr common.Address) uint64 {
4957// set inserts a new virtual nonce into the virtual state database to be returned
5058// whenever the pool requests it instead of reaching into the real state database.
5159func (txn * txNoncer ) set (addr common.Address , nonce uint64 ) {
60+ txn .lock .Lock ()
61+ defer txn .lock .Unlock ()
62+
63+ txn .nonces [addr ] = nonce
64+ }
65+
66+ // setIfLower updates a new virtual nonce into the virtual state database if the
67+ // the new one is lower.
68+ func (txn * txNoncer ) setIfLower (addr common.Address , nonce uint64 ) {
69+ txn .lock .Lock ()
70+ defer txn .lock .Unlock ()
71+
72+ if _ , ok := txn .nonces [addr ]; ! ok {
73+ txn .nonces [addr ] = txn .fallback .GetNonce (addr )
74+ }
75+ if txn .nonces [addr ] <= nonce {
76+ return
77+ }
5278 txn .nonces [addr ] = nonce
5379}
0 commit comments