From 0cb8ad15d3d02ab6466b28bb40d7454d5c69ca15 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 08:52:50 -0500 Subject: [PATCH 01/49] draft sender mempool impl --- types/mempool/sender_nonce.go | 152 ++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 types/mempool/sender_nonce.go diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go new file mode 100644 index 000000000000..32f12260a284 --- /dev/null +++ b/types/mempool/sender_nonce.go @@ -0,0 +1,152 @@ +package mempool + +import ( + "fmt" + + 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 { + txQueue *huandu.SkipList + head *huandu.Element +} + +func newSenderTxs() senderTxs { + return senderTxs{ + head: nil, + txQueue: huandu.New(huandu.LessThanFunc(txKeyLessNonce)), + } +} + +func (s senderTxs) insert(key txKey, tx sdk.Tx) { + s.txQueue.Set(key, tx) + s.head = s.txQueue.Front() +} + +func (s senderTxs) getMove() *huandu.Element { + 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() + } + return nil +} + +type senderNonceMempool struct { + senders map[string]senderTxs + txCount int +} + +func NewSenderNonceMempool() Mempool { + senderMap := make(map[string]senderTxs) + snp := &senderNonceMempool{ + senders: senderMap, + txCount: 0, + } + return snp +} + +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 + tk := txKey{nonce: nonce, sender: sender} + senderTxs, found := snm.senders[sender] + if !found { + senderTxs = newSenderTxs() + } + + senderTxs.insert(tk, tx) + snm.senders[sender] = senderTxs + snm.txCount += 1 + return nil +} + +func (snm senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { + +} + +// 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 + } + + snm.senders[sender] = senderTxs + snm.txCount -= 1 + return nil +} + +type senderNonceMepoolIterator struct { + mempool *senderNonceMempool + currentTx *huandu.Element +} + +func (i senderNonceMepoolIterator) Next() Iterator { + for sender := range i.mempool.senders { + senderTxs, found := i.mempool.senders[sender] + if !found { + continue + } + tx := senderTxs.getMove() + if tx == nil { + continue + } + return senderNonceMepoolIterator{ + currentTx: tx, + mempool: i.mempool, + } + } + + return nil +} + +func (i senderNonceMepoolIterator) Tx() sdk.Tx { + return i.currentTx.Value.(sdk.Tx) +} From b967d5665faefa1bcfea9fbec491d4e388eed6b4 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 08:56:47 -0500 Subject: [PATCH 02/49] select --- types/mempool/sender_nonce.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 32f12260a284..66ba097bb9e2 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -32,7 +32,8 @@ func (s senderTxs) getMove() *huandu.Element { return nil } currentHead := s.head - s.head = s.head.Next() + next := s.head.Next() + s.head = next return currentHead } @@ -81,12 +82,16 @@ func (snm senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { senderTxs.insert(tk, tx) snm.senders[sender] = senderTxs - snm.txCount += 1 + snm.txCount = snm.txCount + 1 return nil } func (snm senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { - + iter := &senderNonceMepoolIterator{ + mempool: &snm, + } + iter.Next() + return iter } // CountTx returns the total count of txs in the mempool. @@ -119,7 +124,7 @@ func (snm senderNonceMempool) Remove(tx sdk.Tx) error { } snm.senders[sender] = senderTxs - snm.txCount -= 1 + snm.txCount = snm.txCount - 1 return nil } From 353378cc86bbe668e0ea24358c4bada2f881d327 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 09:15:12 -0500 Subject: [PATCH 03/49] nit --- types/mempool/sender_nonce.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 66ba097bb9e2..3eaf8814d438 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -32,8 +32,7 @@ func (s senderTxs) getMove() *huandu.Element { return nil } currentHead := s.head - next := s.head.Next() - s.head = next + s.head = s.head.Next() return currentHead } From 20fbacb1cfcab17b8ece31dddeffca5b77f66579 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 12:54:19 -0500 Subject: [PATCH 04/49] random sender update --- types/mempool/sender_nonce.go | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 3eaf8814d438..56c025db11f4 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -2,13 +2,18 @@ package mempool import ( "fmt" + "math/rand" + "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) +var ( + _ Mempool = (*senderNonceMempool)(nil) + _ Iterator = (*nonceMempoolIterator)(nil) +) type senderTxs struct { txQueue *huandu.SkipList @@ -50,6 +55,7 @@ func (s senderTxs) remove(key txKey) error { type senderNonceMempool struct { senders map[string]senderTxs txCount int + rnd *rand.Rand } func NewSenderNonceMempool() Mempool { @@ -58,9 +64,15 @@ func NewSenderNonceMempool() Mempool { senders: senderMap, txCount: 0, } + snp.setSeed(time.Now().UnixNano()) return snp } +func (snm senderNonceMempool) SetSeed(seed int64) { + s1 := rand.NewSource(seed) + snm.rnd = rand.New(s1) +} + func (snm senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2() if err != nil { @@ -86,8 +98,13 @@ func (snm senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { } func (snm senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { + var senders []string + for key := range snm.senders { + senders = append(senders, key) + } iter := &senderNonceMepoolIterator{ mempool: &snm, + senders: senders, } iter.Next() return iter @@ -130,19 +147,34 @@ func (snm senderNonceMempool) Remove(tx sdk.Tx) error { type senderNonceMepoolIterator struct { mempool *senderNonceMempool currentTx *huandu.Element + senders []string + seed int } func (i senderNonceMepoolIterator) Next() Iterator { - for sender := range i.mempool.senders { + 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 { - continue + newSenders := removeAtIndex(i.senders, senderIndex) + return senderNonceMepoolIterator{ + senders: newSenders, + currentTx: nil, + mempool: i.mempool, + } } tx := senderTxs.getMove() if tx == nil { - continue + newSenders := removeAtIndex(i.senders, senderIndex) + return senderNonceMepoolIterator{ + senders: newSenders, + currentTx: nil, + mempool: i.mempool, + } } return senderNonceMepoolIterator{ + senders: i.senders, currentTx: tx, mempool: i.mempool, } @@ -154,3 +186,7 @@ func (i senderNonceMepoolIterator) Next() Iterator { 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:]...) +} From c8ea1691d73070856aaf68e6d77852ebe9a633af Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 12:54:54 -0500 Subject: [PATCH 05/49] nit --- types/mempool/sender_nonce.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 56c025db11f4..de7012c44f6a 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -64,7 +64,7 @@ func NewSenderNonceMempool() Mempool { senders: senderMap, txCount: 0, } - snp.setSeed(time.Now().UnixNano()) + snp.SetSeed(time.Now().UnixNano()) return snp } From 1a8994061e98f5fdbb281626dcd886acdb8ec52a Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 12:57:27 -0500 Subject: [PATCH 06/49] prevent memory leak --- types/mempool/sender_nonce.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index de7012c44f6a..a6b0bd24aed8 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -138,8 +138,11 @@ func (snm senderNonceMempool) Remove(tx sdk.Tx) error { if err != nil { return err } - - snm.senders[sender] = senderTxs + if senderTxs.txQueue.Len() == 0 { + delete(snm.senders, sender) + } else { + snm.senders[sender] = senderTxs + } snm.txCount = snm.txCount - 1 return nil } From 28c6cfcee0476c1a811e8c6f15eba0264204dfc1 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Wed, 16 Nov 2022 22:41:56 -0500 Subject: [PATCH 07/49] fix nil return --- types/mempool/sender_nonce.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index a6b0bd24aed8..e856b03ec41e 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -160,21 +160,13 @@ func (i senderNonceMepoolIterator) Next() Iterator { sender := i.senders[senderIndex] senderTxs, found := i.mempool.senders[sender] if !found { - newSenders := removeAtIndex(i.senders, senderIndex) - return senderNonceMepoolIterator{ - senders: newSenders, - currentTx: nil, - mempool: i.mempool, - } + i.senders = removeAtIndex(i.senders, senderIndex) + continue } tx := senderTxs.getMove() if tx == nil { - newSenders := removeAtIndex(i.senders, senderIndex) - return senderNonceMepoolIterator{ - senders: newSenders, - currentTx: nil, - mempool: i.mempool, - } + i.senders = removeAtIndex(i.senders, senderIndex) + continue } return senderNonceMepoolIterator{ senders: i.senders, From faecdda151680d83ec94e272535e6b6526a426ae Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 01:18:48 -0500 Subject: [PATCH 08/49] small fixes --- types/mempool/sender_nonce.go | 42 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index e856b03ec41e..d8666c2f7796 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -27,12 +27,12 @@ func newSenderTxs() senderTxs { } } -func (s senderTxs) insert(key txKey, tx sdk.Tx) { +func (s *senderTxs) insert(key txKey, tx sdk.Tx) { s.txQueue.Set(key, tx) s.head = s.txQueue.Front() } -func (s senderTxs) getMove() *huandu.Element { +func (s *senderTxs) getMove() *huandu.Element { if s.head == nil { return nil } @@ -41,7 +41,7 @@ func (s senderTxs) getMove() *huandu.Element { return currentHead } -func (s senderTxs) remove(key txKey) error { +func (s *senderTxs) remove(key txKey) error { res := s.txQueue.Remove(key) if res == nil { return ErrTxNotFound @@ -53,13 +53,13 @@ func (s senderTxs) remove(key txKey) error { } type senderNonceMempool struct { - senders map[string]senderTxs + senders map[string]*senderTxs txCount int rnd *rand.Rand } func NewSenderNonceMempool() Mempool { - senderMap := make(map[string]senderTxs) + senderMap := make(map[string]*senderTxs) snp := &senderNonceMempool{ senders: senderMap, txCount: 0, @@ -68,12 +68,12 @@ func NewSenderNonceMempool() Mempool { return snp } -func (snm senderNonceMempool) SetSeed(seed int64) { +func (snm *senderNonceMempool) SetSeed(seed int64) { s1 := rand.NewSource(seed) snm.rnd = rand.New(s1) } -func (snm senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { +func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2() if err != nil { return err @@ -85,39 +85,43 @@ func (snm senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { sig := sigs[0] sender := sig.PubKey.Address().String() nonce := sig.Sequence - tk := txKey{nonce: nonce, sender: sender} senderTxs, found := snm.senders[sender] if !found { - senderTxs = newSenderTxs() + newSenderTx := newSenderTxs() + senderTxs = &newSenderTx } - + tk := txKey{nonce: nonce, sender: sender} senderTxs.insert(tk, tx) snm.senders[sender] = senderTxs snm.txCount = snm.txCount + 1 return nil } -func (snm senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { +func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { var senders []string for key := range snm.senders { senders = append(senders, key) } iter := &senderNonceMepoolIterator{ - mempool: &snm, + mempool: snm, senders: senders, } - iter.Next() - return iter + + newIter := iter.Next() + if newIter == nil { + return nil + } + return newIter } // CountTx returns the total count of txs in the mempool. -func (snm senderNonceMempool) CountTx() int { +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 { +func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2() if err != nil { return err @@ -154,7 +158,7 @@ type senderNonceMepoolIterator struct { seed int } -func (i senderNonceMepoolIterator) Next() Iterator { +func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.mempool.rnd.Intn(len(i.senders)) sender := i.senders[senderIndex] @@ -168,7 +172,7 @@ func (i senderNonceMepoolIterator) Next() Iterator { i.senders = removeAtIndex(i.senders, senderIndex) continue } - return senderNonceMepoolIterator{ + return &senderNonceMepoolIterator{ senders: i.senders, currentTx: tx, mempool: i.mempool, @@ -178,7 +182,7 @@ func (i senderNonceMepoolIterator) Next() Iterator { return nil } -func (i senderNonceMepoolIterator) Tx() sdk.Tx { +func (i *senderNonceMepoolIterator) Tx() sdk.Tx { return i.currentTx.Value.(sdk.Tx) } From 164bded91449883fb451a318fb1c095a4d66c9c6 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 02:32:48 -0500 Subject: [PATCH 09/49] added tests --- types/mempool/mempool_test.go | 9 +- types/mempool/nonce_test.go | 251 ++++++++++++++++++++-------------- types/mempool/sender_nonce.go | 15 +- 3 files changed, 166 insertions(+), 109 deletions(-) diff --git a/types/mempool/mempool_test.go b/types/mempool/mempool_test.go index 44a9103d524d..be9e3997d497 100644 --- a/types/mempool/mempool_test.go +++ b/types/mempool/mempool_test.go @@ -132,6 +132,7 @@ func (s *MempoolTestSuite) TestDefaultMempool() { for i := 0; i < txCount; i++ { acc := accounts[i%len(accounts)] tx := testTx{ + nonce: 0, address: acc.Address, priority: rand.Int63(), } @@ -149,7 +150,8 @@ func (s *MempoolTestSuite) TestDefaultMempool() { err := s.mempool.Insert(ctx, tx) require.NoError(t, err) } - require.Equal(t, len(accounts), s.mempool.CountTx()) + // TODO add validity check to see if it exist not insert. Maybe a map ? + //require.Equal(t, len(accounts), s.mempool.CountTx()) // distinct sender-nonce should not overwrite a tx s.resetMempool() @@ -182,13 +184,14 @@ func (s *MempoolTestSuite) TestDefaultMempool() { require.ErrorIs(t, s.mempool.Remove(txs[1]), mempool.ErrTxNotFound) // inserting a tx with a different priority should overwrite the old tx + // TODO there is no longer priorities newPriorityTx := testTx{ address: txs[0].address, priority: txs[0].priority + 1, nonce: txs[0].nonce, } require.NoError(t, s.mempool.Insert(ctx, newPriorityTx)) - require.Equal(t, 1, s.mempool.CountTx()) + //require.Equal(t, 1, s.mempool.CountTx()) } type MempoolTestSuite struct { @@ -201,7 +204,7 @@ type MempoolTestSuite struct { func (s *MempoolTestSuite) resetMempool() { s.iterations = 0 - s.mempool = mempool.NewNonceMempool() + s.mempool = mempool.NewSenderNonceMempool() } func (s *MempoolTestSuite) SetupTest() { diff --git a/types/mempool/nonce_test.go b/types/mempool/nonce_test.go index 663a17c770de..847e3939e8fc 100644 --- a/types/mempool/nonce_test.go +++ b/types/mempool/nonce_test.go @@ -2,6 +2,7 @@ package mempool_test import ( "fmt" + "github.com/cosmos/cosmos-sdk/types/mempool" "math/rand" "testing" @@ -19,12 +20,13 @@ func (s *MempoolTestSuite) TestTxOrder() { accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 5) sa := accounts[0].Address sb := accounts[1].Address - sc := accounts[2].Address + //sc := accounts[2].Address tests := []struct { txs []txSpec - order []int + order [][]int fail bool + seed int64 }{ { txs: []txSpec{ @@ -34,7 +36,12 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 20, n: 1, a: sa}, }, - order: []int{3, 4, 2, 1, 0}, + order: [][]int{ + {4, 2, 3, 1, 0}, + {3, 4, 2, 1, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, }, { txs: []txSpec{ @@ -45,7 +52,12 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 5, n: 1, a: sb}, {p: 8, n: 2, a: sb}, }, - order: []int{3, 0, 4, 1, 5, 2}, + order: [][]int{ + {0, 1, 3, 2, 4, 5}, + {3, 4, 0, 5, 1, 2}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, }, { txs: []txSpec{ @@ -53,7 +65,12 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 20, n: 1, a: sa}, }, - order: []int{1, 2, 0}, + order: [][]int{ + {2, 0, 1}, + {1, 2, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, }, { txs: []txSpec{ @@ -63,7 +80,12 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 21, n: 2, a: sb}, }, - order: []int{3, 2, 4, 1, 0}, + order: [][]int{ + {2, 1, 3, 0, 4}, + {3, 4, 2, 1, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, }, { txs: []txSpec{ @@ -73,118 +95,134 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 8, n: 2, a: sb}, }, - order: []int{3, 2, 4, 1, 0}, - }, - { - txs: []txSpec{ - {p: 30, a: sa, n: 2}, - {p: 20, a: sb, n: 1}, - {p: 15, a: sa, n: 1}, - {p: 10, a: sa, n: 0}, - {p: 8, a: sb, n: 0}, - {p: 6, a: sa, n: 3}, - {p: 4, a: sb, n: 3}, + order: [][]int{ + {2, 1, 3, 0, 4}, + {3, 4, 2, 1, 0}, }, - order: []int{4, 3, 1, 2, 0, 6, 5}, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, }, { txs: []txSpec{ - {p: 30, n: 2, a: sa}, + {p: 30, a: sa, n: 2}, {p: 20, a: sb, n: 1}, {p: 15, a: sa, n: 1}, {p: 10, a: sa, n: 0}, {p: 8, a: sb, n: 0}, {p: 6, a: sa, n: 3}, {p: 4, a: sb, n: 3}, - {p: 2, a: sc, n: 0}, - {p: 7, a: sc, n: 3}, }, - order: []int{4, 3, 7, 1, 2, 0, 6, 5, 8}, - }, - { - txs: []txSpec{ - {p: 6, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sb}, + order: [][]int{ + {3, 2, 4, 0, 1, 5, 6}, + {4, 1, 3, 6, 2, 0, 5}, }, - order: []int{2, 0, 3, 1}, - }, - { - // if all txs have the same priority they will be ordered lexically sender address, and nonce with the - // sender. - txs: []txSpec{ - {p: 10, n: 7, a: sc}, - {p: 10, n: 8, a: sc}, - {p: 10, n: 9, a: sc}, - {p: 10, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 10, n: 3, a: sa}, - {p: 10, n: 4, a: sb}, - {p: 10, n: 5, a: sb}, - {p: 10, n: 6, a: sb}, - }, - order: []int{3, 4, 5, 6, 7, 8, 0, 1, 2}, - }, - /* - The next 4 tests are different permutations of the same set: - - {p: 5, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 20, n: 2, a: sb}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sc}, - {p: 5, n: 1, a: sc}, - - which exercises the actions required to resolve priority ties. - */ - { - txs: []txSpec{ - {p: 5, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sb}, - }, - order: []int{2, 0, 3, 1}, - }, - { - txs: []txSpec{ - {p: 5, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 20, n: 2, a: sb}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sc}, - {p: 5, n: 1, a: sc}, - }, - order: []int{3, 0, 5, 2, 1, 4}, - }, - { - txs: []txSpec{ - {p: 5, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 5, n: 1, a: sb}, - {p: 20, n: 2, a: sb}, - {p: 5, n: 1, a: sc}, - {p: 99, n: 2, a: sc}, - }, - order: []int{2, 0, 4, 3, 1, 5}, - }, - { - txs: []txSpec{ - {p: 5, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 5, n: 1, a: sc}, - {p: 20, n: 2, a: sc}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sb}, - }, - order: []int{4, 0, 2, 5, 1, 3}, + // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 + seed: 0, }, + //{ + // txs: []txSpec{ + // {p: 30, n: 2, a: sa}, + // {p: 20, a: sb, n: 1}, + // {p: 15, a: sa, n: 1}, + // {p: 10, a: sa, n: 0}, + // {p: 8, a: sb, n: 0}, + // {p: 6, a: sa, n: 3}, + // {p: 4, a: sb, n: 3}, + // {p: 2, a: sc, n: 0}, + // {p: 7, a: sc, n: 3}, + // }, + // order: []int{4, 3, 7, 1, 2, 0, 6, 5, 8}, + // seed: 0, + //}, + //{ + // txs: []txSpec{ + // {p: 6, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 5, n: 1, a: sb}, + // {p: 99, n: 2, a: sb}, + // }, + // order: []int{2, 0, 3, 1}, + // seed: 0, + //}, + //{ + // // if all txs have the same priority they will be ordered lexically sender address, and nonce with the + // // sender. + // txs: []txSpec{ + // {p: 10, n: 7, a: sc}, + // {p: 10, n: 8, a: sc}, + // {p: 10, n: 9, a: sc}, + // {p: 10, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 10, n: 3, a: sa}, + // {p: 10, n: 4, a: sb}, + // {p: 10, n: 5, a: sb}, + // {p: 10, n: 6, a: sb}, + // }, + // order: []int{3, 4, 5, 6, 7, 8, 0, 1, 2}, + // seed: 0, + //}, + ///* + // The next 4 tests are different permutations of the same set: + // + // {p: 5, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 20, n: 2, a: sb}, + // {p: 5, n: 1, a: sb}, + // {p: 99, n: 2, a: sc}, + // {p: 5, n: 1, a: sc}, + // + // which exercises the actions required to resolve priority ties. + //*/ + //{ + // txs: []txSpec{ + // {p: 5, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 5, n: 1, a: sb}, + // {p: 99, n: 2, a: sb}, + // }, + // order: []int{2, 0, 3, 1}, + // seed: 0, + //}, + //{ + // txs: []txSpec{ + // {p: 5, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 20, n: 2, a: sb}, + // {p: 5, n: 1, a: sb}, + // {p: 99, n: 2, a: sc}, + // {p: 5, n: 1, a: sc}, + // }, + // order: []int{3, 0, 5, 2, 1, 4}, + // seed: 0, + //}, + //{ + // txs: []txSpec{ + // {p: 5, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 5, n: 1, a: sb}, + // {p: 20, n: 2, a: sb}, + // {p: 5, n: 1, a: sc}, + // {p: 99, n: 2, a: sc}, + // }, + // order: []int{2, 0, 4, 3, 1, 5}, + // seed: 0, + //}, + //{ + // txs: []txSpec{ + // {p: 5, n: 1, a: sa}, + // {p: 10, n: 2, a: sa}, + // {p: 5, n: 1, a: sc}, + // {p: 20, n: 2, a: sc}, + // {p: 5, n: 1, a: sb}, + // {p: 99, n: 2, a: sb}, + // }, + // order: []int{4, 0, 2, 5, 1, 3}, + // seed: 0, + //}, } for i, tt := range tests { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { - pool := s.mempool - + pool := mempool.NewSenderNonceMempoolWithSeed(tt.seed) // create test txs and insert into mempool for i, ts := range tt.txs { tx := testTx{id: i, priority: int64(ts.p), nonce: uint64(ts.n), address: ts.a} @@ -202,8 +240,13 @@ func (s *MempoolTestSuite) TestTxOrder() { for _, tx := range orderedTxs { require.NoError(t, pool.Remove(tx)) } - - require.Equal(t, tt.order, txOrder) + //orderCorrect := false + //for _, order := range tt.order { + // orderCorrect = orderCorrect || reflect.DeepEqual(order, txOrder) + //} + //require.True(t, orderCorrect) + require.Contains(t, fmt.Sprintf("%v", tt.order), fmt.Sprintf("%v", txOrder)) + //require.Equal(t, tt.order, txOrder) require.Equal(t, 0, pool.CountTx()) }) } diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index d8666c2f7796..128ce29c0e6e 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -64,11 +64,21 @@ func NewSenderNonceMempool() Mempool { senders: senderMap, txCount: 0, } - snp.SetSeed(time.Now().UnixNano()) + snp.setSeed(time.Now().UnixNano()) return snp } -func (snm *senderNonceMempool) SetSeed(seed int64) { +func NewSenderNonceMempoolWithSeed(seed int64) Mempool { + senderMap := make(map[string]*senderTxs) + snp := &senderNonceMempool{ + senders: senderMap, + txCount: 0, + } + snp.setSeed(seed) + return snp +} + +func (snm *senderNonceMempool) setSeed(seed int64) { s1 := rand.NewSource(seed) snm.rnd = rand.New(s1) } @@ -161,6 +171,7 @@ type senderNonceMepoolIterator struct { func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.mempool.rnd.Intn(len(i.senders)) + fmt.Println(senderIndex) sender := i.senders[senderIndex] senderTxs, found := i.mempool.senders[sender] if !found { From 87c221f040a46e4f3600f0a082e3030a45d1f2e3 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 09:55:59 -0500 Subject: [PATCH 10/49] change count --- types/mempool/mempool_test.go | 6 ++---- types/mempool/sender_nonce.go | 12 +++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/types/mempool/mempool_test.go b/types/mempool/mempool_test.go index be9e3997d497..6bbd393ffeca 100644 --- a/types/mempool/mempool_test.go +++ b/types/mempool/mempool_test.go @@ -150,8 +150,7 @@ func (s *MempoolTestSuite) TestDefaultMempool() { err := s.mempool.Insert(ctx, tx) require.NoError(t, err) } - // TODO add validity check to see if it exist not insert. Maybe a map ? - //require.Equal(t, len(accounts), s.mempool.CountTx()) + require.Equal(t, len(accounts), s.mempool.CountTx()) // distinct sender-nonce should not overwrite a tx s.resetMempool() @@ -184,14 +183,13 @@ func (s *MempoolTestSuite) TestDefaultMempool() { require.ErrorIs(t, s.mempool.Remove(txs[1]), mempool.ErrTxNotFound) // inserting a tx with a different priority should overwrite the old tx - // TODO there is no longer priorities newPriorityTx := testTx{ address: txs[0].address, priority: txs[0].priority + 1, nonce: txs[0].nonce, } require.NoError(t, s.mempool.Insert(ctx, newPriorityTx)) - //require.Equal(t, 1, s.mempool.CountTx()) + require.Equal(t, 1, s.mempool.CountTx()) } type MempoolTestSuite struct { diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 128ce29c0e6e..dedbde33108c 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -54,7 +54,6 @@ func (s *senderTxs) remove(key txKey) error { type senderNonceMempool struct { senders map[string]*senderTxs - txCount int rnd *rand.Rand } @@ -62,7 +61,6 @@ func NewSenderNonceMempool() Mempool { senderMap := make(map[string]*senderTxs) snp := &senderNonceMempool{ senders: senderMap, - txCount: 0, } snp.setSeed(time.Now().UnixNano()) return snp @@ -72,7 +70,6 @@ func NewSenderNonceMempoolWithSeed(seed int64) Mempool { senderMap := make(map[string]*senderTxs) snp := &senderNonceMempool{ senders: senderMap, - txCount: 0, } snp.setSeed(seed) return snp @@ -103,7 +100,6 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { tk := txKey{nonce: nonce, sender: sender} senderTxs.insert(tk, tx) snm.senders[sender] = senderTxs - snm.txCount = snm.txCount + 1 return nil } @@ -126,7 +122,11 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { - return snm.txCount + count := 0 + for _, sender := range snm.senders { + count = count + sender.txQueue.Len() + } + return count } // Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx @@ -157,7 +157,6 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { } else { snm.senders[sender] = senderTxs } - snm.txCount = snm.txCount - 1 return nil } @@ -171,7 +170,6 @@ type senderNonceMepoolIterator struct { func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.mempool.rnd.Intn(len(i.senders)) - fmt.Println(senderIndex) sender := i.senders[senderIndex] senderTxs, found := i.mempool.senders[sender] if !found { From 94334f5e89a5725f574a2e77b3ae1e8e7cf4d534 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 10:23:20 -0500 Subject: [PATCH 11/49] finish tx order test removed the three address test due to make the test to bloated when including non determinism --- types/mempool/nonce_test.go | 124 ++++++------------------------------ 1 file changed, 18 insertions(+), 106 deletions(-) diff --git a/types/mempool/nonce_test.go b/types/mempool/nonce_test.go index 847e3939e8fc..075318e5be97 100644 --- a/types/mempool/nonce_test.go +++ b/types/mempool/nonce_test.go @@ -119,106 +119,20 @@ func (s *MempoolTestSuite) TestTxOrder() { // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 seed: 0, }, - //{ - // txs: []txSpec{ - // {p: 30, n: 2, a: sa}, - // {p: 20, a: sb, n: 1}, - // {p: 15, a: sa, n: 1}, - // {p: 10, a: sa, n: 0}, - // {p: 8, a: sb, n: 0}, - // {p: 6, a: sa, n: 3}, - // {p: 4, a: sb, n: 3}, - // {p: 2, a: sc, n: 0}, - // {p: 7, a: sc, n: 3}, - // }, - // order: []int{4, 3, 7, 1, 2, 0, 6, 5, 8}, - // seed: 0, - //}, - //{ - // txs: []txSpec{ - // {p: 6, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 5, n: 1, a: sb}, - // {p: 99, n: 2, a: sb}, - // }, - // order: []int{2, 0, 3, 1}, - // seed: 0, - //}, - //{ - // // if all txs have the same priority they will be ordered lexically sender address, and nonce with the - // // sender. - // txs: []txSpec{ - // {p: 10, n: 7, a: sc}, - // {p: 10, n: 8, a: sc}, - // {p: 10, n: 9, a: sc}, - // {p: 10, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 10, n: 3, a: sa}, - // {p: 10, n: 4, a: sb}, - // {p: 10, n: 5, a: sb}, - // {p: 10, n: 6, a: sb}, - // }, - // order: []int{3, 4, 5, 6, 7, 8, 0, 1, 2}, - // seed: 0, - //}, - ///* - // The next 4 tests are different permutations of the same set: - // - // {p: 5, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 20, n: 2, a: sb}, - // {p: 5, n: 1, a: sb}, - // {p: 99, n: 2, a: sc}, - // {p: 5, n: 1, a: sc}, - // - // which exercises the actions required to resolve priority ties. - //*/ - //{ - // txs: []txSpec{ - // {p: 5, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 5, n: 1, a: sb}, - // {p: 99, n: 2, a: sb}, - // }, - // order: []int{2, 0, 3, 1}, - // seed: 0, - //}, - //{ - // txs: []txSpec{ - // {p: 5, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 20, n: 2, a: sb}, - // {p: 5, n: 1, a: sb}, - // {p: 99, n: 2, a: sc}, - // {p: 5, n: 1, a: sc}, - // }, - // order: []int{3, 0, 5, 2, 1, 4}, - // seed: 0, - //}, - //{ - // txs: []txSpec{ - // {p: 5, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 5, n: 1, a: sb}, - // {p: 20, n: 2, a: sb}, - // {p: 5, n: 1, a: sc}, - // {p: 99, n: 2, a: sc}, - // }, - // order: []int{2, 0, 4, 3, 1, 5}, - // seed: 0, - //}, - //{ - // txs: []txSpec{ - // {p: 5, n: 1, a: sa}, - // {p: 10, n: 2, a: sa}, - // {p: 5, n: 1, a: sc}, - // {p: 20, n: 2, a: sc}, - // {p: 5, n: 1, a: sb}, - // {p: 99, n: 2, a: sb}, - // }, - // order: []int{4, 0, 2, 5, 1, 3}, - // seed: 0, - //}, + { + txs: []txSpec{ + {p: 6, n: 1, a: sa}, + {p: 10, n: 2, a: sa}, + {p: 5, n: 1, a: sb}, + {p: 99, n: 2, a: sb}, + }, + order: [][]int{ + {0, 1, 2, 3}, + {2, 3, 0, 1}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 + seed: 0, + }, } for i, tt := range tests { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { @@ -240,14 +154,12 @@ func (s *MempoolTestSuite) TestTxOrder() { for _, tx := range orderedTxs { require.NoError(t, pool.Remove(tx)) } - //orderCorrect := false - //for _, order := range tt.order { - // orderCorrect = orderCorrect || reflect.DeepEqual(order, txOrder) - //} - //require.True(t, orderCorrect) require.Contains(t, fmt.Sprintf("%v", tt.order), fmt.Sprintf("%v", txOrder)) - //require.Equal(t, tt.order, txOrder) require.Equal(t, 0, pool.CountTx()) }) } } + +func (s *MempoolTestSuite) TestNormalDistributionTxSelection() { + +} From 24ebefe76fdf930974b864f21593c73f4002da91 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 10:32:19 -0500 Subject: [PATCH 12/49] remove unsued variable --- types/mempool/sender_nonce.go | 1 - 1 file changed, 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index dedbde33108c..420e4674a4ed 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -164,7 +164,6 @@ type senderNonceMepoolIterator struct { mempool *senderNonceMempool currentTx *huandu.Element senders []string - seed int } func (i *senderNonceMepoolIterator) Next() Iterator { From 584bc51afe6d49c20abf7c41546feb287bbed2b3 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 10:34:04 -0500 Subject: [PATCH 13/49] nit --- types/mempool/sender_nonce.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 420e4674a4ed..5c4908fc33f6 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -124,7 +124,7 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator func (snm *senderNonceMempool) CountTx() int { count := 0 for _, sender := range snm.senders { - count = count + sender.txQueue.Len() + count += sender.txQueue.Len() } return count } From fe3fbf8ddefef64af3ef1739b91f951c6d143ac1 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 10:47:29 -0500 Subject: [PATCH 14/49] fix --- types/mempool/sender_nonce.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 5c4908fc33f6..ffbf3c64ab8d 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -123,8 +123,8 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { count := 0 - for _, sender := range snm.senders { - count += sender.txQueue.Len() + for senderKey := range snm.senders { + count += snm.senders[senderKey].txQueue.Len() } return count } From 2a18e817e09053692a60848e11b429b3c565f2e6 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Thu, 17 Nov 2022 19:54:37 -0500 Subject: [PATCH 15/49] temoral commit braking --- types/mempool/nonce_test.go | 1 - types/mempool/sender_nonce_test.go | 84 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 types/mempool/sender_nonce_test.go diff --git a/types/mempool/nonce_test.go b/types/mempool/nonce_test.go index 075318e5be97..30fdab8fe36d 100644 --- a/types/mempool/nonce_test.go +++ b/types/mempool/nonce_test.go @@ -20,7 +20,6 @@ func (s *MempoolTestSuite) TestTxOrder() { accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 5) sa := accounts[0].Address sb := accounts[1].Address - //sc := accounts[2].Address tests := []struct { txs []txSpec diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go new file mode 100644 index 000000000000..1f3b3539f3b9 --- /dev/null +++ b/types/mempool/sender_nonce_test.go @@ -0,0 +1,84 @@ +package mempool_test + +import ( + "fmt" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + mempool2 "github.com/cosmos/cosmos-sdk/types/mempool" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "math/rand" + "pgregory.net/rapid" +) + +var ( + _ sdk.Tx = (*testTx)(nil) + _ signing.SigVerifiableTx = (*testTx)(nil) + _ cryptotypes.PubKey = (*testPubKey)(nil) +) + +// Property Based Testing +// Split the senders tx in independent slices and then test the following properties in each slice +// same elements input output +// the reverse of the reverse of the list is the same +// for every sequence element pair a, b a < b + +func testMempoolProperties(t *rapid.T) { + + ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) + mempool := mempool2.NewSenderNonceMempool() + genAddress := rapid.Custom(func(t *rapid.T) simtypes.Account { + accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(rapid.Int64().Draw(t, "seed for account"))), 1) + return accounts[0] + }) + genMultipleAddress := rapid.SliceOfDistinct(genAddress, func(acc simtypes.Account) string { + return acc.Address.String() + }) + + accounts := genMultipleAddress.Draw(t, "address") + fmt.Println(accounts) + genTx := rapid.Custom(func(t *rapid.T) testTx { + return testTx{ + priority: rapid.Int64Range(0, 1000).Draw(t, "priority"), + nonce: rapid.Uint64().Draw(t, "nonce"), + address: rapid.SampledFrom(accounts).Draw(t, "acc").Address, + } + //fmt.Println("genTX:", tx) + //return tx + + }) + fmt.Println(genTx) + genMultipleTX := rapid.SliceOf(genTx) + + txs := genMultipleTX.Draw(t, "txs") + fmt.Println("txs:", txs) + + for _, tx := range txs { + fmt.Println("tx", tx) + fmt.Println(ctx) + fmt.Println(mempool) + //err := mempool.Insert(ctx, tx) + //require.NoError(t, err) + } + + test := rapid.SliceOf(rapid.Int().AsAny()) + for i := 0; i < 5; i++ { + fmt.Println(i) + fmt.Println(test.Example(i)) + fmt.Println(genMultipleAddress.Example(i)) + fmt.Println(genMultipleTX.Example(i)) + + } + + require.True(t, false) + +} + +func (s *MempoolTestSuite) TestProperties() { + t := s.T() + rapid.Check(t, testMempoolProperties) +} From 7784594f9df6ba1f35cccb2689757da1cffa11f3 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 11:44:50 -0500 Subject: [PATCH 16/49] nit most --- types/mempool/sender_nonce_test.go | 66 +++++++++++++++++++----------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go index 1f3b3539f3b9..dd368bdc625a 100644 --- a/types/mempool/sender_nonce_test.go +++ b/types/mempool/sender_nonce_test.go @@ -4,12 +4,13 @@ import ( "fmt" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" - mempool2 "github.com/cosmos/cosmos-sdk/types/mempool" + mempool "github.com/cosmos/cosmos-sdk/types/mempool" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "sort" "math/rand" "pgregory.net/rapid" @@ -30,7 +31,7 @@ var ( func testMempoolProperties(t *rapid.T) { ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) - mempool := mempool2.NewSenderNonceMempool() + mp := mempool.NewSenderNonceMempool() genAddress := rapid.Custom(func(t *rapid.T) simtypes.Account { accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(rapid.Int64().Draw(t, "seed for account"))), 1) return accounts[0] @@ -40,45 +41,64 @@ func testMempoolProperties(t *rapid.T) { }) accounts := genMultipleAddress.Draw(t, "address") - fmt.Println(accounts) genTx := rapid.Custom(func(t *rapid.T) testTx { return testTx{ priority: rapid.Int64Range(0, 1000).Draw(t, "priority"), nonce: rapid.Uint64().Draw(t, "nonce"), address: rapid.SampledFrom(accounts).Draw(t, "acc").Address, } - //fmt.Println("genTX:", tx) - //return tx - }) - fmt.Println(genTx) genMultipleTX := rapid.SliceOf(genTx) txs := genMultipleTX.Draw(t, "txs") - fmt.Println("txs:", txs) + senderTxRaw := getSenderTxMap(txs) for _, tx := range txs { - fmt.Println("tx", tx) - fmt.Println(ctx) - fmt.Println(mempool) - //err := mempool.Insert(ctx, tx) - //require.NoError(t, err) + err := mp.Insert(ctx, tx) + require.NoError(t, err) } - test := rapid.SliceOf(rapid.Int().AsAny()) - for i := 0; i < 5; i++ { - fmt.Println(i) - fmt.Println(test.Example(i)) - fmt.Println(genMultipleAddress.Example(i)) - fmt.Println(genMultipleTX.Example(i)) - + iter := mp.Select(ctx, nil) + orderTx := make([]testTx, 0) + for _, tx := range fetchAllTxs(iter) { + orderTx = append(orderTx, tx.(testTx)) + } + senderTxOrdered := getSenderTxMap(orderTx) + fmt.Println(senderTxOrdered) + for key := range senderTxOrdered { + ordered, found := senderTxOrdered[key] + require.True(t, found) + raw, found := senderTxRaw[key] + require.True(t, found) + sort.Slice(raw, func(i, j int) bool { return raw[i].nonce < raw[j].nonce }) + require.Equal(t, raw, ordered) } - - require.True(t, false) - } func (s *MempoolTestSuite) TestProperties() { t := s.T() rapid.Check(t, testMempoolProperties) } + +func getSenderTxMap(txs []testTx) map[string][]testTx { + senderTxs := make(map[string][]testTx) + for _, tx := range txs { + stx, found := senderTxs[tx.address.String()] + if !found { + stx = make([]testTx, 0) + } + stx = append(stx, tx) + senderTxs[tx.address.String()] = stx + } + return senderTxs +} + +func fetchAllTxs(iterator mempool.Iterator) []sdk.Tx { + var txs []sdk.Tx + for iterator != nil { + txs = append(txs, iterator.Tx()) + i := iterator.Next() + iterator = i + } + return txs +} From d34cd881ccb482a304cfe9f0328a5d19fac501b4 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 11:48:24 -0500 Subject: [PATCH 17/49] nit most --- types/mempool/sender_nonce_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go index dd368bdc625a..7b18e08fc6a4 100644 --- a/types/mempool/sender_nonce_test.go +++ b/types/mempool/sender_nonce_test.go @@ -1,7 +1,6 @@ package mempool_test import ( - "fmt" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" mempool "github.com/cosmos/cosmos-sdk/types/mempool" @@ -64,7 +63,6 @@ func testMempoolProperties(t *rapid.T) { orderTx = append(orderTx, tx.(testTx)) } senderTxOrdered := getSenderTxMap(orderTx) - fmt.Println(senderTxOrdered) for key := range senderTxOrdered { ordered, found := senderTxOrdered[key] require.True(t, found) From 5a385cb80d22de0f9c1b42a9be4e12ca73bb162d Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 12:28:16 -0500 Subject: [PATCH 18/49] final --- types/mempool/nonce_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/types/mempool/nonce_test.go b/types/mempool/nonce_test.go index 30fdab8fe36d..5d5420615b4f 100644 --- a/types/mempool/nonce_test.go +++ b/types/mempool/nonce_test.go @@ -158,7 +158,3 @@ func (s *MempoolTestSuite) TestTxOrder() { }) } } - -func (s *MempoolTestSuite) TestNormalDistributionTxSelection() { - -} From 9e02590c14517332c6cda7f1b4f7d0108f24a4d6 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 16:39:51 -0500 Subject: [PATCH 19/49] comments --- baseapp/baseapp.go | 2 +- types/mempool/nonce.go | 125 ---------------- types/mempool/nonce_test.go | 160 -------------------- types/mempool/sender_nonce.go | 106 +++++++------ types/mempool/sender_nonce_test.go | 232 ++++++++++++++++++----------- 5 files changed, 198 insertions(+), 427 deletions(-) delete mode 100644 types/mempool/nonce.go delete mode 100644 types/mempool/nonce_test.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 31f61e7199d1..2f227f8b4bde 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -170,7 +170,7 @@ func NewBaseApp( } if app.mempool == nil { - app.SetMempool(mempool.NewNonceMempool()) + app.SetMempool(mempool.NewSenderNonceMempool()) } if app.processProposal == nil { diff --git a/types/mempool/nonce.go b/types/mempool/nonce.go deleted file mode 100644 index 3b63f26d74c0..000000000000 --- a/types/mempool/nonce.go +++ /dev/null @@ -1,125 +0,0 @@ -package mempool - -import ( - "fmt" - - huandu "github.com/huandu/skiplist" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/signing" -) - -var ( - _ Mempool = (*nonceMempool)(nil) - _ Iterator = (*nonceMempoolIterator)(nil) -) - -// 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. -type nonceMempool struct { - txQueue *huandu.SkipList -} - -type nonceMempoolIterator struct { - currentTx *huandu.Element -} - -func (i nonceMempoolIterator) Next() Iterator { - if i.currentTx == nil { - return nil - } else if n := i.currentTx.Next(); n != nil { - return nonceMempoolIterator{currentTx: n} - } else { - return nil - } -} - -func (i nonceMempoolIterator) Tx() sdk.Tx { - return i.currentTx.Value.(sdk.Tx) -} - -type txKey struct { - nonce uint64 - sender string -} - -// txKeyLessNonce compares two txKeys by nonce then by sender address. -func txKeyLessNonce(a, b any) int { - keyA := a.(txKey) - keyB := b.(txKey) - - res := huandu.Uint64.Compare(keyB.nonce, keyA.nonce) - if res != 0 { - return res - } - - return huandu.String.Compare(keyB.sender, keyA.sender) -} - -// NewNonceMempool creates a new mempool that prioritizes transactions by nonce, the lowest first. -func NewNonceMempool() Mempool { - sp := &nonceMempool{ - txQueue: huandu.New(huandu.LessThanFunc(txKeyLessNonce)), - } - - return sp -} - -// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer. -// priority is ignored. -func (sp nonceMempool) 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 - tk := txKey{nonce: nonce, sender: sender} - sp.txQueue.Set(tk, tx) - return nil -} - -// Select returns an iterator ordering transactions the mempool with the lowest nonce globally first. A sender's txs -// will always be returned in nonce order. -func (sp nonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { - currentTx := sp.txQueue.Front() - if currentTx == nil { - return nil - } - - return &nonceMempoolIterator{currentTx: currentTx} -} - -// CountTx returns the number of txs in the mempool. -func (sp nonceMempool) CountTx() int { - 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 -// was not found in the pool. -func (sp nonceMempool) 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} - res := sp.txQueue.Remove(tk) - if res == nil { - return ErrTxNotFound - } - return nil -} diff --git a/types/mempool/nonce_test.go b/types/mempool/nonce_test.go deleted file mode 100644 index 5d5420615b4f..000000000000 --- a/types/mempool/nonce_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package mempool_test - -import ( - "fmt" - "github.com/cosmos/cosmos-sdk/types/mempool" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func (s *MempoolTestSuite) TestTxOrder() { - t := s.T() - ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) - accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 5) - sa := accounts[0].Address - sb := accounts[1].Address - - tests := []struct { - txs []txSpec - order [][]int - fail bool - seed int64 - }{ - { - txs: []txSpec{ - {p: 21, n: 4, a: sa}, - {p: 8, n: 3, a: sa}, - {p: 6, n: 2, a: sa}, - {p: 15, n: 1, a: sb}, - {p: 20, n: 1, a: sa}, - }, - order: [][]int{ - {4, 2, 3, 1, 0}, - {3, 4, 2, 1, 0}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 3, n: 0, a: sa}, - {p: 5, n: 1, a: sa}, - {p: 9, n: 2, a: sa}, - {p: 6, n: 0, a: sb}, - {p: 5, n: 1, a: sb}, - {p: 8, n: 2, a: sb}, - }, - order: [][]int{ - {0, 1, 3, 2, 4, 5}, - {3, 4, 0, 5, 1, 2}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 21, n: 4, a: sa}, - {p: 15, n: 1, a: sb}, - {p: 20, n: 1, a: sa}, - }, - order: [][]int{ - {2, 0, 1}, - {1, 2, 0}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 50, n: 3, a: sa}, - {p: 30, n: 2, a: sa}, - {p: 10, n: 1, a: sa}, - {p: 15, n: 1, a: sb}, - {p: 21, n: 2, a: sb}, - }, - order: [][]int{ - {2, 1, 3, 0, 4}, - {3, 4, 2, 1, 0}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 50, n: 3, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 99, n: 1, a: sa}, - {p: 15, n: 1, a: sb}, - {p: 8, n: 2, a: sb}, - }, - order: [][]int{ - {2, 1, 3, 0, 4}, - {3, 4, 2, 1, 0}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 30, a: sa, n: 2}, - {p: 20, a: sb, n: 1}, - {p: 15, a: sa, n: 1}, - {p: 10, a: sa, n: 0}, - {p: 8, a: sb, n: 0}, - {p: 6, a: sa, n: 3}, - {p: 4, a: sb, n: 3}, - }, - order: [][]int{ - {3, 2, 4, 0, 1, 5, 6}, - {4, 1, 3, 6, 2, 0, 5}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 - seed: 0, - }, - { - txs: []txSpec{ - {p: 6, n: 1, a: sa}, - {p: 10, n: 2, a: sa}, - {p: 5, n: 1, a: sb}, - {p: 99, n: 2, a: sb}, - }, - order: [][]int{ - {0, 1, 2, 3}, - {2, 3, 0, 1}, - }, - // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 - seed: 0, - }, - } - for i, tt := range tests { - t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { - pool := mempool.NewSenderNonceMempoolWithSeed(tt.seed) - // create test txs and insert into mempool - for i, ts := range tt.txs { - tx := testTx{id: i, priority: int64(ts.p), nonce: uint64(ts.n), address: ts.a} - c := ctx.WithPriority(tx.priority) - err := pool.Insert(c, tx) - require.NoError(t, err) - } - - itr := pool.Select(ctx, nil) - orderedTxs := fetchTxs(itr, 1000) - var txOrder []int - for _, tx := range orderedTxs { - txOrder = append(txOrder, tx.(testTx).id) - } - for _, tx := range orderedTxs { - require.NoError(t, pool.Remove(tx)) - } - require.Contains(t, fmt.Sprintf("%v", tt.order), fmt.Sprintf("%v", txOrder)) - require.Equal(t, 0, pool.CountTx()) - }) - } -} diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index ffbf3c64ab8d..718879ec2a27 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -1,9 +1,10 @@ package mempool import ( + crand "crypto/rand" + "encoding/binary" "fmt" "math/rand" - "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -12,62 +13,50 @@ import ( var ( _ Mempool = (*senderNonceMempool)(nil) - _ Iterator = (*nonceMempoolIterator)(nil) + _ Iterator = (*senderNonceMepoolIterator)(nil) ) type senderTxs struct { - txQueue *huandu.SkipList - head *huandu.Element + cursor *huandu.Element } -func newSenderTxs() senderTxs { +func newSenderTxs(tx *huandu.Element) senderTxs { return senderTxs{ - head: nil, - txQueue: huandu.New(huandu.LessThanFunc(txKeyLessNonce)), + cursor: tx, } } -func (s *senderTxs) insert(key txKey, tx sdk.Tx) { - s.txQueue.Set(key, tx) - s.head = s.txQueue.Front() -} - -func (s *senderTxs) getMove() *huandu.Element { - if s.head == nil { +func (s *senderTxs) next() *huandu.Element { + if s.cursor == 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() - } - return nil + currentCursor := s.cursor + s.cursor = s.cursor.Next() + return currentCursor } type senderNonceMempool struct { - senders map[string]*senderTxs + senders map[string]*huandu.SkipList rnd *rand.Rand } +// NewSenderNonceMempool creates a new mempool that prioritizes transactions by nonce, the lowest first. func NewSenderNonceMempool() Mempool { - senderMap := make(map[string]*senderTxs) + senderMap := make(map[string]*huandu.SkipList) snp := &senderNonceMempool{ senders: senderMap, } - snp.setSeed(time.Now().UnixNano()) + + var seed int64 + binary.Read(crand.Reader, binary.BigEndian, &seed) + snp.setSeed(seed) + return snp } +// NewSenderNonceMempoolWithSeed creates a new mempool that prioritizes transactions by nonce, the lowest first and sets the random seed. func NewSenderNonceMempoolWithSeed(seed int64) Mempool { - senderMap := make(map[string]*senderTxs) + senderMap := make(map[string]*huandu.SkipList) snp := &senderNonceMempool{ senders: senderMap, } @@ -80,6 +69,8 @@ func (snm *senderNonceMempool) setSeed(seed int64) { snm.rnd = rand.New(s1) } +// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer. +// priority is ignored. func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2() if err != nil { @@ -94,23 +85,27 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { nonce := sig.Sequence senderTxs, found := snm.senders[sender] if !found { - newSenderTx := newSenderTxs() - senderTxs = &newSenderTx + senderTxs = huandu.New(huandu.Uint64) } - tk := txKey{nonce: nonce, sender: sender} - senderTxs.insert(tk, tx) + senderTxs.Set(nonce, tx) snm.senders[sender] = senderTxs return nil } +// Select returns an iterator ordering transactions the mempool with the lowest nonce of a random selected sender first. func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { var senders []string + senderCursors := make(map[string]*senderTxs) for key := range snm.senders { senders = append(senders, key) + senderTx := newSenderTxs(snm.senders[key].Front()) + senderCursors[key] = &senderTx } + iter := &senderNonceMepoolIterator{ - mempool: snm, - senders: senders, + senders: senders, + rnd: snm.rnd, + sendersCurosors: senderCursors, } newIter := iter.Next() @@ -123,8 +118,8 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { count := 0 - for senderKey := range snm.senders { - count += snm.senders[senderKey].txQueue.Len() + for _, value := range snm.senders { + count += value.Len() } return count } @@ -143,16 +138,17 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { 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 + + res := senderTxs.Remove(nonce) + if res == nil { + return ErrTxNotFound } - if senderTxs.txQueue.Len() == 0 { + + if senderTxs.Len() == 0 { delete(snm.senders, sender) } else { snm.senders[sender] = senderTxs @@ -161,29 +157,31 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { } type senderNonceMepoolIterator struct { - mempool *senderNonceMempool - currentTx *huandu.Element - senders []string + rnd *rand.Rand + currentTx *huandu.Element + senders []string + sendersCurosors map[string]*senderTxs } func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { - senderIndex := i.mempool.rnd.Intn(len(i.senders)) + senderIndex := i.rnd.Intn(len(i.senders)) sender := i.senders[senderIndex] - senderTxs, found := i.mempool.senders[sender] + senderTxs, found := i.sendersCurosors[sender] if !found { i.senders = removeAtIndex(i.senders, senderIndex) continue } - tx := senderTxs.getMove() + tx := senderTxs.next() if tx == nil { i.senders = removeAtIndex(i.senders, senderIndex) continue } return &senderNonceMepoolIterator{ - senders: i.senders, - currentTx: tx, - mempool: i.mempool, + senders: i.senders, + currentTx: tx, + rnd: i.rnd, + sendersCurosors: i.sendersCurosors, } } diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go index 7b18e08fc6a4..5d5420615b4f 100644 --- a/types/mempool/sender_nonce_test.go +++ b/types/mempool/sender_nonce_test.go @@ -1,102 +1,160 @@ package mempool_test import ( - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - mempool "github.com/cosmos/cosmos-sdk/types/mempool" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/signing" + "fmt" + "github.com/cosmos/cosmos-sdk/types/mempool" + "math/rand" + "testing" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "sort" - - "math/rand" - "pgregory.net/rapid" -) -var ( - _ sdk.Tx = (*testTx)(nil) - _ signing.SigVerifiableTx = (*testTx)(nil) - _ cryptotypes.PubKey = (*testPubKey)(nil) + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) -// Property Based Testing -// Split the senders tx in independent slices and then test the following properties in each slice -// same elements input output -// the reverse of the reverse of the list is the same -// for every sequence element pair a, b a < b - -func testMempoolProperties(t *rapid.T) { - - ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) - mp := mempool.NewSenderNonceMempool() - genAddress := rapid.Custom(func(t *rapid.T) simtypes.Account { - accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(rapid.Int64().Draw(t, "seed for account"))), 1) - return accounts[0] - }) - genMultipleAddress := rapid.SliceOfDistinct(genAddress, func(acc simtypes.Account) string { - return acc.Address.String() - }) - - accounts := genMultipleAddress.Draw(t, "address") - genTx := rapid.Custom(func(t *rapid.T) testTx { - return testTx{ - priority: rapid.Int64Range(0, 1000).Draw(t, "priority"), - nonce: rapid.Uint64().Draw(t, "nonce"), - address: rapid.SampledFrom(accounts).Draw(t, "acc").Address, - } - }) - genMultipleTX := rapid.SliceOf(genTx) - - txs := genMultipleTX.Draw(t, "txs") - senderTxRaw := getSenderTxMap(txs) - - for _, tx := range txs { - err := mp.Insert(ctx, tx) - require.NoError(t, err) - } - - iter := mp.Select(ctx, nil) - orderTx := make([]testTx, 0) - for _, tx := range fetchAllTxs(iter) { - orderTx = append(orderTx, tx.(testTx)) - } - senderTxOrdered := getSenderTxMap(orderTx) - for key := range senderTxOrdered { - ordered, found := senderTxOrdered[key] - require.True(t, found) - raw, found := senderTxRaw[key] - require.True(t, found) - sort.Slice(raw, func(i, j int) bool { return raw[i].nonce < raw[j].nonce }) - require.Equal(t, raw, ordered) - } -} - -func (s *MempoolTestSuite) TestProperties() { +func (s *MempoolTestSuite) TestTxOrder() { t := s.T() - rapid.Check(t, testMempoolProperties) -} + ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) + accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 5) + sa := accounts[0].Address + sb := accounts[1].Address -func getSenderTxMap(txs []testTx) map[string][]testTx { - senderTxs := make(map[string][]testTx) - for _, tx := range txs { - stx, found := senderTxs[tx.address.String()] - if !found { - stx = make([]testTx, 0) - } - stx = append(stx, tx) - senderTxs[tx.address.String()] = stx + tests := []struct { + txs []txSpec + order [][]int + fail bool + seed int64 + }{ + { + txs: []txSpec{ + {p: 21, n: 4, a: sa}, + {p: 8, n: 3, a: sa}, + {p: 6, n: 2, a: sa}, + {p: 15, n: 1, a: sb}, + {p: 20, n: 1, a: sa}, + }, + order: [][]int{ + {4, 2, 3, 1, 0}, + {3, 4, 2, 1, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 3, n: 0, a: sa}, + {p: 5, n: 1, a: sa}, + {p: 9, n: 2, a: sa}, + {p: 6, n: 0, a: sb}, + {p: 5, n: 1, a: sb}, + {p: 8, n: 2, a: sb}, + }, + order: [][]int{ + {0, 1, 3, 2, 4, 5}, + {3, 4, 0, 5, 1, 2}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 21, n: 4, a: sa}, + {p: 15, n: 1, a: sb}, + {p: 20, n: 1, a: sa}, + }, + order: [][]int{ + {2, 0, 1}, + {1, 2, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 50, n: 3, a: sa}, + {p: 30, n: 2, a: sa}, + {p: 10, n: 1, a: sa}, + {p: 15, n: 1, a: sb}, + {p: 21, n: 2, a: sb}, + }, + order: [][]int{ + {2, 1, 3, 0, 4}, + {3, 4, 2, 1, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 50, n: 3, a: sa}, + {p: 10, n: 2, a: sa}, + {p: 99, n: 1, a: sa}, + {p: 15, n: 1, a: sb}, + {p: 8, n: 2, a: sb}, + }, + order: [][]int{ + {2, 1, 3, 0, 4}, + {3, 4, 2, 1, 0}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 30, a: sa, n: 2}, + {p: 20, a: sb, n: 1}, + {p: 15, a: sa, n: 1}, + {p: 10, a: sa, n: 0}, + {p: 8, a: sb, n: 0}, + {p: 6, a: sa, n: 3}, + {p: 4, a: sb, n: 3}, + }, + order: [][]int{ + {3, 2, 4, 0, 1, 5, 6}, + {4, 1, 3, 6, 2, 0, 5}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 + seed: 0, + }, + { + txs: []txSpec{ + {p: 6, n: 1, a: sa}, + {p: 10, n: 2, a: sa}, + {p: 5, n: 1, a: sb}, + {p: 99, n: 2, a: sb}, + }, + order: [][]int{ + {0, 1, 2, 3}, + {2, 3, 0, 1}, + }, + // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 + seed: 0, + }, } - return senderTxs -} + for i, tt := range tests { + t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { + pool := mempool.NewSenderNonceMempoolWithSeed(tt.seed) + // create test txs and insert into mempool + for i, ts := range tt.txs { + tx := testTx{id: i, priority: int64(ts.p), nonce: uint64(ts.n), address: ts.a} + c := ctx.WithPriority(tx.priority) + err := pool.Insert(c, tx) + require.NoError(t, err) + } -func fetchAllTxs(iterator mempool.Iterator) []sdk.Tx { - var txs []sdk.Tx - for iterator != nil { - txs = append(txs, iterator.Tx()) - i := iterator.Next() - iterator = i + itr := pool.Select(ctx, nil) + orderedTxs := fetchTxs(itr, 1000) + var txOrder []int + for _, tx := range orderedTxs { + txOrder = append(txOrder, tx.(testTx).id) + } + for _, tx := range orderedTxs { + require.NoError(t, pool.Remove(tx)) + } + require.Contains(t, fmt.Sprintf("%v", tt.order), fmt.Sprintf("%v", txOrder)) + require.Equal(t, 0, pool.CountTx()) + }) } - return txs } From 11ceaa7dd18d48bedfeedd48ccc111c8a6909159 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 16:43:29 -0500 Subject: [PATCH 20/49] t --- types/mempool/sender_nonce.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 718879ec2a27..8551f36c4bd4 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -163,6 +163,8 @@ type senderNonceMepoolIterator struct { sendersCurosors map[string]*senderTxs } +// Next it returns the iterator next state where a iterator will contain a tx that was the smallest +// nonce of a randomly selected sender func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.rnd.Intn(len(i.senders)) From 6703390ade3d3d05635366dba3666a3bbd6a6436 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Fri, 18 Nov 2022 16:46:58 -0500 Subject: [PATCH 21/49] comments --- types/mempool/sender_nonce.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 8551f36c4bd4..9a7ffe27699a 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -86,9 +86,10 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { senderTxs, found := snm.senders[sender] if !found { senderTxs = huandu.New(huandu.Uint64) + snm.senders[sender] = senderTxs } senderTxs.Set(nonce, tx) - snm.senders[sender] = senderTxs + return nil } @@ -150,8 +151,6 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { if senderTxs.Len() == 0 { delete(snm.senders, sender) - } else { - snm.senders[sender] = senderTxs } return nil } From 7556b9f5e659b403cedab2c9f23d23aba574af2e Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Sun, 20 Nov 2022 14:13:35 -0500 Subject: [PATCH 22/49] test --- baseapp/abci_v1_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci_v1_test.go b/baseapp/abci_v1_test.go index 4bb6d9296aa9..c8b196414082 100644 --- a/baseapp/abci_v1_test.go +++ b/baseapp/abci_v1_test.go @@ -47,7 +47,7 @@ func TestABCIv1TestSuite(t *testing.T) { func (s *ABCIv1TestSuite) SetupTest() { t := s.T() anteKey := []byte("ante-key") - pool := mempool.NewNonceMempool() + pool := mempool.NewSenderNonceMempool() anteOpt := func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } From d388bc4dfd7eb6281b915ccf4de190acdee69059 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:02:14 -0600 Subject: [PATCH 23/49] add nolint --- types/mempool/sender_nonce.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 9a7ffe27699a..7f048cb0b8e6 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -6,9 +6,10 @@ import ( "fmt" "math/rand" + huandu "github.com/huandu/skiplist" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/signing" - huandu "github.com/huandu/skiplist" ) var ( @@ -119,6 +120,8 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { count := 0 + // nolint:gosec + // We neither need strong randomness here nor deterministic iteration. for _, value := range snm.senders { count += value.Len() } From 9ff7528961b6ccccf4064c9d34a858d4637b036b Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:10:32 -0600 Subject: [PATCH 24/49] Fix comment --- types/mempool/sender_nonce.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 7f048cb0b8e6..facd202cad40 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -95,7 +95,7 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { } // Select returns an iterator ordering transactions the mempool with the lowest nonce of a random selected sender first. -func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator { +func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { var senders []string senderCursors := make(map[string]*senderTxs) for key := range snm.senders { @@ -120,8 +120,8 @@ func (snm *senderNonceMempool) Select(context sdk.Context, i [][]byte) Iterator // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { count := 0 - // nolint:gosec - // We neither need strong randomness here nor deterministic iteration. + // We need neither strong randomness nor deterministic iteration here. + //nolint:gosec for _, value := range snm.senders { count += value.Len() } From ec50ee68d53bcc06d3c5e9d5db290956d6e590c8 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:21:00 -0600 Subject: [PATCH 25/49] golint comment --- types/mempool/sender_nonce.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index facd202cad40..8750a8d44856 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -120,9 +120,8 @@ func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { // CountTx returns the total count of txs in the mempool. func (snm *senderNonceMempool) CountTx() int { count := 0 - // We need neither strong randomness nor deterministic iteration here. - //nolint:gosec - for _, value := range snm.senders { + + for _, value := range snm.senders { //nolint:gosec // we need neither strong randomness nor deterministic iteration count += value.Len() } return count From bc851a9e9b85d7cadee8d0e9031bc402eef0d466 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:50:11 -0600 Subject: [PATCH 26/49] golint --- types/mempool/sender_nonce.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 8750a8d44856..679a92d12c68 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -122,8 +122,8 @@ func (snm *senderNonceMempool) CountTx() int { count := 0 for _, value := range snm.senders { //nolint:gosec // we need neither strong randomness nor deterministic iteration - count += value.Len() - } + count += value.Len() //nolint:gosec + } //nolint:gosec return count } From 1c938bfde472afb9688724c9f1b4938894a2e3f3 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:52:04 -0600 Subject: [PATCH 27/49] improve format? --- types/mempool/sender_nonce.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 679a92d12c68..0c193d00fd47 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -121,7 +121,8 @@ func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { func (snm *senderNonceMempool) CountTx() int { count := 0 - for _, value := range snm.senders { //nolint:gosec // we need neither strong randomness nor deterministic iteration + // Disable gosec here since we need neither strong randomness nor deterministic iteration. + for _, value := range snm.senders { //nolint:gosec count += value.Len() //nolint:gosec } //nolint:gosec return count From 8800e7156ff24ad499566c95b7acc4a91f164729 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 11:55:27 -0600 Subject: [PATCH 28/49] more gosec disable --- types/mempool/sender_nonce.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 0c193d00fd47..0b6ba3108423 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -1,10 +1,10 @@ package mempool import ( - crand "crypto/rand" + crand "crypto/rand" //nolint:gosec // crypto/rand is used for seed generation "encoding/binary" "fmt" - "math/rand" + "math/rand" //notlint:gosec // math/rand is used for random selection and seeded from crypto/rand huandu "github.com/huandu/skiplist" @@ -67,7 +67,7 @@ func NewSenderNonceMempoolWithSeed(seed int64) Mempool { func (snm *senderNonceMempool) setSeed(seed int64) { s1 := rand.NewSource(seed) - snm.rnd = rand.New(s1) + snm.rnd = rand.New(s1) //nolint:gosec // math/rand is seeded from crypto/rand by default } // Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer. From beee298cf4e8028f0ad89ce61420402edf61ad4a Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 12:23:41 -0600 Subject: [PATCH 29/49] Fix ctr usage --- baseapp/util_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/util_test.go b/baseapp/util_test.go index 91a23b8f3177..228331466f2d 100644 --- a/baseapp/util_test.go +++ b/baseapp/util_test.go @@ -150,7 +150,7 @@ func makeTestConfig() depinject.Config { } func makeMinimalConfig() depinject.Config { - var mempoolOpt runtime.BaseAppOption = baseapp.SetMempool(mempool.NewNonceMempool()) + var mempoolOpt runtime.BaseAppOption = baseapp.SetMempool(mempool.NewSenderNonceMempool()) return depinject.Configs( depinject.Supply(mempoolOpt), appconfig.Compose(&appv1alpha1.Config{ From 1dcc89c466f1a4fe2b9a2ea923f728568dbd7c08 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 12:35:26 -0600 Subject: [PATCH 30/49] use #nosec --- types/mempool/sender_nonce.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 0b6ba3108423..8eec9d77675e 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -1,10 +1,10 @@ package mempool import ( - crand "crypto/rand" //nolint:gosec // crypto/rand is used for seed generation + crand "crypto/rand" // #nosec // crypto/rand is used for seed generation "encoding/binary" "fmt" - "math/rand" //notlint:gosec // math/rand is used for random selection and seeded from crypto/rand + "math/rand" // #nosec // math/rand is used for random selection and seeded from crypto/rand huandu "github.com/huandu/skiplist" @@ -67,7 +67,7 @@ func NewSenderNonceMempoolWithSeed(seed int64) Mempool { func (snm *senderNonceMempool) setSeed(seed int64) { s1 := rand.NewSource(seed) - snm.rnd = rand.New(s1) //nolint:gosec // math/rand is seeded from crypto/rand by default + snm.rnd = rand.New(s1) //#nosec // math/rand is seeded from crypto/rand by default } // Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer. @@ -98,6 +98,7 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { var senders []string senderCursors := make(map[string]*senderTxs) + // #nosec for key := range snm.senders { senders = append(senders, key) senderTx := newSenderTxs(snm.senders[key].Front()) @@ -122,9 +123,10 @@ func (snm *senderNonceMempool) CountTx() int { count := 0 // Disable gosec here since we need neither strong randomness nor deterministic iteration. - for _, value := range snm.senders { //nolint:gosec - count += value.Len() //nolint:gosec - } //nolint:gosec + // #nosec + for _, value := range snm.senders { + count += value.Len() + } return count } From 99aff01899597551ea3f9ac58f8dd8e5645bc9a1 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 12:38:48 -0600 Subject: [PATCH 31/49] Update types/mempool/sender_nonce.go --- types/mempool/sender_nonce.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 8eec9d77675e..191cf1426c67 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -49,7 +49,10 @@ func NewSenderNonceMempool() Mempool { } var seed int64 - binary.Read(crand.Reader, binary.BigEndian, &seed) + err := binary.Read(crand.Reader, binary.BigEndian, &seed) + if err != nil { + panic(err) + } snp.setSeed(seed) return snp From b5960c5e175eb3ad5a982218a0558addf949a048 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 12:40:08 -0600 Subject: [PATCH 32/49] Kocubinski/random sender nonce (#13956) * refactor * fix iteration logic * fix merge err --- types/mempool/sender_nonce.go | 55 ++++++++++++----------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 191cf1426c67..50cb20eb734a 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -17,25 +17,6 @@ var ( _ Iterator = (*senderNonceMepoolIterator)(nil) ) -type senderTxs struct { - cursor *huandu.Element -} - -func newSenderTxs(tx *huandu.Element) senderTxs { - return senderTxs{ - cursor: tx, - } -} - -func (s *senderTxs) next() *huandu.Element { - if s.cursor == nil { - return nil - } - currentCursor := s.cursor - s.cursor = s.cursor.Next() - return currentCursor -} - type senderNonceMempool struct { senders map[string]*huandu.SkipList rnd *rand.Rand @@ -100,18 +81,17 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { // Select returns an iterator ordering transactions the mempool with the lowest nonce of a random selected sender first. func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { var senders []string - senderCursors := make(map[string]*senderTxs) + senderCursors := make(map[string]*huandu.Element) // #nosec for key := range snm.senders { senders = append(senders, key) - senderTx := newSenderTxs(snm.senders[key].Front()) - senderCursors[key] = &senderTx + senderCursors[key] = snm.senders[key].Front() } iter := &senderNonceMepoolIterator{ - senders: senders, - rnd: snm.rnd, - sendersCurosors: senderCursors, + senders: senders, + rnd: snm.rnd, + senderCursors: senderCursors, } newIter := iter.Next() @@ -164,10 +144,10 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { } type senderNonceMepoolIterator struct { - rnd *rand.Rand - currentTx *huandu.Element - senders []string - sendersCurosors map[string]*senderTxs + rnd *rand.Rand + currentTx *huandu.Element + senders []string + senderCursors map[string]*huandu.Element } // Next it returns the iterator next state where a iterator will contain a tx that was the smallest @@ -176,21 +156,24 @@ func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.rnd.Intn(len(i.senders)) sender := i.senders[senderIndex] - senderTxs, found := i.sendersCurosors[sender] + senderCursor, found := i.senderCursors[sender] if !found { i.senders = removeAtIndex(i.senders, senderIndex) continue } - tx := senderTxs.next() - if tx == nil { + + if senderCursor == nil { i.senders = removeAtIndex(i.senders, senderIndex) continue } + + i.senderCursors[sender] = senderCursor.Next() + return &senderNonceMepoolIterator{ - senders: i.senders, - currentTx: tx, - rnd: i.rnd, - sendersCurosors: i.sendersCurosors, + senders: i.senders, + currentTx: senderCursor, + rnd: i.rnd, + senderCursors: i.senderCursors, } } From a3bdcb985c82851eafefe251f0311eec92a5d93d Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 12:43:02 -0600 Subject: [PATCH 33/49] import fixes --- types/mempool/sender_nonce_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go index 5d5420615b4f..bea3138c3995 100644 --- a/types/mempool/sender_nonce_test.go +++ b/types/mempool/sender_nonce_test.go @@ -2,7 +2,6 @@ package mempool_test import ( "fmt" - "github.com/cosmos/cosmos-sdk/types/mempool" "math/rand" "testing" @@ -11,6 +10,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/mempool" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) From da6346594213d0dcc0f5804d9fc3f62720eb3ca4 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 13:02:31 -0600 Subject: [PATCH 34/49] derive order randomness from seed only --- types/mempool/sender_nonce.go | 16 +++++++++--- types/mempool/sender_nonce_test.go | 39 +++++++----------------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 50cb20eb734a..fc7cf0017b66 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -82,10 +82,18 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { var senders []string senderCursors := make(map[string]*huandu.Element) - // #nosec - for key := range snm.senders { - senders = append(senders, key) - senderCursors[key] = snm.senders[key].Front() + + orderedSenders := huandu.New(huandu.String) + for s := range snm.senders { + orderedSenders.Set(s, s) + } + + s := orderedSenders.Front() + for s != nil { + sender := s.Value.(string) + senders = append(senders, sender) + senderCursors[sender] = snm.senders[sender].Front() + s = s.Next() } iter := &senderNonceMepoolIterator{ diff --git a/types/mempool/sender_nonce_test.go b/types/mempool/sender_nonce_test.go index bea3138c3995..9b4a52926eef 100644 --- a/types/mempool/sender_nonce_test.go +++ b/types/mempool/sender_nonce_test.go @@ -23,7 +23,7 @@ func (s *MempoolTestSuite) TestTxOrder() { tests := []struct { txs []txSpec - order [][]int + order []int fail bool seed int64 }{ @@ -35,10 +35,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 20, n: 1, a: sa}, }, - order: [][]int{ - {4, 2, 3, 1, 0}, - {3, 4, 2, 1, 0}, - }, + order: []int{3, 4, 2, 1, 0}, // Index order base on seed 0: 0 0 1 0 1 0 0 seed: 0, }, @@ -51,10 +48,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 5, n: 1, a: sb}, {p: 8, n: 2, a: sb}, }, - order: [][]int{ - {0, 1, 3, 2, 4, 5}, - {3, 4, 0, 5, 1, 2}, - }, + order: []int{3, 4, 0, 5, 1, 2}, // Index order base on seed 0: 0 0 1 0 1 0 0 seed: 0, }, @@ -64,10 +58,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 20, n: 1, a: sa}, }, - order: [][]int{ - {2, 0, 1}, - {1, 2, 0}, - }, + order: []int{1, 2, 0}, // Index order base on seed 0: 0 0 1 0 1 0 0 seed: 0, }, @@ -79,10 +70,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 21, n: 2, a: sb}, }, - order: [][]int{ - {2, 1, 3, 0, 4}, - {3, 4, 2, 1, 0}, - }, + order: []int{3, 4, 2, 1, 0}, // Index order base on seed 0: 0 0 1 0 1 0 0 seed: 0, }, @@ -94,10 +82,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 15, n: 1, a: sb}, {p: 8, n: 2, a: sb}, }, - order: [][]int{ - {2, 1, 3, 0, 4}, - {3, 4, 2, 1, 0}, - }, + order: []int{3, 4, 2, 1, 0}, // Index order base on seed 0: 0 0 1 0 1 0 0 seed: 0, }, @@ -111,10 +96,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 6, a: sa, n: 3}, {p: 4, a: sb, n: 3}, }, - order: [][]int{ - {3, 2, 4, 0, 1, 5, 6}, - {4, 1, 3, 6, 2, 0, 5}, - }, + order: []int{4, 1, 3, 6, 2, 0, 5}, // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 seed: 0, }, @@ -125,10 +107,7 @@ func (s *MempoolTestSuite) TestTxOrder() { {p: 5, n: 1, a: sb}, {p: 99, n: 2, a: sb}, }, - order: [][]int{ - {0, 1, 2, 3}, - {2, 3, 0, 1}, - }, + order: []int{2, 3, 0, 1}, // Index order base on seed 0: 0 0 1 0 1 0 1 1 0 seed: 0, }, @@ -153,7 +132,7 @@ func (s *MempoolTestSuite) TestTxOrder() { for _, tx := range orderedTxs { require.NoError(t, pool.Remove(tx)) } - require.Contains(t, fmt.Sprintf("%v", tt.order), fmt.Sprintf("%v", txOrder)) + require.Equal(t, tt.order, txOrder) require.Equal(t, 0, pool.CountTx()) }) } From c306fca6f22f0c51867102bd5187c6958ee382cc Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 13:24:43 -0600 Subject: [PATCH 35/49] gosec fix --- types/mempool/sender_nonce.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index fc7cf0017b66..9aacff726203 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -84,7 +84,7 @@ func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { senderCursors := make(map[string]*huandu.Element) orderedSenders := huandu.New(huandu.String) - for s := range snm.senders { + for s, _ := range snm.senders { orderedSenders.Set(s, s) } From a93c950d3cd6c357c36e627e830e66b74a0f9378 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 13:31:12 -0600 Subject: [PATCH 36/49] ignore gosec again --- types/mempool/sender_nonce.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 9aacff726203..f50efb7b63e2 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -84,7 +84,9 @@ func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { senderCursors := make(map[string]*huandu.Element) orderedSenders := huandu.New(huandu.String) - for s, _ := range snm.senders { + + // #nosec + for s := range snm.senders { orderedSenders.Set(s, s) } From 578046ad02811925190c0ae25d1bd2c11504469e Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 21 Nov 2022 13:37:01 -0600 Subject: [PATCH 37/49] comments --- types/mempool/sender_nonce.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index f50efb7b63e2..3fb3750bd0f5 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -17,6 +17,14 @@ var ( _ Iterator = (*senderNonceMepoolIterator)(nil) ) +// senderNonceMempool is a mempool that prioritizes transactions within a sender by nonce, the lowest first, +// but selects a random sender on each iteration. The mempool is iterated by: +// +// 1) Maintaining a separate list of nonce ordered txs per sender +// 2) For each select iteration, randomly choose a sender and pick the next nonce ordered tx from their list +// 3) Repeat 1,2 until the mempool is exhausted +// +// Note that PrepareProposal could choose to stop iteration before reaching the end if maxBytes is reached. type senderNonceMempool struct { senders map[string]*huandu.SkipList rnd *rand.Rand @@ -160,8 +168,8 @@ type senderNonceMepoolIterator struct { senderCursors map[string]*huandu.Element } -// Next it returns the iterator next state where a iterator will contain a tx that was the smallest -// nonce of a randomly selected sender +// Next returns the next iterator state which will contain a tx with the next smallest nonce of a randomly +// selected sender. func (i *senderNonceMepoolIterator) Next() Iterator { for len(i.senders) > 0 { senderIndex := i.rnd.Intn(len(i.senders)) From 695ed48bf64c9a010e394df714e8c5511bc7b950 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Mon, 21 Nov 2022 16:06:20 -0500 Subject: [PATCH 38/49] property based --- types/mempool/sender_nonce_property_test.go | 104 ++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 types/mempool/sender_nonce_property_test.go diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go new file mode 100644 index 000000000000..6cba13158f39 --- /dev/null +++ b/types/mempool/sender_nonce_property_test.go @@ -0,0 +1,104 @@ +package mempool_test + +import ( + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + mempool "github.com/cosmos/cosmos-sdk/types/mempool" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "sort" + + "math/rand" + "pgregory.net/rapid" +) + +var ( + _ sdk.Tx = (*testTx)(nil) + _ signing.SigVerifiableTx = (*testTx)(nil) + _ cryptotypes.PubKey = (*testPubKey)(nil) +) + +// Property Based Testing +// Split the senders tx in independent slices and then test the following properties in each slice +// same elements input output +// the reverse of the reverse of the list is the same +// for every sequence element pair a, b a < b + +var genAddress = rapid.Custom(func(t *rapid.T) simtypes.Account { + accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(rapid.Int64().Draw(t, "seed for account"))), 1) + return accounts[0] +}) + +func testMempoolProperties(t *rapid.T) { + + ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) + mp := mempool.NewSenderNonceMempool() + + genMultipleAddress := rapid.SliceOfDistinct(genAddress, func(acc simtypes.Account) string { + return acc.Address.String() + }) + + accounts := genMultipleAddress.Draw(t, "address") + genTx := rapid.Custom(func(t *rapid.T) testTx { + return testTx{ + priority: rapid.Int64Range(0, 1000).Draw(t, "priority"), + nonce: rapid.Uint64().Draw(t, "nonce"), + address: rapid.SampledFrom(accounts).Draw(t, "acc").Address, + } + }) + genMultipleTX := rapid.SliceOf(genTx) + + txs := genMultipleTX.Draw(t, "txs") + senderTxRaw := getSenderTxMap(txs) + + for _, tx := range txs { + err := mp.Insert(ctx, tx) + require.NoError(t, err) + } + + iter := mp.Select(ctx, nil) + orderTx := make([]testTx, 0) + for _, tx := range fetchAllTxs(iter) { + orderTx = append(orderTx, tx.(testTx)) + } + senderTxOrdered := getSenderTxMap(orderTx) + for key := range senderTxOrdered { + ordered, found := senderTxOrdered[key] + require.True(t, found) + raw, found := senderTxRaw[key] + require.True(t, found) + sort.Slice(raw, func(i, j int) bool { return raw[i].nonce < raw[j].nonce }) + require.Equal(t, raw, ordered) + } +} + +func (s *MempoolTestSuite) TestProperties() { + t := s.T() + rapid.Check(t, testMempoolProperties) +} + +func getSenderTxMap(txs []testTx) map[string][]testTx { + senderTxs := make(map[string][]testTx) + for _, tx := range txs { + stx, found := senderTxs[tx.address.String()] + if !found { + stx = make([]testTx, 0) + } + stx = append(stx, tx) + senderTxs[tx.address.String()] = stx + } + return senderTxs +} + +func fetchAllTxs(iterator mempool.Iterator) []sdk.Tx { + var txs []sdk.Tx + for iterator != nil { + txs = append(txs, iterator.Tx()) + i := iterator.Next() + iterator = i + } + return txs +} From 99b653696f897c723420f97141048e0f1adf9cab Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Mon, 21 Nov 2022 17:32:44 -0500 Subject: [PATCH 39/49] minor fixes --- types/mempool/sender_nonce_property_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index 6cba13158f39..b06d65ae25e3 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -37,7 +37,7 @@ func testMempoolProperties(t *rapid.T) { ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) mp := mempool.NewSenderNonceMempool() - genMultipleAddress := rapid.SliceOfDistinct(genAddress, func(acc simtypes.Account) string { + genMultipleAddress := rapid.SliceOfNDistinct(genAddress, 1, 10, func(acc simtypes.Account) string { return acc.Address.String() }) @@ -49,7 +49,7 @@ func testMempoolProperties(t *rapid.T) { address: rapid.SampledFrom(accounts).Draw(t, "acc").Address, } }) - genMultipleTX := rapid.SliceOf(genTx) + genMultipleTX := rapid.SliceOfN(genTx, 1, 500) txs := genMultipleTX.Draw(t, "txs") senderTxRaw := getSenderTxMap(txs) From bf64e22a77b191669ceaaadac95e6acee7d05740 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Mon, 21 Nov 2022 17:50:30 -0500 Subject: [PATCH 40/49] added property test --- types/mempool/sender_nonce_property_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index b06d65ae25e3..ddbbf4b44375 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -70,8 +70,9 @@ func testMempoolProperties(t *rapid.T) { require.True(t, found) raw, found := senderTxRaw[key] require.True(t, found) - sort.Slice(raw, func(i, j int) bool { return raw[i].nonce < raw[j].nonce }) - require.Equal(t, raw, ordered) + rawSet := rewriteDuplicateNonce(raw) + sort.Slice(rawSet, func(i, j int) bool { return rawSet[i].nonce < rawSet[j].nonce }) + require.Equal(t, rawSet, ordered) } } @@ -102,3 +103,15 @@ func fetchAllTxs(iterator mempool.Iterator) []sdk.Tx { } return txs } + +func rewriteDuplicateNonce(raw []testTx) []testTx { + rawMap := make(map[uint64]testTx) + for _, v := range raw { + rawMap[v.nonce] = v + } + result := make([]testTx, 0) + for _, v := range rawMap { + result = append(result, v) + } + return result +} From ca1c17f535c453b2b672cda9c63998375c4b8dd6 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Mon, 21 Nov 2022 17:54:30 -0500 Subject: [PATCH 41/49] comment --- types/mempool/sender_nonce_property_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index ddbbf4b44375..5837e0e00890 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -23,8 +23,7 @@ var ( // Property Based Testing // Split the senders tx in independent slices and then test the following properties in each slice -// same elements input output -// the reverse of the reverse of the list is the same +// same elements input output and overwrite the nonce duplicates // for every sequence element pair a, b a < b var genAddress = rapid.Custom(func(t *rapid.T) simtypes.Account { From 745d50dc307ca2a79c0f13b33ecab07fa4692286 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 08:38:44 -0500 Subject: [PATCH 42/49] fix imports --- types/mempool/sender_nonce_property_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index 5837e0e00890..ed10fe8d4278 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -1,6 +1,11 @@ package mempool_test import ( + "math/rand" + "sort" + + "pgregory.net/rapid" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" mempool "github.com/cosmos/cosmos-sdk/types/mempool" @@ -9,10 +14,6 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "sort" - - "math/rand" - "pgregory.net/rapid" ) var ( From 77ea97868b8bfe06c57f66139235b5699de1a6be Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 10:26:12 -0500 Subject: [PATCH 43/49] comment --- types/mempool/sender_nonce_property_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index ed10fe8d4278..6c632a97b5d9 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -24,7 +24,7 @@ var ( // Property Based Testing // Split the senders tx in independent slices and then test the following properties in each slice -// same elements input output and overwrite the nonce duplicates +// same elements input on the mempool should be in the output except for sender nonce duplicates, which are overwritten by the later duplicate entries. // for every sequence element pair a, b a < b var genAddress = rapid.Custom(func(t *rapid.T) simtypes.Account { From 3078d6569faee4cb475f55202e1f1bdb5de71675 Mon Sep 17 00:00:00 2001 From: Jeancarlo Barrios Date: Tue, 22 Nov 2022 10:28:16 -0500 Subject: [PATCH 44/49] Update types/mempool/sender_nonce_property_test.go Co-authored-by: Matt Kocubinski --- types/mempool/sender_nonce_property_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index 6c632a97b5d9..37690c5993ec 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -25,7 +25,7 @@ var ( // Property Based Testing // Split the senders tx in independent slices and then test the following properties in each slice // same elements input on the mempool should be in the output except for sender nonce duplicates, which are overwritten by the later duplicate entries. -// for every sequence element pair a, b a < b +// for every sender transaction tx_n, tx_0.nonce < tx_1.nonce ... < tx_n.nonce var genAddress = rapid.Custom(func(t *rapid.T) simtypes.Account { accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(rapid.Int64().Draw(t, "seed for account"))), 1) From e7c2e2fe355d3e632df8b44fffff652aa251fb8f Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 10:47:45 -0500 Subject: [PATCH 45/49] remove unesessary loop --- types/mempool/sender_nonce_property_test.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index 37690c5993ec..d369dd2d9acf 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -60,10 +60,7 @@ func testMempoolProperties(t *rapid.T) { } iter := mp.Select(ctx, nil) - orderTx := make([]testTx, 0) - for _, tx := range fetchAllTxs(iter) { - orderTx = append(orderTx, tx.(testTx)) - } + orderTx := fetchAllTxs(iter) senderTxOrdered := getSenderTxMap(orderTx) for key := range senderTxOrdered { ordered, found := senderTxOrdered[key] @@ -94,10 +91,11 @@ func getSenderTxMap(txs []testTx) map[string][]testTx { return senderTxs } -func fetchAllTxs(iterator mempool.Iterator) []sdk.Tx { - var txs []sdk.Tx +func fetchAllTxs(iterator mempool.Iterator) []testTx { + var txs []testTx for iterator != nil { - txs = append(txs, iterator.Tx()) + tx := iterator.Tx() + txs = append(txs, tx.(testTx)) i := iterator.Next() iterator = i } From d056a8acae7d6ab3bc53d742b6942168108ccf83 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 11:14:52 -0500 Subject: [PATCH 46/49] improve function name --- types/mempool/sender_nonce_property_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/mempool/sender_nonce_property_test.go b/types/mempool/sender_nonce_property_test.go index d369dd2d9acf..e0bf716edcfa 100644 --- a/types/mempool/sender_nonce_property_test.go +++ b/types/mempool/sender_nonce_property_test.go @@ -67,7 +67,7 @@ func testMempoolProperties(t *rapid.T) { require.True(t, found) raw, found := senderTxRaw[key] require.True(t, found) - rawSet := rewriteDuplicateNonce(raw) + rawSet := mergeByNonce(raw) sort.Slice(rawSet, func(i, j int) bool { return rawSet[i].nonce < rawSet[j].nonce }) require.Equal(t, rawSet, ordered) } @@ -102,7 +102,7 @@ func fetchAllTxs(iterator mempool.Iterator) []testTx { return txs } -func rewriteDuplicateNonce(raw []testTx) []testTx { +func mergeByNonce(raw []testTx) []testTx { rawMap := make(map[uint64]testTx) for _, v := range raw { rawMap[v.nonce] = v From 9073aaf84a46e55f8a5504633b03612f7a4df6a4 Mon Sep 17 00:00:00 2001 From: Jeancarlo Barrios Date: Tue, 22 Nov 2022 13:03:53 -0500 Subject: [PATCH 47/49] Update types/mempool/sender_nonce.go Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com> --- types/mempool/sender_nonce.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 3fb3750bd0f5..88d9968f299a 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -112,11 +112,7 @@ func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { senderCursors: senderCursors, } - newIter := iter.Next() - if newIter == nil { - return nil - } - return newIter + return iter.Next() } // CountTx returns the total count of txs in the mempool. From 69f3bc5f02d630eca0b84a8c85bd95fbe4c32872 Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 13:08:37 -0500 Subject: [PATCH 48/49] change import name --- types/mempool/sender_nonce.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 88d9968f299a..6bf1ff5f50a2 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -6,7 +6,7 @@ import ( "fmt" "math/rand" // #nosec // math/rand is used for random selection and seeded from crypto/rand - huandu "github.com/huandu/skiplist" + "github.com/huandu/skiplist" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -26,13 +26,13 @@ var ( // // Note that PrepareProposal could choose to stop iteration before reaching the end if maxBytes is reached. type senderNonceMempool struct { - senders map[string]*huandu.SkipList + senders map[string]*skiplist.SkipList rnd *rand.Rand } // NewSenderNonceMempool creates a new mempool that prioritizes transactions by nonce, the lowest first. func NewSenderNonceMempool() Mempool { - senderMap := make(map[string]*huandu.SkipList) + senderMap := make(map[string]*skiplist.SkipList) snp := &senderNonceMempool{ senders: senderMap, } @@ -49,7 +49,7 @@ func NewSenderNonceMempool() Mempool { // NewSenderNonceMempoolWithSeed creates a new mempool that prioritizes transactions by nonce, the lowest first and sets the random seed. func NewSenderNonceMempoolWithSeed(seed int64) Mempool { - senderMap := make(map[string]*huandu.SkipList) + senderMap := make(map[string]*skiplist.SkipList) snp := &senderNonceMempool{ senders: senderMap, } @@ -78,7 +78,7 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { nonce := sig.Sequence senderTxs, found := snm.senders[sender] if !found { - senderTxs = huandu.New(huandu.Uint64) + senderTxs = skiplist.New(skiplist.Uint64) snm.senders[sender] = senderTxs } senderTxs.Set(nonce, tx) @@ -89,9 +89,9 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error { // Select returns an iterator ordering transactions the mempool with the lowest nonce of a random selected sender first. func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator { var senders []string - senderCursors := make(map[string]*huandu.Element) + senderCursors := make(map[string]*skiplist.Element) - orderedSenders := huandu.New(huandu.String) + orderedSenders := skiplist.New(skiplist.String) // #nosec for s := range snm.senders { @@ -159,9 +159,9 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error { type senderNonceMepoolIterator struct { rnd *rand.Rand - currentTx *huandu.Element + currentTx *skiplist.Element senders []string - senderCursors map[string]*huandu.Element + senderCursors map[string]*skiplist.Element } // Next returns the next iterator state which will contain a tx with the next smallest nonce of a randomly From 73453ea144d905276dfaca9ecaffccb6db2936eb Mon Sep 17 00:00:00 2001 From: Jeancarlo Date: Tue, 22 Nov 2022 14:14:55 -0500 Subject: [PATCH 49/49] change validation to be preemvtive --- types/mempool/sender_nonce.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index 6bf1ff5f50a2..60d4608b93ca 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -176,13 +176,12 @@ func (i *senderNonceMepoolIterator) Next() Iterator { continue } - if senderCursor == nil { + if nextCursor := senderCursor.Next(); nextCursor != nil { + i.senderCursors[sender] = nextCursor + } else { i.senders = removeAtIndex(i.senders, senderIndex) - continue } - i.senderCursors[sender] = senderCursor.Next() - return &senderNonceMepoolIterator{ senders: i.senders, currentTx: senderCursor,