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

feat: nonce (sequence number) based mempool #13645

Merged
merged 21 commits into from
Oct 26, 2022
Merged

Conversation

kocubinski
Copy link
Member

Description

Closes: #13276

This simple mempool implementation keeps transactions sorted by nonce (sequence number). Transactions with the lowest nonce globally are prioritized. Transactions from different senders with the same nonce are prioritized by sender address. Fee/gas based prioritization is not supported.


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title
  • added ! to the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • followed the guidelines for building modules
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • included comments for documenting Go code
  • updated the relevant documentation or specification
  • reviewed "Files changed" and left comments if necessary
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed ! in the type prefix if API or client breaking change
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic
  • reviewed API design and naming
  • reviewed documentation is accurate
  • reviewed tests and test coverage
  • manually tested (if applicable)

@kocubinski kocubinski requested a review from a team as a code owner October 25, 2022 13:36
Comment on lines 14 to 17

"github.com/cosmos/cosmos-sdk/types/mempool"
"github.com/cosmos/gogoproto/proto"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"github.com/cosmos/cosmos-sdk/types/mempool"
"github.com/cosmos/gogoproto/proto"
"github.com/cosmos/gogoproto/proto"
"github.com/cosmos/cosmos-sdk/types/mempool"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kocubinski do you use VSCode? If so, you can add the following to your SDK workspace settings:

  "gopls": {
    "local": "github.com/cosmos/cosmos-sdk"
  }

I'm sure there is one equivalent for vim or whatever

@codecov
Copy link

codecov bot commented Oct 25, 2022

Codecov Report

Merging #13645 (c0ce7d1) into main (ad08ec4) will increase coverage by 0.15%.
The diff coverage is 96.73%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #13645      +/-   ##
==========================================
+ Coverage   54.69%   54.85%   +0.15%     
==========================================
  Files         645      655      +10     
  Lines       55745    56239     +494     
==========================================
+ Hits        30491    30851     +360     
- Misses      22764    22866     +102     
- Partials     2490     2522      +32     
Impacted Files Coverage Δ
baseapp/baseapp.go 75.12% <0.00%> (ø)
x/auth/tx/builder.go 81.65% <92.30%> (+1.45%) ⬆️
types/mempool/nonce.go 100.00% <100.00%> (ø)
x/distribution/simulation/operations.go 80.64% <0.00%> (-9.68%) ⬇️
x/group/keeper/keeper.go 56.25% <0.00%> (-0.40%) ⬇️
tx/textual/valuerenderer/timestamp.go 89.28% <0.00%> (ø)
tx/textual/valuerenderer/valuerenderer.go 72.41% <0.00%> (ø)
tx/textual/valuerenderer/int.go 50.00% <0.00%> (ø)
tx/textual/valuerenderer/string.go 66.66% <0.00%> (ø)
tx/textual/valuerenderer/message.go 64.22% <0.00%> (ø)
... and 4 more

Copy link
Contributor

@alexanderbez alexanderbez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments, but otherwise LGTM!

Comment on lines 14 to 17

"github.com/cosmos/cosmos-sdk/types/mempool"
"github.com/cosmos/gogoproto/proto"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kocubinski do you use VSCode? If so, you can add the following to your SDK workspace settings:

  "gopls": {
    "local": "github.com/cosmos/cosmos-sdk"
  }

I'm sure there is one equivalent for vim or whatever


type Factory func() Mempool

func IsEmpty(mempool Mempool) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than type cast. I would just define NumTxs() on the mempool interface.

@@ -1,6 +1,7 @@
package tx

