feat: Integrating POB into sim-app base app. (#130)

Co-authored-by: Aleksandr Bezobchuk <aleks.bezobchuk@gmail.com>
This commit is contained in:
David Terpay 2023-05-11 14:58:35 -04:00 committed by GitHub
parent e96831c244
commit 4da95939f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 200 additions and 31 deletions

2
go.mod
View File

@ -13,7 +13,7 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-beta.3
github.com/cosmos/cosmos-sdk v0.47.2
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogoproto v1.4.9
github.com/cosmos/gogoproto v1.4.8
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
github.com/gorilla/mux v1.8.0

4
go.sum
View File

@ -333,8 +333,8 @@ github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4x
github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=
github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI=
github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU=
github.com/cosmos/gogoproto v1.4.9 h1:MjVmV6F1yk1rJLWtKeYdGQcTbE880t+VlRcayEBqUKQ=
github.com/cosmos/gogoproto v1.4.9/go.mod h1:c0ysUnwvnlR+RmCUvqqii7pp8kHBB/DBcp/5VLA/nQk=
github.com/cosmos/gogoproto v1.4.8 h1:BrHKc6WFZt8+jRV71vKSQE+JrfF+JAnzrKo2VP7wIZ4=
github.com/cosmos/gogoproto v1.4.8/go.mod h1:hnb0DIEWTv+wdNzNcqus5xCQXq5+CXauq1FJuurRfVY=
github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38=
github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A=
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=

View File

@ -11,36 +11,59 @@ import (
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
)
var _ sdkmempool.Mempool = (*AuctionMempool)(nil)
var _ Mempool = (*AuctionMempool)(nil)
// AuctionMempool defines an auction mempool. It can be seen as an extension of
// an SDK PriorityNonceMempool, i.e. a mempool that supports <sender, nonce>
// two-dimensional priority ordering, with the additional support of prioritizing
// and indexing auction bids.
type AuctionMempool struct {
// globalIndex defines the index of all transactions in the mempool. It uses
// the SDK's builtin PriorityNonceMempool. Once a bid is selected for top-of-block,
// all subsequent transactions in the mempool will be selected from this index.
globalIndex sdkmempool.Mempool
type (
// Mempool defines the interface for a POB mempool.
Mempool interface {
// Inherit the methods of the SDK's Mempool interface.
sdkmempool.Mempool
// auctionIndex defines an index of auction bids.
auctionIndex sdkmempool.Mempool
// GetTopAuctionTx returns the top auction bid transaction in the mempool.
GetTopAuctionTx(ctx context.Context) sdk.Tx
// txDecoder defines the sdk.Tx decoder that allows us to decode transactions
// and construct sdk.Txs from the bundled transactions.
txDecoder sdk.TxDecoder
// CoutnAuctionTx returns the number of auction bid transactions in the mempool.
CountAuctionTx() int
// txEncoder defines the sdk.Tx encoder that allows us to encode transactions
// to bytes.
txEncoder sdk.TxEncoder
// AuctionBidSelect returns an iterator over the auction bid transactions in the mempool.
AuctionBidSelect(ctx context.Context) sdkmempool.Iterator
// txIndex is a map of all transactions in the mempool. It is used
// to quickly check if a transaction is already in the mempool.
txIndex map[string]struct{}
// Contains returns true if the mempool contains the given transaction.
Contains(tx sdk.Tx) (bool, error)
// AuctionFactory implements the functionality required to process auction transactions.
AuctionFactory
}
// AuctionFactory implements the functionality required to process auction transactions.
AuctionFactory
}
// AuctionMempool defines an auction mempool. It can be seen as an extension of
// an SDK PriorityNonceMempool, i.e. a mempool that supports <sender, nonce>
// two-dimensional priority ordering, with the additional support of prioritizing
// and indexing auction bids.
AuctionMempool struct {
// globalIndex defines the index of all transactions in the mempool. It uses
// the SDK's builtin PriorityNonceMempool. Once a bid is selected for top-of-block,
// all subsequent transactions in the mempool will be selected from this index.
globalIndex sdkmempool.Mempool
// auctionIndex defines an index of auction bids.
auctionIndex sdkmempool.Mempool
// txDecoder defines the sdk.Tx decoder that allows us to decode transactions
// and construct sdk.Txs from the bundled transactions.
txDecoder sdk.TxDecoder
// txEncoder defines the sdk.Tx encoder that allows us to encode transactions
// to bytes.
txEncoder sdk.TxEncoder
// txIndex is a map of all transactions in the mempool. It is used
// to quickly check if a transaction is already in the mempool.
txIndex map[string]struct{}
// AuctionFactory implements the functionality required to process auction transactions.
AuctionFactory
}
)
// AuctionTxPriority returns a TxPriority over auction bid transactions only. It
// is to be used in the auction index only.

55
tests/app/ante.go Normal file
View File

@ -0,0 +1,55 @@
package app
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/skip-mev/pob/mempool"
builderante "github.com/skip-mev/pob/x/builder/ante"
builderkeeper "github.com/skip-mev/pob/x/builder/keeper"
)
type POBHandlerOptions struct {
BaseOptions ante.HandlerOptions
Mempool mempool.Mempool
TxDecoder sdk.TxDecoder
TxEncoder sdk.TxEncoder
BuilderKeeper builderkeeper.Keeper
}
// NewPOBAnteHandler wraps all of the default Cosmos SDK AnteDecorators with the POB AnteHandler.
func NewPOBAnteHandler(options POBHandlerOptions) sdk.AnteHandler {
if options.BaseOptions.AccountKeeper == nil {
panic("account keeper is required for ante builder")
}
if options.BaseOptions.BankKeeper == nil {
panic("bank keeper is required for ante builder")
}
if options.BaseOptions.SignModeHandler == nil {
panic("sign mode handler is required for ante builder")
}
anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
ante.NewExtensionOptionsDecorator(options.BaseOptions.ExtensionOptionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.BaseOptions.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.BaseOptions.AccountKeeper),
ante.NewDeductFeeDecorator(
options.BaseOptions.AccountKeeper,
options.BaseOptions.BankKeeper,
options.BaseOptions.FeegrantKeeper,
options.BaseOptions.TxFeeChecker,
),
ante.NewSetPubKeyDecorator(options.BaseOptions.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(options.BaseOptions.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.BaseOptions.AccountKeeper, options.BaseOptions.SigGasConsumer),
ante.NewSigVerificationDecorator(options.BaseOptions.AccountKeeper, options.BaseOptions.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.BaseOptions.AccountKeeper),
builderante.NewBuilderDecorator(options.BuilderKeeper, options.TxDecoder, options.TxEncoder, options.Mempool),
}
return sdk.ChainAnteDecorators(anteDecorators...)
}

