feat!: Define Genesis state transition (#15999)

This commit is contained in:
Marko 2023-05-03 10:58:58 +02:00 committed by GitHub
parent 672b1f9e15
commit d31f2964b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 79 additions and 44 deletions

View File

@ -180,6 +180,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* The signature of `NewSigVerificationDecorator` has been changed to accept a `x/tx/signing.HandlerMap`.
* The signature of `VerifySignature` has been changed to accept a `x/tx/signing.HandlerMap` and other structs from `x/tx` as arguments.
* The signature of `NewTxConfigWithTextual` has been deprecated and its signature changed to accept a `SignModeOptions`.
* (x/genutil) [#15999](https://github.com/cosmos/cosmos-sdk/pull/15999) Genutil now takes the `GenesisTxHanlder` interface instead of deliverTx. The interface is implemented on baseapp
### Client Breaking Changes

22
baseapp/genesis.go Normal file
View File

@ -0,0 +1,22 @@
package baseapp
import (
"errors"
"cosmossdk.io/core/genesis"
"github.com/cometbft/cometbft/abci/types"
)
var _ genesis.TxHandler = (*BaseApp)(nil)
// ExecuteGenesisTx implements genesis.GenesisState from
// cosmossdk.io/core/genesis to set initial state in genesis
func (ba BaseApp) ExecuteGenesisTx(tx []byte) error {
res := ba.DeliverTx(types.RequestDeliverTx{Tx: tx})
if res.Code != types.CodeTypeOK {
return errors.New(res.Log)
}
return nil
}

View File

@ -38,4 +38,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API-Breaking Changes
- (store)[14635](https://github.com/cosmos/cosmos-sdk/pull/14635) Add error handling to all methods on the `KVStore` interface
* (store)[14635](https://github.com/cosmos/cosmos-sdk/pull/14635) Add error handling to all methods on the `KVStore` interface
### Features
* (genesis) [#15999](https://github.com/cosmos/cosmos-sdk/pull/15999) Add `GenesisTxHandler` interface

View File

@ -0,0 +1,6 @@
package genesis
// TxHandler is an interface that modules can implement to provide genesis state transitions
type TxHandler interface {
ExecuteGenesisTx([]byte) error
}

View File

@ -70,3 +70,11 @@ See an example of `ExportGenesis` from the `auth` module.
```go reference
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/keeper/genesis.go#L37-L49
```
### GenesisTxHandler
`GenesisTxHandler` is a way for modules to submit state transitions prior to the first block. This is used by `x/genutil` to submit the genesis transactions for the validators to be added to staking.
```go reference
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/core/genesis/txhandler.go#L3-L6
```

View File

@ -4,14 +4,13 @@ import (
"fmt"
"os"
"cosmossdk.io/core/genesis"
"cosmossdk.io/core/store"
"cosmossdk.io/log"
"github.com/cosmos/gogoproto/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoregistry"
abci "github.com/cometbft/cometbft/abci/types"
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
"cosmossdk.io/core/appmodule"
@ -62,7 +61,7 @@ func init() {
ProvideKVStoreKey,
ProvideTransientStoreKey,
ProvideMemoryStoreKey,
ProvideDeliverTx,
ProvideGenesisTxHandler,
ProvideKVStoreService,
ProvideMemoryStoreService,
ProvideTransientStoreService,
@ -211,10 +210,8 @@ func ProvideMemoryStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes
return storeKey
}
func ProvideDeliverTx(appBuilder *AppBuilder) func(abci.RequestDeliverTx) abci.ResponseDeliverTx {
return func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx {
return appBuilder.app.BaseApp.DeliverTx(tx)
}
func ProvideGenesisTxHandler(appBuilder *AppBuilder) genesis.TxHandler {
return appBuilder.app
}
func ProvideKVStoreService(config *runtimev1alpha1.Module, key depinject.ModuleKey, app *AppBuilder) store.KVStoreService {

View File

@ -358,7 +358,7 @@ func NewSimApp(
// must be passed by reference here.
app.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
app.AccountKeeper, app.StakingKeeper, app,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),

View File

@ -305,13 +305,13 @@ func TestDeliverGenTxs(t *testing.T) {
if tc.expPass {
require.NotPanics(t, func() {
genutil.DeliverGenTxs(
f.ctx, genTxs, f.stakingKeeper, f.baseApp.DeliverTx,
f.ctx, genTxs, f.stakingKeeper, f.baseApp,
f.encodingConfig.TxConfig,
)
})
} else {
_, err := genutil.DeliverGenTxs(
f.ctx, genTxs, f.stakingKeeper, f.baseApp.DeliverTx,
f.ctx, genTxs, f.stakingKeeper, f.baseApp,
f.encodingConfig.TxConfig,
)

View File

@ -141,8 +141,8 @@ require (
// TODO: remove after merge of https://github.com/cosmos/cosmos-sdk/pull/15873 and tagging releases
replace (
cosmossdk.io/core => ../../core
cosmossdk.io/store => ../../store
cosmossdk.io/x/tx => ../../x/tx
cosmossdk.io/core => ../../core
github.com/cosmos/cosmos-sdk => ../..
)

View File

@ -39,8 +39,6 @@ cosmossdk.io/api v0.4.1 h1:0ikaYM6GyxTYYcfBiyR8YnLCfhNnhKpEFnaSepCTmqg=
cosmossdk.io/api v0.4.1/go.mod h1:jR7k5ok90LxW2lFUXvd8Vpo/dr4PpiyVegxdm7b1ZdE=
cosmossdk.io/collections v0.1.0 h1:nzJGeiq32KnZroSrhB6rPifw4I85Cgmzw/YAmr4luv8=
cosmossdk.io/collections v0.1.0/go.mod h1:xbauc0YsbUF8qKMVeBZl0pFCunxBIhKN/WlxpZ3lBuo=
cosmossdk.io/core v0.6.1 h1:OBy7TI2W+/gyn2z40vVvruK3di+cAluinA6cybFbE7s=
cosmossdk.io/core v0.6.1/go.mod h1:g3MMBCBXtxbDWBURDVnJE7XML4BG5qENhs0gzkcpuFA=
cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw=
cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU=
cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w=

View File

@ -1,6 +1,7 @@
package genutil
import (
"cosmossdk.io/core/genesis"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/client"
@ -11,7 +12,7 @@ import (
// InitGenesis - initialize accounts and deliver genesis transactions
func InitGenesis(
ctx sdk.Context, stakingKeeper types.StakingKeeper,
deliverTx deliverTxfn, genesisState types.GenesisState,
deliverTx genesis.TxHandler, genesisState types.GenesisState,
txEncodingConfig client.TxEncodingConfig,
) (validators []abci.ValidatorUpdate, err error) {
if len(genesisState.GenTxs) > 0 {

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"cosmossdk.io/core/genesis"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/client"
@ -84,14 +85,12 @@ func ValidateAccountInGenesis(
return nil
}
type deliverTxfn func(abci.RequestDeliverTx) abci.ResponseDeliverTx
// DeliverGenTxs iterates over all genesis txs, decodes each into a Tx and
// invokes the provided deliverTxfn with the decoded Tx. It returns the result
// of the staking module's ApplyAndReturnValidatorSetUpdates.
func DeliverGenTxs(
ctx sdk.Context, genTxs []json.RawMessage,
stakingKeeper types.StakingKeeper, deliverTx deliverTxfn,
stakingKeeper types.StakingKeeper, deliverTx genesis.TxHandler,
txEncodingConfig client.TxEncodingConfig,
) ([]abci.ValidatorUpdate, error) {
for _, genTx := range genTxs {
@ -105,9 +104,9 @@ func DeliverGenTxs(
return nil, fmt.Errorf("failed to encode GenTx '%s': %s", genTx, err)
}
res := deliverTx(abci.RequestDeliverTx{Tx: bz})
if !res.IsOK() {
return nil, fmt.Errorf("failed to execute DeliverTx for '%s': %s", genTx, res.Log)
err = deliverTx.ExecuteGenesisTx(bz)
if err != nil {
return nil, fmt.Errorf("failed to execute DeliverTx for '%s': %s", genTx, err)
}
}

View File

@ -2,15 +2,16 @@ package genutil_test
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"testing"
"time"
"cosmossdk.io/core/genesis"
"cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
@ -18,7 +19,6 @@ import (
"github.com/cosmos/cosmos-sdk/testutil"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
@ -246,7 +246,7 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
testCases := []struct {
msg string
malleate func()
deliverTxFn func(abci.RequestDeliverTx) abci.ResponseDeliverTx
deliverTxFn genesis.TxHandler
expPass bool
}{
{
@ -260,14 +260,7 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
suite.Require().NoError(err)
genTxs[0] = tx
},
func(_ abci.RequestDeliverTx) abci.ResponseDeliverTx {
return abci.ResponseDeliverTx{
Code: sdkerrors.ErrNoSignatures.ABCICode(),
GasWanted: int64(10000000),
GasUsed: int64(41913),
Log: "no signatures supplied",
}
},
GenesisState1{},
false,
},
{
@ -293,15 +286,7 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
suite.Require().NoError(err)
genTxs[0] = genTx
},
func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx {
return abci.ResponseDeliverTx{
Code: sdkerrors.ErrUnauthorized.ABCICode(),
GasWanted: int64(10000000),
GasUsed: int64(41353),
Log: "signature verification failed; please verify account number (4) and chain-id (): unauthorized",
Codespace: "sdk",
}
},
GenesisState2{},
true,
},
}
@ -313,6 +298,7 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
tc.malleate()
if tc.expPass {
suite.stakingKeeper.EXPECT().ApplyAndReturnValidatorSetUpdates(gomock.Any()).Return(nil, nil).AnyTimes()
suite.Require().NotPanics(func() {
genutil.DeliverGenTxs(
suite.ctx, genTxs, suite.stakingKeeper, tc.deliverTxFn,
@ -334,3 +320,15 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
func TestGenTxTestSuite(t *testing.T) {
suite.Run(t, new(GenTxTestSuite))
}
type GenesisState1 struct{}
func (GenesisState1) ExecuteGenesisTx(_ []byte) error {
return errors.New("no signatures supplied")
}
type GenesisState2 struct{}
func (GenesisState2) ExecuteGenesisTx(tx []byte) error {
return nil
}

View File

@ -10,6 +10,7 @@ import (
modulev1 "cosmossdk.io/api/cosmos/genutil/module/v1"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/genesis"
"cosmossdk.io/depinject"
@ -80,13 +81,13 @@ type AppModule struct {
accountKeeper types.AccountKeeper
stakingKeeper types.StakingKeeper
deliverTx deliverTxfn
deliverTx genesis.TxHandler
txEncodingConfig client.TxEncodingConfig
}
// NewAppModule creates a new AppModule object
func NewAppModule(accountKeeper types.AccountKeeper,
stakingKeeper types.StakingKeeper, deliverTx deliverTxfn,
stakingKeeper types.StakingKeeper, deliverTx genesis.TxHandler,
txEncodingConfig client.TxEncodingConfig,
) module.GenesisOnlyAppModule {
return module.NewGenesisOnlyAppModule(AppModule{
@ -138,7 +139,7 @@ type ModuleInputs struct {
AccountKeeper types.AccountKeeper
StakingKeeper types.StakingKeeper
DeliverTx func(abci.RequestDeliverTx) abci.ResponseDeliverTx
DeliverTx genesis.TxHandler
Config client.TxConfig
}