Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max nonce txpool #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions core/tx_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ func (h *nonceHeap) Pop() interface{} {
// txSortedMap is a nonce->transaction hash map with a heap based index to allow
// iterating over the contents in a nonce-incrementing way.
type txSortedMap struct {
items map[uint64]*types.Transaction // Hash map storing the transaction data
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
cache types.Transactions // Cache of the transactions already sorted
items map[uint64]*types.Transaction // Hash map storing the transaction data
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
maxNonce uint64 // cache of the current highest nonce
cache types.Transactions // Cache of the transactions already sorted
}

// newTxSortedMap creates a new nonce-sorted transaction map.
Expand All @@ -74,6 +75,9 @@ func (m *txSortedMap) Put(tx *types.Transaction) {
if m.items[nonce] == nil {
heap.Push(m.index, nonce)
}
if nonce > m.maxNonce {
m.maxNonce = nonce
}
m.items[nonce], m.cache = tx, nil
}

Expand All @@ -89,6 +93,10 @@ func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
removed = append(removed, m.items[nonce])
delete(m.items, nonce)
}
// If we pop'd all elements then reset the max nonce
if m.index.Len() == 0 {
m.maxNonce = 0
}
// If we had a cached order, shift the front
if m.cache != nil {
m.cache = m.cache[len(removed):]
Expand Down Expand Up @@ -116,6 +124,10 @@ func (m *txSortedMap) reheap() {
*m.index = append(*m.index, nonce)
}
heap.Init(m.index)
// If the txSortedMap is empty, reset max nonce
if len(m.items) == 0 {
m.maxNonce = 0
}
m.cache = nil
}

Expand Down Expand Up @@ -159,6 +171,13 @@ func (m *txSortedMap) Cap(threshold int) types.Transactions {
if m.cache != nil {
m.cache = m.cache[:len(m.cache)-len(drops)]
}
// Set the new max nonce
if threshold == 0 {
m.maxNonce = 0
} else {
m.maxNonce = m.items[(*m.index)[threshold-1]].Nonce()
}

return drops
}

Expand All @@ -179,7 +198,16 @@ func (m *txSortedMap) Remove(nonce uint64) bool {
}
delete(m.items, nonce)
m.cache = nil

if nonce == m.maxNonce {
if len(m.items) != 0 {
item := m.items[(*m.index)[len(m.items)-1]]
if item != nil {
m.maxNonce = item.Nonce()
return true
}
}
m.maxNonce = 0
}
return true
}

Expand All @@ -203,6 +231,9 @@ func (m *txSortedMap) Ready(start uint64) types.Transactions {
heap.Pop(m.index)
}
m.cache = nil
if m.index.Len() == 0 {
m.maxNonce = 0
}

return ready
}
Expand Down Expand Up @@ -238,8 +269,10 @@ func (m *txSortedMap) Flatten() types.Transactions {
// LastElement returns the last element of a flattened list, thus, the
// transaction with the highest nonce
func (m *txSortedMap) LastElement() *types.Transaction {
cache := m.flatten()
return cache[len(cache)-1]
if len(m.items) == 0 {
return types.NewTx(&types.LegacyTx{})
}
return m.items[m.maxNonce]
}

// txList is a "list" of transactions belonging to an account, sorted by account
Expand Down
4 changes: 3 additions & 1 deletion core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ type TxPool struct {
eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions.

currentState *state.StateDB // Current state in the blockchain head
currentNonces *txNoncer // Current state tracking for nonces
pendingNonces *txNoncer // Pending state tracking virtual nonces
currentMaxGas uint64 // Current gas limit for transaction caps

Expand Down Expand Up @@ -550,7 +551,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrUnderpriced
}
// Ensure the transaction adheres to nonce ordering
if pool.currentState.GetNonce(from) > tx.Nonce() {
if pool.currentNonces.get(from) > tx.Nonce() {
return ErrNonceTooLow
}
// Transactor should have enough funds to cover the costs
Expand Down Expand Up @@ -1194,6 +1195,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
}
pool.currentState = statedb
pool.pendingNonces = newTxNoncer(statedb)
pool.currentNonces = newTxNoncer(statedb)
pool.currentMaxGas = newHead.GasLimit

// Inject any transactions discarded due to reorgs
Expand Down