View File

@ -25,6 +25,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
@ -65,6 +66,10 @@ import (
"github.com/cosmos/cosmos-sdk/x/upgrade"
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
"github.com/skip-mev/pob/abci"
"github.com/skip-mev/pob/mempool"
buildermodule "github.com/skip-mev/pob/x/builder"
builderkeeper "github.com/skip-mev/pob/x/builder/keeper"
)
var (
@ -102,6 +107,7 @@ var (
vesting.AppModuleBasic{},
nftmodule.AppModuleBasic{},
consensus.AppModuleBasic{},
buildermodule.AppModuleBasic{},
)
)
@ -135,6 +141,7 @@ type TestApp struct {
FeeGrantKeeper feegrantkeeper.Keeper
GroupKeeper groupkeeper.Keeper
ConsensusParamsKeeper consensuskeeper.Keeper
BuilderKeeper builderkeeper.Keeper
}
func init() {
@ -212,6 +219,7 @@ func New(
&app.EvidenceKeeper,
&app.FeeGrantKeeper,
&app.GroupKeeper,
&app.BuilderKeeper,
&app.ConsensusParamsKeeper,
); err != nil {
panic(err)
@ -245,6 +253,39 @@ func New(
app.App = appBuilder.Build(logger, db, traceStore, baseAppOptions...)
// Set POB's mempool into the app.
mempool := mempool.NewAuctionMempool(app.txConfig.TxDecoder(), app.txConfig.TxEncoder(), 0, mempool.NewDefaultAuctionFactory(app.txConfig.TxDecoder()))
app.App.SetMempool(mempool)
// Create a global ante handler that will be called on each transaction when
// proposals are being built and verified.
handlerOptions := ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
SignModeHandler: app.txConfig.SignModeHandler(),
}
options := POBHandlerOptions{
BaseOptions: handlerOptions,
BuilderKeeper: app.BuilderKeeper,
Mempool: mempool,
TxDecoder: app.txConfig.TxDecoder(),
TxEncoder: app.txConfig.TxEncoder(),
}
anteHandler := NewPOBAnteHandler(options)
// Set the proposal handlers on the BaseApp.
proposalHandlers := abci.NewProposalHandler(
mempool,
app.App.Logger(),
anteHandler,
options.TxEncoder,
options.TxDecoder,
)
app.App.SetPrepareProposal(proposalHandlers.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandlers.ProcessProposalHandler())
// load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(app.App.BaseApp, appOpts, app.appCodec, logger, app.kvStoreKeys()); err != nil {
logger.Error("failed to load state streaming", "err", err)

View File

@ -43,6 +43,8 @@ import (
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
buildermodulev1 "github.com/skip-mev/pob/api/pob/builder/module/v1"
buildertypes "github.com/skip-mev/pob/x/builder/types"
"google.golang.org/protobuf/types/known/durationpb"
)
@ -59,7 +61,7 @@ var (
distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName,
minttypes.ModuleName, crisistypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
feegrant.ModuleName, group.ModuleName, paramstypes.ModuleName, upgradetypes.ModuleName,
vestingtypes.ModuleName, consensustypes.ModuleName,
vestingtypes.ModuleName, consensustypes.ModuleName, buildertypes.ModuleName,
}
// module account permissions
@ -70,6 +72,7 @@ var (
{Account: stakingtypes.BondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
{Account: stakingtypes.NotBondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}},
{Account: govtypes.ModuleName, Permissions: []string{authtypes.Burner}},
{Account: buildertypes.ModuleName, Permissions: []string{}},
}
// blocked account addresses
@ -113,6 +116,7 @@ var (
group.ModuleName,
paramstypes.ModuleName,
vestingtypes.ModuleName,
buildertypes.ModuleName,
consensustypes.ModuleName,
},
EndBlockers: []string{
@ -134,6 +138,7 @@ var (
consensustypes.ModuleName,
upgradetypes.ModuleName,
vestingtypes.ModuleName,
buildertypes.ModuleName,
},
OverrideStoreKeys: []*runtimev1alpha1.StoreKeyConfig{
{
@ -238,6 +243,10 @@ var (
Name: consensustypes.ModuleName,
Config: appconfig.WrapAny(&consensusmodulev1.Module{}),
},
{
Name: buildertypes.ModuleName,
Config: appconfig.WrapAny(&buildermodulev1.Module{}),
},
},
})
)

View File

@ -23,6 +23,7 @@ import (
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/skip-mev/pob/tests/app"
"github.com/skip-mev/pob/x/builder/types"
"github.com/spf13/viper"
"github.com/stretchr/testify/suite"
)
@ -105,10 +106,21 @@ func (s *IntegrationTestSuite) initNodes() {
// initialize a genesis file for the first validator
val0ConfigDir := s.chain.validators[0].configDir()
// Define the builder module parameters
params := types.Params{
MaxBundleSize: 5,
EscrowAccountAddress: "cosmos14j5j2lsx7629590jvpk3vj0xe9w8203jf4yknk",
ReserveFee: sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000)),
MinBuyInFee: sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000)),
MinBidIncrement: sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000)),
ProposerFee: sdk.NewDecWithPrec(1, 2),
}
for _, val := range s.chain.validators {
valAddr, err := val.keyInfo.GetAddress()
s.Require().NoError(err)
s.Require().NoError(addGenesisAccount(val0ConfigDir, "", initBalanceStr, valAddr))
s.Require().NoError(initGenesisFile(val0ConfigDir, "", initBalanceStr, valAddr, params))
}
// copy the genesis file to the remaining validators
@ -283,7 +295,7 @@ func (s *IntegrationTestSuite) runValidators() {
return true
},
5*time.Minute,
2*time.Minute,
time.Second,
"POB TestApp node failed to produce blocks",
)

