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: sender mempool impl #13888

Merged
merged 60 commits into from
Nov 23, 2022
Merged
Changes from 8 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
0cb8ad1
draft sender mempool impl
JeancarloBarrios Nov 16, 2022
b967d56
select
JeancarloBarrios Nov 16, 2022
353378c
nit
JeancarloBarrios Nov 16, 2022
20fbacb
random sender update
JeancarloBarrios Nov 16, 2022
c8ea169
nit
JeancarloBarrios Nov 16, 2022
1a89940
prevent memory leak
JeancarloBarrios Nov 16, 2022
28c6cfc
fix nil return
JeancarloBarrios Nov 17, 2022
faecdda
small fixes
JeancarloBarrios Nov 17, 2022
164bded
added tests
JeancarloBarrios Nov 17, 2022
87c221f
change count
JeancarloBarrios Nov 17, 2022
94334f5
finish tx order test removed the three address test due to make the t…
JeancarloBarrios Nov 17, 2022
24ebefe
remove unsued variable
JeancarloBarrios Nov 17, 2022
584bc51
nit
JeancarloBarrios Nov 17, 2022
fe3fbf8
fix
JeancarloBarrios Nov 17, 2022
2a18e81
temoral commit braking
JeancarloBarrios Nov 18, 2022
7784594
nit most
JeancarloBarrios Nov 18, 2022
d34cd88
nit most
JeancarloBarrios Nov 18, 2022
5a385cb
final
JeancarloBarrios Nov 18, 2022
9e02590
comments
JeancarloBarrios Nov 18, 2022
11ceaa7
t
JeancarloBarrios Nov 18, 2022
6703390
comments
JeancarloBarrios Nov 18, 2022
36b42cf
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 18, 2022
7556b9f
test
JeancarloBarrios Nov 20, 2022
6f1a08b
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
kocubinski Nov 21, 2022
d388bc4
add nolint
kocubinski Nov 21, 2022
9ff7528
Fix comment
kocubinski Nov 21, 2022
ec50ee6
golint comment
kocubinski Nov 21, 2022
bc851a9
golint
kocubinski Nov 21, 2022
1c938bf
improve format?
kocubinski Nov 21, 2022
8800e71
more gosec disable
kocubinski Nov 21, 2022
ed8a268
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
kocubinski Nov 21, 2022
beee298
Fix ctr usage
kocubinski Nov 21, 2022
1dcc89c
use #nosec
kocubinski Nov 21, 2022
99aff01
Update types/mempool/sender_nonce.go
kocubinski Nov 21, 2022
b5960c5
Kocubinski/random sender nonce (#13956)
kocubinski Nov 21, 2022
a3bdcb9
import fixes
kocubinski Nov 21, 2022
da63465
derive order randomness from seed only
kocubinski Nov 21, 2022
ea54e18
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
kocubinski Nov 21, 2022
c306fca
gosec fix
kocubinski Nov 21, 2022
a93c950
ignore gosec again
kocubinski Nov 21, 2022
578046a
comments
kocubinski Nov 21, 2022
695ed48
property based
JeancarloBarrios Nov 21, 2022
99b6536
minor fixes
JeancarloBarrios Nov 21, 2022
bf64e22
added property test
JeancarloBarrios Nov 21, 2022
5785fe7
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 21, 2022
ca1c17f
comment
JeancarloBarrios Nov 21, 2022
09cac5d
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 22, 2022
745d50d
fix imports
JeancarloBarrios Nov 22, 2022
c841351
Merge branch 'JeancarloBarrios/random-sender-nonce-ordering' of githu…
JeancarloBarrios Nov 22, 2022
77ea978
comment
JeancarloBarrios Nov 22, 2022
3078d65
Update types/mempool/sender_nonce_property_test.go
JeancarloBarrios Nov 22, 2022
e7c2e2f
remove unesessary loop
JeancarloBarrios Nov 22, 2022
d056a8a
improve function name
JeancarloBarrios Nov 22, 2022
9073aaf
Update types/mempool/sender_nonce.go
JeancarloBarrios Nov 22, 2022
69f3bc5
change import name
JeancarloBarrios Nov 22, 2022
73453ea
change validation to be preemvtive
JeancarloBarrios Nov 22, 2022
847bcf5
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 22, 2022
278adb0
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 23, 2022
560e747
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 23, 2022
cb6121e
Merge branch 'main' into JeancarloBarrios/random-sender-nonce-ordering
JeancarloBarrios Nov 23, 2022
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
191 changes: 191 additions & 0 deletions types/mempool/sender_nonce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package mempool

import (
"fmt"
"math/rand"
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
huandu "github.com/huandu/skiplist"
)

var (
_ Mempool = (*senderNonceMempool)(nil)
_ Iterator = (*nonceMempoolIterator)(nil)
)

type senderTxs struct {
Copy link
Member

Choose a reason for hiding this comment

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

Can we simplify usages of senderTxs to just cursor *huandu.Element? The wrapping type seems to serve no purpose.

txQueue *huandu.SkipList
head *huandu.Element
}

func newSenderTxs() senderTxs {
return senderTxs{
head: nil,
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
txQueue: huandu.New(huandu.LessThanFunc(txKeyLessNonce)),
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}
}

func (s *senderTxs) insert(key txKey, tx sdk.Tx) {
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
s.txQueue.Set(key, tx)
s.head = s.txQueue.Front()
Fixed Show fixed Hide fixed
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}

func (s *senderTxs) getMove() *huandu.Element {
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
if s.head == nil {
return nil
}
currentHead := s.head
s.head = s.head.Next()
return currentHead
}

func (s *senderTxs) remove(key txKey) error {
res := s.txQueue.Remove(key)
if res == nil {
return ErrTxNotFound
}
if s.head == res {
s.head = s.txQueue.Front()
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}
return nil
}

type senderNonceMempool struct {
senders map[string]*senderTxs
txCount int
rnd *rand.Rand
}

func NewSenderNonceMempool() Mempool {
senderMap := make(map[string]*senderTxs)
snp := &senderNonceMempool{
senders: senderMap,
txCount: 0,
}
snp.SetSeed(time.Now().UnixNano())
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
return snp
}

func (snm *senderNonceMempool) SetSeed(seed int64) {
s1 := rand.NewSource(seed)
snm.rnd = rand.New(s1)
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved
Fixed Show fixed Hide fixed
}

func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error {
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
if err != nil {
return err
}
if len(sigs) == 0 {
return fmt.Errorf("tx must have at least one signer")
}

sig := sigs[0]
sender := sig.PubKey.Address().String()
nonce := sig.Sequence
senderTxs, found := snm.senders[sender]
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
if !found {
newSenderTx := newSenderTxs()
senderTxs = &newSenderTx
}
tk := txKey{nonce: nonce, sender: sender}
senderTxs.insert(tk, tx)
snm.senders[sender] = senderTxs
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
snm.txCount = snm.txCount + 1
return nil
}

func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator {
var senders []string
for key := range snm.senders {
senders = append(senders, key)
}
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
iter := &senderNonceMepoolIterator{
mempool: snm,
senders: senders,
}

newIter := iter.Next()
if newIter == nil {
return nil
}
return newIter
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}

// CountTx returns the total count of txs in the mempool.
func (snm *senderNonceMempool) CountTx() int {
return snm.txCount
}

// Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx
// was not found in the pool.
func (snm *senderNonceMempool) Remove(tx sdk.Tx) error {
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
if err != nil {
return err
}
if len(sigs) == 0 {
return fmt.Errorf("tx must have at least one signer")
}

sig := sigs[0]
sender := sig.PubKey.Address().String()
nonce := sig.Sequence
tk := txKey{nonce: nonce, sender: sender}
senderTxs, found := snm.senders[sender]
if !found {
return ErrTxNotFound
}
err = senderTxs.remove(tk)
if err != nil {
return err
}
if senderTxs.txQueue.Len() == 0 {
delete(snm.senders, sender)
} else {
snm.senders[sender] = senderTxs
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}
snm.txCount = snm.txCount - 1
return nil
}

type senderNonceMepoolIterator struct {
mempool *senderNonceMempool
currentTx *huandu.Element
senders []string
seed int
}

func (i *senderNonceMepoolIterator) Next() Iterator {
for len(i.senders) > 0 {
senderIndex := i.mempool.rnd.Intn(len(i.senders))
sender := i.senders[senderIndex]
senderTxs, found := i.mempool.senders[sender]
if !found {
i.senders = removeAtIndex(i.senders, senderIndex)
continue
}
tx := senderTxs.getMove()
if tx == nil {
i.senders = removeAtIndex(i.senders, senderIndex)
continue
}
return &senderNonceMepoolIterator{
senders: i.senders,
currentTx: tx,
mempool: i.mempool,
}
}

return nil
}

func (i *senderNonceMepoolIterator) Tx() sdk.Tx {
return i.currentTx.Value.(sdk.Tx)
}

func removeAtIndex[T any](slice []T, index int) []T {
return append(slice[:index], slice[index+1:]...)
}