Merge branch 'develop' into rigel/piggy-bank-fee-spec

This commit is contained in:
Christopher Goes 2018-08-24 14:25:29 +02:00
commit 15b4b338df
15 changed files with 274 additions and 34 deletions

View File

@ -4,6 +4,8 @@ v Before smashing the submit button please review the checkboxes.
v If a checkbox is n/a - please still include it but + a little note why
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
- Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/develop/CONTRIBUTING.md#pr-targeting))
- [ ] Linked to github-issue with discussion and accepted design OR link to spec that describes this work.
- [ ] Wrote tests
- [ ] Updated relevant documentation (`docs/`)

View File

@ -1,5 +1,14 @@
# Changelog
## 0.24.2
*August 22nd, 2018*
BUG FIXES
* Tendermint
- Fix unbounded consensus WAL growth
## 0.24.1
*August 21st, 2018*

View File

@ -133,6 +133,17 @@ Libraries need not follow the model strictly, but would be wise to.
The SDK utilizes [semantic versioning](https://semver.org/).
### PR Targeting
Ensure that you base and target your PR on the correct branch:
- `release/vxx.yy.zz` for a merge into a release candidate
- `master` for a merge of a release
- `develop` in the usual case
All feature additions should be targeted against `develop`. Bug fixes for an outstanding release candidate
should be targeted against the release candidate branch. Release candidate branches themselves should be the
only pull requests targeted directly against master.
### Development Procedure:
- the latest state of development is on `develop`
- `develop` must never fail `make test` or `make test_cli`

9
Gopkg.lock generated
View File

@ -165,13 +165,12 @@
[[projects]]
branch = "master"
digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40"
digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
@ -424,7 +423,7 @@
version = "v0.9.2"
[[projects]]
digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01"
digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -487,8 +486,8 @@
"version",
]
pruneopts = "UT"
revision = "013b9cef642f875634c614019ab13b17570778ad"
version = "v0.23.0"
revision = "81df19e68ab1519399fccf0cab81cb75bf9d782e"
version = "v0.23.1-rc0"
[[projects]]
digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e"

View File

@ -57,7 +57,7 @@
[[override]]
name = "github.com/tendermint/tendermint"
version = "=v0.23.0"
version = "=v0.23.1-rc0"
[[constraint]]
name = "github.com/bartekn/go-bip39"

View File

@ -152,7 +152,7 @@ test_sim_gaia_nondeterminism:
test_sim_gaia_fast:
@echo "Running quick Gaia simulation. This may take several minutes..."
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 24h
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=50 -v -timeout 24h
test_sim_gaia_slow:
@echo "Running full Gaia simulation. This may take awhile!"

View File