View File

@ -12,6 +12,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/skip-mev/pob/x/builder/types"
)
func getGenDoc(path string) (*comettypes.GenesisDoc, error) {
@ -38,7 +39,7 @@ func getGenDoc(path string) (*comettypes.GenesisDoc, error) {
return doc, nil
}
func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error {
func initGenesisFile(path, moniker, amountStr string, accAddr sdk.AccAddress, params types.Params) error {
serverCtx := server.NewDefaultContext()
config := serverCtx.Config
@ -100,6 +101,16 @@ func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress)
appState[banktypes.ModuleName] = bankGenStateBz
builderGenState := types.GetGenesisStateFromAppState(cdc, appState)
builderGenState.Params = params
builderGenStateBz, err := cdc.MarshalJSON(&builderGenState)
if err != nil {
return fmt.Errorf("failed to marshal builder genesis state: %w", err)
}
appState[types.ModuleName] = builderGenStateBz
appStateJSON, err := json.Marshal(appState)
if err != nil {
return fmt.Errorf("failed to marshal application genesis state: %w", err)

View File

@ -1,5 +1,11 @@
package types
import (
"encoding/json"
"github.com/cosmos/cosmos-sdk/codec"
)
// NewGenesisState creates a new GenesisState instance.
func NewGenesisState(params Params) *GenesisState {
return &GenesisState{
@ -18,3 +24,15 @@ func DefaultGenesisState() *GenesisState {
func (gs GenesisState) Validate() error {
return gs.Params.Validate()
}
// GetGenesisStateFromAppState returns x/builder GenesisState given raw application
// genesis state.
func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) GenesisState {
var genesisState GenesisState
if appState[ModuleName] != nil {
cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState)
}
return genesisState
}