diff --git a/.circleci/config.yml b/.circleci/config.yml index ff9395c52..bb4e957b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -62,7 +62,7 @@ jobs: name: Get metalinter command: | export PATH="$GOBIN:$PATH" - make get_tools + make get_dev_tools - run: name: Lint source command: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a539f9b..29d753a6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,5 @@ # Changelog -## PENDING - -BREAKING CHANGES - -FEATURES -* [lcd] Can now query governance proposals by ProposalStatus -* [x/mock/simulation] Randomized simulation framework - * Modules specify invariants and operations, preferably in an x/[module]/simulation package - * Modules can test random combinations of their own operations - * Applications can integrate operations and invariants from modules together for an integrated simulation - -IMPROVEMENTS -* [baseapp] Allow any alphanumeric character in route - -BUG FIXES - ## 0.22.0 *July 16th, 2018* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b18ef2ea9..de349501c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Thank you for considering making contributions to Cosmos-SDK and related repositories! Start by taking a look at this [coding repo](https://github.com/tendermint/coding) for overall information on repository workflow and standards. +Thank you for considering making contributions to Cosmos-SDK and related repositories! Start by taking a look at this [coding repo](https://github.com/tendermint/coding) for overall information on repository workflow and standards. Note, we use `make get_dev_tools` and `make update_dev_tools` for installing the linting tools. Please follow standard github best practices: fork the repo, branch from the tip of develop, make some commits, and submit a pull request to develop. See the [open issues](https://github.com/cosmos/cosmos-sdk/issues) for things we need help with! diff --git a/Makefile b/Makefile index b3b5851d6..9cba9cb61 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ BUILD_TAGS = netgo ledger BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/version.GitCommit=${COMMIT_HASH}" GCC := $(shell command -v gcc 2> /dev/null) LEDGER_ENABLED ?= true -all: get_tools get_vendor_deps install install_examples test_lint test +all: get_tools get_vendor_deps install install_examples install_cosmos-sdk-cli test_lint test ######################################## ### CI @@ -38,6 +38,13 @@ endif build-linux: LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build +build_cosmos-sdk-cli: +ifeq ($(OS),Windows_NT) + go build $(BUILD_FLAGS) -o build/cosmos-sdk-cli.exe ./cmd/cosmos-sdk-cli +else + go build $(BUILD_FLAGS) -o build/cosmos-sdk-cli ./cmd/cosmos-sdk-cli +endif + build_examples: ifeq ($(OS),Windows_NT) go build $(BUILD_FLAGS) -o build/basecoind.exe ./examples/basecoin/cmd/basecoind @@ -61,6 +68,9 @@ install_examples: go install $(BUILD_FLAGS) ./examples/democoin/cmd/democoind go install $(BUILD_FLAGS) ./examples/democoin/cmd/democli +install_cosmos-sdk-cli: + go install $(BUILD_FLAGS) ./cmd/cosmos-sdk-cli + install_debug: go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiadebug @@ -74,14 +84,19 @@ dist: check_tools: cd tools && $(MAKE) check_tools +check_dev_tools: + cd tools && $(MAKE) check_dev_tools + update_tools: cd tools && $(MAKE) update_tools -get_tools: - cd tools && $(MAKE) get_tools +update_dev_tools: + cd tools && $(MAKE) update_dev_tools + +get_dev_tools: + cd tools && $(MAKE) get_dev_tools get_vendor_deps: - @rm -rf vendor/ @echo "--> Running dep ensure" @dep ensure -v @@ -204,7 +219,7 @@ remotenet-status: # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: build build_examples install install_examples install_debug dist \ +.PHONY: build build_cosmos-sdk-cli build_examples install install_examples install_cosmos-sdk-cli install_debug dist \ check_tools get_tools get_vendor_deps draw_deps test test_cli test_unit \ test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \ build-linux build-docker-gaiadnode localnet-start localnet-stop remotenet-start \ diff --git a/PENDING.md b/PENDING.md new file mode 100644 index 000000000..f76df34e7 --- /dev/null +++ b/PENDING.md @@ -0,0 +1,23 @@ +## PENDING + +BREAKING CHANGES +* [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` +* [x/stake] Fixed the period check for the inflation calculation + +FEATURES +* [lcd] Can now query governance proposals by ProposalStatus +* [x/mock/simulation] Randomized simulation framework + * Modules specify invariants and operations, preferably in an x/[module]/simulation package + * Modules can test random combinations of their own operations + * Applications can integrate operations and invariants from modules together for an integrated simulation +* Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd + * This allows SDK users to init a new project repository with a single command. + +IMPROVEMENTS +* [baseapp] Allow any alphanumeric character in route +* [cli] Improve error messages for all txs when the account doesn't exist +* [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` +* [x/stake] Add revoked to human-readable validator + +BUG FIXES +* \#1666 Add intra-tx counter to the genesis validators diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 40b3c2bc1..da75591a2 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -436,7 +436,11 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg return } -// Implements ABCI +// CheckTx implements ABCI +// CheckTx runs the "basic checks" to see whether or not a transaction can possibly be executed, +// first decoding, then the ante handler (which checks signatures/fees/ValidateBasic), +// then finally the route match to see whether a handler exists. CheckTx does not run the actual +// Msg handler function(s). func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) { // Decode the Tx. var result sdk.Result @@ -514,16 +518,11 @@ func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.C ctx = ctx.WithSigningValidators(app.signedValidators) } - // Simulate a DeliverTx for gas calculation - if mode == runTxModeSimulate { - ctx = ctx.WithIsCheckTx(false) - } - return } // Iterates through msgs and executes them -func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg) (result sdk.Result) { +func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { // accumulate results logs := make([]string, 0, len(msgs)) var data []byte // NOTE: we just append them all (?!) @@ -537,7 +536,11 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg) (result sdk.Result) return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgType).Result() } - msgResult := handler(ctx, msg) + var msgResult sdk.Result + // Skip actual execution for CheckTx + if mode != runTxModeCheck { + msgResult = handler(ctx, msg) + } // NOTE: GasWanted is determined by ante handler and // GasUsed by the GasMeter @@ -615,9 +618,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // run the ante handler if app.anteHandler != nil { - newCtx, anteResult, abort := app.anteHandler(ctx, tx) + newCtx, result, abort := app.anteHandler(ctx, tx) if abort { - return anteResult + return result } if !newCtx.IsZero() { ctx = newCtx @@ -636,7 +639,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk } ctx = ctx.WithMultiStore(msCache) - result = app.runMsgs(ctx, msgs) + result = app.runMsgs(ctx, msgs, mode) result.GasWanted = gasWanted // only update state if all messages pass and we're not in a simulation diff --git a/client/context/helpers.go b/client/context/helpers.go index 00ff8a81c..7742dfe03 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -186,6 +186,11 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msgs []sdk.Msg, cdc // sign and build the transaction from the msg func (ctx CoreContext) ensureSignBuild(name string, msgs []sdk.Msg, cdc *wire.Codec) (tyBytes []byte, err error) { + err = EnsureAccountExists(ctx, name) + if err != nil { + return nil, err + } + ctx, err = EnsureAccountNumber(ctx) if err != nil { return nil, err diff --git a/client/context/viper.go b/client/context/viper.go index 611ad1b92..6c7646079 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -3,6 +3,7 @@ package context import ( "fmt" + "github.com/pkg/errors" "github.com/spf13/viper" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" @@ -10,6 +11,9 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/keys" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" ) // NewCoreContextFromViper - return a new context with parameters from the command line @@ -68,6 +72,36 @@ func defaultChainID() (string, error) { return doc.ChainID, nil } +// EnsureAccountExists - Make sure account exists +func EnsureAccountExists(ctx CoreContext, name string) error { + keybase, err := keys.GetKeyBase() + if err != nil { + return err + } + + if name == "" { + return errors.Errorf("must provide a from address name") + } + + info, err := keybase.Get(name) + if err != nil { + return errors.Errorf("no key for: %s", name) + } + + accAddr := sdk.AccAddress(info.GetPubKey().Address()) + + Acc, err := ctx.QueryStore(auth.AddressStoreKey(accAddr), ctx.AccountStore) + if err != nil { + return err + } + + // Check if account was found + if Acc == nil { + return errors.Errorf("No account with address %s was found in the state.\nAre you sure there has been a transaction involving it?", accAddr) + } + return nil +} + // EnsureAccount - automatically set account number if none provided func EnsureAccountNumber(ctx CoreContext) (CoreContext, error) { // Should be viper.IsSet, but this does not work - https://github.com/spf13/viper/pull/331 diff --git a/cmd/cosmos-sdk-cli/cmd/init.go b/cmd/cosmos-sdk-cli/cmd/init.go new file mode 100644 index 000000000..5a0f3ddb3 --- /dev/null +++ b/cmd/cosmos-sdk-cli/cmd/init.go @@ -0,0 +1,152 @@ +package cmd + +import ( + "fmt" + "go/build" + "io/ioutil" + "os" + "strings" + + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + tmversion "github.com/tendermint/tendermint/version" + "path/filepath" +) + +var remoteBasecoinPath = "github.com/cosmos/cosmos-sdk/examples/basecoin" + +// Replacer to replace all instances of basecoin/basecli/BasecoinApp to project specific names +// Gets initialized when initCmd is executing after getting the project name from user +var replacer *strings.Replacer + +// Remote path for the project. +var remoteProjectPath string + +func init() { + initCmd.Flags().StringVarP(&remoteProjectPath, "project-path", "p", "", "Remote project path. eg: github.com/your_user_name/project_name") + rootCmd.AddCommand(initCmd) +} + +var initCmd = &cobra.Command{ + Use: "init [ProjectName]", + Short: "Initialize your new cosmos zone", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Print("Thanks for choosing Cosmos-SDK to build your project.\n\n") + projectName := args[0] + capitalizedProjectName := strings.Title(projectName) + shortProjectName := strings.ToLower(projectName) + remoteProjectPath = strings.ToLower(strings.TrimSpace(remoteProjectPath)) + if remoteProjectPath == "" { + remoteProjectPath = strings.ToLower(shortProjectName) + } + replacer = strings.NewReplacer("basecli", shortProjectName+"cli", + "basecoind", shortProjectName+"d", + "BasecoinApp", capitalizedProjectName+"App", + remoteBasecoinPath, remoteProjectPath, + "basecoin", shortProjectName) + setupBasecoinWorkspace(shortProjectName, remoteProjectPath) + return nil + }, +} + +func resolveProjectPath(remoteProjectPath string) string { + gopath := os.Getenv("GOPATH") + if gopath == "" { + gopath = build.Default.GOPATH + // Use $HOME/go + } + return gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator) + remoteProjectPath +} + +func copyBasecoinTemplate(projectName string, projectPath string, remoteProjectPath string) { + basecoinProjectPath := resolveProjectPath(remoteBasecoinPath) + filepath.Walk(basecoinProjectPath, func(path string, f os.FileInfo, err error) error { + if !f.IsDir() { + data, err := ioutil.ReadFile(path) + if err != nil { + return err + } + contents := string(data) + // Extract relative file path eg: app/app.go instead of /Users/..../github.com/cosmos/...examples/basecoin/app/app.go + relativeFilePath := path[len(basecoinProjectPath)+1:] + // Evaluating the filepath in the new project folder + projectFilePath := projectPath + string(os.PathSeparator) + relativeFilePath + projectFilePath = replacer.Replace(projectFilePath) + lengthOfRootDir := strings.LastIndex(projectFilePath, string(os.PathSeparator)) + // Extracting the path of root directory from the filepath + rootDir := projectFilePath[0:lengthOfRootDir] + // Creating the required directory first + os.MkdirAll(rootDir, os.ModePerm) + fmt.Println("Creating " + projectFilePath) + // Writing the contents to a file in the project folder + contents = replacer.Replace(contents) + ioutil.WriteFile(projectFilePath, []byte(contents), os.ModePerm) + } + return nil + }) +} + +func createGopkg(projectPath string) { + // Create gopkg.toml file + dependencies := map[string]string{ + "github.com/cosmos/cosmos-sdk": "=" + version.Version, + "github.com/stretchr/testify": "=1.2.1", + "github.com/spf13/cobra": "=0.0.1", + "github.com/spf13/viper": "=1.0.0", + } + overrides := map[string]string{ + "github.com/golang/protobuf": "1.1.0", + "github.com/tendermint/tendermint": tmversion.Version, + } + contents := "" + for dependency, version := range dependencies { + contents += "[[constraint]]\n\tname = \"" + dependency + "\"\n\tversion = \"" + version + "\"\n\n" + } + for dependency, version := range overrides { + contents += "[[override]]\n\tname = \"" + dependency + "\"\n\tversion = \"=" + version + "\"\n\n" + } + contents += "[prune]\n\tgo-tests = true\n\tunused-packages = true" + ioutil.WriteFile(projectPath+"/Gopkg.toml", []byte(contents), os.ModePerm) +} + +func createMakefile(projectPath string) { + // Create makefile + // TODO: Should we use tools/ directory as in Cosmos-SDK to get tools for linting etc. + makefileContents := `PACKAGES=$(shell go list ./... | grep -v '/vendor/') + +all: get_tools get_vendor_deps build test + +get_tools: + go get github.com/golang/dep/cmd/dep + +build: + go build -o bin/basecli cmd/basecli/main.go && go build -o bin/basecoind cmd/basecoind/main.go + +get_vendor_deps: + @rm -rf vendor/ + @dep ensure + +test: + @go test $(PACKAGES) + +benchmark: + @go test -bench=. $(PACKAGES) + +.PHONY: all build test benchmark` + + // Replacing instances of base* to project specific names + makefileContents = replacer.Replace(makefileContents) + + ioutil.WriteFile(projectPath+"/Makefile", []byte(makefileContents), os.ModePerm) + +} + +func setupBasecoinWorkspace(projectName string, remoteProjectPath string) { + projectPath := resolveProjectPath(remoteProjectPath) + fmt.Println("Configuring your project in " + projectPath) + copyBasecoinTemplate(projectName, projectPath, remoteProjectPath) + createGopkg(projectPath) + createMakefile(projectPath) + fmt.Printf("\nInitialized a new project at %s.\nHappy hacking!\n", projectPath) +} diff --git a/cmd/cosmos-sdk-cli/cmd/root.go b/cmd/cosmos-sdk-cli/cmd/root.go new file mode 100644 index 000000000..2eddd79b5 --- /dev/null +++ b/cmd/cosmos-sdk-cli/cmd/root.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "cosmos-sdk-cli", + Short: "Tools to develop on cosmos-sdk", +} + +// Execute the command +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/cmd/cosmos-sdk-cli/main.go b/cmd/cosmos-sdk-cli/main.go new file mode 100644 index 000000000..ee5ac0215 --- /dev/null +++ b/cmd/cosmos-sdk-cli/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/cosmos/cosmos-sdk/cmd/cosmos-sdk-cli/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/cmd/gaia/testnets/README.md b/cmd/gaia/testnets/README.md index a76d01921..241cf4928 100644 --- a/cmd/gaia/testnets/README.md +++ b/cmd/gaia/testnets/README.md @@ -337,7 +337,7 @@ gaiacli stake delegate \ While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. -> _*NOTE:*_ Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://faucetcosmos.network/)! +> _*NOTE:*_ Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://gaia.faucetcosmos.network/)! ### Unbond Tokens diff --git a/docs/DOCS_README.md b/docs/DOCS_README.md new file mode 100644 index 000000000..564a7e955 --- /dev/null +++ b/docs/DOCS_README.md @@ -0,0 +1,17 @@ +# Documentation Maintenance Overview + +The documentation found in this directory is hosted at: + +- https://cosmos.network/docs/ + +and built using [VuePress](https://vuepress.vuejs.org/) from the Cosmos website repo: + +- https://github.com/cosmos/cosmos.network + +which has a [configuration file](https://github.com/cosmos/cosmos.network/blob/develop/docs/.vuepress/config.js) for displaying +the Table of Contents that lists all the documentation. + +Under the hood, Jenkins listens for changes in ./docs then pushes a `docs-staging` branch to the cosmos.network repo with the latest documentation. That branch must be manually PR'd to `develop` then `master` for staging then production. This process should happen in synchrony with a release. + +The `README.md` in this directory is the landing page for +website documentation. diff --git a/docs/sdk/cosmos-sdk-cli.md b/docs/sdk/cosmos-sdk-cli.md new file mode 100644 index 000000000..615d72252 --- /dev/null +++ b/docs/sdk/cosmos-sdk-cli.md @@ -0,0 +1,34 @@ +# cosmos-sdk-cli +Create a new blockchain project based on cosmos-sdk with a single command. + +--- + +# Installation + +```shell +$ go get github.com/cosmos/cosmos-sdk +$ cd $GOPATH/src/github.com/cosmos/cosmos-sdk +$ make install_cosmos-sdk-cli +``` + +This will install a binary cosmos-sdk-cli + +# Creating a new project + +**$cosmos-sdk-cli init** _Your-Project-Name_ + +This will initialize a project, the dependencies, directory structures with the specified project name. + +### Example: +```shell +$ cosmos-sdk-cli init testzone -p github.com/your_user_name/testzone +``` +`-p [remote-project-path]`. If this is not provided, it creates testzone under $GOPATH/src/ + + +```shell +$ cd $GOPATH/src/github.com/your_user_name/testzone +$ make +``` +This will create two binaries(testzonecli and testzoned) under bin folder. testzoned is the full node of the application which you can run, and testzonecli is your light client. + diff --git a/examples/democoin/x/cool/handler.go b/examples/democoin/x/cool/handler.go index 82247677c..f8c32be81 100644 --- a/examples/democoin/x/cool/handler.go +++ b/examples/democoin/x/cool/handler.go @@ -47,10 +47,6 @@ func handleMsgQuiz(ctx sdk.Context, k Keeper, msg MsgQuiz) sdk.Result { return ErrIncorrectCoolAnswer(k.codespace, msg.CoolAnswer).Result() } - if ctx.IsCheckTx() { - return sdk.Result{} // TODO - } - bonusCoins := sdk.Coins{sdk.NewCoin(msg.CoolAnswer, 69)} _, _, err := k.ck.AddCoins(ctx, msg.Sender, bonusCoins) diff --git a/examples/democoin/x/pow/handler.go b/examples/democoin/x/pow/handler.go index 2dd549bde..e4fa39d1d 100644 --- a/examples/democoin/x/pow/handler.go +++ b/examples/democoin/x/pow/handler.go @@ -26,14 +26,6 @@ func handleMsgMine(ctx sdk.Context, pk Keeper, msg MsgMine) sdk.Result { return err.Result() } - // commented for now, makes testing difficult - // TODO figure out a better test method that allows early CheckTx return - /* - if ctx.IsCheckTx() { - return sdk.Result{} // TODO - } - */ - err = pk.ApplyValid(ctx, msg.Sender, newDiff, newCount) if err != nil { return err.Result() diff --git a/tools/Makefile b/tools/Makefile index 426600e0c..a11f2ec70 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -30,6 +30,9 @@ ifndef DEP_CHECK else @echo "Found dep in path." endif + +check_dev_tools: + $(MAKE) check_tools ifndef GOLINT_CHECK @echo "No golint in path. Install with 'make get_tools'." else @@ -78,6 +81,9 @@ else @echo "Installing dep" go get -v $(DEP) endif + +get_dev_tools: + $(MAKE) get_tools ifdef GOLINT_CHECK @echo "Golint is already installed. Run 'make update_tools' to update." else @@ -130,6 +136,9 @@ endif update_tools: @echo "Updating dep" go get -u -v $(DEP) + +update_dev_tools: + $(MAKE) update_tools @echo "Updating tendermint/golint" go get -u -v $(GOLINT) @echo "Updating gometalinter.v2" @@ -150,4 +159,4 @@ update_tools: # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: check_tools get_tools update_tools +.PHONY: check_tools get_tools update_tools check_dev_tools get_dev_tools update_dev_tools diff --git a/types/context.go b/types/context.go index e55eff1ab..064625028 100644 --- a/types/context.go +++ b/types/context.go @@ -41,7 +41,6 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Lo c = c.WithBlockHeader(header) c = c.WithBlockHeight(header.Height) c = c.WithChainID(header.ChainID) - c = c.WithIsCheckTx(isCheckTx) c = c.WithTxBytes(nil) c = c.WithLogger(logger) c = c.WithSigningValidators(nil) @@ -127,7 +126,6 @@ const ( contextKeyBlockHeader contextKeyBlockHeight contextKeyChainID - contextKeyIsCheckTx contextKeyTxBytes contextKeyLogger contextKeySigningValidators @@ -151,9 +149,6 @@ func (c Context) BlockHeight() int64 { func (c Context) ChainID() string { return c.Value(contextKeyChainID).(string) } -func (c Context) IsCheckTx() bool { - return c.Value(contextKeyIsCheckTx).(bool) -} func (c Context) TxBytes() []byte { return c.Value(contextKeyTxBytes).([]byte) } @@ -179,9 +174,6 @@ func (c Context) WithBlockHeight(height int64) Context { func (c Context) WithChainID(chainID string) Context { return c.withValue(contextKeyChainID, chainID) } -func (c Context) WithIsCheckTx(isCheckTx bool) Context { - return c.withValue(contextKeyIsCheckTx, isCheckTx) -} func (c Context) WithTxBytes(txBytes []byte) Context { return c.withValue(contextKeyTxBytes, txBytes) } diff --git a/x/mock/test_utils.go b/x/mock/test_utils.go index fa7d9875f..c97f1c0c8 100644 --- a/x/mock/test_utils.go +++ b/x/mock/test_utils.go @@ -74,7 +74,8 @@ func SignCheckDeliver( seq []int64, expPass bool, priv ...crypto.PrivKey, ) sdk.Result { tx := GenTx(msgs, accNums, seq, priv...) - res := app.Check(tx) + // Must simulate now as CheckTx doesn't run Msgs anymore + res := app.Simulate(tx) if expPass { require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log) diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 4531c3882..f5f8c98f8 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -113,6 +113,6 @@ func TestSlashingMsgs(t *testing.T) { checkValidatorSigningInfo(t, mapp, keeper, sdk.ValAddress(addr1), false) // unrevoke should fail with unknown validator - res := mock.CheckGenTx(t, mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, false, priv1) + res := mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, false, priv1) require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotRevoked), res.Code) } diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 3991bc222..19a48b448 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -43,10 +43,6 @@ func handleMsgUnrevoke(ctx sdk.Context, msg MsgUnrevoke, k Keeper) sdk.Result { return ErrValidatorJailed(k.codespace).Result() } - if ctx.IsCheckTx() { - return sdk.Result{} - } - // Update the starting height (so the validator can't be immediately revoked again) info.StartHeight = ctx.BlockHeight() k.setValidatorSigningInfo(ctx, addr, info) diff --git a/x/stake/genesis.go b/x/stake/genesis.go index e54517fa5..b4ed80e51 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -17,7 +17,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error keeper.SetNewParams(ctx, data.Params) keeper.InitIntraTxCounter(ctx) - for _, validator := range data.Validators { + for i, validator := range data.Validators { keeper.SetValidator(ctx, validator) if validator.Tokens.IsZero() { @@ -29,6 +29,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error // Manually set indexes for the first time keeper.SetValidatorByPubKeyIndex(ctx, validator) + + validator.BondIntraTxCounter = int16(i) // set the intra-tx counter to the order the validators are presented keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) if validator.Status == sdk.Bonded { diff --git a/x/stake/genesis_test.go b/x/stake/genesis_test.go index 2faff5bc0..e27c7fed2 100644 --- a/x/stake/genesis_test.go +++ b/x/stake/genesis_test.go @@ -14,23 +14,35 @@ func TestInitGenesis(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) pool := keeper.GetPool(ctx) - pool.LooseTokens = sdk.OneRat() + pool.LooseTokens = sdk.NewRat(2) params := keeper.GetParams(ctx) var delegations []Delegation validators := []Validator{ NewValidator(keep.Addrs[0], keep.PKs[0], Description{Moniker: "hoop"}), + NewValidator(keep.Addrs[1], keep.PKs[1], Description{Moniker: "bloop"}), } - genesisState := types.NewGenesisState(pool, params, validators, delegations) err := InitGenesis(ctx, keeper, genesisState) require.Error(t, err) + // initialize the validators validators[0].Tokens = sdk.OneRat() validators[0].DelegatorShares = sdk.OneRat() + validators[1].Tokens = sdk.OneRat() + validators[1].DelegatorShares = sdk.OneRat() genesisState = types.NewGenesisState(pool, params, validators, delegations) err = InitGenesis(ctx, keeper, genesisState) require.NoError(t, err) + + // now make sure the validators are bonded + resVal, found := keeper.GetValidator(ctx, keep.Addrs[0]) + require.True(t, found) + require.Equal(t, sdk.Bonded, resVal.Status) + + resVal, found = keeper.GetValidator(ctx, keep.Addrs[1]) + require.True(t, found) + require.Equal(t, sdk.Bonded, resVal.Status) } diff --git a/x/stake/handler.go b/x/stake/handler.go index b39298ede..14fb4f7bf 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -39,7 +39,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid // Process types.Validator Provisions blockTime := ctx.BlockHeader().Time - if pool.InflationLastTime+blockTime >= 3600 { + if blockTime-pool.InflationLastTime >= 3600 { pool.InflationLastTime = blockTime pool = pool.ProcessProvisions(params) } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index ee1cb5a44..9c70d69da 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -147,6 +147,34 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Val }, nil } +// HumanReadableString returns a human readable string representation of a +// validator. An error is returned if the owner or the owner's public key +// cannot be converted to Bech32 format. +func (v Validator) HumanReadableString() (string, error) { + bechVal, err := sdk.Bech32ifyValPub(v.PubKey) + if err != nil { + return "", err + } + + resp := "Validator \n" + resp += fmt.Sprintf("Owner: %s\n", v.Owner) + resp += fmt.Sprintf("Validator: %s\n", bechVal) + resp += fmt.Sprintf("Revoked: %v\n", v.Revoked) + resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) + resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString()) + resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString()) + resp += fmt.Sprintf("Description: %s\n", v.Description) + resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight) + resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String()) + resp += fmt.Sprintf("Commission: %s\n", v.Commission.String()) + resp += fmt.Sprintf("Max Commission Rate: %s\n", v.CommissionMax.String()) + resp += fmt.Sprintf("Commission Change Rate: %s\n", v.CommissionChangeRate.String()) + resp += fmt.Sprintf("Commission Change Today: %s\n", v.CommissionChangeToday.String()) + resp += fmt.Sprintf("Previous Bonded Tokens: %s\n", v.LastBondedTokens.String()) + + return resp, nil +} + //___________________________________________________________________ // validator struct for bech output @@ -409,30 +437,3 @@ func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Rat { return v.Tokens } func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } - -// HumanReadableString returns a human readable string representation of a -// validator. An error is returned if the owner or the owner's public key -// cannot be converted to Bech32 format. -func (v Validator) HumanReadableString() (string, error) { - bechVal, err := sdk.Bech32ifyValPub(v.PubKey) - if err != nil { - return "", err - } - - resp := "Validator \n" - resp += fmt.Sprintf("Owner: %s\n", v.Owner) - resp += fmt.Sprintf("Validator: %s\n", bechVal) - resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) - resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString()) - resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString()) - resp += fmt.Sprintf("Description: %s\n", v.Description) - resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight) - resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String()) - resp += fmt.Sprintf("Commission: %s\n", v.Commission.String()) - resp += fmt.Sprintf("Max Commission Rate: %s\n", v.CommissionMax.String()) - resp += fmt.Sprintf("Commission Change Rate: %s\n", v.CommissionChangeRate.String()) - resp += fmt.Sprintf("Commission Change Today: %s\n", v.CommissionChangeToday.String()) - resp += fmt.Sprintf("Previous Bonded Tokens: %s\n", v.LastBondedTokens.String()) - - return resp, nil -}