diff --git a/core/main.go b/core/main.go index 6c0bc1554..3e4860d67 100644 --- a/core/main.go +++ b/core/main.go @@ -8,6 +8,7 @@ import ( "github.com/mesg-foundation/engine/config" "github.com/mesg-foundation/engine/container" + "github.com/mesg-foundation/engine/cosmos" "github.com/mesg-foundation/engine/database" "github.com/mesg-foundation/engine/database/store" "github.com/mesg-foundation/engine/hash" @@ -17,13 +18,13 @@ import ( instancesdk "github.com/mesg-foundation/engine/sdk/instance" servicesdk "github.com/mesg-foundation/engine/sdk/service" "github.com/mesg-foundation/engine/server/grpc" - "github.com/mesg-foundation/engine/tendermint" "github.com/mesg-foundation/engine/version" "github.com/mesg-foundation/engine/x/xerrors" "github.com/mesg-foundation/engine/x/xnet" "github.com/mesg-foundation/engine/x/xos" "github.com/mesg-foundation/engine/x/xsignal" "github.com/sirupsen/logrus" + db "github.com/tendermint/tm-db" ) var network = flag.Bool("experimental-network", false, "start the engine with the network") @@ -145,11 +146,25 @@ func main() { logger.Init(cfg.Log.Format, cfg.Log.Level, cfg.Log.ForceColors) if *network { + // init cosmos app + db, err := db.NewGoLevelDB("app", cfg.Cosmos.Path) + if err != nil { + logrus.WithField("module", "main").Fatalln(err) + } + app := cosmos.NewApp(logger.TendermintLogger(), db) + cosmos.InitDefaultAppModules(app) + err = app.Load() + if err != nil { + logrus.WithField("module", "main").Fatalln(err) + } + // create tendermint node - node, err := tendermint.NewNode(cfg.Tendermint.Config, &cfg.Cosmos) + node, err := cosmos.NewNode(app, cfg.Tendermint.Config, &cfg.Cosmos) if err != nil { logrus.WithField("module", "main").Fatalln(err) } + + // start tendermint node logrus.WithField("module", "main").WithField("seeds", cfg.Tendermint.P2P.Seeds).Info("starting tendermint node") if err := node.Start(); err != nil { logrus.WithField("module", "main").Fatalln(err) diff --git a/cosmos/app.go b/cosmos/app.go new file mode 100644 index 000000000..3c141008a --- /dev/null +++ b/cosmos/app.go @@ -0,0 +1,130 @@ +package cosmos + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/baseapp" + bam "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" +) + +// App is a Cosmos application that inherit from BaseApp. +type App struct { + *baseapp.BaseApp + cdc *codec.Codec + modulesBasic []module.AppModuleBasic + modules []module.AppModule + storeKeys map[string]*sdk.KVStoreKey + transientStoreKeys map[string]*sdk.TransientStoreKey + orderBeginBlockers []string + orderEndBlockers []string + orderInitGenesis []string + anteHandler sdk.AnteHandler +} + +// NewApp initializes a new App. +func NewApp(logger log.Logger, db dbm.DB) *App { + cdc := codec.New() + sdk.RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + + return &App{ + BaseApp: bam.NewBaseApp("engine", logger, db, auth.DefaultTxDecoder(cdc)), + modules: []module.AppModule{}, + cdc: cdc, + storeKeys: map[string]*sdk.KVStoreKey{ + bam.MainStoreKey: sdk.NewKVStoreKey(bam.MainStoreKey), + }, + transientStoreKeys: map[string]*sdk.TransientStoreKey{}, + } +} + +// DefaultGenesis returns the default genesis from the basic manager. +func (a *App) DefaultGenesis() map[string]json.RawMessage { + basicManager := module.NewBasicManager(a.modulesBasic...) + basicManager.RegisterCodec(a.cdc) + return basicManager.DefaultGenesis() +} + +// RegisterModule registers a module to the app. +func (a *App) RegisterModule(module module.AppModule) { + a.modulesBasic = append(a.modulesBasic, module) + a.modules = append(a.modules, module) +} + +// RegisterOrderInitGenesis sets the order of the modules when they are called to initialize the genesis. +func (a *App) RegisterOrderInitGenesis(moduleNames ...string) { + a.orderInitGenesis = moduleNames +} + +// RegisterOrderBeginBlocks sets the order of the modules when they are called on the begin block event. +func (a *App) RegisterOrderBeginBlocks(beginBlockers ...string) { + a.orderBeginBlockers = beginBlockers +} + +// RegisterOrderEndBlocks sets the order of the modules when they are called on the end block event. +func (a *App) RegisterOrderEndBlocks(endBlockers ...string) { + a.orderEndBlockers = endBlockers +} + +// RegisterStoreKey registers a store key to the app. +func (a *App) RegisterStoreKey(storeKey *sdk.KVStoreKey) { + a.storeKeys[storeKey.Name()] = storeKey +} + +// RegisterTransientStoreKey registers a transient store key to the app. +func (a *App) RegisterTransientStoreKey(transientStoreKey *sdk.TransientStoreKey) { + a.transientStoreKeys[transientStoreKey.Name()] = transientStoreKey +} + +// SetAnteHandler registers the authentication handler to the app. +func (a *App) SetAnteHandler(anteHandler sdk.AnteHandler) { + a.anteHandler = anteHandler +} + +// Cdc returns the codec of the app. +func (a *App) Cdc() *codec.Codec { + return a.cdc +} + +// Load creates the module manager, registers the modules to it, mounts the stores and finally load the app itself. +func (a *App) Load() error { + // where all the magic happen + // basically register everything on baseapp and load it + + mm := module.NewManager(a.modules...) + mm.SetOrderBeginBlockers(a.orderBeginBlockers...) + mm.SetOrderEndBlockers(a.orderEndBlockers...) + + // Sets the order of Genesis - Order matters, genutil is to always come last + mm.SetOrderInitGenesis(a.orderInitGenesis...) + + // register all module routes and module queriers + mm.RegisterRoutes(a.Router(), a.QueryRouter()) + + // The initChainer handles translating the genesis.json file into initial state for the network + a.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + var genesisData map[string]json.RawMessage + if err := a.cdc.UnmarshalJSON(req.AppStateBytes, &genesisData); err != nil { + panic(err) + } + return mm.InitGenesis(ctx, genesisData) + }) + a.SetBeginBlocker(mm.BeginBlock) + a.SetEndBlocker(mm.EndBlock) + + // The AnteHandler handles signature verification and transaction pre-processing + a.SetAnteHandler(a.anteHandler) + + // initialize stores + a.MountKVStores(a.storeKeys) + a.MountTransientStores(a.transientStoreKeys) + + return a.LoadLatestVersion(a.storeKeys[bam.MainStoreKey]) +} diff --git a/cosmos/initModules.go b/cosmos/initModules.go new file mode 100644 index 000000000..45239df66 --- /dev/null +++ b/cosmos/initModules.go @@ -0,0 +1,118 @@ +package cosmos + +import ( + cosmostypes "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/genaccounts" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/supply" +) + +// InitDefaultAppModules initializes the default cosmos modules. +func InitDefaultAppModules(app *App) { + // init cosmos stores + paramsStoreKey := cosmostypes.NewKVStoreKey(params.StoreKey) + app.RegisterStoreKey(paramsStoreKey) + paramsTStoreKey := cosmostypes.NewTransientStoreKey(params.TStoreKey) + app.RegisterTransientStoreKey(paramsTStoreKey) + supplyStoreKey := cosmostypes.NewKVStoreKey(supply.StoreKey) + app.RegisterStoreKey(supplyStoreKey) + stakingStoreKey := cosmostypes.NewKVStoreKey(staking.StoreKey) + app.RegisterStoreKey(stakingStoreKey) + stakingTStoreKey := cosmostypes.NewTransientStoreKey(staking.TStoreKey) + app.RegisterTransientStoreKey(stakingTStoreKey) + distrStoreKey := cosmostypes.NewKVStoreKey(distribution.StoreKey) + app.RegisterStoreKey(distrStoreKey) + slashingStoreKey := cosmostypes.NewKVStoreKey(slashing.StoreKey) + app.RegisterStoreKey(slashingStoreKey) + + // init cosmos keepers + paramsKeeper := params.NewKeeper( + app.Cdc(), + paramsStoreKey, + paramsTStoreKey, + params.DefaultCodespace, + ) + accountKeeper := auth.NewAccountKeeper( + app.Cdc(), + paramsStoreKey, + paramsKeeper.Subspace(auth.DefaultParamspace), + auth.ProtoBaseAccount, + ) + bankKeeper := bank.NewBaseKeeper( + accountKeeper, + paramsKeeper.Subspace(bank.DefaultParamspace), + bank.DefaultCodespace, + nil, + ) + supplyKeeper := supply.NewKeeper( + app.Cdc(), + supplyStoreKey, + accountKeeper, + bankKeeper, + map[string][]string{ + auth.FeeCollectorName: nil, + distribution.ModuleName: nil, + staking.BondedPoolName: {supply.Burner, supply.Staking}, + staking.NotBondedPoolName: {supply.Burner, supply.Staking}, + }, + ) + stakingKeeper := staking.NewKeeper( + app.Cdc(), + stakingStoreKey, + stakingTStoreKey, + supplyKeeper, + paramsKeeper.Subspace(staking.DefaultParamspace), + staking.DefaultCodespace, + ) + distrKeeper := distribution.NewKeeper( + app.Cdc(), + distrStoreKey, + paramsKeeper.Subspace(distribution.DefaultParamspace), + &stakingKeeper, + supplyKeeper, + distribution.DefaultCodespace, + auth.FeeCollectorName, + nil, + ) + slashingKeeper := slashing.NewKeeper( + app.Cdc(), + slashingStoreKey, + &stakingKeeper, + paramsKeeper.Subspace(slashing.DefaultParamspace), + slashing.DefaultCodespace, + ) + stakingKeeper = *stakingKeeper.SetHooks( + staking.NewMultiStakingHooks( + distrKeeper.Hooks(), + slashingKeeper.Hooks()), + ) + + // init cosmos module + app.RegisterModule(genaccounts.NewAppModule(accountKeeper)) + app.RegisterModule(genutil.NewAppModule(accountKeeper, stakingKeeper, app.DeliverTx)) + app.RegisterModule(auth.NewAppModule(accountKeeper)) + app.RegisterModule(bank.NewAppModule(bankKeeper, accountKeeper)) + app.RegisterModule(supply.NewAppModule(supplyKeeper, accountKeeper)) + app.RegisterModule(distribution.NewAppModule(distrKeeper, supplyKeeper)) + app.RegisterModule(slashing.NewAppModule(slashingKeeper, stakingKeeper)) + app.RegisterModule(staking.NewAppModule(stakingKeeper, distrKeeper, accountKeeper, supplyKeeper)) + + app.RegisterOrderBeginBlocks(distribution.ModuleName, slashing.ModuleName) + app.RegisterOrderEndBlocks(staking.ModuleName) + + app.RegisterOrderInitGenesis( + genaccounts.ModuleName, + distribution.ModuleName, + staking.ModuleName, + auth.ModuleName, + bank.ModuleName, + slashing.ModuleName, + genutil.ModuleName, + ) +} diff --git a/tendermint/keybase.go b/cosmos/keybase.go similarity index 85% rename from tendermint/keybase.go rename to cosmos/keybase.go index 7f6212797..1b653b278 100644 --- a/tendermint/keybase.go +++ b/cosmos/keybase.go @@ -1,4 +1,4 @@ -package tendermint +package cosmos import ( clientkey "github.com/cosmos/cosmos-sdk/client/keys" @@ -13,8 +13,8 @@ type Keybase struct { keys.Keybase } -// NewFSKeybase initializes a filesystem keybase at a particular dir. -func NewFSKeybase(dir string) (*Keybase, error) { +// NewKeybase initializes a filesystem keybase at a particular dir. +func NewKeybase(dir string) (*Keybase, error) { kb, err := clientkey.NewKeyBaseFromDir(dir) if err != nil { return nil, err diff --git a/cosmos/module.go b/cosmos/module.go new file mode 100644 index 000000000..0583e9023 --- /dev/null +++ b/cosmos/module.go @@ -0,0 +1,143 @@ +package cosmos + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/gorilla/mux" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" +) + +// type check to ensure the interface is properly implemented +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic is a basic element of an cosmos app. +type AppModuleBasic struct { + name string +} + +// AppModule is a main element of an cosmos app. +type AppModule struct { + AppModuleBasic + handler sdk.Handler + querier Querier + cdc *codec.Codec +} + +// Querier is responsible to answer to ABCI queries. +type Querier func(request sdk.Request, path []string, req abci.RequestQuery) (res interface{}, err error) + +// NewAppModuleBasic inits an AppModuleBasic using a name. +func NewAppModuleBasic(name string) AppModuleBasic { + return AppModuleBasic{ + name: name, + } +} + +// NewAppModule inits an AppModule using an AppModuleBasic, Codec, Handler and Querier. +func NewAppModule(moduleBasic AppModuleBasic, cdc *codec.Codec, handler sdk.Handler, querier Querier) AppModule { + return AppModule{ + AppModuleBasic: moduleBasic, + handler: handler, + querier: querier, + cdc: cdc, + } +} + +// ---------------------------------------------- +// AppModuleBasic +// ---------------------------------------------- + +// Name returns the name of the module. +func (m AppModuleBasic) Name() string { + return m.name +} + +// RegisterCodec registers the module's structs in the codec. +func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { +} + +// DefaultGenesis returns the default genesis of the module. +func (AppModuleBasic) DefaultGenesis() json.RawMessage { + return []byte("{}") +} + +// ValidateGenesis checks a Genesis. +func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { + return nil +} + +// RegisterRESTRoutes registers rest routes +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {} + +// GetQueryCmd returns the root query command of this module +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + return nil +} + +// GetTxCmd returns the root tx command of this module +func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { + return nil +} + +// ---------------------------------------------- +// AppModule +// ---------------------------------------------- + +// RegisterInvariants registers invariants to the registry. +func (m AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// Route returns the route prefix for transaction of the module. +func (m AppModule) Route() string { + return m.name +} + +// NewHandler returns the handler used to apply transactions. +func (m AppModule) NewHandler() sdk.Handler { + return m.handler +} + +// QuerierRoute the route prefix for query of the module. +func (m AppModule) QuerierRoute() string { + return m.name +} + +// NewQuerierHandler returns the handler used to reply ABCI query. +func (m AppModule) NewQuerierHandler() sdk.Querier { + return func(request sdk.Request, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + data, err := m.querier(request, path, req) + if err != nil { + return nil, sdk.ErrInternal(err.Error()) + } + res, err := m.cdc.MarshalJSON(data) + if err != nil { + return nil, sdk.ErrInternal(err.Error()) + } + return res, nil + } +} + +// BeginBlock is called at the beginning of the process of a new block. +func (m AppModule) BeginBlock(_ sdk.Request, _ abci.RequestBeginBlock) {} + +// EndBlock is called at the end of the process of a new block. +func (m AppModule) EndBlock(sdk.Request, abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// InitGenesis initializes the genesis from a request and data. +func (m AppModule) InitGenesis(request sdk.Request, data json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ExportGenesis exports the current state of the app. +func (m AppModule) ExportGenesis(request sdk.Request) json.RawMessage { + return []byte("{}") +} diff --git a/tendermint/node.go b/cosmos/node.go similarity index 59% rename from tendermint/node.go rename to cosmos/node.go index 5b5008505..cefd84726 100644 --- a/tendermint/node.go +++ b/cosmos/node.go @@ -1,21 +1,17 @@ -package tendermint +package cosmos import ( "encoding/json" "time" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdktypes "github.com/cosmos/cosmos-sdk/types" - authutils "github.com/cosmos/cosmos-sdk/x/auth/client/utils" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/genaccounts" "github.com/cosmos/cosmos-sdk/x/genutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/mesg-foundation/engine/config" "github.com/mesg-foundation/engine/logger" - "github.com/mesg-foundation/engine/tendermint/app" - "github.com/sirupsen/logrus" tmconfig "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/node" @@ -23,101 +19,60 @@ import ( "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/types" - db "github.com/tendermint/tm-db" ) -// NewNode retruns new tendermint node that runs the app. -func NewNode(cfg *tmconfig.Config, ccfg *config.CosmosConfig) (*node.Node, error) { - nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) - if err != nil { - return nil, err - } - - me := privval.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) +// NewNode creates a new Tendermint node from an App. +func NewNode(app *App, cfg *tmconfig.Config, ccfg *config.CosmosConfig) (*node.Node, error) { + cdc := app.Cdc() - // create user database and generate first user - kb, err := NewFSKeybase(ccfg.Path) + // create user database + kb, err := NewKeybase(ccfg.Path) if err != nil { return nil, err } + // generate first user account, err := kb.GenerateAccount(ccfg.GenesisAccount.Name, ccfg.GenesisAccount.Mnemonic, ccfg.GenesisAccount.Password) if err != nil { return nil, err } - // create app database and create an instance of the app - db, err := db.NewGoLevelDB("app", ccfg.Path) - if err != nil { - return nil, err - } - - logger := logger.TendermintLogger() - app, cdc := app.NewNameServiceApp(logger, db) - // build a message to create validator msg := newMsgCreateValidator( sdktypes.ValAddress(account.GetAddress()), ed25519.PubKeyEd25519(ccfg.ValidatorPubKey), ccfg.GenesisAccount.Name, ) - logrus.WithField("msg", msg).Info("validator tx") - - // sign the message - signedTx, err := signTransaction( - cdc, - kb, - msg, - ccfg.ChainID, - ccfg.GenesisAccount.Name, - ccfg.GenesisAccount.Password, - ) + signedTx, err := NewTxBuilder(cdc, 0, 0, kb, ccfg.ChainID).BuildAndSignStdTx(msg, ccfg.GenesisAccount.Name, ccfg.GenesisAccount.Password) if err != nil { return nil, err } - logrus.WithField("signedTx", signedTx).Info("signed tx") // initialize app state with first validator - appState, err := createAppState(cdc, account.GetAddress(), signedTx) + appState, err := createAppState(app.DefaultGenesis(), cdc, account.GetAddress(), signedTx) + if err != nil { + return nil, err + } + + nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { return nil, err } - return node.NewNode(cfg, - me, + // init node + return node.NewNode( + cfg, + privval.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()), nodeKey, proxy.NewLocalClientCreator(app), genesisLoader(cdc, appState, ccfg.ChainID, ccfg.GenesisTime), node.DefaultDBProvider, node.DefaultMetricsProvider(cfg.Instrumentation), - logger, + logger.TendermintLogger(), ) } -func signTransaction(cdc *codec.Codec, kb *Keybase, msg sdktypes.Msg, chainID, accountName, accountPassword string) (authtypes.StdTx, error) { - fees := authtypes.NewStdFee(flags.DefaultGasLimit, sdktypes.NewCoins()) - gasPrices := sdktypes.DecCoins{} - stdTx := authtypes.NewStdTx([]sdktypes.Msg{msg}, fees, []authtypes.StdSignature{}, "") - - txBldr := authtypes.NewTxBuilder( - authutils.GetTxEncoder(cdc), - 0, - 0, - flags.DefaultGasLimit, - flags.DefaultGasAdjustment, - true, - chainID, - "", - sdktypes.NewCoins(), - gasPrices, - ).WithKeybase(kb) - - return txBldr.SignStdTx(accountName, accountPassword, stdTx, false) -} - -func createAppState(cdc *codec.Codec, address sdktypes.AccAddress, signedStdTx authtypes.StdTx) (map[string]json.RawMessage, error) { - appState := app.ModuleBasics.DefaultGenesis() - +func createAppState(defaultGenesisŚtate map[string]json.RawMessage, cdc *codec.Codec, address sdktypes.AccAddress, signedStdTx authtypes.StdTx) (map[string]json.RawMessage, error) { stakes := sdktypes.NewCoin(sdktypes.DefaultBondDenom, sdktypes.NewInt(100000000)) genAcc := genaccounts.NewGenesisAccountRaw(address, sdktypes.NewCoins(stakes), sdktypes.NewCoins(), 0, 0, "", "") if err := genAcc.Validate(); err != nil { @@ -128,9 +83,9 @@ func createAppState(cdc *codec.Codec, address sdktypes.AccAddress, signedStdTx a if err != nil { return nil, err } - appState[genaccounts.ModuleName] = genstate + defaultGenesisŚtate[genaccounts.ModuleName] = genstate - return genutil.SetGenTxsInAppGenesisState(cdc, appState, []authtypes.StdTx{signedStdTx}) + return genutil.SetGenTxsInAppGenesisState(cdc, defaultGenesisŚtate, []authtypes.StdTx{signedStdTx}) } func genesisLoader(cdc *codec.Codec, appState map[string]json.RawMessage, chainID string, genesisTime time.Time) func() (*types.GenesisDoc, error) { diff --git a/cosmos/txbuilder.go b/cosmos/txbuilder.go new file mode 100644 index 000000000..819271767 --- /dev/null +++ b/cosmos/txbuilder.go @@ -0,0 +1,49 @@ +package cosmos + +import ( + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys" + sdktypes "github.com/cosmos/cosmos-sdk/types" + authutils "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/tendermint/tendermint/types" +) + +// TxBuilder implements a transaction context created in SDK modules. +type TxBuilder struct { + authtypes.TxBuilder +} + +// NewTxBuilder returns a new initialized TxBuilder. +func NewTxBuilder(cdc *codec.Codec, accNumber, accSeq uint64, kb keys.Keybase, chainID string) TxBuilder { + return TxBuilder{ + authtypes.NewTxBuilder( + authutils.GetTxEncoder(cdc), + accNumber, + accSeq, + flags.DefaultGasLimit, + flags.DefaultGasAdjustment, + true, + chainID, + "", + sdktypes.NewCoins(), + sdktypes.DecCoins{}, + ).WithKeybase(kb), + } +} + +// BuildAndSignStdTx a signed transaction from a message. +func (b TxBuilder) BuildAndSignStdTx(msg sdktypes.Msg, accountName, accountPassword string) (authtypes.StdTx, error) { + signedMsg, err := b.BuildSignMsg([]sdktypes.Msg{msg}) + if err != nil { + return authtypes.StdTx{}, err + } + stdTx := authtypes.NewStdTx(signedMsg.Msgs, signedMsg.Fee, []authtypes.StdSignature{}, signedMsg.Memo) + return b.SignStdTx(accountName, accountPassword, stdTx, false) +} + +// Encode a transaction. +func (b TxBuilder) Encode(tx sdktypes.Tx) (types.Tx, error) { + return b.TxEncoder()(tx) +} diff --git a/go.mod b/go.mod index 522461171..ec1fb6aa9 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/golang/protobuf v1.3.2 github.com/google/go-cmp v0.3.1 // indirect github.com/google/uuid v1.1.1 // indirect - github.com/gorilla/mux v1.7.3 // indirect + github.com/gorilla/mux v1.7.3 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/huandu/xstrings v1.2.0 // indirect github.com/imdario/mergo v0.3.7 // indirect @@ -56,6 +56,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962 // indirect github.com/rs/cors v1.7.0 // indirect github.com/sirupsen/logrus v1.4.2 + github.com/spf13/cobra v0.0.5 github.com/spf13/viper v1.4.0 // indirect github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index cdc1e441a..b7cff1abe 100644 --- a/go.sum +++ b/go.sum @@ -463,8 +463,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.26.0 h1:2NPPsBpD0ZoxshmLWewQru8rWmbT5JqSzz9D1ZrAjYQ= -gopkg.in/go-playground/validator.v9 v9.26.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= diff --git a/tendermint/app/app.go b/tendermint/app/app.go deleted file mode 100644 index 5c69150f4..000000000 --- a/tendermint/app/app.go +++ /dev/null @@ -1,284 +0,0 @@ -package app - -import ( - "encoding/json" - - abci "github.com/tendermint/tendermint/abci/types" - cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/log" - dbm "github.com/tendermint/tm-db" - - bam "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - 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/bank" - distr "github.com/cosmos/cosmos-sdk/x/distribution" - "github.com/cosmos/cosmos-sdk/x/genaccounts" - "github.com/cosmos/cosmos-sdk/x/genutil" - "github.com/cosmos/cosmos-sdk/x/params" - "github.com/cosmos/cosmos-sdk/x/slashing" - "github.com/cosmos/cosmos-sdk/x/staking" - "github.com/cosmos/cosmos-sdk/x/supply" - - "github.com/cosmos/sdk-application-tutorial/x/nameservice" -) - -const appName = "nameservice" - -var ( - // ModuleBasics is in charge of setting up basic module elemnets - ModuleBasics = module.NewBasicManager( - genaccounts.AppModuleBasic{}, - genutil.AppModuleBasic{}, - auth.AppModuleBasic{}, - bank.AppModuleBasic{}, - staking.AppModuleBasic{}, - distr.AppModuleBasic{}, - params.AppModuleBasic{}, - slashing.AppModuleBasic{}, - supply.AppModuleBasic{}, - - nameservice.AppModule{}, - ) - // account permissions - maccPerms = map[string][]string{ - auth.FeeCollectorName: nil, - distr.ModuleName: nil, - staking.BondedPoolName: {supply.Burner, supply.Staking}, - staking.NotBondedPoolName: {supply.Burner, supply.Staking}, - } -) - -// MakeCodec generates the necessary codecs for Amino -func MakeCodec() *codec.Codec { - var cdc = codec.New() - ModuleBasics.RegisterCodec(cdc) - sdk.RegisterCodec(cdc) - codec.RegisterCrypto(cdc) - return cdc -} - -type NameServiceApp struct { - *bam.BaseApp - cdc *codec.Codec - - // Keys to access the substores - keyMain *sdk.KVStoreKey - keyAccount *sdk.KVStoreKey - keySupply *sdk.KVStoreKey - keyStaking *sdk.KVStoreKey - tkeyStaking *sdk.TransientStoreKey - keyDistr *sdk.KVStoreKey - keyNS *sdk.KVStoreKey - keyParams *sdk.KVStoreKey - tkeyParams *sdk.TransientStoreKey - keySlashing *sdk.KVStoreKey - - // Keepers - accountKeeper auth.AccountKeeper - bankKeeper bank.Keeper - stakingKeeper staking.Keeper - slashingKeeper slashing.Keeper - distrKeeper distr.Keeper - supplyKeeper supply.Keeper - paramsKeeper params.Keeper - nsKeeper nameservice.Keeper - - // Module Manager - mm *module.Manager -} - -// NewNameServiceApp is a constructor function for NameServiceApp -func NewNameServiceApp(logger log.Logger, db dbm.DB) (*NameServiceApp, *codec.Codec) { - - // First define the top level codec that will be shared by the different modules - cdc := MakeCodec() - - // BaseApp handles interactions with Tendermint through the ABCI protocol - bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc)) - - // Here you initialize your application with the store keys it requires - var app = &NameServiceApp{ - BaseApp: bApp, - cdc: cdc, - - keyMain: sdk.NewKVStoreKey(bam.MainStoreKey), - keyAccount: sdk.NewKVStoreKey(auth.StoreKey), - keySupply: sdk.NewKVStoreKey(supply.StoreKey), - keyStaking: sdk.NewKVStoreKey(staking.StoreKey), - tkeyStaking: sdk.NewTransientStoreKey(staking.TStoreKey), - keyDistr: sdk.NewKVStoreKey(distr.StoreKey), - keyNS: sdk.NewKVStoreKey(nameservice.StoreKey), - keyParams: sdk.NewKVStoreKey(params.StoreKey), - tkeyParams: sdk.NewTransientStoreKey(params.TStoreKey), - keySlashing: sdk.NewKVStoreKey(slashing.StoreKey), - } - - // The ParamsKeeper handles parameter storage for the application - app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams, params.DefaultCodespace) - // Set specific supspaces - authSubspace := app.paramsKeeper.Subspace(auth.DefaultParamspace) - bankSupspace := app.paramsKeeper.Subspace(bank.DefaultParamspace) - stakingSubspace := app.paramsKeeper.Subspace(staking.DefaultParamspace) - distrSubspace := app.paramsKeeper.Subspace(distr.DefaultParamspace) - slashingSubspace := app.paramsKeeper.Subspace(slashing.DefaultParamspace) - - // The AccountKeeper handles address -> account lookups - app.accountKeeper = auth.NewAccountKeeper( - app.cdc, - app.keyAccount, - authSubspace, - auth.ProtoBaseAccount, - ) - - // The BankKeeper allows you perform sdk.Coins interactions - app.bankKeeper = bank.NewBaseKeeper( - app.accountKeeper, - bankSupspace, - bank.DefaultCodespace, - nil, - ) - - // The SupplyKeeper collects transaction fees and renders them to the fee distribution module - app.supplyKeeper = supply.NewKeeper( - app.cdc, - app.keySupply, - app.accountKeeper, - app.bankKeeper, - maccPerms) - - // The staking keeper - stakingKeeper := staking.NewKeeper( - app.cdc, - app.keyStaking, - app.tkeyStaking, - app.supplyKeeper, - stakingSubspace, - staking.DefaultCodespace, - ) - - app.distrKeeper = distr.NewKeeper( - app.cdc, - app.keyDistr, - distrSubspace, - &stakingKeeper, - app.supplyKeeper, - distr.DefaultCodespace, - auth.FeeCollectorName, - nil, - ) - - app.slashingKeeper = slashing.NewKeeper( - app.cdc, - app.keySlashing, - &stakingKeeper, - slashingSubspace, - slashing.DefaultCodespace, - ) - - // register the staking hooks - // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks - app.stakingKeeper = *stakingKeeper.SetHooks( - staking.NewMultiStakingHooks( - app.distrKeeper.Hooks(), - app.slashingKeeper.Hooks()), - ) - - // The NameserviceKeeper is the Keeper from the module for this tutorial - // It handles interactions with the namestore - app.nsKeeper = nameservice.NewKeeper( - app.bankKeeper, - app.keyNS, - app.cdc, - ) - - app.mm = module.NewManager( - genaccounts.NewAppModule(app.accountKeeper), - genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx), - auth.NewAppModule(app.accountKeeper), - bank.NewAppModule(app.bankKeeper, app.accountKeeper), - nameservice.NewAppModule(app.nsKeeper, app.bankKeeper), - supply.NewAppModule(app.supplyKeeper, app.accountKeeper), - distr.NewAppModule(app.distrKeeper, app.supplyKeeper), - slashing.NewAppModule(app.slashingKeeper, app.stakingKeeper), - staking.NewAppModule(app.stakingKeeper, app.distrKeeper, app.accountKeeper, app.supplyKeeper), - ) - - app.mm.SetOrderBeginBlockers(distr.ModuleName, slashing.ModuleName) - app.mm.SetOrderEndBlockers(staking.ModuleName) - - // Sets the order of Genesis - Order matters, genutil is to always come last - app.mm.SetOrderInitGenesis( - genaccounts.ModuleName, - distr.ModuleName, - staking.ModuleName, - auth.ModuleName, - bank.ModuleName, - slashing.ModuleName, - nameservice.ModuleName, - genutil.ModuleName, - ) - - // register all module routes and module queriers - app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) - - // The initChainer handles translating the genesis.json file into initial state for the network - app.SetInitChainer(app.InitChainer) - app.SetBeginBlocker(app.BeginBlocker) - app.SetEndBlocker(app.EndBlocker) - - // The AnteHandler handles signature verification and transaction pre-processing - app.SetAnteHandler( - auth.NewAnteHandler( - app.accountKeeper, - app.supplyKeeper, - auth.DefaultSigVerificationGasConsumer, - ), - ) - - app.MountStores( - app.keyMain, - app.keyAccount, - app.keySupply, - app.keyStaking, - app.tkeyStaking, - app.keyDistr, - app.keySlashing, - app.keyNS, - app.keyParams, - app.tkeyParams, - ) - - err := app.LoadLatestVersion(app.keyMain) - if err != nil { - cmn.Exit(err.Error()) - } - - return app, cdc -} - -// GenesisState represents chain state at the start of the chain. Any initial state (account balances) are stored here. -type GenesisState map[string]json.RawMessage - -func (app *NameServiceApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { - var genesisState GenesisState - - err := app.cdc.UnmarshalJSON(req.AppStateBytes, &genesisState) - if err != nil { - panic(err) - } - - return app.mm.InitGenesis(ctx, genesisState) -} - -func (app *NameServiceApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { - return app.mm.BeginBlock(ctx, req) -} -func (app *NameServiceApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - return app.mm.EndBlock(ctx, req) -} -func (app *NameServiceApp) LoadHeight(height int64) error { - return app.LoadVersion(height, app.keyMain) -}