feat: Integrating POB into sim-app base app. (#130)
Co-authored-by: Aleksandr Bezobchuk <aleks.bezobchuk@gmail.com>
This commit is contained in:
parent
e96831c244
commit
4da95939f5
2
go.mod
2
go.mod
@ -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
4
go.sum
@ -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=
|
||||
|
||||
@ -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
55
tests/app/ante.go
Normal 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...)
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -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{}),
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
@ -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",
|
||||
)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user