@ -16,8 +16,9 @@ BREAKING CHANGES
* Gaia
* Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013)
* [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface.
* [docs] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) Update slashing spec for slashing period
* [x/stake, x/slashing] [#1305](https://github.com/cosmos/cosmos-sdk/issues/1305) - Rename "revoked" to "jailed"
* SDK
* [core] \#1807 Switch from use of rational to decimal
* [types] \#1901 Validator interface's GetOwner() renamed to GetOperator()

View File

@ -0,0 +1,33 @@
# Slashing module specification
## Abstract
This section specifies the slashing module of the Cosmos SDK, which implements functionality
first outlined in the [Cosmos Whitepaper](https://cosmos.network/about/whitepaper) in June 2016.
The slashing module enables Cosmos SDK-based blockchains to disincentivize any attributable action
by a protocol-recognized actor with value at stake by penalizing them ("slashing").
Penalties may include, but are not limited to:
- Burning some amount of their stake
- Removing their ability to vote on future blocks for a period of time.
This module will be used by the Cosmos Hub, the first hub in the Cosmos ecosystem.
## Contents
1. **[Overview](overview.md)**
1. **[State](state.md)**
1. [SigningInfo](state.md#signing-info)
1. [SlashingPeriod](state.md#slashing-period)
1. **[Transactions](transactions.md)**
1. [Unjail](transactions.md#unjail)
1. **[Hooks](hooks.md)**
1. [Validator Bonded](hooks.md#validator-bonded)
1. [Validator Unbonded](hooks.md#validator-unbonded)
1. [Validator Slashed](hooks.md#validator-slashed)
1. **[Begin Block](begin-block.md)**
1. [Evidence handling](begin-block.md#evidence-handling)
1. [Uptime tracking](begin-block.md#uptime-tracking)
1. **[Future Improvements](future-improvements.md)**
1. [State cleanup](future-improvements.md#state-cleanup)

View File

@ -1,12 +1,13 @@
# End-Block
# Begin-Block
## Slashing
## Evidence handling
Tendermint blocks can include
[Evidence](https://github.com/tendermint/tendermint/blob/develop/docs/spec/blockchain/blockchain.md#evidence), which indicates that a validator
committed malicious behaviour. The relevant information is forwarded to the
committed malicious behavior. The relevant information is forwarded to the
application as [ABCI
Evidence](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto#L259), so the validator an be accordingly punished.
Evidence](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto#L259) in `abci.RequestBeginBlock`
so that the validator an be accordingly punished.
For some `evidence` to be valid, it must satisfy:
@ -75,7 +76,9 @@ 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.
## Automatic Unbonding
The amount slashed for all double signature infractions committed within a single slashing period is capped as described in [state-machine.md](state-machine.md).
## Uptime tracking
At the beginning of each block, we update the signing info for each validator and check if they should be automatically unbonded:
@ -113,3 +116,5 @@ for val in block.Validators:
SigningInfo.Set(val.Address, signInfo)
```
The amount slashed for downtime slashes is *not* capped by the slashing period in which they are committed, although they do reset it (since the validator is unbonded).

View File

@ -0,0 +1,4 @@
## State Cleanup
Once no evidence for a given slashing period can possibly be valid (the end time plus the unbonding period is less than the current time),
old slashing periods should be cleaned up. This will be implemented post-launch.

View File

@ -0,0 +1,58 @@
## Hooks
In this section we describe the "hooks" - slashing module code that runs when other events happen.
### Validator Bonded
Upon successful bonding of a validator (a given validator entering the "bonded" state,
which may happen on delegation, on unjailing, etc), we create a new `SlashingPeriod` structure for the
now-bonded validator, which `StartHeight` of the current block, `EndHeight` of `0` (sentinel value for not-yet-ended),
and `SlashedSoFar` of `0`:
```
onValidatorBonded(address sdk.ValAddress)
slashingPeriod = SlashingPeriod{
ValidatorAddr : address,
StartHeight : CurrentHeight,
EndHeight : 0,
SlashedSoFar : 0,
}
setSlashingPeriod(slashingPeriod)
return
```
### Validator Unbonded
When a validator is unbonded, we update the in-progress `SlashingPeriod` with the current block as the `EndHeight`:
```
onValidatorUnbonded(address sdk.ValAddress)
slashingPeriod = getSlashingPeriod(address, CurrentHeight)
slashingPeriod.EndHeight = CurrentHeight
setSlashingPeriod(slashingPeriod)
return
```
### Validator Slashed
When a validator is slashed, we look up the appropriate `SlashingPeriod` based on the validator
address and the time of infraction, cap the fraction slashed as `max(SlashFraction, SlashedSoFar)`
(which may be `0`), and update the `SlashingPeriod` with the increased `SlashedSoFar`:
```
beforeValidatorSlashed(address sdk.ValAddress, fraction sdk.Rat, infractionHeight int64)
slashingPeriod = getSlashingPeriod(address, infractionHeight)
totalToSlash = max(slashingPeriod.SlashedSoFar, fraction)
slashingPeriod.SlashedSoFar = totalToSlash
setSlashingPeriod(slashingPeriod)
remainderToSlash = slashingPeriod.SlashedSoFar - totalToSlash
fraction = remainderToSlash
continue with slashing
```

View File

@ -0,0 +1,68 @@
## Conceptual overview
### States
At any given time, there are any number of validators registered in the state machine.
Each block, the top `n = MaximumBondedValidators` validators who are not jailed become *bonded*, meaning that they may propose and vote on blocks.
Validators who are *bonded* are *at stake*, meaning that part or all of their stake and their delegators' stake is at risk if they commit a protocol fault.
### Slashing period
In order to mitigate the impact of initially likely categories of non-malicious protocol faults, the Cosmos Hub implements for each validator
a *slashing period*, in which the amount by which a validator can be slashed is capped at the punishment for the worst violation. For example,
if you misconfigure your HSM and double-sign a bunch of old blocks, you'll only be punished for the first double-sign (and then immediately jailed,
so that you have a chance to reconfigure your setup). This will still be quite expensive and desirable to avoid, but slashing periods somewhat blunt
the economic impact of unintentional misconfiguration.
Unlike the unbonding period, the slashing period doesn't have a fixed length. A new slashing period starts whenever a validator is bonded and ends
whenever the validator is unbonded (which will happen if the validator is jailed). The amount of tokens slashed relative to validator power for infractions
committed within the slashing period, whenever they are discovered, is capped at the punishment for the worst infraction
(which for the Cosmos Hub at launch will be double-signing a block).
#### ASCII timelines
*Code*
*[* : timeline start
*]* : timeline end
*<* : slashing period start
*>* : slashing period end
*C<sub>n</sub>* : infraction `n` committed
*D<sub>n</sub>* : infraction `n` discovered
*V<sub>b</sub>* : validator bonded
*V<sub>u</sub>* : validator unbonded
*Single infraction*
<----------------->
[----------C<sub>1</sub>----D<sub>1</sub>,V<sub>u</sub>-----]
A single infraction is committed then later discovered, at which point the validator is unbonded and slashed at the full amount for the infraction.
*Multiple infractions*
<--------------------------->
[----------C<sub>1</sub>--C<sub>2</sub>---C<sub>3</sub>---D<sub>1</sub>,D<sub>2</sub>,D<sub>3</sub>V<sub>u</sub>-----]
Multiple infractions are committed within a single slashing period then later discovered, at which point the validator is unbonded and slashed for only the worst infraction.
*Multiple infractions after rebonding*
<--------------------------->&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<------------->
[----------C<sub>1</sub>--C<sub>2</sub>---C<sub>3</sub>---D<sub>1</sub>,D<sub>2</sub>,D<sub>3</sub>V<sub>u</sub>---V<sub>b</sub>---C<sub>4</sub>----D<sub>4</sub>,V<sub>u</sub>--]
Multiple infractions are committed within a single slashing period then later discovered, at which point the validator is unbonded and slashed for only the worst infraction.
The validator then unjails themself and rebonds, then commits a fourth infraction - which is discovered and punished at the full amount, since a new slashing period started
when they unjailed and rebonded.
### Safety note
Slashing is capped fractionally per period, but the amount of total bonded stake associated with any given validator can change (by an unbounded amount) over that period.
For example, with MaxFractionSlashedPerPeriod = `0.5`, if a validator is initially slashed at `0.4` near the start of a period when they have 100 stake bonded,
then later slashed at `0.4` when they have `1000` stake bonded, the total amount slashed is just `40 + 100 = 140` (since the latter slash is capped at `0.1`) -
whereas if they had `1000` stake bonded initially, the first offense would have been slashed for `400` stake and the total amount slashed would have been `400 + 100 = 500`.
This means that any slashing events which utilize the slashing period (are capped-per-period) **must also** jail the validator when the infraction is discovered.
Otherwise it would be possible for a validator to slash themselves intentionally at a low bond, then increase their bond but no longer be at stake since they would have already hit the `SlashedSoFar` cap.

View File

@ -1,6 +1,6 @@
## State
# State
### Signing Info
## Signing Info
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.
@ -36,10 +36,11 @@ The information stored for tracking validator liveness is as follows:
```go
type ValidatorSigningInfo struct {
StartHeight int64
IndexOffset int64
JailedUntil int64
SignedBlocksCounter int64
StartHeight int64 // Height at which the validator became able to sign blocks
IndexOffset int64 // Offset into the signed block bit array
JailedUntilHeight int64 // Block height until which the validator is jailed,
// or sentinel value of 0 for not jailed
SignedBlocksCounter int64 // Running counter of signed blocks
}
```
@ -49,3 +50,31 @@ Where:
* `IndexOffset` is incremented each time the candidate was a bonded validator in a block (and may have signed a precommit or not).
* `JailedUntil` is set whenever the candidate is jailed due to downtime
* `SignedBlocksCounter` is a counter kept to avoid unnecessary array reads. `SignedBlocksBitArray.Sum() == SignedBlocksCounter` always.
## Slashing Period
A slashing period is a start and end block height associated with a particular validator,
within which only the "worst infraction counts" (see the [Overview](overview.md)): the total
amount of slashing for infractions committed within the period (and discovered whenever) is
capped at the penalty for the worst offense.
This period starts when a validator is first bonded and ends when a validator is slashed & jailed
for any reason. When the validator rejoins the validator set (perhaps through unjailing themselves,
and perhaps also changing signing keys), they enter into a new period.
Slashing periods are indexed in the store as follows:
- SlashingPeriod: ` 0x03 | ValTendermintAddr | StartHeight -> amino(slashingPeriod) `
This allows us to look up slashing period by a validator's address, the only lookup necessary,
and iterate over start height to efficiently retrieve the most recent slashing period(s)
or those beginning after a given height.
```go
type SlashingPeriod struct {
ValidatorAddr sdk.ValAddress // Tendermint address of the validator
StartHeight int64 // Block height at which slashing period begin
EndHeight int64 // Block height at which slashing period ended
SlashedSoFar sdk.Rat // Fraction slashed so far, cumulative
}
```

View File

@ -1,19 +1,40 @@
## Transactions
### TxProveLive
In this section we describe the processing of transactions for the `slashing` module.
If a validator was automatically unbonded due to liveness issues and wishes to
assert it is still online, it can send `TxProveLive`:
### Unjail
```golang
type TxProveLive struct {
PubKey crypto.PubKey
If a validator was automatically unbonded due to downtime and wishes to come back online &
possibly rejoin the bonded set, it must send `TxUnjail`:
```
type TxUnjail struct {
ValidatorAddr sdk.AccAddress
}
handleMsgUnjail(tx TxUnjail)
validator = getValidator(tx.ValidatorAddr)
if validator == nil
fail with "No validator found"
if !validator.Jailed
fail with "Validator not jailed, cannot unjail"
info = getValidatorSigningInfo(operator)
if block time < info.JailedUntil
fail with "Validator still jailed, cannot unjail until period has expired"
// Update the start height so the validator won't be immediately unbonded again
info.StartHeight = BlockHeight
setValidatorSigningInfo(info)
validator.Jailed = false
setValidator(validator)
return
```
All delegators in the temporary unbonding pool which have not
transacted to move will be bonded back to the now-live validator and begin to
once again collect provisions and rewards.
```
TODO: pseudo-code
```
If the validator has enough stake to be in the top `n = MaximumBondedValidators`, they will be automatically rebonded,
and all delegators still delegated to the validator will be rebonded and begin to again collect
provisions and rewards.

View File

@ -3,9 +3,9 @@ package version
const Maj = "0"
const Min = "24"
const Fix = "1"
const Fix = "2"
const Version = "0.24.1"
const Version = "0.24.2"
// GitCommit set by build flags
var GitCommit = ""