Merge branch 'develop' into rigel/no-endblock-rat-calcs
This commit is contained in:
commit
52916f3c25
|
@ -4,13 +4,14 @@ v Before smashing the submit button please review the checkboxes.
|
||||||
v If a checkbox is n/a - please still include it but + a little note why
|
v If a checkbox is n/a - please still include it but + a little note why
|
||||||
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
|
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
|
||||||
|
|
||||||
* [ ] Updated all relevant documentation (`docs/`)
|
- [ ] Linked to github-issue with discussion and accepted design
|
||||||
* [ ] Updated all relevant code comments
|
- [ ] Updated all relevant documentation (`docs/`)
|
||||||
* [ ] Wrote tests
|
- [ ] Updated all relevant code comments
|
||||||
* [ ] Updated `CHANGELOG.md`
|
- [ ] Wrote tests
|
||||||
* [ ] Updated `cmd/gaia` and `examples/`
|
- [ ] Added entries in `PENDING.md`
|
||||||
|
- [ ] Updated `cmd/gaia` and `examples/`
|
||||||
___________________________________
|
___________________________________
|
||||||
For Admin Use:
|
For Admin Use:
|
||||||
* [ ] Added appropriate labels to PR (ex. wip, ready-for-review, docs)
|
- [ ] Added appropriate labels to PR (ex. wip, ready-for-review, docs)
|
||||||
* [ ] Reviewers Assigned
|
- [ ] Reviewers Assigned
|
||||||
* [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr))
|
- [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr))
|
||||||
|
|
110
CONTRIBUTING.md
110
CONTRIBUTING.md
|
@ -1,18 +1,52 @@
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Thank you for considering making contributions to Cosmos-SDK and related repositories! Start by taking a look at this [coding repo](https://github.com/tendermint/coding) for overall information on repository workflow and standards. Note, we use `make get_dev_tools` and `make update_dev_tools` for installing the linting tools.
|
Thank you for considering making contributions to Cosmos-SDK and related
|
||||||
|
repositories!
|
||||||
|
|
||||||
Please follow standard github best practices: fork the repo, branch from the tip of develop, make some commits, and submit a pull request to develop. See the [open issues](https://github.com/cosmos/cosmos-sdk/issues) for things we need help with!
|
Contributing to this repo can mean many things such as participated in
|
||||||
|
discussion or proposing code changes. To ensure a smooth workflow for all
|
||||||
|
contributors, the general procedure for contributing has been established:
|
||||||
|
|
||||||
Please make sure to use `gofmt` before every commit - the easiest way to do this is have your editor run it for you upon saving a file. Additionally please ensure that your code is lint compliant by running `make lint`
|
1. either [open](https://github.com/cosmos/cosmos-sdk/issues/new/choose) or
|
||||||
|
[find](https://github.com/cosmos/cosmos-sdk/issues) an issue you'd like to help with,
|
||||||
|
2. participate in thoughtful discussion on that issue,
|
||||||
|
3. if you would then like to contribute code:
|
||||||
|
1. if a the issue is a proposal, ensure that the proposal has been accepted,
|
||||||
|
2. ensure that nobody else has already begun working on this issue, if they have
|
||||||
|
make sure to contact them to collaborate,
|
||||||
|
3. if nobody has been assigned the issue and you would like to work on it
|
||||||
|
make a comment on the issue to inform the community of your intentions
|
||||||
|
to begin work,
|
||||||
|
4. follow standard github best practices: fork the repo, branch from the
|
||||||
|
tip of `develop`, make some commits, and submit a PR to `develop`,
|
||||||
|
5. include `WIP:` in the PR-title to and submit your PR early, even if it's
|
||||||
|
incomplete, this indicates to the community you're working on something and
|
||||||
|
allows them to provide comments early in the development process. When the code
|
||||||
|
is complete it can be marked as ready-for-review by replacing `WIP:` with
|
||||||
|
`R4R:` in the PR-title.
|
||||||
|
|
||||||
Looking for a good place to start contributing? How about checking out some [good first issues](https://github.com/cosmos/cosmos-sdk/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
|
Note that for very small or blatantly obvious problems (such as typos) it is
|
||||||
|
not required to an open issue to submit a PR, but be aware that for more complex
|
||||||
|
problems/features, if a PR is opened before an adequate design discussion has
|
||||||
|
taken place in a github issue, that PR runs a high likelihood of being rejected.
|
||||||
|
|
||||||
|
Take a peek at our [coding repo](https://github.com/tendermint/coding) for
|
||||||
|
overall information on repository workflow and standards. Note, we use `make
|
||||||
|
get_dev_tools` and `make update_dev_tools` for installing the linting tools.
|
||||||
|
|
||||||
|
Other notes:
|
||||||
|
- Looking for a good place to start contributing? How about checking out some
|
||||||
|
[good first
|
||||||
|
issues](https://github.com/cosmos/cosmos-sdk/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
|
||||||
|
- Please make sure to use `gofmt` before every commit - the easiest way to do
|
||||||
|
this is have your editor run it for you upon saving a file. Additionally
|
||||||
|
please ensure that your code is lint compliant by running `make lint`
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
To accommodate review process we suggest that PRs are catagorically broken up.
|
To accommodate review process we suggest that PRs are categorically broken up.
|
||||||
Ideally each PR addresses only a single issue. Additionally, as much as possible
|
Ideally each PR addresses only a single issue. Additionally, as much as possible
|
||||||
code refactoring and cleanup should be submitted as a seperate PRs from bugfixes/feature-additions.
|
code refactoring and cleanup should be submitted as a separate PRs from bugfixes/feature-additions.
|
||||||
|
|
||||||
## Forking
|
## Forking
|
||||||
|
|
||||||
|
@ -24,10 +58,10 @@ Instead, we use `git remote` to add the fork as a new remote for the original re
|
||||||
|
|
||||||
For instance, to create a fork and work on a branch of it, I would:
|
For instance, to create a fork and work on a branch of it, I would:
|
||||||
|
|
||||||
* Create the fork on github, using the fork button.
|
- Create the fork on github, using the fork button.
|
||||||
* Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/cosmos/cosmos-sdk`)
|
- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/cosmos/cosmos-sdk`)
|
||||||
* `git remote rename origin upstream`
|
- `git remote rename origin upstream`
|
||||||
* `git remote add origin git@github.com:ebuchman/basecoin.git`
|
- `git remote add origin git@github.com:ebuchman/basecoin.git`
|
||||||
|
|
||||||
Now `origin` refers to my fork and `upstream` refers to the Cosmos-SDK version.
|
Now `origin` refers to my fork and `upstream` refers to the Cosmos-SDK version.
|
||||||
So I can `git push -u origin master` to update my fork, and make pull requests to Cosmos-SDK from there.
|
So I can `git push -u origin master` to update my fork, and make pull requests to Cosmos-SDK from there.
|
||||||
|
@ -35,8 +69,8 @@ Of course, replace `ebuchman` with your git handle.
|
||||||
|
|
||||||
To pull in updates from the origin repo, run
|
To pull in updates from the origin repo, run
|
||||||
|
|
||||||
* `git fetch upstream`
|
- `git fetch upstream`
|
||||||
* `git rebase upstream/master` (or whatever branch you want)
|
- `git rebase upstream/master` (or whatever branch you want)
|
||||||
|
|
||||||
Please don't make Pull Requests to `master`.
|
Please don't make Pull Requests to `master`.
|
||||||
|
|
||||||
|
@ -100,35 +134,35 @@ Libraries need not follow the model strictly, but would be wise to.
|
||||||
The SDK utilizes [semantic versioning](https://semver.org/).
|
The SDK utilizes [semantic versioning](https://semver.org/).
|
||||||
|
|
||||||
### Development Procedure:
|
### Development Procedure:
|
||||||
- the latest state of development is on `develop`
|
- the latest state of development is on `develop`
|
||||||
- `develop` must never fail `make test` or `make test_cli`
|
- `develop` must never fail `make test` or `make test_cli`
|
||||||
- `develop` should not fail `make test_lint`
|
- `develop` should not fail `make test_lint`
|
||||||
- no --force onto `develop` (except when reverting a broken commit, which should seldom happen)
|
- no --force onto `develop` (except when reverting a broken commit, which should seldom happen)
|
||||||
- create a development branch either on github.com/cosmos/cosmos-sdk, or your fork (using `git remote add origin`)
|
- create a development branch either on github.com/cosmos/cosmos-sdk, or your fork (using `git remote add origin`)
|
||||||
- before submitting a pull request, begin `git rebase` on top of `develop`
|
- before submitting a pull request, begin `git rebase` on top of `develop`
|
||||||
|
|
||||||
### Pull Merge Procedure:
|
### Pull Merge Procedure:
|
||||||
- ensure pull branch is rebased on develop
|
- ensure pull branch is rebased on develop
|
||||||
- run `make test` and `make test_cli` to ensure that all tests pass
|
- run `make test` and `make test_cli` to ensure that all tests pass
|
||||||
- merge pull request
|
- merge pull request
|
||||||
- push master may request that pull requests be rebased on top of `unstable`
|
- push master may request that pull requests be rebased on top of `unstable`
|
||||||
|
|
||||||
### Release Procedure:
|
### Release Procedure:
|
||||||
- start on `develop`
|
- start on `develop`
|
||||||
- prepare changelog/release issue
|
- prepare changelog/release issue
|
||||||
- bump versions
|
- bump versions
|
||||||
- push to release-vX.X.X to run CI
|
- push to release-vX.X.X to run CI
|
||||||
- merge to master
|
- merge to master
|
||||||
- merge master back to develop
|
- merge master back to develop
|
||||||
|
|
||||||
### Hotfix Procedure:
|
### Hotfix Procedure:
|
||||||
- start on `master`
|
- start on `master`
|
||||||
- checkout a new branch named hotfix-vX.X.X
|
- checkout a new branch named hotfix-vX.X.X
|
||||||
- make the required changes
|
- make the required changes
|
||||||
- these changes should be small and an absolute necessity
|
- these changes should be small and an absolute necessity
|
||||||
- add a note to CHANGELOG.md
|
- add a note to CHANGELOG.md
|
||||||
- bump versions
|
- bump versions
|
||||||
- push to hotfix-vX.X.X to run the extended integration tests on the CI
|
- push to hotfix-vX.X.X to run the extended integration tests on the CI
|
||||||
- merge hotfix-vX.X.X to master
|
- merge hotfix-vX.X.X to master
|
||||||
- merge hotfix-vX.X.X to develop
|
- merge hotfix-vX.X.X to develop
|
||||||
- delete the hotfix-vX.X.X branch
|
- delete the hotfix-vX.X.X branch
|
||||||
|
|
|
@ -646,6 +646,7 @@
|
||||||
"github.com/tendermint/tendermint/rpc/lib/client",
|
"github.com/tendermint/tendermint/rpc/lib/client",
|
||||||
"github.com/tendermint/tendermint/rpc/lib/server",
|
"github.com/tendermint/tendermint/rpc/lib/server",
|
||||||
"github.com/tendermint/tendermint/types",
|
"github.com/tendermint/tendermint/types",
|
||||||
|
"github.com/tendermint/tendermint/version",
|
||||||
"github.com/zondax/ledger-goclient",
|
"github.com/zondax/ledger-goclient",
|
||||||
"golang.org/x/crypto/blowfish",
|
"golang.org/x/crypto/blowfish",
|
||||||
"golang.org/x/crypto/ripemd160",
|
"golang.org/x/crypto/ripemd160",
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -93,6 +93,9 @@ update_tools:
|
||||||
update_dev_tools:
|
update_dev_tools:
|
||||||
cd tools && $(MAKE) update_dev_tools
|
cd tools && $(MAKE) update_dev_tools
|
||||||
|
|
||||||
|
get_tools:
|
||||||
|
cd tools && $(MAKE) get_tools
|
||||||
|
|
||||||
get_dev_tools:
|
get_dev_tools:
|
||||||
cd tools && $(MAKE) get_dev_tools
|
cd tools && $(MAKE) get_dev_tools
|
||||||
|
|
||||||
|
@ -220,7 +223,7 @@ remotenet-status:
|
||||||
# unless there is a reason not to.
|
# unless there is a reason not to.
|
||||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||||
.PHONY: build build_cosmos-sdk-cli build_examples install install_examples install_cosmos-sdk-cli install_debug dist \
|
.PHONY: build build_cosmos-sdk-cli build_examples install install_examples install_cosmos-sdk-cli install_debug dist \
|
||||||
check_tools get_tools get_vendor_deps draw_deps test test_cli test_unit \
|
check_tools check_dev_tools get_tools get_dev_tools get_vendor_deps draw_deps test test_cli test_unit \
|
||||||
test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \
|
test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \
|
||||||
build-linux build-docker-gaiadnode localnet-start localnet-stop remotenet-start \
|
build-linux build-docker-gaiadnode localnet-start localnet-stop remotenet-start \
|
||||||
remotenet-stop remotenet-status format check-ledger test_sim
|
remotenet-stop remotenet-status format check-ledger test_sim update_tools update_dev_tools
|
||||||
|
|
11
PENDING.md
11
PENDING.md
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
BREAKING CHANGES
|
BREAKING CHANGES
|
||||||
* [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()`
|
* [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()`
|
||||||
|
* [x/gov] CLI flag changed from `proposalID` to `proposal-id`
|
||||||
* [x/stake] Fixed the period check for the inflation calculation
|
* [x/stake] Fixed the period check for the inflation calculation
|
||||||
* [x/stake] Inflation doesn't use rationals in calculation (performance boost)
|
* [x/stake] Inflation doesn't use rationals in calculation (performance boost)
|
||||||
|
* [baseapp] NewBaseApp constructor now takes sdk.TxDecoder as argument instead of wire.Codec
|
||||||
|
* [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp
|
||||||
* \#1606 The following CLI commands have been switched to use `--from`
|
* \#1606 The following CLI commands have been switched to use `--from`
|
||||||
* `gaiacli stake create-validator --address-validator`
|
* `gaiacli stake create-validator --address-validator`
|
||||||
* `gaiacli stake edit-validator --address-validator`
|
* `gaiacli stake edit-validator --address-validator`
|
||||||
|
@ -16,6 +19,7 @@ BREAKING CHANGES
|
||||||
* `gaiacli gov submit-proposal --proposer`
|
* `gaiacli gov submit-proposal --proposer`
|
||||||
* `gaiacli gov deposit --depositer`
|
* `gaiacli gov deposit --depositer`
|
||||||
* `gaiacli gov vote --voter`
|
* `gaiacli gov vote --voter`
|
||||||
|
* [x/gov] Added tags sub-package, changed tags to use dash-case
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
* [lcd] Can now query governance proposals by ProposalStatus
|
* [lcd] Can now query governance proposals by ProposalStatus
|
||||||
|
@ -24,14 +28,17 @@ FEATURES
|
||||||
* Modules can test random combinations of their own operations
|
* Modules can test random combinations of their own operations
|
||||||
* Applications can integrate operations and invariants from modules together for an integrated simulation
|
* Applications can integrate operations and invariants from modules together for an integrated simulation
|
||||||
* [baseapp] Initialize validator set on ResponseInitChain
|
* [baseapp] Initialize validator set on ResponseInitChain
|
||||||
* Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
|
* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
|
||||||
* This allows SDK users to init a new project repository with a single command.
|
* This allows SDK users to initialize a new project repository.
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
* [baseapp] Allow any alphanumeric character in route
|
* [baseapp] Allow any alphanumeric character in route
|
||||||
* [cli] Improve error messages for all txs when the account doesn't exist
|
* [cli] Improve error messages for all txs when the account doesn't exist
|
||||||
* [tools] Remove `rm -rf vendor/` from `make get_vendor_deps`
|
* [tools] Remove `rm -rf vendor/` from `make get_vendor_deps`
|
||||||
|
* [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly
|
||||||
* [x/stake] Add revoked to human-readable validator
|
* [x/stake] Add revoked to human-readable validator
|
||||||
|
* [x/gov] Votes on a proposal can now be queried
|
||||||
|
* [x/bank] Unit tests are now table-driven
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
* \#1666 Add intra-tx counter to the genesis validators
|
* \#1666 Add intra-tx counter to the genesis validators
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/version"
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
"github.com/cosmos/cosmos-sdk/wire"
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Key to store the header in the DB itself.
|
// Key to store the header in the DB itself.
|
||||||
|
@ -44,14 +43,12 @@ type BaseApp struct {
|
||||||
// initialized on creation
|
// initialized on creation
|
||||||
Logger log.Logger
|
Logger log.Logger
|
||||||
name string // application name from abci.Info
|
name string // application name from abci.Info
|
||||||
cdc *wire.Codec // Amino codec
|
|
||||||
db dbm.DB // common DB backend
|
db dbm.DB // common DB backend
|
||||||
cms sdk.CommitMultiStore // Main (uncached) state
|
cms sdk.CommitMultiStore // Main (uncached) state
|
||||||
router Router // handle any kind of message
|
router Router // handle any kind of message
|
||||||
codespacer *sdk.Codespacer // handle module codespacing
|
codespacer *sdk.Codespacer // handle module codespacing
|
||||||
|
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
|
||||||
|
|
||||||
// must be set
|
|
||||||
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
|
|
||||||
anteHandler sdk.AnteHandler // ante handler for fee and auth
|
anteHandler sdk.AnteHandler // ante handler for fee and auth
|
||||||
|
|
||||||
// may be nil
|
// may be nil
|
||||||
|
@ -80,17 +77,17 @@ var _ abci.Application = (*BaseApp)(nil)
|
||||||
// (e.g. functional options).
|
// (e.g. functional options).
|
||||||
//
|
//
|
||||||
// NOTE: The db is used to store the version number for now.
|
// NOTE: The db is used to store the version number for now.
|
||||||
|
// Accepts a user-defined txDecoder
|
||||||
// Accepts variable number of option functions, which act on the BaseApp to set configuration choices
|
// Accepts variable number of option functions, which act on the BaseApp to set configuration choices
|
||||||
func NewBaseApp(name string, cdc *wire.Codec, logger log.Logger, db dbm.DB, options ...func(*BaseApp)) *BaseApp {
|
func NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp)) *BaseApp {
|
||||||
app := &BaseApp{
|
app := &BaseApp{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
name: name,
|
name: name,
|
||||||
cdc: cdc,
|
|
||||||
db: db,
|
db: db,
|
||||||
cms: store.NewCommitMultiStore(db),
|
cms: store.NewCommitMultiStore(db),
|
||||||
router: NewRouter(),
|
router: NewRouter(),
|
||||||
codespacer: sdk.NewCodespacer(),
|
codespacer: sdk.NewCodespacer(),
|
||||||
txDecoder: defaultTxDecoder(cdc),
|
txDecoder: txDecoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the undefined & root codespaces, which should not be used by
|
// Register the undefined & root codespaces, which should not be used by
|
||||||
|
@ -135,35 +132,6 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
|
||||||
app.cms.MountStoreWithDB(key, typ, nil)
|
app.cms.MountStoreWithDB(key, typ, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the txDecoder function
|
|
||||||
func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) {
|
|
||||||
app.txDecoder = txDecoder
|
|
||||||
}
|
|
||||||
|
|
||||||
// default custom logic for transaction decoding
|
|
||||||
// TODO: remove auth and wire dependencies from baseapp
|
|
||||||
// - move this to auth.DefaultTxDecoder
|
|
||||||
// - set the default here to JSON decode like docs/examples/app1 (it will fail
|
|
||||||
// for multiple messages ;))
|
|
||||||
// - pass a TxDecoder into NewBaseApp, instead of a codec.
|
|
||||||
func defaultTxDecoder(cdc *wire.Codec) sdk.TxDecoder {
|
|
||||||
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
|
||||||
var tx = auth.StdTx{}
|
|
||||||
|
|
||||||
if len(txBytes) == 0 {
|
|
||||||
return nil, sdk.ErrTxDecode("txBytes are empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdTx.Msg is an interface. The concrete types
|
|
||||||
// are registered by MakeTxCodec
|
|
||||||
err := cdc.UnmarshalBinary(txBytes, &tx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, sdk.ErrTxDecode("").TraceSDK(err.Error())
|
|
||||||
}
|
|
||||||
return tx, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint - Set functions
|
// nolint - Set functions
|
||||||
func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) {
|
func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) {
|
||||||
app.initChainer = initChainer
|
app.initChainer = initChainer
|
||||||
|
@ -364,7 +332,9 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc
|
||||||
default:
|
default:
|
||||||
result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result()
|
result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result()
|
||||||
}
|
}
|
||||||
value := app.cdc.MustMarshalBinary(result)
|
|
||||||
|
// Encode with json
|
||||||
|
value := wire.Cdc.MustMarshalBinary(result)
|
||||||
return abci.ResponseQuery{
|
return abci.ResponseQuery{
|
||||||
Code: uint32(sdk.ABCICodeOK),
|
Code: uint32(sdk.ABCICodeOK),
|
||||||
Value: value,
|
Value: value,
|
||||||
|
|
|
@ -30,7 +30,7 @@ func newBaseApp(name string) *BaseApp {
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
codec := wire.NewCodec()
|
codec := wire.NewCodec()
|
||||||
registerTestCodec(codec)
|
registerTestCodec(codec)
|
||||||
return NewBaseApp(name, codec, logger, db)
|
return NewBaseApp(name, logger, db, testTxDecoder(codec))
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerTestCodec(cdc *wire.Codec) {
|
func registerTestCodec(cdc *wire.Codec) {
|
||||||
|
@ -49,8 +49,6 @@ func setupBaseApp(t *testing.T) (*BaseApp, *sdk.KVStoreKey, *sdk.KVStoreKey) {
|
||||||
app := newBaseApp(t.Name())
|
app := newBaseApp(t.Name())
|
||||||
require.Equal(t, t.Name(), app.Name())
|
require.Equal(t, t.Name(), app.Name())
|
||||||
|
|
||||||
app.SetTxDecoder(testTxDecoder(app.cdc))
|
|
||||||
|
|
||||||
// make some cap keys
|
// make some cap keys
|
||||||
capKey1 := sdk.NewKVStoreKey("key1")
|
capKey1 := sdk.NewKVStoreKey("key1")
|
||||||
capKey2 := sdk.NewKVStoreKey("key2")
|
capKey2 := sdk.NewKVStoreKey("key2")
|
||||||
|
@ -85,7 +83,7 @@ func TestLoadVersion(t *testing.T) {
|
||||||
logger := defaultLogger()
|
logger := defaultLogger()
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
name := t.Name()
|
name := t.Name()
|
||||||
app := NewBaseApp(name, nil, logger, db)
|
app := NewBaseApp(name, logger, db, nil)
|
||||||
|
|
||||||
// make a cap key and mount the store
|
// make a cap key and mount the store
|
||||||
capKey := sdk.NewKVStoreKey("main")
|
capKey := sdk.NewKVStoreKey("main")
|
||||||
|
@ -114,7 +112,7 @@ func TestLoadVersion(t *testing.T) {
|
||||||
commitID2 := sdk.CommitID{2, res.Data}
|
commitID2 := sdk.CommitID{2, res.Data}
|
||||||
|
|
||||||
// reload with LoadLatestVersion
|
// reload with LoadLatestVersion
|
||||||
app = NewBaseApp(name, nil, logger, db)
|
app = NewBaseApp(name, logger, db, nil)
|
||||||
app.MountStoresIAVL(capKey)
|
app.MountStoresIAVL(capKey)
|
||||||
err = app.LoadLatestVersion(capKey)
|
err = app.LoadLatestVersion(capKey)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
@ -122,7 +120,7 @@ func TestLoadVersion(t *testing.T) {
|
||||||
|
|
||||||
// reload with LoadVersion, see if you can commit the same block and get
|
// reload with LoadVersion, see if you can commit the same block and get
|
||||||
// the same result
|
// the same result
|
||||||
app = NewBaseApp(name, nil, logger, db)
|
app = NewBaseApp(name, logger, db, nil)
|
||||||
app.MountStoresIAVL(capKey)
|
app.MountStoresIAVL(capKey)
|
||||||
err = app.LoadVersion(1, capKey)
|
err = app.LoadVersion(1, capKey)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
@ -142,9 +140,7 @@ func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, exp
|
||||||
func TestOptionFunction(t *testing.T) {
|
func TestOptionFunction(t *testing.T) {
|
||||||
logger := defaultLogger()
|
logger := defaultLogger()
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
codec := wire.NewCodec()
|
bap := NewBaseApp("starting name", logger, db, nil, testChangeNameHelper("new name"))
|
||||||
registerTestCodec(codec)
|
|
||||||
bap := NewBaseApp("starting name", codec, logger, db, testChangeNameHelper("new name"))
|
|
||||||
require.Equal(t, bap.name, "new name", "BaseApp should have had name changed via option function")
|
require.Equal(t, bap.name, "new name", "BaseApp should have had name changed via option function")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +212,7 @@ func TestInitChainer(t *testing.T) {
|
||||||
// we can reload the same app later
|
// we can reload the same app later
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
logger := defaultLogger()
|
logger := defaultLogger()
|
||||||
app := NewBaseApp(name, nil, logger, db)
|
app := NewBaseApp(name, logger, db, nil)
|
||||||
capKey := sdk.NewKVStoreKey("main")
|
capKey := sdk.NewKVStoreKey("main")
|
||||||
capKey2 := sdk.NewKVStoreKey("key2")
|
capKey2 := sdk.NewKVStoreKey("key2")
|
||||||
app.MountStoresIAVL(capKey, capKey2)
|
app.MountStoresIAVL(capKey, capKey2)
|
||||||
|
@ -257,7 +253,7 @@ func TestInitChainer(t *testing.T) {
|
||||||
require.Equal(t, value, res.Value)
|
require.Equal(t, value, res.Value)
|
||||||
|
|
||||||
// reload app
|
// reload app
|
||||||
app = NewBaseApp(name, nil, logger, db)
|
app = NewBaseApp(name, logger, db, nil)
|
||||||
app.MountStoresIAVL(capKey, capKey2)
|
app.MountStoresIAVL(capKey, capKey2)
|
||||||
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
|
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
@ -444,9 +440,13 @@ func TestCheckTx(t *testing.T) {
|
||||||
|
|
||||||
app.InitChain(abci.RequestInitChain{})
|
app.InitChain(abci.RequestInitChain{})
|
||||||
|
|
||||||
|
// Create same codec used in txDecoder
|
||||||
|
codec := wire.NewCodec()
|
||||||
|
registerTestCodec(codec)
|
||||||
|
|
||||||
for i := int64(0); i < nTxs; i++ {
|
for i := int64(0); i < nTxs; i++ {
|
||||||
tx := newTxCounter(i, 0)
|
tx := newTxCounter(i, 0)
|
||||||
txBytes, err := app.cdc.MarshalBinary(tx)
|
txBytes, err := codec.MarshalBinary(tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
r := app.CheckTx(txBytes)
|
r := app.CheckTx(txBytes)
|
||||||
assert.True(t, r.IsOK(), fmt.Sprintf("%v", r))
|
assert.True(t, r.IsOK(), fmt.Sprintf("%v", r))
|
||||||
|
@ -481,6 +481,10 @@ func TestDeliverTx(t *testing.T) {
|
||||||
deliverKey := []byte("deliver-key")
|
deliverKey := []byte("deliver-key")
|
||||||
app.Router().AddRoute(typeMsgCounter, handlerMsgCounter(t, capKey, deliverKey))
|
app.Router().AddRoute(typeMsgCounter, handlerMsgCounter(t, capKey, deliverKey))
|
||||||
|
|
||||||
|
// Create same codec used in txDecoder
|
||||||
|
codec := wire.NewCodec()
|
||||||
|
registerTestCodec(codec)
|
||||||
|
|
||||||
nBlocks := 3
|
nBlocks := 3
|
||||||
txPerHeight := 5
|
txPerHeight := 5
|
||||||
for blockN := 0; blockN < nBlocks; blockN++ {
|
for blockN := 0; blockN < nBlocks; blockN++ {
|
||||||
|
@ -488,7 +492,7 @@ func TestDeliverTx(t *testing.T) {
|
||||||
for i := 0; i < txPerHeight; i++ {
|
for i := 0; i < txPerHeight; i++ {
|
||||||
counter := int64(blockN*txPerHeight + i)
|
counter := int64(blockN*txPerHeight + i)
|
||||||
tx := newTxCounter(counter, counter)
|
tx := newTxCounter(counter, counter)
|
||||||
txBytes, err := app.cdc.MarshalBinary(tx)
|
txBytes, err := codec.MarshalBinary(tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
res := app.DeliverTx(txBytes)
|
res := app.DeliverTx(txBytes)
|
||||||
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
||||||
|
@ -518,12 +522,16 @@ func TestMultiMsgDeliverTx(t *testing.T) {
|
||||||
app.Router().AddRoute(typeMsgCounter, handlerMsgCounter(t, capKey, deliverKey))
|
app.Router().AddRoute(typeMsgCounter, handlerMsgCounter(t, capKey, deliverKey))
|
||||||
app.Router().AddRoute(typeMsgCounter2, handlerMsgCounter(t, capKey, deliverKey2))
|
app.Router().AddRoute(typeMsgCounter2, handlerMsgCounter(t, capKey, deliverKey2))
|
||||||
|
|
||||||
|
// Create same codec used in txDecoder
|
||||||
|
codec := wire.NewCodec()
|
||||||
|
registerTestCodec(codec)
|
||||||
|
|
||||||
// run a multi-msg tx
|
// run a multi-msg tx
|
||||||
// with all msgs the same type
|
// with all msgs the same type
|
||||||
{
|
{
|
||||||
app.BeginBlock(abci.RequestBeginBlock{})
|
app.BeginBlock(abci.RequestBeginBlock{})
|
||||||
tx := newTxCounter(0, 0, 1, 2)
|
tx := newTxCounter(0, 0, 1, 2)
|
||||||
txBytes, err := app.cdc.MarshalBinary(tx)
|
txBytes, err := codec.MarshalBinary(tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
res := app.DeliverTx(txBytes)
|
res := app.DeliverTx(txBytes)
|
||||||
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
||||||
|
@ -544,7 +552,7 @@ func TestMultiMsgDeliverTx(t *testing.T) {
|
||||||
tx := newTxCounter(1, 3)
|
tx := newTxCounter(1, 3)
|
||||||
tx.Msgs = append(tx.Msgs, msgCounter2{0})
|
tx.Msgs = append(tx.Msgs, msgCounter2{0})
|
||||||
tx.Msgs = append(tx.Msgs, msgCounter2{1})
|
tx.Msgs = append(tx.Msgs, msgCounter2{1})
|
||||||
txBytes, err := app.cdc.MarshalBinary(tx)
|
txBytes, err := codec.MarshalBinary(tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
res := app.DeliverTx(txBytes)
|
res := app.DeliverTx(txBytes)
|
||||||
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
||||||
|
@ -589,6 +597,10 @@ func TestSimulateTx(t *testing.T) {
|
||||||
})
|
})
|
||||||
app.InitChain(abci.RequestInitChain{})
|
app.InitChain(abci.RequestInitChain{})
|
||||||
|
|
||||||
|
// Create same codec used in txDecoder
|
||||||
|
codec := wire.NewCodec()
|
||||||
|
registerTestCodec(codec)
|
||||||
|
|
||||||
nBlocks := 3
|
nBlocks := 3
|
||||||
for blockN := 0; blockN < nBlocks; blockN++ {
|
for blockN := 0; blockN < nBlocks; blockN++ {
|
||||||
count := int64(blockN + 1)
|
count := int64(blockN + 1)
|
||||||
|
@ -607,7 +619,7 @@ func TestSimulateTx(t *testing.T) {
|
||||||
require.Equal(t, int64(gasConsumed), result.GasUsed)
|
require.Equal(t, int64(gasConsumed), result.GasUsed)
|
||||||
|
|
||||||
// simulate by calling Query with encoded tx
|
// simulate by calling Query with encoded tx
|
||||||
txBytes, err := app.cdc.MarshalBinary(tx)
|
txBytes, err := codec.MarshalBinary(tx)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: "/app/simulate",
|
Path: "/app/simulate",
|
||||||
|
@ -617,7 +629,8 @@ func TestSimulateTx(t *testing.T) {
|
||||||
require.True(t, queryResult.IsOK(), queryResult.Log)
|
require.True(t, queryResult.IsOK(), queryResult.Log)
|
||||||
|
|
||||||
var res sdk.Result
|
var res sdk.Result
|
||||||
app.cdc.MustUnmarshalBinary(queryResult.Value, &res)
|
wire.Cdc.MustUnmarshalBinary(queryResult.Value, &res)
|
||||||
|
require.Nil(t, err, "Result unmarshalling failed")
|
||||||
require.True(t, res.IsOK(), res.Log)
|
require.True(t, res.IsOK(), res.Log)
|
||||||
require.Equal(t, gasConsumed, res.GasUsed, res.Log)
|
require.Equal(t, gasConsumed, res.GasUsed, res.Log)
|
||||||
app.EndBlock(abci.RequestEndBlock{})
|
app.EndBlock(abci.RequestEndBlock{})
|
||||||
|
|
|
@ -611,6 +611,17 @@ func TestProposalsQuery(t *testing.T) {
|
||||||
// Test query voted and deposited by addr1
|
// Test query voted and deposited by addr1
|
||||||
proposals = getProposalsFilterVoterDepositer(t, port, addr, addr)
|
proposals = getProposalsFilterVoterDepositer(t, port, addr, addr)
|
||||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||||
|
|
||||||
|
// Test query votes on Proposal 2
|
||||||
|
votes := getVotes(t, port, proposalID2)
|
||||||
|
require.Len(t, votes, 1)
|
||||||
|
require.Equal(t, addr, votes[0].Voter)
|
||||||
|
|
||||||
|
// Test query votes on Proposal 3
|
||||||
|
votes = getVotes(t, port, proposalID3)
|
||||||
|
require.Len(t, votes, 2)
|
||||||
|
require.True(t, addr.String() == votes[0].Voter.String() || addr.String() == votes[1].Voter.String())
|
||||||
|
require.True(t, addr2.String() == votes[0].Voter.String() || addr2.String() == votes[1].Voter.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
//_____________________________________________________________________________
|
//_____________________________________________________________________________
|
||||||
|
@ -875,6 +886,15 @@ func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddre
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getVotes(t *testing.T, port string, proposalID int64) []gov.Vote {
|
||||||
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), nil)
|
||||||
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
var votes []gov.Vote
|
||||||
|
err := cdc.UnmarshalJSON([]byte(body), &votes)
|
||||||
|
require.Nil(t, err)
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
func getProposalsAll(t *testing.T, port string) []gov.Proposal {
|
func getProposalsAll(t *testing.T, port string) []gov.Proposal {
|
||||||
res, body := Request(t, port, "GET", "/gov/proposals", nil)
|
res, body := Request(t, port, "GET", "/gov/proposals", nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
|
@ -44,9 +44,9 @@ var initCmd = &cobra.Command{
|
||||||
"basecoind", shortProjectName+"d",
|
"basecoind", shortProjectName+"d",
|
||||||
"BasecoinApp", capitalizedProjectName+"App",
|
"BasecoinApp", capitalizedProjectName+"App",
|
||||||
remoteBasecoinPath, remoteProjectPath,
|
remoteBasecoinPath, remoteProjectPath,
|
||||||
"basecoin", shortProjectName)
|
"basecoin", shortProjectName,
|
||||||
setupBasecoinWorkspace(shortProjectName, remoteProjectPath)
|
"Basecoin", capitalizedProjectName)
|
||||||
return nil
|
return setupBasecoinWorkspace(shortProjectName, remoteProjectPath)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +142,16 @@ benchmark:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupBasecoinWorkspace(projectName string, remoteProjectPath string) {
|
func setupBasecoinWorkspace(projectName string, remoteProjectPath string) error {
|
||||||
projectPath := resolveProjectPath(remoteProjectPath)
|
projectPath := resolveProjectPath(remoteProjectPath)
|
||||||
fmt.Println("Configuring your project in " + projectPath)
|
fmt.Println("Configuring your project in " + projectPath)
|
||||||
|
// Check if the projectPath already exists or not
|
||||||
|
if _, err := os.Stat(projectPath); !os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("Unable to initialize the project. %s already exists", projectPath)
|
||||||
|
}
|
||||||
copyBasecoinTemplate(projectName, projectPath, remoteProjectPath)
|
copyBasecoinTemplate(projectName, projectPath, remoteProjectPath)
|
||||||
createGopkg(projectPath)
|
createGopkg(projectPath)
|
||||||
createMakefile(projectPath)
|
createMakefile(projectPath)
|
||||||
fmt.Printf("\nInitialized a new project at %s.\nHappy hacking!\n", projectPath)
|
fmt.Printf("Initialized a new project at %s.\nHappy hacking!\n", projectPath)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ type GaiaApp struct {
|
||||||
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
|
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
|
||||||
cdc := MakeCodec()
|
cdc := MakeCodec()
|
||||||
|
|
||||||
bApp := bam.NewBaseApp(appName, cdc, logger, db, baseAppOptions...)
|
bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
|
||||||
bApp.SetCommitMultiStoreTracer(traceStore)
|
bApp.SetCommitMultiStoreTracer(traceStore)
|
||||||
|
|
||||||
var app = &GaiaApp{
|
var app = &GaiaApp{
|
||||||
|
|
|
@ -188,35 +188,40 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf("steak").Int64())
|
||||||
|
|
||||||
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposalID=1 --output=json %v", flags))
|
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, int64(1), proposal1.GetProposalID())
|
require.Equal(t, int64(1), proposal1.GetProposalID())
|
||||||
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
|
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
|
||||||
|
|
||||||
depositStr := fmt.Sprintf("gaiacli gov deposit %v", flags)
|
depositStr := fmt.Sprintf("gaiacli gov deposit %v", flags)
|
||||||
depositStr += fmt.Sprintf(" --from=%s", "foo")
|
depositStr += fmt.Sprintf(" --from=%s", "foo")
|
||||||
depositStr += fmt.Sprintf(" --deposit=%s", "10steak")
|
depositStr += fmt.Sprintf(" --deposit=%s", "10steak")
|
||||||
depositStr += fmt.Sprintf(" --proposalID=%s", "1")
|
depositStr += fmt.Sprintf(" --proposal-id=%s", "1")
|
||||||
|
|
||||||
executeWrite(t, depositStr, pass)
|
executeWrite(t, depositStr, pass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf("steak").Int64())
|
||||||
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposalID=1 --output=json %v", flags))
|
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, int64(1), proposal1.GetProposalID())
|
require.Equal(t, int64(1), proposal1.GetProposalID())
|
||||||
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
||||||
|
|
||||||
voteStr := fmt.Sprintf("gaiacli gov vote %v", flags)
|
voteStr := fmt.Sprintf("gaiacli gov vote %v", flags)
|
||||||
voteStr += fmt.Sprintf(" --from=%s", "foo")
|
voteStr += fmt.Sprintf(" --from=%s", "foo")
|
||||||
voteStr += fmt.Sprintf(" --proposalID=%s", "1")
|
voteStr += fmt.Sprintf(" --proposal-id=%s", "1")
|
||||||
voteStr += fmt.Sprintf(" --option=%s", "Yes")
|
voteStr += fmt.Sprintf(" --option=%s", "Yes")
|
||||||
|
|
||||||
executeWrite(t, voteStr, pass)
|
executeWrite(t, voteStr, pass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposalID=1 --voter=%s --output=json %v", fooAddr, flags))
|
vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposal-id=1 --voter=%s --output=json %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(1), vote.ProposalID)
|
require.Equal(t, int64(1), vote.ProposalID)
|
||||||
require.Equal(t, gov.OptionYes, vote.Option)
|
require.Equal(t, gov.OptionYes, vote.Option)
|
||||||
|
|
||||||
|
votes := executeGetVotes(t, fmt.Sprintf("gaiacli gov query-votes --proposal-id=1 --output=json %v", flags))
|
||||||
|
require.Len(t, votes, 1)
|
||||||
|
require.Equal(t, int64(1), votes[0].ProposalID)
|
||||||
|
require.Equal(t, gov.OptionYes, votes[0].Option)
|
||||||
}
|
}
|
||||||
|
|
||||||
//___________________________________________________________________________________
|
//___________________________________________________________________________________
|
||||||
|
@ -321,3 +326,12 @@ func executeGetVote(t *testing.T, cmdStr string) gov.Vote {
|
||||||
require.NoError(t, err, "out %v\n, err %v", out, err)
|
require.NoError(t, err, "out %v\n, err %v", out, err)
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func executeGetVotes(t *testing.T, cmdStr string) []gov.Vote {
|
||||||
|
out := tests.ExecuteT(t, cmdStr)
|
||||||
|
var votes []gov.Vote
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &votes)
|
||||||
|
require.NoError(t, err, "out %v\n, err %v", out, err)
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ func main() {
|
||||||
client.GetCommands(
|
client.GetCommands(
|
||||||
govcmd.GetCmdQueryProposal("gov", cdc),
|
govcmd.GetCmdQueryProposal("gov", cdc),
|
||||||
govcmd.GetCmdQueryVote("gov", cdc),
|
govcmd.GetCmdQueryVote("gov", cdc),
|
||||||
|
govcmd.GetCmdQueryVotes("gov", cdc),
|
||||||
)...)
|
)...)
|
||||||
govCmd.AddCommand(
|
govCmd.AddCommand(
|
||||||
client.PostCommands(
|
client.PostCommands(
|
||||||
|
|
|
@ -149,7 +149,7 @@ type GaiaApp struct {
|
||||||
func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
|
func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
|
||||||
cdc := MakeCodec()
|
cdc := MakeCodec()
|
||||||
|
|
||||||
bApp := bam.NewBaseApp(appName, cdc, logger, db, baseAppOptions...)
|
bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
|
||||||
bApp.SetCommitMultiStoreTracer(os.Stdout)
|
bApp.SetCommitMultiStoreTracer(os.Stdout)
|
||||||
|
|
||||||
// create your application object
|
// create your application object
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# TESTNET STATUS
|
# TESTNET STATUS
|
||||||
|
|
||||||
|
## *July 22, 2018, 5:30 EST* - Gaia-7001 Consensus Failure
|
||||||
|
|
||||||
|
- [Consensus Failure at Block 24570](https://github.com/cosmos/cosmos-sdk/issues/1787)
|
||||||
|
|
||||||
|
|
||||||
## *July 17, 2018, 4:00 EST* - New Testnet Gaia-7001
|
## *July 17, 2018, 4:00 EST* - New Testnet Gaia-7001
|
||||||
|
|
||||||
- New testnet with fixes for the genesis file
|
- New testnet with fixes for the genesis file
|
||||||
|
|
|
@ -421,17 +421,13 @@ Here is the complete setup for App1:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func NewApp1(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
func NewApp1(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := wire.NewCodec()
|
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app1Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app1Name, logger, db, tx1Decoder)
|
||||||
|
|
||||||
// Create a capability key for accessing the account store.
|
// Create a capability key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
|
||||||
// Determine how transactions are decoded.
|
|
||||||
app.SetTxDecoder(txDecoder)
|
|
||||||
|
|
||||||
// Register message routes.
|
// Register message routes.
|
||||||
// Note the handler receives the keyAccount and thus
|
// Note the handler receives the keyAccount and thus
|
||||||
// gets access to the account store.
|
// gets access to the account store.
|
||||||
|
@ -458,7 +454,7 @@ Here, we have only a single Msg type, `bank`, a single store for accounts, and a
|
||||||
The handler is granted access to the store by giving it the capability key.
|
The handler is granted access to the store by giving it the capability key.
|
||||||
In future apps, we'll have multiple stores and handlers, and not every handler will get access to every store.
|
In future apps, we'll have multiple stores and handlers, and not every handler will get access to every store.
|
||||||
|
|
||||||
After setting the transaction decoder and the message handling routes, the final
|
After setting the message handling routes, the final
|
||||||
step is to mount the stores and load the latest version.
|
step is to mount the stores and load the latest version.
|
||||||
Since we only have one store, we only mount one.
|
Since we only have one store, we only mount one.
|
||||||
|
|
||||||
|
|
|
@ -169,10 +169,19 @@ type app2Tx struct {
|
||||||
func (tx app2Tx) GetMsgs() []sdk.Msg {
|
func (tx app2Tx) GetMsgs() []sdk.Msg {
|
||||||
return []sdk.Msg{tx.Msg}
|
return []sdk.Msg{tx.Msg}
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
We don't need a custom TxDecoder function anymore, since we're just using the
|
// Amino decode app2Tx. Capable of decoding both MsgSend and MsgIssue
|
||||||
Amino codec!
|
func tx2Decoder(cdc *wire.Codec) sdk.TxDecoder {
|
||||||
|
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||||
|
var tx app2Tx
|
||||||
|
err := cdc.UnmarshalBinary(txBytes, &tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrTxDecode(err.Error())
|
||||||
|
}
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## AnteHandler
|
## AnteHandler
|
||||||
|
|
||||||
|
@ -249,7 +258,7 @@ func NewApp2(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := NewCodec()
|
cdc := NewCodec()
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app2Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app2Name, logger, db, txDecoder(cdc))
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
@ -280,9 +289,8 @@ key for a second store that is *only* passed to a second handler, the
|
||||||
`handleMsgIssue`. The first `handleMsgSend` has no access to this second store and cannot read or write to
|
`handleMsgIssue`. The first `handleMsgSend` has no access to this second store and cannot read or write to
|
||||||
it, ensuring a strong separation of concerns.
|
it, ensuring a strong separation of concerns.
|
||||||
|
|
||||||
Note also that we do not need to use `SetTxDecoder` here - now that we're using
|
Note now that we're using Amino, we create a codec, register our types on the codec, and pass the
|
||||||
Amino, we simply create a codec, register our types on the codec, and pass the
|
codec into our TxDecoder constructor, `tx2Decoder`. The SDK takes care of the rest for us!
|
||||||
codec into `NewBaseApp`. The SDK takes care of the rest for us!
|
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := NewCodec()
|
cdc := NewCodec()
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app3Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app3Name, logger, db, auth.DefaultTxDecoder(cdc))
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
@ -361,6 +361,9 @@ and receives only the `bank.Keeper`. See the
|
||||||
[x/bank API docs](https://godoc.org/github.com/cosmos/cosmos-sdk/x/bank)
|
[x/bank API docs](https://godoc.org/github.com/cosmos/cosmos-sdk/x/bank)
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
|
We also use the default txDecoder in `x/auth`, which decodes amino-encoded
|
||||||
|
`auth.StdTx` transactions.
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
Armed with native modules for authentication and coin transfer,
|
Armed with native modules for authentication and coin transfer,
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
bapp "github.com/cosmos/cosmos-sdk/baseapp"
|
bapp "github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/wire"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -18,17 +17,12 @@ const (
|
||||||
|
|
||||||
func NewApp1(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
func NewApp1(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
|
|
||||||
cdc := wire.NewCodec()
|
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app1Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app1Name, logger, db, tx1Decoder)
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
|
||||||
// Determine how transactions are decoded.
|
|
||||||
app.SetTxDecoder(txDecoder)
|
|
||||||
|
|
||||||
// Register message routes.
|
// Register message routes.
|
||||||
// Note the handler gets access to the account store.
|
// Note the handler gets access to the account store.
|
||||||
app.Router().
|
app.Router().
|
||||||
|
@ -225,7 +219,7 @@ func (tx app1Tx) GetMsgs() []sdk.Msg {
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON decode MsgSend.
|
// JSON decode MsgSend.
|
||||||
func txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
|
func tx1Decoder(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||||
var tx app1Tx
|
var tx app1Tx
|
||||||
err := json.Unmarshal(txBytes, &tx)
|
err := json.Unmarshal(txBytes, &tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -37,7 +37,7 @@ func NewApp2(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := NewCodec()
|
cdc := NewCodec()
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app2Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app2Name, logger, db, tx2Decoder(cdc))
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
@ -191,6 +191,18 @@ func (tx app2Tx) GetSignatures() []auth.StdSignature {
|
||||||
return tx.Signatures
|
return tx.Signatures
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Amino decode app2Tx. Capable of decoding both MsgSend and MsgIssue
|
||||||
|
func tx2Decoder(cdc *wire.Codec) sdk.TxDecoder {
|
||||||
|
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||||
|
var tx app2Tx
|
||||||
|
err := cdc.UnmarshalBinary(txBytes, &tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrTxDecode(err.Error())
|
||||||
|
}
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
// Simple anteHandler that ensures msg signers have signed.
|
// Simple anteHandler that ensures msg signers have signed.
|
||||||
|
|
|
@ -21,7 +21,7 @@ func NewApp3(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := NewCodec()
|
cdc := NewCodec()
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app3Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app3Name, logger, db, auth.DefaultTxDecoder(cdc))
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
|
|
@ -22,7 +22,7 @@ func NewApp4(logger log.Logger, db dbm.DB) *bapp.BaseApp {
|
||||||
cdc := NewCodec()
|
cdc := NewCodec()
|
||||||
|
|
||||||
// Create the base application object.
|
// Create the base application object.
|
||||||
app := bapp.NewBaseApp(app3Name, cdc, logger, db)
|
app := bapp.NewBaseApp(app4Name, logger, db, auth.DefaultTxDecoder(cdc))
|
||||||
|
|
||||||
// Create a key for accessing the account store.
|
// Create a key for accessing the account store.
|
||||||
keyAccount := sdk.NewKVStoreKey("acc")
|
keyAccount := sdk.NewKVStoreKey("acc")
|
||||||
|
|
|
@ -53,7 +53,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.Ba
|
||||||
// create your application type
|
// create your application type
|
||||||
var app = &BasecoinApp{
|
var app = &BasecoinApp{
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
BaseApp: bam.NewBaseApp(appName, cdc, logger, db, baseAppOptions...),
|
BaseApp: bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...),
|
||||||
keyMain: sdk.NewKVStoreKey("main"),
|
keyMain: sdk.NewKVStoreKey("main"),
|
||||||
keyAccount: sdk.NewKVStoreKey("acc"),
|
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||||
keyIBC: sdk.NewKVStoreKey("ibc"),
|
keyIBC: sdk.NewKVStoreKey("ibc"),
|
||||||
|
|
|
@ -58,7 +58,7 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
|
||||||
|
|
||||||
// Create your application object.
|
// Create your application object.
|
||||||
var app = &DemocoinApp{
|
var app = &DemocoinApp{
|
||||||
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
|
BaseApp: bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc)),
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
capKeyMainStore: sdk.NewKVStoreKey("main"),
|
capKeyMainStore: sdk.NewKVStoreKey("main"),
|
||||||
capKeyAccountStore: sdk.NewKVStoreKey("acc"),
|
capKeyAccountStore: sdk.NewKVStoreKey("acc"),
|
||||||
|
|
|
@ -32,14 +32,11 @@ func main() {
|
||||||
var capKeyMainStore = sdk.NewKVStoreKey("main")
|
var capKeyMainStore = sdk.NewKVStoreKey("main")
|
||||||
|
|
||||||
// Create BaseApp.
|
// Create BaseApp.
|
||||||
var baseApp = bam.NewBaseApp("kvstore", nil, logger, db)
|
var baseApp = bam.NewBaseApp("kvstore", logger, db, decodeTx)
|
||||||
|
|
||||||
// Set mounts for BaseApp's MultiStore.
|
// Set mounts for BaseApp's MultiStore.
|
||||||
baseApp.MountStoresIAVL(capKeyMainStore)
|
baseApp.MountStoresIAVL(capKeyMainStore)
|
||||||
|
|
||||||
// Set Tx decoder
|
|
||||||
baseApp.SetTxDecoder(decodeTx)
|
|
||||||
|
|
||||||
// Set a handler Route.
|
// Set a handler Route.
|
||||||
baseApp.Router().AddRoute("kvstore", Handler(capKeyMainStore))
|
baseApp.Router().AddRoute("kvstore", Handler(capKeyMainStore))
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,11 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||||
capKeyMainStore := sdk.NewKVStoreKey("main")
|
capKeyMainStore := sdk.NewKVStoreKey("main")
|
||||||
|
|
||||||
// Create BaseApp.
|
// Create BaseApp.
|
||||||
baseApp := bam.NewBaseApp("kvstore", nil, logger, db)
|
baseApp := bam.NewBaseApp("kvstore", logger, db, decodeTx)
|
||||||
|
|
||||||
// Set mounts for BaseApp's MultiStore.
|
// Set mounts for BaseApp's MultiStore.
|
||||||
baseApp.MountStoresIAVL(capKeyMainStore)
|
baseApp.MountStoresIAVL(capKeyMainStore)
|
||||||
|
|
||||||
// Set Tx decoder
|
|
||||||
baseApp.SetTxDecoder(decodeTx)
|
|
||||||
|
|
||||||
baseApp.SetInitChainer(InitChainer(capKeyMainStore))
|
baseApp.SetInitChainer(InitChainer(capKeyMainStore))
|
||||||
|
|
||||||
// Set a handler Route.
|
// Set a handler Route.
|
||||||
|
|
|
@ -17,11 +17,12 @@ const (
|
||||||
// NewAnteHandler returns an AnteHandler that checks
|
// NewAnteHandler returns an AnteHandler that checks
|
||||||
// and increments sequence numbers, checks signatures & account numbers,
|
// and increments sequence numbers, checks signatures & account numbers,
|
||||||
// and deducts fees from the first signer.
|
// and deducts fees from the first signer.
|
||||||
|
// nolint: gocyclo
|
||||||
func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
|
|
||||||
return func(
|
return func(
|
||||||
ctx sdk.Context, tx sdk.Tx,
|
ctx sdk.Context, tx sdk.Tx,
|
||||||
) (_ sdk.Context, _ sdk.Result, abort bool) {
|
) (newCtx sdk.Context, res sdk.Result, abort bool) {
|
||||||
|
|
||||||
// This AnteHandler requires Txs to be StdTxs
|
// This AnteHandler requires Txs to be StdTxs
|
||||||
stdTx, ok := tx.(StdTx)
|
stdTx, ok := tx.(StdTx)
|
||||||
|
@ -29,20 +30,39 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
return ctx, sdk.ErrInternal("tx must be StdTx").Result(), true
|
return ctx, sdk.ErrInternal("tx must be StdTx").Result(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the gas meter
|
||||||
|
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(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 the AnteHandler,
|
||||||
|
// but if it panics the context won't be set properly in runTx's recover ...
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch rType := r.(type) {
|
||||||
|
case sdk.ErrorOutOfGas:
|
||||||
|
log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor)
|
||||||
|
res = sdk.ErrOutOfGas(log).Result()
|
||||||
|
res.GasWanted = stdTx.Fee.Gas
|
||||||
|
res.GasUsed = newCtx.GasMeter().GasConsumed()
|
||||||
|
abort = true
|
||||||
|
default:
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
err := validateBasic(stdTx)
|
err := validateBasic(stdTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err.Result(), true
|
return newCtx, err.Result(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
sigs := stdTx.GetSignatures()
|
sigs := stdTx.GetSignatures()
|
||||||
signerAddrs := stdTx.GetSigners()
|
signerAddrs := stdTx.GetSigners()
|
||||||
msgs := tx.GetMsgs()
|
msgs := tx.GetMsgs()
|
||||||
|
|
||||||
// set the gas meter
|
|
||||||
ctx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas))
|
|
||||||
|
|
||||||
// charge gas for the memo
|
// charge gas for the memo
|
||||||
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(stdTx.GetMemo())), "memo")
|
newCtx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(stdTx.GetMemo())), "memo")
|
||||||
|
|
||||||
// Get the sign bytes (requires all account & sequence numbers and the fee)
|
// Get the sign bytes (requires all account & sequence numbers and the fee)
|
||||||
sequences := make([]int64, len(sigs))
|
sequences := make([]int64, len(sigs))
|
||||||
|
@ -59,38 +79,38 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
signerAddr, sig := signerAddrs[i], sigs[i]
|
signerAddr, sig := signerAddrs[i], sigs[i]
|
||||||
|
|
||||||
// check signature, return account with incremented nonce
|
// check signature, return account with incremented nonce
|
||||||
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], sequences[i], fee, msgs, stdTx.GetMemo())
|
signBytes := StdSignBytes(newCtx.ChainID(), accNums[i], sequences[i], fee, msgs, stdTx.GetMemo())
|
||||||
signerAcc, res := processSig(
|
signerAcc, res := processSig(
|
||||||
ctx, am,
|
newCtx, am,
|
||||||
signerAddr, sig, signBytes,
|
signerAddr, sig, signBytes,
|
||||||
)
|
)
|
||||||
if !res.IsOK() {
|
if !res.IsOK() {
|
||||||
return ctx, res, true
|
return newCtx, res, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// first sig pays the fees
|
// first sig pays the fees
|
||||||
// TODO: Add min fees
|
// TODO: Add min fees
|
||||||
// Can this function be moved outside of the loop?
|
// Can this function be moved outside of the loop?
|
||||||
if i == 0 && !fee.Amount.IsZero() {
|
if i == 0 && !fee.Amount.IsZero() {
|
||||||
ctx.GasMeter().ConsumeGas(deductFeesCost, "deductFees")
|
newCtx.GasMeter().ConsumeGas(deductFeesCost, "deductFees")
|
||||||
signerAcc, res = deductFees(signerAcc, fee)
|
signerAcc, res = deductFees(signerAcc, fee)
|
||||||
if !res.IsOK() {
|
if !res.IsOK() {
|
||||||
return ctx, res, true
|
return newCtx, res, true
|
||||||
}
|
}
|
||||||
fck.addCollectedFees(ctx, fee.Amount)
|
fck.addCollectedFees(newCtx, fee.Amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the account.
|
// Save the account.
|
||||||
am.SetAccount(ctx, signerAcc)
|
am.SetAccount(newCtx, signerAcc)
|
||||||
signerAccs[i] = signerAcc
|
signerAccs[i] = signerAcc
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache the signer accounts in the context
|
// cache the signer accounts in the context
|
||||||
ctx = WithSigners(ctx, signerAccs)
|
newCtx = WithSigners(newCtx, signerAccs)
|
||||||
|
|
||||||
// TODO: tx tags (?)
|
// TODO: tx tags (?)
|
||||||
|
|
||||||
return ctx, sdk.Result{}, false // continue...
|
return newCtx, sdk.Result{GasWanted: stdTx.Fee.Gas}, false // continue...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,21 +47,20 @@ func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx
|
||||||
|
|
||||||
// run the tx through the anteHandler and ensure it fails with the given code
|
// run the tx through the anteHandler and ensure it fails with the given code
|
||||||
func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, code sdk.CodeType) {
|
func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, code sdk.CodeType) {
|
||||||
defer func() {
|
newCtx, result, abort := anteHandler(ctx, tx)
|
||||||
if r := recover(); r != nil {
|
|
||||||
switch r.(type) {
|
|
||||||
case sdk.ErrorOutOfGas:
|
|
||||||
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOutOfGas),
|
|
||||||
fmt.Sprintf("Expected ErrorOutOfGas, got %v", r))
|
|
||||||
default:
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
_, result, abort := anteHandler(ctx, tx)
|
|
||||||
require.True(t, abort)
|
require.True(t, abort)
|
||||||
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), result.Code,
|
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), result.Code,
|
||||||
fmt.Sprintf("Expected %v, got %v", sdk.ToABCICode(sdk.CodespaceRoot, code), result))
|
fmt.Sprintf("Expected %v, got %v", sdk.ToABCICode(sdk.CodespaceRoot, code), result))
|
||||||
|
|
||||||
|
if code == sdk.CodeOutOfGas {
|
||||||
|
stdTx, ok := tx.(StdTx)
|
||||||
|
require.True(t, ok, "tx must be in form auth.StdTx")
|
||||||
|
// GasWanted set correctly
|
||||||
|
require.Equal(t, stdTx.Fee.Gas, result.GasWanted, "Gas wanted not set correctly")
|
||||||
|
require.True(t, result.GasUsed > result.GasWanted, "GasUsed not greated than GasWanted")
|
||||||
|
// Check that context is set correctly
|
||||||
|
require.Equal(t, result.GasUsed, newCtx.GasMeter().GasConsumed(), "Context not updated correctly")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee) sdk.Tx {
|
func newTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee) sdk.Tx {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -162,3 +163,22 @@ type StdSignature struct {
|
||||||
AccountNumber int64 `json:"account_number"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequence int64 `json:"sequence"`
|
Sequence int64 `json:"sequence"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logic for standard transaction decoding
|
||||||
|
func DefaultTxDecoder(cdc *wire.Codec) sdk.TxDecoder {
|
||||||
|
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||||
|
var tx = StdTx{}
|
||||||
|
|
||||||
|
if len(txBytes) == 0 {
|
||||||
|
return nil, sdk.ErrTxDecode("txBytes are empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// StdTx.Msg is an interface. The concrete types
|
||||||
|
// are registered by MakeTxCodec
|
||||||
|
err := cdc.UnmarshalBinary(txBytes, &tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrTxDecode("").TraceSDK(err.Error())
|
||||||
|
}
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,39 +3,50 @@ package bank
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// test bank module in a mock application
|
type (
|
||||||
|
expectedBalance struct {
|
||||||
|
addr sdk.AccAddress
|
||||||
|
coins sdk.Coins
|
||||||
|
}
|
||||||
|
|
||||||
|
appTestCase struct {
|
||||||
|
expPass bool
|
||||||
|
msgs []sdk.Msg
|
||||||
|
accNums []int64
|
||||||
|
accSeqs []int64
|
||||||
|
privKeys []crypto.PrivKey
|
||||||
|
expectedBalances []expectedBalance
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
priv1 = crypto.GenPrivKeyEd25519()
|
priv1 = crypto.GenPrivKeyEd25519()
|
||||||
addr1 = sdk.AccAddress(priv1.PubKey().Address())
|
addr1 = sdk.AccAddress(priv1.PubKey().Address())
|
||||||
priv2 = crypto.GenPrivKeyEd25519()
|
priv2 = crypto.GenPrivKeyEd25519()
|
||||||
addr2 = sdk.AccAddress(priv2.PubKey().Address())
|
addr2 = sdk.AccAddress(priv2.PubKey().Address())
|
||||||
addr3 = sdk.AccAddress(crypto.GenPrivKeyEd25519().PubKey().Address())
|
addr3 = sdk.AccAddress(crypto.GenPrivKeyEd25519().PubKey().Address())
|
||||||
priv4 = crypto.GenPrivKeyEd25519()
|
priv4 = crypto.GenPrivKeyEd25519()
|
||||||
addr4 = sdk.AccAddress(priv4.PubKey().Address())
|
addr4 = sdk.AccAddress(priv4.PubKey().Address())
|
||||||
|
|
||||||
coins = sdk.Coins{sdk.NewCoin("foocoin", 10)}
|
coins = sdk.Coins{sdk.NewCoin("foocoin", 10)}
|
||||||
halfCoins = sdk.Coins{sdk.NewCoin("foocoin", 5)}
|
halfCoins = sdk.Coins{sdk.NewCoin("foocoin", 5)}
|
||||||
manyCoins = sdk.Coins{sdk.NewCoin("foocoin", 1), sdk.NewCoin("barcoin", 1)}
|
manyCoins = sdk.Coins{sdk.NewCoin("foocoin", 1), sdk.NewCoin("barcoin", 1)}
|
||||||
|
freeFee = auth.NewStdFee(100000, sdk.Coins{sdk.NewCoin("foocoin", 0)}...)
|
||||||
freeFee = auth.StdFee{ // no fees for a buncha gas
|
|
||||||
sdk.Coins{sdk.NewCoin("foocoin", 0)},
|
|
||||||
100000,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMsg1 = MsgSend{
|
sendMsg1 = MsgSend{
|
||||||
Inputs: []Input{NewInput(addr1, coins)},
|
Inputs: []Input{NewInput(addr1, coins)},
|
||||||
Outputs: []Output{NewOutput(addr2, coins)},
|
Outputs: []Output{NewOutput(addr2, coins)},
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsg2 = MsgSend{
|
sendMsg2 = MsgSend{
|
||||||
Inputs: []Input{NewInput(addr1, coins)},
|
Inputs: []Input{NewInput(addr1, coins)},
|
||||||
Outputs: []Output{
|
Outputs: []Output{
|
||||||
|
@ -43,7 +54,6 @@ var (
|
||||||
NewOutput(addr3, halfCoins),
|
NewOutput(addr3, halfCoins),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsg3 = MsgSend{
|
sendMsg3 = MsgSend{
|
||||||
Inputs: []Input{
|
Inputs: []Input{
|
||||||
NewInput(addr1, coins),
|
NewInput(addr1, coins),
|
||||||
|
@ -54,7 +64,6 @@ var (
|
||||||
NewOutput(addr3, coins),
|
NewOutput(addr3, coins),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsg4 = MsgSend{
|
sendMsg4 = MsgSend{
|
||||||
Inputs: []Input{
|
Inputs: []Input{
|
||||||
NewInput(addr2, coins),
|
NewInput(addr2, coins),
|
||||||
|
@ -63,7 +72,6 @@ var (
|
||||||
NewOutput(addr1, coins),
|
NewOutput(addr1, coins),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsg5 = MsgSend{
|
sendMsg5 = MsgSend{
|
||||||
Inputs: []Input{
|
Inputs: []Input{
|
||||||
NewInput(addr1, manyCoins),
|
NewInput(addr1, manyCoins),
|
||||||
|
@ -83,39 +91,55 @@ func getMockApp(t *testing.T) *mock.App {
|
||||||
|
|
||||||
func TestMsgSendWithAccounts(t *testing.T) {
|
func TestMsgSendWithAccounts(t *testing.T) {
|
||||||
mapp := getMockApp(t)
|
mapp := getMockApp(t)
|
||||||
|
|
||||||
// Add an account at genesis
|
|
||||||
acc := &auth.BaseAccount{
|
acc := &auth.BaseAccount{
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 67)},
|
Coins: sdk.Coins{sdk.NewCoin("foocoin", 67)},
|
||||||
}
|
}
|
||||||
accs := []auth.Account{acc}
|
|
||||||
|
|
||||||
// Construct genesis state
|
mock.SetGenesis(mapp, []auth.Account{acc})
|
||||||
mock.SetGenesis(mapp, accs)
|
|
||||||
|
|
||||||
// A checkTx context (true)
|
|
||||||
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
res1 := mapp.AccountMapper.GetAccount(ctxCheck, addr1)
|
res1 := mapp.AccountMapper.GetAccount(ctxCheck, addr1)
|
||||||
require.NotNil(t, res1)
|
require.NotNil(t, res1)
|
||||||
require.Equal(t, acc, res1.(*auth.BaseAccount))
|
require.Equal(t, acc, res1.(*auth.BaseAccount))
|
||||||
|
|
||||||
// Run a CheckDeliver
|
testCases := []appTestCase{
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, true, priv1)
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg1},
|
||||||
|
accNums: []int64{0},
|
||||||
|
accSeqs: []int64{0},
|
||||||
|
expPass: true,
|
||||||
|
privKeys: []crypto.PrivKey{priv1},
|
||||||
|
expectedBalances: []expectedBalance{
|
||||||
|
expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)}},
|
||||||
|
expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg1, sendMsg2},
|
||||||
|
accNums: []int64{0},
|
||||||
|
accSeqs: []int64{0},
|
||||||
|
expPass: false,
|
||||||
|
privKeys: []crypto.PrivKey{priv1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Check balances
|
for _, tc := range testCases {
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
|
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expPass, tc.privKeys...)
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
|
||||||
|
|
||||||
// Delivering again should cause replay error
|
for _, eb := range tc.expectedBalances {
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1, sendMsg2}, []int64{0}, []int64{0}, false, priv1)
|
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bumping the txnonce number without resigning should be an auth error
|
// bumping the tx nonce number without resigning should be an auth error
|
||||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
mapp.BeginBlock(abci.RequestBeginBlock{})
|
||||||
|
|
||||||
tx := mock.GenTx([]sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, priv1)
|
tx := mock.GenTx([]sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, priv1)
|
||||||
tx.Signatures[0].Sequence = 1
|
tx.Signatures[0].Sequence = 1
|
||||||
res := mapp.Deliver(tx)
|
|
||||||
|
|
||||||
|
res := mapp.Deliver(tx)
|
||||||
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||||
|
|
||||||
// resigning the tx with the bumped sequence should work
|
// resigning the tx with the bumped sequence should work
|
||||||
|
@ -129,22 +153,35 @@ func TestMsgSendMultipleOut(t *testing.T) {
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
||||||
}
|
}
|
||||||
|
|
||||||
acc2 := &auth.BaseAccount{
|
acc2 := &auth.BaseAccount{
|
||||||
Address: addr2,
|
Address: addr2,
|
||||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
||||||
}
|
}
|
||||||
accs := []auth.Account{acc1, acc2}
|
|
||||||
|
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, []auth.Account{acc1, acc2})
|
||||||
|
|
||||||
// Simulate a Block
|
testCases := []appTestCase{
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg2}, []int64{0}, []int64{0}, true, priv1)
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg2},
|
||||||
|
accNums: []int64{0},
|
||||||
|
accSeqs: []int64{0},
|
||||||
|
expPass: true,
|
||||||
|
privKeys: []crypto.PrivKey{priv1},
|
||||||
|
expectedBalances: []expectedBalance{
|
||||||
|
expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}},
|
||||||
|
expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 47)}},
|
||||||
|
expectedBalance{addr3, sdk.Coins{sdk.NewCoin("foocoin", 5)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Check balances
|
for _, tc := range testCases {
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expPass, tc.privKeys...)
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 47)})
|
|
||||||
mock.CheckBalance(t, mapp, addr3, sdk.Coins{sdk.NewCoin("foocoin", 5)})
|
for _, eb := range tc.expectedBalances {
|
||||||
|
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSengMsgMultipleInOut(t *testing.T) {
|
func TestSengMsgMultipleInOut(t *testing.T) {
|
||||||
|
@ -162,18 +199,32 @@ func TestSengMsgMultipleInOut(t *testing.T) {
|
||||||
Address: addr4,
|
Address: addr4,
|
||||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
||||||
}
|
}
|
||||||
accs := []auth.Account{acc1, acc2, acc4}
|
|
||||||
|
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, []auth.Account{acc1, acc2, acc4})
|
||||||
|
|
||||||
// CheckDeliver
|
testCases := []appTestCase{
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg3}, []int64{0, 2}, []int64{0, 0}, true, priv1, priv4)
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg3},
|
||||||
|
accNums: []int64{0, 2},
|
||||||
|
accSeqs: []int64{0, 0},
|
||||||
|
expPass: true,
|
||||||
|
privKeys: []crypto.PrivKey{priv1, priv4},
|
||||||
|
expectedBalances: []expectedBalance{
|
||||||
|
expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}},
|
||||||
|
expectedBalance{addr4, sdk.Coins{sdk.NewCoin("foocoin", 32)}},
|
||||||
|
expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 52)}},
|
||||||
|
expectedBalance{addr3, sdk.Coins{sdk.NewCoin("foocoin", 10)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Check balances
|
for _, tc := range testCases {
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expPass, tc.privKeys...)
|
||||||
mock.CheckBalance(t, mapp, addr4, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 52)})
|
for _, eb := range tc.expectedBalances {
|
||||||
mock.CheckBalance(t, mapp, addr3, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMsgSendDependent(t *testing.T) {
|
func TestMsgSendDependent(t *testing.T) {
|
||||||
|
@ -183,20 +234,38 @@ func TestMsgSendDependent(t *testing.T) {
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
Coins: sdk.Coins{sdk.NewCoin("foocoin", 42)},
|
||||||
}
|
}
|
||||||
accs := []auth.Account{acc1}
|
|
||||||
|
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, []auth.Account{acc1})
|
||||||
|
|
||||||
// CheckDeliver
|
testCases := []appTestCase{
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, true, priv1)
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg1},
|
||||||
|
accNums: []int64{0},
|
||||||
|
accSeqs: []int64{0},
|
||||||
|
expPass: true,
|
||||||
|
privKeys: []crypto.PrivKey{priv1},
|
||||||
|
expectedBalances: []expectedBalance{
|
||||||
|
expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}},
|
||||||
|
expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgs: []sdk.Msg{sendMsg4},
|
||||||
|
accNums: []int64{1},
|
||||||
|
accSeqs: []int64{0},
|
||||||
|
expPass: true,
|
||||||
|
privKeys: []crypto.PrivKey{priv2},
|
||||||
|
expectedBalances: []expectedBalance{
|
||||||
|
expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Check balances
|
for _, tc := range testCases {
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.SignCheckDeliver(t, mapp.BaseApp, tc.msgs, tc.accNums, tc.accSeqs, tc.expPass, tc.privKeys...)
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
|
||||||
|
|
||||||
// Simulate a Block
|
for _, eb := range tc.expectedBalances {
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg4}, []int64{1}, []int64{0}, true, priv2)
|
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
|
||||||
|
}
|
||||||
// Check balances
|
}
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
flagProposalID = "proposalID"
|
flagProposalID = "proposal-id"
|
||||||
flagTitle = "title"
|
flagTitle = "title"
|
||||||
flagDescription = "description"
|
flagDescription = "description"
|
||||||
flagProposalType = "type"
|
flagProposalType = "type"
|
||||||
|
@ -239,3 +239,54 @@ func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command {
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command to Get a Proposal Information
|
||||||
|
func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "query-votes",
|
||||||
|
Short: "query votes on a proposal",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
proposalID := viper.GetInt64(flagProposalID)
|
||||||
|
|
||||||
|
ctx := context.NewCoreContextFromViper()
|
||||||
|
|
||||||
|
res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
|
||||||
|
if len(res) == 0 || err != nil {
|
||||||
|
return errors.Errorf("proposalID [%d] does not exist", proposalID)
|
||||||
|
}
|
||||||
|
|
||||||
|
var proposal gov.Proposal
|
||||||
|
cdc.MustUnmarshalBinary(res, &proposal)
|
||||||
|
|
||||||
|
if proposal.GetStatus() != gov.StatusVotingPeriod {
|
||||||
|
fmt.Println("Proposal not in voting period.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res2, err := ctx.QuerySubspace(cdc, gov.KeyVotesSubspace(proposalID), storeName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var votes []gov.Vote
|
||||||
|
for i := 0; i < len(res2); i++ {
|
||||||
|
var vote gov.Vote
|
||||||
|
cdc.MustUnmarshalBinary(res2[i].Value, &vote)
|
||||||
|
votes = append(votes, vote)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := wire.MarshalJSONIndent(cdc, votes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(output))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's votes are being queried")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec) {
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc)).Methods("GET")
|
||||||
|
|
||||||
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc)).Methods("GET")
|
||||||
|
|
||||||
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc)).Methods("GET")
|
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc)).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +337,71 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: gocyclo
|
||||||
|
// todo: Split this functionality into helper functions to remove the above
|
||||||
|
func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
strProposalID := vars[RestProposalID]
|
||||||
|
|
||||||
|
if len(strProposalID) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
err := errors.New("proposalId required but not specified")
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
proposalID, err := strconv.ParseInt(strProposalID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
err := errors.Errorf("proposalID [%s] is not positive", proposalID)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.NewCoreContextFromViper()
|
||||||
|
|
||||||
|
res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
|
||||||
|
if err != nil || len(res) == 0 {
|
||||||
|
err := errors.Errorf("proposalID [%d] does not exist", proposalID)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var proposal gov.Proposal
|
||||||
|
cdc.MustUnmarshalBinary(res, &proposal)
|
||||||
|
|
||||||
|
if proposal.GetStatus() != gov.StatusVotingPeriod {
|
||||||
|
err := errors.Errorf("proposal is not in Voting Period", proposalID)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res2, err := ctx.QuerySubspace(cdc, gov.KeyVotesSubspace(proposalID), storeName)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("ProposalID doesn't exist")
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var votes []gov.Vote
|
||||||
|
|
||||||
|
for i := 0; i < len(res2); i++ {
|
||||||
|
var vote gov.Vote
|
||||||
|
cdc.MustUnmarshalBinary(res2[i].Value, &vote)
|
||||||
|
votes = append(votes, vote)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := wire.MarshalJSONIndent(cdc, votes)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Write(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
// todo: Split this functionality into helper functions to remove the above
|
// todo: Split this functionality into helper functions to remove the above
|
||||||
func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc {
|
func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package gov
|
||||||
|
|
||||||
import (
|
import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/gov/tags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handle all "gov" type messages.
|
// Handle all "gov" type messages.
|
||||||
|
@ -32,19 +33,19 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
|
||||||
|
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(proposal.GetProposalID())
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(proposal.GetProposalID())
|
||||||
|
|
||||||
tags := sdk.NewTags(
|
resTags := sdk.NewTags(
|
||||||
"action", []byte("submitProposal"),
|
tags.Action, tags.ActionSubmitProposal,
|
||||||
"proposer", []byte(msg.Proposer.String()),
|
tags.Proposer, []byte(msg.Proposer.String()),
|
||||||
"proposalId", proposalIDBytes,
|
tags.ProposalID, proposalIDBytes,
|
||||||
)
|
)
|
||||||
|
|
||||||
if votingStarted {
|
if votingStarted {
|
||||||
tags.AppendTag("votingPeriodStart", proposalIDBytes)
|
resTags.AppendTag(tags.VotingPeriodStart, proposalIDBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdk.Result{
|
return sdk.Result{
|
||||||
Data: proposalIDBytes,
|
Data: proposalIDBytes,
|
||||||
Tags: tags,
|
Tags: resTags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,18 +59,18 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
||||||
|
|
||||||
// TODO: Add tag for if voting period started
|
// TODO: Add tag for if voting period started
|
||||||
tags := sdk.NewTags(
|
resTags := sdk.NewTags(
|
||||||
"action", []byte("deposit"),
|
tags.Action, tags.ActionDeposit,
|
||||||
"depositer", []byte(msg.Depositer.String()),
|
tags.Depositer, []byte(msg.Depositer.String()),
|
||||||
"proposalId", proposalIDBytes,
|
tags.ProposalID, proposalIDBytes,
|
||||||
)
|
)
|
||||||
|
|
||||||
if votingStarted {
|
if votingStarted {
|
||||||
tags.AppendTag("votingPeriodStart", proposalIDBytes)
|
resTags.AppendTag(tags.VotingPeriodStart, proposalIDBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdk.Result{
|
return sdk.Result{
|
||||||
Tags: tags,
|
Tags: resTags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,30 +83,32 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
|
||||||
|
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
||||||
|
|
||||||
tags := sdk.NewTags(
|
resTags := sdk.NewTags(
|
||||||
"action", []byte("vote"),
|
tags.Action, tags.ActionVote,
|
||||||
"voter", []byte(msg.Voter.String()),
|
tags.Voter, []byte(msg.Voter.String()),
|
||||||
"proposalId", proposalIDBytes,
|
tags.ProposalID, proposalIDBytes,
|
||||||
)
|
)
|
||||||
return sdk.Result{
|
return sdk.Result{
|
||||||
Tags: tags,
|
Tags: resTags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every block, process inflation, update validator set
|
// Called every block, process inflation, update validator set
|
||||||
func EndBlocker(ctx sdk.Context, keeper Keeper) (tags sdk.Tags, nonVotingVals []sdk.AccAddress) {
|
func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals []sdk.AccAddress) {
|
||||||
|
|
||||||
tags = sdk.NewTags()
|
resTags = sdk.NewTags()
|
||||||
|
|
||||||
// Delete proposals that haven't met minDeposit
|
// Delete proposals that haven't met minDeposit
|
||||||
for shouldPopInactiveProposalQueue(ctx, keeper) {
|
for shouldPopInactiveProposalQueue(ctx, keeper) {
|
||||||
inactiveProposal := keeper.InactiveProposalQueuePop(ctx)
|
inactiveProposal := keeper.InactiveProposalQueuePop(ctx)
|
||||||
if inactiveProposal.GetStatus() == StatusDepositPeriod {
|
if inactiveProposal.GetStatus() != StatusDepositPeriod {
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(inactiveProposal.GetProposalID())
|
continue
|
||||||
keeper.DeleteProposal(ctx, inactiveProposal)
|
|
||||||
tags.AppendTag("action", []byte("proposalDropped"))
|
|
||||||
tags.AppendTag("proposalId", proposalIDBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(inactiveProposal.GetProposalID())
|
||||||
|
keeper.DeleteProposal(ctx, inactiveProposal)
|
||||||
|
resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
|
||||||
|
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
var passes bool
|
var passes bool
|
||||||
|
@ -114,26 +117,31 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (tags sdk.Tags, nonVotingVals []
|
||||||
for shouldPopActiveProposalQueue(ctx, keeper) {
|
for shouldPopActiveProposalQueue(ctx, keeper) {
|
||||||
activeProposal := keeper.ActiveProposalQueuePop(ctx)
|
activeProposal := keeper.ActiveProposalQueuePop(ctx)
|
||||||
|
|
||||||
if ctx.BlockHeight() >= activeProposal.GetVotingStartBlock()+keeper.GetVotingProcedure().VotingPeriod {
|
proposalStartBlock := activeProposal.GetVotingStartBlock()
|
||||||
passes, nonVotingVals = tally(ctx, keeper, activeProposal)
|
votingPeriod := keeper.GetVotingProcedure().VotingPeriod
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
|
if ctx.BlockHeight() < proposalStartBlock+votingPeriod {
|
||||||
if passes {
|
continue
|
||||||
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
|
|
||||||
activeProposal.SetStatus(StatusPassed)
|
|
||||||
tags.AppendTag("action", []byte("proposalPassed"))
|
|
||||||
tags.AppendTag("proposalId", proposalIDBytes)
|
|
||||||
} else {
|
|
||||||
keeper.DeleteDeposits(ctx, activeProposal.GetProposalID())
|
|
||||||
activeProposal.SetStatus(StatusRejected)
|
|
||||||
tags.AppendTag("action", []byte("proposalRejected"))
|
|
||||||
tags.AppendTag("proposalId", proposalIDBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
keeper.SetProposal(ctx, activeProposal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
passes, nonVotingVals = tally(ctx, keeper, activeProposal)
|
||||||
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
|
||||||
|
var action []byte
|
||||||
|
if passes {
|
||||||
|
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
|
||||||
|
activeProposal.SetStatus(StatusPassed)
|
||||||
|
action = tags.ActionProposalPassed
|
||||||
|
} else {
|
||||||
|
keeper.DeleteDeposits(ctx, activeProposal.GetProposalID())
|
||||||
|
activeProposal.SetStatus(StatusRejected)
|
||||||
|
action = tags.ActionProposalRejected
|
||||||
|
}
|
||||||
|
keeper.SetProposal(ctx, activeProposal)
|
||||||
|
|
||||||
|
resTags.AppendTag(tags.Action, action)
|
||||||
|
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tags, nonVotingVals
|
return resTags, nonVotingVals
|
||||||
}
|
}
|
||||||
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
||||||
depositProcedure := keeper.GetDepositProcedure()
|
depositProcedure := keeper.GetDepositProcedure()
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// nolint
|
||||||
|
package tags
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ActionSubmitProposal = []byte("submit-proposal")
|
||||||
|
ActionDeposit = []byte("deposit")
|
||||||
|
ActionVote = []byte("vote")
|
||||||
|
ActionProposalDropped = []byte("proposal-dropped")
|
||||||
|
ActionProposalPassed = []byte("proposal-passed")
|
||||||
|
ActionProposalRejected = []byte("proposal-rejected")
|
||||||
|
|
||||||
|
Action = sdk.TagAction
|
||||||
|
Proposer = "proposer"
|
||||||
|
ProposalID = "proposal-id"
|
||||||
|
VotingPeriodStart = "voting-period-start"
|
||||||
|
Depositer = "depositer"
|
||||||
|
Voter = "voter"
|
||||||
|
)
|
|
@ -47,7 +47,7 @@ func NewApp() *App {
|
||||||
|
|
||||||
// Create your application object
|
// Create your application object
|
||||||
app := &App{
|
app := &App{
|
||||||
BaseApp: bam.NewBaseApp("mock", cdc, logger, db),
|
BaseApp: bam.NewBaseApp("mock", logger, db, auth.DefaultTxDecoder(cdc)),
|
||||||
Cdc: cdc,
|
Cdc: cdc,
|
||||||
KeyMain: sdk.NewKVStoreKey("main"),
|
KeyMain: sdk.NewKVStoreKey("main"),
|
||||||
KeyAccount: sdk.NewKVStoreKey("acc"),
|
KeyAccount: sdk.NewKVStoreKey("acc"),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
package tags
|
package tags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -14,10 +14,10 @@ var (
|
||||||
ActionBeginRedelegation = []byte("begin-redelegation")
|
ActionBeginRedelegation = []byte("begin-redelegation")
|
||||||
ActionCompleteRedelegation = []byte("complete-redelegation")
|
ActionCompleteRedelegation = []byte("complete-redelegation")
|
||||||
|
|
||||||
Action = types.TagAction
|
Action = sdk.TagAction
|
||||||
SrcValidator = types.TagSrcValidator
|
SrcValidator = sdk.TagSrcValidator
|
||||||
DstValidator = types.TagDstValidator
|
DstValidator = sdk.TagDstValidator
|
||||||
Delegator = types.TagDelegator
|
Delegator = sdk.TagDelegator
|
||||||
Moniker = "moniker"
|
Moniker = "moniker"
|
||||||
Identity = "Identity"
|
Identity = "identity"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue