feat(adapters): Add SignerExtractionAdapter [ENG-1916] (#114)

* add a signer-extraction-adapter

* linting

* feat(adapters/mev-lane):  Use the SignerExtractionAdapter in the Mev-Lane [ENG-1917] (#115)

* use SignerExtractionAdapter in the Factory

* feat(e2e): block sdk integration updates (#122)

* cherry-pick from injective

* remove transactions from app-side mempool on failed re-checktx
This commit is contained in:
Nikhil Vasan
2023-09-27 08:08:10 -07:00
committed by GitHub
parent 3e5fce9a54
commit 3abfde4f34
23 changed files with 675 additions and 300 deletions
+16 -5
View File
@@ -7,6 +7,7 @@ import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
"github.com/skip-mev/block-sdk/block"
)
@@ -17,6 +18,10 @@ type LaneConfig struct {
TxDecoder sdk.TxDecoder
AnteHandler sdk.AnteHandler
// SignerExtractor defines the interface used for extracting the expected signers of a transaction
// from the transaction.
SignerExtractor signer_extraction.Adapter
// MaxBlockSpace defines the relative percentage of block space that can be
// used by this lane. NOTE: If this is set to zero, then there is no limit
// on the number of transactions that can be included in the block for this
@@ -47,14 +52,16 @@ func NewLaneConfig(
txEncoder sdk.TxEncoder,
txDecoder sdk.TxDecoder,
anteHandler sdk.AnteHandler,
signerExtractor signer_extraction.Adapter,
maxBlockSpace math.LegacyDec,
) LaneConfig {
return LaneConfig{
Logger: logger,
TxEncoder: txEncoder,
TxDecoder: txDecoder,
AnteHandler: anteHandler,
MaxBlockSpace: maxBlockSpace,
Logger: logger,
TxEncoder: txEncoder,
TxDecoder: txDecoder,
AnteHandler: anteHandler,
MaxBlockSpace: maxBlockSpace,
SignerExtractor: signerExtractor,
}
}
@@ -72,6 +79,10 @@ func (c *LaneConfig) ValidateBasic() error {
return fmt.Errorf("tx decoder cannot be nil")
}
if c.SignerExtractor == nil {
return fmt.Errorf("signer extractor cannot be nil")
}
if c.MaxBlockSpace.IsNil() || c.MaxBlockSpace.IsNegative() || c.MaxBlockSpace.GT(math.LegacyOneDec()) {
return fmt.Errorf("max block space must be set to a value between 0 and 1")
}
+3 -1
View File
@@ -8,6 +8,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
"github.com/skip-mev/block-sdk/block/utils"
)
@@ -81,13 +82,14 @@ func DefaultTxPriority() TxPriority[string] {
}
// NewMempool returns a new Mempool.
func NewMempool[C comparable](txPriority TxPriority[C], txEncoder sdk.TxEncoder, maxTx int) *Mempool[C] {
func NewMempool[C comparable](txPriority TxPriority[C], txEncoder sdk.TxEncoder, extractor signer_extraction.Adapter, maxTx int) *Mempool[C] {
return &Mempool[C]{
index: NewPriorityMempool(
PriorityNonceMempoolConfig[C]{
TxPriority: txPriority,
MaxTx: maxTx,
},
extractor,
),
txPriority: txPriority,
txEncoder: txEncoder,
+25 -23
View File
@@ -21,7 +21,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
)
var (
@@ -62,11 +62,12 @@ type (
// priority to other sender txs and must be partially ordered by both sender-nonce
// and priority.
PriorityNonceMempool[C comparable] struct {
priorityIndex *skiplist.SkipList
priorityCounts map[C]int
senderIndices map[string]*skiplist.SkipList
scores map[txMeta[C]]txMeta[C]
cfg PriorityNonceMempoolConfig[C]
priorityIndex *skiplist.SkipList
priorityCounts map[C]int
senderIndices map[string]*skiplist.SkipList
scores map[txMeta[C]]txMeta[C]
cfg PriorityNonceMempoolConfig[C]
signerExtractor signer_extraction.Adapter
}
// PriorityNonceIterator defines an iterator that is used for mempool iteration
@@ -167,21 +168,22 @@ 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] {
func NewPriorityMempool[C comparable](cfg PriorityNonceMempoolConfig[C], extractor signer_extraction.Adapter) *PriorityNonceMempool[C] {
mp := &PriorityNonceMempool[C]{
priorityIndex: skiplist.New(skiplistComparable(cfg.TxPriority)),
priorityCounts: make(map[C]int),
senderIndices: make(map[string]*skiplist.SkipList),
scores: make(map[txMeta[C]]txMeta[C]),
cfg: cfg,
priorityIndex: skiplist.New(skiplistComparable(cfg.TxPriority)),
priorityCounts: make(map[C]int),
senderIndices: make(map[string]*skiplist.SkipList),
scores: make(map[txMeta[C]]txMeta[C]),
cfg: cfg,
signerExtractor: extractor,
}
return mp
}
// DefaultPriorityMempool returns a priorityNonceMempool with no options.
func DefaultPriorityMempool() *PriorityNonceMempool[int64] {
return NewPriorityMempool(DefaultPriorityNonceMempoolConfig())
func DefaultPriorityMempool(extractor signer_extraction.DefaultAdapter) *PriorityNonceMempool[int64] {
return NewPriorityMempool(DefaultPriorityNonceMempoolConfig(), extractor)
}
// NextSenderTx returns the next transaction for a given sender by nonce order,
@@ -213,18 +215,18 @@ func (mp *PriorityNonceMempool[C]) Insert(ctx context.Context, tx sdk.Tx) error
return nil
}
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
signers, err := mp.signerExtractor.GetSigners(tx)
if err != nil {
return err
}
if len(sigs) == 0 {
if len(signers) == 0 {
return fmt.Errorf("tx must have at least one signer")
}
sig := sigs[0]
sender := sdk.AccAddress(sig.PubKey.Address()).String()
signer := signers[0]
sender := signer.Signer.String()
priority := mp.cfg.TxPriority.GetTxPriority(ctx, tx)
nonce := sig.Sequence
nonce := signer.Sequence
key := txMeta[C]{nonce: nonce, priority: priority, sender: sender}
senderIndex, ok := mp.senderIndices[sender]
@@ -427,16 +429,16 @@ func (mp *PriorityNonceMempool[C]) CountTx() int {
// Remove removes a transaction from the mempool in O(log n) time, returning an
// error if unsuccessful.
func (mp *PriorityNonceMempool[C]) Remove(tx sdk.Tx) error {
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
signers, err := mp.signerExtractor.GetSigners(tx)
if err != nil {
return err
}
if len(sigs) == 0 {
if len(signers) == 0 {
return fmt.Errorf("attempted to remove a tx with no signatures")
}
sig := sigs[0]
sender := sdk.AccAddress(sig.PubKey.Address()).String()
sig := signers[0]
sender := sig.Signer.String()
nonce := sig.Sequence
scoreKey := txMeta[C]{nonce: nonce, sender: sender}
+20 -16
View File
@@ -12,6 +12,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
"github.com/skip-mev/block-sdk/block"
"github.com/skip-mev/block-sdk/block/base"
defaultlane "github.com/skip-mev/block-sdk/lanes/base"
@@ -60,24 +61,26 @@ func (suite *BlockBusterTestSuite) SetupTest() {
// TOB lane set up
suite.gasTokenDenom = "stake"
mevConfig := base.LaneConfig{
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
SignerExtractor: signer_extraction.NewDefaultAdapter(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
}
suite.mevLane = mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(suite.encodingConfig.TxConfig.TxDecoder()),
mev.NewDefaultAuctionFactory(suite.encodingConfig.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter()),
)
// Free lane set up
freeConfig := base.LaneConfig{
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
SignerExtractor: signer_extraction.NewDefaultAdapter(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
}
suite.freeLane = free.NewFreeLane(
freeConfig,
@@ -87,11 +90,12 @@ func (suite *BlockBusterTestSuite) SetupTest() {
// Base lane set up
baseConfig := base.LaneConfig{
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
Logger: log.NewNopLogger(),
TxEncoder: suite.encodingConfig.TxConfig.TxEncoder(),
TxDecoder: suite.encodingConfig.TxConfig.TxDecoder(),
SignerExtractor: signer_extraction.NewDefaultAdapter(),
AnteHandler: nil,
MaxBlockSpace: math.LegacyZeroDec(),
}
suite.baseLane = defaultlane.NewDefaultLane(
baseConfig,