Co-authored-by: Eric Warehime <eric.warehime@gmail.com> Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
parent
8ac0492142
commit
3e9a3e94bf
@ -38,10 +38,11 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.50.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.3) - 2023-01-11
|
||||
## [v0.50.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.3) - 2023-01-15
|
||||
|
||||
### Features
|
||||
|
||||
* (types) [#18991](https://github.com/cosmos/cosmos-sdk/pull/18991) Add SignerExtractionAdapter to PriorityNonceMempool/Config and provide Default implementation matching existing behavior.
|
||||
* (gRPC) [#19043](https://github.com/cosmos/cosmos-sdk/pull/19043) Add `halt_height` to the gRPC `/cosmos/base/node/v1beta1/config` request.
|
||||
|
||||
### Improvements
|
||||
|
||||
@ -40,6 +40,9 @@ type (
|
||||
// (sequence number) when evicting transactions.
|
||||
// - if MaxTx < 0, `Insert` is a no-op.
|
||||
MaxTx int
|
||||
|
||||
// SignerExtractor is an implementation which retrieves signer data from a sdk.Tx
|
||||
SignerExtractor SignerExtractionAdapter
|
||||
}
|
||||
|
||||
// PriorityNonceMempool is a mempool implementation that stores txs
|
||||
@ -116,7 +119,8 @@ func NewDefaultTxPriority() TxPriority[int64] {
|
||||
|
||||
func DefaultPriorityNonceMempoolConfig() PriorityNonceMempoolConfig[int64] {
|
||||
return PriorityNonceMempoolConfig[int64]{
|
||||
TxPriority: NewDefaultTxPriority(),
|
||||
TxPriority: NewDefaultTxPriority(),
|
||||
SignerExtractor: NewDefaultSignerExtractionAdapter(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +161,9 @@ func skiplistComparable[C comparable](txPriority TxPriority[C]) skiplist.Compara
|
||||
// NewPriorityMempool returns the SDK's default mempool implementation which
|
||||
// returns txs in a partial order by 2 dimensions; priority, and sender-nonce.
|
||||
func NewPriorityMempool[C comparable](cfg PriorityNonceMempoolConfig[C]) *PriorityNonceMempool[C] {
|
||||
if cfg.SignerExtractor == nil {
|
||||
cfg.SignerExtractor = NewDefaultSignerExtractionAdapter()
|
||||
}
|
||||
mp := &PriorityNonceMempool[C]{
|
||||
priorityIndex: skiplist.New(skiplistComparable(cfg.TxPriority)),
|
||||
priorityCounts: make(map[C]int),
|
||||
@ -204,7 +211,7 @@ func (mp *PriorityNonceMempool[C]) Insert(ctx context.Context, tx sdk.Tx) error
|
||||
return nil
|
||||
}
|
||||
|
||||
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
sigs, err := mp.cfg.SignerExtractor.GetSigners(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -213,7 +220,7 @@ func (mp *PriorityNonceMempool[C]) Insert(ctx context.Context, tx sdk.Tx) error
|
||||
}
|
||||
|
||||
sig := sigs[0]
|
||||
sender := sdk.AccAddress(sig.PubKey.Address()).String()
|
||||
sender := sig.Signer.String()
|
||||
priority := mp.cfg.TxPriority.GetTxPriority(ctx, tx)
|
||||
nonce := sig.Sequence
|
||||
key := txMeta[C]{nonce: nonce, priority: priority, sender: sender}
|
||||
|
||||
@ -435,6 +435,7 @@ func (s *MempoolTestSuite) TestRandomGeneratedTxs() {
|
||||
OnRead: func(tx sdk.Tx) {
|
||||
s.iterations++
|
||||
},
|
||||
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
|
||||
},
|
||||
)
|
||||
|
||||
@ -698,8 +699,9 @@ func TestNextSenderTx_TxLimit(t *testing.T) {
|
||||
// unlimited
|
||||
mp := mempool.NewPriorityMempool(
|
||||
mempool.PriorityNonceMempoolConfig[int64]{
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: 0,
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: 0,
|
||||
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
|
||||
},
|
||||
)
|
||||
for i, tx := range txs {
|
||||
@ -718,8 +720,9 @@ func TestNextSenderTx_TxLimit(t *testing.T) {
|
||||
// limit: 3
|
||||
mp = mempool.NewPriorityMempool(
|
||||
mempool.PriorityNonceMempoolConfig[int64]{
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: 3,
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: 3,
|
||||
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
|
||||
},
|
||||
)
|
||||
for i, tx := range txs {
|
||||
@ -737,8 +740,9 @@ func TestNextSenderTx_TxLimit(t *testing.T) {
|
||||
// disabled
|
||||
mp = mempool.NewPriorityMempool(
|
||||
mempool.PriorityNonceMempoolConfig[int64]{
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: -1,
|
||||
TxPriority: mempool.NewDefaultTxPriority(),
|
||||
MaxTx: -1,
|
||||
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
|
||||
},
|
||||
)
|
||||
for _, tx := range txs {
|
||||
@ -783,6 +787,7 @@ func TestNextSenderTx_TxReplacement(t *testing.T) {
|
||||
threshold := int64(100 + feeBump)
|
||||
return np >= op*threshold/100
|
||||
},
|
||||
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
58
types/mempool/signer_extraction_adapater_test.go
Normal file
58
types/mempool/signer_extraction_adapater_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package mempool_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
type nonVerifiableTx struct{}
|
||||
|
||||
func (n nonVerifiableTx) GetMsgs() []sdk.Msg {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) GetMsgsV2() ([]proto.Message, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func TestDefaultSignerExtractor(t *testing.T) {
|
||||
accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 1)
|
||||
sa := accounts[0].Address
|
||||
ext := mempool.NewDefaultSignerExtractionAdapter()
|
||||
goodTx := testTx{id: 0, priority: 0, nonce: 0, address: sa}
|
||||
badTx := &sigErrTx{getSigs: func() ([]txsigning.SignatureV2, error) {
|
||||
return nil, fmt.Errorf("error")
|
||||
}}
|
||||
nonSigVerify := nonVerifiableTx{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
sea mempool.SignerExtractionAdapter
|
||||
err error
|
||||
}{
|
||||
{name: "valid tx extracts sigs", tx: goodTx, sea: ext, err: nil},
|
||||
{name: "invalid tx fails on sig", tx: badTx, sea: ext, err: fmt.Errorf("err")},
|
||||
{name: "non-verifiable tx fails on conversion", tx: nonSigVerify, sea: ext, err: fmt.Errorf("tx of type %T does not implement SigVerifiableTx", nonSigVerify)},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
sigs, err := test.sea.GetSigners(test.tx)
|
||||
if test.err != nil {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, sigs[0].String(), mempool.SignerData{Signer: sa, Sequence: 0}.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
67
types/mempool/signer_extraction_adapter.go
Normal file
67
types/mempool/signer_extraction_adapter.go
Normal file
@ -0,0 +1,67 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
// SignerData contains canonical useful information about the signer of a transaction
|
||||
type SignerData struct {
|
||||
Signer sdk.AccAddress
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
// NewSignerData returns a new SignerData instance.
|
||||
func NewSignerData(signer sdk.AccAddress, sequence uint64) SignerData {
|
||||
return SignerData{
|
||||
Signer: signer,
|
||||
Sequence: sequence,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (s SignerData) String() string {
|
||||
return fmt.Sprintf("SignerData{Signer: %s, Sequence: %d}", s.Signer, s.Sequence)
|
||||
}
|
||||
|
||||
// SignerExtractionAdapter is an interface used to determine how the signers of a transaction should be extracted
|
||||
// from the transaction.
|
||||
type SignerExtractionAdapter interface {
|
||||
GetSigners(sdk.Tx) ([]SignerData, error)
|
||||
}
|
||||
|
||||
var _ SignerExtractionAdapter = DefaultSignerExtractionAdapter{}
|
||||
|
||||
// DefaultSignerExtractionAdapter is the default implementation of SignerExtractionAdapter. It extracts the signers
|
||||
// from a cosmos-sdk tx via GetSignaturesV2.
|
||||
type DefaultSignerExtractionAdapter struct{}
|
||||
|
||||
// NewDefaultSignerExtractionAdapter constructs a new DefaultSignerExtractionAdapter instance
|
||||
func NewDefaultSignerExtractionAdapter() DefaultSignerExtractionAdapter {
|
||||
return DefaultSignerExtractionAdapter{}
|
||||
}
|
||||
|
||||
// GetSigners implements the Adapter interface
|
||||
func (DefaultSignerExtractionAdapter) GetSigners(tx sdk.Tx) ([]SignerData, error) {
|
||||
sigTx, ok := tx.(signing.SigVerifiableTx)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx)
|
||||
}
|
||||
|
||||
sigs, err := sigTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signers := make([]SignerData, len(sigs))
|
||||
for i, sig := range sigs {
|
||||
signers[i] = NewSignerData(
|
||||
sig.PubKey.Address().Bytes(),
|
||||
sig.Sequence,
|
||||
)
|
||||
}
|
||||
|
||||
return signers, nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user