import (
"github.com/cosmos/cosmos-sdk/types/mempool"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: formatting

// are prioritized. Transactions with the same nonce are prioritized by sender address. Fee/gas based
// prioritization is not supported.
type nonceMempool struct {
txQueue *huandu.SkipList
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to point out that using a skip list this for this type of implementation might be overkill. You could just use a sorted []Tx array, or a wrapper around Tx so you don't have to do anything extra to get the sender and nonce, etc..

Copy link
Member Author

@kocubinski kocubinski Oct 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just use a sorted []Tx array

I think this is an efficient way to maintain a sorted list. Using an array we'd still need to sort on insert, what are you proposing for maintaining the sort?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, its the same semantically. With an array, sort on insert. Both are logarithmic. Not blocking though. Just pointing it out.

Comment on lines 76 to 79
selectedTxs = append(selectedTxs, mempoolTx)
if txBytes += mempoolTx.Size(); txBytes >= maxBytes {
return selectedTxs, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to re-write this slightly. You only want to add the current tx s.t. if when added remains under or equal to maxBytes. I.e. txBytes + mempoolTx.Size() <= maxBytes { // append }

Copy link
Contributor

@alexanderbez alexanderbez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

nice work!

Copy link
Member

@facundomedica facundomedica left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, added some very very silly nits (sorry)

Comment on lines 26 to 40
func (t testPubKey) Reset() { panic("implement me") }

func (t testPubKey) String() string { panic("implement me") }

func (t testPubKey) ProtoMessage() { panic("implement me") }

func (t testPubKey) Address() cryptotypes.Address { return t.address.Bytes() }

func (t testPubKey) Bytes() []byte { panic("implement me") }

func (t testPubKey) VerifySignature(msg []byte, sig []byte) bool { panic("implement me") }

func (t testPubKey) Equals(key cryptotypes.PubKey) bool { panic("implement me") }

func (t testPubKey) Type() string { panic("implement me") }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
func (t testPubKey) Reset() { panic("implement me") }
func (t testPubKey) String() string { panic("implement me") }
func (t testPubKey) ProtoMessage() { panic("implement me") }
func (t testPubKey) Address() cryptotypes.Address { return t.address.Bytes() }
func (t testPubKey) Bytes() []byte { panic("implement me") }
func (t testPubKey) VerifySignature(msg []byte, sig []byte) bool { panic("implement me") }
func (t testPubKey) Equals(key cryptotypes.PubKey) bool { panic("implement me") }
func (t testPubKey) Type() string { panic("implement me") }
func (t testPubKey) Reset() { panic("not implemented") }
func (t testPubKey) String() string { panic("not implemented") }
func (t testPubKey) ProtoMessage() { panic("not implemented") }
func (t testPubKey) Address() cryptotypes.Address { return t.address.Bytes() }
func (t testPubKey) Bytes() []byte { panic("not implemented") }
func (t testPubKey) VerifySignature(msg []byte, sig []byte) bool { panic("not implemented") }
func (t testPubKey) Equals(key cryptotypes.PubKey) bool { panic("not implemented") }
func (t testPubKey) Type() string { panic("not implemented") }

Comment on lines 50 to 52
func (tx testTx) GetSigners() []sdk.AccAddress { panic("implement me") }

func (tx testTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("GetPubKeys not implemented") }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consistency nit:

Suggested change
func (tx testTx) GetSigners() []sdk.AccAddress { panic("implement me") }
func (tx testTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("GetPubKeys not implemented") }
func (tx testTx) GetSigners() []sdk.AccAddress { panic("not implemented") }
func (tx testTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("not implemented") }

require.NoError(t, err)
}

//mempool.DebugPrintKeys(pool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//mempool.DebugPrintKeys(pool)

Comment on lines 12 to 14
// nonceMempool is a mempool that keeps transactions sorted by nonce. Transactions with the lowest nonce globally
// are prioritized. Transactions with the same nonce are prioritized by sender address. Fee/gas based
// prioritization is not supported.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// nonceMempool is a mempool that keeps transactions sorted by nonce. Transactions with the lowest nonce globally
// are prioritized. Transactions with the same nonce are prioritized by sender address. Fee/gas based
// prioritization is not supported.
// nonceMempool is a mempool that keeps transactions sorted by nonce. Transactions with the lowest nonce globally
// are prioritized. Transactions with the same nonce are prioritized by sender address. Fee/gas based
// prioritization is not supported.

return sp
}

// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer.
// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer.

return nil
}

// Select returns txs from the mempool with the lowest nonce globally first. A sender's txs will always be returned
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Select returns txs from the mempool with the lowest nonce globally first. A sender's txs will always be returned
// Select returns txs from the mempool with the lowest nonce globally first. A sender's txs will always be returned

return sp.txQueue.Len()
}

// Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx
// Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx

@kocubinski kocubinski merged commit 2418c3e into main Oct 26, 2022
@kocubinski kocubinski deleted the kocubinski/mempool-nonce branch October 26, 2022 14:04
@kocubinski kocubinski mentioned this pull request Oct 26, 2022
19 tasks
larry0x pushed a commit to larry0x/cosmos-sdk that referenced this pull request May 22, 2023
simple default mempool implementation

Co-authored-by: Jeancarlo <jeancarlobarrios@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide default mempool implementation
5 participants