From e85e6e7544e078553f4600cf91a7b9c4046f256a Mon Sep 17 00:00:00 2001 From: Zhong Qiu <36867992+zhongqiuwood@users.noreply.github.com> Date: Tue, 28 Apr 2020 07:44:47 +0800 Subject: [PATCH] V0.37.9 patched by okchain (#13) * okchain patch * Change system fee to gas fee * remove minimum-gas-prices from the server/start.go * fix backend default config * Remove some meaningless comments and some default value of flags * fix the mock test func * set defaultMinGasPrices = "0.00000001okt" * FIX: issue #47, remove param msdLimited in config/default_params.go * add fee * Update query.go change client tips from cosmosxxx to okchainxxx * open CI and fix UT (#12) * Update config.yml * udpate go mod * Update config.yml * fix UT * fix UT * fix UT * fix UT * fix UT * fix UT * fix UT * fix UT * fix slashing UT * Update config.yml * cancel TxMsgs limit, revert to version cosmos * Update config.yml * Update config.yml * Update config.yml * Update README.md Co-authored-by: ylsGit <> Co-authored-by: yezhigang * To fix okchain issue #70 && order tx not requiring fees (#10) * set the Infinite Gas Meter for order tx Co-authored-by: GeYiLi Co-authored-by: liuxiong Co-authored-by: yanwei.han Co-authored-by: qzhongwood <2609611@qq.com> Co-authored-by: MichaelWang Co-authored-by: lei.ji@okcoin.com Co-authored-by: ZhiGang <44460798+KamiD@users.noreply.github.com> Co-authored-by: ylsGit Co-authored-by: yezhigang Co-authored-by: banishee Co-authored-by: GeYiLi --- .circleci/config.yml | 166 +------- README.md | 16 +- baseapp/baseapp.go | 61 ++- baseapp/helpers_okchain.go | 107 +++++ client/alias.go | 1 + client/flags/flags.go | 8 +- client/keys/add.go | 45 +- client/keys/add_ledger_test.go | 2 +- client/keys/mnemonic.go | 2 +- client/keys/show_test.go | 2 +- client/keys/utils.go | 20 +- client/lcd/root.go | 50 ++- config/default_params.go | 29 ++ crypto/keys/hd/hdpath_test.go | 6 +- crypto/keys/keybase.go | 8 +- crypto/keys/keybase_test.go | 34 +- crypto/keys/lazy_keybase.go | 4 +- crypto/keys/lazy_keybase_test.go | 24 +- crypto/keys/mintkey/mintkey_test.go | 2 +- crypto/keys/types.go | 2 +- crypto/keys/types_test.go | 4 +- crypto/ledger_test.go | 72 ++-- go.mod | 5 + go.sum | 21 +- server/config/config.go | 8 +- server/config/config_okchain.go | 66 +++ server/config/config_test.go | 5 +- server/config/toml.go | 10 + server/init.go | 7 +- server/init_test.go | 8 +- server/start.go | 29 +- server/start_okchain.go | 165 ++++++++ server/util.go | 28 +- simapp/app.go | 2 +- simapp/utils.go | 8 +- simapp/utils_test.go | 5 +- store/iavl/store.go | 4 +- store/iavl/store_test.go | 18 +- store/prefix/store_test.go | 2 +- store/rootmulti/proof_test.go | 2 +- store/rootmulti/store.go | 6 +- types/abci.go | 4 + types/address.go | 6 +- types/coin.go | 461 +-------------------- types/coin_okchain.go | 70 ++++ types/coin_test.go | 132 +++--- types/dec_coin.go | 9 +- types/dec_coin_test.go | 24 +- types/decimal.go | 8 +- types/decimal_test.go | 78 ++-- types/denom.go | 25 -- types/denom_test.go | 43 +- types/events.go | 1 + types/int.go | 2 +- types/rest/rest.go | 3 +- types/rest/rest_test.go | 6 +- types/result.go | 14 +- types/staking.go | 5 +- version/version.go | 66 +-- x/auth/ante.go | 49 ++- x/auth/ante_okchain.go | 9 + x/auth/ante_test.go | 34 +- x/auth/cache_okchain.go | 38 ++ x/auth/client/cli/query.go | 4 +- x/auth/client/cli/tx_multisign.go | 2 +- x/auth/client/rest/query.go | 2 +- x/auth/client/rest/rest.go | 9 +- x/auth/genesis_test.go | 52 +++ x/auth/keeper.go | 6 + x/auth/legacy/v0_36/migrate_test.go | 5 +- x/auth/module.go | 7 +- x/auth/simulation/fake.go | 2 +- x/auth/test_common.go | 4 +- x/auth/types/account.go | 22 +- x/auth/types/stdtx.go | 2 +- x/auth/types/stdtx_test.go | 4 +- x/auth/types/txbuilder.go | 4 +- x/auth/types/txbuilder_test.go | 4 +- x/bank/genesis_test.go | 40 ++ x/bank/internal/keeper/keeper.go | 9 +- x/bank/internal/keeper/keeper_test.go | 2 +- x/bank/internal/keeper/querier_test.go | 2 +- x/bank/internal/types/msgs_test.go | 4 +- x/bank/module.go | 2 +- x/bank/simulation.go | 4 +- x/bank/test_common.go | 51 +++ x/crisis/handler.go | 1 + x/crisis/handler_test.go | 4 +- x/crisis/internal/types/genesis.go | 2 +- x/crisis/module.go | 4 +- x/distribution/abci.go | 3 +- x/distribution/client/cli/utils.go | 2 +- x/distribution/client/rest/utils.go | 2 +- x/distribution/handler.go | 4 +- x/distribution/keeper/allocation.go | 2 +- x/distribution/keeper/fee_pool.go | 2 +- x/distribution/keeper/keeper.go | 2 +- x/distribution/types/proposal.go | 8 +- x/genaccounts/genesis_test.go | 40 ++ x/genaccounts/legacy/v0_36/migrate.go | 25 +- x/genaccounts/legacy/v0_36/migrate_test.go | 8 +- x/genaccounts/test_common.go | 54 +++ x/genutil/collect.go | 4 +- x/genutil/legacy/v036/migrate.go | 5 +- x/genutil/legacy/v036/migrate_test.go | 10 +- x/genutil/utils_test.go | 2 +- x/gov/alias_okchain.go | 7 + x/gov/client/cli/query.go | 9 +- x/gov/client/cli/tx.go | 4 +- x/gov/client/rest/rest.go | 4 +- x/gov/deposit.go | 2 +- x/gov/endblocker.go | 2 +- x/gov/expected_keepers.go | 3 +- x/gov/export_okchain.go | 40 ++ x/gov/genesis.go | 4 +- x/gov/proposal.go | 4 +- x/gov/querier.go | 2 +- x/gov/tally.go | 2 +- x/gov/types/codec.go | 10 +- x/gov/types/content.go | 2 +- x/gov/types/deposit.go | 4 +- x/gov/types/expected_keepers.go | 15 + x/gov/types/msgs.go | 14 +- x/gov/types/params.go | 26 +- x/gov/types/params_okchain.go | 25 ++ x/gov/types/proposal.go | 88 ++-- x/gov/types/queier_okchain.go | 5 + x/mint/abci.go | 53 ++- x/mint/alias.go | 46 +- x/mint/app_test.go | 149 +++++++ x/mint/beginBlocker_test.go | 62 +++ x/mint/client/cli/query.go | 4 +- x/mint/genesis.go | 14 +- x/mint/genesis_test.go | 29 ++ x/mint/internal/keeper/keeper.go | 44 +- x/mint/internal/keeper/querier.go | 10 +- x/mint/internal/keeper/querier_test.go | 10 +- x/mint/internal/types/cache_okchain.go | 6 + x/mint/internal/types/expected_keepers.go | 2 +- x/mint/internal/types/minter.go | 50 +-- x/mint/internal/types/minter_okchain.go | 49 +++ x/mint/internal/types/minter_test.go | 195 +++++---- x/mint/internal/types/params.go | 82 ++-- x/mint/module.go | 2 +- x/mint/test_common.go | 97 +++++ x/mock/app.go | 4 +- x/params/client/utils/utils.go | 4 +- x/params/errors_okchain.go | 23 + x/params/export_okchain.go | 9 + x/params/helper_okchain.go | 21 + x/params/keeper.go | 2 + x/params/proposal_handler.go | 4 +- x/params/types/proposal.go | 8 +- x/slashing/abci_test.go | 2 +- x/slashing/client/cli/query.go | 2 +- x/slashing/genesis_test.go | 38 ++ x/slashing/handler.go | 21 +- x/slashing/handler_test.go | 22 +- x/slashing/hooks.go | 15 + x/slashing/keeper.go | 14 +- x/slashing/keeper_okchain.go | 15 + x/slashing/keeper_test.go | 48 +-- x/slashing/module.go | 2 +- x/slashing/querier_test.go | 4 +- x/slashing/signing_info_test.go | 6 +- x/slashing/test_common.go | 5 +- x/slashing/types/expected_keepers.go | 11 +- x/slashing/types/msg_test.go | 2 +- x/slashing/types/params.go | 10 +- x/slashing/types/signing_info.go | 16 +- x/staking/exported/exported.go | 2 +- x/staking/handler.go | 8 +- x/staking/keeper/invariants.go | 2 +- x/staking/keeper/pool.go | 6 +- x/staking/keeper/querier.go | 4 +- x/staking/keeper/val_state_change.go | 4 + x/staking/simulation/msgs.go | 24 +- x/staking/types/expected_keepers.go | 8 +- x/staking/types/msg.go | 14 +- x/staking/types/validator.go | 26 +- x/supply/client/cli/query.go | 2 +- x/supply/genesis_test.go | 39 ++ x/supply/internal/keeper/bank_test.go | 8 +- x/supply/internal/keeper/keeper_test.go | 4 +- x/supply/internal/keeper/querier_test.go | 10 +- x/supply/internal/keeper/test_common.go | 5 +- x/supply/module.go | 2 +- 187 files changed, 2679 insertions(+), 1551 deletions(-) create mode 100644 baseapp/helpers_okchain.go create mode 100644 config/default_params.go create mode 100644 server/config/config_okchain.go create mode 100644 server/start_okchain.go create mode 100644 types/coin_okchain.go create mode 100644 x/auth/ante_okchain.go create mode 100644 x/auth/cache_okchain.go create mode 100644 x/auth/genesis_test.go create mode 100644 x/bank/genesis_test.go create mode 100644 x/bank/test_common.go create mode 100644 x/genaccounts/genesis_test.go create mode 100644 x/genaccounts/test_common.go create mode 100644 x/gov/alias_okchain.go create mode 100644 x/gov/export_okchain.go create mode 100644 x/gov/types/expected_keepers.go create mode 100644 x/gov/types/params_okchain.go create mode 100644 x/gov/types/queier_okchain.go create mode 100644 x/mint/app_test.go create mode 100644 x/mint/beginBlocker_test.go create mode 100644 x/mint/genesis_test.go create mode 100644 x/mint/internal/types/cache_okchain.go create mode 100644 x/mint/internal/types/minter_okchain.go create mode 100644 x/mint/test_common.go create mode 100644 x/params/errors_okchain.go create mode 100644 x/params/export_okchain.go create mode 100644 x/params/helper_okchain.go create mode 100644 x/slashing/genesis_test.go create mode 100644 x/slashing/keeper_okchain.go create mode 100644 x/supply/genesis_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index df222166ab16..b81aa86e10b7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,15 +1,5 @@ version: 2.1 -executors: - golang: - docker: - - image: circleci/golang:1.13 - docs: - docker: - - image: tendermintdev/docker-website-deployment - environment: - AWS_REGION: us-east-1 - commands: make: parameters: @@ -35,8 +25,10 @@ commands: make << parameters.target >> jobs: - setup_dependencies: - executor: golang + build: + docker: + - image: circleci/golang:1.13 + working_directory: /go/src/github.com/{{ORG_NAME}}/{{REPO_NAME}} steps: - checkout - restore_cache: @@ -47,11 +39,13 @@ jobs: name: Cache go modules command: make go-mod-cache - run: - name: Build - command: make build - - run: - name: Git garbage collection - command: git gc + name: Run tests + command: | + export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')" + export GO111MODULE=on + for pkg in $(go list ./... | grep -v staking | grep -v distribution | grep -v gov | grep -v params | circleci tests split); do + go test -mod=readonly -tags='ledger test_ledger_mock' "$pkg" + done - save_cache: name: "Save go modules cache" key: go-mod-v1-{{ checksum "go.sum" }} @@ -61,140 +55,4 @@ jobs: name: "Save source code cache" key: go-src-v1-{{ .Revision }} paths: - - ".git" - - test_sim_nondeterminism: - executor: golang - steps: - - make: - target: test_sim_nondeterminism - description: "Test individual module simulations" - - test_sim_import_export: - executor: golang - steps: - - make: - target: test_sim_import_export - description: "Test application import/export simulation" - - test_sim_after_import: - executor: golang - steps: - - make: - target: test_sim_after_import - description: "Test simulation after import" - - test_sim_multi_seed_long: - executor: golang - steps: - - make: - target: test_sim_multi_seed_long - description: "Test multi-seed simulation (long)" - - test_sim_multi_seed_short: - executor: golang - steps: - - make: - target: test_sim_multi_seed_short - description: "Test multi-seed simulation (short)" - - test_cover: - executor: golang - parallelism: 4 - steps: - - checkout - - restore_cache: - keys: - - go-mod-v1-{{ checksum "go.sum" }} - - run: - name: Run tests - command: | - export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')" - export GO111MODULE=on - mkdir -p /tmp/logs /tmp/workspace/profiles - for pkg in $(go list ./... | grep -v '/simulation' | circleci tests split); do - id=$(echo "$pkg" | sed 's|[/.]|_|g') - go test -mod=readonly -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" - done - - persist_to_workspace: - root: /tmp/workspace - paths: - - "profiles/*" - - store_artifacts: - path: /tmp/logs - - upload_coverage: - executor: golang - steps: - - attach_workspace: - at: /tmp/workspace - - checkout - - run: - name: gather - command: | - echo "--> Concatenating profiles:" - ls /tmp/workspace/profiles/ - echo "mode: atomic" > coverage.txt - for prof in $(ls /tmp/workspace/profiles/); do - tail -n +2 /tmp/workspace/profiles/"$prof" >> coverage.txt - done - - run: - name: filter out DONTCOVER - command: | - excludelist="$(find ./ -type f -name '*.go' | xargs grep -l 'DONTCOVER' | xargs realpath --relative-to=$GOPATH/src)" - for filename in ${excludelist}; do - echo "Excluding ${filename} ..." - sed -i "\%${filename}:%d" coverage.txt - done - - run: - name: upload - command: bash <(curl -s https://codecov.io/bash) -f coverage.txt - - check_statik: - executor: golang - steps: - - make: - target: update-swagger-docs - description: "Check if statik.go is up-to-date" - -workflows: - version: 2 - test-suite: - jobs: - - check_statik: - requires: - - setup_dependencies - - setup_dependencies: - # This filter enables the job for tags - filters: - tags: - only: - - /^v.*/ - - test_sim_nondeterminism: - requires: - - setup_dependencies - - test_sim_import_export: - requires: - - setup_dependencies - - test_sim_after_import: - requires: - - setup_dependencies - - test_sim_multi_seed_short: - requires: - - setup_dependencies - - test_sim_multi_seed_long: - requires: - - setup_dependencies - # These filters ensure that the long sim only runs during release - filters: - branches: - ignore: /.*/ - tags: - only: - - /^v.*/ - - test_cover: - requires: - - setup_dependencies - - upload_coverage: - requires: - - test_cover + - ".git" \ No newline at end of file diff --git a/README.md b/README.md index 9a0a0781a1d8..e26a2514e500 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # Cosmos SDK ![banner](docs/cosmos-sdk-image.jpg) -[![version](https://img.shields.io/github/tag/cosmos/cosmos-sdk.svg)](https://github.com/cosmos/cosmos-sdk/releases/latest) -[![CircleCI](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master.svg?style=shield)](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master) -[![codecov](https://codecov.io/gh/cosmos/cosmos-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/cosmos/cosmos-sdk) -[![Go Report Card](https://goreportcard.com/badge/github.com/cosmos/cosmos-sdk)](https://goreportcard.com/report/github.com/cosmos/cosmos-sdk) -[![license](https://img.shields.io/github/license/cosmos/cosmos-sdk.svg)](https://github.com/cosmos/cosmos-sdk/blob/master/LICENSE) -[![LoC](https://tokei.rs/b1/github/cosmos/cosmos-sdk)](https://github.com/cosmos/cosmos-sdk) -[![API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk?status.svg -)](https://godoc.org/github.com/cosmos/cosmos-sdk) +[![version](https://img.shields.io/github/tag/dex/cosmos-sdk.svg)](https://github.com/dex/cosmos-sdk/releases/latest) +[![CircleCI](https://circleci.com/gh/okex/cosmos-sdk.svg?style=shield)](https://circleci.com/gh/okex/cosmos-sdk) +[![codecov](https://codecov.io/gh/dex/cosmos-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/dex/cosmos-sdk) +[![Go Report Card](https://goreportcard.com/badge/github.com/cosmos/cosmos-sdk)](https://goreportcard.com/report/github.com/dex/cosmos-sdk) +[![license](https://img.shields.io/github/license/dex/cosmos-sdk.svg)](https://github.com/dex/cosmos-sdk/blob/master/LICENSE) +[![LoC](https://tokei.rs/b1/github/dex/cosmos-sdk)](https://github.com/dex/cosmos-sdk) +[![API Reference](https://godoc.org/github.com/dex/cosmos-sdk?status.svg +)](https://godoc.org/github.com/dex/cosmos-sdk) [![riot.im](https://img.shields.io/badge/riot.im-JOIN%20CHAT-green.svg)](https://riot.im/app/#/room/#cosmos-sdk:matrix.org) The Cosmos-SDK is a framework for building blockchain applications in Golang. diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index ad50b100942e..8959bc18b9d3 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -28,15 +28,15 @@ import ( var mainConsensusParamsKey = []byte("consensus_params") // Enum mode for app.runTx -type runTxMode uint8 +type RunTxMode uint8 const ( // Check a transaction - runTxModeCheck runTxMode = iota + runTxModeCheck RunTxMode = iota // Simulate a transaction - runTxModeSimulate runTxMode = iota + runTxModeSimulate RunTxMode = iota // Deliver a transaction - runTxModeDeliver runTxMode = iota + runTxModeDeliver RunTxMode = iota // MainStoreKey is the string representation of the main store MainStoreKey = "main" @@ -69,8 +69,8 @@ type BaseApp struct { // checkState is set on initialization and reset on Commit. // deliverState is set in InitChain and BeginBlock and cleared on Commit. // See methods setCheckState and setDeliverState. - checkState *state // for CheckTx - deliverState *state // for DeliverTx + checkState *State // for CheckTx + deliverState *State // for DeliverTx voteInfos []abci.VoteInfo // absent validators from begin block // consensus params @@ -92,6 +92,10 @@ type BaseApp struct { // application's version string appVersion string + + ProtocolVersion int32 + + PostEndBlocker sdk.PostEndBlockHandler } var _ abci.Application = (*BaseApp)(nil) @@ -300,7 +304,7 @@ func (app *BaseApp) IsSealed() bool { return app.sealed } // It is called by InitChain() and Commit() func (app *BaseApp) setCheckState(header abci.Header) { ms := app.cms.CacheMultiStore() - app.checkState = &state{ + app.checkState = &State{ ms: ms, ctx: sdk.NewContext(ms, header, true, app.logger).WithMinGasPrices(app.minGasPrices), } @@ -312,7 +316,7 @@ func (app *BaseApp) setCheckState(header abci.Header) { // and deliverState is set nil on Commit(). func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() - app.deliverState = &state{ + app.deliverState = &State{ ms: ms, ctx: sdk.NewContext(ms, header, false, app.logger), } @@ -362,6 +366,7 @@ func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { lastCommitID := app.cms.LastCommitID() return abci.ResponseInfo{ + AppVersion: uint64(app.ProtocolVersion), Data: app.name, LastBlockHeight: lastCommitID.Version, LastBlockAppHash: lastCommitID.Hash, @@ -729,6 +734,9 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliv // validateBasicTxMsgs executes basic validator calls for messages. func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { + //if msgs == nil || len(msgs) != 1 { + // return sdk.ErrUnknownRequest("Tx.GetMsgs() must return only one message") + //} if msgs == nil || len(msgs) == 0 { return sdk.ErrUnknownRequest("Tx.GetMsgs() must return at least one message in list") } @@ -745,7 +753,7 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { } // retrieve the context for the tx w/ txBytes and other memoized values. -func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Context) { +func (app *BaseApp) getContextForTx(mode RunTxMode, txBytes []byte) (ctx sdk.Context) { ctx = app.getState(mode).ctx. WithTxBytes(txBytes). WithVoteInfos(app.voteInfos). @@ -759,7 +767,7 @@ func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Con } /// runMsgs iterates through all the messages and executes them. -func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { +func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode RunTxMode) (result sdk.Result) { msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs)) data := make([]byte, 0, len(msgs)) @@ -799,6 +807,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re events = events.AppendEvents(msgEvents) + // TODO temporary modification: hide the log.event + msgEvents = sdk.EmptyEvents() // stop execution and return on first failed message if !msgResult.IsOK() { msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), false, msgResult.Log, msgEvents)) @@ -825,7 +835,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re // Returns the applications's deliverState if app is in runTxModeDeliver, // otherwise it returns the application's checkstate. -func (app *BaseApp) getState(mode runTxMode) *state { +func (app *BaseApp) getState(mode RunTxMode) *State { if mode == runTxModeCheck || mode == runTxModeSimulate { return app.checkState } @@ -858,7 +868,7 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) ( // anteHandler. The provided txBytes may be nil in some cases, eg. in tests. For // further details on transaction execution, reference the BaseApp SDK // documentation. -func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk.Result) { +func (app *BaseApp) runTx(mode RunTxMode, txBytes []byte, tx sdk.Tx) (result sdk.Result) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas // meter so we initialize upfront. @@ -919,6 +929,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk return err.Result() } + var anteResult sdk.Result if app.anteHandler != nil { var anteCtx sdk.Context var msCache sdk.CacheMultiStore @@ -945,7 +956,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk } gasWanted = result.GasWanted - + anteResult = result if abort { return result } @@ -964,7 +975,19 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk return result } - // only update state if all messages pass + // Set fee tags, no for genesis block + eventI, attrI, sysFee := getFeeFromTags(ctx, anteResult) + i, j, busFee := getFeeFromTags(ctx, result) + if i >= 0 && j >= 0 { //modify fee event + result.Events[i].Attributes[j].Value = []byte(sysFee.Add(busFee).String()) + } else { + // Add new event for fee + result.Events = result.Events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyFee, sysFee.String()))) + } + + result.Events = result.Events.AppendEvents(removeFeeTags(anteResult, eventI, attrI).Events) + + // update state only if all messages are OK if result.IsOK() { msCache.Write() } @@ -982,6 +1005,10 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc res = app.endBlocker(app.deliverState.ctx, req) } + if app.PostEndBlocker != nil { + app.PostEndBlocker(&res) + } + return } @@ -1059,15 +1086,15 @@ func (app *BaseApp) halt() { // ---------------------------------------------------------------------------- // State -type state struct { +type State struct { ms sdk.CacheMultiStore ctx sdk.Context } -func (st *state) CacheMultiStore() sdk.CacheMultiStore { +func (st *State) CacheMultiStore() sdk.CacheMultiStore { return st.ms.CacheMultiStore() } -func (st *state) Context() sdk.Context { +func (st *State) Context() sdk.Context { return st.ctx } diff --git a/baseapp/helpers_okchain.go b/baseapp/helpers_okchain.go new file mode 100644 index 000000000000..ac99514de0a9 --- /dev/null +++ b/baseapp/helpers_okchain.go @@ -0,0 +1,107 @@ +package baseapp + +import ( + "bytes" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func RunTxModeDeliver() RunTxMode { + return runTxModeDeliver +} + +var ( + feeKeyBytes = []byte(sdk.AttributeKeyFee) +) + +// getFeeFromTags get actual system_fee from Result +func getFeeFromTags(ctx sdk.Context, res sdk.Result) (eventI, attrI int, fee sdk.DecCoins) { + if ctx.BlockHeight() < 1 { + return -1, -1, sdk.DecCoins{} + } + for i, event := range res.Events { + if event.Type == sdk.EventTypeMessage { + for j, attr := range event.Attributes { + if bytes.EqualFold(attr.GetKey(), feeKeyBytes) { + if string(attr.Value) == "0"+sdk.DefaultBondDenom || string(attr.Value) == "0.00000000"+sdk.DefaultBondDenom { + return i, j, sdk.DecCoins{} + } + fee, err := sdk.ParseDecCoins(string(attr.Value)) + if err != nil { + panic(fmt.Sprintf("fee attribute's value is not valid, err=%s", err.Error())) + } + return i, j, fee + } + } + } + } + + //if fee is not set, e.g. MsgOrder/MsgCreateValidator... + return -1, -1, sdk.DecCoins{} +} + +func removeFeeTags(res sdk.Result, eventI, attrI int) sdk.Result { + if eventI < 0 || attrI < 0 { + return res + } + + attrs := res.Events[eventI].Attributes + if attrI < len(attrs)-1 { + res.Events[eventI].Attributes = append(res.Events[eventI].Attributes, attrs[attrI+1:]...) + } else { + res.Events[eventI].Attributes = attrs[:attrI] + } + + return res +} + +//------------------------------------------------------- +// BaseApp +//------------------------------------------------------- + +// Returns the applications's deliverState if app is in RunTxModeDeliver, +// otherwise it returns the application's checkstate. +func (app *BaseApp) GetState(mode RunTxMode) *State { + if mode == runTxModeCheck || mode == runTxModeSimulate { + return app.checkState + } + + return app.deliverState +} + +func (app *BaseApp) GetCommitMultiStore() sdk.CommitMultiStore { + return app.cms +} + +func (app *BaseApp) GetDeliverStateCtx() sdk.Context { + return app.deliverState.ctx +} + +//------------------------------------------------------- +// for protocol engine to invoke +//------------------------------------------------------- +func (app *BaseApp) PushInitChainer(initChainer sdk.InitChainer) { + app.initChainer = initChainer +} + +func (app *BaseApp) PushBeginBlocker(beginBlocker sdk.BeginBlocker) { + app.beginBlocker = beginBlocker +} + +func (app *BaseApp) PushEndBlocker(endBlocker sdk.EndBlocker) { + app.endBlocker = endBlocker +} + +func (app *BaseApp) PushAnteHandler(ah sdk.AnteHandler) { + app.anteHandler = ah +} + +func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { + app.txDecoder = txDecoder +} + +func (app *BaseApp) SetRouter(router sdk.Router, queryRouter sdk.QueryRouter) { + app.router = router + app.queryRouter = queryRouter +} diff --git a/client/alias.go b/client/alias.go index 15f6f872905d..6a0ab06f9aab 100644 --- a/client/alias.go +++ b/client/alias.go @@ -52,6 +52,7 @@ const ( FlagRPCWriteTimeout = flags.FlagRPCWriteTimeout FlagOutputDocument = flags.FlagOutputDocument FlagSkipConfirmation = flags.FlagSkipConfirmation + FlagKeyPass = keys.FlagKeyPass DefaultKeyPass = keys.DefaultKeyPass FlagAddress = keys.FlagAddress FlagPublicKey = keys.FlagPublicKey diff --git a/client/flags/flags.go b/client/flags/flags.go index 62f2a8d012f9..74aba68a6790 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -5,6 +5,8 @@ import ( "os" "strconv" + "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" "github.com/spf13/viper" @@ -87,10 +89,10 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response") c.Flags().String(FlagFrom, "", "Name or address of private key with which to sign") c.Flags().Uint64P(FlagAccountNumber, "a", 0, "The account number of the signing account (offline mode only)") - c.Flags().Uint64P(FlagSequence, "s", 0, "The sequence number of the signing account (offline mode only)") + c.Flags().Uint64(FlagSequence, 0, "The sequence number of the signing account (offline mode only)") c.Flags().String(FlagMemo, "", "Memo to send along with transaction") - c.Flags().String(FlagFees, "", "Fees to pay along with transaction; eg: 10uatom") - c.Flags().String(FlagGasPrices, "", "Gas prices to determine the transaction fee (e.g. 10uatom)") + c.Flags().String(FlagFees, "", "Fees to pay along with transaction; eg: 1"+types.DefaultBondDenom) + c.Flags().String(FlagGasPrices, "", "Gas prices to determine the transaction fee (e.g. 1"+types.DefaultBondDenom+")") c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ") diff --git a/client/keys/add.go b/client/keys/add.go index f702c6b90d4f..71d97280e036 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -31,8 +31,10 @@ const ( flagIndex = "index" flagMultisig = "multisig" flagNoSort = "nosort" + flagMnemonic = "mnemonic" // DefaultKeyPass contains the default key password for genesis transactions + FlagKeyPass = "passwd" DefaultKeyPass = "12345678" ) @@ -72,6 +74,8 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") + cmd.Flags().BoolP(flagYes, "y", false, "Overwrite the existing account without confirmation") + cmd.Flags().StringP(flagMnemonic, "m", "", "Mnemonic words") return cmd } @@ -106,15 +110,18 @@ func runAddCmd(cmd *cobra.Command, args []string) error { return err } - _, err = kb.Get(name) - if err == nil { - // account exists, ask for user confirmation - response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf) - if err2 != nil { - return err2 - } - if !response { - return errors.New("aborted") + ask := !viper.GetBool(flagYes) + if ask { + _, err = kb.Get(name) + if err == nil { + // account exists, ask for user confirmation + response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf) + if err2 != nil { + return err2 + } + if !response { + return errors.New("aborted") + } } } @@ -153,12 +160,13 @@ func runAddCmd(cmd *cobra.Command, args []string) error { // ask for a password when generating a local key if viper.GetString(FlagPublicKey) == "" && !viper.GetBool(flags.FlagUseLedger) { - encryptPassword, err = input.GetCheckPassword( - "Enter a passphrase to encrypt your key to disk:", - "Repeat the passphrase:", inBuf) - if err != nil { - return err - } + //encryptPassword, err = input.GetCheckPassword( + // "Enter a passphrase to encrypt your key to disk:", + // "Repeat the passphrase:", inBuf) + //if err != nil { + // return err + //} + encryptPassword = viper.GetString(FlagKeyPass) } } @@ -192,7 +200,12 @@ func runAddCmd(cmd *cobra.Command, args []string) error { var mnemonic string var bip39Passphrase string - if interactive || viper.GetBool(flagRecover) { + inputMnemonic := viper.GetString(flagMnemonic) + if len(inputMnemonic) > 0 { + mnemonic = inputMnemonic + } + + if len(mnemonic) == 0 && (interactive || viper.GetBool(flagRecover)) { bip39Message := "Enter your bip39 mnemonic" if !viper.GetBool(flagRecover) { bip39Message = "Enter your bip39 mnemonic, or hit enter to generate one." diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index 8602820918ee..6e581d56fc85 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -99,6 +99,6 @@ func Test_runAddCmdLedger(t *testing.T) { assert.Equal(t, "keyname1", key1.GetName()) assert.Equal(t, keys.TypeLedger, key1.GetType()) assert.Equal(t, - "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", + "okchainpub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgwxtwrat", sdk.MustBech32ifyAccPub(key1.GetPubKey())) } diff --git a/client/keys/mnemonic.go b/client/keys/mnemonic.go index fcc73a98052f..af61e95cadd4 100644 --- a/client/keys/mnemonic.go +++ b/client/keys/mnemonic.go @@ -14,7 +14,7 @@ import ( const ( flagUserEntropy = "unsafe-entropy" - mnemonicEntropySize = 256 + mnemonicEntropySize = 128 ) func mnemonicKeyCommand() *cobra.Command { diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 53add173bd4d..ea0e4e322edc 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -24,7 +24,7 @@ func Test_multiSigKey_Properties(t *testing.T) { assert.Equal(t, "myMultisig", tmp.GetName()) assert.Equal(t, keys.TypeMulti, tmp.GetType()) assert.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", tmp.GetPubKey().Address().String()) - assert.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", tmp.GetAddress().String()) + assert.Equal(t, "okchain16wfryel63g7axeamw68630wglalcnk3ldcxdmm", tmp.GetAddress().String()) } func Test_showKeysCmd(t *testing.T) { diff --git a/client/keys/utils.go b/client/keys/utils.go index 2c4fcc879ff5..f51672aff979 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -1,9 +1,7 @@ package keys import ( - "bufio" "fmt" - "os" "path/filepath" "github.com/spf13/viper" @@ -11,7 +9,6 @@ import ( "gopkg.in/yaml.v2" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto/keys" ) @@ -64,14 +61,15 @@ func GetPassphrase(name string) (string, error) { // ReadPassphraseFromStdin attempts to read a passphrase from STDIN return an // error upon failure. func ReadPassphraseFromStdin(name string) (string, error) { - buf := bufio.NewReader(os.Stdin) - prompt := fmt.Sprintf("Password to sign with '%s':", name) - - passphrase, err := input.GetPassword(prompt, buf) - if err != nil { - return passphrase, fmt.Errorf("Error reading passphrase: %v", err) - } - + //buf := bufio.NewReader(os.Stdin) + //prompt := fmt.Sprintf("Password to sign with '%s':", name) + // + //passphrase, err := input.GetPassword(prompt, buf) + //if err != nil { + // return passphrase, fmt.Errorf("Error reading passphrase: %v", err) + //} + + passphrase := viper.GetString(FlagKeyPass) return passphrase, nil } diff --git a/client/lcd/root.go b/client/lcd/root.go index 71b70ae083d0..ddf57a1662f4 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -9,19 +9,20 @@ import ( "github.com/gorilla/mux" "github.com/rakyll/statik/fs" - "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/log" - rpcserver "github.com/tendermint/tendermint/rpc/lib/server" + "github.com/tendermint/tendermint/rpc/lib/server" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" keybase "github.com/cosmos/cosmos-sdk/crypto/keys" - "github.com/cosmos/cosmos-sdk/server" // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/lcd/statik" + "github.com/spf13/cobra" + "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/rpc/client" ) // RestServer represents the Light Client Rest server @@ -29,30 +30,38 @@ type RestServer struct { Mux *mux.Router CliCtx context.CLIContext KeyBase keybase.Keybase + Cdc *codec.Codec log log.Logger listener net.Listener } // NewRestServer creates a new rest server instance -func NewRestServer(cdc *codec.Codec) *RestServer { - r := mux.NewRouter() +func NewRestServer(cdc *codec.Codec, tmNode *node.Node) *RestServer { + rootRouter := mux.NewRouter() cliCtx := context.NewCLIContext().WithCodec(cdc) logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server") + if tmNode != nil { + cliCtx.Client = client.NewLocal(tmNode) + } + + cliCtx.TrustNode = true return &RestServer{ - Mux: r, + Mux: rootRouter, CliCtx: cliCtx, - log: logger, + Cdc: cdc, + + log: logger, } } // Start starts the rest server func (rs *RestServer) Start(listenAddr string, maxOpen int, readTimeout, writeTimeout uint) (err error) { - server.TrapSignal(func() { - err := rs.listener.Close() - rs.log.Error("error closing listener", "err", err) - }) + //trapSignal(func() { + // err := rs.listener.Close() + // rs.log.Error("error closing listener", "err", err) + //}) cfg := rpcserver.DefaultConfig() cfg.MaxOpenConnections = maxOpen @@ -81,7 +90,7 @@ func ServeCommand(cdc *codec.Codec, registerRoutesFn func(*RestServer)) *cobra.C Use: "rest-server", Short: "Start LCD (light-client daemon), a local REST server", RunE: func(cmd *cobra.Command, args []string) (err error) { - rs := NewRestServer(cdc) + rs := NewRestServer(cdc, nil) registerRoutesFn(rs) rs.registerSwaggerUI() @@ -101,6 +110,23 @@ func ServeCommand(cdc *codec.Codec, registerRoutesFn func(*RestServer)) *cobra.C return flags.RegisterRestServerFlags(cmd) } +func StartRestServer(cdc *codec.Codec, registerRoutesFn func(*RestServer), tmNode *node.Node, addr string) error { + rs := NewRestServer(cdc, tmNode) + + registerRoutesFn(rs) + rs.registerSwaggerUI() + rs.log.Info("start rest server") + // Start the rest server and return error if one exists + err := rs.Start( + addr, + viper.GetInt(flags.FlagMaxOpenConnections), + uint(viper.GetInt(flags.FlagRPCReadTimeout)), + uint(viper.GetInt(flags.FlagRPCWriteTimeout)), + ) + + return err +} + func (rs *RestServer) registerSwaggerUI() { statikFS, err := fs.New() if err != nil { diff --git a/config/default_params.go b/config/default_params.go new file mode 100644 index 000000000000..a2fd5f60fb65 --- /dev/null +++ b/config/default_params.go @@ -0,0 +1,29 @@ +package config + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // Update the validator set every 252 blocks by default + DefaultBlocksPerEpoch = 252 + + // Default unbonding duration, 14 days + DefaultUnbondingTime time.Duration = time.Hour * 24 * 7 * 2 + + // Default maximum number of bonded validators + DefaultMaxValidators uint16 = 21 + + // Default maximum number of validators to vote + DefaultMaxValsToVote = 30 + + // Default validate rate update interval by hours + DefaultValidateRateUpdateInterval = 24 +) + +var ( + // Default minimum number of Delegate&Unbond limit by okt + DefaultMinDelegation = sdk.NewDecWithPrec(1, 4) +) diff --git a/crypto/keys/hd/hdpath_test.go b/crypto/keys/hd/hdpath_test.go index e375094cb1ee..c45325abf749 100644 --- a/crypto/keys/hd/hdpath_test.go +++ b/crypto/keys/hd/hdpath_test.go @@ -32,10 +32,10 @@ func ExampleStringifyPathParams() { func TestStringifyFundraiserPathParams(t *testing.T) { path := NewFundraiserParams(4, types.CoinType, 22) - require.Equal(t, "44'/118'/4'/0/22", path.String()) + require.Equal(t, "44'/996'/4'/0/22", path.String()) path = NewFundraiserParams(4, types.CoinType, 57) - require.Equal(t, "44'/118'/4'/0/57", path.String()) + require.Equal(t, "44'/996'/4'/0/57", path.String()) path = NewFundraiserParams(4, 12345, 57) require.Equal(t, "44'/12345'/4'/0/57", path.String()) @@ -173,7 +173,7 @@ func ExampleSomeBIP32TestVecs() { // Output: keys from fundraiser test-vector (cosmos, bitcoin, ether) // - // bfcb217c058d8bbafd5e186eae936106ca3e943889b0b4a093ae13822fd3170c + // c2c0034632383a9c3e4ed8254ba86ad42b71117a876e1dcfc2be83f835fbcf76 // e77c3de76965ad89997451de97b95bb65ede23a6bf185a55d80363d92ee37c3d // 7fc4d8a8146dea344ba04c593517d3f377fa6cded36cd55aee0a0bb968e651bc // INVALID diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index 068a0c4b06a1..8f65fb3615c2 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -58,7 +58,7 @@ const ( DefaultBIP39Passphrase = "" // bits of entropy to draw when creating a mnemonic - defaultEntropySize = 256 + defaultEntropySize = 128 //mnemonicEntropySize ) var ( @@ -94,7 +94,7 @@ func NewInMemory() Keybase { return dbKeybase{dbm.NewMemDB()} } // It returns an error if it fails to // generate a key for the given algo type, or if another key is // already stored under the same name. -func (kb dbKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, mnemonic string, err error) { +func (kb dbKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo, mnemonicInput string) (info Info, mnemonic string, err error) { if language != English { return nil, "", ErrUnsupportedLanguage } @@ -114,6 +114,10 @@ func (kb dbKeybase) CreateMnemonic(name string, language Language, passwd string return } + if len(mnemonicInput) > 0{ + mnemonic = mnemonicInput + } + seed := bip39.NewSeed(mnemonic, DefaultBIP39Passphrase) fullFundraiserPath := types.GetConfig().GetFullFundraiserPath() info, err = kb.persistDerivedKey(seed, passwd, name, fullFundraiserPath) diff --git a/crypto/keys/keybase_test.go b/crypto/keys/keybase_test.go index 7670d8afd303..7893942e90b2 100644 --- a/crypto/keys/keybase_test.go +++ b/crypto/keys/keybase_test.go @@ -21,7 +21,7 @@ func init() { func TestLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1) + _, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1, "") assert.Error(t, err) assert.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -64,7 +64,7 @@ func TestCreateLedger(t *testing.T) { pubKey := ledger.GetPubKey() pk, err := sdk.Bech32ifyAccPub(pubKey) assert.NoError(t, err) - assert.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + assert.Equal(t, "okchainpub1addwnpepqg94y3n0sdcg5w0vhjqgp6e2ux20hxpm2sdy59nnlcny76uc729fyquy75e", pk) // Check that restoring the key gets the same results restoredKey, err := kb.Get("some_account") @@ -73,11 +73,11 @@ func TestCreateLedger(t *testing.T) { assert.Equal(t, TypeLedger, restoredKey.GetType()) pubKey = restoredKey.GetPubKey() pk, err = sdk.Bech32ifyAccPub(pubKey) - assert.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + assert.Equal(t, "okchainpub1addwnpepqg94y3n0sdcg5w0vhjqgp6e2ux20hxpm2sdy59nnlcny76uc729fyquy75e", pk) path, err := restoredKey.GetPath() assert.NoError(t, err) - assert.Equal(t, "44'/118'/3'/0/1", path.String()) + assert.Equal(t, "44'/996'/3'/0/1", path.String()) } // TestKeyManagement makes sure we can manipulate these keys well @@ -94,17 +94,17 @@ func TestKeyManagement(t *testing.T) { require.Nil(t, err) assert.Empty(t, l) - _, _, err = cstore.CreateMnemonic(n1, English, p1, Ed25519) + _, _, err = cstore.CreateMnemonic(n1, English, p1, Ed25519, "") require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = cstore.Get(n1) require.Error(t, err) - i, _, err := cstore.CreateMnemonic(n1, English, p1, algo) + i, _, err := cstore.CreateMnemonic(n1, English, p1, algo, "") require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = cstore.CreateMnemonic(n2, English, p2, algo) + _, _, err = cstore.CreateMnemonic(n2, English, p2, algo, "") require.NoError(t, err) // we can get these keys @@ -114,7 +114,7 @@ func TestKeyManagement(t *testing.T) { require.NotNil(t, err) _, err = cstore.GetByAddress(accAddr(i2)) require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + addr, err := sdk.AccAddressFromBech32("okchain1yq8lgssgxlx9smjhes6ryjasmqmd3ts2kwlceg") require.NoError(t, err) _, err = cstore.GetByAddress(addr) require.NotNil(t, err) @@ -173,10 +173,10 @@ func TestSignVerify(t *testing.T) { p1, p2, p3 := "1234", "foobar", "foobar" // create two users and get their info - i1, _, err := cstore.CreateMnemonic(n1, English, p1, algo) + i1, _, err := cstore.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err) - i2, _, err := cstore.CreateMnemonic(n2, English, p2, algo) + i2, _, err := cstore.CreateMnemonic(n2, English, p2, algo, "") require.Nil(t, err) // Import a public key @@ -251,7 +251,7 @@ func TestExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.CreateMnemonic("john", English, "secretcpw", Secp256k1) + info, _, err := cstore.CreateMnemonic("john", English, "secretcpw", Secp256k1, "") require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -281,7 +281,7 @@ func TestExportImportPubKey(t *testing.T) { // CreateMnemonic a private-public key pair and ensure consistency notPasswd := "n9y25ah7" - info, _, err := cstore.CreateMnemonic("john", English, notPasswd, Secp256k1) + info, _, err := cstore.CreateMnemonic("john", English, notPasswd, Secp256k1, "") require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -323,7 +323,7 @@ func TestAdvancedKeyManagement(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - _, _, err := cstore.CreateMnemonic(n1, English, p1, algo) + _, _, err := cstore.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err, "%+v", err) assertPassword(t, cstore, n1, p1, p2) @@ -371,7 +371,7 @@ func TestSeedPhrase(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - info, mnemonic, err := cstore.CreateMnemonic(n1, English, p1, algo) + info, mnemonic, err := cstore.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) assert.NotEmpty(t, mnemonic) @@ -398,7 +398,7 @@ func ExampleNew() { sec := Secp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.CreateMnemonic("Bob", English, "friend", sec) + bob, _, err := cstore.CreateMnemonic("Bob", English, "friend", sec, "") if err != nil { // this should never happen fmt.Println(err) @@ -406,8 +406,8 @@ func ExampleNew() { // return info here just like in List fmt.Println(bob.GetName()) } - _, _, _ = cstore.CreateMnemonic("Alice", English, "secret", sec) - _, _, _ = cstore.CreateMnemonic("Carl", English, "mitm", sec) + _, _, _ = cstore.CreateMnemonic("Alice", English, "secret", sec, "") + _, _, _ = cstore.CreateMnemonic("Carl", English, "mitm", sec, "") info, _ := cstore.List() for _, i := range info { fmt.Println(i.GetName()) diff --git a/crypto/keys/lazy_keybase.go b/crypto/keys/lazy_keybase.go index d1e855fe6efd..3514ba2ac3ec 100644 --- a/crypto/keys/lazy_keybase.go +++ b/crypto/keys/lazy_keybase.go @@ -76,14 +76,14 @@ func (lkb lazyKeybase) Sign(name, passphrase string, msg []byte) ([]byte, crypto return newDbKeybase(db).Sign(name, passphrase, msg) } -func (lkb lazyKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error) { +func (lkb lazyKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo, mnemonicInput string) (info Info, seed string, err error) { db, err := sdk.NewLevelDB(lkb.name, lkb.dir) if err != nil { return nil, "", err } defer db.Close() - return newDbKeybase(db).CreateMnemonic(name, language, passwd, algo) + return newDbKeybase(db).CreateMnemonic(name, language, passwd, algo, mnemonicInput) } func (lkb lazyKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error) { diff --git a/crypto/keys/lazy_keybase_test.go b/crypto/keys/lazy_keybase_test.go index b97ffc40d466..df2a3f92e4fd 100644 --- a/crypto/keys/lazy_keybase_test.go +++ b/crypto/keys/lazy_keybase_test.go @@ -37,17 +37,17 @@ func TestLazyKeyManagement(t *testing.T) { require.Nil(t, err) assert.Empty(t, l) - _, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519) + _, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519, "") require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = kb.Get(n1) require.Error(t, err) - i, _, err := kb.CreateMnemonic(n1, English, p1, algo) + i, _, err := kb.CreateMnemonic(n1, English, p1, algo, "") require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = kb.CreateMnemonic(n2, English, p2, algo) + _, _, err = kb.CreateMnemonic(n2, English, p2, algo, "") require.NoError(t, err) // we can get these keys @@ -57,7 +57,7 @@ func TestLazyKeyManagement(t *testing.T) { require.NotNil(t, err) _, err = kb.GetByAddress(accAddr(i2)) require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + addr, err := sdk.AccAddressFromBech32("okchain1yq8lgssgxlx9smjhes6ryjasmqmd3ts2kwlceg") require.NoError(t, err) _, err = kb.GetByAddress(addr) require.NotNil(t, err) @@ -116,10 +116,10 @@ func TestLazySignVerify(t *testing.T) { p1, p2, p3 := "1234", "foobar", "foobar" // create two users and get their info - i1, _, err := kb.CreateMnemonic(n1, English, p1, algo) + i1, _, err := kb.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err) - i2, _, err := kb.CreateMnemonic(n2, English, p2, algo) + i2, _, err := kb.CreateMnemonic(n2, English, p2, algo, "") require.Nil(t, err) // Import a public key @@ -186,7 +186,7 @@ func TestLazyExportImport(t *testing.T) { defer cleanup() kb := New("keybasename", dir) - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) + info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "") require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -214,7 +214,7 @@ func TestLazyExportImportPrivKey(t *testing.T) { defer cleanup() kb := New("keybasename", dir) - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) + info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "") require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Get("john") @@ -245,7 +245,7 @@ func TestLazyExportImportPubKey(t *testing.T) { // CreateMnemonic a private-public key pair and ensure consistency notPasswd := "n9y25ah7" - info, _, err := kb.CreateMnemonic("john", English, notPasswd, Secp256k1) + info, _, err := kb.CreateMnemonic("john", English, notPasswd, Secp256k1, "") require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -282,7 +282,7 @@ func TestLazyExportPrivateKeyObject(t *testing.T) { defer cleanup() kb := New("keybasename", dir) - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) + info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "") require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -304,7 +304,7 @@ func TestLazyAdvancedKeyManagement(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - _, _, err := kb.CreateMnemonic(n1, English, p1, algo) + _, _, err := kb.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err, "%+v", err) assertPassword(t, kb, n1, p1, p2) @@ -352,7 +352,7 @@ func TestLazySeedPhrase(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo) + info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo, "") require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) assert.NotEmpty(t, mnemonic) diff --git a/crypto/keys/mintkey/mintkey_test.go b/crypto/keys/mintkey/mintkey_test.go index b4ce4d6a0f20..5a15c675827c 100644 --- a/crypto/keys/mintkey/mintkey_test.go +++ b/crypto/keys/mintkey/mintkey_test.go @@ -26,7 +26,7 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keys.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.CreateMnemonic("Bob", keys.English, "passphrase", keys.Secp256k1) + info, _, err := cstore.CreateMnemonic("Bob", keys.English, "passphrase", keys.Secp256k1, "") require.NoError(t, err) armor := mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes()) pubBytes, err := mintkey.UnarmorPubKeyBytes(armor) diff --git a/crypto/keys/types.go b/crypto/keys/types.go index c8424b96920e..0d0148c152ee 100644 --- a/crypto/keys/types.go +++ b/crypto/keys/types.go @@ -23,7 +23,7 @@ type Keybase interface { // CreateMnemonic creates a new mnemonic, and derives a hierarchical deterministic // key from that. - CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error) + CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo, mnemonic string) (info Info, seed string, err error) // CreateAccount creates an account based using the BIP44 path (44'/118'/{account}'/0/{index} CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error) diff --git a/crypto/keys/types_test.go b/crypto/keys/types_test.go index 3b368aa2e65b..82149056713c 100644 --- a/crypto/keys/types_test.go +++ b/crypto/keys/types_test.go @@ -21,9 +21,9 @@ func Test_writeReadLedgerInfo(t *testing.T) { path, err := lInfo.GetPath() assert.NoError(t, err) - assert.Equal(t, "44'/118'/5'/0/1", path.String()) + assert.Equal(t, "44'/996'/5'/0/1", path.String()) assert.Equal(t, - "cosmospub1addwnpepqddddqg2glc8x4fl7vxjlnr7p5a3czm5kcdp4239sg6yqdc4rc2r5wmxv8p", + "okchainpub1addwnpepqddddqg2glc8x4fl7vxjlnr7p5a3czm5kcdp4239sg6yqdc4rc2r58vtd89", types.MustBech32ifyAccPub(lInfo.GetPubKey())) // Serialize and restore diff --git a/crypto/ledger_test.go b/crypto/ledger_test.go index 0f726b410d55..2e192e40b811 100644 --- a/crypto/ledger_test.go +++ b/crypto/ledger_test.go @@ -28,32 +28,32 @@ func TestPublicKeyUnsafe(t *testing.T) { require.Nil(t, err, "%s", err) require.NotNil(t, priv) - require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87", + require.Equal(t, "eb5ae987210216a102323bd08b25b5e8f0cf573c7715a16a5ed907d7298fc21ee3aceef29628", fmt.Sprintf("%x", priv.PubKey().Bytes()), "Is your device using test mnemonic: %s ?", tests.TestMnemonic) pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey()) require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", + require.Equal(t, "okchainpub1addwnpepqgt2zq3j80ggkfd4arcv74euwu26z6j7myraw2v0cg0w8t8w72tzsw0zse0", pubKeyAddr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic) addr := sdk.AccAddress(priv.PubKey().Address()).String() - require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h", + require.Equal(t, "okchain1sjjdwhadqgt4e4507ps54zwc3zvx9c5hfxtysq", addr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic) } func TestPublicKeyUnsafeHDPath(t *testing.T) { expectedAnswers := []string{ - "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", - "cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65", - "cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d", - "cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs", - "cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7", - "cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns", - "cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp", - "cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew", - "cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9", - "cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r", + "okchainpub1addwnpepqgt2zq3j80ggkfd4arcv74euwu26z6j7myraw2v0cg0w8t8w72tzsw0zse0", + "okchainpub1addwnpepqdvr3cuk0yvr6nct8zf6l7pxtyxxgtnc8ncxjnjjs4z2j3s2xlffxja4pkf", + "okchainpub1addwnpepqwmkd5ng58gt8mpt3j5hekp5jnq2p7a55p7qut5tx9xdkyguqgvgjvxdxjq", + "okchainpub1addwnpepq0pk8w5se4p352jm0ga36mrdtxc62rwppthncs9h632xhvxlw8ft6ygdfvm", + "okchainpub1addwnpepq2e43ypcapx6d03rctews7qkjtcxkuav58dazkesrwe5nl77gucvspwql4x", + "okchainpub1addwnpepqdyarkhe2kh56l5j5kde55qq29mff5u49y0qsthww34ymffsps0jv4q9rnz", + "okchainpub1addwnpepqgtg3xaplrf8a79e6j09cxp0hwaq40yrfn90udwz09dwg50asacpceup5r3", + "okchainpub1addwnpepq2wvn84fky0chza9zrje6qkg34rr7fwwlan9npln7j5vay6w3uh9qvzctya", + "okchainpub1addwnpepqg4u7rz8uksafzdgjxvepssnxtn897ettdpkfqcn26ygh7gsp6fygl3nlzl", + "okchainpub1addwnpepqvesztxmxvh8t2hl5q6l0m3vgcd26dnuvsct6fptzt3sruflun255mjuhn3", } const numIters = 10 @@ -104,16 +104,16 @@ func TestPublicKeySafe(t *testing.T) { require.Nil(t, err, "%s", err) require.NotNil(t, priv) - require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87", + require.Equal(t, "eb5ae987210216a102323bd08b25b5e8f0cf573c7715a16a5ed907d7298fc21ee3aceef29628", fmt.Sprintf("%x", priv.PubKey().Bytes()), "Is your device using test mnemonic: %s ?", tests.TestMnemonic) pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey()) require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", + require.Equal(t, "okchainpub1addwnpepqgt2zq3j80ggkfd4arcv74euwu26z6j7myraw2v0cg0w8t8w72tzsw0zse0", pubKeyAddr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic) - require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h", + require.Equal(t, "okchain1sjjdwhadqgt4e4507ps54zwc3zvx9c5hfxtysq", addr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic) addr2 := sdk.AccAddress(priv.PubKey().Address()).String() @@ -122,29 +122,29 @@ func TestPublicKeySafe(t *testing.T) { func TestPublicKeyHDPath(t *testing.T) { expectedPubKeys := []string{ - "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", - "cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65", - "cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d", - "cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs", - "cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7", - "cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns", - "cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp", - "cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew", - "cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9", - "cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r", + "okchainpub1addwnpepqgt2zq3j80ggkfd4arcv74euwu26z6j7myraw2v0cg0w8t8w72tzsw0zse0", + "okchainpub1addwnpepqdvr3cuk0yvr6nct8zf6l7pxtyxxgtnc8ncxjnjjs4z2j3s2xlffxja4pkf", + "okchainpub1addwnpepqwmkd5ng58gt8mpt3j5hekp5jnq2p7a55p7qut5tx9xdkyguqgvgjvxdxjq", + "okchainpub1addwnpepq0pk8w5se4p352jm0ga36mrdtxc62rwppthncs9h632xhvxlw8ft6ygdfvm", + "okchainpub1addwnpepq2e43ypcapx6d03rctews7qkjtcxkuav58dazkesrwe5nl77gucvspwql4x", + "okchainpub1addwnpepqdyarkhe2kh56l5j5kde55qq29mff5u49y0qsthww34ymffsps0jv4q9rnz", + "okchainpub1addwnpepqgtg3xaplrf8a79e6j09cxp0hwaq40yrfn90udwz09dwg50asacpceup5r3", + "okchainpub1addwnpepq2wvn84fky0chza9zrje6qkg34rr7fwwlan9npln7j5vay6w3uh9qvzctya", + "okchainpub1addwnpepqg4u7rz8uksafzdgjxvepssnxtn897ettdpkfqcn26ygh7gsp6fygl3nlzl", + "okchainpub1addwnpepqvesztxmxvh8t2hl5q6l0m3vgcd26dnuvsct6fptzt3sruflun255mjuhn3", } expectedAddrs := []string{ - "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h", - "cosmos19ewxwemt6uahejvwf44u7dh6tq859tkyvarh2q", - "cosmos1a07dzdjgjsntxpp75zg7cgatgq0udh3pcdcxm3", - "cosmos1qvw52lmn9gpvem8welghrkc52m3zczyhlqjsl7", - "cosmos17m78ka80fqkkw2c4ww0v4xm5nsu2drgrlm8mn2", - "cosmos1ferh9ll9c452d2p8k2v7heq084guygkn43up9e", - "cosmos10vf3sxmjg96rqq36axcphzfsl74dsntuehjlw5", - "cosmos1cq83av8cmnar79h0rg7duh9gnr7wkh228a7fxg", - "cosmos1dszhfrt226jy5rsre7e48vw9tgwe90uerfyefa", - "cosmos1734d7qsylzrdt05muhqqtpd90j8mp4y6rzch8l", + "okchain1sjjdwhadqgt4e4507ps54zwc3zvx9c5hfxtysq", + "okchain1kywusqu9t5ppe9nl2rq26tg0cnzwygdctmmz5q", + "okchain1w9jw7273g3n8l0fyjtmlxmqhrctcn2afnlv9a2", + "okchain1lpjkyd2esun6y3l6qkjt377szaszn7ndte9sl7", + "okchain1m4hehxcu4nnq48wh6wummhdqtsnatm2cu8nlvc", + "okchain1chkys65xeekky8rjsr492n9ghytqprm6n3a2nt", + "okchain166tecxhd52la8w33g4kvpnnhp33wdfy0v6uda7", + "okchain1u8nwm4vk3q025azsujfqxwnftzzffjhkm0l7kr", + "okchain1m79f2vy0xm756v7evs2dz9umkw4swfn7j3e2a9", + "okchain13aex5w5w3hyg6zyvfq367g7alu47nk25msf2pj", } const numIters = 10 diff --git a/go.mod b/go.mod index e49ec355ccc9..1157219e2ead 100644 --- a/go.mod +++ b/go.mod @@ -29,3 +29,8 @@ require ( github.com/tendermint/tm-db v0.2.0 gopkg.in/yaml.v2 v2.2.7 ) + +replace ( + github.com/tendermint/iavl => github.com/okex/iavl v0.12.4-okchain + github.com/tendermint/tendermint => github.com/okex/tendermint v0.32.10-okchain +) diff --git a/go.sum b/go.sum index 7394fa9652ae..e6a4fbba7f9c 100644 --- a/go.sum +++ b/go.sum @@ -50,7 +50,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= @@ -59,13 +58,11 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojt github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -93,6 +90,7 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -100,7 +98,6 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -146,6 +143,10 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/okex/iavl v0.12.4-okchain h1:BAFmygzhx6k4KGnLrY87ZrJvRSb+wf8Oo4e2KhUwXcU= +github.com/okex/iavl v0.12.4-okchain/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= +github.com/okex/tendermint v0.32.10-okchain h1:4ZzRPVhDA+fHTQ/hVboAK7PPxL7uA5+Z4wKm8qeheJ0= +github.com/okex/tendermint v0.32.10-okchain/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= @@ -166,7 +167,6 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -179,7 +179,6 @@ github.com/rakyll/statik v0.1.5/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6 github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -205,7 +204,6 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= @@ -229,11 +227,6 @@ github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= github.com/tendermint/go-amino v0.15.0 h1:TC4e66P59W7ML9+bxio17CPKnxW3nKIRAYskntMAoRk= github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8= -github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= -github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= -github.com/tendermint/tendermint v0.32.10 h1:2NSVddRwicGb8a2Hu0QccQAy8uW0zD8Y1y4JeWTLS0U= -github.com/tendermint/tendermint v0.32.10/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= @@ -253,7 +246,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -284,6 +277,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -305,7 +299,6 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/server/config/config.go b/server/config/config.go index d783bdb36376..6d0f9ee7a6d1 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -8,7 +8,7 @@ import ( ) const ( - defaultMinGasPrices = "" + defaultMinGasPrices = "0.00000001"+sdk.DefaultBondDenom ) // BaseConfig defines the server's basic configuration @@ -34,7 +34,8 @@ type BaseConfig struct { // Config defines the server's top level configuration type Config struct { - BaseConfig `mapstructure:",squash"` + BaseConfig `mapstructure:",squash"` + BackendConfig *BackendConfig `mapstructure:"backend"` } // SetMinGasPrices sets the validator's minimum gas prices. @@ -67,8 +68,9 @@ func (c *Config) GetMinGasPrices() sdk.DecCoins { // DefaultConfig returns server's default configuration. func DefaultConfig() *Config { return &Config{ - BaseConfig{ + BaseConfig: BaseConfig{ MinGasPrices: defaultMinGasPrices, }, + BackendConfig: DefaultBackendConfig(), } } diff --git a/server/config/config_okchain.go b/server/config/config_okchain.go new file mode 100644 index 000000000000..57d834ebd88d --- /dev/null +++ b/server/config/config_okchain.go @@ -0,0 +1,66 @@ +package config + +import ( + "os" + "path/filepath" +) + +const ( + BackendOrmEngineTypeSqlite = "sqlite3" + BackendOrmEngineTypeMysql = "mysql" +) + +var defaultNodeHome = os.ExpandEnv("$HOME/.okchaind") + +// SetNodeHome sets the root directory for all data. +func SetNodeHome(home string) { + defaultNodeHome = home +} + +// GetNodeHome returns the root directory for all data. +func GetNodeHome() string { + return defaultNodeHome +} + +type BackendConfig struct { + EnableBackend bool `json:"enable_backend" mapstructure:"enable_backend"` + EnableMktCompute bool `json:"enable_mkt_compute" mapstructure:"enable_mkt_compute"` + //HotKeptDays int `json:"hot_kept_days" mapstructure:"hot_kept_days"` + //UpdateFreq int64 `json:"update_freq" mapstructure:"update_freq"` // unit: second + //BufferSize int `json:"buffer_size" mapstructure:"buffer_size"` // + //SyncMode string `json:"sync_mode" mapstructure:"sync_mode"` // mode: block or minutes + LogSQL bool `json:"log_sql" mapstructure:"log_sql"` // + CleanUpsKeptDays map[string]int `json:"clean_ups_kept_days"` // 0 <= x <= 60 + CleanUpsTime string `json:"clean_ups_time" mapstructure:"clean_ups_time"` // e.g.) 00:00:00, CleanUp job will be fired at this time. + OrmEngine BackendOrmEngineInfo `json:"orm_engine" mapstructure:"orm_engine"` // +} + +type BackendOrmEngineInfo struct { + // engine type should be sqlite3 or mysql + EngineType string `json:"engine_type" mapstructure:"engine_type"` + + // if engine_type is sqlite3, it should be a local path, e.g.) /Users/lingting.fu/.okchaind/data/sqlite3/backend.db + // if engine_type is mysql, it should be "[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]" + ConnectStr string `json:"connect_str" mapstructure:"connect_str"` +} + +func DefaultBackendConfig() *BackendConfig { + c := BackendConfig{} + + c.EnableBackend = false + c.EnableMktCompute = false + //c.HotKeptDays = 3 + //c.UpdateFreq = 60 + //c.BufferSize = 4096 + c.LogSQL = false + c.CleanUpsTime = "00:00:00" + c.CleanUpsKeptDays = map[string]int{} + c.CleanUpsKeptDays["kline_m1"] = 120 + c.CleanUpsKeptDays["kline_m3"] = 120 + c.CleanUpsKeptDays["kline_m5"] = 120 + + c.OrmEngine.EngineType = BackendOrmEngineTypeSqlite + c.OrmEngine.ConnectStr = filepath.Join(GetNodeHome(), "data", c.OrmEngine.EngineType, "backend.sqlite3") + + return &c +} diff --git a/server/config/config_test.go b/server/config/config_test.go index e828a0716dc8..729eacf05680 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -10,11 +10,12 @@ import ( func TestDefaultConfig(t *testing.T) { cfg := DefaultConfig() - require.True(t, cfg.GetMinGasPrices().IsZero()) + require.True(t, cfg.GetMinGasPrices().IsEqual( + sdk.DecCoins{sdk.DecCoin{sdk.DefaultBondDenom, sdk.MustNewDecFromStr("0.00000001")}})) } func TestSetMinimumFees(t *testing.T) { cfg := DefaultConfig() cfg.SetMinGasPrices(sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}) - require.Equal(t, "5.000000000000000000foo", cfg.MinGasPrices) + require.Equal(t, "5.00000000foo", cfg.MinGasPrices) } diff --git a/server/config/toml.go b/server/config/toml.go index f4b58012d72b..ac0ccb79018f 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -30,6 +30,16 @@ halt-height = {{ .BaseConfig.HaltHeight }} # # Note: Commitment of state will be attempted on the corresponding block. halt-time = {{ .BaseConfig.HaltTime }} +##### backend configuration options ##### +[backend] +enable_backend = "{{ .BackendConfig.EnableBackend }}" +enable_mkt_compute = "{{ .BackendConfig.EnableMktCompute }}" +log_sql = "{{ .BackendConfig.LogSQL }}" +clean_ups_kept_days = "{{ .BackendConfig.CleanUpsKeptDays }}" +clean_ups_time = "{{ .BackendConfig.CleanUpsTime }}" +[backend.orm_engine] +engine_type = "{{ .BackendConfig.OrmEngine.EngineType }}" +connect_str = "{{ .BackendConfig.OrmEngine.ConnectStr }}" ` var configTemplate *template.Template diff --git a/server/init.go b/server/init.go index 58cf98d0aba7..8101eabdb040 100644 --- a/server/init.go +++ b/server/init.go @@ -15,7 +15,7 @@ func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase info, secret, err := clkeys.NewInMemoryKeyBase().CreateMnemonic( - "name", keys.English, "pass", keys.Secp256k1) + "name", keys.English, "pass", keys.Secp256k1, "") if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -25,8 +25,7 @@ func GenerateCoinKey() (sdk.AccAddress, string, error) { // GenerateSaveCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. -func GenerateSaveCoinKey(clientRoot, keyName, keyPass string, - overwrite bool) (sdk.AccAddress, string, error) { +func GenerateSaveCoinKey(clientRoot, keyName, keyPass string, overwrite bool, mnemonicInput string) (sdk.AccAddress, string, error) { // get the keystore from the client keybase, err := clkeys.NewKeyBaseFromDir(clientRoot) @@ -44,7 +43,7 @@ func GenerateSaveCoinKey(clientRoot, keyName, keyPass string, } // generate a private key, with recovery phrase - info, secret, err := keybase.CreateMnemonic(keyName, keys.English, keyPass, keys.Secp256k1) + info, secret, err := keybase.CreateMnemonic(keyName, keys.English, keyPass, keys.Secp256k1, mnemonicInput) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index 38b88777900a..6949b535b41f 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -29,7 +29,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { // Remove the dir to that GenerateSaveCoinKey creates it automatically os.RemoveAll(dir) - addr, mnemonic, err := server.GenerateSaveCoinKey(dir, "keyname", "012345678", false) + addr, mnemonic, err := server.GenerateSaveCoinKey(dir, "keyname", "012345678", false, "") require.NoError(t, err) // Test key was actually saved @@ -53,15 +53,15 @@ func TestGenerateSaveCoinKeyOverwriteFlag(t *testing.T) { os.RemoveAll(dir) keyname := "justakey" - addr1, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", false) + addr1, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", false, "") require.NoError(t, err) // Test overwrite with overwrite=false - _, _, err = server.GenerateSaveCoinKey(dir, keyname, "012345678", false) + _, _, err = server.GenerateSaveCoinKey(dir, keyname, "012345678", false, "") require.Error(t, err) // Test overwrite with overwrite=true - addr2, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", true) + addr2, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", true, "") require.NoError(t, err) require.NotEqual(t, addr1, addr2) diff --git a/server/start.go b/server/start.go index 696163300bdf..f3b32dedde6f 100644 --- a/server/start.go +++ b/server/start.go @@ -7,6 +7,8 @@ import ( "os" "runtime/pprof" + "github.com/cosmos/cosmos-sdk/client/lcd" + "github.com/cosmos/cosmos-sdk/codec" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/tendermint/abci/server" @@ -32,7 +34,9 @@ const ( // StartCmd runs the service passed in, either stand-alone or in-process with // Tendermint. -func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command { +func StartCmd(ctx *Context, + cdc *codec.Codec, appCreator AppCreator, + registerRoutesFn func(restServer *lcd.RestServer)) *cobra.Command { cmd := &cobra.Command{ Use: "start", Short: "Run the full node", @@ -62,8 +66,12 @@ which accepts a path for the resulting pprof file. ctx.Logger.Info("starting ABCI with Tendermint") - _, err := startInProcess(ctx, appCreator) - return err + setPID(ctx) + _, err := startInProcess(ctx, cdc, appCreator, registerRoutesFn) + if err != nil { + cmn.Exit(err.Error()) + } + return nil }, } @@ -80,6 +88,9 @@ which accepts a path for the resulting pprof file. cmd.Flags().Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node") cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file") + registerRestServerFlags(cmd) + + registerOkchainPluginFlags(cmd) // add support for all Tendermint-specific command line options tcmd.AddNodeFlags(cmd) return cmd @@ -125,9 +136,15 @@ func startStandAlone(ctx *Context, appCreator AppCreator) error { select {} } -func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) { +func startInProcess(ctx *Context, cdc *codec.Codec, appCreator AppCreator, + registerRoutesFn func(restServer *lcd.RestServer)) (*node.Node, error) { + cfg := ctx.Config home := cfg.RootDir + //startInProcess hooker + + callHooker(FlagHookstartInProcess, ctx) + traceWriterFile := viper.GetString(flagTraceStore) db, err := openDB(home) @@ -199,6 +216,10 @@ func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) { ctx.Logger.Info("exiting...") }) + if registerRoutesFn != nil { + go lcd.StartRestServer(cdc, registerRoutesFn, tmNode, viper.GetString(FlagListenAddr)) + } + // run forever (the node will not be returned) select {} } diff --git a/server/start_okchain.go b/server/start_okchain.go new file mode 100644 index 000000000000..1068b889465e --- /dev/null +++ b/server/start_okchain.go @@ -0,0 +1,165 @@ +package server + +import ( + "bufio" + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + "strconv" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/spf13/cobra" + cmn "github.com/tendermint/tendermint/libs/common" +) + +// okchain full-node start flags +const ( + FlagListenAddr = "rest.laddr" + FlagExternalListenAddr = "rest.external_laddr" + FlagCORS = "cors" + FlagMaxOpenConnections = "max-open" + FlagHookstartInProcess = "startInProcess" + + // plugin flags + FlagBackendEnableBackend = "backend.enable_backend" + FlagBackendEnableMktCompute = "backend.enable_mkt_compute" + FlagBackendLogSQL = "backend.log_sql" + FlagBackendCleanUpsTime = "backend.clean_ups_time" + FlagBacekendOrmEngineType = "backend.orm_engine.engine_type" + FlagBackendOrmEngineConnectStr = "backend.orm_engine.connect_str" +) + +var ( + backendConf = config.DefaultConfig().BackendConfig +) + +//module hook + +type fnHookstartInProcess func(ctx *Context) error + +type serverHookTable struct { + hookTable map[string]interface{} +} + +var gSrvHookTable = serverHookTable{make(map[string]interface{})} + +func InstallHookEx(flag string, hooker fnHookstartInProcess) { + gSrvHookTable.hookTable[flag] = hooker +} + +//call hooker function +func callHooker(flag string, args ...interface{}) error { + params := make([]interface{}, 0) + switch flag { + case FlagHookstartInProcess: + { + //none hook func, return nil + function, ok := gSrvHookTable.hookTable[FlagHookstartInProcess] + if !ok { + return nil + } + params = append(params, args...) + if len(params) != 1 { + return errors.New("too many or less parameter called, want 1") + } + + //param type check + p1, ok := params[0].(*Context) + if !ok { + return errors.New("wrong param 1 type. want *Context, got" + reflect.TypeOf(params[0]).String()) + } + + //get hook function and call it + caller := function.(fnHookstartInProcess) + return caller(p1) + } + default: + break + } + return nil +} + +//end of hook + +func setPID(ctx *Context) { + pid := os.Getpid() + f, err := os.OpenFile(filepath.Join(ctx.Config.RootDir, "config", "pid"), os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + cmn.Exit(err.Error()) + } + defer f.Close() + writer := bufio.NewWriter(f) + _, err = writer.WriteString(strconv.Itoa(pid)) + if err != nil { + fmt.Println(err.Error()) + } + writer.Flush() +} + +// StopCmd stop the node gracefully +// Tendermint. +func StopCmd(ctx *Context) *cobra.Command { + cmd := &cobra.Command{ + Use: "stop", + Short: "Stop the node gracefully", + RunE: func(cmd *cobra.Command, args []string) error { + f, err := os.Open(filepath.Join(ctx.Config.RootDir, "config", "pid")) + if err != nil { + errStr := fmt.Sprintf("%s Please finish the process of okchaind through kill -2 pid to stop gracefully", err.Error()) + cmn.Exit(errStr) + } + defer f.Close() + in := bufio.NewScanner(f) + in.Scan() + pid, err := strconv.Atoi(in.Text()) + if err != nil { + errStr := fmt.Sprintf("%s Please finish the process of okchaind through kill -2 pid to stop gracefully", err.Error()) + cmn.Exit(errStr) + } + process, err := os.FindProcess(pid) + if err != nil { + cmn.Exit(err.Error()) + } + err = process.Signal(os.Interrupt) + if err != nil { + cmn.Exit(err.Error()) + } + fmt.Println("pid", pid, "has been sent SIGINT") + return nil + }, + } + return cmd +} + +var sem *nodeSemaphore + +type nodeSemaphore struct { + done chan struct{} +} + +func Stop() { + sem.done <- struct{}{} +} + +// registerRestServerFlags registers the flags required for rest server +func registerRestServerFlags(cmd *cobra.Command) *cobra.Command { + cmd.Flags().String(FlagListenAddr, "tcp://0.0.0.0:26659", "The address for the rest-server to listen on. (0.0.0.0:0 means any interface, any port)") + cmd.Flags().String(FlagCORS, "", "Set the rest-server domains that can make CORS requests (* for all)") + cmd.Flags().Int(FlagMaxOpenConnections, 1000, "The number of maximum open connections of rest-server") + cmd.Flags().String(FlagExternalListenAddr, "127.0.0.1:26659", "Set the rest-server external ip and port, when it is launched by Docker") + return cmd +} + +// registerOkchainPluginFlags registers the flags required for rest server +func registerOkchainPluginFlags(cmd *cobra.Command) *cobra.Command { + cmd.Flags().Bool(FlagBackendEnableBackend, backendConf.EnableBackend, "Enable the node's backend plugin") + cmd.Flags().Bool(FlagBackendEnableMktCompute, backendConf.EnableMktCompute, "Enable kline and ticker calculating") + cmd.Flags().Bool(FlagBackendLogSQL, backendConf.LogSQL, "Enable backend plugin logging sql feature") + cmd.Flags().String(FlagBackendCleanUpsTime, backendConf.CleanUpsTime, "Backend plugin`s time of cleaning up kline data") + cmd.Flags().String(FlagBacekendOrmEngineType, backendConf.OrmEngine.EngineType, "Backend plugin`s db (mysql or sqlite3)") + cmd.Flags().String(FlagBackendOrmEngineConnectStr, backendConf.OrmEngine.ConnectStr, "Backend plugin`s db connect address") + + return cmd +} diff --git a/server/util.go b/server/util.go index 20eecfe154d3..cd1a0e39d476 100644 --- a/server/util.go +++ b/server/util.go @@ -22,6 +22,7 @@ import ( pvm "github.com/tendermint/tendermint/privval" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/lcd" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server/config" "github.com/cosmos/cosmos-sdk/version" @@ -58,7 +59,16 @@ func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error if err != nil { return err } - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + // okchain + output := os.Stdout + if !config.LogStdout { + output, err = os.OpenFile(config.LogFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) + if err != nil { + return err + } + } + + logger := log.NewTMLogger(log.NewSyncWriter(output)) logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel()) if err != nil { return err @@ -92,7 +102,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) { conf.P2P.RecvRate = 5120000 conf.P2P.SendRate = 5120000 conf.TxIndex.IndexAllTags = true - conf.Consensus.TimeoutCommit = 5 * time.Second + conf.Consensus.TimeoutCommit = 1 * time.Second cfg.WriteConfigFile(configFilePath, conf) // Fall through, just so that its parsed into memory. } @@ -104,13 +114,14 @@ func interceptLoadConfig() (conf *cfg.Config, err error) { } } - appConfigFilePath := filepath.Join(rootDir, "config/app.toml") + config.SetNodeHome(rootDir) + appConfigFilePath := filepath.Join(rootDir, "config/okchaind.toml") if _, err := os.Stat(appConfigFilePath); os.IsNotExist(err) { appConf, _ := config.ParseConfig() config.WriteConfigFile(appConfigFilePath, appConf) } - viper.SetConfigName("app") + viper.SetConfigName("okchaind") err = viper.MergeInConfig() return @@ -120,10 +131,14 @@ func interceptLoadConfig() (conf *cfg.Config, err error) { func AddCommands( ctx *Context, cdc *codec.Codec, rootCmd *cobra.Command, - appCreator AppCreator, appExport AppExporter) { + appCreator AppCreator, appExport AppExporter, + registerRouters func(rs *lcd.RestServer)) { rootCmd.PersistentFlags().String("log_level", ctx.Config.LogLevel, "Log level") + rootCmd.PersistentFlags().String("log_file", ctx.Config.LogFile, "Log file") + rootCmd.PersistentFlags().Bool("log_stdout", ctx.Config.LogStdout, "Print log to stdout, rather than a file") + tendermintCmd := &cobra.Command{ Use: "tendermint", Short: "Tendermint subcommands", @@ -137,7 +152,8 @@ func AddCommands( ) rootCmd.AddCommand( - StartCmd(ctx, appCreator), + StartCmd(ctx, cdc, appCreator, registerRouters), + StopCmd(ctx), UnsafeResetAllCmd(ctx), flags.LineBreak, tendermintCmd, diff --git a/simapp/app.go b/simapp/app.go index 052a622bf937..b1643a62494d 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -207,7 +207,7 @@ func NewSimApp( // initialize BaseApp app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) - app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.supplyKeeper, auth.DefaultSigVerificationGasConsumer)) + app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.supplyKeeper, auth.DefaultSigVerificationGasConsumer, nil, nil)) app.SetEndBlocker(app.EndBlocker) if loadLatest { diff --git a/simapp/utils.go b/simapp/utils.go index a52eb7939cd6..07867256eaa8 100644 --- a/simapp/utils.go +++ b/simapp/utils.go @@ -248,11 +248,11 @@ func GenGovGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, govGenesis := gov.NewGenesisState( uint64(r.Intn(100)), gov.NewDepositParams( - func(r *rand.Rand) sdk.Coins { - var v sdk.Coins + func(r *rand.Rand) sdk.DecCoins { + var v sdk.DecCoins ap.GetOrGenerate(cdc, simulation.DepositParamsMinDeposit, &v, r, func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.DepositParamsMinDeposit](r).(sdk.Coins) + v = simulation.ModuleParamSimulator[simulation.DepositParamsMinDeposit](r).(sdk.DecCoins) }) return v }(r), @@ -294,7 +294,7 @@ func GenGovGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, // GenMintGenesisState generates a random GenesisState for mint func GenMintGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { mintGenesis := mint.NewGenesisState( - mint.InitialMinter( + mint.InitialMinterCustom( func(r *rand.Rand) sdk.Dec { var v sdk.Dec ap.GetOrGenerate(cdc, simulation.Inflation, &v, r, diff --git a/simapp/utils_test.go b/simapp/utils_test.go index b76189728ec5..dc54ad1d3dc4 100644 --- a/simapp/utils_test.go +++ b/simapp/utils_test.go @@ -19,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/mint" "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/supply" @@ -228,7 +229,7 @@ func TestDecodeStakingStore(t *testing.T) { func TestDecodeSlashingStore(t *testing.T) { cdc := makeTestCodec() - info := slashing.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0) + info := slashing.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0, types.Created) bechPK := sdk.MustBech32ifyAccPub(delPk1) missed := true @@ -266,7 +267,7 @@ func TestDecodeGovStore(t *testing.T) { endTime := time.Now().UTC() content := gov.ContentFromProposalType("test", "test", gov.ProposalTypeText) - proposal := gov.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour)) + proposal := gov.NewProposal(sdk.Context{}, sdk.OneDec(), content, 1, endTime, endTime.Add(24*time.Hour)) proposalIDBz := make([]byte, 8) binary.LittleEndian.PutUint64(proposalIDBz, 1) deposit := gov.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()))) diff --git a/store/iavl/store.go b/store/iavl/store.go index 837314c29beb..2802dc0d0453 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -23,8 +23,8 @@ const ( ) // LoadStore loads the iavl store -func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyLoading bool) (types.CommitStore, error) { - tree := iavl.NewMutableTree(db, defaultIAVLCacheSize) +func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyLoading bool, startVersion int64) (types.CommitStore, error) { + tree := iavl.NewMutableTree(db, defaultIAVLCacheSize, startVersion) var err error if lazyLoading { diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index 7480d0737319..9aac64faafa1 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -31,7 +31,7 @@ var ( // make a tree with data from above and save it func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) for k, v := range treeData { tree.Set([]byte(k), []byte(v)) } @@ -205,7 +205,7 @@ func TestIAVLIterator(t *testing.T) { func TestIAVLReverseIterator(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte{0x00}, []byte("0")) @@ -236,7 +236,7 @@ func TestIAVLReverseIterator(t *testing.T) { func TestIAVLPrefixIterator(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte("test1"), []byte("test1")) @@ -298,7 +298,7 @@ func TestIAVLPrefixIterator(t *testing.T) { func TestIAVLReversePrefixIterator(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte("test1"), []byte("test1")) @@ -417,7 +417,7 @@ type pruneState struct { func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []pruneState) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) for step, state := range states { for _, ver := range state.stored { @@ -436,7 +436,7 @@ func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []prune func TestIAVLNoPrune(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, int64(1)) nextVersion(iavlStore) for i := 1; i < 100; i++ { @@ -451,7 +451,7 @@ func TestIAVLNoPrune(t *testing.T) { func TestIAVLPruneEverything(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, int64(0), int64(0)) nextVersion(iavlStore) for i := 1; i < 100; i++ { @@ -469,7 +469,7 @@ func TestIAVLPruneEverything(t *testing.T) { func TestIAVLStoreQuery(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) k1, v1 := []byte("key1"), []byte("val1") @@ -560,7 +560,7 @@ func TestIAVLStoreQuery(t *testing.T) { func BenchmarkIAVLIteratorNext(b *testing.B) { db := dbm.NewMemDB() treeSize := 1000 - tree := iavl.NewMutableTree(db, cacheSize) + tree := iavl.NewMutableTree(db, cacheSize, 0) for i := 0; i < treeSize; i++ { key := cmn.RandBytes(4) value := cmn.RandBytes(50) diff --git a/store/prefix/store_test.go b/store/prefix/store_test.go index 1a59a03f8e17..28b742875271 100644 --- a/store/prefix/store_test.go +++ b/store/prefix/store_test.go @@ -88,7 +88,7 @@ func testPrefixStore(t *testing.T, baseStore types.KVStore, prefix []byte) { func TestIAVLStorePrefix(t *testing.T) { db := dbm.NewMemDB() - tree := tiavl.NewMutableTree(db, cacheSize) + tree := tiavl.NewMutableTree(db, cacheSize, 0) iavlStore := iavl.UnsafeNewStore(tree, numRecent, storeEvery) testPrefixStore(t, iavlStore, []byte("test")) diff --git a/store/rootmulti/proof_test.go b/store/rootmulti/proof_test.go index 03bf5e8c6956..fb05073012a4 100644 --- a/store/rootmulti/proof_test.go +++ b/store/rootmulti/proof_test.go @@ -14,7 +14,7 @@ import ( func TestVerifyIAVLStoreQueryProof(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - iStore, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing, false) + iStore, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing, false, 0) store := iStore.(*iavl.Store) require.Nil(t, err) store.Set([]byte("MYKEY"), []byte("MYVALUE")) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index d259f940a0df..47f50fb43037 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/tmhash" dbm "github.com/tendermint/tm-db" + tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/dbadapter" @@ -112,7 +113,7 @@ func (rs *Store) LoadVersion(ver int64) error { // Special logic for version 0 where there is no need to get commit // information. for key, storeParams := range rs.storesParams { - store, err := rs.loadCommitStoreFromParams(key, types.CommitID{}, storeParams) + store, err := rs.loadCommitStoreFromParams(key, types.CommitID{Version: tmtypes.GetStartBlockHeight()}, storeParams) if err != nil { return fmt.Errorf("failed to load Store: %v", err) } @@ -121,6 +122,7 @@ func (rs *Store) LoadVersion(ver int64) error { } rs.lastCommitID = types.CommitID{} + rs.lastCommitID.Version = tmtypes.GetStartBlockHeight() return nil } @@ -395,7 +397,7 @@ func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID panic("recursive MultiStores not yet supported") case types.StoreTypeIAVL: - return iavl.LoadStore(db, id, rs.pruningOpts, rs.lazyLoading) + return iavl.LoadStore(db, id, rs.pruningOpts, rs.lazyLoading, tmtypes.GetStartBlockHeight()) case types.StoreTypeDB: return commitDBStoreAdapter{dbadapter.Store{db}}, nil diff --git a/types/abci.go b/types/abci.go index 8f71362eda6d..7733edd41dd0 100644 --- a/types/abci.go +++ b/types/abci.go @@ -19,3 +19,7 @@ type EndBlocker func(ctx Context, req abci.RequestEndBlock) abci.ResponseEndBloc // PeerFilter responds to p2p filtering queries from Tendermint type PeerFilter func(info string) abci.ResponseQuery + +type DeliverTx func(txBytes []byte) abci.ResponseDeliverTx + +type PostEndBlockHandler func(res *abci.ResponseEndBlock) diff --git a/types/address.go b/types/address.go index 75640d3ea955..0d07d9633874 100644 --- a/types/address.go +++ b/types/address.go @@ -32,14 +32,14 @@ const ( // AddrLen defines a valid address length AddrLen = 20 // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address - Bech32MainPrefix = "cosmos" + Bech32MainPrefix = "okchain" // Atom in https://github.com/satoshilabs/slips/blob/master/slip-0044.md - CoinType = 118 + CoinType = 996 // BIP44Prefix is the parts of the BIP44 HD path that are fixed by // what we used during the fundraiser. - FullFundraiserPath = "44'/118'/0'/0/0" + FullFundraiserPath = "44'/996'/0'/0/0" // PrefixAccount is the prefix for account keys PrefixAccount = "acc" diff --git a/types/coin.go b/types/coin.go index 84a0e60369c5..c9753d47bb55 100644 --- a/types/coin.go +++ b/types/coin.go @@ -4,152 +4,8 @@ import ( "encoding/json" "fmt" "regexp" - "sort" - "strings" ) -//----------------------------------------------------------------------------- -// Coin - -// Coin hold some amount of one currency. -// -// CONTRACT: A coin will never hold a negative amount of any denomination. -// -// TODO: Make field members private for further safety. -type Coin struct { - Denom string `json:"denom"` - - // To allow the use of unsigned integers (see: #1273) a larger refactor will - // need to be made. So we use signed integers for now with safety measures in - // place preventing negative values being used. - Amount Int `json:"amount"` -} - -// NewCoin returns a new coin with a denomination and amount. It will panic if -// the amount is negative. -func NewCoin(denom string, amount Int) Coin { - if err := validate(denom, amount); err != nil { - panic(err) - } - - return Coin{ - Denom: denom, - Amount: amount, - } -} - -// NewInt64Coin returns a new coin with a denomination and amount. It will panic -// if the amount is negative. -func NewInt64Coin(denom string, amount int64) Coin { - return NewCoin(denom, NewInt(amount)) -} - -// String provides a human-readable representation of a coin -func (coin Coin) String() string { - return fmt.Sprintf("%v%v", coin.Amount, coin.Denom) -} - -// validate returns an error if the Coin has a negative amount or if -// the denom is invalid. -func validate(denom string, amount Int) error { - if err := validateDenom(denom); err != nil { - return err - } - - if amount.LT(ZeroInt()) { - return fmt.Errorf("negative coin amount: %v", amount) - } - - return nil -} - -// IsValid returns true if the Coin has a non-negative amount and the denom is vaild. -func (coin Coin) IsValid() bool { - if err := validate(coin.Denom, coin.Amount); err != nil { - return false - } - return true -} - -// IsZero returns if this represents no money -func (coin Coin) IsZero() bool { - return coin.Amount.IsZero() -} - -// IsGTE returns true if they are the same type and the receiver is -// an equal or greater value -func (coin Coin) IsGTE(other Coin) bool { - if coin.Denom != other.Denom { - panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom)) - } - - return !coin.Amount.LT(other.Amount) -} - -// IsLT returns true if they are the same type and the receiver is -// a smaller value -func (coin Coin) IsLT(other Coin) bool { - if coin.Denom != other.Denom { - panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom)) - } - - return coin.Amount.LT(other.Amount) -} - -// IsEqual returns true if the two sets of Coins have the same value -func (coin Coin) IsEqual(other Coin) bool { - if coin.Denom != other.Denom { - panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, other.Denom)) - } - - return coin.Amount.Equal(other.Amount) -} - -// Adds amounts of two coins with same denom. If the coins differ in denom then -// it panics. -func (coin Coin) Add(coinB Coin) Coin { - if coin.Denom != coinB.Denom { - panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, coinB.Denom)) - } - - return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)} -} - -// Subtracts amounts of two coins with same denom. If the coins differ in denom -// then it panics. -func (coin Coin) Sub(coinB Coin) Coin { - if coin.Denom != coinB.Denom { - panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, coinB.Denom)) - } - - res := Coin{coin.Denom, coin.Amount.Sub(coinB.Amount)} - if res.IsNegative() { - panic("negative count amount") - } - - return res -} - -// IsPositive returns true if coin amount is positive. -// -// TODO: Remove once unsigned integers are used. -func (coin Coin) IsPositive() bool { - return coin.Amount.Sign() == 1 -} - -// IsNegative returns true if the coin amount is negative and false otherwise. -// -// TODO: Remove once unsigned integers are used. -func (coin Coin) IsNegative() bool { - return coin.Amount.Sign() == -1 -} - -//----------------------------------------------------------------------------- -// Coins - -// Coins is a set of Coin, one per currency -type Coins []Coin - // NewCoins constructs a new coin set. func NewCoins(coins ...Coin) Coins { // remove zeroes @@ -184,123 +40,6 @@ func (coins Coins) MarshalJSON() ([]byte, error) { return json.Marshal(coinsJSON(coins)) } -func (coins Coins) String() string { - if len(coins) == 0 { - return "" - } - - out := "" - for _, coin := range coins { - out += fmt.Sprintf("%v,", coin.String()) - } - return out[:len(out)-1] -} - -// IsValid asserts the Coins are sorted, have positive amount, -// and Denom does not contain upper case characters. -func (coins Coins) IsValid() bool { - switch len(coins) { - case 0: - return true - case 1: - if err := validateDenom(coins[0].Denom); err != nil { - return false - } - return coins[0].IsPositive() - default: - // check single coin case - if !(Coins{coins[0]}).IsValid() { - return false - } - - lowDenom := coins[0].Denom - for _, coin := range coins[1:] { - if strings.ToLower(coin.Denom) != coin.Denom { - return false - } - if coin.Denom <= lowDenom { - return false - } - if !coin.IsPositive() { - return false - } - - // we compare each coin against the last denom - lowDenom = coin.Denom - } - - return true - } -} - -// Add adds two sets of coins. -// -// e.g. -// {2A} + {A, 2B} = {3A, 2B} -// {2A} + {0B} = {2A} -// -// NOTE: Add operates under the invariant that coins are sorted by -// denominations. -// -// CONTRACT: Add will never return Coins where one Coin has a non-positive -// amount. In otherwords, IsValid will always return true. -func (coins Coins) Add(coinsB Coins) Coins { - return coins.safeAdd(coinsB) -} - -// safeAdd will perform addition of two coins sets. If both coin sets are -// empty, then an empty set is returned. If only a single set is empty, the -// other set is returned. Otherwise, the coins are compared in order of their -// denomination and addition only occurs when the denominations match, otherwise -// the coin is simply added to the sum assuming it's not zero. -func (coins Coins) safeAdd(coinsB Coins) Coins { - sum := ([]Coin)(nil) - indexA, indexB := 0, 0 - lenA, lenB := len(coins), len(coinsB) - - for { - if indexA == lenA { - if indexB == lenB { - // return nil coins if both sets are empty - return sum - } - - // return set B (excluding zero coins) if set A is empty - return append(sum, removeZeroCoins(coinsB[indexB:])...) - } else if indexB == lenB { - // return set A (excluding zero coins) if set B is empty - return append(sum, removeZeroCoins(coins[indexA:])...) - } - - coinA, coinB := coins[indexA], coinsB[indexB] - - switch strings.Compare(coinA.Denom, coinB.Denom) { - case -1: // coin A denom < coin B denom - if !coinA.IsZero() { - sum = append(sum, coinA) - } - - indexA++ - - case 0: // coin A denom == coin B denom - res := coinA.Add(coinB) - if !res.IsZero() { - sum = append(sum, res) - } - - indexA++ - indexB++ - - case 1: // coin A denom > coin B denom - if !coinB.IsZero() { - sum = append(sum, coinB) - } - - indexB++ - } - } -} - // DenomsSubsetOf returns true if receiver's denom set // is subset of coinsB's denoms. func (coins Coins) DenomsSubsetOf(coinsB Coins) bool { @@ -318,31 +57,6 @@ func (coins Coins) DenomsSubsetOf(coinsB Coins) bool { return true } -// Sub subtracts a set of coins from another. -// -// e.g. -// {2A, 3B} - {A} = {A, 3B} -// {2A} - {0B} = {2A} -// {A, B} - {A} = {B} -// -// CONTRACT: Sub will never return Coins where one Coin has a non-positive -// amount. In otherwords, IsValid will always return true. -func (coins Coins) Sub(coinsB Coins) Coins { - diff, hasNeg := coins.SafeSub(coinsB) - if hasNeg { - panic("negative coin amount") - } - - return diff -} - -// SafeSub performs the same arithmetic as Sub but returns a boolean if any -// negative coin amount was returned. -func (coins Coins) SafeSub(coinsB Coins) (Coins, bool) { - diff := coins.safeAdd(coinsB.negative()) - return diff, diff.IsAnyNegative() -} - // IsAllGT returns true if for every denom in coinsB, // the denom is present at a greater amount in coins. func (coins Coins) IsAllGT(coinsB Coins) bool { @@ -444,115 +158,6 @@ func (coins Coins) IsAnyGTE(coinsB Coins) bool { return false } -// IsZero returns true if there are no coins or all coins are zero. -func (coins Coins) IsZero() bool { - for _, coin := range coins { - if !coin.IsZero() { - return false - } - } - return true -} - -// IsEqual returns true if the two sets of Coins have the same value -func (coins Coins) IsEqual(coinsB Coins) bool { - if len(coins) != len(coinsB) { - return false - } - - coins = coins.Sort() - coinsB = coinsB.Sort() - - for i := 0; i < len(coins); i++ { - if !coins[i].IsEqual(coinsB[i]) { - return false - } - } - - return true -} - -// Empty returns true if there are no coins and false otherwise. -func (coins Coins) Empty() bool { - return len(coins) == 0 -} - -// Returns the amount of a denom from coins -func (coins Coins) AmountOf(denom string) Int { - mustValidateDenom(denom) - - switch len(coins) { - case 0: - return ZeroInt() - - case 1: - coin := coins[0] - if coin.Denom == denom { - return coin.Amount - } - return ZeroInt() - - default: - midIdx := len(coins) / 2 // 2:1, 3:1, 4:2 - coin := coins[midIdx] - - if denom < coin.Denom { - return coins[:midIdx].AmountOf(denom) - } else if denom == coin.Denom { - return coin.Amount - } else { - return coins[midIdx+1:].AmountOf(denom) - } - } -} - -// IsAllPositive returns true if there is at least one coin and all currencies -// have a positive value. -func (coins Coins) IsAllPositive() bool { - if len(coins) == 0 { - return false - } - - for _, coin := range coins { - if !coin.IsPositive() { - return false - } - } - - return true -} - -// IsAnyNegative returns true if there is at least one coin whose amount -// is negative; returns false otherwise. It returns false if the coin set -// is empty too. -// -// TODO: Remove once unsigned integers are used. -func (coins Coins) IsAnyNegative() bool { - for _, coin := range coins { - if coin.IsNegative() { - return true - } - } - - return false -} - -// negative returns a set of coins with all amount negative. -// -// TODO: Remove once unsigned integers are used. -func (coins Coins) negative() Coins { - res := make([]Coin, 0, len(coins)) - - for _, coin := range coins { - res = append(res, Coin{ - Denom: coin.Denom, - Amount: coin.Amount.Neg(), - }) - } - - return res -} - // removeZeroCoins removes all zero coins from the given coin set in-place. func removeZeroCoins(coins Coins) Coins { i, l := 0, len(coins) @@ -569,30 +174,14 @@ func removeZeroCoins(coins Coins) Coins { return coins[:i] } -//----------------------------------------------------------------------------- -// Sort interface - -//nolint -func (coins Coins) Len() int { return len(coins) } -func (coins Coins) Less(i, j int) bool { return coins[i].Denom < coins[j].Denom } -func (coins Coins) Swap(i, j int) { coins[i], coins[j] = coins[j], coins[i] } - -var _ sort.Interface = Coins{} - -// Sort is a helper function to sort the set of coins inplace -func (coins Coins) Sort() Coins { - sort.Sort(coins) - return coins -} - //----------------------------------------------------------------------------- // Parsing var ( // Denominations can be 3 ~ 16 characters long. - reDnmString = `[a-z][a-z0-9]{2,15}` + reDnmString = `[a-z][a-z0-9]{0,9}(\-[a-z0-9]{3})?` reAmt = `[[:digit:]]+` - reDecAmt = `[[:digit:]]*\.[[:digit:]]+` + reDecAmt = `[[:digit:]]*\.?[[:digit:]]+` reSpc = `[[:space:]]*` reDnm = regexp.MustCompile(fmt.Sprintf(`^%s$`, reDnmString)) reCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, reDnmString)) @@ -615,56 +204,14 @@ func mustValidateDenom(denom string) { // ParseCoin parses a cli input for one coin type, returning errors if invalid. // This returns an error on an empty string as well. func ParseCoin(coinStr string) (coin Coin, err error) { - coinStr = strings.TrimSpace(coinStr) - - matches := reCoin.FindStringSubmatch(coinStr) - if matches == nil { - return Coin{}, fmt.Errorf("invalid coin expression: %s", coinStr) - } - - denomStr, amountStr := matches[2], matches[1] - - amount, ok := NewIntFromString(amountStr) - if !ok { - return Coin{}, fmt.Errorf("failed to parse coin amount: %s", amountStr) - } - - if err := validateDenom(denomStr); err != nil { - return Coin{}, fmt.Errorf("invalid denom cannot contain upper case characters or spaces: %s", err) - } - - return NewCoin(denomStr, amount), nil + return ParseDecCoin(coinStr) } // ParseCoins will parse out a list of coins separated by commas. // If nothing is provided, it returns nil Coins. // Returned coins are sorted. func ParseCoins(coinsStr string) (Coins, error) { - coinsStr = strings.TrimSpace(coinsStr) - if len(coinsStr) == 0 { - return nil, nil - } - - coinStrs := strings.Split(coinsStr, ",") - coins := make(Coins, len(coinStrs)) - for i, coinStr := range coinStrs { - coin, err := ParseCoin(coinStr) - if err != nil { - return nil, err - } - - coins[i] = coin - } - - // sort coins for determinism - coins.Sort() - - // validate coins before returning - if !coins.IsValid() { - return nil, fmt.Errorf("parseCoins invalid: %#v", coins) - } - - return coins, nil + return ParseDecCoins(coinsStr) } // findDup works on the assumption that coins is sorted diff --git a/types/coin_okchain.go b/types/coin_okchain.go new file mode 100644 index 000000000000..6cf766bffab1 --- /dev/null +++ b/types/coin_okchain.go @@ -0,0 +1,70 @@ +package types + +import ( + "fmt" + "math/big" +) + +//----------------------------------------------------------------------------- +// Coin: alias to DecCoin +type Coin = DecCoin + +//----------------------------------------------------------------------------- +// Coins: alias to DecCoins +type Coins = DecCoins + +//----------------------------------------------------------------------------- + +func NewCoin(denom string, amount Int) DecCoin { + return NewDecCoin(denom, amount) +} + +func NewInt64Coin(denom string, amount int64) DecCoin { + return NewCoin(denom, NewInt(amount)) +} + +func NewDecCoinsFromDec(denom string, amount Dec) DecCoins { + return DecCoins{NewDecCoinFromDec(denom, amount)} +} + +func (dec DecCoin) ToCoins() Coins { + return NewCoins(dec) +} + +// Round a decimal with precision, perform bankers rounding (gaussian rounding) +func (d Dec) RoundDecimal(precision int64) Dec { + precisionMul := NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(precision), nil)) + return newDecFromInt(d.MulInt(precisionMul).RoundInt()).QuoInt(precisionMul) +} + +func ValidateDenom(denom string) error { + return validateDenom(denom) +} + +func MustParseCoins(denom, amount string) Coins { + coins, err := ParseCoins(amount + denom) + if err != nil { + panic(err) + } + return coins +} + +func validate(denom string, amount Int) error { + if err := validateDenom(denom); err != nil { + return err + } + + if amount.LT(ZeroInt()) { + return fmt.Errorf("negative coin amount: %v", amount) + } + + return nil +} + +func GetSystemFee() Coin { + return NewDecCoinFromDec(DefaultBondDenom, NewDecWithPrec(125, 4)) +} + +func ZeroFee() Coin { + return NewCoin(DefaultBondDenom, ZeroInt()) +} diff --git a/types/coin_test.go b/types/coin_test.go index 5cbb3d8a41c6..fc8711ca8673 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -22,8 +22,8 @@ func TestCoin(t *testing.T) { require.Panics(t, func() { NewCoin(testDenom1, NewInt(-1)) }) require.Panics(t, func() { NewInt64Coin(strings.ToUpper(testDenom1), 10) }) require.Panics(t, func() { NewCoin(strings.ToUpper(testDenom1), NewInt(10)) }) - require.Equal(t, NewInt(5), NewInt64Coin(testDenom1, 5).Amount) - require.Equal(t, NewInt(5), NewCoin(testDenom1, NewInt(5)).Amount) + require.Equal(t, NewDec(5), NewInt64Coin(testDenom1, 5).Amount) + require.Equal(t, NewDec(5), NewCoin(testDenom1, NewInt(5)).Amount) } func TestIsEqualCoin(t *testing.T) { @@ -53,14 +53,14 @@ func TestCoinIsValid(t *testing.T) { coin Coin expectPass bool }{ - {Coin{testDenom1, NewInt(-1)}, false}, - {Coin{testDenom1, NewInt(0)}, true}, - {Coin{testDenom1, NewInt(1)}, true}, - {Coin{"Atom", NewInt(1)}, false}, - {Coin{"a", NewInt(1)}, false}, - {Coin{"a very long coin denom", NewInt(1)}, false}, - {Coin{"atOm", NewInt(1)}, false}, - {Coin{" ", NewInt(1)}, false}, + {Coin{testDenom1, NewDec(-1)}, false}, + {Coin{testDenom1, NewDec(0)}, true}, + {Coin{testDenom1, NewDec(1)}, true}, + {Coin{"Atom", NewDec(1)}, false}, + {Coin{"a", NewDec(1)}, true}, + {Coin{"a very long coin denom", NewDec(1)}, false}, + {Coin{"atOm", NewDec(1)}, false}, + {Coin{" ", NewDec(1)}, false}, } for i, tc := range cases { @@ -227,9 +227,9 @@ func TestEqualCoins(t *testing.T) { } func TestAddCoins(t *testing.T) { - zero := NewInt(0) - one := NewInt(1) - two := NewInt(2) + zero := NewDec(0) + one := NewDec(1) + two := NewDec(2) cases := []struct { inputOne Coins @@ -251,9 +251,9 @@ func TestAddCoins(t *testing.T) { } func TestSubCoins(t *testing.T) { - zero := NewInt(0) - one := NewInt(1) - two := NewInt(2) + zero := NewDec(0) + one := NewDec(1) + two := NewDec(2) testCases := []struct { inputOne Coins @@ -281,48 +281,48 @@ func TestSubCoins(t *testing.T) { func TestCoins(t *testing.T) { good := Coins{ - {"gas", NewInt(1)}, - {"mineral", NewInt(1)}, - {"tree", NewInt(1)}, + {"gas", NewDec(1)}, + {"mineral", NewDec(1)}, + {"tree", NewDec(1)}, } mixedCase1 := Coins{ - {"gAs", NewInt(1)}, - {"MineraL", NewInt(1)}, - {"TREE", NewInt(1)}, + {"gAs", NewDec(1)}, + {"MineraL", NewDec(1)}, + {"TREE", NewDec(1)}, } mixedCase2 := Coins{ - {"gAs", NewInt(1)}, - {"mineral", NewInt(1)}, + {"gAs", NewDec(1)}, + {"mineral", NewDec(1)}, } mixedCase3 := Coins{ - {"gAs", NewInt(1)}, + {"gAs", NewDec(1)}, } empty := NewCoins() badSort1 := Coins{ - {"tree", NewInt(1)}, - {"gas", NewInt(1)}, - {"mineral", NewInt(1)}, + {"tree", NewDec(1)}, + {"gas", NewDec(1)}, + {"mineral", NewDec(1)}, } // both are after the first one, but the second and third are in the wrong order badSort2 := Coins{ - {"gas", NewInt(1)}, - {"tree", NewInt(1)}, - {"mineral", NewInt(1)}, + {"gas", NewDec(1)}, + {"tree", NewDec(1)}, + {"mineral", NewDec(1)}, } badAmt := Coins{ - {"gas", NewInt(1)}, - {"tree", NewInt(0)}, - {"mineral", NewInt(1)}, + {"gas", NewDec(1)}, + {"tree", NewDec(0)}, + {"mineral", NewDec(1)}, } dup := Coins{ - {"gas", NewInt(1)}, - {"gas", NewInt(1)}, - {"mineral", NewInt(1)}, + {"gas", NewDec(1)}, + {"gas", NewDec(1)}, + {"mineral", NewDec(1)}, } neg := Coins{ - {"gas", NewInt(-1)}, - {"mineral", NewInt(1)}, + {"gas", NewDec(-1)}, + {"mineral", NewDec(1)}, } assert.True(t, good.IsValid(), "Coins are valid") @@ -342,8 +342,8 @@ func TestCoins(t *testing.T) { } func TestCoinsGT(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.False(t, Coins{}.IsAllGT(Coins{})) assert.True(t, Coins{{testDenom1, one}}.IsAllGT(Coins{})) @@ -354,8 +354,8 @@ func TestCoinsGT(t *testing.T) { } func TestCoinsLT(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.False(t, Coins{}.IsAllLT(Coins{})) assert.False(t, Coins{{testDenom1, one}}.IsAllLT(Coins{})) @@ -369,8 +369,8 @@ func TestCoinsLT(t *testing.T) { } func TestCoinsLTE(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.True(t, Coins{}.IsAllLTE(Coins{})) assert.False(t, Coins{{testDenom1, one}}.IsAllLTE(Coins{})) @@ -384,7 +384,7 @@ func TestCoinsLTE(t *testing.T) { } func TestParse(t *testing.T) { - one := NewInt(1) + one := NewDec(1) cases := []struct { input string @@ -393,16 +393,16 @@ func TestParse(t *testing.T) { }{ {"", true, nil}, {"1foo", true, Coins{{"foo", one}}}, - {"10bar", true, Coins{{"bar", NewInt(10)}}}, - {"99bar,1foo", true, Coins{{"bar", NewInt(99)}, {"foo", one}}}, - {"98 bar , 1 foo ", true, Coins{{"bar", NewInt(98)}, {"foo", one}}}, - {" 55\t \t bling\n", true, Coins{{"bling", NewInt(55)}}}, - {"2foo, 97 bar", true, Coins{{"bar", NewInt(97)}, {"foo", NewInt(2)}}}, - {"5 mycoin,", false, nil}, // no empty coins in a list - {"2 3foo, 97 bar", false, nil}, // 3foo is invalid coin name - {"11me coin, 12you coin", false, nil}, // no spaces in coin names - {"1.2btc", false, nil}, // amount must be integer - {"5foo-bar", false, nil}, // once more, only letters in coin name + {"10bar", true, Coins{{"bar", NewDec(10)}}}, + {"99bar,1foo", true, Coins{{"bar", NewDec(99)}, {"foo", one}}}, + {"98 bar , 1 foo ", true, Coins{{"bar", NewDec(98)}, {"foo", one}}}, + {" 55\t \t bling\n", true, Coins{{"bling", NewDec(55)}}}, + {"2foo, 97 bar", true, Coins{{"bar", NewDec(97)}, {"foo", NewDec(2)}}}, + {"5 mycoin,", false, nil}, // no empty coins in a list + {"2 3foo, 97 bar", false, nil}, // 3foo is invalid coin name + {"11me coin, 12you coin", false, nil}, // no spaces in coin names + {"1.2btc", true, Coins{{"btc", MustNewDecFromStr("1.2")}}}, // amount must be integer + {"5foo-bar", true, Coins{{"foo-bar", NewDec(5)}}}, // once more, only letters in coin name } for tcIndex, tc := range cases { @@ -498,17 +498,17 @@ func TestAmountOf(t *testing.T) { } for _, tc := range cases { - assert.Equal(t, NewInt(tc.amountOfGAS), tc.coins.AmountOf("gas")) - assert.Equal(t, NewInt(tc.amountOfMINERAL), tc.coins.AmountOf("mineral")) - assert.Equal(t, NewInt(tc.amountOfTREE), tc.coins.AmountOf("tree")) + assert.Equal(t, NewDec(tc.amountOfGAS), tc.coins.AmountOf("gas")) + assert.Equal(t, NewDec(tc.amountOfMINERAL), tc.coins.AmountOf("mineral")) + assert.Equal(t, NewDec(tc.amountOfTREE), tc.coins.AmountOf("tree")) } assert.Panics(t, func() { cases[0].coins.AmountOf("Invalid") }) } func TestCoinsIsAnyGTE(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.False(t, Coins{}.IsAnyGTE(Coins{})) assert.False(t, Coins{{testDenom1, one}}.IsAnyGTE(Coins{})) @@ -527,8 +527,8 @@ func TestCoinsIsAnyGTE(t *testing.T) { } func TestCoinsIsAllGT(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.False(t, Coins{}.IsAllGT(Coins{})) assert.True(t, Coins{{testDenom1, one}}.IsAllGT(Coins{})) @@ -547,8 +547,8 @@ func TestCoinsIsAllGT(t *testing.T) { } func TestCoinsIsAllGTE(t *testing.T) { - one := NewInt(1) - two := NewInt(2) + one := NewDec(1) + two := NewDec(2) assert.True(t, Coins{}.IsAllGTE(Coins{})) assert.True(t, Coins{{testDenom1, one}}.IsAllGTE(Coins{})) @@ -654,7 +654,7 @@ func TestMarshalJSONCoins(t *testing.T) { }{ {"nil coins", nil, `[]`}, {"empty coins", Coins{}, `[]`}, - {"non-empty coins", NewCoins(NewInt64Coin("foo", 50)), `[{"denom":"foo","amount":"50"}]`}, + {"non-empty coins", NewCoins(NewInt64Coin("foo", 50)), `[{"denom":"foo","amount":"50.00000000"}]`}, } for _, tc := range testCases { diff --git a/types/dec_coin.go b/types/dec_coin.go index 40bc3da391e6..406e27ec3d69 100644 --- a/types/dec_coin.go +++ b/types/dec_coin.go @@ -45,14 +45,7 @@ func NewDecCoinFromDec(denom string, amount Dec) DecCoin { // NewDecCoinFromCoin creates a new DecCoin from a Coin. func NewDecCoinFromCoin(coin Coin) DecCoin { - if err := validate(coin.Denom, coin.Amount); err != nil { - panic(err) - } - - return DecCoin{ - Denom: coin.Denom, - Amount: coin.Amount.ToDec(), - } + return coin } // NewInt64DecCoin returns a new DecCoin with a denomination and amount. It will diff --git a/types/dec_coin_test.go b/types/dec_coin_test.go index 6a092c0b3a8d..e4e477c8771d 100644 --- a/types/dec_coin_test.go +++ b/types/dec_coin_test.go @@ -39,16 +39,16 @@ func TestNewDecCoinFromDec(t *testing.T) { func TestNewDecCoinFromCoin(t *testing.T) { require.NotPanics(t, func() { - NewDecCoinFromCoin(Coin{testDenom1, NewInt(5)}) + NewDecCoinFromCoin(Coin{testDenom1, NewDec(5)}) }) require.NotPanics(t, func() { - NewDecCoinFromCoin(Coin{testDenom1, NewInt(0)}) + NewDecCoinFromCoin(Coin{testDenom1, NewDec(0)}) }) - require.Panics(t, func() { - NewDecCoinFromCoin(Coin{strings.ToUpper(testDenom1), NewInt(5)}) + require.NotPanics(t, func() { + NewDecCoinFromCoin(Coin{strings.ToUpper(testDenom1), NewDec(5)}) }) - require.Panics(t, func() { - NewDecCoinFromCoin(Coin{testDenom1, NewInt(-5)}) + require.NotPanics(t, func() { + NewDecCoinFromCoin(Coin{testDenom1, NewDec(-5)}) }) } @@ -279,20 +279,20 @@ func TestParseDecCoins(t *testing.T) { expectedErr bool }{ {"", nil, false}, - {"4stake", nil, true}, - {"5.5atom,4stake", nil, true}, + {"4stake", DecCoins{{"stake", NewDec(4)}}, false}, + {"5.5atom,4stake", DecCoins{{"atom", mustNewDecFromStr(t, "5.5")}, {"stake", NewDec(4)}}, false}, {"0.0stake", nil, true}, {"0.004STAKE", nil, true}, { "0.004stake", - DecCoins{NewDecCoinFromDec("stake", NewDecWithPrec(4000000000000000, Precision))}, + DecCoins{{"stake", mustNewDecFromStr(t, "0.004")}}, false, }, { "5.04atom,0.004stake", DecCoins{ - NewDecCoinFromDec("atom", NewDecWithPrec(5040000000000000000, Precision)), - NewDecCoinFromDec("stake", NewDecWithPrec(4000000000000000, Precision)), + {"atom", mustNewDecFromStr(t, "5.04")}, + {"stake", mustNewDecFromStr(t, "0.004")}, }, false, }, @@ -320,7 +320,7 @@ func TestDecCoinsString(t *testing.T) { NewDecCoinFromDec("atom", NewDecWithPrec(5040000000000000000, Precision)), NewDecCoinFromDec("stake", NewDecWithPrec(4000000000000000, Precision)), }, - "5.040000000000000000atom,0.004000000000000000stake", + "50400000000.00000000atom,40000000.00000000stake", }, } diff --git a/types/decimal.go b/types/decimal.go index c7c5f197d83e..6c7cd05f0585 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -17,7 +17,7 @@ type Dec struct { // number of decimal places const ( - Precision = 18 + Precision = 8 // bytes required to represent the above precision // Ceiling[Log2[999 999 999 999 999 999]] @@ -99,13 +99,13 @@ func NewDecFromBigIntWithPrec(i *big.Int, prec int64) Dec { // create a new Dec from big integer assuming whole numbers // CONTRACT: prec <= Precision -func NewDecFromInt(i Int) Dec { - return NewDecFromIntWithPrec(i, 0) +func newDecFromInt(i Int) Dec { + return newDecFromIntWithPrec(i, 0) } // create a new Dec from big integer with decimal place at prec // CONTRACT: prec <= Precision -func NewDecFromIntWithPrec(i Int, prec int64) Dec { +func newDecFromIntWithPrec(i Int, prec int64) Dec { return Dec{ new(big.Int).Mul(i.BigInt(), precisionMultiplier(prec)), } diff --git a/types/decimal_test.go b/types/decimal_test.go index 301ddd0c4293..4091cbd6b307 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -22,7 +22,7 @@ func mustNewDecFromStr(t *testing.T, str string) (d Dec) { func TestPrecisionMultiplier(t *testing.T) { res := precisionMultiplier(5) - exp := big.NewInt(10000000000000) + exp := big.NewInt(1000) require.Equal(t, 0, res.Cmp(exp), "equality was incorrect, res %v, exp %v", res, exp) } @@ -81,14 +81,14 @@ func TestDecString(t *testing.T) { d Dec want string }{ - {NewDec(0), "0.000000000000000000"}, - {NewDec(1), "1.000000000000000000"}, - {NewDec(10), "10.000000000000000000"}, - {NewDec(12340), "12340.000000000000000000"}, - {NewDecWithPrec(12340, 4), "1.234000000000000000"}, - {NewDecWithPrec(12340, 5), "0.123400000000000000"}, - {NewDecWithPrec(12340, 8), "0.000123400000000000"}, - {NewDecWithPrec(1009009009009009009, 17), "10.090090090090090090"}, + {NewDec(0), "0.00000000"}, + {NewDec(1), "1.00000000"}, + {NewDec(10), "10.00000000"}, + {NewDec(12340), "12340.00000000"}, + {NewDecWithPrec(12340, 4), "1.23400000"}, + {NewDecWithPrec(12340, 5), "0.12340000"}, + {NewDecWithPrec(12340, 8), "0.00012340"}, + {NewDecWithPrec(1009009009009009009, 8), "10090090090.09009009"}, } for tcIndex, tc := range tests { assert.Equal(t, tc.want, tc.d.String(), "bad String(), index: %v", tcIndex) @@ -174,7 +174,7 @@ func TestArithmetic(t *testing.T) { {NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)}, {NewDec(3), NewDec(7), NewDec(21), NewDec(21), - NewDecWithPrec(428571428571428571, 18), NewDecWithPrec(428571428571428572, 18), NewDecWithPrec(428571428571428571, 18), + NewDecWithPrec(42857143, 8), NewDecWithPrec(42857143, 8), NewDecWithPrec(42857142, 8), NewDec(10), NewDec(-4)}, {NewDec(2), NewDec(4), NewDec(8), NewDec(8), NewDecWithPrec(5, 1), NewDecWithPrec(5, 1), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)}, @@ -184,7 +184,7 @@ func TestArithmetic(t *testing.T) { {NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2), NewDecWithPrec(225, 2), NewDec(1), NewDec(1), NewDec(1), NewDec(3), NewDec(0)}, {NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8), NewDecWithPrec(1109889, 8), - MustNewDecFromStr("10.009009009009009009"), MustNewDecFromStr("10.009009009009009010"), MustNewDecFromStr("10.009009009009009009"), + MustNewDecFromStr("10.00900901"), MustNewDecFromStr("10.00900901"), MustNewDecFromStr("10.00900900"), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)}, } @@ -281,14 +281,14 @@ func TestDecMarshalJSON(t *testing.T) { want string wantErr bool // if wantErr = false, will also attempt unmarshaling }{ - {"zero", decimal(0), "\"0.000000000000000000\"", false}, - {"one", decimal(1), "\"0.000000000000000001\"", false}, - {"ten", decimal(10), "\"0.000000000000000010\"", false}, - {"12340", decimal(12340), "\"0.000000000000012340\"", false}, - {"zeroInt", NewDec(0), "\"0.000000000000000000\"", false}, - {"oneInt", NewDec(1), "\"1.000000000000000000\"", false}, - {"tenInt", NewDec(10), "\"10.000000000000000000\"", false}, - {"12340Int", NewDec(12340), "\"12340.000000000000000000\"", false}, + {"zero", decimal(0), "\"0.00000000\"", false}, + {"one", decimal(1), "\"0.00000001\"", false}, + {"ten", decimal(10), "\"0.00000010\"", false}, + {"12340", decimal(12340), "\"0.00012340\"", false}, + {"zeroInt", NewDec(0), "\"0.00000000\"", false}, + {"oneInt", NewDec(1), "\"1.00000000\"", false}, + {"tenInt", NewDec(10), "\"10.00000000\"", false}, + {"12340Int", NewDec(12340), "\"12340.00000000\"", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -380,7 +380,7 @@ func TestStringOverflow(t *testing.T) { require.NoError(t, err) dec3 := dec1.Add(dec2) require.Equal(t, - "19844653375691057515930281852116324640.000000000000000000", + "19844653375691057515930281852116324640.00000000", dec3.String(), ) } @@ -407,14 +407,14 @@ func TestDecCeil(t *testing.T) { input Dec expected Dec }{ - {NewDecWithPrec(1000000000000000, Precision), NewDec(1)}, // 0.001 => 1.0 - {NewDecWithPrec(-1000000000000000, Precision), ZeroDec()}, // -0.001 => 0.0 - {ZeroDec(), ZeroDec()}, // 0.0 => 0.0 - {NewDecWithPrec(900000000000000000, Precision), NewDec(1)}, // 0.9 => 1.0 - {NewDecWithPrec(4001000000000000000, Precision), NewDec(5)}, // 4.001 => 5.0 - {NewDecWithPrec(-4001000000000000000, Precision), NewDec(-4)}, // -4.001 => -4.0 - {NewDecWithPrec(4700000000000000000, Precision), NewDec(5)}, // 4.7 => 5.0 - {NewDecWithPrec(-4700000000000000000, Precision), NewDec(-4)}, // -4.7 => -4.0 + {NewDecWithPrec(100000, Precision), NewDec(1)}, // 0.001 => 1.0 + {NewDecWithPrec(-100000, Precision), ZeroDec()}, // -0.001 => 0.0 + {ZeroDec(), ZeroDec()}, // 0.0 => 0.0 + {NewDecWithPrec(90000000, Precision), NewDec(1)}, // 0.9 => 1.0 + {NewDecWithPrec(400100000, Precision), NewDec(5)}, // 4.001 => 5.0 + {NewDecWithPrec(-400100000, Precision), NewDec(-4)}, // -4.001 => -4.0 + {NewDecWithPrec(470000000, Precision), NewDec(5)}, // 4.7 => 5.0 + {NewDecWithPrec(-470000000, Precision), NewDec(-4)}, // -4.7 => -4.0 } for i, tc := range testCases { @@ -428,17 +428,17 @@ func TestDecSortableBytes(t *testing.T) { d Dec want []byte }{ - {NewDec(0), []byte("000000000000000000.000000000000000000")}, - {NewDec(1), []byte("000000000000000001.000000000000000000")}, - {NewDec(10), []byte("000000000000000010.000000000000000000")}, - {NewDec(12340), []byte("000000000000012340.000000000000000000")}, - {NewDecWithPrec(12340, 4), []byte("000000000000000001.234000000000000000")}, - {NewDecWithPrec(12340, 5), []byte("000000000000000000.123400000000000000")}, - {NewDecWithPrec(12340, 8), []byte("000000000000000000.000123400000000000")}, - {NewDecWithPrec(1009009009009009009, 17), []byte("000000000000000010.090090090090090090")}, - {NewDecWithPrec(-1009009009009009009, 17), []byte("-000000000000000010.090090090090090090")}, - {NewDec(1000000000000000000), []byte("max")}, - {NewDec(-1000000000000000000), []byte("--")}, + {NewDec(0), []byte("00000000.00000000")}, + {NewDec(1), []byte("00000001.00000000")}, + {NewDec(10), []byte("00000010.00000000")}, + {NewDec(12340), []byte("00012340.00000000")}, + {NewDecWithPrec(12340, 4), []byte("00000001.23400000")}, + {NewDecWithPrec(12340, 5), []byte("00000000.12340000")}, + {NewDecWithPrec(12340, 8), []byte("00000000.00012340")}, + {NewDecWithPrec(100909009, 7), []byte("00000010.09090090")}, + {NewDecWithPrec(-100909009, 7), []byte("-00000010.09090090")}, + {NewDec(100000000), []byte("max")}, + {NewDec(-100000000), []byte("--")}, } for tcIndex, tc := range tests { assert.Equal(t, tc.want, SortableDecBytes(tc.d), "bad String(), index: %v", tcIndex) diff --git a/types/denom.go b/types/denom.go index 73d396644523..6881f1b07976 100644 --- a/types/denom.go +++ b/types/denom.go @@ -37,28 +37,3 @@ func GetDenomUnit(denom string) (Dec, bool) { return unit, true } - -// ConvertCoin attempts to convert a coin to a given denomination. If the given -// denomination is invalid or if neither denomination is registered, an error -// is returned. -func ConvertCoin(coin Coin, denom string) (Coin, error) { - if err := validateDenom(denom); err != nil { - return Coin{}, err - } - - srcUnit, ok := GetDenomUnit(coin.Denom) - if !ok { - return Coin{}, fmt.Errorf("source denom not registered: %s", coin.Denom) - } - - dstUnit, ok := GetDenomUnit(denom) - if !ok { - return Coin{}, fmt.Errorf("destination denom not registered: %s", denom) - } - - if srcUnit.Equal(dstUnit) { - return NewCoin(denom, coin.Amount), nil - } - - return NewCoin(denom, coin.Amount.ToDec().Mul(srcUnit.Quo(dstUnit)).TruncateInt()), nil -} diff --git a/types/denom_test.go b/types/denom_test.go index de6437994bef..8310af66dba0 100644 --- a/types/denom_test.go +++ b/types/denom_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/require" @@ -41,7 +42,7 @@ func TestConvertCoins(t *testing.T) { uatomUnit := NewDecWithPrec(1, 6) // 10^-6 (micro) require.NoError(t, RegisterDenom(uatom, uatomUnit)) - natomUnit := NewDecWithPrec(1, 9) // 10^-9 (nano) + natomUnit := NewDecWithPrec(1, 8) // 10^-8 require.NoError(t, RegisterDenom(natom, natomUnit)) testCases := []struct { @@ -54,20 +55,20 @@ func TestConvertCoins(t *testing.T) { {NewCoin(atom, ZeroInt()), "foo", Coin{}, true}, {NewCoin(atom, ZeroInt()), "FOO", Coin{}, true}, - {NewCoin(atom, NewInt(5)), matom, NewCoin(matom, NewInt(5000)), false}, // atom => matom - {NewCoin(atom, NewInt(5)), uatom, NewCoin(uatom, NewInt(5000000)), false}, // atom => uatom - {NewCoin(atom, NewInt(5)), natom, NewCoin(natom, NewInt(5000000000)), false}, // atom => natom + {NewCoin(atom, NewInt(5)), matom, NewCoin(matom, NewInt(5000)), false}, // atom => matom + {NewCoin(atom, NewInt(5)), uatom, NewCoin(uatom, NewInt(5000000)), false}, // atom => uatom + {NewCoin(atom, NewInt(5)), natom, NewCoin(natom, NewInt(500000000)), false}, // atom => natom - {NewCoin(uatom, NewInt(5000000)), matom, NewCoin(matom, NewInt(5000)), false}, // uatom => matom - {NewCoin(uatom, NewInt(5000000)), natom, NewCoin(natom, NewInt(5000000000)), false}, // uatom => natom - {NewCoin(uatom, NewInt(5000000)), atom, NewCoin(atom, NewInt(5)), false}, // uatom => atom + {NewCoin(uatom, NewInt(5000000)), matom, NewCoin(matom, NewInt(5000)), false}, // uatom => matom + {NewCoin(uatom, NewInt(5000000)), natom, NewCoin(natom, NewInt(500000000)), false}, // uatom => natom + {NewCoin(uatom, NewInt(5000000)), atom, NewCoin(atom, NewInt(5)), false}, // uatom => atom - {NewCoin(matom, NewInt(5000)), natom, NewCoin(natom, NewInt(5000000000)), false}, // matom => natom - {NewCoin(matom, NewInt(5000)), uatom, NewCoin(uatom, NewInt(5000000)), false}, // matom => uatom + {NewCoin(matom, NewInt(5000)), natom, NewCoin(natom, NewInt(500000000)), false}, // matom => natom + {NewCoin(matom, NewInt(5000)), uatom, NewCoin(uatom, NewInt(5000000)), false}, // matom => uatom } for i, tc := range testCases { - res, err := ConvertCoin(tc.input, tc.denom) + res, err := convertCoin(tc.input, tc.denom) require.Equal( t, tc.expErr, err != nil, "unexpected error; tc: #%d, input: %s, denom: %s", i+1, tc.input, tc.denom, @@ -81,3 +82,25 @@ func TestConvertCoins(t *testing.T) { // reset registration denomUnits = map[string]Dec{} } + +func convertCoin(coin Coin, denom string) (Coin, error) { + if err := ValidateDenom(denom); err != nil { + return Coin{}, err + } + + srcUnit, ok := GetDenomUnit(coin.Denom) + if !ok { + return Coin{}, fmt.Errorf("source denom not registered: %s", coin.Denom) + } + + dstUnit, ok := GetDenomUnit(denom) + if !ok { + return Coin{}, fmt.Errorf("destination denom not registered: %s", denom) + } + + if srcUnit.Equal(dstUnit) { + return NewDecCoinFromDec(denom, coin.Amount), nil + } + + return NewCoin(denom, coin.Amount.Mul(srcUnit.Quo(dstUnit)).TruncateInt()), nil +} diff --git a/types/events.go b/types/events.go index bbe51819c5f3..760eae1612b5 100644 --- a/types/events.go +++ b/types/events.go @@ -138,6 +138,7 @@ var ( AttributeKeyModule = "module" AttributeKeySender = "sender" AttributeKeyAmount = "amount" + AttributeKeyFee = "fee" ) type ( diff --git a/types/int.go b/types/int.go index 41a6efef74c7..c0007d13bcd0 100644 --- a/types/int.go +++ b/types/int.go @@ -161,7 +161,7 @@ func OneInt() Int { return Int{big.NewInt(1)} } // ToDec converts Int to Dec func (i Int) ToDec() Dec { - return NewDecFromInt(i) + return newDecFromInt(i) } // Int64 converts Int to int64 diff --git a/types/rest/rest.go b/types/rest/rest.go index 146faaede130..42c0f52817eb 100644 --- a/types/rest/rest.go +++ b/types/rest/rest.go @@ -318,7 +318,8 @@ func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, resp } w.Header().Set("Content-Type", "application/json") - _, _ = w.Write(output) + _, _ = w.Write(result) + _ = output } // ParseHTTPArgsWithLimit parses the request's URL and returns a slice containing diff --git a/types/rest/rest_test.go b/types/rest/rest_test.go index 29d24af27dac..d32db1d5a7a9 100644 --- a/types/rest/rest_test.go +++ b/types/rest/rest_test.go @@ -22,7 +22,7 @@ import ( type mockResponseWriter struct{} func TestBaseReqValidateBasic(t *testing.T) { - fromAddr := "cosmos1cq0sxam6x4l0sv9yz3a2vlqhdhvt2k6jtgcse0" + fromAddr := "okchain1cq0sxam6x4l0sv9yz3a2vlqhdhvt2k6jfjzq0v" tenstakes, err := types.ParseCoins("10stake") require.NoError(t, err) onestake, err := types.ParseDecCoins("1.0stake") @@ -186,9 +186,9 @@ func TestProcessPostResponse(t *testing.T) { require.Nil(t, err) respNoIndent := NewResponseWithHeight(height, jsonNoIndent) respWithIndent := NewResponseWithHeight(height, jsonWithIndent) - expectedNoIndent, err := ctx.Codec.MarshalJSON(respNoIndent) + expectedNoIndent, err := ctx.Codec.MarshalJSON(respNoIndent.Result) require.Nil(t, err) - expectedWithIndent, err := ctx.Codec.MarshalJSONIndent(respWithIndent, "", " ") + expectedWithIndent, err := ctx.Codec.MarshalJSONIndent(respWithIndent.Result, "", " ") require.Nil(t, err) // check that negative height writes an error diff --git a/types/result.go b/types/result.go index 41a31b84ba3c..d4ef7a690f72 100644 --- a/types/result.go +++ b/types/result.go @@ -241,13 +241,13 @@ func (r TxResponse) String() string { sb.WriteString(fmt.Sprintf(" Info: %s\n", r.Info)) } - if r.GasWanted != 0 { - sb.WriteString(fmt.Sprintf(" GasWanted: %d\n", r.GasWanted)) - } - - if r.GasUsed != 0 { - sb.WriteString(fmt.Sprintf(" GasUsed: %d\n", r.GasUsed)) - } + //if r.GasWanted != 0 { + // sb.WriteString(fmt.Sprintf(" GasWanted: %d\n", r.GasWanted)) + //} + // + //if r.GasUsed != 0 { + // sb.WriteString(fmt.Sprintf(" GasUsed: %d\n", r.GasUsed)) + //} if r.Codespace != "" { sb.WriteString(fmt.Sprintf(" Codespace: %s\n", r.Codespace)) diff --git a/types/staking.go b/types/staking.go index 9f623b3575e6..03ba3f4b5812 100644 --- a/types/staking.go +++ b/types/staking.go @@ -6,9 +6,8 @@ import ( // staking constants const ( - // default bond denomination - DefaultBondDenom = "stake" + DefaultBondDenom = "okt" // Delay, in blocks, between when validator updates are returned to the // consensus-engine and when they are applied. For example, if @@ -23,7 +22,7 @@ const ( ) // PowerReduction is the amount of staking tokens required for 1 unit of consensus-engine power -var PowerReduction = NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(6), nil)) +var PowerReduction = NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil)) // TokensToConsensusPower - convert input tokens to potential consensus-engine power func TokensToConsensusPower(tokens Int) int64 { diff --git a/version/version.go b/version/version.go index 9429a9c1f9f1..6b7e602ab63a 100644 --- a/version/version.go +++ b/version/version.go @@ -34,37 +34,55 @@ var ( // commit Commit = "" // build tags - BuildTags = "" + BuildTags = "" + CosmosSDK = "" + Tendermint = "" + VendorDirHash = "" ) // Info defines the application version information. type Info struct { - Name string `json:"name" yaml:"name"` - ServerName string `json:"server_name" yaml:"server_name"` - ClientName string `json:"client_name" yaml:"client_name"` - Version string `json:"version" yaml:"version"` - GitCommit string `json:"commit" yaml:"commit"` - BuildTags string `json:"build_tags" yaml:"build_tags"` - GoVersion string `json:"go" yaml:"go"` + Name string `json:"name" yaml:"name"` + ServerName string `json:"server_name" yaml:"server_name"` + ClientName string `json:"client_name" yaml:"client_name"` + Version string `json:"version" yaml:"version"` + GitCommit string `json:"commit" yaml:"commit"` + BuildTags string `json:"build_tags" yaml:"build_tags"` + GoVersion string `json:"go" yaml:"go"` + CosmosSDK string `json:"cosmos_sdk"` + Tendermint string `json:"tendermint"` + VendorDirHash string `json:"vendor_hash"` } -func NewInfo() Info { - return Info{ - Name: Name, - ServerName: ServerName, - ClientName: ClientName, - Version: Version, - GitCommit: Commit, - BuildTags: BuildTags, - GoVersion: fmt.Sprintf("go version %s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH), - } -} +//func NewInfo() Info { +// return Info{ +// Name: Name, +// ServerName: ServerName, +// ClientName: ClientName, +// Version: Version, +// GitCommit: Commit, +// BuildTags: BuildTags, +// GoVersion: fmt.Sprintf("go version %s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH), +// } +//} -func (vi Info) String() string { - return fmt.Sprintf(`%s: %s +func (v Info) String() string { + return fmt.Sprintf(`version: %s git commit: %s +vendor hash: %s build tags: %s -%s`, - vi.Name, vi.Version, vi.GitCommit, vi.BuildTags, vi.GoVersion, - ) +cosmos-sdk: %s +tendermint: %s +%s`, v.Version, v.GitCommit, v.VendorDirHash, v.BuildTags, v.CosmosSDK, v.Tendermint, v.GoVersion) +} + +func NewInfo() Info { + return Info{ + Version: Version, + CosmosSDK: CosmosSDK, + Tendermint: Tendermint, + GitCommit: Commit, + VendorDirHash: VendorDirHash, + BuildTags: BuildTags, + GoVersion: fmt.Sprintf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)} } diff --git a/x/auth/ante.go b/x/auth/ante.go index 9387b07ecd39..973b761ab443 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -35,7 +35,9 @@ type SignatureVerificationGasConsumer = func(meter sdk.GasMeter, sig []byte, pub // NewAnteHandler returns an AnteHandler that checks and increments sequence // numbers, checks signatures & account numbers, and deducts fees from the first // signer. -func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasConsumer SignatureVerificationGasConsumer) sdk.AnteHandler { +func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, + sigGasConsumer SignatureVerificationGasConsumer, validateMsgHandler ValidateMsgHandler, + isSystemFreeHandler IsSystemFreeHandler) sdk.AnteHandler { return func( ctx sdk.Context, tx sdk.Tx, simulate bool, ) (newCtx sdk.Context, res sdk.Result, abort bool) { @@ -55,17 +57,26 @@ func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasCon params := ak.GetParams(ctx) + isFree := false + if isSystemFreeHandler != nil { + isFree = isSystemFreeHandler(ctx, stdTx.GetMsgs()) + } + // Ensure that the provided fees meet a minimum threshold for the validator, // if this is a CheckTx. This is only for local mempool purposes, and thus // is only ran on check tx. - if ctx.IsCheckTx() && !simulate { + if ctx.IsCheckTx() && !simulate && !isFree { res := EnsureSufficientMempoolFees(ctx, stdTx.Fee) if !res.IsOK() { return newCtx, res, true } } - newCtx = SetGasMeter(simulate, ctx, stdTx.Fee.Gas) + if isFree { + newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) + } else { + newCtx = SetGasMeter(simulate, ctx, stdTx.Fee.Gas) + } // AnteHandlers must have their own defer/recover in order for the BaseApp // to know how much gas was used! This is because the GasMeter is created in @@ -117,7 +128,7 @@ func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasCon } // deduct the fees - if !stdTx.Fee.Amount.IsZero() { + if !stdTx.Fee.Amount.IsZero() && !isFree { res = DeductFees(supplyKeeper, newCtx, signerAccs[0], stdTx.Fee.Amount) if !res.IsOK() { return newCtx, res, true @@ -144,14 +155,36 @@ func NewAnteHandler(ak AccountKeeper, supplyKeeper types.SupplyKeeper, sigGasCon signBytes := GetSignBytes(newCtx.ChainID(), stdTx, signerAccs[i], isGenesis) signerAccs[i], res = processSig(newCtx, signerAccs[i], stdSigs[i], signBytes, simulate, params, sigGasConsumer) if !res.IsOK() { + ctx.Logger().Info("signData:" + string(signBytes)) return newCtx, res, true } ak.SetAccount(newCtx, signerAccs[i]) } + // *ABORT* the tx in case of failing to validate it in checkTx mode + if newCtx.IsCheckTx() && !simulate && validateMsgHandler != nil { + res := validateMsgHandler(newCtx, stdTx.GetMsgs()) + if !res.IsOK() { + return newCtx, res, true + } + } + + //stat actual system fee + actualSysFee := stdTx.Fee.Amount + if isFree { + actualSysFee = sdk.ZeroFee().ToCoins() + } + + //fire systemFee event + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyFee, actualSysFee.String()), + ), + ) // TODO: tx tags (?) - return newCtx, sdk.Result{GasWanted: stdTx.Fee.Gas}, false // continue... + return newCtx, sdk.Result{GasWanted: stdTx.Fee.Gas, Events: ctx.EventManager().Events()}, false } } @@ -227,7 +260,9 @@ func processSig( } if !simulate && !pubKey.VerifyBytes(signBytes, sig.Signature) { - return nil, sdk.ErrUnauthorized("signature verification failed; verify correct account sequence and chain-id").Result() + return nil, sdk.ErrUnauthorized("signature verification failed; " + + "verify correct account sequence, chain-id and message format. " + + "Expected message format: " + string(signBytes)).Result() } if err := acc.SetSequence(acc.GetSequence() + 1); err != nil { @@ -382,7 +417,7 @@ func EnsureSufficientMempoolFees(ctx sdk.Context, stdFee StdFee) sdk.Result { glDec := sdk.NewDec(int64(stdFee.Gas)) for i, gp := range minGasPrices { fee := gp.Amount.Mul(glDec) - requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + requiredFees[i] = sdk.NewDecCoinFromDec(gp.Denom, fee) } if !stdFee.Amount.IsAnyGTE(requiredFees) { diff --git a/x/auth/ante_okchain.go b/x/auth/ante_okchain.go new file mode 100644 index 000000000000..978afefeff43 --- /dev/null +++ b/x/auth/ante_okchain.go @@ -0,0 +1,9 @@ +package auth + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ValidateMsgHandler func(ctx sdk.Context, msgs []sdk.Msg) sdk.Result + +type IsSystemFreeHandler func(ctx sdk.Context, msgs []sdk.Msg) bool diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index 4faae8ea92ac..6117a0bd05ac 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -49,7 +49,7 @@ func TestAnteHandlerSigErrors(t *testing.T) { // setup input := setupTestInput() ctx := input.ctx - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) // keys and addresses priv1, _, addr1 := types.KeyTestPubAddr() @@ -97,7 +97,7 @@ func TestAnteHandlerSigErrors(t *testing.T) { func TestAnteHandlerAccountNumbers(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -154,7 +154,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(0) // keys and addresses @@ -210,7 +210,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { func TestAnteHandlerSequences(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -288,7 +288,7 @@ func TestAnteHandlerFees(t *testing.T) { // setup input := setupTestInput() ctx := input.ctx - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) // keys and addresses priv1, _, addr1 := types.KeyTestPubAddr() @@ -313,21 +313,21 @@ func TestAnteHandlerFees(t *testing.T) { checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds) require.True(t, input.sk.GetModuleAccount(ctx, types.FeeCollectorName).GetCoins().Empty()) - require.True(sdk.IntEq(t, input.ak.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewInt(149))) + require.True(sdk.DecEq(t, input.ak.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewDec(149))) acc1.SetCoins(sdk.NewCoins(sdk.NewInt64Coin("atom", 150))) input.ak.SetAccount(ctx, acc1) checkValidTx(t, anteHandler, ctx, tx, false) - require.True(sdk.IntEq(t, input.sk.GetModuleAccount(ctx, types.FeeCollectorName).GetCoins().AmountOf("atom"), sdk.NewInt(150))) - require.True(sdk.IntEq(t, input.ak.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewInt(0))) + require.True(sdk.DecEq(t, input.sk.GetModuleAccount(ctx, types.FeeCollectorName).GetCoins().AmountOf("atom"), sdk.NewDec(150))) + require.True(sdk.DecEq(t, input.ak.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewDec(0))) } // Test logic around memo gas consumption. func TestAnteHandlerMemoGas(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -367,7 +367,7 @@ func TestAnteHandlerMemoGas(t *testing.T) { func TestAnteHandlerMultiSigner(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -417,7 +417,7 @@ func TestAnteHandlerMultiSigner(t *testing.T) { func TestAnteHandlerBadSignBytes(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -441,7 +441,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { fee2 := types.NewTestStdFee() fee2.Gas += 100 fee3 := types.NewTestStdFee() - fee3.Amount[0].Amount = fee3.Amount[0].Amount.AddRaw(100) + fee3.Amount[0].Amount = fee3.Amount[0].Amount.Add(sdk.NewDec(100)) // test good tx and signBytes privs, accnums, seqs := []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0} @@ -494,7 +494,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { func TestAnteHandlerSetPubKey(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -690,7 +690,7 @@ func TestCountSubkeys(t *testing.T) { func TestAnteHandlerSigLimitExceeded(t *testing.T) { // setup input := setupTestInput() - anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer) + anteHandler := NewAnteHandler(input.ak, input.sk, DefaultSigVerificationGasConsumer, nil, nil) ctx := input.ctx.WithBlockHeight(1) // keys and addresses @@ -729,8 +729,8 @@ func TestEnsureSufficientMempoolFees(t *testing.T) { input := setupTestInput() ctx := input.ctx.WithMinGasPrices( sdk.DecCoins{ - sdk.NewDecCoinFromDec("photino", sdk.NewDecWithPrec(50000000000000, sdk.Precision)), // 0.0001photino - sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(10000000000000, sdk.Precision)), // 0.000001stake + sdk.NewDecCoinFromDec("photino", sdk.NewDecWithPrec(5000, sdk.Precision)), // 0.0001photino + sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(1000, sdk.Precision)), // 0.000001stake }, ) @@ -788,7 +788,7 @@ func TestCustomSignatureVerificationGasConsumer(t *testing.T) { default: return sdk.ErrInvalidPubKey(fmt.Sprintf("unrecognized public key type: %T", pubkey)).Result() } - }) + }, nil, nil) ctx := input.ctx.WithBlockHeight(1) // verify that an secp256k1 account gets rejected diff --git a/x/auth/cache_okchain.go b/x/auth/cache_okchain.go new file mode 100644 index 000000000000..086d0a0ca680 --- /dev/null +++ b/x/auth/cache_okchain.go @@ -0,0 +1,38 @@ +package auth + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Cache struct { + updatedAccAddress map[string]struct{} +} + +func NewCache() *Cache { + return &Cache{ + updatedAccAddress: make(map[string]struct{}), + } +} + +func (c *Cache) AddUpdatedAccount(acc Account) { + if _, ok := c.updatedAccAddress[acc.GetAddress().String()]; !ok { + c.updatedAccAddress[acc.GetAddress().String()] = struct{}{} + } +} + +func (c *Cache) Flush() { + c.updatedAccAddress = make(map[string]struct{}) +} + +// GetAllAccounts returns all accounts in the accountKeeper. +func (ak AccountKeeper) GetUpdatedAccAddress(ctx sdk.Context) (accs []sdk.AccAddress) { + for acc := range ak.cache.updatedAccAddress { + addr, err := sdk.AccAddressFromBech32(acc) + if err == nil { + accs = append(accs, addr) + } + } + + ak.cache.Flush() + return accs +} diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index 1ca8882136a8..a24bb173ed34 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -28,7 +28,7 @@ const ( eventFormat = "{eventType}.{eventAttribute}={value}" ) -// GetTxCmd returns the transaction commands for this module +// GetQueryCmd returns the transaction commands for this module func GetQueryCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: types.ModuleName, @@ -56,7 +56,7 @@ func GetAccountCmd(cdc *codec.Codec) *cobra.Command { key, err := sdk.AccAddressFromBech32(args[0]) if err != nil { - return err + return sdk.ErrInvalidAddress(fmt.Sprintf("invalid address:%s", args[0])) } if err := accGetter.EnsureExists(key); err != nil { diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index e6d958a5d9cd..4e3ca2835e39 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -22,7 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/types" ) -// GetSignCommand returns the sign command +// GetMultiSignCommand returns the sign command func GetMultiSignCommand(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "multisign [file] [name] [[signature]...]", diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index be094b6c69a4..6e57a63f8650 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -17,7 +17,7 @@ import ( ) // query accountREST Handler -func QueryAccountRequestHandlerFn(storeName string, cliCtx context.CLIContext) http.HandlerFunc { +func QueryAccountRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bech32addr := vars["address"] diff --git a/x/auth/client/rest/rest.go b/x/auth/client/rest/rest.go index 99acd4e5d441..933490faf18a 100644 --- a/x/auth/client/rest/rest.go +++ b/x/auth/client/rest/rest.go @@ -7,14 +7,9 @@ import ( ) // RegisterRoutes registers the auth module REST routes. -func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string) { - r.HandleFunc( - "/auth/accounts/{address}", QueryAccountRequestHandlerFn(storeName, cliCtx), - ).Methods("GET") -} +func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { + r.HandleFunc("/auth/accounts/{address}", QueryAccountRequestHandlerFn(cliCtx)).Methods("GET") -// RegisterTxRoutes registers all transaction routes on the provided router. -func RegisterTxRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(cliCtx)).Methods("GET") r.HandleFunc("/txs", QueryTxsRequestHandlerFn(cliCtx)).Methods("GET") r.HandleFunc("/txs", BroadcastTxRequest(cliCtx)).Methods("POST") diff --git a/x/auth/genesis_test.go b/x/auth/genesis_test.go new file mode 100644 index 000000000000..98673eb5410a --- /dev/null +++ b/x/auth/genesis_test.go @@ -0,0 +1,52 @@ +package auth + +import ( + "fmt" + "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" + "testing" +) + +const ( + defaultGenExportExpected = `{"params":{"max_memo_characters":"256","tx_sig_limit":"7","tx_size_cost_per_byte":"10","sig_verify_cost_ed25519":"590","sig_verify_cost_secp256k1":"1000"}}` + maxMemoCharactersExpected = uint64(512) + txSigLimitExpected = uint64(14) + txSizeCostPerByteExpected = uint64(20) + sigVerifyCostED25519Expected = uint64(1180) + sigVerifyCostSecp256k1Expected = uint64(2000) +) + +var ( + genExportExpected = fmt.Sprintf(`{"params":{"max_memo_characters":"%d","tx_sig_limit":"%d","tx_size_cost_per_byte":"%d","sig_verify_cost_ed25519":"%d","sig_verify_cost_secp256k1":"%d"}}`, + maxMemoCharactersExpected, txSigLimitExpected, txSizeCostPerByteExpected, sigVerifyCostED25519Expected, sigVerifyCostSecp256k1Expected) +) + +func TestInitGenesis(t *testing.T) { + input := setupTestInput() + ctx, accKeeper := input.ctx, input.ak + appModule := NewAppModule(accKeeper) + + // 1.check default export + require.Equal(t, defaultGenExportExpected, string(appModule.ExportGenesis(ctx))) + + // 2.change context + newParams := types.NewParams(maxMemoCharactersExpected, txSigLimitExpected, txSizeCostPerByteExpected, + sigVerifyCostED25519Expected, sigVerifyCostSecp256k1Expected) + accKeeper.SetParams(ctx, newParams) + + // 3.export again + genExport := appModule.ExportGenesis(ctx) + require.Equal(t, genExportExpected, string(genExport)) + + // 4.init again && check + newInput := setupTestInput() + newCtx, newAccKeeper := newInput.ctx, newInput.ak + newAppModule := NewAppModule(newAccKeeper) + newAppModule.InitGenesis(newCtx, genExport) + newParams = newAccKeeper.GetParams(newCtx) + require.Equal(t, maxMemoCharactersExpected, newParams.MaxMemoCharacters) + require.Equal(t, txSigLimitExpected, newParams.TxSigLimit) + require.Equal(t, txSizeCostPerByteExpected, newParams.TxSizeCostPerByte) + require.Equal(t, sigVerifyCostED25519Expected, newParams.SigVerifyCostED25519) + require.Equal(t, sigVerifyCostSecp256k1Expected, newParams.SigVerifyCostSecp256k1) +} diff --git a/x/auth/keeper.go b/x/auth/keeper.go index f70d4430552d..ec51cda2e1cb 100644 --- a/x/auth/keeper.go +++ b/x/auth/keeper.go @@ -25,6 +25,9 @@ type AccountKeeper struct { // The codec codec for binary encoding/decoding of accounts. cdc *codec.Codec + //The cache is used to record account which is dirty. + cache *Cache + paramSubspace subspace.Subspace } @@ -40,6 +43,7 @@ func NewAccountKeeper( proto: proto, cdc: cdc, paramSubspace: paramstore.WithKeyTable(types.ParamKeyTable()), + cache: NewCache(), } } @@ -103,6 +107,8 @@ func (ak AccountKeeper) SetAccount(ctx sdk.Context, acc exported.Account) { panic(err) } store.Set(types.AddressStoreKey(addr), bz) + + ak.cache.AddUpdatedAccount(acc) } // RemoveAccount removes an account for the account mapper store. diff --git a/x/auth/legacy/v0_36/migrate_test.go b/x/auth/legacy/v0_36/migrate_test.go index c552fc809e2f..64ec90d1a82c 100644 --- a/x/auth/legacy/v0_36/migrate_test.go +++ b/x/auth/legacy/v0_36/migrate_test.go @@ -1,9 +1,10 @@ package v0_36 import ( + "testing" + "github.com/cosmos/cosmos-sdk/types" v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" - "testing" "github.com/stretchr/testify/require" ) @@ -14,7 +15,7 @@ func TestMigrate(t *testing.T) { genesisState = Migrate(v034auth.GenesisState{ CollectedFees: types.Coins{ { - Amount: types.NewInt(10), + Amount: types.NewDec(10), Denom: "stake", }, }, diff --git a/x/auth/module.go b/x/auth/module.go index 138907ace0fc..db8112510518 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -44,7 +44,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { var data types.GenesisState if err := types.ModuleCdc.UnmarshalJSON(bz, &data); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %s", types.ModuleName, err) } return types.ValidateGenesis(data) @@ -52,7 +52,7 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { // register rest routes func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { - rest.RegisterRoutes(ctx, rtr, types.StoreKey) + rest.RegisterRoutes(ctx, rtr) } // get the root tx command of this module @@ -62,7 +62,8 @@ func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { // get the root query command of this module func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { - return cli.GetQueryCmd(cdc) + //return cli.GetQueryCmd(cdc) + return nil } //___________________________ diff --git a/x/auth/simulation/fake.go b/x/auth/simulation/fake.go index 18e528f7bcb0..157209af2d08 100644 --- a/x/auth/simulation/fake.go +++ b/x/auth/simulation/fake.go @@ -36,7 +36,7 @@ func SimulateDeductFee(ak auth.AccountKeeper, supplyKeeper types.SupplyKeeper) s denomIndex := r.Intn(len(initCoins)) randCoin := initCoins[denomIndex] - amt, err := randPositiveInt(r, randCoin.Amount) + amt, err := randPositiveInt(r, randCoin.Amount.RoundInt()) if err != nil { return opMsg, nil, nil } diff --git a/x/auth/test_common.go b/x/auth/test_common.go index 6cfaad5ec723..3034bc7016d2 100644 --- a/x/auth/test_common.go +++ b/x/auth/test_common.go @@ -66,7 +66,9 @@ func setupTestInput() testInput { ms.MountStoreWithDB(authCapKey, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) - ms.LoadLatestVersion() + if err := ms.LoadLatestVersion(); err != nil { + panic(err) + } ps := subspace.NewSubspace(cdc, keyParams, tkeyParams, types.DefaultParamspace) ak := NewAccountKeeper(cdc, authCapKey, ps, types.ProtoBaseAccount) diff --git a/x/auth/types/account.go b/x/auth/types/account.go index daaad1ecdad4..93396b51679b 100644 --- a/x/auth/types/account.go +++ b/x/auth/types/account.go @@ -236,8 +236,8 @@ func (bva BaseVestingAccount) spendableCoins(vestingCoins sdk.Coins) sdk.Coins { delVestingAmt := bva.DelegatedVesting.AmountOf(coin.Denom) // compute min((BC + DV) - V, BC) per the specification - min := sdk.MinInt(baseAmt.Add(delVestingAmt).Sub(vestingAmt), baseAmt) - spendableCoin := sdk.NewCoin(coin.Denom, min) + min := sdk.MinDec(baseAmt.Add(delVestingAmt).Sub(vestingAmt), baseAmt) + spendableCoin := sdk.NewDecCoinFromDec(coin.Denom, min) if !spendableCoin.IsZero() { spendableCoins = spendableCoins.Add(sdk.Coins{spendableCoin}) @@ -272,16 +272,16 @@ func (bva *BaseVestingAccount) trackDelegation(vestingCoins, amount sdk.Coins) { // compute x and y per the specification, where: // X := min(max(V - DV, 0), D) // Y := D - X - x := sdk.MinInt(sdk.MaxInt(vestingAmt.Sub(delVestingAmt), sdk.ZeroInt()), coin.Amount) + x := sdk.MinDec(sdk.MaxDec(vestingAmt.Sub(delVestingAmt), sdk.ZeroDec()), coin.Amount) y := coin.Amount.Sub(x) if !x.IsZero() { - xCoin := sdk.NewCoin(coin.Denom, x) + xCoin := sdk.NewDecCoinFromDec(coin.Denom, x) bva.DelegatedVesting = bva.DelegatedVesting.Add(sdk.Coins{xCoin}) } if !y.IsZero() { - yCoin := sdk.NewCoin(coin.Denom, y) + yCoin := sdk.NewDecCoinFromDec(coin.Denom, y) bva.DelegatedFree = bva.DelegatedFree.Add(sdk.Coins{yCoin}) } @@ -312,16 +312,16 @@ func (bva *BaseVestingAccount) TrackUndelegation(amount sdk.Coins) { // compute x and y per the specification, where: // X := min(DF, D) // Y := min(DV, D - X) - x := sdk.MinInt(delegatedFree, coin.Amount) - y := sdk.MinInt(delegatedVesting, coin.Amount.Sub(x)) + x := sdk.MinDec(delegatedFree, coin.Amount) + y := sdk.MinDec(delegatedVesting, coin.Amount.Sub(x)) if !x.IsZero() { - xCoin := sdk.NewCoin(coin.Denom, x) + xCoin := sdk.NewDecCoinFromDec(coin.Denom, x) bva.DelegatedFree = bva.DelegatedFree.Sub(sdk.Coins{xCoin}) } if !y.IsZero() { - yCoin := sdk.NewCoin(coin.Denom, y) + yCoin := sdk.NewDecCoinFromDec(coin.Denom, y) bva.DelegatedVesting = bva.DelegatedVesting.Sub(sdk.Coins{yCoin}) } @@ -430,8 +430,8 @@ func (cva ContinuousVestingAccount) GetVestedCoins(blockTime time.Time) sdk.Coin s := sdk.NewDec(x).Quo(sdk.NewDec(y)) for _, ovc := range cva.OriginalVesting { - vestedAmt := ovc.Amount.ToDec().Mul(s).RoundInt() - vestedCoins = append(vestedCoins, sdk.NewCoin(ovc.Denom, vestedAmt)) + vestedAmt := ovc.Amount.Mul(s) + vestedCoins = append(vestedCoins, sdk.NewDecCoinFromDec(ovc.Denom, vestedAmt)) } return vestedCoins diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go index 9e71b1127d46..19cacfe7017b 100644 --- a/x/auth/types/stdtx.go +++ b/x/auth/types/stdtx.go @@ -147,7 +147,7 @@ func (fee StdFee) Bytes() []byte { // originally part of the submitted transaction because the fee is computed // as fee = ceil(gasWanted * gasPrices). func (fee StdFee) GasPrices() sdk.DecCoins { - return sdk.NewDecCoins(fee.Amount).QuoDec(sdk.NewDec(int64(fee.Gas))) + return fee.Amount.QuoDec(sdk.NewDec(int64(fee.Gas))) } //__________________________________________________________ diff --git a/x/auth/types/stdtx_test.go b/x/auth/types/stdtx_test.go index 661db3fd4752..179e0dd7ece3 100644 --- a/x/auth/types/stdtx_test.go +++ b/x/auth/types/stdtx_test.go @@ -49,7 +49,7 @@ func TestStdSignBytes(t *testing.T) { }{ { args{"1234", 3, 6, defaultFee, []sdk.Msg{sdk.NewTestMsg(addr)}, "memo"}, - fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"50000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\"}", addr), + fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150.00000000\",\"denom\":\"atom\"}],\"gas\":\"50000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\"}", addr), }, } for i, tc := range tests { @@ -73,7 +73,7 @@ func TestTxValidateBasic(t *testing.T) { // require to fail validation upon invalid fee badFee := NewTestStdFee() - badFee.Amount[0].Amount = sdk.NewInt(-5) + badFee.Amount[0].Amount = sdk.NewDec(-5) tx := NewTestTx(ctx, nil, nil, nil, nil, badFee) err := tx.ValidateBasic() diff --git a/x/auth/types/txbuilder.go b/x/auth/types/txbuilder.go index b29d977fd468..9d2110ed0baa 100644 --- a/x/auth/types/txbuilder.go +++ b/x/auth/types/txbuilder.go @@ -188,11 +188,11 @@ func (bldr TxBuilder) BuildSignMsg(msgs []sdk.Msg) (StdSignMsg, error) { glDec := sdk.NewDec(int64(bldr.gas)) // Derive the fees based on the provided gas prices, where - // fee = ceil(gasPrice * gasLimit). + // fee = gasPrice * gasLimit. fees = make(sdk.Coins, len(bldr.gasPrices)) for i, gp := range bldr.gasPrices { fee := gp.Amount.Mul(glDec) - fees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + fees[i] = sdk.NewDecCoinFromDec(gp.Denom, fee) } } diff --git a/x/auth/types/txbuilder_test.go b/x/auth/types/txbuilder_test.go index 063401c8a4ba..9c8dd0bafe0c 100644 --- a/x/auth/types/txbuilder_test.go +++ b/x/auth/types/txbuilder_test.go @@ -66,7 +66,7 @@ func TestTxBuilderBuild(t *testing.T) { SimulateGas: false, ChainID: "test-chain", Memo: "hello from Voyager 2!", - GasPrices: sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDecWithPrec(10000, sdk.Precision))}, + GasPrices: sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDecWithPrec(1000, sdk.Precision))}, }, defaultMsg, StdSignMsg{ @@ -75,7 +75,7 @@ func TestTxBuilderBuild(t *testing.T) { Sequence: 1, Memo: "hello from Voyager 2!", Msgs: defaultMsg, - Fee: NewStdFee(200000, sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))}), + Fee: NewStdFee(200000, sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2))}), }, false, }, diff --git a/x/bank/genesis_test.go b/x/bank/genesis_test.go new file mode 100644 index 000000000000..c385e2752db8 --- /dev/null +++ b/x/bank/genesis_test.go @@ -0,0 +1,40 @@ +package bank + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +const ( + defaultGenExportExpected = `{"send_enabled":true}` + sendEnabledExpected = false +) + +var ( + genExportExpected = fmt.Sprintf(`{"send_enabled":%v}`, sendEnabledExpected) +) + +func TestInitGenesis(t *testing.T) { + input := setupTestInput() + ctx, accKeeper, bankKeeper := input.ctx, input.ak, input.bk + appModule := NewAppModule(bankKeeper, accKeeper) + + // 1.check default export + require.Equal(t, defaultGenExportExpected, string(appModule.ExportGenesis(ctx))) + + // 2.change context + bankKeeper.SetSendEnabled(ctx, sendEnabledExpected) + + // 3.export again + genExport := appModule.ExportGenesis(ctx) + require.Equal(t, genExportExpected, string(genExport)) + + // 4.init again && check + newInput := setupTestInput() + newCtx, newAccKeeper, newBankKeeper := newInput.ctx, newInput.ak, newInput.bk + newAppModule := NewAppModule(newBankKeeper, newAccKeeper) + newAppModule.InitGenesis(newCtx, genExport) + require.Equal(t, sendEnabledExpected, newBankKeeper.GetSendEnabled(newCtx)) +} diff --git a/x/bank/internal/keeper/keeper.go b/x/bank/internal/keeper/keeper.go index aa408c60236b..8578a82839bb 100644 --- a/x/bank/internal/keeper/keeper.go +++ b/x/bank/internal/keeper/keeper.go @@ -70,7 +70,7 @@ func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAcc _, hasNeg := oldCoins.SafeSub(amt) if hasNeg { return sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt), + fmt.Sprintf("insufficient account funds; %s is less than %s", oldCoins, amt), ) } @@ -184,7 +184,7 @@ func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.In } for _, in := range inputs { - _, err := keeper.SubtractCoins(ctx, in.Address, in.Coins) + _, err := keeper.SubtractCoins(ctx, in.Address, in.Coins) if err != nil { return err } @@ -258,13 +258,12 @@ func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, oldCoins = acc.GetCoins() spendableCoins = acc.SpendableCoins(ctx.BlockHeader().Time) } - // For non-vesting accounts, spendable coins will simply be the original coins. // So the check here is sufficient instead of subtracting from oldCoins. _, hasNeg := spendableCoins.SafeSub(amt) if hasNeg { return amt, sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", spendableCoins, amt), + fmt.Sprintf("insufficient account funds; %s is less than %s", spendableCoins, amt), ) } @@ -286,7 +285,7 @@ func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt if newCoins.IsAnyNegative() { return amt, sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt), + fmt.Sprintf("insufficient account funds; %s is less than %s", oldCoins, amt), ) } diff --git a/x/bank/internal/keeper/keeper_test.go b/x/bank/internal/keeper/keeper_test.go index 27a32c225ab0..e4c33bc508ac 100644 --- a/x/bank/internal/keeper/keeper_test.go +++ b/x/bank/internal/keeper/keeper_test.go @@ -139,7 +139,7 @@ func TestSendKeeper(t *testing.T) { // validate coins with invalid denoms or negative values cannot be sent // NOTE: We must use the Coin literal as the constructor does not allow // negative values. - err = sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{"FOOCOIN", sdk.NewInt(-5)}}) + err = sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{"FOOCOIN", sdk.NewDec(-5)}}) require.Error(t, err) } diff --git a/x/bank/internal/keeper/querier_test.go b/x/bank/internal/keeper/querier_test.go index 0d1d1cdee52b..2489f3245062 100644 --- a/x/bank/internal/keeper/querier_test.go +++ b/x/bank/internal/keeper/querier_test.go @@ -43,7 +43,7 @@ func TestBalances(t *testing.T) { require.Nil(t, err) require.NotNil(t, res) require.NoError(t, input.cdc.UnmarshalJSON(res, &coins)) - require.True(t, coins.AmountOf("foo").Equal(sdk.NewInt(10))) + require.True(t, coins.AmountOf("foo").Equal(sdk.NewDec(10))) } func TestQuerierRouteNotFound(t *testing.T) { diff --git a/x/bank/internal/types/msgs_test.go b/x/bank/internal/types/msgs_test.go index 2a09c1b9f728..15e5fedf9d6d 100644 --- a/x/bank/internal/types/msgs_test.go +++ b/x/bank/internal/types/msgs_test.go @@ -58,7 +58,7 @@ func TestMsgSendGetSignBytes(t *testing.T) { var msg = NewMsgSend(addr1, addr2, coins) res := msg.GetSignBytes() - expected := `{"type":"cosmos-sdk/MsgSend","value":{"amount":[{"amount":"10","denom":"atom"}],"from_address":"cosmos1d9h8qat57ljhcm","to_address":"cosmos1da6hgur4wsmpnjyg"}}` + expected := `{"type":"cosmos-sdk/MsgSend","value":{"amount":[{"amount":"10.00000000","denom":"atom"}],"from_address":"okchain1d9h8qat5h0q7xg","to_address":"okchain1da6hgur4wss2fvsy"}}` require.Equal(t, expected, string(res)) } @@ -224,7 +224,7 @@ func TestMsgMultiSendGetSignBytes(t *testing.T) { } res := msg.GetSignBytes() - expected := `{"type":"cosmos-sdk/MsgMultiSend","value":{"inputs":[{"address":"cosmos1d9h8qat57ljhcm","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmos1da6hgur4wsmpnjyg","coins":[{"amount":"10","denom":"atom"}]}]}}` + expected := `{"type":"cosmos-sdk/MsgMultiSend","value":{"inputs":[{"address":"okchain1d9h8qat5h0q7xg","coins":[{"amount":"10.00000000","denom":"atom"}]}],"outputs":[{"address":"okchain1da6hgur4wss2fvsy","coins":[{"amount":"10.00000000","denom":"atom"}]}]}}` require.Equal(t, expected, string(res)) } diff --git a/x/bank/module.go b/x/bank/module.go index fd79eb2f8d13..2499c1ce1e3c 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -41,7 +41,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { var data GenesisState if err := ModuleCdc.UnmarshalJSON(bz, &data); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %s", ModuleName, err) } return ValidateGenesis(data) diff --git a/x/bank/simulation.go b/x/bank/simulation.go index 85532502eaab..95a396cd646d 100644 --- a/x/bank/simulation.go +++ b/x/bank/simulation.go @@ -53,7 +53,7 @@ func createMsgSend(r *rand.Rand, ctx sdk.Context, accs []simulation.Account, map } denomIndex := r.Intn(len(initFromCoins)) - amt, goErr := simulation.RandPositiveInt(r, initFromCoins[denomIndex].Amount) + amt, goErr := simulation.RandPositiveInt(r, initFromCoins[denomIndex].Amount.RoundInt()) if goErr != nil { return fromAcc, "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, msg, false } @@ -148,7 +148,7 @@ func createSingleInputMsgMultiSend(r *rand.Rand, ctx sdk.Context, accs []simulat } denomIndex := r.Intn(len(initFromCoins)) - amt, goErr := simulation.RandPositiveInt(r, initFromCoins[denomIndex].Amount) + amt, goErr := simulation.RandPositiveInt(r, initFromCoins[denomIndex].Amount.RoundInt()) if goErr != nil { return fromAcc, "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, msg, false } diff --git a/x/bank/test_common.go b/x/bank/test_common.go new file mode 100644 index 000000000000..916755bf6078 --- /dev/null +++ b/x/bank/test_common.go @@ -0,0 +1,51 @@ +// nolint +package bank + +import ( + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/params" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + autypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/internal/types" + "github.com/cosmos/cosmos-sdk/x/params/subspace" +) + +type testInput struct { + cdc *codec.Codec + ctx sdk.Context + ak types.AccountKeeper + bk BaseKeeper +} + +func setupTestInput() testInput { + db := dbm.NewMemDB() + cdc := codec.New() + + authCapKey := sdk.NewKVStoreKey("authCapKey") + keyParams := sdk.NewKVStoreKey("subspace") + tkeyParams := sdk.NewTransientStoreKey("transient_subspace") + + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(authCapKey, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) + if err := ms.LoadLatestVersion(); err != nil { + panic(err) + } + + pk := params.NewKeeper(types.ModuleCdc, keyParams, tkeyParams, params.DefaultCodespace) + ps := subspace.NewSubspace(cdc, keyParams, tkeyParams, types.DefaultParamspace) + ak := auth.NewAccountKeeper(cdc, authCapKey, ps, autypes.ProtoBaseAccount) + bk := NewBaseKeeper(ak, pk.Subspace(DefaultParamspace), DefaultCodespace, nil) + + ctx := sdk.NewContext(ms, abci.Header{ChainID: "test-chain-id"}, false, log.NewNopLogger()) + bk.SetSendEnabled(ctx, true) + + return testInput{cdc: cdc, ctx: ctx, ak: ak, bk: bk} +} diff --git a/x/crisis/handler.go b/x/crisis/handler.go index 9ff52c2f339e..6b41c820916c 100644 --- a/x/crisis/handler.go +++ b/x/crisis/handler.go @@ -31,6 +31,7 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k constantFee := sdk.NewCoins(k.GetConstantFee(ctx)) if err := k.SendCoinsFromAccountToFeeCollector(ctx, msg.Sender, constantFee); err != nil { + fmt.Println(err) return err.Result() } diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index fa4a0f5670b2..c6dde2070433 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -29,7 +29,7 @@ func CreateTestInput(t *testing.T) (sdk.Context, crisis.Keeper, auth.AccountKeep paramSpace := paramsKeeper.Subspace(crisis.DefaultParamspace) crisisKeeper := crisis.NewKeeper(paramSpace, 1, supplyKeeper, auth.FeeCollectorName) - constantFee := sdk.NewInt64Coin("stake", 10000000) + constantFee := sdk.NewInt64Coin("okt", 10000000) crisisKeeper.SetConstantFee(ctx, constantFee) crisisKeeper.RegisterRoute(testModuleName, dummyRouteWhichPasses.Route, dummyRouteWhichPasses.Invar) @@ -49,7 +49,7 @@ func TestHandleMsgVerifyInvariantWithNotEnoughSenderCoins(t *testing.T) { ctx, crisisKeeper, accKeeper, _ := CreateTestInput(t) sender := addrs[0] coin := accKeeper.GetAccount(ctx, sender).GetCoins()[0] - excessCoins := sdk.NewCoin(coin.Denom, coin.Amount.AddRaw(1)) + excessCoins := sdk.NewDecCoinFromDec(coin.Denom, coin.Amount.Add(sdk.NewDec(1))) crisisKeeper.SetConstantFee(ctx, excessCoins) h := crisis.NewHandler(crisisKeeper) diff --git a/x/crisis/internal/types/genesis.go b/x/crisis/internal/types/genesis.go index b38fd67166fc..b1b6e67e43b9 100644 --- a/x/crisis/internal/types/genesis.go +++ b/x/crisis/internal/types/genesis.go @@ -21,7 +21,7 @@ func NewGenesisState(constantFee sdk.Coin) GenesisState { // DefaultGenesisState creates a default GenesisState object func DefaultGenesisState() GenesisState { return GenesisState{ - ConstantFee: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), + ConstantFee: sdk.NewDecCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), } } diff --git a/x/crisis/module.go b/x/crisis/module.go index 5a5ed1adedb1..1ba57f2b65e6 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -13,7 +13,6 @@ import ( "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/crisis/client/cli" "github.com/cosmos/cosmos-sdk/x/crisis/internal/keeper" "github.com/cosmos/cosmos-sdk/x/crisis/internal/types" ) @@ -57,7 +56,8 @@ func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {} // GetTxCmd returns the root tx command for the crisis module. func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { - return cli.GetTxCmd(cdc) + //return cli.GetTxCmd(cdc) + return nil } // GetQueryCmd returns no root query command for the crisis module. diff --git a/x/distribution/abci.go b/x/distribution/abci.go index de7df339e25a..0c19106964ed 100644 --- a/x/distribution/abci.go +++ b/x/distribution/abci.go @@ -2,6 +2,7 @@ package distribution import ( abci "github.com/tendermint/tendermint/abci/types" + tmtypes "github.com/tendermint/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" @@ -21,7 +22,7 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) // TODO this is Tendermint-dependent // ref https://github.com/cosmos/cosmos-sdk/issues/3095 - if ctx.BlockHeight() > 1 { + if ctx.BlockHeight() > tmtypes.GetStartBlockHeight() + 1 { previousProposer := k.GetPreviousProposerConsAddr(ctx) k.AllocateTokens(ctx, sumPreviousPrecommitPower, previousTotalPower, previousProposer, req.LastCommitInfo.GetVotes()) } diff --git a/x/distribution/client/cli/utils.go b/x/distribution/client/cli/utils.go index 286016250228..83cc12971fb3 100644 --- a/x/distribution/client/cli/utils.go +++ b/x/distribution/client/cli/utils.go @@ -14,7 +14,7 @@ type ( Description string `json:"description" yaml:"description"` Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"` Amount sdk.Coins `json:"amount" yaml:"amount"` - Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Deposit sdk.DecCoins `json:"deposit" yaml:"deposit"` } ) diff --git a/x/distribution/client/rest/utils.go b/x/distribution/client/rest/utils.go index 3f7a3d0020ba..1569e6d1a7b8 100644 --- a/x/distribution/client/rest/utils.go +++ b/x/distribution/client/rest/utils.go @@ -15,6 +15,6 @@ type ( Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"` Amount sdk.Coins `json:"amount" yaml:"amount"` Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"` - Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Deposit sdk.DecCoins `json:"deposit" yaml:"deposit"` } ) diff --git a/x/distribution/handler.go b/x/distribution/handler.go index ca047cec3672..53947d35fa2f 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -84,8 +84,8 @@ func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdraw } func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) sdk.Error { - switch c := content.(type) { + return func(ctx sdk.Context, content *govtypes.Proposal) sdk.Error { + switch c := content.Content.(type) { case types.CommunityPoolSpendProposal: return keeper.HandleCommunityPoolSpendProposal(ctx, k, c) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 43a659999a7c..852eefbd161f 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -23,7 +23,7 @@ func (k Keeper) AllocateTokens( // (and distributed to the previous proposer) feeCollector := k.supplyKeeper.GetModuleAccount(ctx, k.feeCollectorName) feesCollectedInt := feeCollector.GetCoins() - feesCollected := sdk.NewDecCoins(feesCollectedInt) + feesCollected := feesCollectedInt // transfer collected fees to the distribution module account err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, k.feeCollectorName, types.ModuleName, feesCollectedInt) diff --git a/x/distribution/keeper/fee_pool.go b/x/distribution/keeper/fee_pool.go index a16e8258c029..a0f60e54ed95 100644 --- a/x/distribution/keeper/fee_pool.go +++ b/x/distribution/keeper/fee_pool.go @@ -13,7 +13,7 @@ func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receive // NOTE the community pool isn't a module account, however its coins // are held in the distribution module account. Thus the community pool // must be reduced separately from the SendCoinsFromModuleToAccount call - newPool, negative := feePool.CommunityPool.SafeSub(sdk.NewDecCoins(amount)) + newPool, negative := feePool.CommunityPool.SafeSub(amount) if negative { return types.ErrBadDistribution(k.codespace) } diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 0f9b56199063..4b9be5d3b15d 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -118,7 +118,7 @@ func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddr // update outstanding outstanding := k.GetValidatorOutstandingRewards(ctx, valAddr) - k.SetValidatorOutstandingRewards(ctx, valAddr, outstanding.Sub(sdk.NewDecCoins(commission))) + k.SetValidatorOutstandingRewards(ctx, valAddr, outstanding.Sub(commission)) if !commission.IsZero() { accAddr := sdk.AccAddress(valAddr) diff --git a/x/distribution/types/proposal.go b/x/distribution/types/proposal.go index 0562d81df18d..a3c8955f8a05 100644 --- a/x/distribution/types/proposal.go +++ b/x/distribution/types/proposal.go @@ -16,10 +16,10 @@ const ( // Assert CommunityPoolSpendProposal implements govtypes.Content at compile-time var _ govtypes.Content = CommunityPoolSpendProposal{} -func init() { - govtypes.RegisterProposalType(ProposalTypeCommunityPoolSpend) - govtypes.RegisterProposalTypeCodec(CommunityPoolSpendProposal{}, "cosmos-sdk/CommunityPoolSpendProposal") -} +//func init() { +// govtypes.RegisterProposalType(ProposalTypeCommunityPoolSpend) +// govtypes.RegisterProposalTypeCodec(CommunityPoolSpendProposal{}, "cosmos-sdk/CommunityPoolSpendProposal") +//} // CommunityPoolSpendProposal spends from the community pool type CommunityPoolSpendProposal struct { diff --git a/x/genaccounts/genesis_test.go b/x/genaccounts/genesis_test.go new file mode 100644 index 000000000000..dac62b960b8b --- /dev/null +++ b/x/genaccounts/genesis_test.go @@ -0,0 +1,40 @@ +package genaccounts + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" + authType "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func TestGenesis(t *testing.T) { + config := setupTestInput() + genCoin := sdk.NewCoins(sdk.Coin{ + Denom: "okt", + Amount: sdk.NewDec(10000), + }) + + _, pubKey, addr := KeyTestPubAddr() + + genesisAccount := NewGenesisAccount( + authType.NewBaseAccount(addr, genCoin, pubKey, 0, 1)) + gaccs := make(GenesisState, 0) + gaccs = append(gaccs, genesisAccount) + InitGenesis(config.ctx, ModuleCdc, config.ak, gaccs) + + genesisState := ExportGenesis(config.ctx, config.ak) + + require.Equal(t, gaccs, genesisState) + + require.NotNil(t, genesisState) + require.Len(t, genesisState, 1) + + config.ak.IterateAccounts(config.ctx, + func(account authexported.Account) (stop bool) { + require.Equal(t, account, genesisAccount.ToAccount()) + return false + }) +} diff --git a/x/genaccounts/legacy/v0_36/migrate.go b/x/genaccounts/legacy/v0_36/migrate.go index d69aece98156..516647e040d8 100644 --- a/x/genaccounts/legacy/v0_36/migrate.go +++ b/x/genaccounts/legacy/v0_36/migrate.go @@ -30,13 +30,14 @@ const ( // genesis state. It deletes the governance base accounts and creates the new module accounts. // The remaining accounts are updated to the new GenesisAccount type from 0.36 func Migrate( - oldGenState v034accounts.GenesisState, fees sdk.Coins, communityPool sdk.DecCoins, + oldGenState v034accounts.GenesisState, fees sdk.Coins, communityPool sdk.DecCoins, lockCoins sdk.Coins, deposits []v034gov.DepositWithMetadata, vals v034staking.Validators, ubds []v034staking.UnbondingDelegation, - valOutRewards []v034distr.ValidatorOutstandingRewardsRecord, bondDenom, distrModuleName, govModuleName string, + valOutRewards []v034distr.ValidatorOutstandingRewardsRecord, bondDenom, distrModuleName, govModuleName, tokenModuleName string, ) GenesisState { depositedCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govDepositedCoins"))) burnedDepositCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins"))) + dexListDepositedCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govDexListDepositedCoins"))) bondedAmt := sdk.ZeroInt() notBondedAmt := sdk.ZeroInt() @@ -45,9 +46,10 @@ func Migrate( // coins from rejected proposals add six new module accounts: // distribution, gov, mint, fee collector, bonded and not bonded pool var ( - newGenState GenesisState - govCoins sdk.Coins - extraAccounts = 6 + newGenState GenesisState + govCoins sdk.Coins + dexListDeposited = sdk.Coins{} + extraAccounts = 7 ) for _, acc := range oldGenState { @@ -61,6 +63,11 @@ func Migrate( // remove gov burned deposits base account extraAccounts -= 1 + case acc.Address.Equals(dexListDepositedCoinsAccAddr): + // remove gov dexList deposits base account + dexListDeposited = acc.Coins + extraAccounts -= 1 + default: newGenState = append( newGenState, @@ -125,6 +132,7 @@ func Migrate( notBondedAddr := sdk.AccAddress(crypto.AddressHash([]byte(notBondedPoolName))) distrAddr := sdk.AccAddress(crypto.AddressHash([]byte(distrModuleName))) mintAddr := sdk.AccAddress(crypto.AddressHash([]byte(mintModuleName))) + tokenAddr := sdk.AccAddress(crypto.AddressHash([]byte(tokenModuleName))) // create module genesis accounts feeCollectorModuleAcc := NewGenesisAccount( @@ -157,12 +165,17 @@ func Migrate( sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, 0, 0, mintModuleName, []string{minter}, ) + tokenModuleAcc := NewGenesisAccount( + tokenAddr, dexListDeposited.Add(lockCoins), 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, tokenModuleName, []string{minter, burner}, + ) newGenState = append( newGenState, []GenesisAccount{ feeCollectorModuleAcc, govModuleAcc, distrModuleAcc, - bondedModuleAcc, notBondedModuleAcc, mintModuleAcc, + bondedModuleAcc, notBondedModuleAcc, mintModuleAcc, tokenModuleAcc, }..., ) diff --git a/x/genaccounts/legacy/v0_36/migrate_test.go b/x/genaccounts/legacy/v0_36/migrate_test.go index e3e3b9a900ac..2f736f89a2a8 100644 --- a/x/genaccounts/legacy/v0_36/migrate_test.go +++ b/x/genaccounts/legacy/v0_36/migrate_test.go @@ -1,6 +1,8 @@ package v0_36 import ( + "testing" + "github.com/cosmos/cosmos-sdk/types" v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" v034accounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34" @@ -8,7 +10,6 @@ import ( v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/secp256k1" - "testing" "github.com/stretchr/testify/require" ) @@ -56,6 +57,7 @@ var ( Amount: coins, }, } + tokenModuleName = "token" ) func TestMigrateEmptyRecord(t *testing.T) { @@ -80,6 +82,7 @@ func TestMigrateEmptyRecord(t *testing.T) { tt.args.accounts, types.Coins{}, types.DecCoins{}, + types.DecCoins{}, tt.args.deposits, v034staking.Validators{}, []v034staking.UnbondingDelegation{}, @@ -87,6 +90,7 @@ func TestMigrateEmptyRecord(t *testing.T) { types.DefaultBondDenom, v034distr.ModuleName, v034gov.ModuleName, + tokenModuleName, ) }) }) @@ -102,6 +106,7 @@ func TestMigrateWrongDeposit(t *testing.T) { }, types.Coins{}, types.DecCoins{}, + types.DecCoins{}, []v034gov.DepositWithMetadata{ { ProposalID: 1, @@ -118,6 +123,7 @@ func TestMigrateWrongDeposit(t *testing.T) { types.DefaultBondDenom, v034distr.ModuleName, v034gov.ModuleName, + tokenModuleName, ) }) } diff --git a/x/genaccounts/test_common.go b/x/genaccounts/test_common.go new file mode 100644 index 000000000000..ef66d043b32f --- /dev/null +++ b/x/genaccounts/test_common.go @@ -0,0 +1,54 @@ +package genaccounts + +import ( + "github.com/cosmos/cosmos-sdk/x/auth" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + autypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/genaccounts/internal/types" + "github.com/cosmos/cosmos-sdk/x/params/subspace" +) + +type testInput struct { + cdc *codec.Codec + ctx sdk.Context + ak types.AccountKeeper +} + +func setupTestInput() testInput { + db := dbm.NewMemDB() + cdc := codec.New() + codec.RegisterCrypto(cdc) + auth.RegisterCodec(cdc) + authCapKey := sdk.NewKVStoreKey("authCapKey") + keyParams := sdk.NewKVStoreKey("subspace") + tkeyParams := sdk.NewTransientStoreKey("transient_subspace") + + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(authCapKey, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) + if err := ms.LoadLatestVersion(); err != nil { + panic(err) + } + + ps := subspace.NewSubspace(cdc, keyParams, tkeyParams, "genaccounts") + ak := auth.NewAccountKeeper(cdc, authCapKey, ps, autypes.ProtoBaseAccount) + + ctx := sdk.NewContext(ms, abci.Header{ChainID: "test-chain-id"}, false, log.NewNopLogger()) + + return testInput{cdc: cdc, ctx: ctx, ak: ak} +} +func KeyTestPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { + key := secp256k1.GenPrivKey() + pub := key.PubKey() + addr := sdk.AccAddress(pub.Address()) + return key, pub, addr +} diff --git a/x/genutil/collect.go b/x/genutil/collect.go index 7145efb048a6..6561cc6051cc 100644 --- a/x/genutil/collect.go +++ b/x/genutil/collect.go @@ -145,10 +145,10 @@ func CollectStdTxs(cdc *codec.Codec, moniker, genTxsDir string, "account %v not in genesis.json: %+v", valAddr, addrMap) } - if delAcc.GetCoins().AmountOf(msg.Value.Denom).LT(msg.Value.Amount) { + if delAcc.GetCoins().AmountOf(sdk.DefaultBondDenom).LT(msg.MinSelfDelegation.ToDec()) { return appGenTxs, persistentPeers, fmt.Errorf( "insufficient fund for delegation %v: %v < %v", - delAcc.GetAddress(), delAcc.GetCoins().AmountOf(msg.Value.Denom), msg.Value.Amount, + delAcc.GetAddress(), delAcc.GetCoins().AmountOf(sdk.DefaultBondDenom), msg.MinSelfDelegation, ) } diff --git a/x/genutil/legacy/v036/migrate.go b/x/genutil/legacy/v036/migrate.go index 5ba4af490e36..c2eccc66b642 100644 --- a/x/genutil/legacy/v036/migrate.go +++ b/x/genutil/legacy/v036/migrate.go @@ -2,6 +2,7 @@ package v036 import ( "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36" v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" @@ -46,9 +47,9 @@ func Migrate(appState genutil.AppMap) genutil.AppMap { delete(appState, v034genAccounts.ModuleName) // delete old key in case the name changed appState[v036genAccounts.ModuleName] = v036Codec.MustMarshalJSON( v036genAccounts.Migrate( - genAccs, authGenState.CollectedFees, distrGenState.FeePool.CommunityPool, govGenState.Deposits, + genAccs, authGenState.CollectedFees, distrGenState.FeePool.CommunityPool, sdk.Coins{}, govGenState.Deposits, stakingGenState.Validators, stakingGenState.UnbondingDelegations, distrGenState.OutstandingRewards, - stakingGenState.Params.BondDenom, v036distr.ModuleName, v036gov.ModuleName, + stakingGenState.Params.BondDenom, v036distr.ModuleName, v036gov.ModuleName, "", ), ) } diff --git a/x/genutil/legacy/v036/migrate_test.go b/x/genutil/legacy/v036/migrate_test.go index 3909d3d4b6a6..f494509f68c8 100644 --- a/x/genutil/legacy/v036/migrate_test.go +++ b/x/genutil/legacy/v036/migrate_test.go @@ -15,7 +15,7 @@ var basic034Gov = []byte(` { "proposal_id": "1", "deposit": { - "depositor": "cosmos1grgelyng2v6v3t8z87wu3sxgt9m5s03xvslewd", + "depositor": "okchain1grgelyng2v6v3t8z87wu3sxgt9m5s03xw29fcw", "proposal_id": "1", "amount": [ { @@ -30,7 +30,7 @@ var basic034Gov = []byte(` { "proposal_id": "1", "vote": { - "voter": "cosmos1lktjhnzkpkz3ehrg8psvmwhafg56kfss5597tg", + "voter": "okchain1lktjhnzkpkz3ehrg8psvmwhafg56kfsskwlwat", "proposal_id": "1", "option": "Yes" } @@ -78,9 +78,9 @@ var basic034Gov = []byte(` "voting_period": "1209600000000000" }, "tally_params": { - "quorum": "0.400000000000000000", - "threshold": "0.500000000000000000", - "veto": "0.334000000000000000" + "quorum": "0.4", + "threshold": "0.5", + "veto": "0.334" } } `) diff --git a/x/genutil/utils_test.go b/x/genutil/utils_test.go index cb04c8f866b1..2061b947c324 100644 --- a/x/genutil/utils_test.go +++ b/x/genutil/utils_test.go @@ -17,5 +17,5 @@ func TestExportGenesisFileWithTime(t *testing.T) { defer cleanup() fname := filepath.Join(dir, "genesis.json") - require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage(""), time.Now())) + require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage("{}"), time.Now())) } diff --git a/x/gov/alias_okchain.go b/x/gov/alias_okchain.go new file mode 100644 index 000000000000..cc28497c86b5 --- /dev/null +++ b/x/gov/alias_okchain.go @@ -0,0 +1,7 @@ +package gov + +import "github.com/cosmos/cosmos-sdk/x/gov/types" + +var ( + NewTendermintParams = types.NewTendermintParams +) diff --git a/x/gov/client/cli/query.go b/x/gov/client/cli/query.go index 8dc4642e36b4..63e4fb5c968d 100644 --- a/x/gov/client/cli/query.go +++ b/x/gov/client/cli/query.go @@ -495,6 +495,10 @@ $ %s query gov params if err != nil { return err } + tmp, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/tendermint", queryRoute), nil) + if err != nil { + return err + } var tallyParams types.TallyParams cdc.MustUnmarshalJSON(tp, &tallyParams) @@ -502,8 +506,11 @@ $ %s query gov params cdc.MustUnmarshalJSON(dp, &depositParams) var votingParams types.VotingParams cdc.MustUnmarshalJSON(vp, &votingParams) + var maxTxNum int + cdc.MustUnmarshalJSON(tmp, &maxTxNum) + tendermintParams := types.TendermintParams{maxTxNum} - return cliCtx.PrintOutput(types.NewParams(votingParams, tallyParams, depositParams)) + return cliCtx.PrintOutput(types.NewParams(votingParams, tallyParams, depositParams, tendermintParams)) }, } } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 137003c51930..df820dee4a4a 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -113,7 +113,7 @@ $ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome pr return err } - amount, err := sdk.ParseCoins(proposal.Deposit) + amount, err := sdk.ParseDecCoins(proposal.Deposit) if err != nil { return err } @@ -168,7 +168,7 @@ $ %s tx gov deposit 1 10stake --from mykey from := cliCtx.GetFromAddress() // Get amount of coins - amount, err := sdk.ParseCoins(args[1]) + amount, err := sdk.ParseDecCoins(args[1]) if err != nil { return err } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 9312a4e76923..934974e03013 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -69,14 +69,14 @@ type PostProposalReq struct { Description string `json:"description" yaml:"description"` // Description of the proposal ProposalType string `json:"proposal_type" yaml:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"` // Address of the proposer - InitialDeposit sdk.Coins `json:"initial_deposit" yaml:"initial_deposit"` // Coins to add to the proposal's deposit + InitialDeposit sdk.DecCoins `json:"initial_deposit" yaml:"initial_deposit"` // Coins to add to the proposal's deposit } // DepositReq defines the properties of a deposit request's body. type DepositReq struct { BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"` // Address of the depositor - Amount sdk.Coins `json:"amount" yaml:"amount"` // Coins to add to the proposal's deposit + Amount sdk.DecCoins `json:"amount" yaml:"amount"` // Coins to add to the proposal's deposit } // VoteReq defines the properties of a vote request's body. diff --git a/x/gov/deposit.go b/x/gov/deposit.go index 03b1ab7d3c7f..b772f7569692 100644 --- a/x/gov/deposit.go +++ b/x/gov/deposit.go @@ -27,7 +27,7 @@ func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositorAdd // AddDeposit adds or updates a deposit of a specific depositor on a specific proposal // Activates voting period when appropriate -func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) { +func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.DecCoins) (sdk.Error, bool) { // Checks to see if proposal exists proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { diff --git a/x/gov/endblocker.go b/x/gov/endblocker.go index d2b8ee03d4ec..7b5817e64797 100644 --- a/x/gov/endblocker.go +++ b/x/gov/endblocker.go @@ -54,7 +54,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) { // The proposal handler may execute state mutating logic depending // on the proposal content. If the handler fails, no state mutation // is written and the error message is logged. - err := handler(cacheCtx, proposal.Content) + err := handler(cacheCtx, &proposal) if err == nil { proposal.Status = StatusPassed tagValue = types.AttributeValueProposalPassed diff --git a/x/gov/expected_keepers.go b/x/gov/expected_keepers.go index f53a49527269..d674d2757047 100644 --- a/x/gov/expected_keepers.go +++ b/x/gov/expected_keepers.go @@ -16,6 +16,7 @@ type SupplyKeeper interface { SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) sdk.Error BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error } @@ -25,7 +26,7 @@ type StakingKeeper interface { IterateBondedValidatorsByPower(sdk.Context, func(index int64, validator stakingexported.ValidatorI) (stop bool)) - TotalBondedTokens(sdk.Context) sdk.Int // total bonded tokens within the validator set + TotalBondedTokens(sdk.Context) sdk.Dec // total bonded tokens within the validator set IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, fn func(index int64, delegation stakingexported.DelegationI) (stop bool)) diff --git a/x/gov/export_okchain.go b/x/gov/export_okchain.go new file mode 100644 index 000000000000..e69655d01735 --- /dev/null +++ b/x/gov/export_okchain.go @@ -0,0 +1,40 @@ +package gov + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/params" +) + +func (keeper Keeper) SupplyKeeper() SupplyKeeper { + return keeper.supplyKeeper +} + +func (keeper Keeper) ParamSpace() params.Subspace { + return keeper.paramSpace +} + +func (keeper Keeper) StoreKey() sdk.StoreKey { + return keeper.storeKey +} + +func (keeper Keeper) Cdc() *codec.Codec { + return keeper.cdc +} + +func (keeper Keeper) Router() Router { + return keeper.router +} + +func (keeper Keeper) Codespace() sdk.CodespaceType { + return keeper.codespace +} + +type ( + ValidatorGovInfo = validatorGovInfo +) + +var ( + NewValidatorGovInfo = newValidatorGovInfo + IsAlphaNumeric = isAlphaNumeric +) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 2ac972c4fdac..01d78a50ecf8 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -41,7 +41,7 @@ func DefaultGenesisState() GenesisState { return GenesisState{ StartingProposalID: 1, DepositParams: DepositParams{ - MinDeposit: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, minDepositTokens)}, + MinDeposit: sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, minDepositTokens)}, MaxDepositPeriod: DefaultPeriod, }, VotingParams: VotingParams{ @@ -104,7 +104,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, supplyKeeper SupplyKeeper, data Gene panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) } - var totalDeposits sdk.Coins + var totalDeposits sdk.DecCoins for _, deposit := range data.Deposits { k.setDeposit(ctx, deposit.ProposalID, deposit.Depositor, deposit) totalDeposits = totalDeposits.Add(deposit.Amount) diff --git a/x/gov/proposal.go b/x/gov/proposal.go index ef9b7e89e281..7eb3fcfbd89b 100644 --- a/x/gov/proposal.go +++ b/x/gov/proposal.go @@ -18,7 +18,7 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, content Content) (Proposal, // governance process. State is not persisted. cacheCtx, _ := ctx.CacheContext() handler := keeper.router.GetRoute(content.ProposalRoute()) - if err := handler(cacheCtx, content); err != nil { + if err := handler(cacheCtx, &Proposal{Content: content}); err != nil { return Proposal{}, ErrInvalidProposalContent(keeper.codespace, err.Result().Log) } @@ -30,7 +30,7 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, content Content) (Proposal, submitTime := ctx.BlockHeader().Time depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod - proposal := NewProposal(content, proposalID, submitTime, submitTime.Add(depositPeriod)) + proposal := NewProposal(ctx, sdk.OneDec(), content, proposalID, submitTime, submitTime.Add(depositPeriod)) keeper.SetProposal(ctx, proposal) keeper.InsertInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime) diff --git a/x/gov/querier.go b/x/gov/querier.go index 03e37c84a13b..c4a907a9dac6 100644 --- a/x/gov/querier.go +++ b/x/gov/querier.go @@ -147,7 +147,7 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke var tallyResult TallyResult if proposal.Status == StatusDepositPeriod { - tallyResult = EmptyTallyResult() + tallyResult = EmptyTallyResult(sdk.ZeroDec()) } else if proposal.Status == StatusPassed || proposal.Status == StatusRejected { tallyResult = proposal.FinalTallyResult } else { diff --git a/x/gov/tally.go b/x/gov/tally.go index 58160b8ab02a..f1c04f9000b5 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -106,7 +106,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, burn } // If there is not enough quorum of votes, the proposal fails - percentVoting := totalVotingPower.Quo(keeper.sk.TotalBondedTokens(ctx).ToDec()) + percentVoting := totalVotingPower.Quo(keeper.sk.TotalBondedTokens(ctx)) if percentVoting.LT(tallyParams.Quorum) { return false, true, tallyResults } diff --git a/x/gov/types/codec.go b/x/gov/types/codec.go index 32d4900785af..a3549c9d97ac 100644 --- a/x/gov/types/codec.go +++ b/x/gov/types/codec.go @@ -12,12 +12,12 @@ var ModuleCdc = codec.New() func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*Content)(nil), nil) - cdc.RegisterConcrete(MsgSubmitProposal{}, "cosmos-sdk/MsgSubmitProposal", nil) - cdc.RegisterConcrete(MsgDeposit{}, "cosmos-sdk/MsgDeposit", nil) - cdc.RegisterConcrete(MsgVote{}, "cosmos-sdk/MsgVote", nil) + cdc.RegisterConcrete(MsgSubmitProposal{}, "okchain/gov/MsgSubmitProposal", nil) + cdc.RegisterConcrete(MsgDeposit{}, "okchain/gov/MsgDeposit", nil) + cdc.RegisterConcrete(MsgVote{}, "okchain/gov/MsgVote", nil) - cdc.RegisterConcrete(TextProposal{}, "cosmos-sdk/TextProposal", nil) - cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal", nil) + cdc.RegisterConcrete(TextProposal{}, "okchain/gov/TextProposal", nil) + cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "okchain/gov/SoftwareUpgradeProposal", nil) } // RegisterProposalTypeCodec registers an external proposal content type defined diff --git a/x/gov/types/content.go b/x/gov/types/content.go index 22a7f7a4af62..1e7dc5721721 100644 --- a/x/gov/types/content.go +++ b/x/gov/types/content.go @@ -28,7 +28,7 @@ type Content interface { // Handler defines a function that handles a proposal after it has passed the // governance process. -type Handler func(ctx sdk.Context, content Content) sdk.Error +type Handler func(ctx sdk.Context, proposal *Proposal) sdk.Error // ValidateAbstract validates a proposal's abstract contents returning an error // if invalid. diff --git a/x/gov/types/deposit.go b/x/gov/types/deposit.go index 2ec06e8e8ee7..087f056a3fa3 100644 --- a/x/gov/types/deposit.go +++ b/x/gov/types/deposit.go @@ -10,11 +10,11 @@ import ( type Deposit struct { ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"` // proposalID of the proposal Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"` // Address of the depositor - Amount sdk.Coins `json:"amount" yaml:"amount"` // Deposit amount + Amount sdk.DecCoins `json:"amount" yaml:"amount"` // Deposit amount } // NewDeposit creates a new Deposit instance -func NewDeposit(proposalID uint64, depositor sdk.AccAddress, amount sdk.Coins) Deposit { +func NewDeposit(proposalID uint64, depositor sdk.AccAddress, amount sdk.DecCoins) Deposit { return Deposit{proposalID, depositor, amount} } diff --git a/x/gov/types/expected_keepers.go b/x/gov/types/expected_keepers.go new file mode 100644 index 000000000000..7dafe11a90d6 --- /dev/null +++ b/x/gov/types/expected_keepers.go @@ -0,0 +1,15 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + stakingexported "github.com/cosmos/cosmos-sdk/x/staking/exported" +) + +// StakingKeeper expected staking keeper (Validator and Delegator sets) +type StakingKeeper interface { + // iterate through bonded validators by operator address, execute func for each validator + IterateBondedValidatorsByPower(sdk.Context, + func(index int64, validator stakingexported.ValidatorI) (stop bool)) + + TotalBondedTokens(sdk.Context) sdk.Int // total bonded tokens within the validator set +} diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 57fc2e0ce69f..5e9c022d28c4 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -18,11 +18,11 @@ var _, _, _ sdk.Msg = MsgSubmitProposal{}, MsgDeposit{}, MsgVote{} // MsgSubmitProposal type MsgSubmitProposal struct { Content Content `json:"content" yaml:"content"` - InitialDeposit sdk.Coins `json:"initial_deposit" yaml:"initial_deposit"` // Initial deposit paid by sender. Must be strictly positive + InitialDeposit sdk.DecCoins `json:"initial_deposit" yaml:"initial_deposit"` // Initial deposit paid by sender. Must be strictly positive Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"` // Address of the proposer } -func NewMsgSubmitProposal(content Content, initialDeposit sdk.Coins, proposer sdk.AccAddress) MsgSubmitProposal { +func NewMsgSubmitProposal(content Content, initialDeposit sdk.DecCoins, proposer sdk.AccAddress) MsgSubmitProposal { return MsgSubmitProposal{content, initialDeposit, proposer} } @@ -50,6 +50,12 @@ func (msg MsgSubmitProposal) ValidateBasic() sdk.Error { if msg.InitialDeposit.IsAnyNegative() { return sdk.ErrInvalidCoins(msg.InitialDeposit.String()) } + + if len(msg.InitialDeposit) != 1 || msg.InitialDeposit[0].Denom != sdk.DefaultBondDenom || !msg.InitialDeposit.IsValid() { + return sdk.ErrInvalidCoins(fmt.Sprintf("must deposit %s but got %s", sdk.DefaultBondDenom, + msg.InitialDeposit.String())) + } + if !IsValidProposalType(msg.Content.ProposalType()) { return ErrInvalidProposalType(DefaultCodespace, msg.Content.ProposalType()) } @@ -79,10 +85,10 @@ func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress { type MsgDeposit struct { ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"` // ID of the proposal Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"` // Address of the depositor - Amount sdk.Coins `json:"amount" yaml:"amount"` // Coins to add to the proposal's deposit + Amount sdk.DecCoins `json:"amount" yaml:"amount"` // Coins to add to the proposal's deposit } -func NewMsgDeposit(depositor sdk.AccAddress, proposalID uint64, amount sdk.Coins) MsgDeposit { +func NewMsgDeposit(depositor sdk.AccAddress, proposalID uint64, amount sdk.DecCoins) MsgDeposit { return MsgDeposit{proposalID, depositor, amount} } diff --git a/x/gov/types/params.go b/x/gov/types/params.go index 9ae33e75a0ff..7a167b5cee1a 100644 --- a/x/gov/types/params.go +++ b/x/gov/types/params.go @@ -21,17 +21,18 @@ func ParamKeyTable() params.KeyTable { ParamStoreKeyDepositParams, DepositParams{}, ParamStoreKeyVotingParams, VotingParams{}, ParamStoreKeyTallyParams, TallyParams{}, + ParamStoreKeyTendermintParams, TendermintParams{}, ) } // Param around deposits for governance type DepositParams struct { - MinDeposit sdk.Coins `json:"min_deposit,omitempty" yaml:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period. + MinDeposit sdk.DecCoins `json:"min_deposit,omitempty" yaml:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period. MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty" yaml:"max_deposit_period,omitempty"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // NewDepositParams creates a new DepositParams object -func NewDepositParams(minDeposit sdk.Coins, maxDepositPeriod time.Duration) DepositParams { +func NewDepositParams(minDeposit sdk.DecCoins, maxDepositPeriod time.Duration) DepositParams { return DepositParams{ MinDeposit: minDeposit, MaxDepositPeriod: maxDepositPeriod, @@ -51,9 +52,10 @@ func (dp DepositParams) Equal(dp2 DepositParams) bool { // Param around Tallying votes in governance type TallyParams struct { - Quorum sdk.Dec `json:"quorum,omitempty" yaml:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid - Threshold sdk.Dec `json:"threshold,omitempty" yaml:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5 - Veto sdk.Dec `json:"veto,omitempty" yaml:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 + Quorum sdk.Dec `json:"quorum,omitempty" yaml:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid + Threshold sdk.Dec `json:"threshold,omitempty" yaml:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5 + Veto sdk.Dec `json:"veto,omitempty" yaml:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 + YesInVotePeriod sdk.Dec `json:"yes_in_vote_period,omitempty" yaml:"yes_in_vote_period,omitempty"` // } // NewTallyParams creates a new TallyParams object @@ -95,17 +97,21 @@ type Params struct { VotingParams VotingParams `json:"voting_params" yaml:"voting_params"` TallyParams TallyParams `json:"tally_params" yaml:"tally_params"` DepositParams DepositParams `json:"deposit_params" yaml:"deposit_parmas"` + TendermintParams TendermintParams `json:"tendermint_params" yaml:"tendermint_params"` } func (gp Params) String() string { return gp.VotingParams.String() + "\n" + - gp.TallyParams.String() + "\n" + gp.DepositParams.String() + gp.TallyParams.String() + "\n" + + gp.DepositParams.String() + "\n" + + gp.TendermintParams.String() } -func NewParams(vp VotingParams, tp TallyParams, dp DepositParams) Params { +func NewParams(vp VotingParams, tp TallyParams, dp DepositParams, tmp TendermintParams) Params { return Params{ - VotingParams: vp, - DepositParams: dp, - TallyParams: tp, + VotingParams: vp, + DepositParams: dp, + TallyParams: tp, + TendermintParams: tmp, } } diff --git a/x/gov/types/params_okchain.go b/x/gov/types/params_okchain.go new file mode 100644 index 000000000000..e8f1d7a639e1 --- /dev/null +++ b/x/gov/types/params_okchain.go @@ -0,0 +1,25 @@ +package types + +import ( + "fmt" +) + +var ( + ParamStoreKeyTendermintParams = []byte("tendermintparams") +) + +type TendermintParams struct { + MaxTxNumPerBlock int `json:"max_tx_num_per_block" yaml:"max_tx_num_per_block"` +} + +// NewMaxTxNumParams creates a new TendermintParams object +func NewTendermintParams(maxTxNumPerBlock int) TendermintParams { + return TendermintParams{ + MaxTxNumPerBlock: maxTxNumPerBlock, + } +} + +func (tp TendermintParams) String() string { + return fmt.Sprintf(`Tendermint Params: + MaxTxNumPerBlock: %d`, tp.MaxTxNumPerBlock) +} diff --git a/x/gov/types/proposal.go b/x/gov/types/proposal.go index a44b80730bc9..f5ee2e6839b3 100644 --- a/x/gov/types/proposal.go +++ b/x/gov/types/proposal.go @@ -18,21 +18,21 @@ type Proposal struct { Status ProposalStatus `json:"proposal_status" yaml:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} FinalTallyResult TallyResult `json:"final_tally_result" yaml:"final_tally_result"` // Result of Tallys - SubmitTime time.Time `json:"submit_time" yaml:"submit_time"` // Time of the block where TxGovSubmitProposal was included - DepositEndTime time.Time `json:"deposit_end_time" yaml:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met - TotalDeposit sdk.Coins `json:"total_deposit" yaml:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit + SubmitTime time.Time `json:"submit_time" yaml:"submit_time"` // Time of the block where TxGovSubmitProposal was included + DepositEndTime time.Time `json:"deposit_end_time" yaml:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met + TotalDeposit sdk.DecCoins `json:"total_deposit" yaml:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit VotingStartTime time.Time `json:"voting_start_time" yaml:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached VotingEndTime time.Time `json:"voting_end_time" yaml:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied } -func NewProposal(content Content, id uint64, submitTime, depositEndTime time.Time) Proposal { +func NewProposal(ctx sdk.Context, totalVoting sdk.Dec, content Content, id uint64, submitTime, depositEndTime time.Time) Proposal { return Proposal{ Content: content, ProposalID: id, Status: StatusDepositPeriod, - FinalTallyResult: EmptyTallyResult(), - TotalDeposit: sdk.NewCoins(), + FinalTallyResult: EmptyTallyResult(totalVoting), + TotalDeposit: sdk.DecCoins{}, SubmitTime: submitTime, DepositEndTime: depositEndTime, } @@ -70,6 +70,16 @@ func (p Proposals) String() string { return strings.TrimSpace(out) } +//func (p Proposals) MarshalYAML() (interface{}, error) { +// out := "ID - (Status) [Type] Title\n" +// for _, prop := range p { +// out += fmt.Sprintf("%d - (%s) [%s] %s\n", +// prop.ProposalID, prop.Status, +// prop.ProposalType(), prop.GetTitle()) +// } +// return strings.TrimSpace(out), nil +//} + type ( // ProposalQueue ProposalQueue []uint64 @@ -183,6 +193,28 @@ func (status ProposalStatus) String() string { } } +func (status ProposalStatus) MarshalYAML() (interface{}, error) { + switch status { + case StatusDepositPeriod: + return "DepositPeriod", nil + + case StatusVotingPeriod: + return "VotingPeriod", nil + + case StatusPassed: + return "Passed", nil + + case StatusRejected: + return "Rejected", nil + + case StatusFailed: + return "Failed", nil + + default: + return "", nil + } +} + // Format implements the fmt.Formatter interface. // nolint: errcheck func (status ProposalStatus) Format(s fmt.State, verb rune) { @@ -197,13 +229,17 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) { // Tally Results type TallyResult struct { - Yes sdk.Int `json:"yes" yaml:"yes"` - Abstain sdk.Int `json:"abstain" yaml:"abstain"` - No sdk.Int `json:"no" yaml:"no"` - NoWithVeto sdk.Int `json:"no_with_veto" yaml:"no_with_veto"` + // total power of accounts whose votes are voted to the current validator set + TotalPower sdk.Dec `json:"total_power"` + // total power of accounts who has voted for a proposal + TotalVotedPower sdk.Dec `json:"total_voted_power"` + Yes sdk.Dec `json:"yes"` + Abstain sdk.Dec `json:"abstain"` + No sdk.Dec `json:"no"` + NoWithVeto sdk.Dec `json:"no_with_veto"` } -func NewTallyResult(yes, abstain, no, noWithVeto sdk.Int) TallyResult { +func NewTallyResult(yes, abstain, no, noWithVeto sdk.Dec) TallyResult { return TallyResult{ Yes: yes, Abstain: abstain, @@ -214,20 +250,22 @@ func NewTallyResult(yes, abstain, no, noWithVeto sdk.Int) TallyResult { func NewTallyResultFromMap(results map[VoteOption]sdk.Dec) TallyResult { return TallyResult{ - Yes: results[OptionYes].TruncateInt(), - Abstain: results[OptionAbstain].TruncateInt(), - No: results[OptionNo].TruncateInt(), - NoWithVeto: results[OptionNoWithVeto].TruncateInt(), + Yes: results[OptionYes], + Abstain: results[OptionAbstain], + No: results[OptionNo], + NoWithVeto: results[OptionNoWithVeto], } } // EmptyTallyResult returns an empty TallyResult. -func EmptyTallyResult() TallyResult { +func EmptyTallyResult(totalVoting sdk.Dec) TallyResult { return TallyResult{ - Yes: sdk.ZeroInt(), - Abstain: sdk.ZeroInt(), - No: sdk.ZeroInt(), - NoWithVeto: sdk.ZeroInt(), + TotalPower: totalVoting, + TotalVotedPower: sdk.ZeroDec(), + Yes: sdk.ZeroDec(), + Abstain: sdk.ZeroDec(), + No: sdk.ZeroDec(), + NoWithVeto: sdk.ZeroDec(), } } @@ -241,10 +279,12 @@ func (tr TallyResult) Equals(comp TallyResult) bool { func (tr TallyResult) String() string { return fmt.Sprintf(`Tally Result: + TotalPower %s + TotalVotedPower %s Yes: %s Abstain: %s No: %s - NoWithVeto: %s`, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto) + NoWithVeto: %s`, tr.TotalPower, tr.TotalVotedPower, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto) } // Proposal types @@ -353,14 +393,14 @@ func IsValidProposalType(ty string) bool { // proposals (ie. TextProposal and SoftwareUpgradeProposal). Since these are // merely signaling mechanisms at the moment and do not affect state, it // performs a no-op. -func ProposalHandler(_ sdk.Context, c Content) sdk.Error { - switch c.ProposalType() { +func ProposalHandler(_ sdk.Context, p *Proposal) sdk.Error { + switch p.ProposalType() { case ProposalTypeText, ProposalTypeSoftwareUpgrade: // both proposal types do not change state so this performs a no-op return nil default: - errMsg := fmt.Sprintf("unrecognized gov proposal type: %s", c.ProposalType()) + errMsg := fmt.Sprintf("unrecognized gov proposal type: %s", p.ProposalType()) return sdk.ErrUnknownRequest(errMsg) } } diff --git a/x/gov/types/queier_okchain.go b/x/gov/types/queier_okchain.go new file mode 100644 index 000000000000..36134644f949 --- /dev/null +++ b/x/gov/types/queier_okchain.go @@ -0,0 +1,5 @@ +package types + +const ( + ParamTendermint = "tendermint" +) diff --git a/x/mint/abci.go b/x/mint/abci.go index 07d8d84624d0..a3c71f240eaa 100644 --- a/x/mint/abci.go +++ b/x/mint/abci.go @@ -1,34 +1,48 @@ package mint import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mint/internal/types" ) +func disableMining(minter *types.Minter) { + minter.Inflation = sdk.ZeroDec() +} + +var setInflationHandler func(minter *types.Minter) + // BeginBlocker mints new tokens for the previous block. -func BeginBlocker(ctx sdk.Context, k Keeper) { +func beginBlocker(ctx sdk.Context, k Keeper) { + + logger := ctx.Logger().With("module", "mint") // fetch stored minter & params - minter := k.GetMinter(ctx) params := k.GetParams(ctx) + minter := k.GetMinterCustom(ctx) + if ctx.BlockHeight() == 0 || uint64(ctx.BlockHeight()) > minter.NextBlockToUpdate { + k.UpdateMinterCustom(ctx, &minter, params) + } - // recalculate inflation rate - totalStakingSupply := k.StakingTokenSupply(ctx) - bondedRatio := k.BondedRatio(ctx) - minter.Inflation = minter.NextInflationRate(params, bondedRatio) - minter.AnnualProvisions = minter.NextAnnualProvisions(params, totalStakingSupply) - k.SetMinter(ctx, minter) - - // mint coins, update supply - mintedCoin := minter.BlockProvision(params) - mintedCoins := sdk.NewCoins(mintedCoin) + logger.Debug(fmt.Sprintf( + "total supply <%v>, "+ + "annual provisions <%v>, "+ + "params <%v>, "+ + "minted this block <%v>, "+ + "next block to update minted per block <%v>, ", + sdk.NewDecCoinFromDec(params.MintDenom, k.StakingTokenSupply(ctx)), + sdk.NewDecCoinFromDec(params.MintDenom, minter.AnnualProvisions), + params, + minter.MintedPerBlock, + minter.NextBlockToUpdate)) - err := k.MintCoins(ctx, mintedCoins) + err := k.MintCoins(ctx, minter.MintedPerBlock) if err != nil { panic(err) } // send the minted coins to the fee collector account - err = k.AddCollectedFees(ctx, mintedCoins) + err = k.AddCollectedFees(ctx, minter.MintedPerBlock) if err != nil { panic(err) } @@ -36,10 +50,15 @@ func BeginBlocker(ctx sdk.Context, k Keeper) { ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeMint, - sdk.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()), - sdk.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()), + sdk.NewAttribute(types.AttributeKeyInflation, params.InflationRate.String()), sdk.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()), - sdk.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, minter.MintedPerBlock.String()), ), ) } + +// BeginBlocker mints new tokens for the previous block. +func BeginBlocker(ctx sdk.Context, k Keeper) { + setInflationHandler = disableMining + beginBlocker(ctx, k) +} diff --git a/x/mint/alias.go b/x/mint/alias.go index e3a9bcf1e9bb..e7d49d7823e9 100644 --- a/x/mint/alias.go +++ b/x/mint/alias.go @@ -22,30 +22,34 @@ const ( var ( // functions aliases - NewKeeper = keeper.NewKeeper - NewQuerier = keeper.NewQuerier - NewMinter = types.NewMinter - InitialMinter = types.InitialMinter - DefaultInitialMinter = types.DefaultInitialMinter - ValidateMinter = types.ValidateMinter - ParamKeyTable = types.ParamKeyTable - NewParams = types.NewParams - DefaultParams = types.DefaultParams - ValidateParams = types.ValidateParams + NewKeeper = keeper.NewKeeper + NewQuerier = keeper.NewQuerier + NewMinter = types.NewMinter + InitialMinter = types.InitialMinter + InitialMinterCustom = types.InitialMinterCustom + DefaultInitialMinter = types.DefaultInitialMinter + DefaultInitialMinterCustom = types.DefaultInitialMinterCustom + ValidateMinter = types.ValidateMinter + ValidateMinterCustom = types.ValidateMinterCustom + ParamKeyTable = types.ParamKeyTable + NewParams = types.NewParams + DefaultParams = types.DefaultParams + ValidateParams = types.ValidateParams // variable aliases - ModuleCdc = types.ModuleCdc - MinterKey = types.MinterKey - KeyMintDenom = types.KeyMintDenom - KeyInflationRateChange = types.KeyInflationRateChange - KeyInflationMax = types.KeyInflationMax - KeyInflationMin = types.KeyInflationMin - KeyGoalBonded = types.KeyGoalBonded - KeyBlocksPerYear = types.KeyBlocksPerYear + ModuleCdc = types.ModuleCdc + MinterKey = types.MinterKey + KeyMintDenom = types.KeyMintDenom + KeyInflationRate = types.KeyInflationRate + //KeyInflationMax = types.KeyInflationMax + //KeyInflationMin = types.KeyInflationMin + //KeyGoalBonded = types.KeyGoalBonded + KeyBlocksPerYear = types.KeyBlocksPerYear ) type ( - Keeper = keeper.Keeper - Minter = types.Minter - Params = types.Params + Keeper = keeper.Keeper + Minter = types.Minter + MinterCustom = types.MinterCustom + Params = types.Params ) diff --git a/x/mint/app_test.go b/x/mint/app_test.go new file mode 100644 index 000000000000..79f4d9bed91a --- /dev/null +++ b/x/mint/app_test.go @@ -0,0 +1,149 @@ +package mint + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "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/mint/internal/types" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/supply" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/secp256k1" +) + +type MockApp struct { + *mock.App + + keySupply *sdk.KVStoreKey + keyStaking *sdk.KVStoreKey + tkeyStaking *sdk.KVStoreKey + keyMint *sdk.KVStoreKey + + bankKeeper bank.Keeper + supplyKeeper supply.Keeper + stakingKeeper staking.Keeper + mintKeeper Keeper +} + +func registerCodec(cdc *codec.Codec) { + supply.RegisterCodec(cdc) +} + +func getMockApp(t *testing.T, numGenAccs int, balance int64, mintParams Params) (mockApp *MockApp, addrKeysSlice mock.AddrKeysSlice) { + mapp := mock.NewApp() + registerCodec(mapp.Cdc) + + mockApp = &MockApp{ + App: mapp, + + keySupply: sdk.NewKVStoreKey(supply.StoreKey), + keyStaking: sdk.NewKVStoreKey(staking.StoreKey), + tkeyStaking: sdk.NewKVStoreKey(staking.TStoreKey), + keyMint: sdk.NewKVStoreKey(types.StoreKey), + } + + mockApp.bankKeeper = bank.NewBaseKeeper(mockApp.AccountKeeper, + mockApp.ParamsKeeper.Subspace(bank.DefaultParamspace), + bank.DefaultCodespace, nil) + + maccPerms := map[string][]string{ + auth.FeeCollectorName: nil, + types.ModuleName: []string{supply.Minter}, + staking.NotBondedPoolName: []string{supply.Burner, supply.Staking}, + staking.BondedPoolName: []string{supply.Burner, supply.Staking}, + } + + mockApp.supplyKeeper = supply.NewKeeper(mockApp.Cdc, mockApp.keySupply, mockApp.AccountKeeper, + mockApp.bankKeeper, maccPerms) + + mockApp.stakingKeeper = staking.NewKeeper( + mockApp.Cdc, mockApp.keyStaking, mockApp.tkeyStaking, mockApp.supplyKeeper, + mockApp.ParamsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace, + ) + + mockApp.mintKeeper = NewKeeper(mockApp.Cdc, mockApp.keyMint, + mockApp.ParamsKeeper.Subspace(types.DefaultParamspace), &mockApp.stakingKeeper, + mockApp.supplyKeeper, auth.FeeCollectorName) + + //mockApp.Router().AddRoute("", nil) + mockApp.QueryRouter().AddRoute(QuerierRoute, NewQuerier(mockApp.mintKeeper)) + + decCoins, _ := sdk.ParseDecCoins(fmt.Sprintf("%d%s", + balance, sdk.DefaultBondDenom)) + coins := decCoins + + keysSlice, genAccs := CreateGenAccounts(numGenAccs, coins) + addrKeysSlice = keysSlice + + mockApp.SetBeginBlocker(getBeginBlocker(mockApp.mintKeeper)) + mockApp.SetInitChainer(getInitChainer(mockApp.App, mockApp.supplyKeeper, mockApp.mintKeeper, mockApp.stakingKeeper, + genAccs, mintParams)) + + // todo: checkTx in mock app + mockApp.SetAnteHandler(nil) + + app := mockApp + require.NoError(t, app.CompleteSetup( + app.keyStaking, + app.tkeyStaking, + app.keyMint, + app.keySupply, + )) + mock.SetGenesis(mockApp.App, genAccs) + + for i := 0; i < numGenAccs; i++ { + mock.CheckBalance(t, app.App, keysSlice[i].Address, coins) + } + + return +} + +func getBeginBlocker(keeper Keeper) sdk.BeginBlocker { + return func(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { + BeginBlocker(ctx, keeper) + return abci.ResponseBeginBlock{} + } +} + +func getInitChainer(mapp *mock.App, supplyKeeper supply.Keeper, mintKeeper Keeper, stakingkeeper staking.Keeper, + genAccs []auth.Account, mintParams Params) sdk.InitChainer { + return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + mapp.InitChainer(ctx, req) + + for _, acc := range genAccs { + mapp.TotalCoinsSupply = mapp.TotalCoinsSupply.Add(acc.GetCoins()) + } + supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) + + mintKeeper.SetParams(ctx, mintParams) + mintKeeper.SetMinterCustom(ctx, types.MinterCustom{}) + + stakingkeeper.SetParams(ctx, staking.DefaultParams()) + + return abci.ResponseInitChain{} + } +} + +func CreateGenAccounts(numAccs int, genCoins sdk.Coins) (addrKeysSlice mock.AddrKeysSlice, + genAccs []auth.Account) { + for i := 0; i < numAccs; i++ { + privKey := secp256k1.GenPrivKey() + pubKey := privKey.PubKey() + addr := sdk.AccAddress(pubKey.Address()) + + addrKeys := mock.NewAddrKeys(addr, pubKey, privKey) + account := &auth.BaseAccount{ + Address: addr, + Coins: genCoins, + } + genAccs = append(genAccs, account) + addrKeysSlice = append(addrKeysSlice, addrKeys) + } + return +} diff --git a/x/mint/beginBlocker_test.go b/x/mint/beginBlocker_test.go new file mode 100644 index 000000000000..98e0d6283058 --- /dev/null +++ b/x/mint/beginBlocker_test.go @@ -0,0 +1,62 @@ +package mint + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + abci "github.com/tendermint/tendermint/abci/types" +) + +func TestBeginBlocker(t *testing.T) { + mintParams := Params{ + MintDenom: sdk.DefaultBondDenom, + InflationRate: sdk.NewDecWithPrec(1, 2), + BlocksPerYear: uint64(100), + } + var balance int64 = 10000 + mapp, _ := getMockApp(t, 1, balance, mintParams) + + mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: int64(2)}}) + ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(int64(2)) + + // mint rate test + minter := mapp.mintKeeper.GetMinterCustom(ctx) + ratePerBlock0 := minter.MintedPerBlock.AmountOf(sdk.DefaultBondDenom) + + annualProvisions := mintParams.InflationRate.Mul(sdk.NewDec(balance)) + provisionAmtPerBlock := annualProvisions.Quo(sdk.NewDec(int64(mintParams.BlocksPerYear))) + assert.EqualValues(t, ratePerBlock0, provisionAmtPerBlock) + + var curHeight int64 = 2 + for ; curHeight < 101; curHeight++ { + mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: curHeight}}) + mapp.EndBlock(abci.RequestEndBlock{Height: curHeight}) + mapp.Commit() + } + + // this year mint test + curSupply0 := mapp.supplyKeeper.GetSupply(ctx).GetTotal().AmountOf(sdk.DefaultBondDenom) + curCoin0 := curSupply0 + rawCoin := sdk.NewDec(balance) + assert.EqualValues(t, curCoin0.Sub(rawCoin), ratePerBlock0.Mul(sdk.NewDec(curHeight-1))) + + // next year mint test + mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: curHeight}}) + ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(curHeight) + curSupply1 := mapp.supplyKeeper.GetSupply(ctx).GetTotal().AmountOf(sdk.DefaultBondDenom) + curCoin1 := curSupply1 + + minter = mapp.mintKeeper.GetMinterCustom(ctx) + ratePerBlock1 := minter.MintedPerBlock.AmountOf(sdk.DefaultBondDenom) + lastMintTotalSupply := mintParams.InflationRate.Mul(sdk.NewDec(balance)).Add(sdk.NewDec(balance)) + annualProvisions = mintParams.InflationRate.Mul(lastMintTotalSupply) + provisionAmtPerBlock = annualProvisions.Quo(sdk.NewDec(int64(mintParams.BlocksPerYear))) + assert.EqualValues(t, ratePerBlock1, provisionAmtPerBlock) + + // annual mint test + step1Mint := ratePerBlock0.Mul(sdk.NewDec(100)) + step2Mint := ratePerBlock1.Mul(sdk.NewDec(curHeight - 100)) + totalMint := step1Mint.Add(step2Mint) + assert.EqualValues(t, curCoin1.Sub(rawCoin), totalMint) +} diff --git a/x/mint/client/cli/query.go b/x/mint/client/cli/query.go index 3350706362f3..534cb61bc04e 100644 --- a/x/mint/client/cli/query.go +++ b/x/mint/client/cli/query.go @@ -25,8 +25,8 @@ func GetQueryCmd(cdc *codec.Codec) *cobra.Command { mintingQueryCmd.AddCommand( client.GetCommands( GetCmdQueryParams(cdc), - GetCmdQueryInflation(cdc), - GetCmdQueryAnnualProvisions(cdc), + //GetCmdQueryInflation(cdc), + //GetCmdQueryAnnualProvisions(cdc), )..., ) diff --git a/x/mint/genesis.go b/x/mint/genesis.go index 68722158e66f..d365bb4ae63b 100644 --- a/x/mint/genesis.go +++ b/x/mint/genesis.go @@ -6,12 +6,12 @@ import ( // GenesisState - minter state type GenesisState struct { - Minter Minter `json:"minter" yaml:"minter"` // minter object - Params Params `json:"params" yaml:"params"` // inflation params + Minter MinterCustom `json:"minter_custom" yaml:"minter_custom"` // minter object + Params Params `json:"params" yaml:"params"` // inflation params } // NewGenesisState creates a new GenesisState object -func NewGenesisState(minter Minter, params Params) GenesisState { +func NewGenesisState(minter MinterCustom, params Params) GenesisState { return GenesisState{ Minter: minter, Params: params, @@ -21,20 +21,20 @@ func NewGenesisState(minter Minter, params Params) GenesisState { // DefaultGenesisState creates a default GenesisState object func DefaultGenesisState() GenesisState { return GenesisState{ - Minter: DefaultInitialMinter(), + Minter: DefaultInitialMinterCustom(), Params: DefaultParams(), } } // InitGenesis new mint genesis func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) { - keeper.SetMinter(ctx, data.Minter) + keeper.SetMinterCustom(ctx, data.Minter) keeper.SetParams(ctx, data.Params) } // ExportGenesis returns a GenesisState for a given context and keeper. func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState { - minter := keeper.GetMinter(ctx) + minter := keeper.GetMinterCustom(ctx) params := keeper.GetParams(ctx) return NewGenesisState(minter, params) } @@ -47,7 +47,7 @@ func ValidateGenesis(data GenesisState) error { return err } - err = ValidateMinter(data.Minter) + err = ValidateMinterCustom(data.Minter) if err != nil { return err } diff --git a/x/mint/genesis_test.go b/x/mint/genesis_test.go new file mode 100644 index 000000000000..59c78db2fde9 --- /dev/null +++ b/x/mint/genesis_test.go @@ -0,0 +1,29 @@ +package mint + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGenesis(t *testing.T) { + + setup := newTestInput(t) + + genesisState := NewGenesisState( + DefaultInitialMinterCustom(), DefaultParams()) + + defaultGenesisState := DefaultGenesisState() + + require.Equal(t, genesisState, defaultGenesisState) + + InitGenesis(setup.ctx, setup.mintKeeper, defaultGenesisState) + + require.NoError(t, ValidateGenesis(defaultGenesisState)) + + exportedState := ExportGenesis(setup.ctx, setup.mintKeeper) + + require.NotNil(t, exportedState) + + require.Equal(t, defaultGenesisState, exportedState) +} diff --git a/x/mint/internal/keeper/keeper.go b/x/mint/internal/keeper/keeper.go index ff4bd029dfda..9befe13479b5 100644 --- a/x/mint/internal/keeper/keeper.go +++ b/x/mint/internal/keeper/keeper.go @@ -19,6 +19,7 @@ type Keeper struct { sk types.StakingKeeper supplyKeeper types.SupplyKeeper feeCollectorName string + cache *types.Cache } // NewKeeper creates a new mint Keeper instance @@ -38,6 +39,7 @@ func NewKeeper( sk: sk, supplyKeeper: supplyKeeper, feeCollectorName: feeCollectorName, + cache: &types.Cache{}, } } @@ -71,20 +73,25 @@ func (k Keeper) SetMinter(ctx sdk.Context, minter types.Minter) { // GetParams returns the total set of minting parameters. func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + if k.cache.Params != nil { + return *k.cache.Params + } k.paramSpace.GetParamSet(ctx, ¶ms) + k.cache.Params = ¶ms return params } // SetParams sets the total set of minting parameters. func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) + k.cache.Params = ¶ms } //______________________________________________________________________ // StakingTokenSupply implements an alias call to the underlying staking keeper's // StakingTokenSupply to be used in BeginBlocker. -func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Int { +func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Dec { return k.sk.StakingTokenSupply(ctx) } @@ -109,3 +116,38 @@ func (k Keeper) MintCoins(ctx sdk.Context, newCoins sdk.Coins) sdk.Error { func (k Keeper) AddCollectedFees(ctx sdk.Context, fees sdk.Coins) sdk.Error { return k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.feeCollectorName, fees) } + +// get the minter custom +func (k Keeper) GetMinterCustom(ctx sdk.Context) (minter types.MinterCustom) { + if k.cache.Minter != nil { + return *k.cache.Minter + } + store := ctx.KVStore(k.storeKey) + b := store.Get(types.MinterKey) + if b != nil { + k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &minter) + } + + k.cache.Minter = &minter + return +} + +// set the minter custom +func (k Keeper) SetMinterCustom(ctx sdk.Context, minter types.MinterCustom) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinaryLengthPrefixed(minter) + store.Set(types.MinterKey, b) + k.cache.Minter = &minter +} + +func (k Keeper) UpdateMinterCustom(ctx sdk.Context, minter *types.MinterCustom, params types.Params) { + totalStakingSupply := k.StakingTokenSupply(ctx) + annualProvisions := params.InflationRate.Mul(totalStakingSupply) + provisionAmtPerBlock := annualProvisions.Quo(sdk.NewDec(int64(params.BlocksPerYear))) + + // update new MinterCustom + minter.MintedPerBlock = sdk.NewDecCoinsFromDec(params.MintDenom, provisionAmtPerBlock) + minter.NextBlockToUpdate += params.BlocksPerYear + minter.AnnualProvisions = annualProvisions + k.SetMinterCustom(ctx, *minter) +} diff --git a/x/mint/internal/keeper/querier.go b/x/mint/internal/keeper/querier.go index fe3943f0896a..4087de7fbcbc 100644 --- a/x/mint/internal/keeper/querier.go +++ b/x/mint/internal/keeper/querier.go @@ -17,11 +17,11 @@ func NewQuerier(k Keeper) sdk.Querier { case types.QueryParameters: return queryParams(ctx, k) - case types.QueryInflation: - return queryInflation(ctx, k) - - case types.QueryAnnualProvisions: - return queryAnnualProvisions(ctx, k) + //case types.QueryInflation: + // return queryInflation(ctx, k) + // + //case types.QueryAnnualProvisions: + // return queryAnnualProvisions(ctx, k) default: return nil, sdk.ErrUnknownRequest(fmt.Sprintf("unknown minting query endpoint: %s", path[0])) diff --git a/x/mint/internal/keeper/querier_test.go b/x/mint/internal/keeper/querier_test.go index f6a1779ede1c..6d62138beb74 100644 --- a/x/mint/internal/keeper/querier_test.go +++ b/x/mint/internal/keeper/querier_test.go @@ -23,11 +23,11 @@ func TestNewQuerier(t *testing.T) { _, err := querier(input.ctx, []string{types.QueryParameters}, query) require.NoError(t, err) - _, err = querier(input.ctx, []string{types.QueryInflation}, query) - require.NoError(t, err) - - _, err = querier(input.ctx, []string{types.QueryAnnualProvisions}, query) - require.NoError(t, err) + //_, err = querier(input.ctx, []string{types.QueryInflation}, query) + //require.NoError(t, err) + // + //_, err = querier(input.ctx, []string{types.QueryAnnualProvisions}, query) + //require.NoError(t, err) _, err = querier(input.ctx, []string{"foo"}, query) require.Error(t, err) diff --git a/x/mint/internal/types/cache_okchain.go b/x/mint/internal/types/cache_okchain.go new file mode 100644 index 000000000000..7a1f45df0616 --- /dev/null +++ b/x/mint/internal/types/cache_okchain.go @@ -0,0 +1,6 @@ +package types + +type Cache struct { + Params *Params + Minter *MinterCustom +} diff --git a/x/mint/internal/types/expected_keepers.go b/x/mint/internal/types/expected_keepers.go index 564a0136b5c7..674b50f438cb 100644 --- a/x/mint/internal/types/expected_keepers.go +++ b/x/mint/internal/types/expected_keepers.go @@ -7,7 +7,7 @@ import ( // StakingKeeper defines the expected staking keeper type StakingKeeper interface { - StakingTokenSupply(ctx sdk.Context) sdk.Int + StakingTokenSupply(ctx sdk.Context) sdk.Dec BondedRatio(ctx sdk.Context) sdk.Dec } diff --git a/x/mint/internal/types/minter.go b/x/mint/internal/types/minter.go index e07716acd716..487b08e023fa 100644 --- a/x/mint/internal/types/minter.go +++ b/x/mint/internal/types/minter.go @@ -33,7 +33,7 @@ func InitialMinter(inflation sdk.Dec) Minter { // which uses an inflation rate of 13%. func DefaultInitialMinter() Minter { return InitialMinter( - sdk.NewDecWithPrec(13, 2), + sdk.NewDecWithPrec(1, 2), ) } @@ -47,30 +47,30 @@ func ValidateMinter(minter Minter) error { } // NextInflationRate returns the new inflation rate for the next hour. -func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) sdk.Dec { - // The target annual inflation rate is recalculated for each previsions cycle. The - // inflation is also subject to a rate change (positive or negative) depending on - // the distance from the desired ratio (67%). The maximum rate change possible is - // defined to be 13% per year, however the annual inflation is capped as between - // 7% and 20%. - - // (1 - bondedRatio/GoalBonded) * InflationRateChange - inflationRateChangePerYear := sdk.OneDec(). - Sub(bondedRatio.Quo(params.GoalBonded)). - Mul(params.InflationRateChange) - inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear))) - - // adjust the new annual inflation for this next cycle - inflation := m.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative - if inflation.GT(params.InflationMax) { - inflation = params.InflationMax - } - if inflation.LT(params.InflationMin) { - inflation = params.InflationMin - } - - return inflation -} +//func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) sdk.Dec { +// // The target annual inflation rate is recalculated for each previsions cycle. The +// // inflation is also subject to a rate change (positive or negative) depending on +// // the distance from the desired ratio (67%). The maximum rate change possible is +// // defined to be 13% per year, however the annual inflation is capped as between +// // 7% and 20%. +// +// // (1 - bondedRatio/GoalBonded) * InflationRate +// inflationRateChangePerYear := sdk.OneDec(). +// Sub(bondedRatio.Quo(params.GoalBonded)). +// Mul(params.InflationRate) +// inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear))) +// +// // adjust the new annual inflation for this next cycle +// inflation := m.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative +// if inflation.GT(params.InflationMax) { +// inflation = params.InflationMax +// } +// if inflation.LT(params.InflationMin) { +// inflation = params.InflationMin +// } +// +// return inflation +//} // NextAnnualProvisions returns the annual provisions based on current total // supply and inflation rate. diff --git a/x/mint/internal/types/minter_okchain.go b/x/mint/internal/types/minter_okchain.go new file mode 100644 index 000000000000..cb588f69a0e3 --- /dev/null +++ b/x/mint/internal/types/minter_okchain.go @@ -0,0 +1,49 @@ +package types + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MinterCustom struct { + NextBlockToUpdate uint64 `json:"next_block_to_update" yaml:"next_block_to_update"` // record the block height for next year + AnnualProvisions sdk.Dec `json:"annual_provisions" yaml:"annual_provisions"` // record the amount of Annual minted + MintedPerBlock types.DecCoins `json:"minted_per_block" yaml:"minted_per_block"` // record the MintedPerBlock per block in this year +} + +// NewMinterCustom returns a new Minter object with the given inflation and annual +// provisions values. +func NewMinterCustom(nextBlockToUpdate uint64, annualProvisions sdk.Dec, mintedPerBlock sdk.DecCoins) MinterCustom { + return MinterCustom{ + NextBlockToUpdate: nextBlockToUpdate, + AnnualProvisions: annualProvisions, + MintedPerBlock: mintedPerBlock, + } +} + +// InitialMinterCustom returns an initial Minter object with a given inflation value. +func InitialMinterCustom(inflation sdk.Dec) MinterCustom { + return NewMinterCustom( + 0, + sdk.NewDec(0), + sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, sdk.ZeroInt())}, + ) +} + +// DefaultInitialMinterCustom returns a default initial MinterCustom object for a new chain +// which uses an inflation rate of 1%. +func DefaultInitialMinterCustom() MinterCustom { + return InitialMinterCustom( + sdk.NewDecWithPrec(1, 2), + ) +} + +// ValidateMinterCustom validate minter +func ValidateMinterCustom(minter MinterCustom) error { + if len(minter.MintedPerBlock) != 1 || minter.MintedPerBlock[0].Denom != sdk.DefaultBondDenom { + return fmt.Errorf(" MintedPerBlock must contain only %s", sdk.DefaultBondDenom) + } + return nil +} diff --git a/x/mint/internal/types/minter_test.go b/x/mint/internal/types/minter_test.go index 8760a66f4466..2e7cc12570c6 100644 --- a/x/mint/internal/types/minter_test.go +++ b/x/mint/internal/types/minter_test.go @@ -1,86 +1,83 @@ package types import ( - "math/rand" "testing" - "github.com/stretchr/testify/require" - sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestNextInflation(t *testing.T) { - minter := DefaultInitialMinter() - params := DefaultParams() - blocksPerYr := sdk.NewDec(int64(params.BlocksPerYear)) - - // Governing Mechanism: - // inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange - - tests := []struct { - bondedRatio, setInflation, expChange sdk.Dec - }{ - // with 0% bonded atom supply the inflation should increase by InflationRateChange - {sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(blocksPerYr)}, - - // 100% bonded, starting at 20% inflation and being reduced - // (1 - (1/0.67))*(0.13/8667) - {sdk.OneDec(), sdk.NewDecWithPrec(20, 2), - sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)}, - - // 50% bonded, starting at 10% inflation and being increased - {sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(10, 2), - sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)}, - - // test 7% minimum stop (testing with 100% bonded) - {sdk.OneDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()}, - {sdk.OneDec(), sdk.NewDecWithPrec(700000001, 10), sdk.NewDecWithPrec(-1, 10)}, - - // test 20% maximum stop (testing with 0% bonded) - {sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()}, - {sdk.ZeroDec(), sdk.NewDecWithPrec(1999999999, 10), sdk.NewDecWithPrec(1, 10)}, - - // perfect balance shouldn't change inflation - {sdk.NewDecWithPrec(67, 2), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()}, - } - for i, tc := range tests { - minter.Inflation = tc.setInflation - - inflation := minter.NextInflationRate(params, tc.bondedRatio) - diffInflation := inflation.Sub(tc.setInflation) - - require.True(t, diffInflation.Equal(tc.expChange), - "Test Index: %v\nDiff: %v\nExpected: %v\n", i, diffInflation, tc.expChange) - } -} - -func TestBlockProvision(t *testing.T) { - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() - - secondsPerYear := int64(60 * 60 * 8766) - - tests := []struct { - annualProvisions int64 - expProvisions int64 - }{ - {secondsPerYear / 5, 1}, - {secondsPerYear/5 + 1, 1}, - {(secondsPerYear / 5) * 2, 2}, - {(secondsPerYear / 5) / 2, 0}, - } - for i, tc := range tests { - minter.AnnualProvisions = sdk.NewDec(tc.annualProvisions) - provisions := minter.BlockProvision(params) - - expProvisions := sdk.NewCoin(params.MintDenom, - sdk.NewInt(tc.expProvisions)) - - require.True(t, expProvisions.IsEqual(provisions), - "test: %v\n\tExp: %v\n\tGot: %v\n", - i, tc.expProvisions, provisions) - } -} +//func TestNextInflation(t *testing.T) { +// minter := DefaultInitialMinter() +// params := DefaultParams() +// blocksPerYr := sdk.NewDec(int64(params.BlocksPerYear)) +// +// // Governing Mechanism: +// // inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange +// +// tests := []struct { +// bondedRatio, setInflation, expChange sdk.Dec +// }{ +// // with 0% bonded atom supply the inflation should increase by InflationRateChange +// {sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(blocksPerYr)}, +// +// // 100% bonded, starting at 20% inflation and being reduced +// // (1 - (1/0.67))*(0.13/8667) +// {sdk.OneDec(), sdk.NewDecWithPrec(20, 2), +// sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)}, +// +// // 50% bonded, starting at 10% inflation and being increased +// {sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(10, 2), +// sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)}, +// +// // test 7% minimum stop (testing with 100% bonded) +// {sdk.OneDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()}, +// {sdk.OneDec(), sdk.NewDecWithPrec(700000001, 10), sdk.NewDecWithPrec(-1, 10)}, +// +// // test 20% maximum stop (testing with 0% bonded) +// {sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()}, +// {sdk.ZeroDec(), sdk.NewDecWithPrec(1999999999, 10), sdk.NewDecWithPrec(1, 10)}, +// +// // perfect balance shouldn't change inflation +// {sdk.NewDecWithPrec(67, 2), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()}, +// } +// for i, tc := range tests { +// minter.Inflation = tc.setInflation +// +// inflation := minter.NextInflationRate(params, tc.bondedRatio) +// diffInflation := inflation.Sub(tc.setInflation) +// +// require.True(t, diffInflation.Equal(tc.expChange), +// "Test Index: %v\nDiff: %v\nExpected: %v\n", i, diffInflation, tc.expChange) +// } +//} +// +//func TestBlockProvision(t *testing.T) { +// minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) +// params := DefaultParams() +// +// secondsPerYear := int64(60 * 60 * 8766) +// +// tests := []struct { +// annualProvisions int64 +// expProvisions int64 +// }{ +// {secondsPerYear / 5, 1}, +// {secondsPerYear/5 + 1, 1}, +// {(secondsPerYear / 5) * 2, 2}, +// {(secondsPerYear / 5) / 2, 0}, +// } +// for i, tc := range tests { +// minter.AnnualProvisions = sdk.NewDec(tc.annualProvisions) +// provisions := minter.BlockProvision(params) +// +// expProvisions := sdk.NewCoin(params.MintDenom, +// sdk.NewInt(tc.expProvisions)) +// +// require.True(t, expProvisions.IsEqual(provisions), +// "test: %v\n\tExp: %v\n\tGot: %v\n", +// i, tc.expProvisions, provisions) +// } +//} // Benchmarking :) // previously using sdk.Int operations: @@ -88,33 +85,33 @@ func TestBlockProvision(t *testing.T) { // // using sdk.Dec operations: (current implementation) // BenchmarkBlockProvision-4 3000000 429 ns/op -func BenchmarkBlockProvision(b *testing.B) { - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() - - s1 := rand.NewSource(100) - r1 := rand.New(s1) - minter.AnnualProvisions = sdk.NewDec(r1.Int63n(1000000)) - - // run the BlockProvision function b.N times - for n := 0; n < b.N; n++ { - minter.BlockProvision(params) - } -} +//func BenchmarkBlockProvision(b *testing.B) { +// minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) +// params := DefaultParams() +// +// s1 := rand.NewSource(100) +// r1 := rand.New(s1) +// minter.AnnualProvisions = sdk.NewDec(r1.Int63n(1000000)) +// +// // run the BlockProvision function b.N times +// for n := 0; n < b.N; n++ { +// minter.BlockProvision(params) +// } +//} // Next inflation benchmarking // BenchmarkNextInflation-4 1000000 1828 ns/op -func BenchmarkNextInflation(b *testing.B) { - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() - bondedRatio := sdk.NewDecWithPrec(1, 1) - - // run the NextInflationRate function b.N times - for n := 0; n < b.N; n++ { - minter.NextInflationRate(params, bondedRatio) - } - -} +//func BenchmarkNextInflation(b *testing.B) { +// minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) +// params := DefaultParams() +// bondedRatio := sdk.NewDecWithPrec(1, 1) +// +// // run the NextInflationRate function b.N times +// for n := 0; n < b.N; n++ { +// minter.NextInflationRate(params, bondedRatio) +// } +// +//} // Next annual provisions benchmarking // BenchmarkNextAnnualProvisions-4 5000000 251 ns/op diff --git a/x/mint/internal/types/params.go b/x/mint/internal/types/params.go index 864d8ef32e74..1f4b99bed335 100644 --- a/x/mint/internal/types/params.go +++ b/x/mint/internal/types/params.go @@ -9,22 +9,22 @@ import ( // Parameter store keys var ( - KeyMintDenom = []byte("MintDenom") - KeyInflationRateChange = []byte("InflationRateChange") - KeyInflationMax = []byte("InflationMax") - KeyInflationMin = []byte("InflationMin") - KeyGoalBonded = []byte("GoalBonded") - KeyBlocksPerYear = []byte("BlocksPerYear") + KeyMintDenom = []byte("MintDenom") + KeyInflationRate = []byte("InflationRate") + //KeyInflationMax = []byte("InflationMax") + //KeyInflationMin = []byte("InflationMin") + //KeyGoalBonded = []byte("GoalBonded") + KeyBlocksPerYear = []byte("BlocksPerYear") ) // mint parameters type Params struct { - MintDenom string `json:"mint_denom" yaml:"mint_denom"` // type of coin to mint - InflationRateChange sdk.Dec `json:"inflation_rate_change" yaml:"inflation_rate_change"` // maximum annual change in inflation rate - InflationMax sdk.Dec `json:"inflation_max" yaml:"inflation_max"` // maximum inflation rate - InflationMin sdk.Dec `json:"inflation_min" yaml:"inflation_min"` // minimum inflation rate - GoalBonded sdk.Dec `json:"goal_bonded" yaml:"goal_bonded"` // goal of percent bonded atoms - BlocksPerYear uint64 `json:"blocks_per_year" yaml:"blocks_per_year"` // expected blocks per year + MintDenom string `json:"mint_denom" yaml:"mint_denom"` // type of coin to mint + InflationRate sdk.Dec `json:"inflation_rate" yaml:"inflation_rate"` // maximum annual change in inflation rate + //InflationMax sdk.Dec `json:"inflation_max" yaml:"inflation_max"` // maximum inflation rate + //InflationMin sdk.Dec `json:"inflation_min" yaml:"inflation_min"` // minimum inflation rate + //GoalBonded sdk.Dec `json:"goal_bonded" yaml:"goal_bonded"` // goal of percent bonded atoms + BlocksPerYear uint64 `json:"blocks_per_year" yaml:"blocks_per_year"` // expected blocks per year } // ParamTable for minting module. @@ -36,38 +36,38 @@ func NewParams(mintDenom string, inflationRateChange, inflationMax, inflationMin, goalBonded sdk.Dec, blocksPerYear uint64) Params { return Params{ - MintDenom: mintDenom, - InflationRateChange: inflationRateChange, - InflationMax: inflationMax, - InflationMin: inflationMin, - GoalBonded: goalBonded, - BlocksPerYear: blocksPerYear, + MintDenom: mintDenom, + InflationRate: inflationRateChange, + //InflationMax: inflationMax, + //InflationMin: inflationMin, + //GoalBonded: goalBonded, + BlocksPerYear: blocksPerYear, } } // default minting module parameters func DefaultParams() Params { return Params{ - MintDenom: sdk.DefaultBondDenom, - InflationRateChange: sdk.NewDecWithPrec(13, 2), - InflationMax: sdk.NewDecWithPrec(20, 2), - InflationMin: sdk.NewDecWithPrec(7, 2), - GoalBonded: sdk.NewDecWithPrec(67, 2), - BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5 second block times + MintDenom: sdk.DefaultBondDenom, + InflationRate: sdk.NewDecWithPrec(1, 2), + //InflationMax: sdk.NewDecWithPrec(20, 2), + //InflationMin: sdk.NewDecWithPrec(7, 2), + //GoalBonded: sdk.NewDecWithPrec(67, 2), + BlocksPerYear: uint64(60 * 60 * 8766 / 3), // assuming 5 second block times } } // validate params func ValidateParams(params Params) error { - if params.GoalBonded.LT(sdk.ZeroDec()) { - return fmt.Errorf("mint parameter GoalBonded should be positive, is %s ", params.GoalBonded.String()) - } - if params.GoalBonded.GT(sdk.OneDec()) { - return fmt.Errorf("mint parameter GoalBonded must be <= 1, is %s", params.GoalBonded.String()) - } - if params.InflationMax.LT(params.InflationMin) { - return fmt.Errorf("mint parameter Max inflation must be greater than or equal to min inflation") - } + //if params.GoalBonded.LT(sdk.ZeroDec()) { + // return fmt.Errorf("mint parameter GoalBonded should be positive, is %s ", params.GoalBonded.String()) + //} + //if params.GoalBonded.GT(sdk.OneDec()) { + // return fmt.Errorf("mint parameter GoalBonded must be <= 1, is %s", params.GoalBonded.String()) + //} + //if params.InflationMax.LT(params.InflationMin) { + // return fmt.Errorf("mint parameter Max inflation must be greater than or equal to min inflation") + //} if params.MintDenom == "" { return fmt.Errorf("mint parameter MintDenom can't be an empty string") } @@ -77,14 +77,10 @@ func ValidateParams(params Params) error { func (p Params) String() string { return fmt.Sprintf(`Minting Params: Mint Denom: %s - Inflation Rate Change: %s - Inflation Max: %s - Inflation Min: %s - Goal Bonded: %s + Inflation Rate: %s Blocks Per Year: %d `, - p.MintDenom, p.InflationRateChange, p.InflationMax, - p.InflationMin, p.GoalBonded, p.BlocksPerYear, + p.MintDenom, p.InflationRate, p.BlocksPerYear, ) } @@ -92,10 +88,10 @@ func (p Params) String() string { func (p *Params) ParamSetPairs() params.ParamSetPairs { return params.ParamSetPairs{ {KeyMintDenom, &p.MintDenom}, - {KeyInflationRateChange, &p.InflationRateChange}, - {KeyInflationMax, &p.InflationMax}, - {KeyInflationMin, &p.InflationMin}, - {KeyGoalBonded, &p.GoalBonded}, + {KeyInflationRate, &p.InflationRate}, + //{KeyInflationMax, &p.InflationMax}, + //{KeyInflationMin, &p.InflationMin}, + //{KeyGoalBonded, &p.GoalBonded}, {KeyBlocksPerYear, &p.BlocksPerYear}, } } diff --git a/x/mint/module.go b/x/mint/module.go index f56b5415f961..6aea35f111c5 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -43,7 +43,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { var data GenesisState if err := ModuleCdc.UnmarshalJSON(bz, &data); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %s", ModuleName, err) } return ValidateGenesis(data) diff --git a/x/mint/test_common.go b/x/mint/test_common.go new file mode 100644 index 000000000000..154e3e6113d0 --- /dev/null +++ b/x/mint/test_common.go @@ -0,0 +1,97 @@ +// nolint:deadcode unused +package mint + +import ( + "os" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/x/mint/internal/keeper" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + + "github.com/stretchr/testify/require" + + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + sdk "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/mint/internal/types" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/supply" +) + +type testInput struct { + ctx sdk.Context + cdc *codec.Codec + mintKeeper keeper.Keeper +} + +func newTestInput(t *testing.T) testInput { + db := dbm.NewMemDB() + + keyAcc := sdk.NewKVStoreKey(auth.StoreKey) + keySupply := sdk.NewKVStoreKey(supply.StoreKey) + keyStaking := sdk.NewKVStoreKey(staking.StoreKey) + tkeyStaking := sdk.NewTransientStoreKey(staking.TStoreKey) + keyParams := sdk.NewKVStoreKey(params.StoreKey) + tkeyParams := sdk.NewTransientStoreKey(params.TStoreKey) + keyMint := sdk.NewKVStoreKey(types.StoreKey) + + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyStaking, sdk.StoreTypeTransient, nil) + ms.MountStoreWithDB(keyStaking, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keySupply, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyMint, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) + err := ms.LoadLatestVersion() + require.Nil(t, err) + + ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout)) + + feeCollectorAcc := supply.NewEmptyModuleAccount(auth.FeeCollectorName) + notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner, supply.Staking) + bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner, supply.Staking) + minterAcc := supply.NewEmptyModuleAccount(types.ModuleName, supply.Minter) + + blacklistedAddrs := make(map[string]bool) + blacklistedAddrs[feeCollectorAcc.String()] = true + blacklistedAddrs[notBondedPool.String()] = true + blacklistedAddrs[bondPool.String()] = true + blacklistedAddrs[minterAcc.String()] = true + + paramsKeeper := params.NewKeeper(types.ModuleCdc, keyParams, tkeyParams, params.DefaultCodespace) + accountKeeper := auth.NewAccountKeeper(types.ModuleCdc, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount) + bankKeeper := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + maccPerms := map[string][]string{ + auth.FeeCollectorName: nil, + types.ModuleName: []string{supply.Minter}, + staking.NotBondedPoolName: []string{supply.Burner, supply.Staking}, + staking.BondedPoolName: []string{supply.Burner, supply.Staking}, + } + supplyKeeper := supply.NewKeeper(types.ModuleCdc, keySupply, accountKeeper, bankKeeper, maccPerms) + supplyKeeper.SetSupply(ctx, supply.NewSupply(sdk.Coins{})) + + stakingKeeper := staking.NewKeeper( + types.ModuleCdc, keyStaking, tkeyStaking, supplyKeeper, paramsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace, + ) + mintKeeper := keeper.NewKeeper(types.ModuleCdc, keyMint, paramsKeeper.Subspace(types.DefaultParamspace), &stakingKeeper, supplyKeeper, auth.FeeCollectorName) + + // set module accounts + supplyKeeper.SetModuleAccount(ctx, feeCollectorAcc) + supplyKeeper.SetModuleAccount(ctx, minterAcc) + supplyKeeper.SetModuleAccount(ctx, notBondedPool) + supplyKeeper.SetModuleAccount(ctx, bondPool) + + mintKeeper.SetParams(ctx, types.DefaultParams()) + mintKeeper.SetMinter(ctx, types.DefaultInitialMinter()) + + return testInput{ctx, types.ModuleCdc, mintKeeper} +} diff --git a/x/mock/app.go b/x/mock/app.go index 72d0545584e6..b1f05c41631f 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -77,7 +77,7 @@ func NewApp() *App { // Initialize the app. The chainers and blockers can be overwritten before // calling complete setup. app.SetInitChainer(app.InitChainer) - app.SetAnteHandler(auth.NewAnteHandler(app.AccountKeeper, supplyKeeper, auth.DefaultSigVerificationGasConsumer)) + app.SetAnteHandler(auth.NewAnteHandler(app.AccountKeeper, supplyKeeper, auth.DefaultSigVerificationGasConsumer, nil, nil)) // Not sealing for custom extension @@ -296,7 +296,7 @@ func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []s // generate a random coin for each denomination for j := 0; j < len(denoms); j++ { coins[j] = sdk.Coin{Denom: denoms[j], - Amount: RandFromBigInterval(r, randCoinIntervals), + Amount: RandFromBigInterval(r, randCoinIntervals).ToDec(), } } diff --git a/x/params/client/utils/utils.go b/x/params/client/utils/utils.go index 6bcbeb43a520..941233c31f16 100644 --- a/x/params/client/utils/utils.go +++ b/x/params/client/utils/utils.go @@ -30,7 +30,7 @@ type ( Title string `json:"title" yaml:"title"` Description string `json:"description" yaml:"description"` Changes ParamChangesJSON `json:"changes" yaml:"changes"` - Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Deposit sdk.DecCoins `json:"deposit" yaml:"deposit"` } // ParamChangeProposalReq defines a parameter change proposal request body. @@ -41,7 +41,7 @@ type ( Description string `json:"description" yaml:"description"` Changes ParamChangesJSON `json:"changes" yaml:"changes"` Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"` - Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Deposit sdk.DecCoins `json:"deposit" yaml:"deposit"` } ) diff --git a/x/params/errors_okchain.go b/x/params/errors_okchain.go new file mode 100644 index 000000000000..3e7d842afcee --- /dev/null +++ b/x/params/errors_okchain.go @@ -0,0 +1,23 @@ +package params + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + CodeInvalidMinDepositDenom sdk.CodeType = 100 + CodeInvalidMinDepositAmount sdk.CodeType = 101 + CodeInvalidDepositPeriod sdk.CodeType = 102 + CodeInvalidVotingPeriod sdk.CodeType = 103 + CodeInvalidThreshold sdk.CodeType = 104 + CodeInvalidVeto sdk.CodeType = 105 + CodeInvalidMaxProposalNum sdk.CodeType = 106 + CodeInvalidKey sdk.CodeType = 107 + CodeInvalidString sdk.CodeType = 108 +) + +func ErrInvalidString(valuestr string) sdk.Error { + return sdk.NewError(DefaultCodespace, CodeInvalidString, fmt.Sprintf("%s can't convert to a specific type", valuestr)) +} diff --git a/x/params/export_okchain.go b/x/params/export_okchain.go new file mode 100644 index 000000000000..3bff9333e1e3 --- /dev/null +++ b/x/params/export_okchain.go @@ -0,0 +1,9 @@ +package params + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k Keeper) Codespace() sdk.CodespaceType { + return k.codespace +} diff --git a/x/params/helper_okchain.go b/x/params/helper_okchain.go new file mode 100644 index 000000000000..444a17619923 --- /dev/null +++ b/x/params/helper_okchain.go @@ -0,0 +1,21 @@ +package params + +import ( + "strings" +) + +func GetParamSpaceFromKey(keystr string) string { + strs := strings.Split(keystr, "/") + if len(strs) != 2 { + return "" + } + return strs[0] +} + +func GetParamKey(keystr string) string { + strs := strings.Split(keystr, "/") + if len(strs) != 2 { + return "" + } + return strs[1] +} diff --git a/x/params/keeper.go b/x/params/keeper.go index a3dc5c077457..24ee4d766c45 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -18,6 +18,7 @@ type Keeper struct { tkey sdk.StoreKey codespace sdk.CodespaceType spaces map[string]*Subspace + paramSets map[string]ParamSet } // NewKeeper constructs a params keeper @@ -28,6 +29,7 @@ func NewKeeper(cdc *codec.Codec, key *sdk.KVStoreKey, tkey *sdk.TransientStoreKe tkey: tkey, codespace: codespace, spaces: make(map[string]*Subspace), + paramSets: make(map[string]ParamSet), } return k diff --git a/x/params/proposal_handler.go b/x/params/proposal_handler.go index a40d8df838dd..8799f5271b48 100644 --- a/x/params/proposal_handler.go +++ b/x/params/proposal_handler.go @@ -8,8 +8,8 @@ import ( ) func NewParamChangeProposalHandler(k Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) sdk.Error { - switch c := content.(type) { + return func(ctx sdk.Context, proposal *govtypes.Proposal) sdk.Error { + switch c := proposal.Content.(type) { case ParameterChangeProposal: return handleParameterChangeProposal(ctx, k, c) diff --git a/x/params/types/proposal.go b/x/params/types/proposal.go index 1039a082e533..7ff66572e51e 100644 --- a/x/params/types/proposal.go +++ b/x/params/types/proposal.go @@ -16,10 +16,10 @@ const ( // Assert ParameterChangeProposal implements govtypes.Content at compile-time var _ govtypes.Content = ParameterChangeProposal{} -func init() { - govtypes.RegisterProposalType(ProposalTypeChange) - govtypes.RegisterProposalTypeCodec(ParameterChangeProposal{}, "cosmos-sdk/ParameterChangeProposal") -} +//func init() { +// govtypes.RegisterProposalType(ProposalTypeChange) +// govtypes.RegisterProposalTypeCodec(ParameterChangeProposal{}, "cosmos-sdk/ParameterChangeProposal") +//} // ParameterChangeProposal defines a proposal which contains multiple parameter // changes. diff --git a/x/slashing/abci_test.go b/x/slashing/abci_test.go index 5edea6309331..b75dc142da1c 100644 --- a/x/slashing/abci_test.go +++ b/x/slashing/abci_test.go @@ -13,7 +13,7 @@ import ( ) func TestBeginBlocker(t *testing.T) { - ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) power := int64(100) amt := sdk.TokensFromConsensusPower(power) addr, pk := addrs[2], pks[2] diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index 07b55458b82d..bc52d4004729 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -43,7 +43,7 @@ func GetCmdQuerySigningInfo(storeName string, cdc *codec.Codec) *cobra.Command { Short: "Query a validator's signing information", Long: strings.TrimSpace(`Use a validators' consensus public key to find the signing-info for that validator: -$ query slashing signing-info cosmosvalconspub1zcjduepqfhvwcmt7p06fvdgexxhmz0l8c7sgswl7ulv7aulk364x4g5xsw7sr0k2g5 +$ query slashing signing-info okchainvalconspub1zcjduepqfhvwcmt7p06fvdgexxhmz0l8c7sgswl7ulv7aulk364x4g5xsw7sr0k2g5 `), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/x/slashing/genesis_test.go b/x/slashing/genesis_test.go new file mode 100644 index 000000000000..62a63f578693 --- /dev/null +++ b/x/slashing/genesis_test.go @@ -0,0 +1,38 @@ +package slashing + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func TestInitGenesis(t *testing.T) { + cdc, ctx, _, stakingKeeper, _, slashingKeeper := createTestInput(t, DefaultParams()) + appModule := NewAppModule(slashingKeeper, stakingKeeper) + var exportState GenesisState + + // 1.check default export + cdc.MustUnmarshalJSON(appModule.ExportGenesis(ctx), &exportState) + require.Equal(t, DefaultGenesisState(), exportState) + + // 2.change params and check again + initParams := NewParams(10000000000,1000,sdk.MustNewDecFromStr("0.05"), 600000000000,sdk.ZeroDec(),sdk.ZeroDec()) + genesisState := NewGenesisState(initParams, exportState.SigningInfos, exportState.MissedBlocks) + appModule.InitGenesis(ctx, cdc.MustMarshalJSON(genesisState)) + + cdc.MustUnmarshalJSON(appModule.ExportGenesis(ctx), &exportState) + require.Equal(t, genesisState, exportState) + + // 3.change the state.SigningInfos and state.MissedBlocks info and check again + conAddress := sdk.GetConsAddress(pks[0]) + slashingKeeper.addPubkey(ctx, pks[0]) + sigingInfo := NewValidatorSigningInfo(conAddress, 10, 1, time.Now().Add(10000), true, 5, types.Destroying) + slashingKeeper.SetValidatorSigningInfo(ctx, conAddress, sigingInfo) + slashingKeeper.HandleValidatorSignature(ctx, pks[0].Address(), 100,false) + + cdc.MustUnmarshalJSON(appModule.ExportGenesis(ctx), &exportState) + require.Equal(t,1, len(exportState.SigningInfos)) + require.Equal(t, 1 ,len(exportState.MissedBlocks)) +} \ No newline at end of file diff --git a/x/slashing/handler.go b/x/slashing/handler.go index be7885885ac0..2918b6a9bc6e 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -30,15 +30,19 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrNoValidatorForAddress(k.codespace).Result() } - // cannot be unjailed if no self-delegation exists - selfDel := k.sk.Delegation(ctx, sdk.AccAddress(msg.ValidatorAddr), msg.ValidatorAddr) - if selfDel == nil { + if validator.GetMinSelfDelegation().IsZero() { return ErrMissingSelfDelegation(k.codespace).Result() } - if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return ErrSelfDelegationTooLowToUnjail(k.codespace).Result() - } + // cannot be unjailed if no self-delegation exists + //selfDel := k.sk.Delegation(ctx, sdk.AccAddress(msg.ValidatorAddr), msg.ValidatorAddr) + //if selfDel == nil { + // return ErrMissingSelfDelegation(k.codespace).Result() + //} + + //if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { + // return ErrSelfDelegationTooLowToUnjail(k.codespace).Result() + //} // cannot be unjailed if not jailed if !validator.IsJailed() { @@ -52,6 +56,11 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrNoValidatorForAddress(k.codespace).Result() } + if info.ValidatorStatus == types.Destroying{ + //cannot be unjailed while target validator was destroying + return ErrValidatorJailed(k.codespace).Result() + } + // cannot be unjailed if tombstoned if info.Tombstoned { return ErrValidatorJailed(k.codespace).Result() diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 854a1d14041c..7dc3317eadc9 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -9,12 +9,13 @@ import ( abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" ) func TestCannotUnjailUnlessJailed(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) slh := NewHandler(keeper) amt := sdk.TokensFromConsensusPower(100) addr, val := addrs[0], pks[0] @@ -38,7 +39,7 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams()) slh := NewHandler(keeper) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.TokensFromConsensusPower(amtInt) @@ -57,17 +58,24 @@ func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { undelegateMsg := staking.NewMsgUndelegate(sdk.AccAddress(addr), addr, unbondAmt) got = staking.NewHandler(sk)(ctx, undelegateMsg) + require.True(t, sk.Validator(ctx, addr).IsJailed()) + validator, found := sk.GetValidator(ctx, addr) + if found{ + validator.MinSelfDelegation = sdk.NewInt(0) + sk.SetValidator(ctx,validator) + } + // assert non-jailed validator can't be unjailed got = slh(ctx, NewMsgUnjail(addr)) require.False(t, got.IsOK(), "allowed unjail of validator with less than MinSelfDelegation") - require.EqualValues(t, CodeValidatorNotJailed, got.Code) + require.EqualValues(t, CodeMissingSelfDelegation, got.Code) require.EqualValues(t, DefaultCodespace, got.Codespace) } func TestJailedValidatorDelegations(t *testing.T) { - ctx, _, stakingKeeper, _, slashingKeeper := createTestInput(t, DefaultParams()) + _, ctx, _, stakingKeeper, _, slashingKeeper := createTestInput(t, DefaultParams()) stakingParams := stakingKeeper.GetParams(ctx) stakingParams.UnbondingTime = 0 @@ -86,7 +94,7 @@ func TestJailedValidatorDelegations(t *testing.T) { staking.EndBlocker(ctx, stakingKeeper) // set dummy signing info - newInfo := NewValidatorSigningInfo(consAddr, 0, 0, time.Unix(0, 0), false, 0) + newInfo := NewValidatorSigningInfo(consAddr, 0, 0, time.Unix(0, 0), false, 0, types.Created) slashingKeeper.SetValidatorSigningInfo(ctx, consAddr, newInfo) // delegate tokens to the validator @@ -109,6 +117,8 @@ func TestJailedValidatorDelegations(t *testing.T) { validator, found := stakingKeeper.GetValidator(ctx, valAddr) require.True(t, found) require.True(t, validator.IsJailed()) + validator.MinSelfDelegation = sdk.ZeroInt() + stakingKeeper.SetValidator(ctx,validator) // verify the validator cannot unjail itself got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) @@ -119,6 +129,8 @@ func TestJailedValidatorDelegations(t *testing.T) { got = staking.NewHandler(stakingKeeper)(ctx, msgSelfDelegate) require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) + validator.MinSelfDelegation = sdk.NewInt(1) + stakingKeeper.SetValidator(ctx,validator) // verify the validator can now unjail itself got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) require.True(t, got.IsOK(), "expected jailed validator to be able to unjail, got: %v", got) diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 7535ab4acb10..7db472326d99 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -21,6 +21,7 @@ func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ time.Unix(0, 0), false, 0, + types.Created, ) k.SetValidatorSigningInfo(ctx, address, signingInfo) } @@ -30,11 +31,20 @@ func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { validator := k.sk.Validator(ctx, valAddr) k.addPubkey(ctx, validator.GetConsPubKey()) + k.modifyValidatorStatus(ctx, validator.GetConsAddr(), types.Created) } // When a validator is removed, delete the address-pubkey relation. func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) { k.deleteAddrPubkeyRelation(ctx, crypto.Address(address)) + k.modifyValidatorStatus(ctx, address, types.Destroyed) +} + +func (k Keeper) AfterValidatorDestroyed(ctx sdk.Context, valAddr sdk.ValAddress) { + validator := k.sk.Validator(ctx, valAddr) + if validator != nil { + k.modifyValidatorStatus(ctx, validator.GetConsAddr(), types.Destroying) + } } //_________________________________________________________________________________________ @@ -66,6 +76,11 @@ func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { h.k.AfterValidatorCreated(ctx, valAddr) } +// Implements when validator destroyed +func (h Hooks) AfterValidatorDestroyed(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) { + h.k.AfterValidatorDestroyed(ctx, valAddr) +} + // nolint - unused hooks func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {} func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 52b186857e41..fb25c456cd17 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -101,10 +101,10 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Note that this *can* result in a negative "distributionHeight", up to -ValidatorUpdateDelay, // i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block. // That's fine since this is just used to filter unbonding delegations & redelegations. - distributionHeight := infractionHeight - sdk.ValidatorUpdateDelay + //distributionHeight := infractionHeight - sdk.ValidatorUpdateDelay // get the percentage slash penalty fraction - fraction := k.SlashFractionDoubleSign(ctx) + //fraction := k.SlashFractionDoubleSign(ctx) // Slash validator // `power` is the int64 power of the validator as provided to/by @@ -119,7 +119,8 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio sdk.NewAttribute(types.AttributeKeyReason, types.AttributeValueDoubleSign), ), ) - k.sk.Slash(ctx, consAddr, distributionHeight, power, fraction) + //don't slashing tokens, just jail the validator + //k.sk.Slash(ctx, consAddr, distributionHeight, power, fraction) // Jail validator if not already jailed // begin unbonding validator if not already unbonding (tombstone) @@ -131,6 +132,7 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio ), ) k.sk.Jail(ctx, consAddr) + k.sk.AppendAbandonedValidatorAddrs(ctx, consAddr) } // Set tombstoned to be true @@ -214,7 +216,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p // Note that this *can* result in a negative "distributionHeight" up to -ValidatorUpdateDelay-1, // i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block. // That's fine since this is just used to filter unbonding delegations & redelegations. - distributionHeight := height - sdk.ValidatorUpdateDelay - 1 + // distributionHeight := height - sdk.ValidatorUpdateDelay - 1 ctx.EventManager().EmitEvent( sdk.NewEvent( @@ -225,8 +227,10 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p sdk.NewAttribute(types.AttributeKeyJailed, consAddr.String()), ), ) - k.sk.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx)) + //don't slashing tokens, just jail the validator + //k.sk.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx)) k.sk.Jail(ctx, consAddr) + k.sk.AppendAbandonedValidatorAddrs(ctx, consAddr) signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeJailDuration(ctx)) diff --git a/x/slashing/keeper_okchain.go b/x/slashing/keeper_okchain.go new file mode 100644 index 000000000000..0ea451b12b4f --- /dev/null +++ b/x/slashing/keeper_okchain.go @@ -0,0 +1,15 @@ +package slashing + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/slashing/types" +) + +func (k Keeper) modifyValidatorStatus(ctx sdk.Context, consAddress sdk.ConsAddress, status types.ValStatus) { + signingInfo, found := k.getValidatorSigningInfo(ctx, consAddress) + if found { + //update validator status to Created + signingInfo.ValidatorStatus = status + k.SetValidatorSigningInfo(ctx, consAddress, signingInfo) + } +} diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 523cc6485b91..eae796b285cf 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -28,7 +28,7 @@ func keeperTestParams() types.Params { func TestHandleDoubleSign(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) // validator added pre-genesis ctx = ctx.WithBlockHeight(-1) power := int64(100) @@ -55,8 +55,9 @@ func TestHandleDoubleSign(t *testing.T) { require.True(t, sk.Validator(ctx, operatorAddr).IsJailed()) // tokens should be decreased + // don't slashing tokens, just jail the validator newTokens := sk.Validator(ctx, operatorAddr).GetTokens() - require.True(t, newTokens.LT(oldTokens)) + require.True(t, newTokens.Equal(oldTokens)) // New evidence keeper.HandleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), power) @@ -89,7 +90,7 @@ func TestHandleDoubleSign(t *testing.T) { func TestPastMaxEvidenceAge(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) // validator added pre-genesis ctx = ctx.WithBlockHeight(-1) power := int64(100) @@ -126,7 +127,7 @@ func TestPastMaxEvidenceAge(t *testing.T) { func TestHandleAbsentValidator(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) power := int64(100) amt := sdk.TokensFromConsensusPower(power) addr, val := addrs[0], pks[0] @@ -175,7 +176,7 @@ func TestHandleAbsentValidator(t *testing.T) { validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) bondPool := sk.GetBondedPool(ctx) - require.True(sdk.IntEq(t, amt, bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)))) + require.True(sdk.IntEq(t, amt, bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)).RoundInt())) // 501st block missed ctx = ctx.WithBlockHeight(height) @@ -232,7 +233,7 @@ func TestHandleAbsentValidator(t *testing.T) { // validator should have been slashed bondPool = sk.GetBondedPool(ctx) - require.Equal(t, amt.Int64()-slashAmt, bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)).Int64()) + require.Equal(t, sdk.NewDec(amt.Int64()-slashAmt).Int64(), bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)).Int64()) // Validator start height should not have been changed info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) @@ -248,22 +249,14 @@ func TestHandleAbsentValidator(t *testing.T) { validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) - // 500 signed blocks - nextHeight := height + keeper.MinSignedPerWindow(ctx) + 1 + // maxmissed signed blocks + maxMissed := keeper.SignedBlocksWindow(ctx) - keeper.MinSignedPerWindow(ctx) + nextHeight := height + maxMissed + 1 for ; height < nextHeight; height++ { ctx = ctx.WithBlockHeight(height) keeper.HandleValidatorSignature(ctx, val.Address(), power, false) } - // end block - staking.EndBlocker(ctx, sk) - - // validator should be jailed again after 500 unsigned blocks - nextHeight = height + keeper.MinSignedPerWindow(ctx) + 1 - for ; height <= nextHeight; height++ { - ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) - } // end block staking.EndBlocker(ctx, sk) @@ -277,7 +270,7 @@ func TestHandleAbsentValidator(t *testing.T) { // and that they are not immediately jailed func TestHandleNewValidator(t *testing.T) { // initial setup - ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams()) addr, val := addrs[0], pks[0] amt := sdk.TokensFromConsensusPower(100) sh := staking.NewHandler(sk) @@ -313,7 +306,7 @@ func TestHandleNewValidator(t *testing.T) { require.Equal(t, sdk.Bonded, validator.GetStatus()) bondPool := sk.GetBondedPool(ctx) expTokens := sdk.TokensFromConsensusPower(100) - require.Equal(t, expTokens.Int64(), bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)).Int64()) + require.Equal(t, sdk.NewDecFromBigInt(expTokens.BigInt()).Int64(), bondPool.GetCoins().AmountOf(sk.BondDenom(ctx)).Int64()) } // Test a jailed validator being "down" twice @@ -321,7 +314,7 @@ func TestHandleNewValidator(t *testing.T) { func TestHandleAlreadyJailed(t *testing.T) { // initial setup - ctx, _, sk, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, _, sk, _, keeper := createTestInput(t, DefaultParams()) power := int64(100) amt := sdk.TokensFromConsensusPower(power) addr, val := addrs[0], pks[0] @@ -351,8 +344,9 @@ func TestHandleAlreadyJailed(t *testing.T) { require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed - resultingTokens := amt.Sub(sdk.TokensFromConsensusPower(1)) - require.Equal(t, resultingTokens, validator.GetTokens()) + // only jailed + //resultingTokens := amt.Sub(sdk.TokensFromConsensusPower(1)) + require.Equal(t, amt, validator.GetTokens()) // another block missed ctx = ctx.WithBlockHeight(height) @@ -360,7 +354,7 @@ func TestHandleAlreadyJailed(t *testing.T) { // validator should not have been slashed twice validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) - require.Equal(t, resultingTokens, validator.GetTokens()) + require.Equal(t, amt, validator.GetTokens()) } @@ -371,7 +365,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { // initial setup // keeperTestParams set the SignedBlocksWindow to 1000 and MaxMissedBlocksPerWindow to 500 - ctx, _, sk, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, _, sk, _, keeper := createTestInput(t, keeperTestParams()) params := sk.GetParams(ctx) params.MaxValidators = 1 sk.SetParams(ctx, params) @@ -383,6 +377,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) require.True(t, got.IsOK()) staking.EndBlocker(ctx, sk) + maxMissed := keeper.SignedBlocksWindow(ctx) - keeper.MinSignedPerWindow(ctx) // 100 first blocks OK height := int64(0) @@ -424,7 +419,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { // validator misses 500 more blocks, 501 total latest := height - for ; height < latest+500; height++ { + for ; height < latest+maxMissed; height++ { ctx = ctx.WithBlockHeight(height) keeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) } @@ -460,8 +455,9 @@ func TestValidatorDippingInAndOut(t *testing.T) { require.Equal(t, sdk.Bonded, validator.Status) // validator misses 501 blocks + latest = height - for ; height < latest+501; height++ { + for ; height < latest+maxMissed+1; height++ { ctx = ctx.WithBlockHeight(height) keeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) } diff --git a/x/slashing/module.go b/x/slashing/module.go index 5aa922be1bd2..0ee0ae01938e 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -46,7 +46,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { var data GenesisState if err := ModuleCdc.UnmarshalJSON(bz, &data); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %s", types.ModuleName, err) } return ValidateGenesis(data) diff --git a/x/slashing/querier_test.go b/x/slashing/querier_test.go index a4941e0a9efe..5f89992670f8 100644 --- a/x/slashing/querier_test.go +++ b/x/slashing/querier_test.go @@ -10,7 +10,7 @@ import ( ) func TestNewQuerier(t *testing.T) { - ctx, _, _, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, _, _, _, keeper := createTestInput(t, keeperTestParams()) querier := NewQuerier(keeper) query := abci.RequestQuery{ @@ -24,7 +24,7 @@ func TestNewQuerier(t *testing.T) { func TestQueryParams(t *testing.T) { cdc := codec.New() - ctx, _, _, _, keeper := createTestInput(t, keeperTestParams()) + _, ctx, _, _, _, keeper := createTestInput(t, keeperTestParams()) var params Params diff --git a/x/slashing/signing_info_test.go b/x/slashing/signing_info_test.go index d6803af8da48..ec5f8f5f65d0 100644 --- a/x/slashing/signing_info_test.go +++ b/x/slashing/signing_info_test.go @@ -7,10 +7,11 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/slashing/types" ) func TestGetSetValidatorSigningInfo(t *testing.T) { - ctx, _, _, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, _, _, _, keeper := createTestInput(t, DefaultParams()) info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0])) require.False(t, found) newInfo := NewValidatorSigningInfo( @@ -20,6 +21,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) { time.Unix(2, 0), false, int64(10), + types.Created, ) keeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0]), newInfo) info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0])) @@ -31,7 +33,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) { } func TestGetSetValidatorMissedBlockBitArray(t *testing.T) { - ctx, _, _, _, keeper := createTestInput(t, DefaultParams()) + _, ctx, _, _, _, keeper := createTestInput(t, DefaultParams()) missed := keeper.getValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(addrs[0]), 0) require.False(t, missed) // treat empty key as not missed keeper.setValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(addrs[0]), 0, true) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 224052857f21..6dec680903b1 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -52,7 +52,8 @@ func createTestCodec() *codec.Codec { return cdc } -func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, staking.Keeper, params.Subspace, Keeper) { +func createTestInput(t *testing.T, defaults Params) (*codec.Codec, sdk.Context, bank.Keeper, staking.Keeper, + params.Subspace, Keeper) { keyAcc := sdk.NewKVStoreKey(auth.StoreKey) keyStaking := sdk.NewKVStoreKey(staking.StoreKey) tkeyStaking := sdk.NewTransientStoreKey(staking.TStoreKey) @@ -123,7 +124,7 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s InitGenesis(ctx, keeper, sk, GenesisState{defaults, nil, nil}) }) - return ctx, bk, sk, paramstore, keeper + return cdc, ctx, bk, sk, paramstore, keeper } func newPubKey(pk string) (res crypto.PubKey) { diff --git a/x/slashing/types/expected_keepers.go b/x/slashing/types/expected_keepers.go index 4626e079b11a..bd4dc6701e53 100644 --- a/x/slashing/types/expected_keepers.go +++ b/x/slashing/types/expected_keepers.go @@ -20,17 +20,14 @@ type StakingKeeper interface { Validator(sdk.Context, sdk.ValAddress) exported.ValidatorI // get a particular validator by operator address ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) exported.ValidatorI // get a particular validator by consensus address - // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction - Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec) Jail(sdk.Context, sdk.ConsAddress) // jail a validator Unjail(sdk.Context, sdk.ConsAddress) // unjail a validator - // Delegation allows for getting a particular delegation for a given validator - // and delegator outside the scope of the staking module. - Delegation(sdk.Context, sdk.AccAddress, sdk.ValAddress) exported.DelegationI - // MaxValidators returns the maximum amount of bonded validators MaxValidators(sdk.Context) uint16 + + // kick out the bonded validator in an epoch + AppendAbandonedValidatorAddrs(ctx sdk.Context, ConsAddr sdk.ConsAddress) } // StakingHooks event hooks for staking validator object @@ -39,4 +36,6 @@ type StakingHooks interface { AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is deleted AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is bonded + /* required by okchain */ + AfterValidatorDestroyed(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is destroyed by tx } diff --git a/x/slashing/types/msg_test.go b/x/slashing/types/msg_test.go index 31f7a70e75db..81f0bd9d18cb 100644 --- a/x/slashing/types/msg_test.go +++ b/x/slashing/types/msg_test.go @@ -14,7 +14,7 @@ func TestMsgUnjailGetSignBytes(t *testing.T) { bytes := msg.GetSignBytes() require.Equal( t, - `{"type":"cosmos-sdk/MsgUnjail","value":{"address":"cosmosvaloper1v93xxeqhg9nn6"}}`, + `{"type":"cosmos-sdk/MsgUnjail","value":{"address":"okchainvaloper1v93xxeqhet2kl"}}`, string(bytes), ) } diff --git a/x/slashing/types/params.go b/x/slashing/types/params.go index 532324a28d3d..42b146c22570 100644 --- a/x/slashing/types/params.go +++ b/x/slashing/types/params.go @@ -12,16 +12,18 @@ import ( const ( DefaultParamspace = ModuleName DefaultMaxEvidenceAge = 60 * 2 * time.Second - DefaultSignedBlocksWindow = int64(100) + DefaultSignedBlocksWindow = int64(10000) DefaultDowntimeJailDuration = 60 * 10 * time.Second ) // The Double Sign Jail period ends at Max Time supported by Amino (Dec 31, 9999 - 23:59:59 GMT) var ( DoubleSignJailEndTime = time.Unix(253402300799, 0) - DefaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1) - DefaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20)) - DefaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100)) + DefaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 2) + DefaultSlashFractionDoubleSign = sdk.ZeroDec() + DefaultSlashFractionDowntime = sdk.ZeroDec() + //DefaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20)) + //DefaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100)) ) // Parameter store keys diff --git a/x/slashing/types/signing_info.go b/x/slashing/types/signing_info.go index 804db7b97625..5bb7aa8c92a4 100644 --- a/x/slashing/types/signing_info.go +++ b/x/slashing/types/signing_info.go @@ -7,6 +7,18 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +type ValStatus byte + +const ( + Created ValStatus = 0x00 + Destroying ValStatus = 0x01 + Destroyed ValStatus = 0x02 + + ValStatusCreated = "Created" + ValStatusDestroying = "Destroying" + ValStatusDestroyed = "Destroied" +) + // Signing info for a validator type ValidatorSigningInfo struct { Address sdk.ConsAddress `json:"address" yaml:"address"` // validator consensus address @@ -15,12 +27,13 @@ type ValidatorSigningInfo struct { JailedUntil time.Time `json:"jailed_until" yaml:"jailed_until"` // timestamp validator cannot be unjailed until Tombstoned bool `json:"tombstoned" yaml:"tombstoned"` // whether or not a validator has been tombstoned (killed out of validator set) MissedBlocksCounter int64 `json:"missed_blocks_counter" yaml:"missed_blocks_counter"` // missed blocks counter (to avoid scanning the array every time) + ValidatorStatus ValStatus `json:"validator_status" yaml:"validator_status"` } // Construct a new `ValidatorSigningInfo` struct func NewValidatorSigningInfo( condAddr sdk.ConsAddress, startHeight, indexOffset int64, - jailedUntil time.Time, tombstoned bool, missedBlocksCounter int64, + jailedUntil time.Time, tombstoned bool, missedBlocksCounter int64, validatorStatus ValStatus, ) ValidatorSigningInfo { return ValidatorSigningInfo{ @@ -30,6 +43,7 @@ func NewValidatorSigningInfo( JailedUntil: jailedUntil, Tombstoned: tombstoned, MissedBlocksCounter: missedBlocksCounter, + ValidatorStatus: validatorStatus, } } diff --git a/x/staking/exported/exported.go b/x/staking/exported/exported.go index 88fa00c02468..6cc3330af83b 100644 --- a/x/staking/exported/exported.go +++ b/x/staking/exported/exported.go @@ -27,7 +27,7 @@ type ValidatorI interface { GetBondedTokens() sdk.Int // validator bonded tokens GetConsensusPower() int64 // validation power in tendermint GetCommission() sdk.Dec // validator commission rate - GetMinSelfDelegation() sdk.Int // validator minimum self delegation + GetMinSelfDelegation() sdk.Dec // validator minimum self delegation GetDelegatorShares() sdk.Dec // total outstanding delegator shares TokensFromShares(sdk.Dec) sdk.Dec // token worth of provided delegator shares TokensFromSharesTruncated(sdk.Dec) sdk.Dec // token worth of provided delegator shares, truncated diff --git a/x/staking/handler.go b/x/staking/handler.go index 875793c2bc46..9a57ad99b477 100644 --- a/x/staking/handler.go +++ b/x/staking/handler.go @@ -153,7 +153,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k // move coins from the msg.Address account to a (self-delegation) delegator account // the validator account and global shares are updated within here // NOTE source will always be from a wallet which are unbonded - _, err = k.Delegate(ctx, msg.DelegatorAddress, msg.Value.Amount, sdk.Unbonded, validator, true) + _, err = k.Delegate(ctx, msg.DelegatorAddress, msg.Value.Amount.RoundInt(), sdk.Unbonded, validator, true) if err != nil { return err.Result() } @@ -240,7 +240,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) } // NOTE: source funds are always unbonded - _, err := k.Delegate(ctx, msg.DelegatorAddress, msg.Amount.Amount, sdk.Unbonded, validator, true) + _, err := k.Delegate(ctx, msg.DelegatorAddress, msg.Amount.Amount.RoundInt(), sdk.Unbonded, validator, true) if err != nil { return err.Result() } @@ -263,7 +263,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keeper) sdk.Result { shares, err := k.ValidateUnbondAmount( - ctx, msg.DelegatorAddress, msg.ValidatorAddress, msg.Amount.Amount, + ctx, msg.DelegatorAddress, msg.ValidatorAddress, msg.Amount.Amount.RoundInt(), ) if err != nil { return err.Result() @@ -298,7 +298,7 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) sdk.Result { shares, err := k.ValidateUnbondAmount( - ctx, msg.DelegatorAddress, msg.ValidatorSrcAddress, msg.Amount.Amount, + ctx, msg.DelegatorAddress, msg.ValidatorSrcAddress, msg.Amount.Amount.RoundInt(), ) if err != nil { return err.Result() diff --git a/x/staking/keeper/invariants.go b/x/staking/keeper/invariants.go index e89cfab1d047..7762ed8fd1e5 100644 --- a/x/staking/keeper/invariants.go +++ b/x/staking/keeper/invariants.go @@ -76,7 +76,7 @@ func ModuleAccountInvariants(k Keeper) sdk.Invariant { poolBonded := bondedPool.GetCoins().AmountOf(bondDenom) poolNotBonded := notBondedPool.GetCoins().AmountOf(bondDenom) - broken := !poolBonded.Equal(bonded) || !poolNotBonded.Equal(notBonded) + broken := !poolBonded.Equal(bonded.ToDec()) || !poolNotBonded.Equal(notBonded.ToDec()) // Bonded tokens should equal sum of tokens with bonded validators // Not-bonded tokens should equal unbonding delegations plus tokens on unbonded validators diff --git a/x/staking/keeper/pool.go b/x/staking/keeper/pool.go index 4ceb02446d93..5d1d1e16906f 100644 --- a/x/staking/keeper/pool.go +++ b/x/staking/keeper/pool.go @@ -55,13 +55,13 @@ func (k Keeper) burnNotBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error { } // TotalBondedTokens total staking tokens supply which is bonded -func (k Keeper) TotalBondedTokens(ctx sdk.Context) sdk.Int { +func (k Keeper) TotalBondedTokens(ctx sdk.Context) sdk.Dec { bondedPool := k.GetBondedPool(ctx) return bondedPool.GetCoins().AmountOf(k.BondDenom(ctx)) } // StakingTokenSupply staking tokens from the total supply -func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Int { +func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Dec { return k.supplyKeeper.GetSupply(ctx).GetTotal().AmountOf(k.BondDenom(ctx)) } @@ -71,7 +71,7 @@ func (k Keeper) BondedRatio(ctx sdk.Context) sdk.Dec { stakeSupply := k.StakingTokenSupply(ctx) if stakeSupply.IsPositive() { - return bondedPool.GetCoins().AmountOf(k.BondDenom(ctx)).ToDec().QuoInt(stakeSupply) + return bondedPool.GetCoins().AmountOf(k.BondDenom(ctx)).Quo(stakeSupply) } return sdk.ZeroDec() } diff --git a/x/staking/keeper/querier.go b/x/staking/keeper/querier.go index 4cc4be19d841..50bd70308c4f 100644 --- a/x/staking/keeper/querier.go +++ b/x/staking/keeper/querier.go @@ -314,8 +314,8 @@ func queryPool(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { } pool := types.NewPool( - notBondedPool.GetCoins().AmountOf(bondDenom), - bondedPool.GetCoins().AmountOf(bondDenom), + notBondedPool.GetCoins().AmountOf(bondDenom).RoundInt(), + bondedPool.GetCoins().AmountOf(bondDenom).RoundInt(), ) res, err := codec.MarshalJSONIndent(types.ModuleCdc, pool) diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index 7b782d682e80..4ded05eed2f2 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -295,3 +295,7 @@ func sortNoLongerBonded(last validatorsByAddr) [][]byte { }) return noLongerBonded } + +// append validator addresses to kick out +func (k Keeper) AppendAbandonedValidatorAddrs(ctx sdk.Context, ConsAddr sdk.ConsAddress) { +} \ No newline at end of file diff --git a/x/staking/simulation/msgs.go b/x/staking/simulation/msgs.go index c16d4075cb48..84722a0c9752 100644 --- a/x/staking/simulation/msgs.go +++ b/x/staking/simulation/msgs.go @@ -34,15 +34,15 @@ func SimulateMsgCreateValidator(m auth.AccountKeeper, k staking.Keeper) simulati acc := simulation.RandomAcc(r, accs) address := sdk.ValAddress(acc.Address) amount := m.GetAccount(ctx, acc.Address).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = simulation.RandomAmount(r, amount) + if amount.GT(sdk.ZeroDec()) { + amount = simulation.RandomAmount(r, amount.RoundInt()).ToDec() } - if amount.Equal(sdk.ZeroInt()) { + if amount.Equal(sdk.ZeroDec()) { return simulation.NoOpMsg(staking.ModuleName), nil, nil } - selfDelegation := sdk.NewCoin(denom, amount) + selfDelegation := sdk.NewDecCoinFromDec(denom, amount) msg := staking.NewMsgCreateValidator(address, acc.PubKey, selfDelegation, description, commission, sdk.OneInt()) @@ -111,15 +111,15 @@ func SimulateMsgDelegate(m auth.AccountKeeper, k staking.Keeper) simulation.Oper delegatorAcc := simulation.RandomAcc(r, accs) delegatorAddress := delegatorAcc.Address amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = simulation.RandomAmount(r, amount) + if amount.GT(sdk.ZeroDec()) { + amount = simulation.RandomAmount(r, amount.RoundInt()).ToDec() } - if amount.Equal(sdk.ZeroInt()) { + if amount.Equal(sdk.ZeroDec()) { return simulation.NoOpMsg(staking.ModuleName), nil, nil } msg := staking.NewMsgDelegate( - delegatorAddress, validatorAddress, sdk.NewCoin(denom, amount)) + delegatorAddress, validatorAddress, sdk.NewDecCoinFromDec(denom, amount)) if msg.ValidateBasic() != nil { return simulation.NoOpMsg(staking.ModuleName), nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) @@ -196,15 +196,15 @@ func SimulateMsgBeginRedelegate(m auth.AccountKeeper, k staking.Keeper) simulati delegatorAddress := delegatorAcc.Address // TODO amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = simulation.RandomAmount(r, amount) + if amount.GT(sdk.ZeroDec()) { + amount = simulation.RandomAmount(r, amount.RoundInt()).ToDec() } - if amount.Equal(sdk.ZeroInt()) { + if amount.Equal(sdk.ZeroDec()) { return simulation.NoOpMsg(staking.ModuleName), nil, nil } msg := staking.NewMsgBeginRedelegate( - delegatorAddress, srcValidatorAddress, destValidatorAddress, sdk.NewCoin(denom, amount), + delegatorAddress, srcValidatorAddress, destValidatorAddress, sdk.NewDecCoinFromDec(denom, amount), ) if msg.ValidateBasic() != nil { return simulation.NoOpMsg(staking.ModuleName), nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index d3faecf820f7..c70656c13702 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -51,18 +51,14 @@ type ValidatorSet interface { Validator(sdk.Context, sdk.ValAddress) stakingexported.ValidatorI // get a particular validator by operator address ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingexported.ValidatorI // get a particular validator by consensus address - TotalBondedTokens(sdk.Context) sdk.Int // total bonded tokens within the validator set - StakingTokenSupply(sdk.Context) sdk.Int // total staking token supply + TotalBondedTokens(sdk.Context) sdk.Dec // total bonded tokens within the validator set + StakingTokenSupply(sdk.Context) sdk.Dec // total staking token supply // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec) Jail(sdk.Context, sdk.ConsAddress) // jail a validator Unjail(sdk.Context, sdk.ConsAddress) // unjail a validator - // Delegation allows for getting a particular delegation for a given validator - // and delegator outside the scope of the staking module. - Delegation(sdk.Context, sdk.AccAddress, sdk.ValAddress) stakingexported.DelegationI - // MaxValidators returns the maximum amount of bonded validators MaxValidators(sdk.Context) uint16 } diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index cc991389ca22..5cdc4dda691c 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -130,7 +130,7 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error { if !sdk.AccAddress(msg.ValidatorAddress).Equals(msg.DelegatorAddress) { return ErrBadValidatorAddr(DefaultCodespace) } - if msg.Value.Amount.LTE(sdk.ZeroInt()) { + if msg.Value.Amount.LTE(sdk.ZeroDec()) { return ErrBadDelegationAmount(DefaultCodespace) } if msg.Description == (Description{}) { @@ -145,9 +145,9 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error { if !msg.MinSelfDelegation.GT(sdk.ZeroInt()) { return ErrMinSelfDelegationInvalid(DefaultCodespace) } - if msg.Value.Amount.LT(msg.MinSelfDelegation) { - return ErrSelfDelegationBelowMinimum(DefaultCodespace) - } + //if msg.Value.Amount.LT(msg.MinSelfDelegation) { + // return ErrSelfDelegationBelowMinimum(DefaultCodespace) + //} return nil } @@ -247,7 +247,7 @@ func (msg MsgDelegate) ValidateBasic() sdk.Error { if msg.ValidatorAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } - if msg.Amount.Amount.LTE(sdk.ZeroInt()) { + if msg.Amount.Amount.LTE(sdk.ZeroDec()) { return ErrBadDelegationAmount(DefaultCodespace) } return nil @@ -298,7 +298,7 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error { if msg.ValidatorDstAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } - if msg.Amount.Amount.LTE(sdk.ZeroInt()) { + if msg.Amount.Amount.LTE(sdk.ZeroDec()) { return ErrBadSharesAmount(DefaultCodespace) } return nil @@ -338,7 +338,7 @@ func (msg MsgUndelegate) ValidateBasic() sdk.Error { if msg.ValidatorAddress.Empty() { return ErrNilValidatorAddr(DefaultCodespace) } - if msg.Amount.Amount.LTE(sdk.ZeroInt()) { + if msg.Amount.Amount.LTE(sdk.ZeroDec()) { return ErrBadSharesAmount(DefaultCodespace) } return nil diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index 014ff84d3a54..4bac4bca2719 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -482,15 +482,17 @@ func (v Validator) RemoveDelShares(delShares sdk.Dec) (Validator, sdk.Int) { } // nolint - for ValidatorI -func (v Validator) IsJailed() bool { return v.Jailed } -func (v Validator) GetMoniker() string { return v.Description.Moniker } -func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddress } -func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } -func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } -func (v Validator) GetTokens() sdk.Int { return v.Tokens } -func (v Validator) GetBondedTokens() sdk.Int { return v.BondedTokens() } -func (v Validator) GetConsensusPower() int64 { return v.ConsensusPower() } -func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } -func (v Validator) GetMinSelfDelegation() sdk.Int { return v.MinSelfDelegation } -func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } +func (v Validator) IsJailed() bool { return v.Jailed } +func (v Validator) GetMoniker() string { return v.Description.Moniker } +func (v Validator) GetStatus() sdk.BondStatus { return v.Status } +func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddress } +func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } +func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } +func (v Validator) GetTokens() sdk.Int { return v.Tokens } +func (v Validator) GetBondedTokens() sdk.Int { return v.BondedTokens() } +func (v Validator) GetConsensusPower() int64 { return v.ConsensusPower() } +func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } +func (v Validator) GetMinSelfDelegation() sdk.Dec { + return sdk.NewDecFromBigInt(v.MinSelfDelegation.BigInt()) +} +func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } diff --git a/x/supply/client/cli/query.go b/x/supply/client/cli/query.go index de0f25d22f2b..ac6ba2dbd2e8 100644 --- a/x/supply/client/cli/query.go +++ b/x/supply/client/cli/query.go @@ -94,7 +94,7 @@ func querySupplyOf(cliCtx context.CLIContext, cdc *codec.Codec, denom string) er return err } - var supply sdk.Int + var supply sdk.Dec err = cdc.UnmarshalJSON(res, &supply) if err != nil { return err diff --git a/x/supply/genesis_test.go b/x/supply/genesis_test.go new file mode 100644 index 000000000000..5cad7e5fffee --- /dev/null +++ b/x/supply/genesis_test.go @@ -0,0 +1,39 @@ +package supply + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/supply/internal/keeper" + "github.com/stretchr/testify/require" + "testing" +) + +func TestInitGenesis(t *testing.T) { + _, ctx, accKeeper, supplyKeeper := keeper.CreateTestInput(t, false, 100,2) + appModule := NewAppModule(supplyKeeper, accKeeper) + + // 1.check default export + require.Equal(t, `{"supply":[{"denom":"okt","amount":"20000000000.00000000"}]}`, + string(appModule.ExportGenesis(ctx))) + + // 2.init again && check + newCdc, newCtx, newAccKeeper, newSupplyKeeper := keeper.CreateTestInput(t, false, 100,2) + newAppModule := NewAppModule(newSupplyKeeper, newAccKeeper) + + coins := sdk.Coins{{"okt",sdk.NewDec(100000)},{"usd", sdk.NewDec(1000)}} + genesisState := GenesisState{coins} + newAppModule.InitGenesis(newCtx, newCdc.MustMarshalJSON(genesisState)) + + var exportGenesisState GenesisState + newCdc.MustUnmarshalJSON(newAppModule.ExportGenesis(newCtx), &exportGenesisState) + require.Equal(t, genesisState, exportGenesisState) + + // 3. mint coins + addCoins := sdk.Coins{{"rmb", sdk.NewDec(1000)}} + genesisState.Supply = genesisState.Supply.Add(addCoins) + + err := newSupplyKeeper.MintCoins(newCtx, "minter", addCoins) + require.Nil(t, err) + + newCdc.MustUnmarshalJSON(newAppModule.ExportGenesis(newCtx), &exportGenesisState) + require.Equal(t, genesisState, exportGenesisState) +} diff --git a/x/supply/internal/keeper/bank_test.go b/x/supply/internal/keeper/bank_test.go index c331e1e277c2..6e46a96651bb 100644 --- a/x/supply/internal/keeper/bank_test.go +++ b/x/supply/internal/keeper/bank_test.go @@ -33,7 +33,7 @@ func getCoinsByName(ctx sdk.Context, k Keeper, moduleName string) sdk.Coins { func TestSendCoins(t *testing.T) { nAccs := int64(4) - ctx, ak, keeper := createTestInput(t, false, initialPower, nAccs) + _, ctx, ak, keeper := CreateTestInput(t, false, initialPower, nAccs) baseAcc := ak.NewAccountWithAddress(ctx, types.NewModuleAddress("baseAcc")) @@ -76,7 +76,7 @@ func TestSendCoins(t *testing.T) { func TestMintCoins(t *testing.T) { nAccs := int64(4) - ctx, _, keeper := createTestInput(t, false, initialPower, nAccs) + _, ctx, _, keeper := CreateTestInput(t, false, initialPower, nAccs) keeper.SetModuleAccount(ctx, burnerAcc) keeper.SetModuleAccount(ctx, minterAcc) @@ -87,7 +87,7 @@ func TestMintCoins(t *testing.T) { require.Error(t, keeper.MintCoins(ctx, "", initCoins), "no module account") require.Panics(t, func() { keeper.MintCoins(ctx, types.Burner, initCoins) }, "invalid permission") - require.Panics(t, func() { keeper.MintCoins(ctx, types.Minter, sdk.Coins{sdk.Coin{"denom", sdk.NewInt(-10)}}) }, "insufficient coins") //nolint + require.Panics(t, func() { keeper.MintCoins(ctx, types.Minter, sdk.Coins{sdk.Coin{"denom", sdk.NewDec(-10)}}) }, "insufficient coins") //nolint require.Panics(t, func() { keeper.MintCoins(ctx, randomPerm, initCoins) }) @@ -109,7 +109,7 @@ func TestMintCoins(t *testing.T) { func TestBurnCoins(t *testing.T) { nAccs := int64(4) - ctx, _, keeper := createTestInput(t, false, initialPower, nAccs) + _, ctx, _, keeper := CreateTestInput(t, false, initialPower, nAccs) require.NoError(t, burnerAcc.SetCoins(initCoins)) keeper.SetModuleAccount(ctx, burnerAcc) diff --git a/x/supply/internal/keeper/keeper_test.go b/x/supply/internal/keeper/keeper_test.go index 61e0afa596ae..178f045862c3 100644 --- a/x/supply/internal/keeper/keeper_test.go +++ b/x/supply/internal/keeper/keeper_test.go @@ -14,7 +14,7 @@ func TestSupply(t *testing.T) { initTokens := sdk.TokensFromConsensusPower(initialPower) nAccs := int64(4) - ctx, _, keeper := createTestInput(t, false, initialPower, nAccs) + _, ctx, _, keeper := CreateTestInput(t, false, initialPower, nAccs) total := keeper.GetSupply(ctx).GetTotal() expectedTotal := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens.MulRaw(nAccs))) @@ -25,7 +25,7 @@ func TestSupply(t *testing.T) { func TestValidatePermissions(t *testing.T) { nAccs := int64(0) initialPower := int64(100) - _, _, keeper := createTestInput(t, false, initialPower, nAccs) + _, _, _, keeper := CreateTestInput(t, false, initialPower, nAccs) err := keeper.ValidatePermissions(multiPermAcc) require.NoError(t, err) diff --git a/x/supply/internal/keeper/querier_test.go b/x/supply/internal/keeper/querier_test.go index 2a06d9ee5828..9413afaa2707 100644 --- a/x/supply/internal/keeper/querier_test.go +++ b/x/supply/internal/keeper/querier_test.go @@ -12,7 +12,7 @@ import ( ) func TestNewQuerier(t *testing.T) { - ctx, _, keeper := createTestInput(t, false, 1000, 2) + _, ctx, _, keeper := CreateTestInput(t, false, 1000, 2) supplyCoins := sdk.NewCoins( sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), @@ -56,7 +56,7 @@ func TestNewQuerier(t *testing.T) { } func TestQuerySupply(t *testing.T) { - ctx, _, keeper := createTestInput(t, false, 1000, 2) + _, ctx, _, keeper := CreateTestInput(t, false, 1000, 2) supplyCoins := sdk.NewCoins( sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), @@ -96,10 +96,10 @@ func TestQuerySupply(t *testing.T) { res, err = querySupplyOf(ctx, query, keeper) require.Nil(t, err) - - var supply sdk.Int + fmt.Println(string(res)) + var supply sdk.Dec errRes = supply.UnmarshalJSON(res) require.Nil(t, errRes) - require.True(sdk.IntEq(t, sdk.NewInt(100), supply)) + require.True(sdk.DecEq(t, sdk.NewDec(100), supply)) } diff --git a/x/supply/internal/keeper/test_common.go b/x/supply/internal/keeper/test_common.go index 3b0051f13b98..f57f8e76bd2c 100644 --- a/x/supply/internal/keeper/test_common.go +++ b/x/supply/internal/keeper/test_common.go @@ -43,7 +43,8 @@ func makeTestCodec() *codec.Codec { } // nolint: deadcode unused -func createTestInput(t *testing.T, isCheckTx bool, initPower int64, nAccs int64) (sdk.Context, auth.AccountKeeper, Keeper) { +func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64, nAccs int64) (*codec.Codec, sdk.Context, + auth.AccountKeeper, Keeper) { keyAcc := sdk.NewKVStoreKey(auth.StoreKey) keyParams := sdk.NewKVStoreKey(params.StoreKey) @@ -91,7 +92,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initPower int64, nAccs int64) totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, valTokens.MulRaw(nAccs))) keeper.SetSupply(ctx, types.NewSupply(totalSupply)) - return ctx, ak, keeper + return cdc, ctx, ak, keeper } // nolint: unparam deadcode unused diff --git a/x/supply/module.go b/x/supply/module.go index 2f55536c55dd..689fd8fd5cff 100644 --- a/x/supply/module.go +++ b/x/supply/module.go @@ -44,7 +44,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { var data GenesisState if err := ModuleCdc.UnmarshalJSON(bz, &data); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %s", ModuleName, err) } return ValidateGenesis(data)