diff --git a/.circleci/config.yml b/.circleci/config.yml index 122827afd..2accbf179 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -84,22 +84,6 @@ jobs: export PATH="$GOBIN:$PATH" make test_unit - test_cli: - <<: *defaults - parallelism: 1 - steps: - - attach_workspace: - at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} - - run: - name: Test cli - command: | - export PATH="$GOBIN:$PATH" - make test_cli - test_cover: <<: *defaults parallelism: 4 @@ -115,7 +99,7 @@ jobs: command: | export PATH="$GOBIN:$PATH" make install - for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | circleci tests split --split-by=timings); do + for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do id=$(basename "$pkg") go test -timeout 5m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" @@ -156,9 +140,6 @@ workflows: - test_unit: requires: - setup_dependencies - - test_cli: - requires: - - setup_dependencies - test_cover: requires: - setup_dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b1e67bee..77b4ffba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ BREAKING CHANGES FEATURES: +* Added `gaiad export` command, which exports genesis information & current state * Gaia stake commands include, DeclareCandidacy, EditCandidacy, Delegate, Unbond * MountStoreWithDB without providing a custom store works. * Repo is now lint compliant / GoMetaLinter with tendermint-lint integrated into CI diff --git a/Makefile b/Makefile index abcdc5756..043645c67 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ godocs: ######################################## ### Testing -test: test_unit test_cli +test: test_unit test_cli: @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test` diff --git a/docs/spec/staking/slashing.md b/docs/spec/staking/slashing.md new file mode 100644 index 000000000..c64aa9d79 --- /dev/null +++ b/docs/spec/staking/slashing.md @@ -0,0 +1,79 @@ + +# Slashing + +A validator bond is an economic commitment made by a validator signing key to both the safety and liveness of +the consensus. Validator keys must not sign invalid messages which could +violate consensus safety, and their signed precommit messages must be regularly included in +block commits. + +The incentivization of these two goals are treated separately. + +## Safety + +Messges which may compromise the safety of the underlying consensus protocol ("equivocations") +result in some amount of the offending validator's shares being removed ("slashed"). + +Currently, such messages include only the following: + +- prevotes by the same validator for more than one BlockID at the same + Height and Round +- precommits by the same validator for more than one BlockID at the same + Height and Round + +We call any such pair of conflicting votes `Evidence`. Full nodes in the network prioritize the +detection and gossipping of `Evidence` so that it may be rapidly included in blocks and the offending +validators punished. + +For some `evidence` to be valid, it must satisfy: + +`evidence.Height >= block.Height - MAX_EVIDENCE_AGE` + +If valid evidence is included in a block, the offending validator loses +a constant `SLASH_PROPORTION` of their current stake: + +``` +oldShares = validator.shares +validator.shares = oldShares * (1 - SLASH_PROPORTION) +``` + +This ensures that offending validators are punished the same amount whether they +act as a single validator with X stake or as N validators with collectively X +stake. + + + +## Liveness + +Every block includes a set of precommits by the validators for the previous block, +known as the LastCommit. A LastCommit is valid so long as it contains precommits from +2/3 of voting power. + +Proposers are incentivized to include precommits from all +validators in the LastCommit by receiving additional fees +proportional to the difference between the voting power included in the +LastCommit and +2/3 (see [TODO](https://github.com/cosmos/cosmos-sdk/issues/967)). + +Validators are penalized for failing to be included in the LastCommit for some +number of blocks by being automatically unbonded. + + +TODO: do we do this by trying to track absence directly in the state, using +something like the below, or do we let users notify the app when a validator has +been absent using the +[TxLivenessCheck](https://github.com/cosmos/cosmos-sdk/blob/develop/docs/spec/staking/spec-technical.md#txlivelinesscheck). + + +A list, `ValidatorAbsenceInfos`, is stored in the state and used to track how often +validators were included in a LastCommit. + +```go +// Ordered by ValidatorAddress. +// One entry for each validator. +type ValidatorAbsenceInfos []ValidatorAbsenceInfo + +type ValidatorAbsenceInfo struct { + ValidatorAddress []byte // address of the validator + FirstHeight int64 // first height the validator was absent + Count int64 // number of heights validator was absent since (and including) first +} +``` + diff --git a/docs/spec/staking/spec-technical.md b/docs/spec/staking/spec-technical.md index 8d9baa796..c55615936 100644 --- a/docs/spec/staking/spec-technical.md +++ b/docs/spec/staking/spec-technical.md @@ -36,24 +36,22 @@ provisions and transaction fees. ## State The staking module persists the following information to the store: -* `GlobalState`, describing the global pools and the inflation related fields -* validator candidates (including current validators), indexed by public key and shares in the global pool -(bonded or unbonded depending on candidate status) -* delegator bonds (for each delegation to a candidate by a delegator), indexed by the delegator address and the candidate +* `GlobalState`, a struct describing the global pools, inflation, and + fees +* `ValidatorCandidates: => `, a map of all candidates (including current validators) in the store, +indexed by their public key and shares in the global pool. +* `DelegatorBonds: < delegator-address | candidate-pubkey > => `. a map of all delegations by a delegator to a candidate, +indexed by delegator address and candidate pubkey. public key -* the queue of unbonding delegations -* the queue of re-delegations +* `UnbondQueue`, the queue of unbonding delegations +* `RedelegateQueue`, the queue of re-delegations ### Global State -The GlobalState data structure contains total Atom supply, amount of Atoms in -the bonded pool, sum of all shares distributed for the bonded pool, amount of -Atoms in the unbonded pool, sum of all shares distributed for the unbonded -pool, a timestamp of the last processing of inflation, the current annual -inflation rate, a timestamp for the last comission accounting reset, the global -fee pool, a pool of reserve taxes collected for the governance use and an -adjustment factor for calculating global fee accum. `Params` is global data -structure that stores system parameters and defines overall functioning of the +The GlobalState contains information about the total amount of Atoms, the +global bonded/unbonded position, the Atom inflation rate, and the fees. + +`Params` is global data structure that stores system parameters and defines overall functioning of the module. ``` go @@ -95,7 +93,7 @@ type Params struct { ### Candidate -The `Candidate` data structure holds the current state and some historical +The `Candidate` holds the current state and some historical actions of validators or candidate-validators. ``` go diff --git a/server/export.go b/server/export.go index 3d0e49a12..dad2df9cc 100644 --- a/server/export.go +++ b/server/export.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/wire" + tmtypes "github.com/tendermint/tendermint/types" ) // ExportCmd dumps app state to JSON @@ -21,7 +22,16 @@ func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Co if err != nil { return errors.Errorf("Error exporting state: %v\n", err) } - fmt.Println(string(appState)) + doc, err := tmtypes.GenesisDocFromFile(ctx.Config.GenesisFile()) + if err != nil { + return err + } + doc.AppStateJSON = appState + encoded, err := wire.MarshalJSONIndent(cdc, doc) + if err != nil { + return err + } + fmt.Println(string(encoded)) return nil }, } diff --git a/tests/test_cover.sh b/tests/test_cover.sh index 4f8aa55f1..be6215b5a 100644 --- a/tests/test_cover.sh +++ b/tests/test_cover.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -PKGS=$(go list ./... | grep -v /vendor/) +PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test) set -e echo "mode: atomic" > coverage.txt