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

Mempool: handle not-executable transactions related to guardians #58

Merged
merged 7 commits into from
Nov 28, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,28 @@ import (
"math/big"
"sync"

"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-storage-go/types"
)

// AccountStateProviderMock -
type AccountStateProviderMock struct {
// SelectionSessionMock -
type SelectionSessionMock struct {
mutex sync.Mutex

AccountStateByAddress map[string]*types.AccountState
GetAccountStateCalled func(address []byte) (*types.AccountState, error)
AccountStateByAddress map[string]*types.AccountState
GetAccountStateCalled func(address []byte) (*types.AccountState, error)
IsIncorrectlyGuardedCalled func(tx data.TransactionHandler) bool
}

// NewAccountStateProviderMock -
func NewAccountStateProviderMock() *AccountStateProviderMock {
return &AccountStateProviderMock{
// NewSelectionSessionMock -
func NewSelectionSessionMock() *SelectionSessionMock {
return &SelectionSessionMock{
AccountStateByAddress: make(map[string]*types.AccountState),
}
}

// SetNonce -
func (mock *AccountStateProviderMock) SetNonce(address []byte, nonce uint64) {
func (mock *SelectionSessionMock) SetNonce(address []byte, nonce uint64) {
mock.mutex.Lock()
defer mock.mutex.Unlock()

Expand All @@ -37,7 +39,7 @@ func (mock *AccountStateProviderMock) SetNonce(address []byte, nonce uint64) {
}

// SetBalance -
func (mock *AccountStateProviderMock) SetBalance(address []byte, balance *big.Int) {
func (mock *SelectionSessionMock) SetBalance(address []byte, balance *big.Int) {
mock.mutex.Lock()
defer mock.mutex.Unlock()

Expand All @@ -51,7 +53,7 @@ func (mock *AccountStateProviderMock) SetBalance(address []byte, balance *big.In
}

// GetAccountState -
func (mock *AccountStateProviderMock) GetAccountState(address []byte) (*types.AccountState, error) {
func (mock *SelectionSessionMock) GetAccountState(address []byte) (*types.AccountState, error) {
mock.mutex.Lock()
defer mock.mutex.Unlock()

Expand All @@ -67,8 +69,17 @@ func (mock *AccountStateProviderMock) GetAccountState(address []byte) (*types.Ac
return newDefaultAccountState(), nil
}

// IsIncorrectlyGuarded -
func (mock *SelectionSessionMock) IsIncorrectlyGuarded(tx data.TransactionHandler) bool {
if mock.IsIncorrectlyGuardedCalled != nil {
return mock.IsIncorrectlyGuardedCalled(tx)
}

return false
}

// IsInterfaceNil -
func (mock *AccountStateProviderMock) IsInterfaceNil() bool {
func (mock *SelectionSessionMock) IsInterfaceNil() bool {
return mock == nil
}

Expand Down
2 changes: 1 addition & 1 deletion txcache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Thus, the mempool selects transactions using an efficient and value-driven algor
- If a middle nonce gap is detected, the sender is skipped (from now on) in the current selection session.
- Transactions with nonces lower than the current nonce of the sender are skipped.
- Transactions having the same nonce as a previously selected one (in the scope of a sender) are skipped. Also see paragraph 5.
- Badly guarded transactions are skipped.
- Incorrectly guarded transactions are skipped.
- Once the accumulated fees of selected transactions of a given sender exceed the sender's balance, the sender is skipped (from now one).


Expand Down
2 changes: 1 addition & 1 deletion txcache/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package txcache
import "errors"

var errNilTxGasHandler = errors.New("nil tx gas handler")
var errNilAccountStateProvider = errors.New("nil account state provider")
var errNilSelectionSession = errors.New("nil selection session")
var errItemAlreadyInCache = errors.New("item already in cache")
var errEmptyBunchOfTransactions = errors.New("empty bunch of transactions")
5 changes: 3 additions & 2 deletions txcache/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ type TxGasHandler interface {
IsInterfaceNil() bool
}

// AccountStateProvider defines the behavior of a component able to provide the state of an account
type AccountStateProvider interface {
// SelectionSession provides blockchain information for transaction selection
type SelectionSession interface {
GetAccountState(accountKey []byte) (*types.AccountState, error)
IsIncorrectlyGuarded(tx data.TransactionHandler) bool
IsInterfaceNil() bool
}

Expand Down
14 changes: 7 additions & 7 deletions txcache/selection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"time"
)

func (cache *TxCache) doSelectTransactions(accountStateProvider AccountStateProvider, gasRequested uint64, maxNum int, selectionLoopMaximumDuration time.Duration) (bunchOfTransactions, uint64) {
func (cache *TxCache) doSelectTransactions(session SelectionSession, gasRequested uint64, maxNum int, selectionLoopMaximumDuration time.Duration) (bunchOfTransactions, uint64) {
bunches := cache.acquireBunchesOfTransactions()

return selectTransactionsFromBunches(accountStateProvider, bunches, gasRequested, maxNum, selectionLoopMaximumDuration)
return selectTransactionsFromBunches(session, bunches, gasRequested, maxNum, selectionLoopMaximumDuration)
}

func (cache *TxCache) acquireBunchesOfTransactions() []bunchOfTransactions {
Expand All @@ -23,7 +23,7 @@ func (cache *TxCache) acquireBunchesOfTransactions() []bunchOfTransactions {
}

// Selection tolerates concurrent transaction additions / removals.
func selectTransactionsFromBunches(accountStateProvider AccountStateProvider, bunches []bunchOfTransactions, gasRequested uint64, maxNum int, selectionLoopMaximumDuration time.Duration) (bunchOfTransactions, uint64) {
func selectTransactionsFromBunches(session SelectionSession, bunches []bunchOfTransactions, gasRequested uint64, maxNum int, selectionLoopMaximumDuration time.Duration) (bunchOfTransactions, uint64) {
selectedTransactions := make(bunchOfTransactions, 0, initialCapacityOfSelectionSlice)

// Items popped from the heap are added to "selectedTransactions".
Expand Down Expand Up @@ -63,7 +63,7 @@ func selectTransactionsFromBunches(accountStateProvider AccountStateProvider, bu
}
}

err := item.requestAccountStateIfNecessary(accountStateProvider)
err := item.requestAccountStateIfNecessary(session)
if err != nil {
// Skip this sender.
logSelect.Debug("TxCache.selectTransactionsFromBunches, could not retrieve account state", "sender", item.sender, "err", err)
Expand All @@ -77,7 +77,7 @@ func selectTransactionsFromBunches(accountStateProvider AccountStateProvider, bu
continue
}

shouldSkipTransaction := detectSkippableTransaction(item)
shouldSkipTransaction := detectSkippableTransaction(session, item)
if !shouldSkipTransaction {
accumulatedGas += gasLimit
selectedTransactions = append(selectedTransactions, item.selectCurrentTransaction())
Expand Down Expand Up @@ -108,11 +108,11 @@ func detectSkippableSender(item *transactionsHeapItem) bool {
return false
}

func detectSkippableTransaction(item *transactionsHeapItem) bool {
func detectSkippableTransaction(session SelectionSession, item *transactionsHeapItem) bool {
if item.detectLowerNonce() {
return true
}
if item.detectBadlyGuarded() {
if item.detectIncorrectlyGuarded(session) {
return true
}
if item.detectNonceDuplicate() {
Expand Down
Loading