Merge branch 'develop' into sunny/get_all_delegations_validator_querier
This commit is contained in:
commit
4d1246dae9
|
@ -137,6 +137,24 @@ jobs:
|
||||||
export PATH="$GOBIN:$PATH"
|
export PATH="$GOBIN:$PATH"
|
||||||
make test_sim_gaia_fast
|
make test_sim_gaia_fast
|
||||||
|
|
||||||
|
test_sim_gaia_import_export:
|
||||||
|
<<: *defaults
|
||||||
|
parallelism: 1
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /tmp/workspace
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: dependencies
|
||||||
|
command: |
|
||||||
|
export PATH="$GOBIN:$PATH"
|
||||||
|
make get_vendor_deps
|
||||||
|
- run:
|
||||||
|
name: Test Gaia import/export simulation
|
||||||
|
command: |
|
||||||
|
export PATH="$GOBIN:$PATH"
|
||||||
|
make test_sim_gaia_import_export
|
||||||
|
|
||||||
test_sim_gaia_multi_seed:
|
test_sim_gaia_multi_seed:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
parallelism: 1
|
parallelism: 1
|
||||||
|
@ -259,6 +277,9 @@ workflows:
|
||||||
- test_sim_gaia_fast:
|
- test_sim_gaia_fast:
|
||||||
requires:
|
requires:
|
||||||
- setup_dependencies
|
- setup_dependencies
|
||||||
|
- test_sim_gaia_import_export:
|
||||||
|
requires:
|
||||||
|
- setup_dependencies
|
||||||
- test_sim_gaia_multi_seed:
|
- test_sim_gaia_multi_seed:
|
||||||
requires:
|
requires:
|
||||||
- setup_dependencies
|
- setup_dependencies
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
|
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
|
||||||
|
|
||||||
# Primary repo maintainers
|
# Primary repo maintainers
|
||||||
* @jaekwon
|
* @ebuchman @rigelrozanski @cwgoes
|
||||||
|
|
||||||
# Precious documentation
|
# Precious documentation
|
||||||
/docs/ @zramsay @jolesbi
|
/docs/ @zramsay @jolesbi
|
||||||
|
|
57
CHANGELOG.md
57
CHANGELOG.md
|
@ -1,5 +1,62 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.26.0
|
||||||
|
|
||||||
|
BREAKING CHANGES
|
||||||
|
|
||||||
|
* Gaia
|
||||||
|
* [gaiad init] [\#2602](https://github.com/cosmos/cosmos-sdk/issues/2602) New genesis workflow
|
||||||
|
|
||||||
|
* SDK
|
||||||
|
* [simulation] [\#2665](https://github.com/cosmos/cosmos-sdk/issues/2665) only argument to simulation.Invariant is now app
|
||||||
|
|
||||||
|
* Tendermint
|
||||||
|
* Upgrade to version 0.26.0
|
||||||
|
|
||||||
|
FEATURES
|
||||||
|
|
||||||
|
* Gaia CLI (`gaiacli`)
|
||||||
|
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
||||||
|
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
||||||
|
* [cli] [\#2524](https://github.com/cosmos/cosmos-sdk/issues/2524) Add support offline mode to `gaiacli tx sign`. Lookups are not performed if the flag `--offline` is on.
|
||||||
|
* [cli] [\#2558](https://github.com/cosmos/cosmos-sdk/issues/2558) Rename --print-sigs to --validate-signatures. It now performs a complete set of sanity checks and reports to the user. Also added --print-signature-only to print the signature only, not the whole transaction.
|
||||||
|
|
||||||
|
* SDK
|
||||||
|
* [\#1336](https://github.com/cosmos/cosmos-sdk/issues/1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
|
||||||
|
|
||||||
|
IMPROVEMENTS
|
||||||
|
|
||||||
|
* Gaia
|
||||||
|
* [\#2637](https://github.com/cosmos/cosmos-sdk/issues/2637) [x/gov] Switched inactive and active proposal queues to an iterator based queue
|
||||||
|
|
||||||
|
* SDK
|
||||||
|
* [\#2573](https://github.com/cosmos/cosmos-sdk/issues/2573) [x/distribution] add accum invariance
|
||||||
|
* [\#2556](https://github.com/cosmos/cosmos-sdk/issues/2556) [x/mock/simulation] Fix debugging output
|
||||||
|
* [\#2396](https://github.com/cosmos/cosmos-sdk/issues/2396) [x/mock/simulation] Change parameters to get more slashes
|
||||||
|
* [\#2617](https://github.com/cosmos/cosmos-sdk/issues/2617) [x/mock/simulation] Randomize all genesis parameters
|
||||||
|
* [\#2669](https://github.com/cosmos/cosmos-sdk/issues/2669) [x/stake] Added invarant check to make sure validator's power aligns with its spot in the power store.
|
||||||
|
* [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) [x/mock/simulation] Use a transition matrix for block size
|
||||||
|
* [\#2660](https://github.com/cosmos/cosmos-sdk/issues/2660) [x/mock/simulation] Staking transactions get tested far more frequently
|
||||||
|
* [\#2610](https://github.com/cosmos/cosmos-sdk/issues/2610) [x/stake] Block redelegation to and from the same validator
|
||||||
|
* [\#2652](https://github.com/cosmos/cosmos-sdk/issues/2652) [x/auth] Add benchmark for get and set account
|
||||||
|
* [\#2685](https://github.com/cosmos/cosmos-sdk/issues/2685) [store] Add general merkle absence proof (also for empty substores)
|
||||||
|
* [\#2708](https://github.com/cosmos/cosmos-sdk/issues/2708) [store] Disallow setting nil values
|
||||||
|
|
||||||
|
BUG FIXES
|
||||||
|
|
||||||
|
* Gaia
|
||||||
|
* [\#2670](https://github.com/cosmos/cosmos-sdk/issues/2670) [x/stake] fixed incorrect `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
||||||
|
* [\#2691](https://github.com/cosmos/cosmos-sdk/issues/2691) Fix local testnet creation by using a single canonical genesis time
|
||||||
|
- [\#2670](https://github.com/cosmos/cosmos-sdk/issues/2670) [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
||||||
|
- [\#2648](https://github.com/cosmos/cosmos-sdk/issues/2648) [gaiad] Fix `gaiad export` / `gaiad import` consistency, test in CI
|
||||||
|
|
||||||
|
* SDK
|
||||||
|
* [\#2625](https://github.com/cosmos/cosmos-sdk/issues/2625) [x/gov] fix AppendTag function usage error
|
||||||
|
* [\#2677](https://github.com/cosmos/cosmos-sdk/issues/2677) [x/stake, x/distribution] various staking/distribution fixes as found by the simulator
|
||||||
|
* [\#2674](https://github.com/cosmos/cosmos-sdk/issues/2674) [types] Fix coin.IsLT() impl, coins.IsLT() impl, and renamed coins.Is\* to coins.IsAll\* (see [\#2686](https://github.com/cosmos/cosmos-sdk/issues/2686))
|
||||||
|
* [\#2711](https://github.com/cosmos/cosmos-sdk/issues/2711) [x/stake] Add commission data to `MsgCreateValidator` signature bytes.
|
||||||
|
* Temporarily disable insecure mode for Gaia Lite
|
||||||
|
|
||||||
## 0.25.0
|
## 0.25.0
|
||||||
|
|
||||||
*October 24th, 2018*
|
*October 24th, 2018*
|
||||||
|
|
|
@ -165,13 +165,12 @@
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
|
digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8"
|
||||||
name = "github.com/hashicorp/hcl"
|
name = "github.com/hashicorp/hcl"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"hcl/ast",
|
"hcl/ast",
|
||||||
"hcl/parser",
|
"hcl/parser",
|
||||||
"hcl/printer",
|
|
||||||
"hcl/scanner",
|
"hcl/scanner",
|
||||||
"hcl/strconv",
|
"hcl/strconv",
|
||||||
"hcl/token",
|
"hcl/token",
|
||||||
|
@ -435,7 +434,7 @@
|
||||||
version = "v0.11.1"
|
version = "v0.11.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:92d7d1678577fd1a6f3348168cef87880bbc710ef5f4e9a1216f45c56567d734"
|
digest = "1:395820b381043b9d2204e181ddf0f9147397c4a7b8f5dc3162de4cfcddf4589a"
|
||||||
name = "github.com/tendermint/tendermint"
|
name = "github.com/tendermint/tendermint"
|
||||||
packages = [
|
packages = [
|
||||||
"abci/client",
|
"abci/client",
|
||||||
|
@ -501,7 +500,8 @@
|
||||||
"version",
|
"version",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "ebee4377b15f2958b08994485375dd2ee8a649ac"
|
revision = "03e42d2e3866f01a00625f608e3bbfaeb30690de"
|
||||||
|
version = "v0.26.1-rc0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
|
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
|
||||||
|
@ -689,6 +689,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/types/time",
|
||||||
"github.com/tendermint/tendermint/version",
|
"github.com/tendermint/tendermint/version",
|
||||||
"github.com/zondax/ledger-goclient",
|
"github.com/zondax/ledger-goclient",
|
||||||
"golang.org/x/crypto/bcrypt",
|
"golang.org/x/crypto/bcrypt",
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
[[override]]
|
[[override]]
|
||||||
name = "github.com/tendermint/tendermint"
|
name = "github.com/tendermint/tendermint"
|
||||||
revision = "ebee4377b15f2958b08994485375dd2ee8a649ac" # TODO replace w/ 0.26.1
|
version = "v0.26.1-rc0" # TODO replace w/ 0.26.1
|
||||||
|
|
||||||
## deps without releases:
|
## deps without releases:
|
||||||
|
|
||||||
|
@ -84,4 +84,3 @@
|
||||||
[prune]
|
[prune]
|
||||||
go-tests = true
|
go-tests = true
|
||||||
unused-packages = true
|
unused-packages = true
|
||||||
|
|
||||||
|
|
12
Makefile
12
Makefile
|
@ -171,6 +171,15 @@ test_sim_gaia_fast:
|
||||||
@echo "Running quick Gaia simulation. This may take several minutes..."
|
@echo "Running quick Gaia simulation. This may take several minutes..."
|
||||||
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=10 -v -timeout 24h
|
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=10 -v -timeout 24h
|
||||||
|
|
||||||
|
test_sim_gaia_import_export:
|
||||||
|
@echo "Running Gaia import/export simulation. This may take several minutes..."
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=4 -v -timeout 24h
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=11 -v -timeout 24h
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=12 -v -timeout 24h
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=13 -v -timeout 24h
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=414 -v -timeout 24h
|
||||||
|
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=4142 -v -timeout 24h
|
||||||
|
|
||||||
test_sim_gaia_multi_seed:
|
test_sim_gaia_multi_seed:
|
||||||
@echo "Running multi-seed Gaia simulation. This may take awhile!"
|
@echo "Running multi-seed Gaia simulation. This may take awhile!"
|
||||||
@bash scripts/multisim.sh 25
|
@bash scripts/multisim.sh 25
|
||||||
|
@ -250,4 +259,5 @@ localnet-stop:
|
||||||
check_tools check_dev_tools get_tools get_dev_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 \
|
build-linux build-docker-gaiadnode localnet-start localnet-stop \
|
||||||
format check-ledger test_sim_gaia_nondeterminism test_sim_modules test_sim_gaia_fast test_sim_gaia_multi_seed update_tools update_dev_tools
|
format check-ledger test_sim_gaia_nondeterminism test_sim_modules test_sim_gaia_fast \
|
||||||
|
test_sim_gaia_multi_seed test_sim_gaia_import_export update_tools update_dev_tools
|
||||||
|
|
22
PENDING.md
22
PENDING.md
|
@ -7,29 +7,22 @@ BREAKING CHANGES
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
* [gaiad init] \#2602 New genesis workflow
|
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [simulation] \#2665 only argument to simulation.Invariant is now app
|
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
* Upgrade to version 0.26.0
|
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
|
|
||||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||||
|
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
|
||||||
* [cli] [\#2569](https://github.com/cosmos/cosmos-sdk/pull/2569) Add commands to query validator unbondings and redelegations
|
|
||||||
* [cli] [\#2524](https://github.com/cosmos/cosmos-sdk/issues/2524) Add support offline mode to `gaiacli tx sign`. Lookups are not performed if the flag `--offline` is on.
|
|
||||||
* [cli] [\#2558](https://github.com/cosmos/cosmos-sdk/issues/2558) Rename --print-sigs to --validate-signatures. It now performs a complete set of sanity checks and reports to the user. Also added --print-signature-only to print the signature only, not the whole transaction.
|
|
||||||
* [stake][cli] [\#2027] Add CLI query command for getting all delegations to a specific validator.
|
* [stake][cli] [\#2027] Add CLI query command for getting all delegations to a specific validator.
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* (#1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
|
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -43,16 +36,6 @@ IMPROVEMENTS
|
||||||
* Gaia
|
* Gaia
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
- \#2573 [x/distribution] add accum invariance
|
|
||||||
- \#2556 [x/mock/simulation] Fix debugging output
|
|
||||||
- \#2396 [x/mock/simulation] Change parameters to get more slashes
|
|
||||||
- \#2617 [x/mock/simulation] Randomize all genesis parameters
|
|
||||||
- \#2669 [x/stake] Added invarant check to make sure validator's power aligns with its spot in the power store.
|
|
||||||
- \#1924 [x/mock/simulation] Use a transition matrix for block size
|
|
||||||
- \#2660 [x/mock/simulation] Staking transactions get tested far more frequently
|
|
||||||
- \#2027 [x/stake] Add `Querier` for getting all delegations to a specific validator.
|
|
||||||
- \#2610 [x/stake] Block redelegation to and from the same validator
|
|
||||||
- \#2652 [x/auth] Add benchmark for get and set account
|
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -64,10 +47,7 @@ BUG FIXES
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
- \#2670 [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
|
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
- \#2625 [x/gov] fix AppendTag function usage error
|
|
||||||
- \#2677 [x/stake, x/distribution] various staking/distribution fixes as found by the simulator
|
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
|
@ -632,8 +632,8 @@ func TestSubmitProposal(t *testing.T) {
|
||||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||||
|
|
||||||
var proposalID int64
|
var proposalID uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
proposal := getProposal(t, port, proposalID)
|
proposal := getProposal(t, port, proposalID)
|
||||||
|
@ -654,8 +654,8 @@ func TestDeposit(t *testing.T) {
|
||||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||||
|
|
||||||
var proposalID int64
|
var proposalID uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
proposal := getProposal(t, port, proposalID)
|
proposal := getProposal(t, port, proposalID)
|
||||||
|
@ -688,8 +688,8 @@ func TestVote(t *testing.T) {
|
||||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||||
|
|
||||||
var proposalID int64
|
var proposalID uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
proposal := getProposal(t, port, proposalID)
|
proposal := getProposal(t, port, proposalID)
|
||||||
|
@ -736,18 +736,18 @@ func TestProposalsQuery(t *testing.T) {
|
||||||
|
|
||||||
// Addr1 proposes (and deposits) proposals #1 and #2
|
// Addr1 proposes (and deposits) proposals #1 and #2
|
||||||
resultTx := doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
|
resultTx := doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
|
||||||
var proposalID1 int64
|
var proposalID1 uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID1)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
resultTx = doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
|
resultTx = doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
|
||||||
var proposalID2 int64
|
var proposalID2 uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID2)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// Addr2 proposes (and deposits) proposals #3
|
// Addr2 proposes (and deposits) proposals #3
|
||||||
resultTx = doSubmitProposal(t, port, seeds[1], names[1], passwords[1], addrs[1], 5)
|
resultTx = doSubmitProposal(t, port, seeds[1], names[1], passwords[1], addrs[1], 5)
|
||||||
var proposalID3 int64
|
var proposalID3 uint64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
|
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID3)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// Addr2 deposits on proposals #2 & #3
|
// Addr2 deposits on proposals #2 & #3
|
||||||
|
@ -1245,7 +1245,7 @@ func getValidatorRedelegations(t *testing.T, port string, validatorAddr sdk.ValA
|
||||||
|
|
||||||
// ============= Governance Module ================
|
// ============= Governance Module ================
|
||||||
|
|
||||||
func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
|
func getProposal(t *testing.T, port string, proposalID uint64) gov.Proposal {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d", proposalID), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d", proposalID), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var proposal gov.Proposal
|
var proposal gov.Proposal
|
||||||
|
@ -1254,7 +1254,7 @@ func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
|
||||||
return proposal
|
return proposal
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
|
func getDeposits(t *testing.T, port string, proposalID uint64) []gov.Deposit {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var deposits []gov.Deposit
|
var deposits []gov.Deposit
|
||||||
|
@ -1263,7 +1263,7 @@ func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
|
||||||
return deposits
|
return deposits
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit {
|
func getDeposit(t *testing.T, port string, proposalID uint64, depositerAddr sdk.AccAddress) gov.Deposit {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var deposit gov.Deposit
|
var deposit gov.Deposit
|
||||||
|
@ -1272,7 +1272,7 @@ func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.A
|
||||||
return deposit
|
return deposit
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddress) gov.Vote {
|
func getVote(t *testing.T, port string, proposalID uint64, voterAddr sdk.AccAddress) gov.Vote {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes/%s", proposalID, voterAddr), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes/%s", proposalID, voterAddr), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var vote gov.Vote
|
var vote gov.Vote
|
||||||
|
@ -1281,7 +1281,7 @@ 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 {
|
func getVotes(t *testing.T, port string, proposalID uint64) []gov.Vote {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var votes []gov.Vote
|
var votes []gov.Vote
|
||||||
|
@ -1373,7 +1373,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||||
|
|
||||||
acc := getAccount(t, port, proposerAddr)
|
acc := getAccount(t, port, proposerAddr)
|
||||||
accnum := acc.GetAccountNumber()
|
accnum := acc.GetAccountNumber()
|
||||||
|
@ -1403,7 +1403,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||||
// get the account to get the sequence
|
// get the account to get the sequence
|
||||||
acc := getAccount(t, port, proposerAddr)
|
acc := getAccount(t, port, proposerAddr)
|
||||||
accnum := acc.GetAccountNumber()
|
accnum := acc.GetAccountNumber()
|
||||||
|
|
|
@ -2,6 +2,11 @@ package lcd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||||
|
@ -20,9 +25,6 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
|
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -46,7 +48,9 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||||
listenAddr := viper.GetString(flagListenAddr)
|
listenAddr := viper.GetString(flagListenAddr)
|
||||||
handler := createHandler(cdc)
|
handler := createHandler(cdc)
|
||||||
|
|
||||||
registerSwaggerUI(handler)
|
registerSwaggerUI(handler)
|
||||||
|
|
||||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
|
||||||
maxOpen := viper.GetInt(flagMaxOpenConnections)
|
maxOpen := viper.GetInt(flagMaxOpenConnections)
|
||||||
sslHosts := viper.GetString(flagSSLHosts)
|
sslHosts := viper.GetString(flagSSLHosts)
|
||||||
|
@ -62,14 +66,20 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
})
|
})
|
||||||
|
|
||||||
var cleanupFunc func()
|
var cleanupFunc func()
|
||||||
|
|
||||||
|
// TODO: re-enable insecure mode once #2715 has been addressed
|
||||||
if viper.GetBool(flagInsecure) {
|
if viper.GetBool(flagInsecure) {
|
||||||
listener, err = tmserver.StartHTTPServer(
|
fmt.Println(
|
||||||
listenAddr, handler, logger,
|
"Insecure mode is temporarily disabled, please locally generate an " +
|
||||||
tmserver.Config{MaxOpenConnections: maxOpen},
|
"SSL certificate to test. Support will be re-enabled soon!",
|
||||||
)
|
)
|
||||||
if err != nil {
|
// listener, err = tmserver.StartHTTPServer(
|
||||||
return
|
// listenAddr, handler, logger,
|
||||||
}
|
// tmserver.Config{MaxOpenConnections: maxOpen},
|
||||||
|
// )
|
||||||
|
// if err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
if certFile != "" {
|
if certFile != "" {
|
||||||
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
|
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
|
||||||
|
@ -77,6 +87,7 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// cert/key pair is provided, read the fingerprint
|
// cert/key pair is provided, read the fingerprint
|
||||||
fingerprint, err = fingerprintFromFile(certFile)
|
fingerprint, err = fingerprintFromFile(certFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,10 +99,12 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupFunc = func() {
|
cleanupFunc = func() {
|
||||||
os.Remove(certFile)
|
os.Remove(certFile)
|
||||||
os.Remove(keyFile)
|
os.Remove(keyFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +117,12 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info(fingerprint)
|
logger.Info(fingerprint)
|
||||||
|
logger.Info("REST server started")
|
||||||
}
|
}
|
||||||
logger.Info("REST server started")
|
|
||||||
|
// logger.Info("REST server started")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -123,6 +139,7 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
|
||||||
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
|
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
|
||||||
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||||
cmd.Flags().Bool(client.FlagIndentResponse, false, "Add indent to JSON response")
|
cmd.Flags().Bool(client.FlagIndentResponse, false, "Add indent to JSON response")
|
||||||
|
|
||||||
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
|
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
|
||||||
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
|
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
|
||||||
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
|
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
|
||||||
|
|
|
@ -65,6 +65,20 @@ func ParseInt64OrReturnBadRequest(w http.ResponseWriter, s string) (n int64, ok
|
||||||
return n, true
|
return n, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseUint64OrReturnBadRequest converts s to a uint64 value.
|
||||||
|
func ParseUint64OrReturnBadRequest(w http.ResponseWriter, s string) (n uint64, ok bool) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
n, err = strconv.ParseUint(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("'%s' is not a valid uint64", s)
|
||||||
|
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
|
return n, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, true
|
||||||
|
}
|
||||||
|
|
||||||
// ParseFloat64OrReturnBadRequest converts s to a float64 value. It returns a
|
// ParseFloat64OrReturnBadRequest converts s to a float64 value. It returns a
|
||||||
// default value, defaultIfEmpty, if the string is empty.
|
// default value, defaultIfEmpty, if the string is empty.
|
||||||
func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEmpty float64) (n float64, ok bool) {
|
func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEmpty float64) (n float64, ok bool) {
|
||||||
|
|
|
@ -210,9 +210,6 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R
|
||||||
tags := gov.EndBlocker(ctx, app.govKeeper)
|
tags := gov.EndBlocker(ctx, app.govKeeper)
|
||||||
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
||||||
|
|
||||||
// Add these new validators to the addr -> pubkey map.
|
|
||||||
app.slashingKeeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
|
|
||||||
return abci.ResponseEndBlock{
|
return abci.ResponseEndBlock{
|
||||||
ValidatorUpdates: validatorUpdates,
|
ValidatorUpdates: validatorUpdates,
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
|
@ -231,6 +228,10 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
||||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort by account number to maintain consistency
|
||||||
|
sort.Slice(genesisState.Accounts, func(i, j int) bool {
|
||||||
|
return genesisState.Accounts[i].AccountNumber < genesisState.Accounts[j].AccountNumber
|
||||||
|
})
|
||||||
// load the accounts
|
// load the accounts
|
||||||
for _, gacc := range genesisState.Accounts {
|
for _, gacc := range genesisState.Accounts {
|
||||||
acc := gacc.ToAccount()
|
acc := gacc.ToAccount()
|
||||||
|
@ -244,7 +245,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
||||||
panic(err) // TODO find a way to do this w/o panics
|
panic(err) // TODO find a way to do this w/o panics
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the address to pubkey map
|
// initialize module-specific stores
|
||||||
|
auth.InitGenesis(ctx, app.feeCollectionKeeper, genesisState.AuthData)
|
||||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
||||||
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
||||||
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
|
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
|
||||||
|
@ -270,7 +272,6 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
||||||
|
|
||||||
validators = app.stakeKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
validators = app.stakeKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||||
}
|
}
|
||||||
app.slashingKeeper.AddValidators(ctx, validators)
|
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if len(req.Validators) > 0 {
|
if len(req.Validators) > 0 {
|
||||||
|
@ -306,11 +307,12 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val
|
||||||
app.accountKeeper.IterateAccounts(ctx, appendAccount)
|
app.accountKeeper.IterateAccounts(ctx, appendAccount)
|
||||||
genState := NewGenesisState(
|
genState := NewGenesisState(
|
||||||
accounts,
|
accounts,
|
||||||
stake.WriteGenesis(ctx, app.stakeKeeper),
|
auth.ExportGenesis(ctx, app.feeCollectionKeeper),
|
||||||
mint.WriteGenesis(ctx, app.mintKeeper),
|
stake.ExportGenesis(ctx, app.stakeKeeper),
|
||||||
distr.WriteGenesis(ctx, app.distrKeeper),
|
mint.ExportGenesis(ctx, app.mintKeeper),
|
||||||
gov.WriteGenesis(ctx, app.govKeeper),
|
distr.ExportGenesis(ctx, app.distrKeeper),
|
||||||
slashing.GenesisState{}, // TODO create write methods
|
gov.ExportGenesis(ctx, app.govKeeper),
|
||||||
|
slashing.ExportGenesis(ctx, app.slashingKeeper),
|
||||||
)
|
)
|
||||||
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -337,12 +339,15 @@ var _ sdk.StakingHooks = Hooks{}
|
||||||
// nolint
|
// nolint
|
||||||
func (h Hooks) OnValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnValidatorCreated(ctx, valAddr)
|
h.dh.OnValidatorCreated(ctx, valAddr)
|
||||||
|
h.sh.OnValidatorCreated(ctx, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnValidatorModified(ctx, valAddr)
|
h.dh.OnValidatorModified(ctx, valAddr)
|
||||||
|
h.sh.OnValidatorModified(ctx, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnValidatorRemoved(ctx, valAddr)
|
h.dh.OnValidatorRemoved(ctx, consAddr, valAddr)
|
||||||
|
h.sh.OnValidatorRemoved(ctx, consAddr, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnValidatorBonded(ctx, consAddr, valAddr)
|
h.dh.OnValidatorBonded(ctx, consAddr, valAddr)
|
||||||
|
@ -358,10 +363,13 @@ func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddre
|
||||||
}
|
}
|
||||||
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnDelegationCreated(ctx, delAddr, valAddr)
|
h.dh.OnDelegationCreated(ctx, delAddr, valAddr)
|
||||||
|
h.sh.OnDelegationCreated(ctx, delAddr, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
h.dh.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||||
|
h.sh.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
h.dh.OnDelegationRemoved(ctx, delAddr, valAddr)
|
h.dh.OnDelegationRemoved(ctx, delAddr, valAddr)
|
||||||
|
h.sh.OnDelegationRemoved(ctx, delAddr, valAddr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ var (
|
||||||
// State to Unmarshal
|
// State to Unmarshal
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
Accounts []GenesisAccount `json:"accounts"`
|
Accounts []GenesisAccount `json:"accounts"`
|
||||||
|
AuthData auth.GenesisState `json:"auth"`
|
||||||
StakeData stake.GenesisState `json:"stake"`
|
StakeData stake.GenesisState `json:"stake"`
|
||||||
MintData mint.GenesisState `json:"mint"`
|
MintData mint.GenesisState `json:"mint"`
|
||||||
DistrData distr.GenesisState `json:"distr"`
|
DistrData distr.GenesisState `json:"distr"`
|
||||||
|
@ -40,11 +41,12 @@ type GenesisState struct {
|
||||||
GenTxs []json.RawMessage `json:"gentxs"`
|
GenTxs []json.RawMessage `json:"gentxs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisState(accounts []GenesisAccount, stakeData stake.GenesisState, mintData mint.GenesisState,
|
func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState, stakeData stake.GenesisState, mintData mint.GenesisState,
|
||||||
distrData distr.GenesisState, govData gov.GenesisState, slashingData slashing.GenesisState) GenesisState {
|
distrData distr.GenesisState, govData gov.GenesisState, slashingData slashing.GenesisState) GenesisState {
|
||||||
|
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
Accounts: accounts,
|
Accounts: accounts,
|
||||||
|
AuthData: authData,
|
||||||
StakeData: stakeData,
|
StakeData: stakeData,
|
||||||
MintData: mintData,
|
MintData: mintData,
|
||||||
DistrData: distrData,
|
DistrData: distrData,
|
||||||
|
@ -53,31 +55,39 @@ func NewGenesisState(accounts []GenesisAccount, stakeData stake.GenesisState, mi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenesisAccount doesn't need pubkey or sequence
|
// nolint
|
||||||
type GenesisAccount struct {
|
type GenesisAccount struct {
|
||||||
Address sdk.AccAddress `json:"address"`
|
Address sdk.AccAddress `json:"address"`
|
||||||
Coins sdk.Coins `json:"coins"`
|
Coins sdk.Coins `json:"coins"`
|
||||||
|
Sequence int64 `json:"sequence_number"`
|
||||||
|
AccountNumber int64 `json:"account_number"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
|
func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
|
||||||
return GenesisAccount{
|
return GenesisAccount{
|
||||||
Address: acc.Address,
|
Address: acc.Address,
|
||||||
Coins: acc.Coins,
|
Coins: acc.Coins,
|
||||||
|
AccountNumber: acc.AccountNumber,
|
||||||
|
Sequence: acc.Sequence,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisAccountI(acc auth.Account) GenesisAccount {
|
func NewGenesisAccountI(acc auth.Account) GenesisAccount {
|
||||||
return GenesisAccount{
|
return GenesisAccount{
|
||||||
Address: acc.GetAddress(),
|
Address: acc.GetAddress(),
|
||||||
Coins: acc.GetCoins(),
|
Coins: acc.GetCoins(),
|
||||||
|
AccountNumber: acc.GetAccountNumber(),
|
||||||
|
Sequence: acc.GetSequence(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert GenesisAccount to auth.BaseAccount
|
// convert GenesisAccount to auth.BaseAccount
|
||||||
func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
|
func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
|
||||||
return &auth.BaseAccount{
|
return &auth.BaseAccount{
|
||||||
Address: ga.Address,
|
Address: ga.Address,
|
||||||
Coins: ga.Coins.Sort(),
|
Coins: ga.Coins.Sort(),
|
||||||
|
AccountNumber: ga.AccountNumber,
|
||||||
|
Sequence: ga.Sequence,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,10 @@ package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
"testing"
|
|
||||||
|
|
||||||
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"
|
||||||
|
@ -91,8 +92,10 @@ func TestGaiaAppGenState(t *testing.T) {
|
||||||
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
|
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
|
||||||
desc := stake.NewDescription(name, "", "", "")
|
desc := stake.NewDescription(name, "", "", "")
|
||||||
comm := stakeTypes.CommissionMsg{}
|
comm := stakeTypes.CommissionMsg{}
|
||||||
msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom,
|
msg := stake.NewMsgCreateValidator(
|
||||||
50), desc, comm)
|
sdk.ValAddress(pk.Address()), pk,
|
||||||
|
sdk.NewInt64Coin(bondDenom, 50), desc, comm,
|
||||||
|
)
|
||||||
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
|
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
|
@ -70,15 +71,15 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
|
|
||||||
// Random genesis states
|
// Random genesis states
|
||||||
govGenesis := gov.GenesisState{
|
govGenesis := gov.GenesisState{
|
||||||
StartingProposalID: int64(r.Intn(100)),
|
StartingProposalID: uint64(r.Intn(100)),
|
||||||
DepositProcedure: gov.DepositProcedure{
|
DepositParams: gov.DepositParams{
|
||||||
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
|
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
|
||||||
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
||||||
},
|
},
|
||||||
VotingProcedure: gov.VotingProcedure{
|
VotingParams: gov.VotingParams{
|
||||||
VotingPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
VotingPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
|
||||||
},
|
},
|
||||||
TallyingProcedure: gov.TallyingProcedure{
|
TallyParams: gov.TallyParams{
|
||||||
Threshold: sdk.NewDecWithPrec(5, 1),
|
Threshold: sdk.NewDecWithPrec(5, 1),
|
||||||
Veto: sdk.NewDecWithPrec(334, 3),
|
Veto: sdk.NewDecWithPrec(334, 3),
|
||||||
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
||||||
|
@ -166,7 +167,7 @@ func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
|
||||||
{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
|
{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
|
||||||
{50, distrsim.SimulateMsgWithdrawValidatorRewardsAll(app.accountKeeper, app.distrKeeper)},
|
{50, distrsim.SimulateMsgWithdrawValidatorRewardsAll(app.accountKeeper, app.distrKeeper)},
|
||||||
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
|
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
|
||||||
{100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)},
|
{100, govsim.SimulateMsgDeposit(app.govKeeper)},
|
||||||
{100, stakesim.SimulateMsgCreateValidator(app.accountKeeper, app.stakeKeeper)},
|
{100, stakesim.SimulateMsgCreateValidator(app.accountKeeper, app.stakeKeeper)},
|
||||||
{5, stakesim.SimulateMsgEditValidator(app.stakeKeeper)},
|
{5, stakesim.SimulateMsgEditValidator(app.stakeKeeper)},
|
||||||
{100, stakesim.SimulateMsgDelegate(app.accountKeeper, app.stakeKeeper)},
|
{100, stakesim.SimulateMsgDelegate(app.accountKeeper, app.stakeKeeper)},
|
||||||
|
@ -266,6 +267,103 @@ func TestFullGaiaSimulation(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGaiaImportExport(t *testing.T) {
|
||||||
|
if !enabled {
|
||||||
|
t.Skip("Skipping Gaia import/export simulation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Gaia application
|
||||||
|
var logger log.Logger
|
||||||
|
if verbose {
|
||||||
|
logger = log.TestingLogger()
|
||||||
|
} else {
|
||||||
|
logger = log.NewNopLogger()
|
||||||
|
}
|
||||||
|
var db dbm.DB
|
||||||
|
dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
|
||||||
|
db, _ = dbm.NewGoLevelDB("Simulation", dir)
|
||||||
|
defer func() {
|
||||||
|
db.Close()
|
||||||
|
os.RemoveAll(dir)
|
||||||
|
}()
|
||||||
|
app := NewGaiaApp(logger, db, nil)
|
||||||
|
require.Equal(t, "GaiaApp", app.Name())
|
||||||
|
|
||||||
|
// Run randomized simulation
|
||||||
|
err := simulation.SimulateFromSeed(
|
||||||
|
t, app.BaseApp, appStateFn, seed,
|
||||||
|
testAndRunTxs(app),
|
||||||
|
[]simulation.RandSetup{},
|
||||||
|
invariants(app),
|
||||||
|
numBlocks,
|
||||||
|
blockSize,
|
||||||
|
commit,
|
||||||
|
)
|
||||||
|
if commit {
|
||||||
|
// for memdb:
|
||||||
|
// fmt.Println("Database Size", db.Stats()["database.size"])
|
||||||
|
fmt.Println("GoLevelDB Stats")
|
||||||
|
fmt.Println(db.Stats()["leveldb.stats"])
|
||||||
|
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
|
||||||
|
}
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
fmt.Printf("Exporting genesis...\n")
|
||||||
|
|
||||||
|
appState, _, err := app.ExportAppStateAndValidators()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Importing genesis...\n")
|
||||||
|
|
||||||
|
newDir, _ := ioutil.TempDir("", "goleveldb-gaia-sim-2")
|
||||||
|
newDB, _ := dbm.NewGoLevelDB("Simulation-2", dir)
|
||||||
|
defer func() {
|
||||||
|
newDB.Close()
|
||||||
|
os.RemoveAll(newDir)
|
||||||
|
}()
|
||||||
|
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil)
|
||||||
|
require.Equal(t, "GaiaApp", newApp.Name())
|
||||||
|
request := abci.RequestInitChain{
|
||||||
|
AppStateBytes: appState,
|
||||||
|
}
|
||||||
|
newApp.InitChain(request)
|
||||||
|
newApp.Commit()
|
||||||
|
|
||||||
|
fmt.Printf("Comparing stores...\n")
|
||||||
|
ctxA := app.NewContext(true, abci.Header{})
|
||||||
|
ctxB := newApp.NewContext(true, abci.Header{})
|
||||||
|
type StoreKeysPrefixes struct {
|
||||||
|
A sdk.StoreKey
|
||||||
|
B sdk.StoreKey
|
||||||
|
Prefixes [][]byte
|
||||||
|
}
|
||||||
|
storeKeysPrefixes := []StoreKeysPrefixes{
|
||||||
|
{app.keyMain, newApp.keyMain, [][]byte{}},
|
||||||
|
{app.keyAccount, newApp.keyAccount, [][]byte{}},
|
||||||
|
{app.keyStake, newApp.keyStake, [][]byte{stake.UnbondingQueueKey, stake.RedelegationQueueKey, stake.ValidatorQueueKey}}, // ordering may change but it doesn't matter
|
||||||
|
{app.keySlashing, newApp.keySlashing, [][]byte{}},
|
||||||
|
{app.keyMint, newApp.keyMint, [][]byte{}},
|
||||||
|
{app.keyDistr, newApp.keyDistr, [][]byte{}},
|
||||||
|
{app.keyFeeCollection, newApp.keyFeeCollection, [][]byte{}},
|
||||||
|
{app.keyParams, newApp.keyParams, [][]byte{}},
|
||||||
|
{app.keyGov, newApp.keyGov, [][]byte{}},
|
||||||
|
}
|
||||||
|
for _, storeKeysPrefix := range storeKeysPrefixes {
|
||||||
|
storeKeyA := storeKeysPrefix.A
|
||||||
|
storeKeyB := storeKeysPrefix.B
|
||||||
|
prefixes := storeKeysPrefix.Prefixes
|
||||||
|
storeA := ctxA.KVStore(storeKeyA)
|
||||||
|
storeB := ctxB.KVStore(storeKeyB)
|
||||||
|
kvA, kvB, count, equal := sdk.DiffKVStores(storeA, storeB, prefixes)
|
||||||
|
fmt.Printf("Compared %d key/value pairs between %s and %s\n", count, storeKeyA, storeKeyB)
|
||||||
|
require.True(t, equal, "unequal stores: %s / %s:\nstore A %s (%X) => %s (%X)\nstore B %s (%X) => %s (%X)",
|
||||||
|
storeKeyA, storeKeyB, kvA.Key, kvA.Key, kvA.Value, kvA.Value, kvB.Key, kvB.Key, kvB.Value, kvB.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Make another test for the fuzzer itself, which just has noOp txs
|
// TODO: Make another test for the fuzzer itself, which just has noOp txs
|
||||||
// and doesn't depend on gaia
|
// and doesn't depend on gaia
|
||||||
func TestAppStateDeterminism(t *testing.T) {
|
func TestAppStateDeterminism(t *testing.T) {
|
||||||
|
|
|
@ -5,13 +5,14 @@ package clitest
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
@ -352,7 +353,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
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 query proposal --proposal-id=1 --output=json %v", flags))
|
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, int64(1), proposal1.GetProposalID())
|
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||||
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
|
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
|
||||||
|
|
||||||
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals %v", flags), "")
|
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals %v", flags), "")
|
||||||
|
@ -395,7 +396,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query 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 query proposal --proposal-id=1 --output=json %v", flags))
|
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
|
||||||
require.Equal(t, int64(1), proposal1.GetProposalID())
|
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||||
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
||||||
|
|
||||||
voteStr := fmt.Sprintf("gaiacli tx vote %v", flags)
|
voteStr := fmt.Sprintf("gaiacli tx vote %v", flags)
|
||||||
|
@ -417,12 +418,12 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
vote := executeGetVote(t, fmt.Sprintf("gaiacli query vote --proposal-id=1 --voter=%s --output=json %v", fooAddr, flags))
|
vote := executeGetVote(t, fmt.Sprintf("gaiacli query vote --proposal-id=1 --voter=%s --output=json %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(1), vote.ProposalID)
|
require.Equal(t, uint64(1), vote.ProposalID)
|
||||||
require.Equal(t, gov.OptionYes, vote.Option)
|
require.Equal(t, gov.OptionYes, vote.Option)
|
||||||
|
|
||||||
votes := executeGetVotes(t, fmt.Sprintf("gaiacli query votes --proposal-id=1 --output=json %v", flags))
|
votes := executeGetVotes(t, fmt.Sprintf("gaiacli query votes --proposal-id=1 --output=json %v", flags))
|
||||||
require.Len(t, votes, 1)
|
require.Len(t, votes, 1)
|
||||||
require.Equal(t, int64(1), votes[0].ProposalID)
|
require.Equal(t, uint64(1), votes[0].ProposalID)
|
||||||
require.Equal(t, gov.OptionYes, votes[0].Option)
|
require.Equal(t, gov.OptionYes, votes[0].Option)
|
||||||
|
|
||||||
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --status=DepositPeriod %v", flags), "")
|
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --status=DepositPeriod %v", flags), "")
|
||||||
|
@ -442,7 +443,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
executeWrite(t, spStr, app.DefaultKeyPass)
|
executeWrite(t, spStr, app.DefaultKeyPass)
|
||||||
tests.WaitForNextNBlocksTM(2, port)
|
tests.WaitForNextNBlocksTM(2, port)
|
||||||
|
|
||||||
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --latest=1 %v", flags), "")
|
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --limit=1 %v", flags), "")
|
||||||
require.Equal(t, " 2 - Apples", proposalsQuery)
|
require.Equal(t, " 2 - Apples", proposalsQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package init
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
@ -12,7 +11,6 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/tendermint/go-amino"
|
|
||||||
cfg "github.com/tendermint/tendermint/config"
|
cfg "github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
"github.com/tendermint/tendermint/libs/cli"
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
@ -35,12 +33,13 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
|
||||||
RunE: func(_ *cobra.Command, _ []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
config := ctx.Config
|
config := ctx.Config
|
||||||
config.SetRoot(viper.GetString(cli.HomeFlag))
|
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||||
|
|
||||||
name := viper.GetString(client.FlagName)
|
name := viper.GetString(client.FlagName)
|
||||||
|
|
||||||
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
|
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
|
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -59,12 +58,14 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
|
||||||
NodeID: nodeID,
|
NodeID: nodeID,
|
||||||
ValPubKey: valPubKey,
|
ValPubKey: valPubKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
|
appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrint.AppMessage = appMessage
|
toPrint.AppMessage = appMessage
|
||||||
|
|
||||||
// print out some key information
|
// print out some key information
|
||||||
return displayInfo(cdc, toPrint)
|
return displayInfo(cdc, toPrint)
|
||||||
},
|
},
|
||||||
|
@ -74,23 +75,29 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func genAppStateFromConfig(cdc *codec.Codec, config *cfg.Config, initCfg initConfig,
|
func genAppStateFromConfig(
|
||||||
genDoc types.GenesisDoc) (appState json.RawMessage, err error) {
|
cdc *codec.Codec, config *cfg.Config, initCfg initConfig, genDoc types.GenesisDoc,
|
||||||
|
) (appState json.RawMessage, err error) {
|
||||||
|
|
||||||
genFile := config.GenesisFile()
|
genFile := config.GenesisFile()
|
||||||
// process genesis transactions, else create default genesis.json
|
var (
|
||||||
var appGenTxs []auth.StdTx
|
appGenTxs []auth.StdTx
|
||||||
var persistentPeers string
|
persistentPeers string
|
||||||
var genTxs []json.RawMessage
|
genTxs []json.RawMessage
|
||||||
var jsonRawTx json.RawMessage
|
jsonRawTx json.RawMessage
|
||||||
|
)
|
||||||
|
|
||||||
|
// process genesis transactions, else create default genesis.json
|
||||||
appGenTxs, persistentPeers, err = app.CollectStdTxs(
|
appGenTxs, persistentPeers, err = app.CollectStdTxs(
|
||||||
cdc, config.Moniker, initCfg.GenTxsDir, genDoc)
|
cdc, config.Moniker, initCfg.GenTxsDir, genDoc,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
genTxs = make([]json.RawMessage, len(appGenTxs))
|
genTxs = make([]json.RawMessage, len(appGenTxs))
|
||||||
config.P2P.PersistentPeers = persistentPeers
|
config.P2P.PersistentPeers = persistentPeers
|
||||||
|
|
||||||
for i, stdTx := range appGenTxs {
|
for i, stdTx := range appGenTxs {
|
||||||
jsonRawTx, err = cdc.MarshalJSON(stdTx)
|
jsonRawTx, err = cdc.MarshalJSON(stdTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -100,20 +107,12 @@ func genAppStateFromConfig(cdc *codec.Codec, config *cfg.Config, initCfg initCon
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
|
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
|
||||||
|
|
||||||
appState, err = app.GaiaAppGenStateJSON(cdc, genDoc, genTxs)
|
appState, err = app.GaiaAppGenStateJSON(cdc, genDoc, genTxs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = WriteGenesisFile(genFile, initCfg.ChainID, nil, appState)
|
err = ExportGenesisFile(genFile, initCfg.ChainID, nil, appState)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) {
|
|
||||||
genContents, err := ioutil.ReadFile(genFile)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = cdc.UnmarshalJSON(genContents, &genDoc)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package init
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tendermint/tendermint/privval"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -14,11 +13,8 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
cfg "github.com/tendermint/tendermint/config"
|
cfg "github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
"github.com/tendermint/tendermint/libs/cli"
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
"github.com/tendermint/tendermint/libs/common"
|
"github.com/tendermint/tendermint/libs/common"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -74,7 +70,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
|
||||||
viper.GetBool(flagOverwrite)); err != nil {
|
viper.GetBool(flagOverwrite)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = WriteGenesisFile(genFile, chainID, nil, appState); err != nil {
|
if err = ExportGenesisFile(genFile, chainID, nil, appState); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,54 +93,3 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
|
||||||
cmd.Flags().String(flagMoniker, "", "set the validator's moniker")
|
cmd.Flags().String(flagMoniker, "", "set the validator's moniker")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
|
|
||||||
func InitializeNodeValidatorFiles(config *cfg.Config) (nodeID string, valPubKey crypto.PubKey, err error) {
|
|
||||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
nodeID = string(nodeKey.ID())
|
|
||||||
valPubKey = ReadOrCreatePrivValidator(config.PrivValidatorFile())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteGenesisFile creates and writes the genesis configuration to disk. An
|
|
||||||
// error is returned if building or writing the configuration to file fails.
|
|
||||||
// nolint: unparam
|
|
||||||
func WriteGenesisFile(genesisFile, chainID string, validators []types.GenesisValidator, appState json.RawMessage) error {
|
|
||||||
genDoc := types.GenesisDoc{
|
|
||||||
ChainID: chainID,
|
|
||||||
Validators: validators,
|
|
||||||
AppState: appState,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := genDoc.ValidateAndComplete(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return genDoc.SaveAs(genesisFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// read of create the private key file for this config
|
|
||||||
func ReadOrCreatePrivValidator(privValFile string) crypto.PubKey {
|
|
||||||
// private validator
|
|
||||||
var privValidator *privval.FilePV
|
|
||||||
if common.FileExists(privValFile) {
|
|
||||||
privValidator = privval.LoadFilePV(privValFile)
|
|
||||||
} else {
|
|
||||||
privValidator = privval.GenFilePV(privValFile)
|
|
||||||
privValidator.Save()
|
|
||||||
}
|
|
||||||
return privValidator.GetPubKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initializeEmptyGenesis(cdc *codec.Codec, genFile string, chainID string,
|
|
||||||
overwrite bool) (appState json.RawMessage, err error) {
|
|
||||||
if !overwrite && common.FileExists(genFile) {
|
|
||||||
err = fmt.Errorf("genesis.json file already exists: %v", genFile)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState())
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,10 @@ package init
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
@ -10,10 +14,6 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -21,16 +21,17 @@ import (
|
||||||
cfg "github.com/tendermint/tendermint/config"
|
cfg "github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nodeDirPrefix = "node-dir-prefix"
|
flagNodeDirPrefix = "node-dir-prefix"
|
||||||
nValidators = "v"
|
flagNumValidators = "v"
|
||||||
outputDir = "output-dir"
|
flagOutputDir = "output-dir"
|
||||||
nodeDaemonHome = "node-daemon-home"
|
flagNodeDaemonHome = "node-daemon-home"
|
||||||
nodeCliHome = "node-cli-home"
|
flagNodeCliHome = "node-cli-home"
|
||||||
|
flagStartingIPAddress = "starting-ip-address"
|
||||||
startingIPAddress = "starting-ip-address"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const nodeDirPerm = 0755
|
const nodeDirPerm = 0755
|
||||||
|
@ -48,50 +49,59 @@ necessary files (private validator, genesis, config, etc.).
|
||||||
Note, strict routability for addresses is turned off in the config file.
|
Note, strict routability for addresses is turned off in the config file.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
gaiad testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2
|
||||||
gaiad testnet --v 4 --o ./output --starting-ip-address 192.168.10.2
|
|
||||||
`,
|
`,
|
||||||
RunE: func(_ *cobra.Command, _ []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
config := ctx.Config
|
config := ctx.Config
|
||||||
return testnetWithConfig(config, cdc)
|
return initTestnet(config, cdc)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().Int(nValidators, 4,
|
|
||||||
"Number of validators to initialize the testnet with")
|
|
||||||
cmd.Flags().StringP(outputDir, "o", "./mytestnet",
|
|
||||||
"Directory to store initialization data for the testnet")
|
|
||||||
cmd.Flags().String(nodeDirPrefix, "node",
|
|
||||||
"Prefix the directory name for each node with (node results in node0, node1, ...)")
|
|
||||||
cmd.Flags().String(nodeDaemonHome, "gaiad",
|
|
||||||
"Home directory of the node's daemon configuration")
|
|
||||||
cmd.Flags().String(nodeCliHome, "gaiacli",
|
|
||||||
"Home directory of the node's cli configuration")
|
|
||||||
|
|
||||||
cmd.Flags().String(startingIPAddress, "192.168.0.1",
|
cmd.Flags().Int(flagNumValidators, 4,
|
||||||
|
"Number of validators to initialize the testnet with",
|
||||||
|
)
|
||||||
|
cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet",
|
||||||
|
"Directory to store initialization data for the testnet",
|
||||||
|
)
|
||||||
|
cmd.Flags().String(flagNodeDirPrefix, "node",
|
||||||
|
"Prefix the directory name for each node with (node results in node0, node1, ...)",
|
||||||
|
)
|
||||||
|
cmd.Flags().String(flagNodeDaemonHome, "gaiad",
|
||||||
|
"Home directory of the node's daemon configuration",
|
||||||
|
)
|
||||||
|
cmd.Flags().String(flagNodeCliHome, "gaiacli",
|
||||||
|
"Home directory of the node's cli configuration",
|
||||||
|
)
|
||||||
|
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
|
||||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
func initTestnet(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
outDir := viper.GetString(outputDir)
|
outDir := viper.GetString(flagOutputDir)
|
||||||
numValidators := viper.GetInt(nValidators)
|
numValidators := viper.GetInt(flagNumValidators)
|
||||||
|
|
||||||
// Generate genesis.json and config.toml
|
|
||||||
chainID := "chain-" + cmn.RandStr(6)
|
chainID := "chain-" + cmn.RandStr(6)
|
||||||
|
|
||||||
monikers := make([]string, numValidators)
|
monikers := make([]string, numValidators)
|
||||||
nodeIDs := make([]string, numValidators)
|
nodeIDs := make([]string, numValidators)
|
||||||
valPubKeys := make([]crypto.PubKey, numValidators)
|
valPubKeys := make([]crypto.PubKey, numValidators)
|
||||||
|
|
||||||
// Generate private key, node ID, initial transaction
|
var (
|
||||||
var accs []app.GenesisAccount
|
accs []app.GenesisAccount
|
||||||
var genFiles []string
|
genFiles []string
|
||||||
|
)
|
||||||
|
|
||||||
|
// generate private keys, node IDs, and initial transactions
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(flagNodeDirPrefix), i)
|
||||||
nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
|
nodeDaemonHomeName := viper.GetString(flagNodeDaemonHome)
|
||||||
nodeCliHomeName := viper.GetString(nodeCliHome)
|
nodeCliHomeName := viper.GetString(flagNodeCliHome)
|
||||||
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
||||||
clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName)
|
clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName)
|
||||||
gentxsDir := filepath.Join(outDir, "gentxs")
|
gentxsDir := filepath.Join(outDir, "gentxs")
|
||||||
|
|
||||||
config.SetRoot(nodeDir)
|
config.SetRoot(nodeDir)
|
||||||
|
|
||||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
|
err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
|
||||||
|
@ -108,24 +118,27 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
|
|
||||||
monikers = append(monikers, nodeDirName)
|
monikers = append(monikers, nodeDirName)
|
||||||
config.Moniker = nodeDirName
|
config.Moniker = nodeDirName
|
||||||
ip, err := getIP(i)
|
|
||||||
|
ip, err := getIP(i, viper.GetString(flagStartingIPAddress))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.RemoveAll(outDir)
|
_ = os.RemoveAll(outDir)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeIDs[i], valPubKeys[i], err = InitializeNodeValidatorFiles(config)
|
nodeIDs[i], valPubKeys[i], err = InitializeNodeValidatorFiles(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.RemoveAll(outDir)
|
_ = os.RemoveAll(outDir)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
|
|
||||||
|
|
||||||
// write genesis
|
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
|
||||||
genFiles = append(genFiles, config.GenesisFile())
|
genFiles = append(genFiles, config.GenesisFile())
|
||||||
|
|
||||||
buf := client.BufferStdin()
|
buf := client.BufferStdin()
|
||||||
prompt := fmt.Sprintf(
|
prompt := fmt.Sprintf(
|
||||||
"Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass)
|
"Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass,
|
||||||
|
)
|
||||||
|
|
||||||
keyPass, err := client.GetPassword(prompt, buf)
|
keyPass, err := client.GetPassword(prompt, buf)
|
||||||
if err != nil && keyPass != "" {
|
if err != nil && keyPass != "" {
|
||||||
// An error was returned that either failed to read the password from
|
// An error was returned that either failed to read the password from
|
||||||
|
@ -133,6 +146,7 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
// length requirements.
|
// length requirements.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyPass == "" {
|
if keyPass == "" {
|
||||||
keyPass = app.DefaultKeyPass
|
keyPass = app.DefaultKeyPass
|
||||||
}
|
}
|
||||||
|
@ -142,11 +156,14 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
_ = os.RemoveAll(outDir)
|
_ = os.RemoveAll(outDir)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := map[string]string{"secret": secret}
|
info := map[string]string{"secret": secret}
|
||||||
|
|
||||||
cliPrint, err := json.Marshal(info)
|
cliPrint, err := json.Marshal(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// save private key seed words
|
// save private key seed words
|
||||||
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint)
|
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,6 +187,7 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
)
|
)
|
||||||
tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo)
|
tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo)
|
||||||
txBldr := authtx.NewTxBuilderFromCLI().WithChainID(chainID).WithMemo(memo)
|
txBldr := authtx.NewTxBuilderFromCLI().WithChainID(chainID).WithMemo(memo)
|
||||||
|
|
||||||
signedTx, err := txBldr.SignStdTx(nodeDirName, app.DefaultKeyPass, tx, false)
|
signedTx, err := txBldr.SignStdTx(nodeDirName, app.DefaultKeyPass, tx, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.RemoveAll(outDir)
|
_ = os.RemoveAll(outDir)
|
||||||
|
@ -182,7 +200,7 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather gentxs folder
|
// gather gentxs folder
|
||||||
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes)
|
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.RemoveAll(outDir)
|
_ = os.RemoveAll(outDir)
|
||||||
|
@ -190,37 +208,70 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate empty genesis.json
|
if err := initGenFiles(cdc, chainID, accs, genFiles, numValidators); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err := collectGenFiles(
|
||||||
|
cdc, config, chainID, monikers, nodeIDs, valPubKeys, numValidators,
|
||||||
|
outDir, viper.GetString(flagNodeDirPrefix), viper.GetString(flagNodeDaemonHome),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully initialized %d node directories\n", numValidators)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initGenFiles(
|
||||||
|
cdc *codec.Codec, chainID string, accs []app.GenesisAccount,
|
||||||
|
genFiles []string, numValidators int,
|
||||||
|
) error {
|
||||||
|
|
||||||
appGenState := app.NewDefaultGenesisState()
|
appGenState := app.NewDefaultGenesisState()
|
||||||
appGenState.Accounts = accs
|
appGenState.Accounts = accs
|
||||||
|
|
||||||
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
|
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
genDoc := types.GenesisDoc{
|
genDoc := types.GenesisDoc{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
AppState: appGenStateJSON,
|
AppState: appGenStateJSON,
|
||||||
Validators: nil,
|
Validators: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save all genesis.json files
|
// generate empty genesis files for each validator and save
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectGenFiles(
|
||||||
|
cdc *codec.Codec, config *cfg.Config, chainID string,
|
||||||
|
monikers, nodeIDs []string, valPubKeys []crypto.PubKey,
|
||||||
|
numValidators int, outDir, nodeDirPrefix, nodeDaemonHomeName string,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
var appState json.RawMessage
|
||||||
|
genTime := tmtime.Now()
|
||||||
|
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||||
nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
|
|
||||||
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
||||||
gentxsDir := filepath.Join(outDir, "gentxs")
|
gentxsDir := filepath.Join(outDir, "gentxs")
|
||||||
moniker := monikers[i]
|
moniker := monikers[i]
|
||||||
config.Moniker = nodeDirName
|
config.Moniker = nodeDirName
|
||||||
|
|
||||||
config.SetRoot(nodeDir)
|
config.SetRoot(nodeDir)
|
||||||
|
|
||||||
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
||||||
// Run `init` and generate genesis.json and config.toml
|
|
||||||
initCfg := initConfig{
|
initCfg := initConfig{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
GenTxsDir: gentxsDir,
|
GenTxsDir: gentxsDir,
|
||||||
|
@ -228,46 +279,69 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error {
|
||||||
NodeID: nodeID,
|
NodeID: nodeID,
|
||||||
ValPubKey: valPubKey,
|
ValPubKey: valPubKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
|
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := genAppStateFromConfig(cdc, config, initCfg, genDoc); err != nil {
|
|
||||||
|
nodeAppState, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if appState == nil {
|
||||||
|
// set the canonical application state (they should not differ)
|
||||||
|
appState = nodeAppState
|
||||||
|
}
|
||||||
|
|
||||||
|
genFile := config.GenesisFile()
|
||||||
|
|
||||||
|
// overwrite each validator's genesis file to have a canonical genesis time
|
||||||
|
err = ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Successfully initialized %v node directories\n", viper.GetInt(nValidators))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIP(i int) (ip string, err error) {
|
func getIP(i int, startingIPAddr string) (string, error) {
|
||||||
ip = viper.GetString(startingIPAddress)
|
var (
|
||||||
if len(ip) == 0 {
|
ip string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(startingIPAddr) == 0 {
|
||||||
ip, err = server.ExternalIP()
|
ip, err = server.ExternalIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ip, err = calculateIP(ip, i)
|
ip, err = calculateIP(startingIPAddr, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip, nil
|
return ip, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFile(name string, dir string, contents []byte) error {
|
func writeFile(name string, dir string, contents []byte) error {
|
||||||
writePath := filepath.Join(dir)
|
writePath := filepath.Join(dir)
|
||||||
file := filepath.Join(writePath, name)
|
file := filepath.Join(writePath, name)
|
||||||
|
|
||||||
err := cmn.EnsureDir(writePath, 0700)
|
err := cmn.EnsureDir(writePath, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmn.WriteFile(file, contents, 0600)
|
err = cmn.WriteFile(file, contents, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,5 +354,6 @@ func calculateIP(ip string, i int) (string, error) {
|
||||||
for j := 0; j < i; j++ {
|
for j := 0; j < i; j++ {
|
||||||
ipv4[3]++
|
ipv4[3]++
|
||||||
}
|
}
|
||||||
|
|
||||||
return ipv4.String(), nil
|
return ipv4.String(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package init
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
amino "github.com/tendermint/go-amino"
|
||||||
|
cfg "github.com/tendermint/tendermint/config"
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
"github.com/tendermint/tendermint/libs/common"
|
||||||
|
"github.com/tendermint/tendermint/p2p"
|
||||||
|
"github.com/tendermint/tendermint/privval"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExportGenesisFile creates and writes the genesis configuration to disk. An
|
||||||
|
// error is returned if building or writing the configuration to file fails.
|
||||||
|
func ExportGenesisFile(
|
||||||
|
genFile, chainID string, validators []types.GenesisValidator, appState json.RawMessage,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
genDoc := types.GenesisDoc{
|
||||||
|
ChainID: chainID,
|
||||||
|
Validators: validators,
|
||||||
|
AppState: appState,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := genDoc.ValidateAndComplete(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return genDoc.SaveAs(genFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportGenesisFileWithTime creates and writes the genesis configuration to disk.
|
||||||
|
// An error is returned if building or writing the configuration to file fails.
|
||||||
|
func ExportGenesisFileWithTime(
|
||||||
|
genFile, chainID string, validators []types.GenesisValidator,
|
||||||
|
appState json.RawMessage, genTime time.Time,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
genDoc := types.GenesisDoc{
|
||||||
|
GenesisTime: genTime,
|
||||||
|
ChainID: chainID,
|
||||||
|
Validators: validators,
|
||||||
|
AppState: appState,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := genDoc.ValidateAndComplete(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return genDoc.SaveAs(genFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read of create the private key file for this config
|
||||||
|
func ReadOrCreatePrivValidator(privValFile string) crypto.PubKey {
|
||||||
|
var privValidator *privval.FilePV
|
||||||
|
|
||||||
|
if common.FileExists(privValFile) {
|
||||||
|
privValidator = privval.LoadFilePV(privValFile)
|
||||||
|
} else {
|
||||||
|
privValidator = privval.GenFilePV(privValFile)
|
||||||
|
privValidator.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
return privValidator.GetPubKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
|
||||||
|
func InitializeNodeValidatorFiles(
|
||||||
|
config *cfg.Config) (nodeID string, valPubKey crypto.PubKey, err error,
|
||||||
|
) {
|
||||||
|
|
||||||
|
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||||
|
if err != nil {
|
||||||
|
return nodeID, valPubKey, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeID = string(nodeKey.ID())
|
||||||
|
valPubKey = ReadOrCreatePrivValidator(config.PrivValidatorFile())
|
||||||
|
|
||||||
|
return nodeID, valPubKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) {
|
||||||
|
genContents, err := ioutil.ReadFile(genFile)
|
||||||
|
if err != nil {
|
||||||
|
return genDoc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cdc.UnmarshalJSON(genContents, &genDoc); err != nil {
|
||||||
|
return genDoc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return genDoc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeEmptyGenesis(
|
||||||
|
cdc *codec.Codec, genFile, chainID string, overwrite bool,
|
||||||
|
) (appState json.RawMessage, err error) {
|
||||||
|
|
||||||
|
if !overwrite && common.FileExists(genFile) {
|
||||||
|
return nil, fmt.Errorf("genesis.json file already exists: %v", genFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState())
|
||||||
|
}
|
|
@ -96,10 +96,12 @@ type Proposal struct {
|
||||||
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
||||||
TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit
|
TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit
|
||||||
Deposits []Deposit // List of deposits on the proposal
|
Deposits []Deposit // List of deposits on the proposal
|
||||||
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
|
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
|
||||||
Submitter sdk.Address // Address of the submitter
|
DepositEndTime time.Time // Time that the DepositPeriod of a proposal would expire
|
||||||
|
Submitter sdk.AccAddress // Address of the submitter
|
||||||
|
|
||||||
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
|
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
|
||||||
|
VotingEndTime time.Time // Time of the block that the VotingPeriod for a proposal will end.
|
||||||
CurrentStatus ProposalStatus // Current status of the proposal
|
CurrentStatus ProposalStatus // Current status of the proposal
|
||||||
|
|
||||||
YesVotes sdk.Dec
|
YesVotes sdk.Dec
|
||||||
|
@ -134,46 +136,26 @@ For pseudocode purposes, here are the two function we will use to read or write
|
||||||
|
|
||||||
**Store:**
|
**Store:**
|
||||||
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
|
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
|
||||||
`ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest
|
`ProposalIDs` of proposals that reached `MinDeposit`. Each `EndBlock`, all the proposals
|
||||||
element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if
|
that have reached the end of their voting period are processed.
|
||||||
`CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is,
|
To process a finished proposal, the application tallies the votes, compute the votes of
|
||||||
then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted
|
each validator and checks if every validator in the valdiator set have voted.
|
||||||
and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded.
|
If the proposal is accepted, deposits are refunded.
|
||||||
After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated.
|
|
||||||
|
|
||||||
And the pseudocode for the `ProposalProcessingQueue`:
|
And the pseudocode for the `ProposalProcessingQueue`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
in EndBlock do
|
in EndBlock do
|
||||||
|
|
||||||
checkProposal() // First call of the recursive function
|
for finishedProposalID in GetAllFinishedProposalIDs(block.Time)
|
||||||
|
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
|
||||||
|
|
||||||
|
validators = Keeper.getAllValidators()
|
||||||
|
tmpValMap := map(sdk.AccAddress)ValidatorGovInfo
|
||||||
|
|
||||||
// Recursive function. First call in BeginBlock
|
// Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes
|
||||||
func checkProposal()
|
|
||||||
proposalID = ProposalProcessingQueue.Peek()
|
|
||||||
if (proposalID == nil)
|
|
||||||
return
|
|
||||||
|
|
||||||
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
|
|
||||||
votingProcedure = load(GlobalParams, 'VotingProcedure')
|
|
||||||
|
|
||||||
if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
|
|
||||||
|
|
||||||
// End of voting period, tally
|
|
||||||
|
|
||||||
ProposalProcessingQueue.pop()
|
|
||||||
validators =
|
|
||||||
|
|
||||||
|
|
||||||
Keeper.getAllValidators()
|
|
||||||
tmpValMap := map(sdk.Address)ValidatorGovInfo
|
|
||||||
|
|
||||||
// Initiate mapping at 0. Validators that remain at 0 at the end of tally will be punished
|
|
||||||
for each validator in validators
|
for each validator in validators
|
||||||
tmpValMap(validator).Minus = 0
|
tmpValMap(validator.OperatorAddr).Minus = 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Tally
|
// Tally
|
||||||
voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
|
voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
|
||||||
|
@ -212,5 +194,4 @@ And the pseudocode for the `ProposalProcessingQueue`:
|
||||||
proposal.CurrentStatus = ProposalStatusRejected
|
proposal.CurrentStatus = ProposalStatusRejected
|
||||||
|
|
||||||
store(Governance, <proposalID|'proposal'>, proposal)
|
store(Governance, <proposalID|'proposal'>, proposal)
|
||||||
checkProposal()
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -46,6 +46,8 @@ upon receiving txGovSubmitProposal from sender do
|
||||||
|
|
||||||
sender.AtomBalance -= initialDeposit.Atoms
|
sender.AtomBalance -= initialDeposit.Atoms
|
||||||
|
|
||||||
|
depositProcedure = load(GlobalParams, 'DepositProcedure')
|
||||||
|
|
||||||
proposalID = generate new proposalID
|
proposalID = generate new proposalID
|
||||||
proposal = NewProposal()
|
proposal = NewProposal()
|
||||||
|
|
||||||
|
@ -53,27 +55,15 @@ upon receiving txGovSubmitProposal from sender do
|
||||||
proposal.Description = txGovSubmitProposal.Description
|
proposal.Description = txGovSubmitProposal.Description
|
||||||
proposal.Type = txGovSubmitProposal.Type
|
proposal.Type = txGovSubmitProposal.Type
|
||||||
proposal.TotalDeposit = initialDeposit
|
proposal.TotalDeposit = initialDeposit
|
||||||
proposal.SubmitBlock = CurrentBlock
|
proposal.SubmitTime = <CurrentTime>
|
||||||
|
proposal.DepositEndTime = <CurrentTime>.Add(depositProcedure.MaxDepositPeriod)
|
||||||
proposal.Deposits.append({initialDeposit, sender})
|
proposal.Deposits.append({initialDeposit, sender})
|
||||||
proposal.Submitter = sender
|
proposal.Submitter = sender
|
||||||
proposal.YesVotes = 0
|
proposal.YesVotes = 0
|
||||||
proposal.NoVotes = 0
|
proposal.NoVotes = 0
|
||||||
proposal.NoWithVetoVotes = 0
|
proposal.NoWithVetoVotes = 0
|
||||||
proposal.AbstainVotes = 0
|
proposal.AbstainVotes = 0
|
||||||
|
proposal.CurrentStatus = ProposalStatusOpen
|
||||||
depositProcedure = load(GlobalParams, 'DepositProcedure')
|
|
||||||
|
|
||||||
if (initialDeposit < depositProcedure.MinDeposit)
|
|
||||||
// MinDeposit is not reached
|
|
||||||
|
|
||||||
proposal.CurrentStatus = ProposalStatusOpen
|
|
||||||
|
|
||||||
else
|
|
||||||
// MinDeposit is reached
|
|
||||||
|
|
||||||
proposal.CurrentStatus = ProposalStatusActive
|
|
||||||
proposal.VotingStartBlock = CurrentBlock
|
|
||||||
ProposalProcessingQueue.push(proposalID)
|
|
||||||
|
|
||||||
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
|
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
|
||||||
return proposalID
|
return proposalID
|
||||||
|
|
|
@ -7,7 +7,7 @@ The staking module allow for the following hooks to be registered with staking e
|
||||||
type StakingHooks interface {
|
type StakingHooks interface {
|
||||||
OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created
|
OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created
|
||||||
OnValidatorModified(ctx Context, address ValAddress) // Must be called when a validator's state changes
|
OnValidatorModified(ctx Context, address ValAddress) // Must be called when a validator's state changes
|
||||||
OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted
|
OnValidatorRemoved(ctx Context, address ConsAddress, operator ValAddress) // Must be called when a validator is deleted
|
||||||
|
|
||||||
OnValidatorBonded(ctx Context, address ConsAddress) // called when a validator is bonded
|
OnValidatorBonded(ctx Context, address ConsAddress) // called when a validator is bonded
|
||||||
OnValidatorBeginUnbonding(ctx Context, address ConsAddress, operator ValAddress) // called when a validator begins unbonding
|
OnValidatorBeginUnbonding(ctx Context, address ConsAddress, operator ValAddress) // called when a validator begins unbonding
|
||||||
|
|
|
@ -108,7 +108,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", string(out))
|
fmt.Fprintf(os.Stderr, "%s\n", string(out))
|
||||||
return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID,
|
return gaiaInit.ExportGenesisFile(config.GenesisFile(), chainID,
|
||||||
[]tmtypes.GenesisValidator{validator}, appStateJSON)
|
[]tmtypes.GenesisValidator{validator}, appStateJSON)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,8 +186,8 @@ func (app *DemocoinApp) ExportAppStateAndValidators() (appState json.RawMessage,
|
||||||
|
|
||||||
genState := types.GenesisState{
|
genState := types.GenesisState{
|
||||||
Accounts: accounts,
|
Accounts: accounts,
|
||||||
POWGenesis: pow.WriteGenesis(ctx, app.powKeeper),
|
POWGenesis: pow.ExportGenesis(ctx, app.powKeeper),
|
||||||
CoolGenesis: cool.WriteGenesis(ctx, app.coolKeeper),
|
CoolGenesis: cool.ExportGenesis(ctx, app.coolKeeper),
|
||||||
}
|
}
|
||||||
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -115,7 +115,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", string(out))
|
fmt.Fprintf(os.Stderr, "%s\n", string(out))
|
||||||
return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID,
|
return gaiaInit.ExportGenesisFile(config.GenesisFile(), chainID,
|
||||||
[]tmtypes.GenesisValidator{validator}, appStateJSON)
|
[]tmtypes.GenesisValidator{validator}, appStateJSON)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ func InitGenesis(ctx sdk.Context, k Keeper, data Genesis) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis - output the genesis trend
|
// ExportGenesis - output the genesis trend
|
||||||
func WriteGenesis(ctx sdk.Context, k Keeper) Genesis {
|
func ExportGenesis(ctx sdk.Context, k Keeper) Genesis {
|
||||||
trend := k.GetTrend(ctx)
|
trend := k.GetTrend(ctx)
|
||||||
return Genesis{trend}
|
return Genesis{trend}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ func TestCoolKeeper(t *testing.T) {
|
||||||
err := InitGenesis(ctx, keeper, Genesis{"icy"})
|
err := InitGenesis(ctx, keeper, Genesis{"icy"})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
genesis := WriteGenesis(ctx, keeper)
|
genesis := ExportGenesis(ctx, keeper)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, genesis, Genesis{"icy"})
|
require.Equal(t, genesis, Genesis{"icy"})
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,8 @@ func InitGenesis(ctx sdk.Context, k Keeper, genesis Genesis) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis for the PoW module
|
// ExportGenesis for the PoW module
|
||||||
func WriteGenesis(ctx sdk.Context, k Keeper) Genesis {
|
func ExportGenesis(ctx sdk.Context, k Keeper) Genesis {
|
||||||
difficulty, err := k.GetLastDifficulty(ctx)
|
difficulty, err := k.GetLastDifficulty(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -41,7 +41,7 @@ func TestPowKeeperGetSet(t *testing.T) {
|
||||||
err := InitGenesis(ctx, keeper, Genesis{uint64(1), uint64(0)})
|
err := InitGenesis(ctx, keeper, Genesis{uint64(1), uint64(0)})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
genesis := WriteGenesis(ctx, keeper)
|
genesis := ExportGenesis(ctx, keeper)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, genesis, Genesis{uint64(1), uint64(0)})
|
require.Equal(t, genesis, Genesis{uint64(1), uint64(0)})
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ func (ci *cacheKVStore) Set(key []byte, value []byte) {
|
||||||
ci.mtx.Lock()
|
ci.mtx.Lock()
|
||||||
defer ci.mtx.Unlock()
|
defer ci.mtx.Unlock()
|
||||||
ci.assertValidKey(key)
|
ci.assertValidKey(key)
|
||||||
|
ci.assertValidValue(value)
|
||||||
|
|
||||||
ci.setCacheValue(key, value, false, true)
|
ci.setCacheValue(key, value, false, true)
|
||||||
}
|
}
|
||||||
|
@ -196,6 +197,12 @@ func (ci *cacheKVStore) assertValidKey(key []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ci *cacheKVStore) assertValidValue(value []byte) {
|
||||||
|
if value == nil {
|
||||||
|
panic("value is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only entrypoint to mutate ci.cache.
|
// Only entrypoint to mutate ci.cache.
|
||||||
func (ci *cacheKVStore) setCacheValue(key, value []byte, deleted bool, dirty bool) {
|
func (ci *cacheKVStore) setCacheValue(key, value []byte, deleted bool, dirty bool) {
|
||||||
ci.cache[string(key)] = cValue{
|
ci.cache[string(key)] = cValue{
|
||||||
|
|
|
@ -225,8 +225,21 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||||
res.Log = err.Error()
|
res.Log = err.Error()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
res.Value = value
|
if proof == nil {
|
||||||
res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewIAVLValueOp(key, proof).ProofOp()}}
|
// Proof == nil implies that the store is empty.
|
||||||
|
if value != nil {
|
||||||
|
panic("unexpected value for an empty proof")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if value != nil {
|
||||||
|
// value was found
|
||||||
|
res.Value = value
|
||||||
|
res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewIAVLValueOp(key, proof).ProofOp()}}
|
||||||
|
} else {
|
||||||
|
// value wasn't found
|
||||||
|
res.Value = nil
|
||||||
|
res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewIAVLAbsenceOp(key, proof).ProofOp()}}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_, res.Value = tree.GetVersioned(key, res.Height)
|
_, res.Value = tree.GetVersioned(key, res.Height)
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,3 +106,69 @@ func TestVerifyMultiStoreQueryProof(t *testing.T) {
|
||||||
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte(nil))
|
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte(nil))
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerifyMultiStoreQueryProofEmptyStore(t *testing.T) {
|
||||||
|
// Create main tree for testing.
|
||||||
|
db := dbm.NewMemDB()
|
||||||
|
store := NewCommitMultiStore(db)
|
||||||
|
iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey")
|
||||||
|
|
||||||
|
store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil)
|
||||||
|
store.LoadVersion(0)
|
||||||
|
cid := store.Commit() // Commit with empty iavl store.
|
||||||
|
|
||||||
|
// Get Proof
|
||||||
|
res := store.Query(abci.RequestQuery{
|
||||||
|
Path: "/iavlStoreKey/key", // required path to get key/value+proof
|
||||||
|
Data: []byte("MYKEY"),
|
||||||
|
Prove: true,
|
||||||
|
})
|
||||||
|
require.NotNil(t, res.Proof)
|
||||||
|
|
||||||
|
// Verify proof.
|
||||||
|
prt := DefaultProofRuntime()
|
||||||
|
err := prt.VerifyAbsence(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Verify (bad) proof.
|
||||||
|
prt = DefaultProofRuntime()
|
||||||
|
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYKEY", []byte("MYVALUE"))
|
||||||
|
require.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyMultiStoreQueryProofAbsence(t *testing.T) {
|
||||||
|
// Create main tree for testing.
|
||||||
|
db := dbm.NewMemDB()
|
||||||
|
store := NewCommitMultiStore(db)
|
||||||
|
iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey")
|
||||||
|
|
||||||
|
store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil)
|
||||||
|
store.LoadVersion(0)
|
||||||
|
|
||||||
|
iavlStore := store.GetCommitStore(iavlStoreKey).(*iavlStore)
|
||||||
|
iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE"))
|
||||||
|
cid := store.Commit() // Commit with empty iavl store.
|
||||||
|
|
||||||
|
// Get Proof
|
||||||
|
res := store.Query(abci.RequestQuery{
|
||||||
|
Path: "/iavlStoreKey/key", // required path to get key/value+proof
|
||||||
|
Data: []byte("MYABSENTKEY"),
|
||||||
|
Prove: true,
|
||||||
|
})
|
||||||
|
require.NotNil(t, res.Proof)
|
||||||
|
|
||||||
|
// Verify proof.
|
||||||
|
prt := DefaultProofRuntime()
|
||||||
|
err := prt.VerifyAbsence(res.Proof, cid.Hash, "/iavlStoreKey/MYABSENTKEY")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Verify (bad) proof.
|
||||||
|
prt = DefaultProofRuntime()
|
||||||
|
err = prt.VerifyAbsence(res.Proof, cid.Hash, "/MYABSENTKEY")
|
||||||
|
require.NotNil(t, err)
|
||||||
|
|
||||||
|
// Verify (bad) proof.
|
||||||
|
prt = DefaultProofRuntime()
|
||||||
|
err = prt.VerifyValue(res.Proof, cid.Hash, "/iavlStoreKey/MYABSENTKEY", []byte(""))
|
||||||
|
require.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
|
@ -295,6 +295,10 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if res.Proof == nil || len(res.Proof.Ops) == 0 {
|
||||||
|
return sdk.ErrInternal("substore proof was nil/empty when it should never be").QueryResult()
|
||||||
|
}
|
||||||
|
|
||||||
commitInfo, errMsg := getCommitInfo(rs.db, res.Height)
|
commitInfo, errMsg := getCommitInfo(rs.db, res.Height)
|
||||||
if errMsg != nil {
|
if errMsg != nil {
|
||||||
return sdk.ErrInternal(errMsg.Error()).QueryResult()
|
return sdk.ErrInternal(errMsg.Error()).QueryResult()
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (coin Coin) IsGTE(other Coin) bool {
|
||||||
// IsLT returns true if they are the same type and the receiver is
|
// IsLT returns true if they are the same type and the receiver is
|
||||||
// a smaller value
|
// a smaller value
|
||||||
func (coin Coin) IsLT(other Coin) bool {
|
func (coin Coin) IsLT(other Coin) bool {
|
||||||
return !coin.IsGTE(other)
|
return coin.SameDenomAs(other) && coin.Amount.LT(other.Amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEqual returns true if the two sets of Coins have the same value
|
// IsEqual returns true if the two sets of Coins have the same value
|
||||||
|
@ -142,7 +142,11 @@ func (coins Coins) Plus(coinsB Coins) Coins {
|
||||||
coinA, coinB := coins[indexA], coinsB[indexB]
|
coinA, coinB := coins[indexA], coinsB[indexB]
|
||||||
switch strings.Compare(coinA.Denom, coinB.Denom) {
|
switch strings.Compare(coinA.Denom, coinB.Denom) {
|
||||||
case -1:
|
case -1:
|
||||||
sum = append(sum, coinA)
|
if coinA.IsZero() {
|
||||||
|
// ignore 0 sum coin type
|
||||||
|
} else {
|
||||||
|
sum = append(sum, coinA)
|
||||||
|
}
|
||||||
indexA++
|
indexA++
|
||||||
case 0:
|
case 0:
|
||||||
if coinA.Amount.Add(coinB.Amount).IsZero() {
|
if coinA.Amount.Add(coinB.Amount).IsZero() {
|
||||||
|
@ -153,7 +157,11 @@ func (coins Coins) Plus(coinsB Coins) Coins {
|
||||||
indexA++
|
indexA++
|
||||||
indexB++
|
indexB++
|
||||||
case 1:
|
case 1:
|
||||||
sum = append(sum, coinB)
|
if coinB.IsZero() {
|
||||||
|
// ignore 0 sum coin type
|
||||||
|
} else {
|
||||||
|
sum = append(sum, coinB)
|
||||||
|
}
|
||||||
indexB++
|
indexB++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,10 +184,19 @@ func (coins Coins) Minus(coinsB Coins) Coins {
|
||||||
return coins.Plus(coinsB.Negative())
|
return coins.Plus(coinsB.Negative())
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsGTE returns True iff coins is NonNegative(), and for every
|
// IsAllGT returns True iff for every denom in coins, the denom is present at a
|
||||||
// currency in coinsB, the currency is present at an equal or greater
|
// greater amount in coinsB.
|
||||||
// amount in coinsB
|
func (coins Coins) IsAllGT(coinsB Coins) bool {
|
||||||
func (coins Coins) IsGTE(coinsB Coins) bool {
|
diff := coins.Minus(coinsB)
|
||||||
|
if len(diff) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return diff.IsPositive()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAllGTE returns True iff for every denom in coins, the denom is present at an
|
||||||
|
// equal or greater amount in coinsB.
|
||||||
|
func (coins Coins) IsAllGTE(coinsB Coins) bool {
|
||||||
diff := coins.Minus(coinsB)
|
diff := coins.Minus(coinsB)
|
||||||
if len(diff) == 0 {
|
if len(diff) == 0 {
|
||||||
return true
|
return true
|
||||||
|
@ -187,14 +204,27 @@ func (coins Coins) IsGTE(coinsB Coins) bool {
|
||||||
return diff.IsNotNegative()
|
return diff.IsNotNegative()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLT returns True iff every currency in coins, the currency is
|
// IsAllLT returns True iff for every denom in coins, the denom is present at
|
||||||
// present at a smaller amount in coins
|
// a smaller amount in coinsB.
|
||||||
func (coins Coins) IsLT(coinsB Coins) bool {
|
func (coins Coins) IsAllLT(coinsB Coins) bool {
|
||||||
return !coins.IsGTE(coinsB)
|
diff := coinsB.Minus(coins)
|
||||||
|
if len(diff) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return diff.IsPositive()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsZero returns true if there are no coins
|
// IsAllLTE returns True iff for every denom in coins, the denom is present at
|
||||||
// or all coins are zero.
|
// a smaller or equal amount in coinsB.
|
||||||
|
func (coins Coins) IsAllLTE(coinsB Coins) bool {
|
||||||
|
diff := coinsB.Minus(coins)
|
||||||
|
if len(diff) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return diff.IsNotNegative()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero returns true if there are no coins or all coins are zero.
|
||||||
func (coins Coins) IsZero() bool {
|
func (coins Coins) IsZero() bool {
|
||||||
for _, coin := range coins {
|
for _, coin := range coins {
|
||||||
if !coin.IsZero() {
|
if !coin.IsZero() {
|
||||||
|
|
|
@ -86,7 +86,10 @@ func TestIsLTCoin(t *testing.T) {
|
||||||
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), false},
|
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), false},
|
||||||
{NewInt64Coin("A", 2), NewInt64Coin("A", 1), false},
|
{NewInt64Coin("A", 2), NewInt64Coin("A", 1), false},
|
||||||
{NewInt64Coin("A", -1), NewInt64Coin("A", 5), true},
|
{NewInt64Coin("A", -1), NewInt64Coin("A", 5), true},
|
||||||
{NewInt64Coin("a", 0), NewInt64Coin("b", 1), true},
|
{NewInt64Coin("a", 0), NewInt64Coin("b", 1), false},
|
||||||
|
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
|
||||||
|
{NewInt64Coin("a", 1), NewInt64Coin("a", 1), false},
|
||||||
|
{NewInt64Coin("a", 1), NewInt64Coin("a", 2), true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tcIndex, tc := range cases {
|
for tcIndex, tc := range cases {
|
||||||
|
@ -245,9 +248,9 @@ func TestCoins(t *testing.T) {
|
||||||
assert.True(t, good.IsValid(), "Coins are valid")
|
assert.True(t, good.IsValid(), "Coins are valid")
|
||||||
assert.True(t, good.IsPositive(), "Expected coins to be positive: %v", good)
|
assert.True(t, good.IsPositive(), "Expected coins to be positive: %v", good)
|
||||||
assert.False(t, null.IsPositive(), "Expected coins to not be positive: %v", null)
|
assert.False(t, null.IsPositive(), "Expected coins to not be positive: %v", null)
|
||||||
assert.True(t, good.IsGTE(empty), "Expected %v to be >= %v", good, empty)
|
assert.True(t, good.IsAllGTE(empty), "Expected %v to be >= %v", good, empty)
|
||||||
assert.False(t, good.IsLT(empty), "Expected %v to be < %v", good, empty)
|
assert.False(t, good.IsAllLT(empty), "Expected %v to be < %v", good, empty)
|
||||||
assert.True(t, empty.IsLT(good), "Expected %v to be < %v", empty, good)
|
assert.True(t, empty.IsAllLT(good), "Expected %v to be < %v", empty, good)
|
||||||
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
|
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
|
||||||
assert.Zero(t, len(sum), "Expected 0 coins")
|
assert.Zero(t, len(sum), "Expected 0 coins")
|
||||||
assert.False(t, badSort1.IsValid(), "Coins are not sorted")
|
assert.False(t, badSort1.IsValid(), "Coins are not sorted")
|
||||||
|
@ -257,6 +260,60 @@ func TestCoins(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCoinsGT(t *testing.T) {
|
||||||
|
one := NewInt(1)
|
||||||
|
two := NewInt(2)
|
||||||
|
|
||||||
|
assert.False(t, Coins{}.IsAllGT(Coins{}))
|
||||||
|
assert.True(t, Coins{{"A", one}}.IsAllGT(Coins{}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllGT(Coins{{"A", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllGT(Coins{{"B", one}}))
|
||||||
|
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllGT(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllGT(Coins{{"B", two}}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCoinsGTE(t *testing.T) {
|
||||||
|
one := NewInt(1)
|
||||||
|
two := NewInt(2)
|
||||||
|
|
||||||
|
assert.True(t, Coins{}.IsAllGTE(Coins{}))
|
||||||
|
assert.True(t, Coins{{"A", one}}.IsAllGTE(Coins{}))
|
||||||
|
assert.True(t, Coins{{"A", one}}.IsAllGTE(Coins{{"A", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllGTE(Coins{{"B", one}}))
|
||||||
|
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllGTE(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllGTE(Coins{{"B", two}}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCoinsLT(t *testing.T) {
|
||||||
|
one := NewInt(1)
|
||||||
|
two := NewInt(2)
|
||||||
|
|
||||||
|
assert.False(t, Coins{}.IsAllLT(Coins{}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{{"A", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"B", two}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"A", one}, {"B", one}}))
|
||||||
|
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"A", one}, {"B", two}}))
|
||||||
|
assert.True(t, Coins{}.IsAllLT(Coins{{"A", one}}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCoinsLTE(t *testing.T) {
|
||||||
|
one := NewInt(1)
|
||||||
|
two := NewInt(2)
|
||||||
|
|
||||||
|
assert.True(t, Coins{}.IsAllLTE(Coins{}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllLTE(Coins{}))
|
||||||
|
assert.True(t, Coins{{"A", one}}.IsAllLTE(Coins{{"A", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}}.IsAllLTE(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"B", one}}))
|
||||||
|
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"B", two}}))
|
||||||
|
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"A", one}, {"B", one}}))
|
||||||
|
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"A", one}, {"B", two}}))
|
||||||
|
assert.True(t, Coins{}.IsAllLTE(Coins{{"A", one}}))
|
||||||
|
}
|
||||||
|
|
||||||
func TestPlusCoins(t *testing.T) {
|
func TestPlusCoins(t *testing.T) {
|
||||||
one := NewInt(1)
|
one := NewInt(1)
|
||||||
zero := NewInt(0)
|
zero := NewInt(0)
|
||||||
|
|
|
@ -115,9 +115,9 @@ type DelegationSet interface {
|
||||||
|
|
||||||
// event hooks for staking validator object
|
// event hooks for staking validator object
|
||||||
type StakingHooks interface {
|
type StakingHooks interface {
|
||||||
OnValidatorCreated(ctx Context, valAddr ValAddress) // Must be called when a validator is created
|
OnValidatorCreated(ctx Context, valAddr ValAddress) // Must be called when a validator is created
|
||||||
OnValidatorModified(ctx Context, valAddr ValAddress) // Must be called when a validator's state changes
|
OnValidatorModified(ctx Context, valAddr ValAddress) // Must be called when a validator's state changes
|
||||||
OnValidatorRemoved(ctx Context, valAddr ValAddress) // Must be called when a validator is deleted
|
OnValidatorRemoved(ctx Context, consAddr ConsAddress, valAddr ValAddress) // Must be called when a validator is deleted
|
||||||
|
|
||||||
OnValidatorBonded(ctx Context, consAddr ConsAddress, valAddr ValAddress) // Must be called when a validator is bonded
|
OnValidatorBonded(ctx Context, consAddr ConsAddress, valAddr ValAddress) // Must be called when a validator is bonded
|
||||||
OnValidatorBeginUnbonding(ctx Context, consAddr ConsAddress, valAddr ValAddress) // Must be called when a validator begins unbonding
|
OnValidatorBeginUnbonding(ctx Context, consAddr ConsAddress, valAddr ValAddress) // Must be called when a validator begins unbonding
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ type KVStore interface {
|
||||||
// Has checks if a key exists. Panics on nil key.
|
// Has checks if a key exists. Panics on nil key.
|
||||||
Has(key []byte) bool
|
Has(key []byte) bool
|
||||||
|
|
||||||
// Set sets the key. Panics on nil key.
|
// Set sets the key. Panics on nil key or value.
|
||||||
Set(key, value []byte)
|
Set(key, value []byte)
|
||||||
|
|
||||||
// Delete deletes the key. Panics on nil key.
|
// Delete deletes the key. Panics on nil key.
|
||||||
|
@ -176,6 +177,43 @@ func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
|
||||||
return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix))
|
return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare two KVstores, return either the first key/value pair
|
||||||
|
// at which they differ and whether or not they are equal, skipping
|
||||||
|
// value comparison for a set of provided prefixes
|
||||||
|
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) {
|
||||||
|
iterA := a.Iterator(nil, nil)
|
||||||
|
iterB := b.Iterator(nil, nil)
|
||||||
|
count = int64(0)
|
||||||
|
for {
|
||||||
|
if !iterA.Valid() && !iterB.Valid() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
var kvA, kvB cmn.KVPair
|
||||||
|
if iterA.Valid() {
|
||||||
|
kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()}
|
||||||
|
iterA.Next()
|
||||||
|
}
|
||||||
|
if iterB.Valid() {
|
||||||
|
kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()}
|
||||||
|
iterB.Next()
|
||||||
|
}
|
||||||
|
compareValue := true
|
||||||
|
for _, prefix := range prefixesToSkip {
|
||||||
|
if bytes.Equal(kvA.Key[:len(prefix)], prefix) {
|
||||||
|
compareValue = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !bytes.Equal(kvA.Key, kvB.Key) {
|
||||||
|
return kvA, kvB, count, false
|
||||||
|
}
|
||||||
|
if compareValue && !bytes.Equal(kvA.Value, kvB.Value) {
|
||||||
|
return kvA, kvB, count, false
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return cmn.KVPair{}, cmn.KVPair{}, count, true
|
||||||
|
}
|
||||||
|
|
||||||
// CacheKVStore cache-wraps a KVStore. After calling .Write() on
|
// CacheKVStore cache-wraps a KVStore. After calling .Write() on
|
||||||
// the CacheKVStore, all previously created CacheKVStores on the
|
// the CacheKVStore, all previously created CacheKVStores on the
|
||||||
// object expire.
|
// object expire.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -36,6 +37,13 @@ func MustSortJSON(toSortJSON []byte) []byte {
|
||||||
return js
|
return js
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uint64ToBigEndian - marshals uint64 to a bigendian byte slice so it can be sorted
|
||||||
|
func Uint64ToBigEndian(i uint64) []byte {
|
||||||
|
b := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(b, i)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// Slight modification of the RFC3339Nano but it right pads all zeros and drops the time zone info
|
// Slight modification of the RFC3339Nano but it right pads all zeros and drops the time zone info
|
||||||
const SortableTimeFormat = "2006-01-02T15:04:05.000000000"
|
const SortableTimeFormat = "2006-01-02T15:04:05.000000000"
|
||||||
|
|
||||||
|
|
|
@ -282,7 +282,8 @@ func ensureSufficientMempoolFees(ctx sdk.Context, stdTx StdTx) sdk.Result {
|
||||||
// TODO: Make the gasPrice not a constant, and account for tx size.
|
// TODO: Make the gasPrice not a constant, and account for tx size.
|
||||||
requiredFees := adjustFeesByGas(ctx.MinimumFees(), stdTx.Fee.Gas)
|
requiredFees := adjustFeesByGas(ctx.MinimumFees(), stdTx.Fee.Gas)
|
||||||
|
|
||||||
if !ctx.MinimumFees().IsZero() && stdTx.Fee.Amount.IsLT(requiredFees) {
|
// NOTE: !A.IsAllGTE(B) is not the same as A.IsAllLT(B).
|
||||||
|
if !ctx.MinimumFees().IsZero() && !stdTx.Fee.Amount.IsAllGTE(requiredFees) {
|
||||||
// validators reject any tx from the mempool with less than the minimum fee per gas * gas factor
|
// validators reject any tx from the mempool with less than the minimum fee per gas * gas factor
|
||||||
return sdk.ErrInsufficientFee(fmt.Sprintf(
|
return sdk.ErrInsufficientFee(fmt.Sprintf(
|
||||||
"insufficient fee, got: %q required: %q", stdTx.Fee.Amount, requiredFees)).Result()
|
"insufficient fee, got: %q required: %q", stdTx.Fee.Amount, requiredFees)).Result()
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenesisState - all auth state that must be provided at genesis
|
||||||
|
type GenesisState struct {
|
||||||
|
CollectedFees sdk.Coins `json:"collected_fees"` // collected fees
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new genesis state
|
||||||
|
func NewGenesisState(collectedFees sdk.Coins) GenesisState {
|
||||||
|
return GenesisState{
|
||||||
|
CollectedFees: collectedFees,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a default genesis state
|
||||||
|
func DefaultGenesisState() GenesisState {
|
||||||
|
return NewGenesisState(sdk.Coins{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init store state from genesis data
|
||||||
|
func InitGenesis(ctx sdk.Context, keeper FeeCollectionKeeper, data GenesisState) {
|
||||||
|
keeper.setCollectedFees(ctx, data.CollectedFees)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportGenesis returns a GenesisState for a given context and keeper
|
||||||
|
func ExportGenesis(ctx sdk.Context, keeper FeeCollectionKeeper) GenesisState {
|
||||||
|
collectedFees := keeper.GetCollectedFees(ctx)
|
||||||
|
return NewGenesisState(collectedFees)
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure account has enough coins
|
// ensure account has enough coins
|
||||||
if !account.GetCoins().IsGTE(coins) {
|
if !account.GetCoins().IsAllGTE(coins) {
|
||||||
return errors.Errorf("Address %s doesn't have enough coins to pay for this transaction.", from)
|
return errors.Errorf("Address %s doesn't have enough coins to pay for this transaction.", from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ func setCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress, amt s
|
||||||
// HasCoins returns whether or not an account has at least amt coins.
|
// HasCoins returns whether or not an account has at least amt coins.
|
||||||
func hasCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) bool {
|
func hasCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) bool {
|
||||||
ctx.GasMeter().ConsumeGas(costHasCoins, "hasCoins")
|
ctx.GasMeter().ConsumeGas(costHasCoins, "hasCoins")
|
||||||
return getCoins(ctx, am, addr).IsGTE(amt)
|
return getCoins(ctx, am, addr).IsAllGTE(amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubtractCoins subtracts amt from the coins at the addr.
|
// SubtractCoins subtracts amt from the coins at the addr.
|
||||||
|
|
|
@ -21,11 +21,12 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
|
||||||
for _, dw := range data.DelegatorWithdrawInfos {
|
for _, dw := range data.DelegatorWithdrawInfos {
|
||||||
keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr)
|
keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr)
|
||||||
}
|
}
|
||||||
|
keeper.SetPreviousProposerConsAddr(ctx, data.PreviousProposer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis returns a GenesisState for a given context and keeper. The
|
// ExportGenesis returns a GenesisState for a given context and keeper. The
|
||||||
// GenesisState will contain the pool, and validator/delegator distribution info's
|
// GenesisState will contain the pool, and validator/delegator distribution info's
|
||||||
func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
||||||
feePool := keeper.GetFeePool(ctx)
|
feePool := keeper.GetFeePool(ctx)
|
||||||
communityTax := keeper.GetCommunityTax(ctx)
|
communityTax := keeper.GetCommunityTax(ctx)
|
||||||
baseProposerRewards := keeper.GetBaseProposerReward(ctx)
|
baseProposerRewards := keeper.GetBaseProposerReward(ctx)
|
||||||
|
@ -33,6 +34,7 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
||||||
vdis := keeper.GetAllValidatorDistInfos(ctx)
|
vdis := keeper.GetAllValidatorDistInfos(ctx)
|
||||||
ddis := keeper.GetAllDelegationDistInfos(ctx)
|
ddis := keeper.GetAllDelegationDistInfos(ctx)
|
||||||
dwis := keeper.GetAllDelegatorWithdrawInfos(ctx)
|
dwis := keeper.GetAllDelegatorWithdrawInfos(ctx)
|
||||||
|
pp := keeper.GetPreviousProposerConsAddr(ctx)
|
||||||
return NewGenesisState(feePool, communityTax, baseProposerRewards,
|
return NewGenesisState(feePool, communityTax, baseProposerRewards,
|
||||||
bonusProposerRewards, vdis, ddis, dwis)
|
bonusProposerRewards, vdis, ddis, dwis, pp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,12 @@ func (k Keeper) GetAllDelegationDistInfos(ctx sdk.Context) (ddis []types.Delegat
|
||||||
// Get the set of all delegator-withdraw addresses with no limits, used during genesis dump
|
// Get the set of all delegator-withdraw addresses with no limits, used during genesis dump
|
||||||
func (k Keeper) GetAllDelegatorWithdrawInfos(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) {
|
func (k Keeper) GetAllDelegatorWithdrawInfos(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
|
iterator := sdk.KVStorePrefixIterator(store, DelegatorWithdrawInfoKey)
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
|
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
dw := types.DelegatorWithdrawInfo{
|
dw := types.DelegatorWithdrawInfo{
|
||||||
DelegatorAddr: sdk.AccAddress(iterator.Key()),
|
DelegatorAddr: GetDelegatorWithdrawInfoAddress(iterator.Key()),
|
||||||
WithdrawAddr: sdk.AccAddress(iterator.Value()),
|
WithdrawAddr: sdk.AccAddress(iterator.Value()),
|
||||||
}
|
}
|
||||||
dwis = append(dwis, dw)
|
dwis = append(dwis, dw)
|
||||||
|
|
|
@ -103,7 +103,7 @@ func (h Hooks) OnValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
func (h Hooks) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
h.k.onValidatorModified(ctx, valAddr)
|
h.k.onValidatorModified(ctx, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {
|
||||||
h.k.onValidatorRemoved(ctx, valAddr)
|
h.k.onValidatorRemoved(ctx, valAddr)
|
||||||
}
|
}
|
||||||
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
|
|
|
@ -44,3 +44,12 @@ func GetDelegationDistInfosKey(delAddr sdk.AccAddress) []byte {
|
||||||
func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte {
|
func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte {
|
||||||
return append(DelegatorWithdrawInfoKey, delAddr.Bytes()...)
|
return append(DelegatorWithdrawInfoKey, delAddr.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gets an address from a delegator's withdraw info key
|
||||||
|
func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
|
||||||
|
addr := key[1:]
|
||||||
|
if len(addr) != sdk.AddrLen {
|
||||||
|
panic("unexpected key length")
|
||||||
|
}
|
||||||
|
return sdk.AccAddress(addr)
|
||||||
|
}
|
||||||
|
|
|
@ -18,10 +18,11 @@ type GenesisState struct {
|
||||||
ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"`
|
ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"`
|
||||||
DelegationDistInfos []DelegationDistInfo `json:"delegator_dist_infos"`
|
DelegationDistInfos []DelegationDistInfo `json:"delegator_dist_infos"`
|
||||||
DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
|
DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
|
||||||
|
PreviousProposer sdk.ConsAddress `json:"previous_proposer"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisState(feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec,
|
func NewGenesisState(feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec,
|
||||||
vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo) GenesisState {
|
vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo, pp sdk.ConsAddress) GenesisState {
|
||||||
|
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
FeePool: feePool,
|
FeePool: feePool,
|
||||||
|
@ -31,6 +32,7 @@ func NewGenesisState(feePool FeePool, communityTax, baseProposerReward, bonusPro
|
||||||
ValidatorDistInfos: vdis,
|
ValidatorDistInfos: vdis,
|
||||||
DelegationDistInfos: ddis,
|
DelegationDistInfos: ddis,
|
||||||
DelegatorWithdrawInfos: dwis,
|
DelegatorWithdrawInfos: dwis,
|
||||||
|
PreviousProposer: pp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
flagProposalID = "proposal-id"
|
flagProposalID = "proposal-id"
|
||||||
flagTitle = "title"
|
flagTitle = "title"
|
||||||
flagDescription = "description"
|
flagDescription = "description"
|
||||||
flagProposalType = "type"
|
flagProposalType = "type"
|
||||||
flagDeposit = "deposit"
|
flagDeposit = "deposit"
|
||||||
flagVoter = "voter"
|
flagVoter = "voter"
|
||||||
flagOption = "option"
|
flagOption = "option"
|
||||||
flagDepositer = "depositer"
|
flagDepositer = "depositer"
|
||||||
flagStatus = "status"
|
flagStatus = "status"
|
||||||
flagLatestProposalIDs = "latest"
|
flagNumLimit = "limit"
|
||||||
flagProposal = "proposal"
|
flagProposal = "proposal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type proposal struct {
|
type proposal struct {
|
||||||
|
@ -170,7 +170,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
amount, err := sdk.ParseCoins(viper.GetString(flagDeposit))
|
amount, err := sdk.ParseCoins(viper.GetString(flagDeposit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -215,7 +215,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
option := viper.GetString(flagOption)
|
option := viper.GetString(flagOption)
|
||||||
|
|
||||||
byteVoteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(option))
|
byteVoteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(option))
|
||||||
|
@ -256,7 +256,7 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Query details of a single proposal",
|
Short: "Query details of a single proposal",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
params := gov.QueryProposalParams{
|
params := gov.QueryProposalParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
|
@ -291,10 +291,10 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
bechDepositerAddr := viper.GetString(flagDepositer)
|
bechDepositerAddr := viper.GetString(flagDepositer)
|
||||||
bechVoterAddr := viper.GetString(flagVoter)
|
bechVoterAddr := viper.GetString(flagVoter)
|
||||||
strProposalStatus := viper.GetString(flagStatus)
|
strProposalStatus := viper.GetString(flagStatus)
|
||||||
latestProposalsIDs := viper.GetInt64(flagLatestProposalIDs)
|
numLimit := uint64(viper.GetInt64(flagNumLimit))
|
||||||
|
|
||||||
params := gov.QueryProposalsParams{
|
params := gov.QueryProposalsParams{
|
||||||
NumLatestProposals: latestProposalsIDs,
|
Limit: numLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(bechDepositerAddr) != 0 {
|
if len(bechDepositerAddr) != 0 {
|
||||||
|
@ -352,7 +352,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().String(flagLatestProposalIDs, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
|
cmd.Flags().String(flagNumLimit, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
|
||||||
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
|
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
|
||||||
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
|
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
|
||||||
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
|
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
|
||||||
|
@ -368,7 +368,7 @@ func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Query details of a single vote",
|
Short: "Query details of a single vote",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
voterAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagVoter))
|
voterAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagVoter))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -407,7 +407,7 @@ func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Query votes on a proposal",
|
Short: "Query votes on a proposal",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
params := gov.QueryVotesParams{
|
params := gov.QueryVotesParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
|
@ -440,7 +440,7 @@ func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Query details of a deposit",
|
Short: "Query details of a deposit",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
|
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -479,7 +479,7 @@ func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Query deposits on a proposal",
|
Short: "Query deposits on a proposal",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
params := gov.QueryDepositsParams{
|
params := gov.QueryDepositsParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
|
@ -511,7 +511,7 @@ func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
Short: "Get the tally of a proposal vote",
|
Short: "Get the tally of a proposal vote",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
proposalID := viper.GetInt64(flagProposalID)
|
proposalID := uint64(viper.GetInt64(flagProposalID))
|
||||||
|
|
||||||
params := gov.QueryTallyParams{
|
params := gov.QueryTallyParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
|
|
|
@ -22,7 +22,7 @@ const (
|
||||||
RestDepositer = "depositer"
|
RestDepositer = "depositer"
|
||||||
RestVoter = "voter"
|
RestVoter = "voter"
|
||||||
RestProposalStatus = "status"
|
RestProposalStatus = "status"
|
||||||
RestNumLatest = "latest"
|
RestNumLimit = "limit"
|
||||||
storeName = "gov"
|
storeName = "gov"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ func queryProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
strProposalID := vars[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,7 @@ func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Handle
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,7 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
||||||
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
||||||
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
|
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
|
||||||
strProposalStatus := r.URL.Query().Get(RestProposalStatus)
|
strProposalStatus := r.URL.Query().Get(RestProposalStatus)
|
||||||
strNumLatest := r.URL.Query().Get(RestNumLatest)
|
strNumLimit := r.URL.Query().Get(RestNumLimit)
|
||||||
|
|
||||||
params := gov.QueryProposalsParams{}
|
params := gov.QueryProposalsParams{}
|
||||||
|
|
||||||
|
@ -446,12 +446,12 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
||||||
}
|
}
|
||||||
params.ProposalStatus = proposalStatus
|
params.ProposalStatus = proposalStatus
|
||||||
}
|
}
|
||||||
if len(strNumLatest) != 0 {
|
if len(strNumLimit) != 0 {
|
||||||
numLatest, ok := utils.ParseInt64OrReturnBadRequest(w, strNumLatest)
|
numLimit, ok := utils.ParseUint64OrReturnBadRequest(w, strNumLimit)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
params.NumLatestProposals = numLatest
|
params.Limit = numLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
bz, err := cdc.MarshalJSON(params)
|
bz, err := cdc.MarshalJSON(params)
|
||||||
|
@ -484,7 +484,7 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// Vote
|
// Vote
|
||||||
type Vote struct {
|
type Vote struct {
|
||||||
Voter sdk.AccAddress `json:"voter"` // address of the voter
|
Voter sdk.AccAddress `json:"voter"` // address of the voter
|
||||||
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
|
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
|
||||||
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
|
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ func (voteA Vote) Empty() bool {
|
||||||
// Deposit
|
// Deposit
|
||||||
type Deposit struct {
|
type Deposit struct {
|
||||||
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
|
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
|
||||||
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
|
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
|
||||||
Amount sdk.Coins `json:"amount"` // Deposit amount
|
Amount sdk.Coins `json:"amount"` // Deposit amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,35 +16,40 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
|
||||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
govHandler := NewHandler(keeper)
|
govHandler := NewHandler(keeper)
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newHeader := ctx.BlockHeader()
|
newHeader := ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newHeader = ctx.BlockHeader()
|
newHeader = ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
|
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.True(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
EndBlocker(ctx, keeper)
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
||||||
|
@ -53,49 +58,54 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
||||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
govHandler := NewHandler(keeper)
|
govHandler := NewHandler(keeper)
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newHeader := ctx.BlockHeader()
|
newHeader := ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
res = govHandler(ctx, newProposalMsg2)
|
res = govHandler(ctx, newProposalMsg2)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
newHeader = ctx.BlockHeader()
|
newHeader = ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.True(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
EndBlocker(ctx, keeper)
|
EndBlocker(ctx, keeper)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newHeader = ctx.BlockHeader()
|
newHeader = ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.True(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
EndBlocker(ctx, keeper)
|
EndBlocker(ctx, keeper)
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTickPassedDepositPeriod(t *testing.T) {
|
func TestTickPassedDepositPeriod(t *testing.T) {
|
||||||
|
@ -104,45 +114,39 @@ func TestTickPassedDepositPeriod(t *testing.T) {
|
||||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
govHandler := NewHandler(keeper)
|
govHandler := NewHandler(keeper)
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
inactiveQueue.Close()
|
||||||
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
|
activeQueue := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
require.False(t, activeQueue.Valid())
|
||||||
|
activeQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
var proposalID int64
|
var proposalID uint64
|
||||||
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newHeader := ctx.BlockHeader()
|
newHeader := ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
inactiveQueue.Close()
|
||||||
|
|
||||||
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
res = govHandler(ctx, newDepositMsg)
|
res = govHandler(ctx, newDepositMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, activeQueue.Valid())
|
||||||
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
|
activeQueue.Close()
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
|
||||||
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
|
|
||||||
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTickPassedVotingPeriod(t *testing.T) {
|
func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
|
@ -152,17 +156,19 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
govHandler := NewHandler(keeper)
|
govHandler := NewHandler(keeper)
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
require.False(t, inactiveQueue.Valid())
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
inactiveQueue.Close()
|
||||||
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
|
activeQueue := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
require.False(t, activeQueue.Valid())
|
||||||
|
activeQueue.Close()
|
||||||
|
|
||||||
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||||
|
|
||||||
res := govHandler(ctx, newProposalMsg)
|
res := govHandler(ctx, newProposalMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
var proposalID int64
|
var proposalID uint64
|
||||||
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
|
||||||
|
|
||||||
newHeader := ctx.BlockHeader()
|
newHeader := ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||||
|
@ -172,24 +178,27 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
res = govHandler(ctx, newDepositMsg)
|
res = govHandler(ctx, newDepositMsg)
|
||||||
require.True(t, res.IsOK())
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
|
||||||
|
|
||||||
newHeader = ctx.BlockHeader()
|
newHeader = ctx.BlockHeader()
|
||||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
|
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(keeper.GetVotingParams(ctx).VotingPeriod)
|
||||||
ctx = ctx.WithBlockHeader(newHeader)
|
ctx = ctx.WithBlockHeader(newHeader)
|
||||||
|
|
||||||
require.True(t, shouldPopActiveProposalQueue(ctx, keeper))
|
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
require.False(t, inactiveQueue.Valid())
|
||||||
|
inactiveQueue.Close()
|
||||||
|
|
||||||
|
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
require.True(t, activeQueue.Valid())
|
||||||
|
var activeProposalID uint64
|
||||||
|
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeQueue.Value(), &activeProposalID)
|
||||||
|
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, activeProposalID).GetStatus())
|
||||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||||
require.True(t, depositsIterator.Valid())
|
require.True(t, depositsIterator.Valid())
|
||||||
depositsIterator.Close()
|
depositsIterator.Close()
|
||||||
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
|
activeQueue.Close()
|
||||||
|
|
||||||
EndBlocker(ctx, keeper)
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
depositsIterator = keeper.GetDeposits(ctx, proposalID)
|
require.False(t, activeQueue.Valid())
|
||||||
require.False(t, depositsIterator.Valid())
|
activeQueue.Close()
|
||||||
depositsIterator.Close()
|
|
||||||
require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus())
|
|
||||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult()))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,19 +26,19 @@ const (
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Error constructors
|
// Error constructors
|
||||||
|
|
||||||
func ErrUnknownProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
|
func ErrUnknownProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeUnknownProposal, fmt.Sprintf("Unknown proposal with id %d", proposalID))
|
return sdk.NewError(codespace, CodeUnknownProposal, fmt.Sprintf("Unknown proposal with id %d", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrInactiveProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
|
func ErrInactiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInactiveProposal, fmt.Sprintf("Inactive proposal with id %d", proposalID))
|
return sdk.NewError(codespace, CodeInactiveProposal, fmt.Sprintf("Inactive proposal with id %d", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrAlreadyActiveProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
|
func ErrAlreadyActiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeAlreadyActiveProposal, fmt.Sprintf("Proposal %d has been already active", proposalID))
|
return sdk.NewError(codespace, CodeAlreadyActiveProposal, fmt.Sprintf("Proposal %d has been already active", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrAlreadyFinishedProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
|
func ErrAlreadyFinishedProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeAlreadyFinishedProposal, fmt.Sprintf("Proposal %d has already passed its voting period", proposalID))
|
return sdk.NewError(codespace, CodeAlreadyFinishedProposal, fmt.Sprintf("Proposal %d has already passed its voting period", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,33 @@ import (
|
||||||
|
|
||||||
// GenesisState - all staking state that must be provided at genesis
|
// GenesisState - all staking state that must be provided at genesis
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
StartingProposalID int64 `json:"starting_proposalID"`
|
StartingProposalID uint64 `json:"starting_proposal_id"`
|
||||||
DepositProcedure DepositProcedure `json:"deposit_period"`
|
Deposits []DepositWithMetadata `json:"deposits"`
|
||||||
VotingProcedure VotingProcedure `json:"voting_period"`
|
Votes []VoteWithMetadata `json:"votes"`
|
||||||
TallyingProcedure TallyingProcedure `json:"tallying_procedure"`
|
Proposals []Proposal `json:"proposals"`
|
||||||
|
DepositParams DepositParams `json:"deposit_params"`
|
||||||
|
VotingParams VotingParams `json:"voting_params"`
|
||||||
|
TallyParams TallyParams `json:"tally_params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisState(startingProposalID int64, dp DepositProcedure, vp VotingProcedure, tp TallyingProcedure) GenesisState {
|
// DepositWithMetadata (just for genesis)
|
||||||
|
type DepositWithMetadata struct {
|
||||||
|
ProposalID uint64 `json:"proposal_id"`
|
||||||
|
Deposit Deposit `json:"deposit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VoteWithMetadata (just for genesis)
|
||||||
|
type VoteWithMetadata struct {
|
||||||
|
ProposalID uint64 `json:"proposal_id"`
|
||||||
|
Vote Vote `json:"vote"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGenesisState(startingProposalID uint64, dp DepositParams, vp VotingParams, tp TallyParams) GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
StartingProposalID: startingProposalID,
|
StartingProposalID: startingProposalID,
|
||||||
DepositProcedure: dp,
|
DepositParams: dp,
|
||||||
VotingProcedure: vp,
|
VotingParams: vp,
|
||||||
TallyingProcedure: tp,
|
TallyParams: tp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +42,14 @@ func NewGenesisState(startingProposalID int64, dp DepositProcedure, vp VotingPro
|
||||||
func DefaultGenesisState() GenesisState {
|
func DefaultGenesisState() GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
StartingProposalID: 1,
|
StartingProposalID: 1,
|
||||||
DepositProcedure: DepositProcedure{
|
DepositParams: DepositParams{
|
||||||
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
|
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
|
||||||
MaxDepositPeriod: time.Duration(172800) * time.Second,
|
MaxDepositPeriod: time.Duration(172800) * time.Second,
|
||||||
},
|
},
|
||||||
VotingProcedure: VotingProcedure{
|
VotingParams: VotingParams{
|
||||||
VotingPeriod: time.Duration(172800) * time.Second,
|
VotingPeriod: time.Duration(172800) * time.Second,
|
||||||
},
|
},
|
||||||
TallyingProcedure: TallyingProcedure{
|
TallyParams: TallyParams{
|
||||||
Threshold: sdk.NewDecWithPrec(5, 1),
|
Threshold: sdk.NewDecWithPrec(5, 1),
|
||||||
Veto: sdk.NewDecWithPrec(334, 3),
|
Veto: sdk.NewDecWithPrec(334, 3),
|
||||||
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
||||||
|
@ -49,22 +64,52 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
|
||||||
// TODO: Handle this with #870
|
// TODO: Handle this with #870
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
k.setDepositProcedure(ctx, data.DepositProcedure)
|
k.setDepositParams(ctx, data.DepositParams)
|
||||||
k.setVotingProcedure(ctx, data.VotingProcedure)
|
k.setVotingParams(ctx, data.VotingParams)
|
||||||
k.setTallyingProcedure(ctx, data.TallyingProcedure)
|
k.setTallyParams(ctx, data.TallyParams)
|
||||||
|
for _, deposit := range data.Deposits {
|
||||||
|
k.setDeposit(ctx, deposit.ProposalID, deposit.Deposit.Depositer, deposit.Deposit)
|
||||||
|
}
|
||||||
|
for _, vote := range data.Votes {
|
||||||
|
k.setVote(ctx, vote.ProposalID, vote.Vote.Voter, vote.Vote)
|
||||||
|
}
|
||||||
|
for _, proposal := range data.Proposals {
|
||||||
|
k.SetProposal(ctx, proposal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis - output genesis parameters
|
// ExportGenesis - output genesis parameters
|
||||||
func WriteGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||||
startingProposalID, _ := k.getNewProposalID(ctx)
|
startingProposalID, _ := k.peekCurrentProposalID(ctx)
|
||||||
depositProcedure := k.GetDepositProcedure(ctx)
|
depositParams := k.GetDepositParams(ctx)
|
||||||
votingProcedure := k.GetVotingProcedure(ctx)
|
votingParams := k.GetVotingParams(ctx)
|
||||||
tallyingProcedure := k.GetTallyingProcedure(ctx)
|
tallyParams := k.GetTallyParams(ctx)
|
||||||
|
var deposits []DepositWithMetadata
|
||||||
|
var votes []VoteWithMetadata
|
||||||
|
proposals := k.GetProposalsFiltered(ctx, nil, nil, StatusNil, 0)
|
||||||
|
for _, proposal := range proposals {
|
||||||
|
proposalID := proposal.GetProposalID()
|
||||||
|
depositsIterator := k.GetDeposits(ctx, proposalID)
|
||||||
|
for ; depositsIterator.Valid(); depositsIterator.Next() {
|
||||||
|
var deposit Deposit
|
||||||
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
|
||||||
|
deposits = append(deposits, DepositWithMetadata{proposalID, deposit})
|
||||||
|
}
|
||||||
|
votesIterator := k.GetVotes(ctx, proposalID)
|
||||||
|
for ; votesIterator.Valid(); votesIterator.Next() {
|
||||||
|
var vote Vote
|
||||||
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
|
||||||
|
votes = append(votes, VoteWithMetadata{proposalID, vote})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
StartingProposalID: startingProposalID,
|
StartingProposalID: startingProposalID,
|
||||||
DepositProcedure: depositProcedure,
|
Deposits: deposits,
|
||||||
VotingProcedure: votingProcedure,
|
Votes: votes,
|
||||||
TallyingProcedure: tallyingProcedure,
|
Proposals: proposals,
|
||||||
|
DepositParams: depositParams,
|
||||||
|
VotingParams: votingParams,
|
||||||
|
TallyParams: tallyParams,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
|
||||||
return err.Result()
|
return err.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(proposal.GetProposalID())
|
proposalIDBytes := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal.GetProposalID())
|
||||||
|
|
||||||
resTags := sdk.NewTags(
|
resTags := sdk.NewTags(
|
||||||
tags.Action, tags.ActionSubmitProposal,
|
tags.Action, tags.ActionSubmitProposal,
|
||||||
|
@ -102,40 +102,35 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
|
|
||||||
resTags = sdk.NewTags()
|
resTags = sdk.NewTags()
|
||||||
|
|
||||||
// Delete proposals that haven't met minDeposit
|
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
for shouldPopInactiveProposalQueue(ctx, keeper) {
|
for ; inactiveIterator.Valid(); inactiveIterator.Next() {
|
||||||
inactiveProposal := keeper.InactiveProposalQueuePop(ctx)
|
var proposalID uint64
|
||||||
if inactiveProposal.GetStatus() != StatusDepositPeriod {
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
|
||||||
continue
|
inactiveProposal := keeper.GetProposal(ctx, proposalID)
|
||||||
}
|
keeper.DeleteProposal(ctx, proposalID)
|
||||||
|
keeper.DeleteDeposits(ctx, proposalID) // delete any associated deposits (burned)
|
||||||
|
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(inactiveProposal.GetProposalID())
|
|
||||||
keeper.DeleteProposal(ctx, inactiveProposal)
|
|
||||||
resTags = resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
|
resTags = resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
|
||||||
resTags = resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
resTags = resTags.AppendTag(tags.ProposalID, []byte(string(proposalID)))
|
||||||
|
|
||||||
logger.Info(
|
logger.Info(
|
||||||
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %v steak); deleted",
|
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted",
|
||||||
inactiveProposal.GetProposalID(),
|
inactiveProposal.GetProposalID(),
|
||||||
inactiveProposal.GetTitle(),
|
inactiveProposal.GetTitle(),
|
||||||
keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"),
|
keeper.GetDepositParams(ctx).MinDeposit,
|
||||||
inactiveProposal.GetTotalDeposit().AmountOf("steak"),
|
inactiveProposal.GetTotalDeposit(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
inactiveIterator.Close()
|
||||||
|
|
||||||
// Check if earliest Active Proposal ended voting period yet
|
activeIterator := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
for shouldPopActiveProposalQueue(ctx, keeper) {
|
for ; activeIterator.Valid(); activeIterator.Next() {
|
||||||
activeProposal := keeper.ActiveProposalQueuePop(ctx)
|
var proposalID uint64
|
||||||
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||||
proposalStartTime := activeProposal.GetVotingStartTime()
|
activeProposal := keeper.GetProposal(ctx, proposalID)
|
||||||
votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod
|
|
||||||
if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
passes, tallyResults := tally(ctx, keeper, activeProposal)
|
passes, tallyResults := tally(ctx, keeper, activeProposal)
|
||||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
|
|
||||||
var action []byte
|
var action []byte
|
||||||
if passes {
|
if passes {
|
||||||
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
|
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
|
||||||
|
@ -149,37 +144,15 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
activeProposal.SetTallyResult(tallyResults)
|
activeProposal.SetTallyResult(tallyResults)
|
||||||
keeper.SetProposal(ctx, activeProposal)
|
keeper.SetProposal(ctx, activeProposal)
|
||||||
|
|
||||||
|
keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.GetVotingEndTime(), activeProposal.GetProposalID())
|
||||||
|
|
||||||
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
|
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
|
||||||
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))
|
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))
|
||||||
|
|
||||||
resTags = resTags.AppendTag(tags.Action, action)
|
resTags = resTags.AppendTag(tags.Action, action)
|
||||||
resTags = resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
resTags = resTags.AppendTag(tags.ProposalID, []byte(string(proposalID)))
|
||||||
}
|
}
|
||||||
|
activeIterator.Close()
|
||||||
|
|
||||||
return resTags
|
return resTags
|
||||||
}
|
}
|
||||||
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
|
||||||
depositProcedure := keeper.GetDepositProcedure(ctx)
|
|
||||||
peekProposal := keeper.InactiveProposalQueuePeek(ctx)
|
|
||||||
|
|
||||||
if peekProposal == nil {
|
|
||||||
return false
|
|
||||||
} else if peekProposal.GetStatus() != StatusDepositPeriod {
|
|
||||||
return true
|
|
||||||
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
|
||||||
votingProcedure := keeper.GetVotingProcedure(ctx)
|
|
||||||
peekProposal := keeper.ActiveProposalQueuePeek(ctx)
|
|
||||||
|
|
||||||
if peekProposal == nil {
|
|
||||||
return false
|
|
||||||
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
231
x/gov/keeper.go
231
x/gov/keeper.go
|
@ -1,10 +1,14 @@
|
||||||
package gov
|
package gov
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
codec "github.com/cosmos/cosmos-sdk/codec"
|
codec "github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parameter store default namestore
|
// Parameter store default namestore
|
||||||
|
@ -14,17 +18,20 @@ const (
|
||||||
|
|
||||||
// Parameter store key
|
// Parameter store key
|
||||||
var (
|
var (
|
||||||
ParamStoreKeyDepositProcedure = []byte("depositprocedure")
|
ParamStoreKeyDepositParams = []byte("depositparams")
|
||||||
ParamStoreKeyVotingProcedure = []byte("votingprocedure")
|
ParamStoreKeyVotingParams = []byte("votingparams")
|
||||||
ParamStoreKeyTallyingProcedure = []byte("tallyingprocedure")
|
ParamStoreKeyTallyParams = []byte("tallyparams")
|
||||||
|
|
||||||
|
DepositedCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("govDepositedCoins")))
|
||||||
|
BurnedDepositCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins")))
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type declaration for parameters
|
// Type declaration for parameters
|
||||||
func ParamTypeTable() params.TypeTable {
|
func ParamTypeTable() params.TypeTable {
|
||||||
return params.NewTypeTable(
|
return params.NewTypeTable(
|
||||||
ParamStoreKeyDepositProcedure, DepositProcedure{},
|
ParamStoreKeyDepositParams, DepositParams{},
|
||||||
ParamStoreKeyVotingProcedure, VotingProcedure{},
|
ParamStoreKeyVotingParams, VotingParams{},
|
||||||
ParamStoreKeyTallyingProcedure, TallyingProcedure{},
|
ParamStoreKeyTallyParams, TallyParams{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,13 +99,17 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description
|
||||||
TotalDeposit: sdk.Coins{},
|
TotalDeposit: sdk.Coins{},
|
||||||
SubmitTime: ctx.BlockHeader().Time,
|
SubmitTime: ctx.BlockHeader().Time,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
|
||||||
|
proposal.SetDepositEndTime(proposal.GetSubmitTime().Add(depositPeriod))
|
||||||
|
|
||||||
keeper.SetProposal(ctx, proposal)
|
keeper.SetProposal(ctx, proposal)
|
||||||
keeper.InactiveProposalQueuePush(ctx, proposal)
|
keeper.InsertInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
|
||||||
return proposal
|
return proposal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Proposal from store by ProposalID
|
// Get Proposal from store by ProposalID
|
||||||
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID int64) Proposal {
|
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) Proposal {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyProposal(proposalID))
|
bz := store.Get(KeyProposal(proposalID))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
|
@ -119,13 +130,16 @@ func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.AccountKeeper.
|
// Implements sdk.AccountKeeper.
|
||||||
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposal Proposal) {
|
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
store.Delete(KeyProposal(proposal.GetProposalID()))
|
proposal := keeper.GetProposal(ctx, proposalID)
|
||||||
|
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
|
||||||
|
keeper.RemoveFromActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposalID)
|
||||||
|
store.Delete(KeyProposal(proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Proposal from store by ProposalID
|
// Get Proposal from store by ProposalID
|
||||||
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest int64) []Proposal {
|
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest uint64) []Proposal {
|
||||||
|
|
||||||
maxProposalID, err := keeper.peekCurrentProposalID(ctx)
|
maxProposalID, err := keeper.peekCurrentProposalID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -134,7 +148,7 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
|
||||||
|
|
||||||
matchingProposals := []Proposal{}
|
matchingProposals := []Proposal{}
|
||||||
|
|
||||||
if numLatest <= 0 {
|
if numLatest == 0 {
|
||||||
numLatest = maxProposalID
|
numLatest = maxProposalID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +183,7 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
|
||||||
return matchingProposals
|
return matchingProposals
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk.Error {
|
func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID uint64) sdk.Error {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyNextProposalID)
|
bz := store.Get(KeyNextProposalID)
|
||||||
if bz != nil {
|
if bz != nil {
|
||||||
|
@ -181,7 +195,7 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the last used proposal ID
|
// Get the last used proposal ID
|
||||||
func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
|
func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID uint64) {
|
||||||
proposalID, err := keeper.peekCurrentProposalID(ctx)
|
proposalID, err := keeper.peekCurrentProposalID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -191,11 +205,11 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the next available ProposalID and increments it
|
// Gets the next available ProposalID and increments it
|
||||||
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
|
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyNextProposalID)
|
bz := store.Get(KeyNextProposalID)
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
|
return 0, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
|
||||||
}
|
}
|
||||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
|
||||||
bz = keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID + 1)
|
bz = keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID + 1)
|
||||||
|
@ -204,11 +218,11 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peeks the next available ProposalID without incrementing it
|
// Peeks the next available ProposalID without incrementing it
|
||||||
func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
|
func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyNextProposalID)
|
bz := store.Get(KeyNextProposalID)
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
|
return 0, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
|
||||||
}
|
}
|
||||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
|
||||||
return proposalID, nil
|
return proposalID, nil
|
||||||
|
@ -216,58 +230,62 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e
|
||||||
|
|
||||||
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
||||||
proposal.SetVotingStartTime(ctx.BlockHeader().Time)
|
proposal.SetVotingStartTime(ctx.BlockHeader().Time)
|
||||||
|
votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
|
||||||
|
proposal.SetVotingEndTime(proposal.GetVotingStartTime().Add(votingPeriod))
|
||||||
proposal.SetStatus(StatusVotingPeriod)
|
proposal.SetStatus(StatusVotingPeriod)
|
||||||
keeper.SetProposal(ctx, proposal)
|
keeper.SetProposal(ctx, proposal)
|
||||||
keeper.ActiveProposalQueuePush(ctx, proposal)
|
|
||||||
|
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposal.GetProposalID())
|
||||||
|
keeper.InsertActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposal.GetProposalID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// Procedures
|
// Params
|
||||||
|
|
||||||
// Returns the current Deposit Procedure from the global param store
|
// Returns the current DepositParams from the global param store
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
|
func (keeper Keeper) GetDepositParams(ctx sdk.Context) DepositParams {
|
||||||
var depositProcedure DepositProcedure
|
var depositParams DepositParams
|
||||||
keeper.paramSpace.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
keeper.paramSpace.Get(ctx, ParamStoreKeyDepositParams, &depositParams)
|
||||||
return depositProcedure
|
return depositParams
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current Voting Procedure from the global param store
|
// Returns the current Voting Procedure from the global param store
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
|
func (keeper Keeper) GetVotingParams(ctx sdk.Context) VotingParams {
|
||||||
var votingProcedure VotingProcedure
|
var votingParams VotingParams
|
||||||
keeper.paramSpace.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
keeper.paramSpace.Get(ctx, ParamStoreKeyVotingParams, &votingParams)
|
||||||
return votingProcedure
|
return votingParams
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current Tallying Procedure from the global param store
|
// Returns the current Tallying Procedure from the global param store
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) GetTallyingProcedure(ctx sdk.Context) TallyingProcedure {
|
func (keeper Keeper) GetTallyParams(ctx sdk.Context) TallyParams {
|
||||||
var tallyingProcedure TallyingProcedure
|
var tallyParams TallyParams
|
||||||
keeper.paramSpace.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
keeper.paramSpace.Get(ctx, ParamStoreKeyTallyParams, &tallyParams)
|
||||||
return tallyingProcedure
|
return tallyParams
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) setDepositProcedure(ctx sdk.Context, depositProcedure DepositProcedure) {
|
func (keeper Keeper) setDepositParams(ctx sdk.Context, depositParams DepositParams) {
|
||||||
keeper.paramSpace.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
|
keeper.paramSpace.Set(ctx, ParamStoreKeyDepositParams, &depositParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) setVotingProcedure(ctx sdk.Context, votingProcedure VotingProcedure) {
|
func (keeper Keeper) setVotingParams(ctx sdk.Context, votingParams VotingParams) {
|
||||||
keeper.paramSpace.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
|
keeper.paramSpace.Set(ctx, ParamStoreKeyVotingParams, &votingParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (keeper Keeper) setTallyingProcedure(ctx sdk.Context, tallyingProcedure TallyingProcedure) {
|
func (keeper Keeper) setTallyParams(ctx sdk.Context, tallyParams TallyParams) {
|
||||||
keeper.paramSpace.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
|
keeper.paramSpace.Set(ctx, ParamStoreKeyTallyParams, &tallyParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// Votes
|
// Votes
|
||||||
|
|
||||||
// Adds a vote on a specific proposal
|
// Adds a vote on a specific proposal
|
||||||
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, option VoteOption) sdk.Error {
|
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option VoteOption) sdk.Error {
|
||||||
proposal := keeper.GetProposal(ctx, proposalID)
|
proposal := keeper.GetProposal(ctx, proposalID)
|
||||||
if proposal == nil {
|
if proposal == nil {
|
||||||
return ErrUnknownProposal(keeper.codespace, proposalID)
|
return ErrUnknownProposal(keeper.codespace, proposalID)
|
||||||
|
@ -291,7 +309,7 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the vote of a specific voter on a specific proposal
|
// Gets the vote of a specific voter on a specific proposal
|
||||||
func (keeper Keeper) GetVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress) (Vote, bool) {
|
func (keeper Keeper) GetVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) (Vote, bool) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyVote(proposalID, voterAddr))
|
bz := store.Get(KeyVote(proposalID, voterAddr))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
|
@ -302,19 +320,19 @@ func (keeper Keeper) GetVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac
|
||||||
return vote, true
|
return vote, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) setVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, vote Vote) {
|
func (keeper Keeper) setVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, vote Vote) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(vote)
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(vote)
|
||||||
store.Set(KeyVote(proposalID, voterAddr), bz)
|
store.Set(KeyVote(proposalID, voterAddr), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets all the votes on a specific proposal
|
// Gets all the votes on a specific proposal
|
||||||
func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID int64) sdk.Iterator {
|
func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID uint64) sdk.Iterator {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
return sdk.KVStorePrefixIterator(store, KeyVotesSubspace(proposalID))
|
return sdk.KVStorePrefixIterator(store, KeyVotesSubspace(proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress) {
|
func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
store.Delete(KeyVote(proposalID, voterAddr))
|
store.Delete(KeyVote(proposalID, voterAddr))
|
||||||
}
|
}
|
||||||
|
@ -323,7 +341,7 @@ func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID int64, voterAddr sdk
|
||||||
// Deposits
|
// Deposits
|
||||||
|
|
||||||
// Gets the deposit of a specific depositer on a specific proposal
|
// Gets the deposit of a specific depositer on a specific proposal
|
||||||
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress) (Deposit, bool) {
|
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress) (Deposit, bool) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyDeposit(proposalID, depositerAddr))
|
bz := store.Get(KeyDeposit(proposalID, depositerAddr))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
|
@ -334,7 +352,7 @@ func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID int64, depositerAddr
|
||||||
return deposit, true
|
return deposit, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, deposit Deposit) {
|
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, deposit Deposit) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
|
||||||
store.Set(KeyDeposit(proposalID, depositerAddr), bz)
|
store.Set(KeyDeposit(proposalID, depositerAddr), bz)
|
||||||
|
@ -342,7 +360,7 @@ func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr
|
||||||
|
|
||||||
// Adds or updates a deposit of a specific depositer on a specific proposal
|
// Adds or updates a deposit of a specific depositer on a specific proposal
|
||||||
// Activates voting period when appropriate
|
// Activates voting period when appropriate
|
||||||
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
|
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
|
||||||
// Checks to see if proposal exists
|
// Checks to see if proposal exists
|
||||||
proposal := keeper.GetProposal(ctx, proposalID)
|
proposal := keeper.GetProposal(ctx, proposalID)
|
||||||
if proposal == nil {
|
if proposal == nil {
|
||||||
|
@ -354,8 +372,8 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
|
||||||
return ErrAlreadyFinishedProposal(keeper.codespace, proposalID), false
|
return ErrAlreadyFinishedProposal(keeper.codespace, proposalID), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtract coins from depositer's account
|
// Send coins from depositer's account to DepositedCoinsAccAddr account
|
||||||
_, _, err := keeper.ck.SubtractCoins(ctx, depositerAddr, depositAmount)
|
_, err := keeper.ck.SendCoins(ctx, depositerAddr, DepositedCoinsAccAddr, depositAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, false
|
return err, false
|
||||||
}
|
}
|
||||||
|
@ -367,7 +385,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
|
||||||
// Check if deposit tipped proposal into voting period
|
// Check if deposit tipped proposal into voting period
|
||||||
// Active voting period if so
|
// Active voting period if so
|
||||||
activatedVotingPeriod := false
|
activatedVotingPeriod := false
|
||||||
if proposal.GetStatus() == StatusDepositPeriod && proposal.GetTotalDeposit().IsGTE(keeper.GetDepositProcedure(ctx).MinDeposit) {
|
if proposal.GetStatus() == StatusDepositPeriod && proposal.GetTotalDeposit().IsAllGTE(keeper.GetDepositParams(ctx).MinDeposit) {
|
||||||
keeper.activateVotingPeriod(ctx, proposal)
|
keeper.activateVotingPeriod(ctx, proposal)
|
||||||
activatedVotingPeriod = true
|
activatedVotingPeriod = true
|
||||||
}
|
}
|
||||||
|
@ -386,13 +404,13 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets all the deposits on a specific proposal
|
// Gets all the deposits on a specific proposal
|
||||||
func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID int64) sdk.Iterator {
|
func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) sdk.Iterator {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
return sdk.KVStorePrefixIterator(store, KeyDepositsSubspace(proposalID))
|
return sdk.KVStorePrefixIterator(store, KeyDepositsSubspace(proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns and deletes all the deposits on a specific proposal
|
// Returns and deletes all the deposits on a specific proposal
|
||||||
func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
|
func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID uint64) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||||
|
|
||||||
|
@ -400,7 +418,7 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
|
||||||
deposit := &Deposit{}
|
deposit := &Deposit{}
|
||||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
|
||||||
|
|
||||||
_, _, err := keeper.ck.AddCoins(ctx, deposit.Depositer, deposit.Amount)
|
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, deposit.Depositer, deposit.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should not happen")
|
panic("should not happen")
|
||||||
}
|
}
|
||||||
|
@ -412,11 +430,19 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deletes all the deposits on a specific proposal without refunding them
|
// Deletes all the deposits on a specific proposal without refunding them
|
||||||
func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID int64) {
|
func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID uint64) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||||
|
|
||||||
for ; depositsIterator.Valid(); depositsIterator.Next() {
|
for ; depositsIterator.Valid(); depositsIterator.Next() {
|
||||||
|
deposit := &Deposit{}
|
||||||
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
|
||||||
|
|
||||||
|
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, BurnedDepositCoinsAccAddr, deposit.Amount)
|
||||||
|
if err != nil {
|
||||||
|
panic("should not happen")
|
||||||
|
}
|
||||||
|
|
||||||
store.Delete(depositsIterator.Key())
|
store.Delete(depositsIterator.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,93 +452,40 @@ func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID int64) {
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// ProposalQueues
|
// ProposalQueues
|
||||||
|
|
||||||
func (keeper Keeper) getActiveProposalQueue(ctx sdk.Context) ProposalQueue {
|
// Returns an iterator for all the proposals in the Active Queue that expire by endTime
|
||||||
|
func (keeper Keeper) ActiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyActiveProposalQueue)
|
return store.Iterator(PrefixActiveProposalQueue, sdk.PrefixEndBytes(PrefixActiveProposalQueueTime(endTime)))
|
||||||
if bz == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var proposalQueue ProposalQueue
|
|
||||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
|
|
||||||
|
|
||||||
return proposalQueue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) setActiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
|
// Inserts a ProposalID into the active proposal queue at endTime
|
||||||
|
func (keeper Keeper) InsertActiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
|
||||||
store.Set(KeyActiveProposalQueue, bz)
|
store.Set(KeyActiveProposalQueueProposal(endTime, proposalID), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the Proposal at the front of the ProposalQueue
|
// removes a proposalID from the Active Proposal Queue
|
||||||
func (keeper Keeper) ActiveProposalQueuePeek(ctx sdk.Context) Proposal {
|
func (keeper Keeper) RemoveFromActiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
|
||||||
proposalQueue := keeper.getActiveProposalQueue(ctx)
|
|
||||||
if len(proposalQueue) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return keeper.GetProposal(ctx, proposalQueue[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove and return a Proposal from the front of the ProposalQueue
|
|
||||||
func (keeper Keeper) ActiveProposalQueuePop(ctx sdk.Context) Proposal {
|
|
||||||
proposalQueue := keeper.getActiveProposalQueue(ctx)
|
|
||||||
if len(proposalQueue) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
frontElement, proposalQueue := proposalQueue[0], proposalQueue[1:]
|
|
||||||
keeper.setActiveProposalQueue(ctx, proposalQueue)
|
|
||||||
return keeper.GetProposal(ctx, frontElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a proposalID to the back of the ProposalQueue
|
|
||||||
func (keeper Keeper) ActiveProposalQueuePush(ctx sdk.Context, proposal Proposal) {
|
|
||||||
proposalQueue := append(keeper.getActiveProposalQueue(ctx), proposal.GetProposalID())
|
|
||||||
keeper.setActiveProposalQueue(ctx, proposalQueue)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (keeper Keeper) getInactiveProposalQueue(ctx sdk.Context) ProposalQueue {
|
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := store.Get(KeyInactiveProposalQueue)
|
store.Delete(KeyActiveProposalQueueProposal(endTime, proposalID))
|
||||||
if bz == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var proposalQueue ProposalQueue
|
|
||||||
|
|
||||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
|
|
||||||
|
|
||||||
return proposalQueue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (keeper Keeper) setInactiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
|
// Returns an iterator for all the proposals in the Inactive Queue that expire by endTime
|
||||||
|
func (keeper Keeper) InactiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||||
store := ctx.KVStore(keeper.storeKey)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
|
return store.Iterator(PrefixInactiveProposalQueue, sdk.PrefixEndBytes(PrefixInactiveProposalQueueTime(endTime)))
|
||||||
store.Set(KeyInactiveProposalQueue, bz)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the Proposal at the front of the ProposalQueue
|
// Inserts a ProposalID into the inactive proposal queue at endTime
|
||||||
func (keeper Keeper) InactiveProposalQueuePeek(ctx sdk.Context) Proposal {
|
func (keeper Keeper) InsertInactiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
|
||||||
proposalQueue := keeper.getInactiveProposalQueue(ctx)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
if len(proposalQueue) == 0 {
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
|
||||||
return nil
|
store.Set(KeyInactiveProposalQueueProposal(endTime, proposalID), bz)
|
||||||
}
|
|
||||||
return keeper.GetProposal(ctx, proposalQueue[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove and return a Proposal from the front of the ProposalQueue
|
// removes a proposalID from the Inactive Proposal Queue
|
||||||
func (keeper Keeper) InactiveProposalQueuePop(ctx sdk.Context) Proposal {
|
func (keeper Keeper) RemoveFromInactiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
|
||||||
proposalQueue := keeper.getInactiveProposalQueue(ctx)
|
store := ctx.KVStore(keeper.storeKey)
|
||||||
if len(proposalQueue) == 0 {
|
store.Delete(KeyInactiveProposalQueueProposal(endTime, proposalID))
|
||||||
return nil
|
|
||||||
}
|
|
||||||
frontElement, proposalQueue := proposalQueue[0], proposalQueue[1:]
|
|
||||||
keeper.setInactiveProposalQueue(ctx, proposalQueue)
|
|
||||||
return keeper.GetProposal(ctx, frontElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a proposalID to the back of the ProposalQueue
|
|
||||||
func (keeper Keeper) InactiveProposalQueuePush(ctx sdk.Context, proposal Proposal) {
|
|
||||||
proposalQueue := append(keeper.getInactiveProposalQueue(ctx), proposal.GetProposalID())
|
|
||||||
keeper.setInactiveProposalQueue(ctx, proposalQueue)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package gov
|
package gov
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
@ -10,32 +12,68 @@ import (
|
||||||
|
|
||||||
// Key for getting a the next available proposalID from the store
|
// Key for getting a the next available proposalID from the store
|
||||||
var (
|
var (
|
||||||
KeyNextProposalID = []byte("newProposalID")
|
KeyDelimiter = []byte(":")
|
||||||
KeyActiveProposalQueue = []byte("activeProposalQueue")
|
|
||||||
KeyInactiveProposalQueue = []byte("inactiveProposalQueue")
|
KeyNextProposalID = []byte("newProposalID")
|
||||||
|
PrefixActiveProposalQueue = []byte("activeProposalQueue")
|
||||||
|
PrefixInactiveProposalQueue = []byte("inactiveProposalQueue")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Key for getting a specific proposal from the store
|
// Key for getting a specific proposal from the store
|
||||||
func KeyProposal(proposalID int64) []byte {
|
func KeyProposal(proposalID uint64) []byte {
|
||||||
return []byte(fmt.Sprintf("proposals:%d", proposalID))
|
return []byte(fmt.Sprintf("proposals:%d", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key for getting a specific deposit from the store
|
// Key for getting a specific deposit from the store
|
||||||
func KeyDeposit(proposalID int64, depositerAddr sdk.AccAddress) []byte {
|
func KeyDeposit(proposalID uint64, depositerAddr sdk.AccAddress) []byte {
|
||||||
return []byte(fmt.Sprintf("deposits:%d:%d", proposalID, depositerAddr))
|
return []byte(fmt.Sprintf("deposits:%d:%d", proposalID, depositerAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key for getting a specific vote from the store
|
// Key for getting a specific vote from the store
|
||||||
func KeyVote(proposalID int64, voterAddr sdk.AccAddress) []byte {
|
func KeyVote(proposalID uint64, voterAddr sdk.AccAddress) []byte {
|
||||||
return []byte(fmt.Sprintf("votes:%d:%d", proposalID, voterAddr))
|
return []byte(fmt.Sprintf("votes:%d:%d", proposalID, voterAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key for getting all deposits on a proposal from the store
|
// Key for getting all deposits on a proposal from the store
|
||||||
func KeyDepositsSubspace(proposalID int64) []byte {
|
func KeyDepositsSubspace(proposalID uint64) []byte {
|
||||||
return []byte(fmt.Sprintf("deposits:%d:", proposalID))
|
return []byte(fmt.Sprintf("deposits:%d:", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key for getting all votes on a proposal from the store
|
// Key for getting all votes on a proposal from the store
|
||||||
func KeyVotesSubspace(proposalID int64) []byte {
|
func KeyVotesSubspace(proposalID uint64) []byte {
|
||||||
return []byte(fmt.Sprintf("votes:%d:", proposalID))
|
return []byte(fmt.Sprintf("votes:%d:", proposalID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the key for a proposalID in the activeProposalQueue
|
||||||
|
func PrefixActiveProposalQueueTime(endTime time.Time) []byte {
|
||||||
|
return bytes.Join([][]byte{
|
||||||
|
PrefixActiveProposalQueue,
|
||||||
|
sdk.FormatTimeBytes(endTime),
|
||||||
|
}, KeyDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the key for a proposalID in the activeProposalQueue
|
||||||
|
func KeyActiveProposalQueueProposal(endTime time.Time, proposalID uint64) []byte {
|
||||||
|
return bytes.Join([][]byte{
|
||||||
|
PrefixActiveProposalQueue,
|
||||||
|
sdk.FormatTimeBytes(endTime),
|
||||||
|
sdk.Uint64ToBigEndian(proposalID),
|
||||||
|
}, KeyDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the key for a proposalID in the activeProposalQueue
|
||||||
|
func PrefixInactiveProposalQueueTime(endTime time.Time) []byte {
|
||||||
|
return bytes.Join([][]byte{
|
||||||
|
PrefixInactiveProposalQueue,
|
||||||
|
sdk.FormatTimeBytes(endTime),
|
||||||
|
}, KeyDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the key for a proposalID in the activeProposalQueue
|
||||||
|
func KeyInactiveProposalQueueProposal(endTime time.Time, proposalID uint64) []byte {
|
||||||
|
return bytes.Join([][]byte{
|
||||||
|
PrefixInactiveProposalQueue,
|
||||||
|
sdk.FormatTimeBytes(endTime),
|
||||||
|
sdk.Uint64ToBigEndian(proposalID),
|
||||||
|
}, KeyDelimiter)
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ func TestIncrementProposalNumber(t *testing.T) {
|
||||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
proposal6 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal6 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
|
|
||||||
require.Equal(t, int64(6), proposal6.GetProposalID())
|
require.Equal(t, uint64(6), proposal6.GetProposalID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestActivateVotingPeriod(t *testing.T) {
|
func TestActivateVotingPeriod(t *testing.T) {
|
||||||
|
@ -47,12 +47,17 @@ func TestActivateVotingPeriod(t *testing.T) {
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
|
|
||||||
require.True(t, proposal.GetVotingStartTime().Equal(time.Time{}))
|
require.True(t, proposal.GetVotingStartTime().Equal(time.Time{}))
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
|
||||||
|
|
||||||
keeper.activateVotingPeriod(ctx, proposal)
|
keeper.activateVotingPeriod(ctx, proposal)
|
||||||
|
|
||||||
require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||||
require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
|
|
||||||
|
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
|
||||||
|
require.True(t, activeIterator.Valid())
|
||||||
|
var proposalID uint64
|
||||||
|
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||||
|
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||||
|
activeIterator.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeposits(t *testing.T) {
|
func TestDeposits(t *testing.T) {
|
||||||
|
@ -79,7 +84,6 @@ func TestDeposits(t *testing.T) {
|
||||||
deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1])
|
deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1])
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{}))
|
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{}))
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
|
||||||
|
|
||||||
// Check first deposit
|
// Check first deposit
|
||||||
err, votingStarted := keeper.AddDeposit(ctx, proposalID, addrs[0], fourSteak)
|
err, votingStarted := keeper.AddDeposit(ctx, proposalID, addrs[0], fourSteak)
|
||||||
|
@ -116,8 +120,6 @@ func TestDeposits(t *testing.T) {
|
||||||
|
|
||||||
// Check that proposal moved to voting period
|
// Check that proposal moved to voting period
|
||||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||||
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
|
|
||||||
require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
|
|
||||||
|
|
||||||
// Test deposit iterator
|
// Test deposit iterator
|
||||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||||
|
@ -207,44 +209,21 @@ func TestProposalQueues(t *testing.T) {
|
||||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
mapp.InitChainer(ctx, abci.RequestInitChain{})
|
mapp.InitChainer(ctx, abci.RequestInitChain{})
|
||||||
|
|
||||||
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
|
|
||||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
|
||||||
|
|
||||||
// create test proposals
|
// create test proposals
|
||||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||||
proposal2 := keeper.NewTextProposal(ctx, "Test2", "description", ProposalTypeText)
|
|
||||||
proposal3 := keeper.NewTextProposal(ctx, "Test3", "description", ProposalTypeText)
|
|
||||||
proposal4 := keeper.NewTextProposal(ctx, "Test4", "description", ProposalTypeText)
|
|
||||||
|
|
||||||
// test pushing to inactive proposal queue
|
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, proposal.GetDepositEndTime())
|
||||||
keeper.InactiveProposalQueuePush(ctx, proposal)
|
require.True(t, inactiveIterator.Valid())
|
||||||
keeper.InactiveProposalQueuePush(ctx, proposal2)
|
var proposalID uint64
|
||||||
keeper.InactiveProposalQueuePush(ctx, proposal3)
|
keeper.cdc.UnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
|
||||||
keeper.InactiveProposalQueuePush(ctx, proposal4)
|
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||||
|
inactiveIterator.Close()
|
||||||
|
|
||||||
// test peeking and popping from inactive proposal queue
|
keeper.activateVotingPeriod(ctx, proposal)
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal2.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal2.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal3.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal3.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal4.GetProposalID())
|
|
||||||
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal4.GetProposalID())
|
|
||||||
|
|
||||||
// test pushing to active proposal queue
|
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
|
||||||
keeper.ActiveProposalQueuePush(ctx, proposal)
|
require.True(t, activeIterator.Valid())
|
||||||
keeper.ActiveProposalQueuePush(ctx, proposal2)
|
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||||
keeper.ActiveProposalQueuePush(ctx, proposal3)
|
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||||
keeper.ActiveProposalQueuePush(ctx, proposal4)
|
activeIterator.Close()
|
||||||
|
|
||||||
// test peeking and popping from active proposal queue
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal2.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal2.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal3.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal3.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal4.GetProposalID())
|
|
||||||
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal4.GetProposalID())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,12 +84,12 @@ func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress {
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// MsgDeposit
|
// MsgDeposit
|
||||||
type MsgDeposit struct {
|
type MsgDeposit struct {
|
||||||
ProposalID int64 `json:"proposal_id"` // ID of the proposal
|
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
|
||||||
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
|
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
|
||||||
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
|
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMsgDeposit(depositer sdk.AccAddress, proposalID int64, amount sdk.Coins) MsgDeposit {
|
func NewMsgDeposit(depositer sdk.AccAddress, proposalID uint64, amount sdk.Coins) MsgDeposit {
|
||||||
return MsgDeposit{
|
return MsgDeposit{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
Depositer: depositer,
|
Depositer: depositer,
|
||||||
|
@ -145,12 +145,12 @@ func (msg MsgDeposit) GetSigners() []sdk.AccAddress {
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// MsgVote
|
// MsgVote
|
||||||
type MsgVote struct {
|
type MsgVote struct {
|
||||||
ProposalID int64 `json:"proposal_id"` // ID of the proposal
|
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
|
||||||
Voter sdk.AccAddress `json:"voter"` // address of the voter
|
Voter sdk.AccAddress `json:"voter"` // address of the voter
|
||||||
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
|
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMsgVote(voter sdk.AccAddress, proposalID int64, option VoteOption) MsgVote {
|
func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption) MsgVote {
|
||||||
return MsgVote{
|
return MsgVote{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
Voter: voter,
|
Voter: voter,
|
||||||
|
|
|
@ -53,13 +53,12 @@ func TestMsgSubmitProposal(t *testing.T) {
|
||||||
func TestMsgDeposit(t *testing.T) {
|
func TestMsgDeposit(t *testing.T) {
|
||||||
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
proposalID int64
|
proposalID uint64
|
||||||
depositerAddr sdk.AccAddress
|
depositerAddr sdk.AccAddress
|
||||||
depositAmount sdk.Coins
|
depositAmount sdk.Coins
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{0, addrs[0], coinsPos, true},
|
{0, addrs[0], coinsPos, true},
|
||||||
{-1, addrs[0], coinsPos, false},
|
|
||||||
{1, sdk.AccAddress{}, coinsPos, false},
|
{1, sdk.AccAddress{}, coinsPos, false},
|
||||||
{1, addrs[0], coinsZero, true},
|
{1, addrs[0], coinsZero, true},
|
||||||
{1, addrs[0], coinsNeg, false},
|
{1, addrs[0], coinsNeg, false},
|
||||||
|
@ -80,13 +79,12 @@ func TestMsgDeposit(t *testing.T) {
|
||||||
func TestMsgVote(t *testing.T) {
|
func TestMsgVote(t *testing.T) {
|
||||||
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
proposalID int64
|
proposalID uint64
|
||||||
voterAddr sdk.AccAddress
|
voterAddr sdk.AccAddress
|
||||||
option VoteOption
|
option VoteOption
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{0, addrs[0], OptionYes, true},
|
{0, addrs[0], OptionYes, true},
|
||||||
{-1, addrs[0], OptionYes, false},
|
|
||||||
{0, sdk.AccAddress{}, OptionYes, false},
|
{0, sdk.AccAddress{}, OptionYes, false},
|
||||||
{0, addrs[0], OptionNo, true},
|
{0, addrs[0], OptionNo, true},
|
||||||
{0, addrs[0], OptionNoWithVeto, true},
|
{0, addrs[0], OptionNoWithVeto, true},
|
||||||
|
|
|
@ -7,19 +7,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Procedure around Deposits for governance
|
// Procedure around Deposits for governance
|
||||||
type DepositProcedure struct {
|
type DepositParams struct {
|
||||||
MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period.
|
MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period.
|
||||||
MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||||
}
|
}
|
||||||
|
|
||||||
// Procedure around Tallying votes in governance
|
// Procedure around Tallying votes in governance
|
||||||
type TallyingProcedure struct {
|
type TallyParams struct {
|
||||||
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||||
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||||
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
|
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Procedure around Voting in governance
|
// Procedure around Voting in governance
|
||||||
type VotingProcedure struct {
|
type VotingParams struct {
|
||||||
VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period.
|
VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period.
|
||||||
}
|
}
|
|
@ -13,8 +13,8 @@ import (
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Proposal interface
|
// Proposal interface
|
||||||
type Proposal interface {
|
type Proposal interface {
|
||||||
GetProposalID() int64
|
GetProposalID() uint64
|
||||||
SetProposalID(int64)
|
SetProposalID(uint64)
|
||||||
|
|
||||||
GetTitle() string
|
GetTitle() string
|
||||||
SetTitle(string)
|
SetTitle(string)
|
||||||
|
@ -34,11 +34,17 @@ type Proposal interface {
|
||||||
GetSubmitTime() time.Time
|
GetSubmitTime() time.Time
|
||||||
SetSubmitTime(time.Time)
|
SetSubmitTime(time.Time)
|
||||||
|
|
||||||
|
GetDepositEndTime() time.Time
|
||||||
|
SetDepositEndTime(time.Time)
|
||||||
|
|
||||||
GetTotalDeposit() sdk.Coins
|
GetTotalDeposit() sdk.Coins
|
||||||
SetTotalDeposit(sdk.Coins)
|
SetTotalDeposit(sdk.Coins)
|
||||||
|
|
||||||
GetVotingStartTime() time.Time
|
GetVotingStartTime() time.Time
|
||||||
SetVotingStartTime(time.Time)
|
SetVotingStartTime(time.Time)
|
||||||
|
|
||||||
|
GetVotingEndTime() time.Time
|
||||||
|
SetVotingEndTime(time.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if two proposals are equal
|
// checks if two proposals are equal
|
||||||
|
@ -50,8 +56,10 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
|
||||||
proposalA.GetStatus() == proposalB.GetStatus() &&
|
proposalA.GetStatus() == proposalB.GetStatus() &&
|
||||||
proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) &&
|
proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) &&
|
||||||
proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) &&
|
proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) &&
|
||||||
|
proposalA.GetDepositEndTime().Equal(proposalB.GetDepositEndTime()) &&
|
||||||
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
|
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
|
||||||
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) {
|
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) &&
|
||||||
|
proposalA.GetVotingEndTime().Equal(proposalB.GetVotingEndTime()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -60,7 +68,7 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Text Proposals
|
// Text Proposals
|
||||||
type TextProposal struct {
|
type TextProposal struct {
|
||||||
ProposalID int64 `json:"proposal_id"` // ID of the proposal
|
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
|
||||||
Title string `json:"title"` // Title of the proposal
|
Title string `json:"title"` // Title of the proposal
|
||||||
Description string `json:"description"` // Description of the proposal
|
Description string `json:"description"` // Description of the proposal
|
||||||
ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
||||||
|
@ -68,18 +76,20 @@ type TextProposal struct {
|
||||||
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
|
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
|
||||||
TallyResult TallyResult `json:"tally_result"` // Result of Tallys
|
TallyResult TallyResult `json:"tally_result"` // Result of Tallys
|
||||||
|
|
||||||
SubmitTime time.Time `json:"submit_time"` // Height of the block where TxGovSubmitProposal was included
|
SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included
|
||||||
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
|
DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met
|
||||||
|
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
|
||||||
|
|
||||||
VotingStartTime time.Time `json:"voting_start_time"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||||
|
VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Proposal Interface
|
// Implements Proposal Interface
|
||||||
var _ Proposal = (*TextProposal)(nil)
|
var _ Proposal = (*TextProposal)(nil)
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
func (tp TextProposal) GetProposalID() int64 { return tp.ProposalID }
|
func (tp TextProposal) GetProposalID() uint64 { return tp.ProposalID }
|
||||||
func (tp *TextProposal) SetProposalID(proposalID int64) { tp.ProposalID = proposalID }
|
func (tp *TextProposal) SetProposalID(proposalID uint64) { tp.ProposalID = proposalID }
|
||||||
func (tp TextProposal) GetTitle() string { return tp.Title }
|
func (tp TextProposal) GetTitle() string { return tp.Title }
|
||||||
func (tp *TextProposal) SetTitle(title string) { tp.Title = title }
|
func (tp *TextProposal) SetTitle(title string) { tp.Title = title }
|
||||||
func (tp TextProposal) GetDescription() string { return tp.Description }
|
func (tp TextProposal) GetDescription() string { return tp.Description }
|
||||||
|
@ -92,16 +102,24 @@ func (tp TextProposal) GetTallyResult() TallyResult { return tp.T
|
||||||
func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult }
|
func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult }
|
||||||
func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime }
|
func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime }
|
||||||
func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime }
|
func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime }
|
||||||
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
|
func (tp TextProposal) GetDepositEndTime() time.Time { return tp.DepositEndTime }
|
||||||
func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit }
|
func (tp *TextProposal) SetDepositEndTime(depositEndTime time.Time) {
|
||||||
func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime }
|
tp.DepositEndTime = depositEndTime
|
||||||
|
}
|
||||||
|
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
|
||||||
|
func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit }
|
||||||
|
func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime }
|
||||||
func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) {
|
func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) {
|
||||||
tp.VotingStartTime = votingStartTime
|
tp.VotingStartTime = votingStartTime
|
||||||
}
|
}
|
||||||
|
func (tp TextProposal) GetVotingEndTime() time.Time { return tp.VotingEndTime }
|
||||||
|
func (tp *TextProposal) SetVotingEndTime(votingEndTime time.Time) {
|
||||||
|
tp.VotingEndTime = votingEndTime
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// ProposalQueue
|
// ProposalQueue
|
||||||
type ProposalQueue []int64
|
type ProposalQueue []uint64
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// ProposalKind
|
// ProposalKind
|
||||||
|
|
|
@ -42,7 +42,7 @@ func NewQuerier(keeper Keeper) sdk.Querier {
|
||||||
|
|
||||||
// Params for query 'custom/gov/proposal'
|
// Params for query 'custom/gov/proposal'
|
||||||
type QueryProposalParams struct {
|
type QueryProposalParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
|
@ -67,7 +67,7 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
|
||||||
|
|
||||||
// Params for query 'custom/gov/deposit'
|
// Params for query 'custom/gov/deposit'
|
||||||
type QueryDepositParams struct {
|
type QueryDepositParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
Depositer sdk.AccAddress
|
Depositer sdk.AccAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
|
||||||
|
|
||||||
// Params for query 'custom/gov/vote'
|
// Params for query 'custom/gov/vote'
|
||||||
type QueryVoteParams struct {
|
type QueryVoteParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
Voter sdk.AccAddress
|
Voter sdk.AccAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Kee
|
||||||
|
|
||||||
// Params for query 'custom/gov/deposits'
|
// Params for query 'custom/gov/deposits'
|
||||||
type QueryDepositsParams struct {
|
type QueryDepositsParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
|
@ -139,7 +139,7 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
|
||||||
|
|
||||||
// Params for query 'custom/gov/votes'
|
// Params for query 'custom/gov/votes'
|
||||||
type QueryVotesParams struct {
|
type QueryVotesParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
|
@ -168,10 +168,10 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
|
||||||
|
|
||||||
// Params for query 'custom/gov/proposals'
|
// Params for query 'custom/gov/proposals'
|
||||||
type QueryProposalsParams struct {
|
type QueryProposalsParams struct {
|
||||||
Voter sdk.AccAddress
|
Voter sdk.AccAddress
|
||||||
Depositer sdk.AccAddress
|
Depositer sdk.AccAddress
|
||||||
ProposalStatus ProposalStatus
|
ProposalStatus ProposalStatus
|
||||||
NumLatestProposals int64
|
Limit uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
|
@ -182,7 +182,7 @@ func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
|
||||||
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.NumLatestProposals)
|
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.Limit)
|
||||||
|
|
||||||
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, proposals)
|
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, proposals)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
|
@ -193,19 +193,21 @@ func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
|
||||||
|
|
||||||
// Params for query 'custom/gov/tally'
|
// Params for query 'custom/gov/tally'
|
||||||
type QueryTallyParams struct {
|
type QueryTallyParams struct {
|
||||||
ProposalID int64
|
ProposalID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
|
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
|
||||||
// TODO: Dependant on #1914
|
// TODO: Dependant on #1914
|
||||||
|
|
||||||
var proposalID int64
|
var params QueryTallyParams
|
||||||
err2 := keeper.cdc.UnmarshalJSON(req.Data, proposalID)
|
err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proposalID := params.ProposalID
|
||||||
|
|
||||||
proposal := keeper.GetProposal(ctx, proposalID)
|
proposal := keeper.GetProposal(ctx, proposalID)
|
||||||
if proposal == nil {
|
if proposal == nil {
|
||||||
return nil, ErrUnknownProposal(DefaultCodespace, proposalID)
|
return nil, ErrUnknownProposal(DefaultCodespace, proposalID)
|
||||||
|
|
|
@ -50,7 +50,7 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
action, ok := simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
|
action, ok := simulateHandleMsgSubmitProposal(msg, handler, ctx, event)
|
||||||
// don't schedule votes if proposal failed
|
// don't schedule votes if proposal failed
|
||||||
if !ok {
|
if !ok {
|
||||||
return action, nil, nil
|
return action, nil, nil
|
||||||
|
@ -64,11 +64,11 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
|
||||||
whoVotes := r.Perm(len(accs))
|
whoVotes := r.Perm(len(accs))
|
||||||
// didntVote := whoVotes[numVotes:]
|
// didntVote := whoVotes[numVotes:]
|
||||||
whoVotes = whoVotes[:numVotes]
|
whoVotes = whoVotes[:numVotes]
|
||||||
votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod
|
votingPeriod := k.GetVotingParams(ctx).VotingPeriod
|
||||||
fops := make([]simulation.FutureOperation, numVotes+1)
|
fops := make([]simulation.FutureOperation, numVotes+1)
|
||||||
for i := 0; i < numVotes; i++ {
|
for i := 0; i < numVotes; i++ {
|
||||||
whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second)
|
whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second)
|
||||||
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, accs[whoVotes[i]], proposalID)}
|
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, accs[whoVotes[i]], proposalID)}
|
||||||
}
|
}
|
||||||
// 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant)
|
// 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant)
|
||||||
// TODO: Find a way to check if a validator was slashed other than just checking their balance a block
|
// TODO: Find a way to check if a validator was slashed other than just checking their balance a block
|
||||||
|
@ -80,7 +80,7 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
|
||||||
|
|
||||||
// SimulateMsgSubmitProposal simulates a msg Submit Proposal
|
// SimulateMsgSubmitProposal simulates a msg Submit Proposal
|
||||||
// Note: Currently doesn't ensure that the proposal txt is in JSON form
|
// Note: Currently doesn't ensure that the proposal txt is in JSON form
|
||||||
func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
func SimulateMsgSubmitProposal(k gov.Keeper) simulation.Operation {
|
||||||
handler := gov.NewHandler(k)
|
handler := gov.NewHandler(k)
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
|
||||||
sender := simulation.RandomAcc(r, accs)
|
sender := simulation.RandomAcc(r, accs)
|
||||||
|
@ -88,22 +88,14 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operati
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
action, _ = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
|
action, _ = simulateHandleMsgSubmitProposal(msg, handler, ctx, event)
|
||||||
return action, nil, nil
|
return action, nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper, handler sdk.Handler, ctx sdk.Context, event func(string)) (action string, ok bool) {
|
func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, handler sdk.Handler, ctx sdk.Context, event func(string)) (action string, ok bool) {
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, _ = ctx.CacheContext()
|
||||||
result := handler(ctx, msg)
|
handler(ctx, msg)
|
||||||
ok = result.IsOK()
|
|
||||||
if ok {
|
|
||||||
// Update pool to keep invariants
|
|
||||||
pool := sk.GetPool(ctx)
|
|
||||||
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom)))
|
|
||||||
sk.SetPool(ctx, pool)
|
|
||||||
write()
|
|
||||||
}
|
|
||||||
event(fmt.Sprintf("gov/MsgSubmitProposal/%v", ok))
|
event(fmt.Sprintf("gov/MsgSubmitProposal/%v", ok))
|
||||||
action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", ok, msg.GetSignBytes())
|
action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", ok, msg.GetSignBytes())
|
||||||
return
|
return
|
||||||
|
@ -125,7 +117,7 @@ func simulationCreateMsgSubmitProposal(r *rand.Rand, sender simulation.Account)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimulateMsgDeposit
|
// SimulateMsgDeposit
|
||||||
func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
func SimulateMsgDeposit(k gov.Keeper) simulation.Operation {
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||||
acc := simulation.RandomAcc(r, accs)
|
acc := simulation.RandomAcc(r, accs)
|
||||||
proposalID, ok := randomProposalID(r, k, ctx)
|
proposalID, ok := randomProposalID(r, k, ctx)
|
||||||
|
@ -137,15 +129,8 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
||||||
if msg.ValidateBasic() != nil {
|
if msg.ValidateBasic() != nil {
|
||||||
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||||
}
|
}
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, _ = ctx.CacheContext()
|
||||||
result := gov.NewHandler(k)(ctx, msg)
|
result := gov.NewHandler(k)(ctx, msg)
|
||||||
if result.IsOK() {
|
|
||||||
// Update pool to keep invariants
|
|
||||||
pool := sk.GetPool(ctx)
|
|
||||||
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom)))
|
|
||||||
sk.SetPool(ctx, pool)
|
|
||||||
write()
|
|
||||||
}
|
|
||||||
event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK()))
|
event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK()))
|
||||||
action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
||||||
return action, nil, nil
|
return action, nil, nil
|
||||||
|
@ -154,12 +139,12 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
||||||
|
|
||||||
// SimulateMsgVote
|
// SimulateMsgVote
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
func SimulateMsgVote(k gov.Keeper) simulation.Operation {
|
||||||
return operationSimulateMsgVote(k, sk, simulation.Account{}, -1)
|
return operationSimulateMsgVote(k, simulation.Account{}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, acc simulation.Account, proposalID int64) simulation.Operation {
|
func operationSimulateMsgVote(k gov.Keeper, acc simulation.Account, proposalID uint64) simulation.Operation {
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||||
if acc.Equals(simulation.Account{}) {
|
if acc.Equals(simulation.Account{}) {
|
||||||
acc = simulation.RandomAcc(r, accs)
|
acc = simulation.RandomAcc(r, accs)
|
||||||
|
@ -200,12 +185,12 @@ func randomDeposit(r *rand.Rand) sdk.Coins {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a random proposal ID
|
// Pick a random proposal ID
|
||||||
func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID int64, ok bool) {
|
func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID uint64, ok bool) {
|
||||||
lastProposalID := k.GetLastProposalID(ctx)
|
lastProposalID := k.GetLastProposalID(ctx)
|
||||||
if lastProposalID < 1 {
|
if lastProposalID < 1 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
proposalID = int64(r.Intn(int(lastProposalID)))
|
proposalID = uint64(r.Intn(int(lastProposalID)))
|
||||||
return proposalID, true
|
return proposalID, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,9 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.WeightedOperation{
|
[]simulation.WeightedOperation{
|
||||||
{2, SimulateMsgSubmitProposal(govKeeper, stakeKeeper)},
|
{2, SimulateMsgSubmitProposal(govKeeper)},
|
||||||
{3, SimulateMsgDeposit(govKeeper, stakeKeeper)},
|
{3, SimulateMsgDeposit(govKeeper)},
|
||||||
{20, SimulateMsgVote(govKeeper, stakeKeeper)},
|
{20, SimulateMsgVote(govKeeper)},
|
||||||
}, []simulation.RandSetup{
|
}, []simulation.RandSetup{
|
||||||
setup,
|
setup,
|
||||||
}, []simulation.Invariant{
|
}, []simulation.Invariant{
|
||||||
|
@ -75,7 +75,7 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.WeightedOperation{
|
[]simulation.WeightedOperation{
|
||||||
{10, SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper)},
|
{10, SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper)},
|
||||||
{5, SimulateMsgDeposit(govKeeper, stakeKeeper)},
|
{5, SimulateMsgDeposit(govKeeper)},
|
||||||
}, []simulation.RandSetup{
|
}, []simulation.RandSetup{
|
||||||
setup,
|
setup,
|
||||||
}, []simulation.Invariant{
|
}, []simulation.Invariant{
|
||||||
|
|
|
@ -84,7 +84,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
|
||||||
totalVotingPower = totalVotingPower.Add(votingPower)
|
totalVotingPower = totalVotingPower.Add(votingPower)
|
||||||
}
|
}
|
||||||
|
|
||||||
tallyingProcedure := keeper.GetTallyingProcedure(ctx)
|
tallyParams := keeper.GetTallyParams(ctx)
|
||||||
|
|
||||||
tallyResults = TallyResult{
|
tallyResults = TallyResult{
|
||||||
Yes: results[OptionYes],
|
Yes: results[OptionYes],
|
||||||
|
@ -98,11 +98,11 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
|
||||||
return false, tallyResults
|
return false, tallyResults
|
||||||
}
|
}
|
||||||
// If more than 1/3 of voters veto, proposal fails
|
// If more than 1/3 of voters veto, proposal fails
|
||||||
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyingProcedure.Veto) {
|
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyParams.Veto) {
|
||||||
return false, tallyResults
|
return false, tallyResults
|
||||||
}
|
}
|
||||||
// If more than 1/2 of non-abstaining voters vote Yes, proposal passes
|
// If more than 1/2 of non-abstaining voters vote Yes, proposal passes
|
||||||
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyingProcedure.Threshold) {
|
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyParams.Threshold) {
|
||||||
return true, tallyResults
|
return true, tallyResults
|
||||||
}
|
}
|
||||||
// If more than 1/2 of non-abstaining voters vote No, proposal fails
|
// If more than 1/2 of non-abstaining voters vote No, proposal fails
|
||||||
|
|
|
@ -31,9 +31,9 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
|
||||||
keeper.SetParams(ctx, data.Params)
|
keeper.SetParams(ctx, data.Params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis returns a GenesisState for a given context and keeper. The
|
// ExportGenesis returns a GenesisState for a given context and keeper. The
|
||||||
// GenesisState will contain the pool, and validator/delegator distribution info's
|
// GenesisState will contain the pool, and validator/delegator distribution info's
|
||||||
func WriteGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
|
func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
|
||||||
|
|
||||||
minter := keeper.GetMinter(ctx)
|
minter := keeper.GetMinter(ctx)
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
|
|
|
@ -7,13 +7,25 @@ import (
|
||||||
|
|
||||||
// GenesisState - all slashing state that must be provided at genesis
|
// GenesisState - all slashing state that must be provided at genesis
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
Params Params
|
Params Params
|
||||||
|
SigningInfos map[string]ValidatorSigningInfo
|
||||||
|
MissedBlocks map[string][]MissedBlock
|
||||||
|
SlashingPeriods []ValidatorSlashingPeriod
|
||||||
|
}
|
||||||
|
|
||||||
|
// MissedBlock
|
||||||
|
type MissedBlock struct {
|
||||||
|
Index int64 `json:"index"`
|
||||||
|
Missed bool `json:"missed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HubDefaultGenesisState - default GenesisState used by Cosmos Hub
|
// HubDefaultGenesisState - default GenesisState used by Cosmos Hub
|
||||||
func DefaultGenesisState() GenesisState {
|
func DefaultGenesisState() GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
Params: DefaultParams(),
|
Params: DefaultParams(),
|
||||||
|
SigningInfos: make(map[string]ValidatorSigningInfo),
|
||||||
|
MissedBlocks: make(map[string][]MissedBlock),
|
||||||
|
SlashingPeriods: []ValidatorSlashingPeriod{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,5 +36,64 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState, sdata types.
|
||||||
keeper.addPubkey(ctx, validator.GetConsPubKey())
|
keeper.addPubkey(ctx, validator.GetConsPubKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for addr, info := range data.SigningInfos {
|
||||||
|
address, err := sdk.ConsAddressFromBech32(addr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
keeper.setValidatorSigningInfo(ctx, address, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
for addr, array := range data.MissedBlocks {
|
||||||
|
address, err := sdk.ConsAddressFromBech32(addr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, missed := range array {
|
||||||
|
keeper.setValidatorMissedBlockBitArray(ctx, address, missed.Index, missed.Missed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, slashingPeriod := range data.SlashingPeriods {
|
||||||
|
keeper.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
|
||||||
|
}
|
||||||
|
|
||||||
keeper.paramspace.SetParamSet(ctx, &data.Params)
|
keeper.paramspace.SetParamSet(ctx, &data.Params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExportGenesis writes the current store values
|
||||||
|
// to a genesis file, which can be imported again
|
||||||
|
// with InitGenesis
|
||||||
|
func ExportGenesis(ctx sdk.Context, keeper Keeper) (data GenesisState) {
|
||||||
|
var params Params
|
||||||
|
keeper.paramspace.GetParamSet(ctx, ¶ms)
|
||||||
|
|
||||||
|
signingInfos := make(map[string]ValidatorSigningInfo)
|
||||||
|
missedBlocks := make(map[string][]MissedBlock)
|
||||||
|
keeper.iterateValidatorSigningInfos(ctx, func(address sdk.ConsAddress, info ValidatorSigningInfo) (stop bool) {
|
||||||
|
bechAddr := address.String()
|
||||||
|
signingInfos[bechAddr] = info
|
||||||
|
array := []MissedBlock{}
|
||||||
|
|
||||||
|
keeper.iterateValidatorMissedBlockBitArray(ctx, address, func(index int64, missed bool) (stop bool) {
|
||||||
|
array = append(array, MissedBlock{index, missed})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
missedBlocks[bechAddr] = array
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
slashingPeriods := []ValidatorSlashingPeriod{}
|
||||||
|
keeper.iterateValidatorSlashingPeriods(ctx, func(slashingPeriod ValidatorSlashingPeriod) (stop bool) {
|
||||||
|
slashingPeriods = append(slashingPeriods, slashingPeriod)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
return GenesisState{
|
||||||
|
Params: params,
|
||||||
|
SigningInfos: signingInfos,
|
||||||
|
MissedBlocks: missedBlocks,
|
||||||
|
SlashingPeriods: slashingPeriods,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package slashing
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,6 +38,17 @@ func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddre
|
||||||
k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
|
k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When a validator is created, add the address-pubkey relation.
|
||||||
|
func (k Keeper) onValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
|
validator := k.validatorSet.Validator(ctx, valAddr)
|
||||||
|
k.addPubkey(ctx, validator.GetConsPubKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a validator is removed, delete the address-pubkey relation.
|
||||||
|
func (k Keeper) onValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
|
k.deleteAddrPubkeyRelation(ctx, crypto.Address(address))
|
||||||
|
}
|
||||||
|
|
||||||
//_________________________________________________________________________________________
|
//_________________________________________________________________________________________
|
||||||
|
|
||||||
// Wrapper struct
|
// Wrapper struct
|
||||||
|
@ -60,12 +73,20 @@ func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddre
|
||||||
h.k.onValidatorBeginUnbonding(ctx, consAddr, valAddr)
|
h.k.onValidatorBeginUnbonding(ctx, consAddr, valAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements sdk.ValidatorHooks
|
||||||
|
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) {
|
||||||
|
h.k.onValidatorRemoved(ctx, consAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements sdk.ValidatorHooks
|
||||||
|
func (h Hooks) OnValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
|
h.k.onValidatorCreated(ctx, valAddr)
|
||||||
|
}
|
||||||
|
|
||||||
// nolint - unused hooks
|
// nolint - unused hooks
|
||||||
func (h Hooks) OnValidatorPowerDidChange(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
func (h Hooks) OnValidatorPowerDidChange(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
||||||
}
|
}
|
||||||
func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {}
|
|
||||||
func (h Hooks) OnValidatorModified(_ sdk.Context, _ sdk.ValAddress) {}
|
func (h Hooks) OnValidatorModified(_ sdk.Context, _ sdk.ValAddress) {}
|
||||||
func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {}
|
|
||||||
func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
|
|
|
@ -4,13 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
stake "github.com/cosmos/cosmos-sdk/x/stake/types"
|
stake "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -174,19 +171,6 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
|
||||||
k.setValidatorSigningInfo(ctx, consAddr, signInfo)
|
k.setValidatorSigningInfo(ctx, consAddr, signInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddValidators adds the validators to the keepers validator addr to pubkey mapping.
|
|
||||||
func (k Keeper) AddValidators(ctx sdk.Context, vals []abci.ValidatorUpdate) {
|
|
||||||
for i := 0; i < len(vals); i++ {
|
|
||||||
val := vals[i]
|
|
||||||
pubkey, err := tmtypes.PB2TM.PubKey(val.PubKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
k.addPubkey(ctx, pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make a method to remove the pubkey from the map when a validator is unbonded.
|
|
||||||
func (k Keeper) addPubkey(ctx sdk.Context, pubkey crypto.PubKey) {
|
func (k Keeper) addPubkey(ctx sdk.Context, pubkey crypto.PubKey) {
|
||||||
addr := pubkey.Address()
|
addr := pubkey.Address()
|
||||||
k.setAddrPubkeyRelation(ctx, addr, pubkey)
|
k.setAddrPubkeyRelation(ctx, addr, pubkey)
|
||||||
|
|
|
@ -34,8 +34,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||||
operatorAddr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
operatorAddr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, val, amt))
|
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, val, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, operatorAddr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, operatorAddr).GetPower()))
|
||||||
|
|
||||||
|
@ -75,9 +74,8 @@ func TestSlashingPeriodCap(t *testing.T) {
|
||||||
valConsPubKey, valConsAddr := pks[0], pks[0].Address()
|
valConsPubKey, valConsAddr := pks[0], pks[0].Address()
|
||||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, valConsPubKey, amt))
|
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, valConsPubKey, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, operatorAddr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, operatorAddr).GetPower()))
|
||||||
|
|
||||||
|
@ -141,8 +139,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
slh := NewHandler(keeper)
|
slh := NewHandler(keeper)
|
||||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
// will exist since the validator has been bonded
|
// will exist since the validator has been bonded
|
||||||
|
@ -298,8 +295,7 @@ func TestHandleNewValidator(t *testing.T) {
|
||||||
// Validator created
|
// Validator created
|
||||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
|
got := sh(ctx, NewTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
|
||||||
require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower())
|
||||||
|
|
||||||
|
@ -333,8 +329,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||||
sh := stake.NewHandler(sk)
|
sh := stake.NewHandler(sk)
|
||||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
|
|
||||||
// 1000 first blocks OK
|
// 1000 first blocks OK
|
||||||
height := int64(0)
|
height := int64(0)
|
||||||
|
@ -386,8 +381,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||||
sh := stake.NewHandler(sk)
|
sh := stake.NewHandler(sk)
|
||||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
|
|
||||||
// 100 first blocks OK
|
// 100 first blocks OK
|
||||||
height := int64(0)
|
height := int64(0)
|
||||||
|
@ -400,9 +394,8 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||||
newAmt := int64(101)
|
newAmt := int64(101)
|
||||||
got = sh(ctx, NewTestMsgCreateValidator(addrs[1], pks[1], sdk.NewInt(newAmt)))
|
got = sh(ctx, NewTestMsgCreateValidator(addrs[1], pks[1], sdk.NewInt(newAmt)))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates = stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
require.Equal(t, 2, len(validatorUpdates))
|
require.Equal(t, 2, len(validatorUpdates))
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
validator, _ := sk.GetValidator(ctx, addr)
|
validator, _ := sk.GetValidator(ctx, addr)
|
||||||
require.Equal(t, sdk.Unbonding, validator.Status)
|
require.Equal(t, sdk.Unbonding, validator.Status)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,15 @@ func GetValidatorSigningInfoKey(v sdk.ConsAddress) []byte {
|
||||||
return append(ValidatorSigningInfoKey, v.Bytes()...)
|
return append(ValidatorSigningInfoKey, v.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract the address from a validator signing info key
|
||||||
|
func GetValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) {
|
||||||
|
addr := key[1:]
|
||||||
|
if len(addr) != sdk.AddrLen {
|
||||||
|
panic("unexpected key length")
|
||||||
|
}
|
||||||
|
return sdk.ConsAddress(addr)
|
||||||
|
}
|
||||||
|
|
||||||
// stored by *Tendermint* address (not operator address)
|
// stored by *Tendermint* address (not operator address)
|
||||||
func GetValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte {
|
func GetValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte {
|
||||||
return append(ValidatorMissedBlockBitArrayKey, v.Bytes()...)
|
return append(ValidatorMissedBlockBitArrayKey, v.Bytes()...)
|
||||||
|
|
|
@ -20,6 +20,21 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stored by *validator* address (not operator address)
|
||||||
|
func (k Keeper) iterateValidatorSigningInfos(ctx sdk.Context, handler func(address sdk.ConsAddress, info ValidatorSigningInfo) (stop bool)) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
iter := sdk.KVStorePrefixIterator(store, ValidatorSigningInfoKey)
|
||||||
|
defer iter.Close()
|
||||||
|
for ; iter.Valid(); iter.Next() {
|
||||||
|
address := GetValidatorSigningInfoAddress(iter.Key())
|
||||||
|
var info ValidatorSigningInfo
|
||||||
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(iter.Value(), &info)
|
||||||
|
if handler(address, info) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stored by *validator* address (not operator address)
|
// Stored by *validator* address (not operator address)
|
||||||
func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) {
|
func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
@ -40,6 +55,24 @@ func (k Keeper) getValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.Con
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stored by *validator* address (not operator address)
|
||||||
|
func (k Keeper) iterateValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, handler func(index int64, missed bool) (stop bool)) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
index := int64(0)
|
||||||
|
// Array may be sparse
|
||||||
|
for ; index < k.SignedBlocksWindow(ctx); index++ {
|
||||||
|
var missed bool
|
||||||
|
bz := store.Get(GetValidatorMissedBlockBitArrayKey(address, index))
|
||||||
|
if bz == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &missed)
|
||||||
|
if handler(index, missed) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stored by *validator* address (not operator address)
|
// Stored by *validator* address (not operator address)
|
||||||
func (k Keeper) setValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, missed bool) {
|
func (k Keeper) setValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, missed bool) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
|
@ -51,6 +51,21 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate over all slashing periods in the store, calling on each
|
||||||
|
// decode slashing period a provided handler function
|
||||||
|
// Stop if the provided handler function returns true
|
||||||
|
func (k Keeper) iterateValidatorSlashingPeriods(ctx sdk.Context, handler func(slashingPeriod ValidatorSlashingPeriod) (stop bool)) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
iter := sdk.KVStorePrefixIterator(store, ValidatorSlashingPeriodKey)
|
||||||
|
defer iter.Close()
|
||||||
|
for ; iter.Valid(); iter.Next() {
|
||||||
|
slashingPeriod := k.unmarshalSlashingPeriodKeyValue(iter.Key(), iter.Value())
|
||||||
|
if handler(slashingPeriod) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stored by validator Tendermint address (not operator address)
|
// Stored by validator Tendermint address (not operator address)
|
||||||
// This function sets a validator slashing period for a particular validator,
|
// This function sets a validator slashing period for a particular validator,
|
||||||
// start height, end height, and current slashed-so-far total, or updates
|
// start height, end height, and current slashed-so-far total, or updates
|
||||||
|
|
|
@ -91,7 +91,7 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s
|
||||||
sk.SetHooks(keeper.Hooks())
|
sk.SetHooks(keeper.Hooks())
|
||||||
|
|
||||||
require.NotPanics(t, func() {
|
require.NotPanics(t, func() {
|
||||||
InitGenesis(ctx, keeper, GenesisState{defaults}, genesis)
|
InitGenesis(ctx, keeper, GenesisState{defaults, nil, nil, nil}, genesis)
|
||||||
})
|
})
|
||||||
|
|
||||||
return ctx, ck, sk, paramstore, keeper
|
return ctx, ck, sk, paramstore, keeper
|
||||||
|
|
|
@ -19,8 +19,7 @@ func TestBeginBlocker(t *testing.T) {
|
||||||
// bond the validator
|
// bond the validator
|
||||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, pk, amt))
|
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, pk, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
|
||||||
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, sdk.AccAddress(addr)), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@ package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitGenesis sets the pool and parameters for the provided keeper and
|
// InitGenesis sets the pool and parameters for the provided keeper and
|
||||||
|
@ -26,22 +26,33 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
|
||||||
|
|
||||||
keeper.SetPool(ctx, data.Pool)
|
keeper.SetPool(ctx, data.Pool)
|
||||||
keeper.SetParams(ctx, data.Params)
|
keeper.SetParams(ctx, data.Params)
|
||||||
|
keeper.SetIntraTxCounter(ctx, data.IntraTxCounter)
|
||||||
|
keeper.SetLastTotalPower(ctx, data.LastTotalPower)
|
||||||
|
|
||||||
|
// We only need to set this if we're starting from a list of validators, not a state export
|
||||||
|
setBondIntraTxCounter := true
|
||||||
|
for _, validator := range data.Validators {
|
||||||
|
if validator.BondIntraTxCounter != 0 {
|
||||||
|
setBondIntraTxCounter = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i, validator := range data.Validators {
|
for i, validator := range data.Validators {
|
||||||
validator.BondIntraTxCounter = int16(i) // set the intra-tx counter to the order the validators are presented
|
// set the intra-tx counter to the order the validators are presented, if necessary
|
||||||
|
if setBondIntraTxCounter {
|
||||||
|
validator.BondIntraTxCounter = int16(i)
|
||||||
|
}
|
||||||
keeper.SetValidator(ctx, validator)
|
keeper.SetValidator(ctx, validator)
|
||||||
|
|
||||||
if validator.Tokens.IsZero() {
|
|
||||||
return res, errors.Errorf("genesis validator cannot have zero pool shares, validator: %v", validator)
|
|
||||||
}
|
|
||||||
if validator.DelegatorShares.IsZero() {
|
|
||||||
return res, errors.Errorf("genesis validator cannot have zero delegator shares, validator: %v", validator)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manually set indices for the first time
|
// Manually set indices for the first time
|
||||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||||
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
||||||
keeper.OnValidatorCreated(ctx, validator.OperatorAddr)
|
keeper.OnValidatorCreated(ctx, validator.OperatorAddr)
|
||||||
|
|
||||||
|
// Set timeslice if necessary
|
||||||
|
if validator.Status == sdk.Unbonding {
|
||||||
|
keeper.InsertValidatorQueue(ctx, validator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, delegation := range data.Bonds {
|
for _, delegation := range data.Bonds {
|
||||||
|
@ -49,24 +60,56 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
|
||||||
keeper.OnDelegationCreated(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
|
keeper.OnDelegationCreated(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(data.UnbondingDelegations[:], func(i, j int) bool {
|
||||||
|
return data.UnbondingDelegations[i].CreationHeight < data.UnbondingDelegations[j].CreationHeight
|
||||||
|
})
|
||||||
|
for _, ubd := range data.UnbondingDelegations {
|
||||||
|
keeper.SetUnbondingDelegation(ctx, ubd)
|
||||||
|
keeper.InsertUnbondingQueue(ctx, ubd)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(data.Redelegations[:], func(i, j int) bool {
|
||||||
|
return data.Redelegations[i].CreationHeight < data.Redelegations[j].CreationHeight
|
||||||
|
})
|
||||||
|
for _, red := range data.Redelegations {
|
||||||
|
keeper.SetRedelegation(ctx, red)
|
||||||
|
keeper.InsertRedelegationQueue(ctx, red)
|
||||||
|
}
|
||||||
|
|
||||||
res = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
res = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteGenesis returns a GenesisState for a given context and keeper. The
|
// ExportGenesis returns a GenesisState for a given context and keeper. The
|
||||||
// GenesisState will contain the pool, params, validators, and bonds found in
|
// GenesisState will contain the pool, params, validators, and bonds found in
|
||||||
// the keeper.
|
// the keeper.
|
||||||
func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
|
intraTxCounter := keeper.GetIntraTxCounter(ctx)
|
||||||
|
lastTotalPower := keeper.GetLastTotalPower(ctx)
|
||||||
validators := keeper.GetAllValidators(ctx)
|
validators := keeper.GetAllValidators(ctx)
|
||||||
bonds := keeper.GetAllDelegations(ctx)
|
bonds := keeper.GetAllDelegations(ctx)
|
||||||
|
var unbondingDelegations []types.UnbondingDelegation
|
||||||
|
keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
|
||||||
|
unbondingDelegations = append(unbondingDelegations, ubd)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
var redelegations []types.Redelegation
|
||||||
|
keeper.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
|
||||||
|
redelegations = append(redelegations, red)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
return types.GenesisState{
|
return types.GenesisState{
|
||||||
Pool: pool,
|
Pool: pool,
|
||||||
Params: params,
|
Params: params,
|
||||||
Validators: validators,
|
IntraTxCounter: intraTxCounter,
|
||||||
Bonds: bonds,
|
LastTotalPower: lastTotalPower,
|
||||||
|
Validators: validators,
|
||||||
|
Bonds: bonds,
|
||||||
|
UnbondingDelegations: unbondingDelegations,
|
||||||
|
Redelegations: redelegations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,11 +161,8 @@ func validateGenesisStateValidators(validators []types.Validator) (err error) {
|
||||||
if val.Jailed && val.Status == sdk.Bonded {
|
if val.Jailed && val.Status == sdk.Bonded {
|
||||||
return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress())
|
return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress())
|
||||||
}
|
}
|
||||||
if val.Tokens.IsZero() {
|
if val.DelegatorShares.IsZero() && val.Status != sdk.Unbonding {
|
||||||
return fmt.Errorf("genesis validator cannot have zero pool shares, validator: %v", val)
|
return fmt.Errorf("bonded/unbonded genesis validator cannot have zero delegator shares, validator: %v", val)
|
||||||
}
|
|
||||||
if val.DelegatorShares.IsZero() {
|
|
||||||
return fmt.Errorf("genesis validator cannot have zero delegator shares, validator: %v", val)
|
|
||||||
}
|
}
|
||||||
addrMap[strKey] = true
|
addrMap[strKey] = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,29 +22,28 @@ func TestInitGenesis(t *testing.T) {
|
||||||
pool.BondedTokens = sdk.NewDec(2)
|
pool.BondedTokens = sdk.NewDec(2)
|
||||||
|
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
|
validators := make([]Validator, 2)
|
||||||
var delegations []Delegation
|
var delegations []Delegation
|
||||||
|
|
||||||
validators := []Validator{
|
|
||||||
NewValidator(sdk.ValAddress(keep.Addrs[0]), keep.PKs[0], Description{Moniker: "hoop"}),
|
|
||||||
NewValidator(sdk.ValAddress(keep.Addrs[1]), keep.PKs[1], Description{Moniker: "bloop"}),
|
|
||||||
}
|
|
||||||
genesisState := types.NewGenesisState(pool, params, validators, delegations)
|
|
||||||
_, err := InitGenesis(ctx, keeper, genesisState)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
// initialize the validators
|
// initialize the validators
|
||||||
|
validators[0].OperatorAddr = sdk.ValAddress(keep.Addrs[0])
|
||||||
|
validators[0].ConsPubKey = keep.PKs[0]
|
||||||
|
validators[0].Description = Description{Moniker: "hoop"}
|
||||||
validators[0].Status = sdk.Bonded
|
validators[0].Status = sdk.Bonded
|
||||||
validators[0].Tokens = sdk.OneDec()
|
validators[0].Tokens = sdk.OneDec()
|
||||||
validators[0].DelegatorShares = sdk.OneDec()
|
validators[0].DelegatorShares = sdk.OneDec()
|
||||||
|
validators[1].OperatorAddr = sdk.ValAddress(keep.Addrs[1])
|
||||||
|
validators[1].ConsPubKey = keep.PKs[1]
|
||||||
|
validators[1].Description = Description{Moniker: "bloop"}
|
||||||
validators[1].Status = sdk.Bonded
|
validators[1].Status = sdk.Bonded
|
||||||
validators[1].Tokens = sdk.OneDec()
|
validators[1].Tokens = sdk.OneDec()
|
||||||
validators[1].DelegatorShares = sdk.OneDec()
|
validators[1].DelegatorShares = sdk.OneDec()
|
||||||
|
|
||||||
genesisState = types.NewGenesisState(pool, params, validators, delegations)
|
genesisState := types.NewGenesisState(pool, params, validators, delegations)
|
||||||
vals, err := InitGenesis(ctx, keeper, genesisState)
|
vals, err := InitGenesis(ctx, keeper, genesisState)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
actualGenesis := WriteGenesis(ctx, keeper)
|
actualGenesis := ExportGenesis(ctx, keeper)
|
||||||
require.Equal(t, genesisState.Pool, actualGenesis.Pool)
|
require.Equal(t, genesisState.Pool, actualGenesis.Pool)
|
||||||
require.Equal(t, genesisState.Params, actualGenesis.Params)
|
require.Equal(t, genesisState.Params, actualGenesis.Params)
|
||||||
require.Equal(t, genesisState.Bonds, actualGenesis.Bonds)
|
require.Equal(t, genesisState.Bonds, actualGenesis.Bonds)
|
||||||
|
@ -126,10 +125,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||||
(*data).Validators = genValidators1
|
(*data).Validators = genValidators1
|
||||||
(*data).Validators = append((*data).Validators, genValidators1[0])
|
(*data).Validators = append((*data).Validators, genValidators1[0])
|
||||||
}, true},
|
}, true},
|
||||||
{"no pool shares", func(data *types.GenesisState) {
|
|
||||||
(*data).Validators = genValidators1
|
|
||||||
(*data).Validators[0].Tokens = sdk.ZeroDec()
|
|
||||||
}, true},
|
|
||||||
{"no delegator shares", func(data *types.GenesisState) {
|
{"no delegator shares", func(data *types.GenesisState) {
|
||||||
(*data).Validators = genValidators1
|
(*data).Validators = genValidators1
|
||||||
(*data).Validators[0].DelegatorShares = sdk.ZeroDec()
|
(*data).Validators[0].DelegatorShares = sdk.ZeroDec()
|
||||||
|
|
|
@ -298,6 +298,21 @@ func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) {
|
||||||
store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{})
|
store.Set(GetREDByValDstIndexKey(red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr), []byte{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// iterate through all redelegations
|
||||||
|
func (k Keeper) IterateRedelegations(ctx sdk.Context, fn func(index int64, red types.Redelegation) (stop bool)) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
iterator := sdk.KVStorePrefixIterator(store, RedelegationKey)
|
||||||
|
defer iterator.Close()
|
||||||
|
|
||||||
|
for i := int64(0); iterator.Valid(); iterator.Next() {
|
||||||
|
red := types.MustUnmarshalRED(k.cdc, iterator.Key(), iterator.Value())
|
||||||
|
if stop := fn(i, red); stop {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remove a redelegation object and associated index
|
// remove a redelegation object and associated index
|
||||||
func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
|
func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
|
@ -17,9 +17,9 @@ func (k Keeper) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) OnValidatorRemoved(ctx sdk.Context, valAddr sdk.ValAddress) {
|
func (k Keeper) OnValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
|
||||||
if k.hooks != nil {
|
if k.hooks != nil {
|
||||||
k.hooks.OnValidatorRemoved(ctx, valAddr)
|
k.hooks.OnValidatorRemoved(ctx, consAddr, valAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,11 +191,13 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||||
k.SetPool(ctx, pool)
|
k.SetPool(ctx, pool)
|
||||||
|
|
||||||
// save the now bonded validator record to the three referenced stores
|
// save the now bonded validator record to the two referenced stores
|
||||||
k.SetValidator(ctx, validator)
|
k.SetValidator(ctx, validator)
|
||||||
|
|
||||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||||
|
|
||||||
|
// delete from queue if present
|
||||||
|
k.DeleteValidatorQueue(ctx, validator)
|
||||||
|
|
||||||
// call the bond hook if present
|
// call the bond hook if present
|
||||||
if k.hooks != nil {
|
if k.hooks != nil {
|
||||||
k.hooks.OnValidatorBonded(ctx, validator.ConsAddress(), validator.OperatorAddr)
|
k.hooks.OnValidatorBonded(ctx, validator.ConsAddress(), validator.OperatorAddr)
|
||||||
|
@ -224,9 +226,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
||||||
validator.UnbondingMinTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
|
validator.UnbondingMinTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
|
||||||
validator.UnbondingHeight = ctx.BlockHeader().Height
|
validator.UnbondingHeight = ctx.BlockHeader().Height
|
||||||
|
|
||||||
// save the now unbonded validator record
|
// save the now unbonded validator record and power index
|
||||||
k.SetValidator(ctx, validator)
|
k.SetValidator(ctx, validator)
|
||||||
|
|
||||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||||
|
|
||||||
// Adds to unbonding validator queue
|
// Adds to unbonding validator queue
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
@ -201,6 +202,11 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
|
store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
|
||||||
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
||||||
|
|
||||||
|
// call hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorRemoved(ctx, validator.ConsAddress(), validator.OperatorAddr)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//___________________________________________________________________________
|
//___________________________________________________________________________
|
||||||
|
@ -320,6 +326,12 @@ func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time,
|
||||||
store.Set(GetValidatorQueueTimeKey(timestamp), bz)
|
store.Set(GetValidatorQueueTimeKey(timestamp), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deletes a specific validator queue timeslice.
|
||||||
|
func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
store.Delete(GetValidatorQueueTimeKey(timestamp))
|
||||||
|
}
|
||||||
|
|
||||||
// Insert an validator address to the appropriate timeslice in the validator queue
|
// Insert an validator address to the appropriate timeslice in the validator queue
|
||||||
func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
||||||
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
||||||
|
@ -331,6 +343,22 @@ func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete a validator address from the validator queue
|
||||||
|
func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
|
||||||
|
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
||||||
|
newTimeSlice := []sdk.ValAddress{}
|
||||||
|
for _, addr := range timeSlice {
|
||||||
|
if !bytes.Equal(addr, val.OperatorAddr) {
|
||||||
|
newTimeSlice = append(newTimeSlice, addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(newTimeSlice) == 0 {
|
||||||
|
k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
||||||
|
} else {
|
||||||
|
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime, newTimeSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns all the validator queue timeslices from time 0 until endTime
|
// Returns all the validator queue timeslices from time 0 until endTime
|
||||||
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
@ -358,9 +386,12 @@ func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
|
||||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice)
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice)
|
||||||
for _, valAddr := range timeslice {
|
for _, valAddr := range timeslice {
|
||||||
val, found := k.GetValidator(ctx, valAddr)
|
val, found := k.GetValidator(ctx, valAddr)
|
||||||
if !found || val.GetStatus() != sdk.Unbonding {
|
if !found {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if val.GetStatus() != sdk.Unbonding {
|
||||||
|
panic("unexpected validator in unbonding queue, status was not unbonding")
|
||||||
|
}
|
||||||
k.unbondingToUnbonded(ctx, val)
|
k.unbondingToUnbonded(ctx, val)
|
||||||
if val.GetDelegatorShares().IsZero() {
|
if val.GetDelegatorShares().IsZero() {
|
||||||
k.RemoveValidator(ctx, val.OperatorAddr)
|
k.RemoveValidator(ctx, val.OperatorAddr)
|
||||||
|
|
|
@ -57,6 +57,9 @@ var (
|
||||||
GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey
|
GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey
|
||||||
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
|
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
|
||||||
TestingUpdateValidator = keeper.TestingUpdateValidator
|
TestingUpdateValidator = keeper.TestingUpdateValidator
|
||||||
|
UnbondingQueueKey = keeper.UnbondingQueueKey
|
||||||
|
RedelegationQueueKey = keeper.RedelegationQueueKey
|
||||||
|
ValidatorQueueKey = keeper.ValidatorQueueKey
|
||||||
|
|
||||||
DefaultParamspace = keeper.DefaultParamspace
|
DefaultParamspace = keeper.DefaultParamspace
|
||||||
KeyUnbondingTime = types.KeyUnbondingTime
|
KeyUnbondingTime = types.KeyUnbondingTime
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
// GenesisState - all staking state that must be provided at genesis
|
// GenesisState - all staking state that must be provided at genesis
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
Pool Pool `json:"pool"`
|
Pool Pool `json:"pool"`
|
||||||
Params Params `json:"params"`
|
Params Params `json:"params"`
|
||||||
Validators []Validator `json:"validators"`
|
IntraTxCounter int16 `json:"intra_tx_counter"`
|
||||||
Bonds []Delegation `json:"bonds"`
|
LastTotalPower sdk.Int `json:"last_total_power"`
|
||||||
|
Validators []Validator `json:"validators"`
|
||||||
|
Bonds []Delegation `json:"bonds"`
|
||||||
|
UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations"`
|
||||||
|
Redelegations []Redelegation `json:"redelegations"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenesisState(pool Pool, params Params, validators []Validator, bonds []Delegation) GenesisState {
|
func NewGenesisState(pool Pool, params Params, validators []Validator, bonds []Delegation) GenesisState {
|
||||||
|
|
|
@ -68,6 +68,7 @@ func (msg MsgCreateValidator) GetSigners() []sdk.AccAddress {
|
||||||
func (msg MsgCreateValidator) GetSignBytes() []byte {
|
func (msg MsgCreateValidator) GetSignBytes() []byte {
|
||||||
b, err := MsgCdc.MarshalJSON(struct {
|
b, err := MsgCdc.MarshalJSON(struct {
|
||||||
Description
|
Description
|
||||||
|
Commission CommissionMsg
|
||||||
DelegatorAddr sdk.AccAddress `json:"delegator_address"`
|
DelegatorAddr sdk.AccAddress `json:"delegator_address"`
|
||||||
ValidatorAddr sdk.ValAddress `json:"validator_address"`
|
ValidatorAddr sdk.ValAddress `json:"validator_address"`
|
||||||
PubKey string `json:"pubkey"`
|
PubKey string `json:"pubkey"`
|
||||||
|
|
Loading…
Reference in New Issue