From cb2fa04da1845855ccd9ed8901b25c1550fe4bf7 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 22 Aug 2018 18:10:31 +0200 Subject: [PATCH 01/26] Update PENDING.md --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index cf68b69b5780..e4303619b201 100644 --- a/PENDING.md +++ b/PENDING.md @@ -21,6 +21,7 @@ BREAKING CHANGES * SDK * [core] \#1807 Switch from use of rational to decimal * [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() + * [x/slashing] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2121) - Implement slashing period * Tendermint From fedb717f1ad5197ab327aa8402222fc62eb5be6c Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 22 Aug 2018 18:28:36 +0200 Subject: [PATCH 02/26] SlashingPeriod struct --- PENDING.md | 2 +- x/slashing/slashing_period.go | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 x/slashing/slashing_period.go diff --git a/PENDING.md b/PENDING.md index e4303619b201..f3b3826ddef0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -21,7 +21,7 @@ BREAKING CHANGES * SDK * [core] \#1807 Switch from use of rational to decimal * [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() - * [x/slashing] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2121) - Implement slashing period + * [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period * Tendermint diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go new file mode 100644 index 000000000000..120a6f7fef07 --- /dev/null +++ b/x/slashing/slashing_period.go @@ -0,0 +1,52 @@ +package slashing + +import ( + "encoding/binary" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Stored by *validator* address (not owner address) +func (k Keeper) getValidatorSlashingPeriod(ctx sdk.Context, address sdk.ValAddress, startHeight int64) (slashingPeriod ValidatorSlashingPeriod) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(GetValidatorSlashingPeriodKey(address, startHeight)) + k.cdc.MustUnmarshalBinary(bz, &slashingPeriod) + return +} + +// Stored by *validator* address (not owner address) +func (k Keeper) setValidatorSlashingPeriod(ctx sdk.Context, address sdk.ValAddress, startHeight int64, slashingPeriod ValidatorSlashingPeriod) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinary(slashingPeriod) + store.Set(GetValidatorSlashingPeriodKey(address, startHeight), bz) +} + +// Construct a new `ValidatorSlashingPeriod` struct +func NewValidatorSlashingPeriod(startHeight int64, endHeight int64, slashedSoFar sdk.Dec) ValidatorSlashingPeriod { + return ValidatorSlashingPeriod{ + StartHeight: startHeight, + EndHeight: endHeight, + SlashedSoFar: slashedSoFar, + } +} + +// Slashing period for a validator +type ValidatorSlashingPeriod struct { + StartHeight int64 `json:"start_height"` // starting height of the slashing period + EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress + SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period +} + +// Return human readable slashing period +func (p ValidatorSlashingPeriod) HumanReadableString() string { + return fmt.Sprintf("Start height: %d, end height: %d, slashed so far: %v", + p.StartHeight, p.EndHeight, p.SlashedSoFar) +} + +// Stored by *validator* address (not owner address) followed by start height +func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(startHeight)) + return append([]byte{0x03}, append(v.Bytes(), b...)...) +} From 23f888758bfa4aa4e5c53631c9358c66f0b9cb73 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 22 Aug 2018 18:48:20 +0200 Subject: [PATCH 03/26] Seperate keys.go, constant prefixes --- x/slashing/keys.go | 32 ++++++++++++++++++++++++++++++++ x/slashing/signing_info.go | 13 ------------- x/slashing/slashing_period.go | 8 -------- 3 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 x/slashing/keys.go diff --git a/x/slashing/keys.go b/x/slashing/keys.go new file mode 100644 index 000000000000..b7aaf191231b --- /dev/null +++ b/x/slashing/keys.go @@ -0,0 +1,32 @@ +package slashing + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + ValidatorSigningInfoKey = []byte{0x01} + ValidatorSigningBitArrayKey = []byte{0x02} + ValidatorSlashingPeriodKey = []byte{0x03} +) + +// Stored by *validator* address (not owner address) +func GetValidatorSigningInfoKey(v sdk.ValAddress) []byte { + return append(ValidatorSigningInfoKey, v.Bytes()...) +} + +// Stored by *validator* address (not owner address) +func GetValidatorSigningBitArrayKey(v sdk.ValAddress, i int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(i)) + return append(ValidatorSigningBitArrayKey, append(v.Bytes(), b...)...) +} + +// Stored by *validator* address (not owner address) followed by start height +func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(startHeight)) + return append([]byte{0x03}, append(v.Bytes(), b...)...) +} diff --git a/x/slashing/signing_info.go b/x/slashing/signing_info.go index 25a83e833d31..9edd9910f38a 100644 --- a/x/slashing/signing_info.go +++ b/x/slashing/signing_info.go @@ -1,7 +1,6 @@ package slashing import ( - "encoding/binary" "fmt" "time" @@ -71,15 +70,3 @@ func (i ValidatorSigningInfo) HumanReadableString() string { return fmt.Sprintf("Start height: %d, index offset: %d, jailed until: %v, signed blocks counter: %d", i.StartHeight, i.IndexOffset, i.JailedUntil, i.SignedBlocksCounter) } - -// Stored by *validator* address (not owner address) -func GetValidatorSigningInfoKey(v sdk.ValAddress) []byte { - return append([]byte{0x01}, v.Bytes()...) -} - -// Stored by *validator* address (not owner address) -func GetValidatorSigningBitArrayKey(v sdk.ValAddress, i int64) []byte { - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(i)) - return append([]byte{0x02}, append(v.Bytes(), b...)...) -} diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 120a6f7fef07..be3c2420b627 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -1,7 +1,6 @@ package slashing import ( - "encoding/binary" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" @@ -43,10 +42,3 @@ func (p ValidatorSlashingPeriod) HumanReadableString() string { return fmt.Sprintf("Start height: %d, end height: %d, slashed so far: %v", p.StartHeight, p.EndHeight, p.SlashedSoFar) } - -// Stored by *validator* address (not owner address) followed by start height -func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(startHeight)) - return append([]byte{0x03}, append(v.Bytes(), b...)...) -} From ddce1cfcde9bbb1eda8fda11f5d4e2c7d7c92537 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 22 Aug 2018 18:56:29 +0200 Subject: [PATCH 04/26] Make linter happy --- x/slashing/keys.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/x/slashing/keys.go b/x/slashing/keys.go index b7aaf191231b..1dc3bba57c4f 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -7,9 +7,12 @@ import ( ) var ( - ValidatorSigningInfoKey = []byte{0x01} + // Prefix for signing info + ValidatorSigningInfoKey = []byte{0x01} + // Prefix for signature bit array ValidatorSigningBitArrayKey = []byte{0x02} - ValidatorSlashingPeriodKey = []byte{0x03} + // Prefix for slashing period + ValidatorSlashingPeriodKey = []byte{0x03} ) // Stored by *validator* address (not owner address) From 3c59d43b208993709b62709b671c4901c38c4ce5 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 24 Aug 2018 13:43:05 +0200 Subject: [PATCH 05/26] Update Gopkg.lock --- Gopkg.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 81591a0ae395..077050a8c2c2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -38,7 +38,7 @@ name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" + revision = "79e00513b1011888b1e675157ab89f527f901cae" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -230,12 +230,12 @@ version = "v1.0.1" [[projects]] - branch = "master" - digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" + digest = "1:645110e089152bd0f4a011a2648fbb0e4df5977be73ca605781157ac297f50c4" name = "github.com/mitchellh/mapstructure" packages = ["."] pruneopts = "UT" - revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" + revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8" + version = "v1.0.0" [[projects]] digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" @@ -545,14 +545,14 @@ [[projects]] branch = "master" - digest = "1:a0e12bc26f317c0e2d497baf767285e1790e526e8dd46553c5a67fcbc8692157" + digest = "1:86171d21d59449dcf7cee0b7d2da83dff989dab9b9b69bfe0a3d59c3c1ca6081" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" + revision = "11551d06cbcc94edc80a0facaccbda56473c19c1" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" From bc392cfe35f0f1055accf87c7e43f58409431bd6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 24 Aug 2018 14:13:19 +0200 Subject: [PATCH 06/26] Seek slashing period by infraction height --- x/slashing/keys.go | 7 ++++- x/slashing/slashing_period.go | 52 +++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 1dc3bba57c4f..27324afa87a0 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -27,9 +27,14 @@ func GetValidatorSigningBitArrayKey(v sdk.ValAddress, i int64) []byte { return append(ValidatorSigningBitArrayKey, append(v.Bytes(), b...)...) } +// Stored by *validator* address (not owner address) +func GetValidatorSlashingPeriodPrefix(v sdk.ValAddress) []byte { + return append(ValidatorSlashingPeriodKey, v.Bytes()...) +} + // Stored by *validator* address (not owner address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(startHeight)) - return append([]byte{0x03}, append(v.Bytes(), b...)...) + return append(GetValidatorSlashingPeriodPrefix(v), b...) } diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index be3c2420b627..3eda0bafd397 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -1,24 +1,51 @@ package slashing import ( + "encoding/binary" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" ) // Stored by *validator* address (not owner address) -func (k Keeper) getValidatorSlashingPeriod(ctx sdk.Context, address sdk.ValAddress, startHeight int64) (slashingPeriod ValidatorSlashingPeriod) { +func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) - bz := store.Get(GetValidatorSlashingPeriodKey(address, startHeight)) - k.cdc.MustUnmarshalBinary(bz, &slashingPeriod) + start := GetValidatorSlashingPeriodKey(address, height) + end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodPrefix(address)) + iterator := store.Iterator(start, end) + if !iterator.Valid() { + panic("expected to find slashing period, but none was found") + } + slashingPeriod = k.unmarshalSlashingPeriodKeyValue(iterator.Key(), iterator.Value()) + if slashingPeriod.EndHeight < height { + panic("slashing period ended before infraction") + } return } // Stored by *validator* address (not owner address) -func (k Keeper) setValidatorSlashingPeriod(ctx sdk.Context, address sdk.ValAddress, startHeight int64, slashingPeriod ValidatorSlashingPeriod) { +func (k Keeper) setValidatorSlashingPeriod(ctx sdk.Context, slashingPeriod ValidatorSlashingPeriod) { + slashingPeriodValue := ValidatorSlashingPeriodValue{ + EndHeight: slashingPeriod.EndHeight, + SlashedSoFar: slashingPeriod.SlashedSoFar, + } store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinary(slashingPeriod) - store.Set(GetValidatorSlashingPeriodKey(address, startHeight), bz) + bz := k.cdc.MustMarshalBinary(slashingPeriodValue) + store.Set(GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), bz) +} + +// Unmarshal key/value into a ValidatorSlashingPeriod +func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) ValidatorSlashingPeriod { + var slashingPeriodValue ValidatorSlashingPeriodValue + k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) + address := sdk.ValAddress(key[1 : 1+sdk.AddrLen]) + startHeight := int64(binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) + return ValidatorSlashingPeriod{ + ValidatorAddr: address, + StartHeight: startHeight, + EndHeight: slashingPeriodValue.EndHeight, + SlashedSoFar: slashingPeriodValue.SlashedSoFar, + } } // Construct a new `ValidatorSlashingPeriod` struct @@ -32,9 +59,16 @@ func NewValidatorSlashingPeriod(startHeight int64, endHeight int64, slashedSoFar // Slashing period for a validator type ValidatorSlashingPeriod struct { - StartHeight int64 `json:"start_height"` // starting height of the slashing period - EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress - SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period + ValidatorAddr sdk.ValAddress `json:"validator"` // validator which this slashing period is for + StartHeight int64 `json:"start_height"` // starting height of the slashing period + EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress + SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period +} + +// Value part of slashing period (validator address & start height are stored in the key) +type ValidatorSlashingPeriodValue struct { + EndHeight int64 `json:"end_height"` + SlashedSoFar sdk.Dec `json:"slashed_so_far"` } // Return human readable slashing period From fa8faadf5f7dfd9304e80d3735dd1baf4c34481c Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 24 Aug 2018 19:06:45 +0200 Subject: [PATCH 07/26] Slashing period hooks --- types/decimal.go | 8 ++++++++ x/slashing/hooks.go | 23 +++++++++++++++++++++++ x/slashing/slashing_period.go | 15 +++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 x/slashing/hooks.go diff --git a/types/decimal.go b/types/decimal.go index baf2d9573d39..8e7db1340b0e 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -415,6 +415,14 @@ func MinDec(d1, d2 Dec) Dec { return d2 } +// maximum decimal between two +func MaxDec(d1, d2 Dec) Dec { + if d1.LT(d2) { + return d2 + } + return d1 +} + // intended to be used with require/assert: require.True(DecEq(...)) func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) { return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go new file mode 100644 index 000000000000..f74d7ab149b5 --- /dev/null +++ b/x/slashing/hooks.go @@ -0,0 +1,23 @@ +package slashing + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Create a new slashing period when a validator is bonded +func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { + slashingPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: address, + StartHeight: ctx.BlockHeight(), + EndHeight: 0, + SlashedSoFar: sdk.ZeroDec(), + } + k.setValidatorSlashingPeriod(ctx, slashingPeriod) +} + +// Mark the slashing period as having ended when a validator is unbonded +func (k Keeper) onValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { + slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, ctx.BlockHeight()) + slashingPeriod.EndHeight = ctx.BlockHeight() + k.setValidatorSlashingPeriod(ctx, slashingPeriod) +} diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 3eda0bafd397..e9c4398df0a1 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -7,6 +7,21 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// Cap an infraction's slash amount by the slashing period in which it was committed +func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fraction sdk.Dec, infractionHeight int64) (revisedFraction sdk.Dec) { + + // Calculate total amount to be slashed + slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, infractionHeight) + totalToSlash := sdk.MaxDec(slashingPeriod.SlashedSoFar, fraction) + slashingPeriod.SlashedSoFar = totalToSlash + k.setValidatorSlashingPeriod(ctx, slashingPeriod) + + // Calculate remainder + revisedFraction = slashingPeriod.SlashedSoFar.Sub(totalToSlash) + return + +} + // Stored by *validator* address (not owner address) func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) From 23fbba7701070ca894aacfe7d1014936e6f8fa89 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 11:50:50 +0200 Subject: [PATCH 08/26] Slashing period unit tests; bugfix --- x/slashing/slashing_period.go | 7 ++-- x/slashing/slashing_period_test.go | 55 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 x/slashing/slashing_period_test.go diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index e9c4398df0a1..76de26ea7636 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -13,11 +13,14 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // Calculate total amount to be slashed slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, infractionHeight) totalToSlash := sdk.MaxDec(slashingPeriod.SlashedSoFar, fraction) + + // Calculate remainder + revisedFraction = totalToSlash.Sub(slashingPeriod.SlashedSoFar) + + // Update slashing period slashingPeriod.SlashedSoFar = totalToSlash k.setValidatorSlashingPeriod(ctx, slashingPeriod) - // Calculate remainder - revisedFraction = slashingPeriod.SlashedSoFar.Sub(totalToSlash) return } diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go new file mode 100644 index 000000000000..8714fc3be4d9 --- /dev/null +++ b/x/slashing/slashing_period_test.go @@ -0,0 +1,55 @@ +package slashing + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestGetSetValidatorSlashingPeriod(t *testing.T) { + ctx, _, _, _, keeper := createTestInput(t) + addr := sdk.ValAddress(addrs[0]) + height := int64(5) + require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) }) + newPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: addr, + StartHeight: height, + EndHeight: height + 10, + SlashedSoFar: sdk.ZeroDec(), + } + keeper.setValidatorSlashingPeriod(ctx, newPeriod) + // Get at start height + retrieved := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) + require.Equal(t, addr, retrieved.ValidatorAddr) + // Get before start height + retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(0)) + require.Equal(t, addr, retrieved.ValidatorAddr) + // Get after start height (panic) + require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(6)) }) + // Get after end height (panic) + newPeriod.EndHeight = int64(4) + keeper.setValidatorSlashingPeriod(ctx, newPeriod) + require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) }) +} + +func TestValidatorSlashingPeriodCap(t *testing.T) { + ctx, _, _, _, keeper := createTestInput(t) + addr := sdk.ValAddress(addrs[0]) + height := int64(5) + newPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: addr, + StartHeight: height, + EndHeight: height + 10, + SlashedSoFar: sdk.ZeroDec(), + } + keeper.setValidatorSlashingPeriod(ctx, newPeriod) + half := sdk.NewDec(1).Quo(sdk.NewDec(2)) + // First slash should be full + fractionA := keeper.capBySlashingPeriod(ctx, addr, half, height) + require.True(t, fractionA.Equal(half)) + // Second slash should be capped + fractionB := keeper.capBySlashingPeriod(ctx, addr, half, height) + require.True(t, fractionB.Equal(sdk.ZeroDec())) +} From 8d2c74b622ffc29e8d939a270e3b9cd8848fa290 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 18:04:27 +0200 Subject: [PATCH 09/26] Add simple hook tests --- x/slashing/hooks_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 x/slashing/hooks_test.go diff --git a/x/slashing/hooks_test.go b/x/slashing/hooks_test.go new file mode 100644 index 000000000000..0eafcfb52e70 --- /dev/null +++ b/x/slashing/hooks_test.go @@ -0,0 +1,26 @@ +package slashing + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestHookOnValidatorBonded(t *testing.T) { + ctx, _, _, _, keeper := createTestInput(t) + addr := sdk.ValAddress(addrs[0]) + keeper.onValidatorBonded(ctx, addr) + period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight()) + require.Equal(t, ValidatorSlashingPeriod{addr, ctx.BlockHeight(), 0, sdk.ZeroDec()}, period) +} + +func TestHookOnValidatorUnbonded(t *testing.T) { + ctx, _, _, _, keeper := createTestInput(t) + addr := sdk.ValAddress(addrs[0]) + keeper.onValidatorBonded(ctx, addr) + keeper.onValidatorUnbonded(ctx, addr) + period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight()) + require.Equal(t, ValidatorSlashingPeriod{addr, ctx.BlockHeight(), ctx.BlockHeight(), sdk.ZeroDec()}, period) +} From b111c758f7b50c1c3ff128bc9cdf0b7decfa3b59 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 18:20:42 +0200 Subject: [PATCH 10/26] Add sdk.ValidatorHooks interface --- types/stake.go | 6 ++++++ x/slashing/hooks.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/types/stake.go b/types/stake.go index d872277256df..7dd0c421c631 100644 --- a/types/stake.go +++ b/types/stake.go @@ -95,3 +95,9 @@ type DelegationSet interface { IterateDelegations(ctx Context, delegator AccAddress, fn func(index int64, delegation Delegation) (stop bool)) } + +// validator event hooks +type ValidatorHooks interface { + OnValidatorBonded(ctx Context, address ValAddress) // Must be called when a validator is bonded + OnValidatorUnbonded(ctx Context, address ValAddress) // Must be called when a validator is unbonded +} diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index f74d7ab149b5..7012b640f459 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -21,3 +21,21 @@ func (k Keeper) onValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { slashingPeriod.EndHeight = ctx.BlockHeight() k.setValidatorSlashingPeriod(ctx, slashingPeriod) } + +// Wrapper struct for sdk.ValidatorHooks +type ValidatorHooks struct { + k Keeper +} + +// Implements sdk.ValidatorHooks +func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { + v.k.onValidatorBonded(ctx, address) +} + +// Implements sdk.ValidatorHooks +func (v ValidatorHooks) OnValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { + v.k.onValidatorUnbonded(ctx, address) +} + +// Assert implementation +var _ sdk.ValidatorHooks = ValidatorHooks{} From dac51aa294fa9cc5858781c18621f5c8f1c9e03c Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 18:35:42 +0200 Subject: [PATCH 11/26] No-op hooks --- cmd/gaia/app/app.go | 1 + x/slashing/hooks.go | 5 +++++ x/stake/keeper/keeper.go | 24 +++++++++++++++++------- x/stake/keeper/validator.go | 13 +++++++++++++ x/stake/types/validator.go | 5 +++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 4ce6b2806de7..ab7cccf712cd 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -96,6 +96,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) + // app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) // register message routes app.Router(). diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 7012b640f459..fe6c716a7527 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -27,6 +27,11 @@ type ValidatorHooks struct { k Keeper } +// Return a sdk.ValidatorHooks interface over the wrapper struct +func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { + return ValidatorHooks{k} +} + // Implements sdk.ValidatorHooks func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { v.k.onValidatorBonded(ctx, address) diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 187649c5f766..4af56aeeff28 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -10,9 +10,10 @@ import ( // keeper of the stake store type Keeper struct { - storeKey sdk.StoreKey - cdc *wire.Codec - coinKeeper bank.Keeper + storeKey sdk.StoreKey + cdc *wire.Codec + coinKeeper bank.Keeper + validatorHooks sdk.ValidatorHooks // codespace codespace sdk.CodespaceType @@ -20,14 +21,23 @@ type Keeper struct { func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ - storeKey: key, - cdc: cdc, - coinKeeper: ck, - codespace: codespace, + storeKey: key, + cdc: cdc, + coinKeeper: ck, + validatorHooks: nil, + codespace: codespace, } return keeper } +// Set the validator hooks +func (k Keeper) SetValidatorHooks(v sdk.ValidatorHooks) { + if k.validatorHooks != nil { + panic("cannot set validator hooks twice") + } + k.validatorHooks = v +} + //_________________________________________________________________________ // return the codespace diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index e933a6d2360a..1d789aca273e 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -591,6 +591,13 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // also remove from the Bonded types.Validators Store store.Delete(GetValidatorsBondedIndexKey(validator.Operator)) + + // call the unbond hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnValidatorUnbonded(ctx, validator.ValAddress()) + } + + // return updated validator return validator } @@ -617,6 +624,12 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI) + // call the bond hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnValidatorBonded(ctx, validator.ValAddress()) + } + + // return updated validator return validator } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index f8404b596363..bb1a6260f5e0 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -246,6 +246,11 @@ func (v Validator) Equal(c2 Validator) bool { v.LastBondedTokens.Equal(c2.LastBondedTokens) } +// return the TM validator address +func (v Validator) ValAddress() sdk.ValAddress { + return sdk.ValAddress(v.PubKey.Address()) +} + // constant used in flags to indicate that description field should not be updated const DoNotModifyDesc = "[do-not-modify]" From a0f706a8edfa982c916ea631d5ecf599899f8515 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 18:41:39 +0200 Subject: [PATCH 12/26] Real hooks --- cmd/gaia/app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index ab7cccf712cd..d05b56415638 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -96,7 +96,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - // app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) + app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) // register message routes app.Router(). From 35e89904518a7ce7a2cb469a66d3e8e31d363ad8 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 19:28:39 +0200 Subject: [PATCH 13/26] Fix iteration direction & duplicate key, update Gaia --- cmd/gaia/app/app.go | 4 ++-- x/slashing/keeper.go | 11 ++++++----- x/slashing/keeper_test.go | 2 ++ x/slashing/keys.go | 6 ++++++ x/slashing/slashing_period.go | 6 +++--- x/slashing/slashing_period_test.go | 8 ++++---- x/stake/keeper/keeper.go | 3 ++- 7 files changed, 25 insertions(+), 15 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index d05b56415638..e4bd9abf95c1 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -93,10 +93,10 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) + app.stakeKeeper = app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) - app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) // register message routes app.Router(). diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 6d8e47cbe29f..b8fe83ac0ec3 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -56,8 +56,13 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Double sign confirmed logger.Info(fmt.Sprintf("Confirmed double sign from %s at height %d, age of %d less than max age of %d", pubkey.Address(), infractionHeight, age, maxEvidenceAge)) + // Cap by slashing period + fraction := k.SlashFractionDoubleSign(ctx) + revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight) + logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction)) + // Slash validator - k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, k.SlashFractionDoubleSign(ctx)) + k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, revisedFraction) // Jail validator k.validatorSet.Jail(ctx, pubkey) @@ -169,7 +174,3 @@ func (k Keeper) deleteAddrPubkeyRelation(ctx sdk.Context, addr crypto.Address) { store := ctx.KVStore(k.storeKey) store.Delete(getAddrPubkeyRelationKey(addr)) } - -func getAddrPubkeyRelationKey(address []byte) []byte { - return append([]byte{0x03}, address...) -} diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 808c82014e16..a00fc7ee8737 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -24,6 +24,7 @@ func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) + sk = sk.SetValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -58,6 +59,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) + sk = sk.SetValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 27324afa87a0..15cfa5742059 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -13,6 +13,8 @@ var ( ValidatorSigningBitArrayKey = []byte{0x02} // Prefix for slashing period ValidatorSlashingPeriodKey = []byte{0x03} + // Prefix for address-pubkey relation + AddrPubkeyRelationKey = []byte{0x04} ) // Stored by *validator* address (not owner address) @@ -38,3 +40,7 @@ func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { binary.LittleEndian.PutUint64(b, uint64(startHeight)) return append(GetValidatorSlashingPeriodPrefix(v), b...) } + +func getAddrPubkeyRelationKey(address []byte) []byte { + return append(AddrPubkeyRelationKey, address...) +} diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 76de26ea7636..528120f0f2fc 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -28,9 +28,9 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // Stored by *validator* address (not owner address) func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) - start := GetValidatorSlashingPeriodKey(address, height) - end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodPrefix(address)) - iterator := store.Iterator(start, end) + start := GetValidatorSlashingPeriodPrefix(address) + end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodKey(address, height)) + iterator := store.ReverseIterator(start, end) if !iterator.Valid() { panic("expected to find slashing period, but none was found") } diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index 8714fc3be4d9..be09656d8d55 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -23,11 +23,11 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { // Get at start height retrieved := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) require.Equal(t, addr, retrieved.ValidatorAddr) - // Get before start height - retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(0)) + // Get after start height (works) + retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(6)) require.Equal(t, addr, retrieved.ValidatorAddr) - // Get after start height (panic) - require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(6)) }) + // Get before start height (panic) + require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(0)) }) // Get after end height (panic) newPeriod.EndHeight = int64(4) keeper.setValidatorSlashingPeriod(ctx, newPeriod) diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 4af56aeeff28..1d93ae2a7e52 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -31,11 +31,12 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk. } // Set the validator hooks -func (k Keeper) SetValidatorHooks(v sdk.ValidatorHooks) { +func (k Keeper) SetValidatorHooks(v sdk.ValidatorHooks) Keeper { if k.validatorHooks != nil { panic("cannot set validator hooks twice") } k.validatorHooks = v + return k } //_________________________________________________________________________ From 3534a990135bd7cedd5d42153625eea5a95e459d Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 19:46:18 +0200 Subject: [PATCH 14/26] Correctly simulate past validator set signatures --- x/mock/simulation/random_simulate_blocks.go | 53 +++++++++++---------- x/slashing/slashing_period.go | 4 +- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 5b1d4030c902..adeec4163deb 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -67,14 +67,16 @@ func SimulateFromSeed( header := abci.Header{Height: 0, Time: timestamp} opCount := 0 - request := abci.RequestBeginBlock{Header: header} - var pastTimes []time.Time + var pastSigningValidators [][]abci.SigningValidator + + request := RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header, log) for i := 0; i < numBlocks; i++ { // Log the header time for future lookup pastTimes = append(pastTimes, header.Time) + pastSigningValidators = append(pastSigningValidators, request.LastCommitInfo.Validators) // Run the BeginBlock handler app.BeginBlock(request) @@ -124,7 +126,7 @@ func SimulateFromSeed( } // Generate a random RequestBeginBlock with the current validator set for the next block - request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header, log) // Update the validator set validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) @@ -147,13 +149,12 @@ func getKeys(validators map[string]mockValidator) []string { // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, - pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { + pastTimes []time.Time, pastSigningValidators [][]abci.SigningValidator, event func(string), header abci.Header, log string) abci.RequestBeginBlock { if len(validators) == 0 { return abci.RequestBeginBlock{Header: header} } signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 - for _, key := range getKeys(validators) { mVal := validators[key] mVal.livenessState = livenessTransitions.NextState(r, mVal.livenessState) @@ -180,26 +181,30 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m i++ } evidence := make([]abci.Evidence, 0) - for r.Float64() < evidenceFraction { - height := header.Height - time := header.Time - if r.Float64() < pastEvidenceFraction { - height = int64(r.Intn(int(header.Height))) - time = pastTimes[height] - } - validator := signingValidators[r.Intn(len(signingValidators))].Validator - var currentTotalVotingPower int64 - for _, mVal := range validators { - currentTotalVotingPower += mVal.val.Power + // Anything but the first block + if len(pastTimes) > 0 { + for r.Float64() < evidenceFraction { + height := header.Height + time := header.Time + if r.Float64() < pastEvidenceFraction { + height = int64(r.Intn(int(header.Height))) + time = pastTimes[height] + } + past := pastSigningValidators[height] + validator := past[r.Intn(len(past))].Validator + var totalVotingPower int64 + for _, val := range past { + totalVotingPower += val.Validator.Power + } + evidence = append(evidence, abci.Evidence{ + Type: tmtypes.ABCIEvidenceTypeDuplicateVote, + Validator: validator, + Height: height, + Time: time, + TotalVotingPower: totalVotingPower, + }) + event("beginblock/evidence") } - evidence = append(evidence, abci.Evidence{ - Type: tmtypes.ABCIEvidenceTypeDuplicateVote, - Validator: validator, - Height: height, - Time: time, - TotalVotingPower: currentTotalVotingPower, - }) - event("beginblock/evidence") } return abci.RequestBeginBlock{ Header: header, diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 528120f0f2fc..0e5806aee97b 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -35,8 +35,8 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk panic("expected to find slashing period, but none was found") } slashingPeriod = k.unmarshalSlashingPeriodKeyValue(iterator.Key(), iterator.Value()) - if slashingPeriod.EndHeight < height { - panic("slashing period ended before infraction") + if slashingPeriod.EndHeight > 0 && slashingPeriod.EndHeight < height { + panic(fmt.Sprintf("slashing period ended before infraction: infraction height %d, slashing period ended at %d", height, slashingPeriod.EndHeight)) } return } From 111754a87ea88595336fe8b76b057ced92e56056 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 19:49:12 +0200 Subject: [PATCH 15/26] Tiny rename --- cmd/gaia/app/app.go | 2 +- x/slashing/keeper_test.go | 4 ++-- x/stake/keeper/keeper.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index e4bd9abf95c1..f1ca2a7b6630 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -94,7 +94,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - app.stakeKeeper = app.stakeKeeper.SetValidatorHooks(app.slashingKeeper.ValidatorHooks()) + app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index a00fc7ee8737..fd859b51c42e 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -24,7 +24,7 @@ func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.SetValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -59,7 +59,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.SetValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 1d93ae2a7e52..14c834387898 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -31,7 +31,7 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk. } // Set the validator hooks -func (k Keeper) SetValidatorHooks(v sdk.ValidatorHooks) Keeper { +func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper { if k.validatorHooks != nil { panic("cannot set validator hooks twice") } From 5071897df8acda384de95682c38fff2fc889f3b2 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 19:52:32 +0200 Subject: [PATCH 16/26] Update dep; 'make format' --- Gopkg.lock | 17 +++++++++-------- server/export_test.go | 14 +++++++------- server/mock/app.go | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 077050a8c2c2..1a5ed142250e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -95,12 +95,12 @@ version = "v0.3.0" [[projects]] - digest = "1:c4a2528ccbcabf90f9f3c464a5fc9e302d592861bbfd0b7135a7de8a943d0406" + digest = "1:586ea76dbd0374d6fb649a91d70d652b7fe0ccffb8910a77468e7702e7901f3d" name = "github.com/go-stack/stack" packages = ["."] pruneopts = "UT" - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" + revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a" + version = "v1.8.0" [[projects]] digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" @@ -164,13 +164,13 @@ version = "v1.2.0" [[projects]] - branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -179,7 +179,8 @@ "json/token", ] pruneopts = "UT" - revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" + revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241" + version = "v1.0.0" [[projects]] digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" @@ -545,14 +546,14 @@ [[projects]] branch = "master" - digest = "1:86171d21d59449dcf7cee0b7d2da83dff989dab9b9b69bfe0a3d59c3c1ca6081" + digest = "1:a32f75c7db4d919e5103b97e5b8bbe4c9d089be6d333a5ae750e8b3b1ee2051e" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "11551d06cbcc94edc80a0facaccbda56473c19c1" + revision = "4910a1d54f876d7b22162a85f4d066d3ee649450" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" diff --git a/server/export_test.go b/server/export_test.go index 358f72cf60fe..488c55bbf654 100644 --- a/server/export_test.go +++ b/server/export_test.go @@ -1,16 +1,16 @@ package server import ( - "testing" - "github.com/stretchr/testify/require" + "bytes" + "github.com/cosmos/cosmos-sdk/server/mock" "github.com/cosmos/cosmos-sdk/wire" - "github.com/tendermint/tendermint/libs/log" + "github.com/stretchr/testify/require" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" - "os" - "bytes" + "github.com/tendermint/tendermint/libs/log" "io" - "github.com/cosmos/cosmos-sdk/server/mock" - ) + "os" + "testing" +) func TestEmptyState(t *testing.T) { defer setupViper(t)() diff --git a/server/mock/app.go b/server/mock/app.go index eb2dfc3cc300..3c6ad3ec2798 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -129,7 +129,7 @@ func AppGenStateEmpty(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMess // Return a validator, not much else func AppGenTx(_ *wire.Codec, pk crypto.PubKey, genTxConfig gc.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { + appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { validator = tmtypes.GenesisValidator{ PubKey: pk, From d3ba71f7c8977a1869fb3ae190e8ac1a074b53a8 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 20:00:06 +0200 Subject: [PATCH 17/26] Add quick slashing period functionality test --- x/slashing/keeper_test.go | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index fd859b51c42e..23a15638d532 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -53,6 +53,58 @@ func TestHandleDoubleSign(t *testing.T) { require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) } +// Test that the amount a validator is slashed for multiple double signs +// is correctly capped by the slashing period in which they were committed +func TestSlashingPeriodCap(t *testing.T) { + + // initial setup + ctx, ck, sk, _, keeper := createTestInput(t) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + amtInt := int64(100) + addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + require.True(t, got.IsOK()) + validatorUpdates := stake.EndBlocker(ctx, sk) + keeper.AddValidators(ctx, validatorUpdates) + require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + + // handle a signature to set signing info + keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) + + // double sign less than max age + keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + + // should be jailed + require.True(t, sk.Validator(ctx, addr).GetJailed()) + // update block height + ctx = ctx.WithBlockHeight(int64(1)) + // unjail to measure power + sk.Unjail(ctx, val) + // power should be reduced + require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + + // double sign again, same slashing period + keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + // should be jailed + require.True(t, sk.Validator(ctx, addr).GetJailed()) + // update block height + ctx = ctx.WithBlockHeight(int64(2)) + // unjail to measure power + sk.Unjail(ctx, val) + // power should be equal, no more should have been slashed + require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + + // double sign again, new slashing period + keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt) + // should be jailed + require.True(t, sk.Validator(ctx, addr).GetJailed()) + // unjail to measure power + sk.Unjail(ctx, val) + // power should be reduced + require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) +} + // Test a validator through uptime, downtime, revocation, // unrevocation, starting height reset, and revocation again func TestHandleAbsentValidator(t *testing.T) { From 97cdfd865512ab3cc12ac1a8d4955be2e0ef6239 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 20:09:58 +0200 Subject: [PATCH 18/26] Additional unit tests --- x/slashing/slashing_period.go | 1 + x/slashing/slashing_period_test.go | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 0e5806aee97b..396cf83cb2fa 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -28,6 +28,7 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // Stored by *validator* address (not owner address) func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) + // Get the most recent slashing period at or before the infraction height start := GetValidatorSlashingPeriodPrefix(address) end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodKey(address, height)) iterator := store.ReverseIterator(start, end) diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index be09656d8d55..3e3edfaf54f2 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -22,16 +22,33 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { keeper.setValidatorSlashingPeriod(ctx, newPeriod) // Get at start height retrieved := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) - require.Equal(t, addr, retrieved.ValidatorAddr) + require.Equal(t, newPeriod, retrieved) // Get after start height (works) retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(6)) - require.Equal(t, addr, retrieved.ValidatorAddr) + require.Equal(t, newPeriod, retrieved) // Get before start height (panic) require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(0)) }) // Get after end height (panic) newPeriod.EndHeight = int64(4) keeper.setValidatorSlashingPeriod(ctx, newPeriod) require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) }) + // Back to old end height + newPeriod.EndHeight = height + 10 + keeper.setValidatorSlashingPeriod(ctx, newPeriod) + // Set a new, later period + anotherPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: addr, + StartHeight: height + 1, + EndHeight: height + 11, + SlashedSoFar: sdk.ZeroDec(), + } + keeper.setValidatorSlashingPeriod(ctx, anotherPeriod) + // Old period retrieved for prior height + retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) + require.Equal(t, newPeriod, retrieved) + // New period retrieved at new height + retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height+1) + require.Equal(t, anotherPeriod, retrieved) } func TestValidatorSlashingPeriodCap(t *testing.T) { @@ -52,4 +69,7 @@ func TestValidatorSlashingPeriodCap(t *testing.T) { // Second slash should be capped fractionB := keeper.capBySlashingPeriod(ctx, addr, half, height) require.True(t, fractionB.Equal(sdk.ZeroDec())) + // Third slash should be capped to difference + fractionC := keeper.capBySlashingPeriod(ctx, addr, sdk.OneDec(), height) + require.True(t, fractionC.Equal(half)) } From 527bbbd478361caa60535400e6ccec0eb581fc73 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 20:12:40 +0200 Subject: [PATCH 19/26] Use current validators when selected --- x/mock/simulation/random_simulate_blocks.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index adeec4163deb..05b1c8a734f1 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -186,14 +186,15 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m for r.Float64() < evidenceFraction { height := header.Height time := header.Time + vals := signingValidators if r.Float64() < pastEvidenceFraction { height = int64(r.Intn(int(header.Height))) time = pastTimes[height] + vals = pastSigningValidators[height] } - past := pastSigningValidators[height] - validator := past[r.Intn(len(past))].Validator + validator := vals[r.Intn(len(vals))].Validator var totalVotingPower int64 - for _, val := range past { + for _, val := range vals { totalVotingPower += val.Validator.Power } evidence = append(evidence, abci.Evidence{ From 6ed552a38c91c764d0dc54e747fd90ff520c5ab4 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 27 Aug 2018 20:19:50 +0200 Subject: [PATCH 20/26] Panic in the right place --- x/slashing/slashing_period.go | 10 +++++++--- x/slashing/slashing_period_test.go | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 396cf83cb2fa..a6971f211097 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -12,6 +12,13 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // Calculate total amount to be slashed slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, infractionHeight) + + // Sanity check + if slashingPeriod.EndHeight > 0 && slashingPeriod.EndHeight < infractionHeight { + panic(fmt.Sprintf("slashing period ended before infraction: infraction height %d, slashing period ended at %d", infractionHeight, slashingPeriod.EndHeight)) + } + + // Calculate the total slash amount totalToSlash := sdk.MaxDec(slashingPeriod.SlashedSoFar, fraction) // Calculate remainder @@ -36,9 +43,6 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk panic("expected to find slashing period, but none was found") } slashingPeriod = k.unmarshalSlashingPeriodKeyValue(iterator.Key(), iterator.Value()) - if slashingPeriod.EndHeight > 0 && slashingPeriod.EndHeight < height { - panic(fmt.Sprintf("slashing period ended before infraction: infraction height %d, slashing period ended at %d", height, slashingPeriod.EndHeight)) - } return } diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index 3e3edfaf54f2..2adc5b75a3e5 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -31,7 +31,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { // Get after end height (panic) newPeriod.EndHeight = int64(4) keeper.setValidatorSlashingPeriod(ctx, newPeriod) - require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) }) + require.Panics(t, func() { keeper.capBySlashingPeriod(ctx, addr, sdk.ZeroDec(), height) }) // Back to old end height newPeriod.EndHeight = height + 10 keeper.setValidatorSlashingPeriod(ctx, newPeriod) From d9ad52f39662bf9fe228948cee1426a667b2ec10 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 29 Aug 2018 14:15:16 +0200 Subject: [PATCH 21/26] Address @rigelrozanski comments --- types/stake.go | 6 +++++- x/slashing/hooks.go | 8 ++++---- x/slashing/keeper.go | 3 ++- x/slashing/keeper_test.go | 9 ++++++--- x/slashing/keys.go | 20 ++++++++------------ x/slashing/slashing_period.go | 22 ++++++++++++++-------- x/slashing/slashing_period_test.go | 11 +++++++++++ 7 files changed, 50 insertions(+), 29 deletions(-) diff --git a/types/stake.go b/types/stake.go index 7dd0c421c631..3224f00bcc82 100644 --- a/types/stake.go +++ b/types/stake.go @@ -97,7 +97,11 @@ type DelegationSet interface { } // validator event hooks +// These can be utilized to communicate between a staking keeper +// and another keeper which must take particular actions when +// validators are bonded and unbonded. The second keeper must implement +// this interface, which then the staking keeper can call. type ValidatorHooks interface { OnValidatorBonded(ctx Context, address ValAddress) // Must be called when a validator is bonded - OnValidatorUnbonded(ctx Context, address ValAddress) // Must be called when a validator is unbonded + OnValidatorUnbonded(ctx Context, address ValAddress) // Must be called when a validator begins unbonding } diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index fe6c716a7527..a2476f3fc496 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -15,7 +15,7 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { k.setValidatorSlashingPeriod(ctx, slashingPeriod) } -// Mark the slashing period as having ended when a validator is unbonded +// Mark the slashing period as having ended when a validator begins unbonding func (k Keeper) onValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, ctx.BlockHeight()) slashingPeriod.EndHeight = ctx.BlockHeight() @@ -27,6 +27,9 @@ type ValidatorHooks struct { k Keeper } +// Assert implementation +var _ sdk.ValidatorHooks = ValidatorHooks{} + // Return a sdk.ValidatorHooks interface over the wrapper struct func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} @@ -41,6 +44,3 @@ func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ValAddres func (v ValidatorHooks) OnValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { v.k.onValidatorUnbonded(ctx, address) } - -// Assert implementation -var _ sdk.ValidatorHooks = ValidatorHooks{} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index b8fe83ac0ec3..1bb857f7de96 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -56,7 +56,8 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Double sign confirmed logger.Info(fmt.Sprintf("Confirmed double sign from %s at height %d, age of %d less than max age of %d", pubkey.Address(), infractionHeight, age, maxEvidenceAge)) - // Cap by slashing period + // Cap the amount slashed to the penalty for the worst infraction + // within the slashing period when this infraction was committed fraction := k.SlashFractionDoubleSign(ctx) revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight) logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction)) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 23a15638d532..3c20663fb59b 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -82,7 +82,8 @@ func TestSlashingPeriodCap(t *testing.T) { // unjail to measure power sk.Unjail(ctx, val) // power should be reduced - require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) + require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, same slashing period keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) @@ -93,7 +94,8 @@ func TestSlashingPeriodCap(t *testing.T) { // unjail to measure power sk.Unjail(ctx, val) // power should be equal, no more should have been slashed - require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) + require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, new slashing period keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt) @@ -102,7 +104,8 @@ func TestSlashingPeriodCap(t *testing.T) { // unjail to measure power sk.Unjail(ctx, val) // power should be reduced - require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) + require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) } // Test a validator through uptime, downtime, revocation, diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 15cfa5742059..191a83b33477 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -7,34 +7,30 @@ import ( ) var ( - // Prefix for signing info - ValidatorSigningInfoKey = []byte{0x01} - // Prefix for signature bit array - ValidatorSigningBitArrayKey = []byte{0x02} - // Prefix for slashing period - ValidatorSlashingPeriodKey = []byte{0x03} - // Prefix for address-pubkey relation - AddrPubkeyRelationKey = []byte{0x04} + ValidatorSigningInfoKey = []byte{0x01} // Prefix for signing info + ValidatorSigningBitArrayKey = []byte{0x02} // Prefix for signature bit array + ValidatorSlashingPeriodKey = []byte{0x03} // Prefix for slashing period + AddrPubkeyRelationKey = []byte{0x04} // Prefix for address-pubkey relation ) -// Stored by *validator* address (not owner address) +// stored by *validator* address (not owner address) func GetValidatorSigningInfoKey(v sdk.ValAddress) []byte { return append(ValidatorSigningInfoKey, v.Bytes()...) } -// Stored by *validator* address (not owner address) +// stored by *validator* address (not owner address) func GetValidatorSigningBitArrayKey(v sdk.ValAddress, i int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(i)) return append(ValidatorSigningBitArrayKey, append(v.Bytes(), b...)...) } -// Stored by *validator* address (not owner address) +// stored by *validator* address (not owner address) func GetValidatorSlashingPeriodPrefix(v sdk.ValAddress) []byte { return append(ValidatorSlashingPeriodKey, v.Bytes()...) } -// Stored by *validator* address (not owner address) followed by start height +// stored by *validator* address (not owner address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(startHeight)) diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index a6971f211097..991fb455ae2a 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -10,7 +10,7 @@ import ( // Cap an infraction's slash amount by the slashing period in which it was committed func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fraction sdk.Dec, infractionHeight int64) (revisedFraction sdk.Dec) { - // Calculate total amount to be slashed + // Fetch the newest slashing period starting before this infraction was committed slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, infractionHeight) // Sanity check @@ -18,21 +18,24 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra panic(fmt.Sprintf("slashing period ended before infraction: infraction height %d, slashing period ended at %d", infractionHeight, slashingPeriod.EndHeight)) } - // Calculate the total slash amount + // Calculate the updated total slash amount + // This is capped at the slashing fraction for the worst infraction within this slashing period totalToSlash := sdk.MaxDec(slashingPeriod.SlashedSoFar, fraction) - // Calculate remainder + // Calculate the remainder which we now must slash revisedFraction = totalToSlash.Sub(slashingPeriod.SlashedSoFar) - // Update slashing period + // Update the slashing period struct slashingPeriod.SlashedSoFar = totalToSlash k.setValidatorSlashingPeriod(ctx, slashingPeriod) return - } -// Stored by *validator* address (not owner address) +// Stored by validator Tendermint address (not owner address) +// This function retrieves the most recent slashing period starting +// before a particular height - so the slashing period that was "in effect" +// at the time of an infraction committed at that height. func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) // Get the most recent slashing period at or before the infraction height @@ -46,7 +49,10 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk return } -// Stored by *validator* address (not owner address) +// Stored by validator Tendermint address (not owner address) +// This function sets a validator slashing period for a particular validator, +// start height, end height, and current slashed-so-far total, or updates +// an existing slashing period for the same validator and start height. func (k Keeper) setValidatorSlashingPeriod(ctx sdk.Context, slashingPeriod ValidatorSlashingPeriod) { slashingPeriodValue := ValidatorSlashingPeriodValue{ EndHeight: slashingPeriod.EndHeight, @@ -82,7 +88,7 @@ func NewValidatorSlashingPeriod(startHeight int64, endHeight int64, slashedSoFar // Slashing period for a validator type ValidatorSlashingPeriod struct { - ValidatorAddr sdk.ValAddress `json:"validator"` // validator which this slashing period is for + ValidatorAddr sdk.ValAddress `json:"validator_addr"` // validator which this slashing period is for StartHeight int64 `json:"start_height"` // starting height of the slashing period EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index 2adc5b75a3e5..f2c139ef5186 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -20,21 +20,27 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { SlashedSoFar: sdk.ZeroDec(), } keeper.setValidatorSlashingPeriod(ctx, newPeriod) + // Get at start height retrieved := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) require.Equal(t, newPeriod, retrieved) + // Get after start height (works) retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(6)) require.Equal(t, newPeriod, retrieved) + // Get before start height (panic) require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, int64(0)) }) + // Get after end height (panic) newPeriod.EndHeight = int64(4) keeper.setValidatorSlashingPeriod(ctx, newPeriod) require.Panics(t, func() { keeper.capBySlashingPeriod(ctx, addr, sdk.ZeroDec(), height) }) + // Back to old end height newPeriod.EndHeight = height + 10 keeper.setValidatorSlashingPeriod(ctx, newPeriod) + // Set a new, later period anotherPeriod := ValidatorSlashingPeriod{ ValidatorAddr: addr, @@ -43,9 +49,11 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { SlashedSoFar: sdk.ZeroDec(), } keeper.setValidatorSlashingPeriod(ctx, anotherPeriod) + // Old period retrieved for prior height retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) require.Equal(t, newPeriod, retrieved) + // New period retrieved at new height retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height+1) require.Equal(t, anotherPeriod, retrieved) @@ -63,12 +71,15 @@ func TestValidatorSlashingPeriodCap(t *testing.T) { } keeper.setValidatorSlashingPeriod(ctx, newPeriod) half := sdk.NewDec(1).Quo(sdk.NewDec(2)) + // First slash should be full fractionA := keeper.capBySlashingPeriod(ctx, addr, half, height) require.True(t, fractionA.Equal(half)) + // Second slash should be capped fractionB := keeper.capBySlashingPeriod(ctx, addr, half, height) require.True(t, fractionB.Equal(sdk.ZeroDec())) + // Third slash should be capped to difference fractionC := keeper.capBySlashingPeriod(ctx, addr, sdk.OneDec(), height) require.True(t, fractionC.Equal(half)) From 225cb34e4ce72fce1d178bb2ca9e8b89bff3c3c6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 29 Aug 2018 14:20:04 +0200 Subject: [PATCH 22/26] Fix linter errors --- x/slashing/keeper_test.go | 4 ++-- x/slashing/keys.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 3c20663fb59b..8c364b423187 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -94,7 +94,7 @@ func TestSlashingPeriodCap(t *testing.T) { // unjail to measure power sk.Unjail(ctx, val) // power should be equal, no more should have been slashed - expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) + expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, new slashing period @@ -104,7 +104,7 @@ func TestSlashingPeriodCap(t *testing.T) { // unjail to measure power sk.Unjail(ctx, val) // power should be reduced - expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) + expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) } diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 191a83b33477..3ebf02ddfcbf 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// key prefix bytes var ( ValidatorSigningInfoKey = []byte{0x01} // Prefix for signing info ValidatorSigningBitArrayKey = []byte{0x02} // Prefix for signature bit array From a349376e472f1b598f50cc7df0479fe9ff69a453 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 29 Aug 2018 14:41:16 +0200 Subject: [PATCH 23/26] Address @melekes suggestion --- x/slashing/hooks.go | 4 ++-- x/slashing/slashing_period.go | 4 ++-- x/slashing/slashing_period_test.go | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index a2476f3fc496..4122f9e8ee8f 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -12,14 +12,14 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { EndHeight: 0, SlashedSoFar: sdk.ZeroDec(), } - k.setValidatorSlashingPeriod(ctx, slashingPeriod) + k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) } // Mark the slashing period as having ended when a validator begins unbonding func (k Keeper) onValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, ctx.BlockHeight()) slashingPeriod.EndHeight = ctx.BlockHeight() - k.setValidatorSlashingPeriod(ctx, slashingPeriod) + k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) } // Wrapper struct for sdk.ValidatorHooks diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 991fb455ae2a..8ad8e3068952 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -27,7 +27,7 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // Update the slashing period struct slashingPeriod.SlashedSoFar = totalToSlash - k.setValidatorSlashingPeriod(ctx, slashingPeriod) + k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) return } @@ -53,7 +53,7 @@ func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk // This function sets a validator slashing period for a particular validator, // start height, end height, and current slashed-so-far total, or updates // an existing slashing period for the same validator and start height. -func (k Keeper) setValidatorSlashingPeriod(ctx sdk.Context, slashingPeriod ValidatorSlashingPeriod) { +func (k Keeper) addOrUpdateValidatorSlashingPeriod(ctx sdk.Context, slashingPeriod ValidatorSlashingPeriod) { slashingPeriodValue := ValidatorSlashingPeriodValue{ EndHeight: slashingPeriod.EndHeight, SlashedSoFar: slashingPeriod.SlashedSoFar, diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index f2c139ef5186..b3db42b9b23d 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -19,7 +19,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { EndHeight: height + 10, SlashedSoFar: sdk.ZeroDec(), } - keeper.setValidatorSlashingPeriod(ctx, newPeriod) + keeper.addOrUpdateValidatorSlashingPeriod(ctx, newPeriod) // Get at start height retrieved := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) @@ -34,12 +34,12 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { // Get after end height (panic) newPeriod.EndHeight = int64(4) - keeper.setValidatorSlashingPeriod(ctx, newPeriod) + keeper.addOrUpdateValidatorSlashingPeriod(ctx, newPeriod) require.Panics(t, func() { keeper.capBySlashingPeriod(ctx, addr, sdk.ZeroDec(), height) }) // Back to old end height newPeriod.EndHeight = height + 10 - keeper.setValidatorSlashingPeriod(ctx, newPeriod) + keeper.addOrUpdateValidatorSlashingPeriod(ctx, newPeriod) // Set a new, later period anotherPeriod := ValidatorSlashingPeriod{ @@ -48,7 +48,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { EndHeight: height + 11, SlashedSoFar: sdk.ZeroDec(), } - keeper.setValidatorSlashingPeriod(ctx, anotherPeriod) + keeper.addOrUpdateValidatorSlashingPeriod(ctx, anotherPeriod) // Old period retrieved for prior height retrieved = keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) @@ -69,7 +69,7 @@ func TestValidatorSlashingPeriodCap(t *testing.T) { EndHeight: height + 10, SlashedSoFar: sdk.ZeroDec(), } - keeper.setValidatorSlashingPeriod(ctx, newPeriod) + keeper.addOrUpdateValidatorSlashingPeriod(ctx, newPeriod) half := sdk.NewDec(1).Quo(sdk.NewDec(2)) // First slash should be full From 468aad6d4f87e66f297b950158acee79f15171d0 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 31 Aug 2018 15:28:41 +0200 Subject: [PATCH 24/26] Rename hook --- types/stake.go | 4 ++-- x/slashing/hooks.go | 6 +++--- x/slashing/hooks_test.go | 4 ++-- x/stake/keeper/validator.go | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/types/stake.go b/types/stake.go index 3224f00bcc82..9a22345676d6 100644 --- a/types/stake.go +++ b/types/stake.go @@ -102,6 +102,6 @@ type DelegationSet interface { // validators are bonded and unbonded. The second keeper must implement // this interface, which then the staking keeper can call. type ValidatorHooks interface { - OnValidatorBonded(ctx Context, address ValAddress) // Must be called when a validator is bonded - OnValidatorUnbonded(ctx Context, address ValAddress) // Must be called when a validator begins unbonding + OnValidatorBonded(ctx Context, address ValAddress) // Must be called when a validator is bonded + OnValidatorBeginUnbonding(ctx Context, address ValAddress) // Must be called when a validator begins unbonding } diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 4122f9e8ee8f..cfbe55567537 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -16,7 +16,7 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { } // Mark the slashing period as having ended when a validator begins unbonding -func (k Keeper) onValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { +func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ValAddress) { slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, ctx.BlockHeight()) slashingPeriod.EndHeight = ctx.BlockHeight() k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) @@ -41,6 +41,6 @@ func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ValAddres } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorUnbonded(ctx sdk.Context, address sdk.ValAddress) { - v.k.onValidatorUnbonded(ctx, address) +func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ValAddress) { + v.k.onValidatorBeginUnbonding(ctx, address) } diff --git a/x/slashing/hooks_test.go b/x/slashing/hooks_test.go index 0eafcfb52e70..cb0b0e00204f 100644 --- a/x/slashing/hooks_test.go +++ b/x/slashing/hooks_test.go @@ -16,11 +16,11 @@ func TestHookOnValidatorBonded(t *testing.T) { require.Equal(t, ValidatorSlashingPeriod{addr, ctx.BlockHeight(), 0, sdk.ZeroDec()}, period) } -func TestHookOnValidatorUnbonded(t *testing.T) { +func TestHookOnValidatorBeginUnbonding(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) addr := sdk.ValAddress(addrs[0]) keeper.onValidatorBonded(ctx, addr) - keeper.onValidatorUnbonded(ctx, addr) + keeper.onValidatorBeginUnbonding(ctx, addr) period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight()) require.Equal(t, ValidatorSlashingPeriod{addr, ctx.BlockHeight(), ctx.BlockHeight(), sdk.ZeroDec()}, period) } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 1d789aca273e..8fe5de705b58 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -594,7 +594,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // call the unbond hook if present if k.validatorHooks != nil { - k.validatorHooks.OnValidatorUnbonded(ctx, validator.ValAddress()) + k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ValAddress()) } // return updated validator From 05ede6cde6d18ff95f1913755602fe6e0c12bf50 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 31 Aug 2018 15:47:49 +0200 Subject: [PATCH 25/26] Update for new bech32 types --- types/stake.go | 4 ++-- x/slashing/app_test.go | 4 ++-- x/slashing/client/cli/query.go | 2 +- x/slashing/client/rest/query.go | 2 +- x/slashing/handler.go | 2 +- x/slashing/handler_test.go | 2 +- x/slashing/hooks.go | 8 ++++---- x/slashing/hooks_test.go | 4 ++-- x/slashing/keeper.go | 4 ++-- x/slashing/keeper_test.go | 20 ++++++++++---------- x/slashing/keys.go | 16 ++++++++-------- x/slashing/signing_info.go | 8 ++++---- x/slashing/signing_info_test.go | 12 ++++++------ x/slashing/slashing_period.go | 14 +++++++------- x/slashing/slashing_period_test.go | 4 ++-- x/slashing/test_common.go | 10 +++++----- x/slashing/tick_test.go | 4 ++-- x/stake/keeper/validator.go | 4 ++-- x/stake/types/validator.go | 4 ++-- 19 files changed, 64 insertions(+), 64 deletions(-) diff --git a/types/stake.go b/types/stake.go index 3fbb824d94ee..24274f3dbd76 100644 --- a/types/stake.go +++ b/types/stake.go @@ -102,6 +102,6 @@ type DelegationSet interface { // validators are bonded and unbonded. The second keeper must implement // this interface, which then the staking keeper can call. type ValidatorHooks interface { - OnValidatorBonded(ctx Context, address ValAddress) // Must be called when a validator is bonded - OnValidatorBeginUnbonding(ctx Context, address ValAddress) // Must be called when a validator begins unbonding + OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded + OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding } diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index f9ec0833fa15..0c3270139dce 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -79,7 +79,7 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper stake.Keeper, } func checkValidatorSigningInfo(t *testing.T, mapp *mock.App, keeper Keeper, - addr sdk.ValAddress, expFound bool) ValidatorSigningInfo { + addr sdk.ConsAddress, expFound bool) ValidatorSigningInfo { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) signingInfo, found := keeper.getValidatorSigningInfo(ctxCheck, addr) require.Equal(t, expFound, found) @@ -113,7 +113,7 @@ func TestSlashingMsgs(t *testing.T) { unjailMsg := MsgUnjail{ValidatorAddr: sdk.ValAddress(validator.PubKey.Address())} // no signing info yet - checkValidatorSigningInfo(t, mapp, keeper, sdk.ValAddress(addr1), false) + checkValidatorSigningInfo(t, mapp, keeper, sdk.ConsAddress(addr1), false) // unjail should fail with unknown validator res := mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{unjailMsg}, []int64{0}, []int64{1}, false, priv1) diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index 9f6d834dda06..87d0ad41d358 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -25,7 +25,7 @@ func GetCmdQuerySigningInfo(storeName string, cdc *wire.Codec) *cobra.Command { return err } - key := slashing.GetValidatorSigningInfoKey(sdk.ValAddress(pk.Address())) + key := slashing.GetValidatorSigningInfoKey(sdk.ConsAddress(pk.Address())) cliCtx := context.NewCLIContext().WithCodec(cdc) res, err := cliCtx.QueryStore(key, storeName) diff --git a/x/slashing/client/rest/query.go b/x/slashing/client/rest/query.go index 291679375b06..78c4a2d2f859 100644 --- a/x/slashing/client/rest/query.go +++ b/x/slashing/client/rest/query.go @@ -30,7 +30,7 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *wire return } - key := slashing.GetValidatorSigningInfoKey(sdk.ValAddress(pk.Address())) + key := slashing.GetValidatorSigningInfoKey(sdk.ConsAddress(pk.Address())) res, err := cliCtx.QueryStore(key, storeName) if err != nil { diff --git a/x/slashing/handler.go b/x/slashing/handler.go index d79ea73c2d3e..0531b714d1ad 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -30,7 +30,7 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorNotJailed(k.codespace).Result() } - addr := sdk.ValAddress(validator.GetPubKey().Address()) + addr := sdk.ConsAddress(validator.GetPubKey().Address()) // Signing info must exist info, found := k.getValidatorSigningInfo(ctx, addr) diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 8e3b719f4986..ea1a9ad58a61 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -19,7 +19,7 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { got := stake.NewHandler(sk)(ctx, msg) require.True(t, got.IsOK()) stake.EndBlocker(ctx, sk) - require.Equal(t, ck.GetCoins(ctx, 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, sdk.ValAddress(addr)).GetPower())) // assert non-jailed validator can't be unjailed diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index cfbe55567537..f5f3cc48c3d7 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -5,7 +5,7 @@ import ( ) // Create a new slashing period when a validator is bonded -func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { +func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { slashingPeriod := ValidatorSlashingPeriod{ ValidatorAddr: address, StartHeight: ctx.BlockHeight(), @@ -16,7 +16,7 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { } // Mark the slashing period as having ended when a validator begins unbonding -func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ValAddress) { +func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, ctx.BlockHeight()) slashingPeriod.EndHeight = ctx.BlockHeight() k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) @@ -36,11 +36,11 @@ func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ValAddress) { +func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { v.k.onValidatorBonded(ctx, address) } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ValAddress) { +func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { v.k.onValidatorBeginUnbonding(ctx, address) } diff --git a/x/slashing/hooks_test.go b/x/slashing/hooks_test.go index cb0b0e00204f..0731fd8f26fb 100644 --- a/x/slashing/hooks_test.go +++ b/x/slashing/hooks_test.go @@ -10,7 +10,7 @@ import ( func TestHookOnValidatorBonded(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - addr := sdk.ValAddress(addrs[0]) + addr := sdk.ConsAddress(addrs[0]) keeper.onValidatorBonded(ctx, addr) period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight()) require.Equal(t, ValidatorSlashingPeriod{addr, ctx.BlockHeight(), 0, sdk.ZeroDec()}, period) @@ -18,7 +18,7 @@ func TestHookOnValidatorBonded(t *testing.T) { func TestHookOnValidatorBeginUnbonding(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - addr := sdk.ValAddress(addrs[0]) + addr := sdk.ConsAddress(addrs[0]) keeper.onValidatorBonded(ctx, addr) keeper.onValidatorBeginUnbonding(ctx, addr) period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight()) diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 1bb857f7de96..272516585765 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -40,7 +40,7 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio logger := ctx.Logger().With("module", "x/slashing") time := ctx.BlockHeader().Time age := time.Sub(timestamp) - address := sdk.ValAddress(addr) + address := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { panic(fmt.Sprintf("Validator address %v not found", addr)) @@ -82,7 +82,7 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { logger := ctx.Logger().With("module", "x/slashing") height := ctx.BlockHeight() - address := sdk.ValAddress(addr) + address := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { panic(fmt.Sprintf("Validator address %v not found", addr)) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 0b691d7fa46c..af15bc2b288c 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) { require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) - require.Equal(t, ck.GetCoins(ctx, 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, sdk.ValAddress(addr)).GetPower())) // handle a signature to set signing info @@ -72,7 +72,7 @@ func TestSlashingPeriodCap(t *testing.T) { require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) - require.Equal(t, ck.GetCoins(ctx, 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())) // handle a signature to set signing info @@ -129,9 +129,9 @@ func TestHandleAbsentValidator(t *testing.T) { require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) - require.Equal(t, ck.GetCoins(ctx, 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, sdk.ValAddress(addr)).GetPower())) - info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.False(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, int64(0), info.IndexOffset) @@ -146,7 +146,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) } - info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, keeper.SignedBlocksWindow(ctx), info.SignedBlocksCounter) @@ -156,7 +156,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) } - info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) @@ -170,7 +170,7 @@ func TestHandleAbsentValidator(t *testing.T) { // 501st block missed ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) - info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) @@ -198,7 +198,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64()) // validator start height should have been changed - info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, height, info.StartHeight) require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) @@ -239,7 +239,7 @@ func TestHandleNewValidator(t *testing.T) { require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) - require.Equal(t, ck.GetCoins(ctx, 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, sdk.ValAddress(addr)).GetPower()) // 1000 first blocks not a validator @@ -250,7 +250,7 @@ func TestHandleNewValidator(t *testing.T) { ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 2) keeper.handleValidatorSignature(ctx, val.Address(), 100, false) - info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) + info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(keeper.SignedBlocksWindow(ctx)+1), info.StartHeight) require.Equal(t, int64(2), info.IndexOffset) diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 3ebf02ddfcbf..2af9e069a13c 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -14,25 +14,25 @@ var ( AddrPubkeyRelationKey = []byte{0x04} // Prefix for address-pubkey relation ) -// stored by *validator* address (not owner address) -func GetValidatorSigningInfoKey(v sdk.ValAddress) []byte { +// stored by *Tendermint* address (not owner address) +func GetValidatorSigningInfoKey(v sdk.ConsAddress) []byte { return append(ValidatorSigningInfoKey, v.Bytes()...) } -// stored by *validator* address (not owner address) -func GetValidatorSigningBitArrayKey(v sdk.ValAddress, i int64) []byte { +// stored by *Tendermint* address (not owner address) +func GetValidatorSigningBitArrayKey(v sdk.ConsAddress, i int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(i)) return append(ValidatorSigningBitArrayKey, append(v.Bytes(), b...)...) } -// stored by *validator* address (not owner address) -func GetValidatorSlashingPeriodPrefix(v sdk.ValAddress) []byte { +// stored by *Tendermint* address (not owner address) +func GetValidatorSlashingPeriodPrefix(v sdk.ConsAddress) []byte { return append(ValidatorSlashingPeriodKey, v.Bytes()...) } -// stored by *validator* address (not owner address) followed by start height -func GetValidatorSlashingPeriodKey(v sdk.ValAddress, startHeight int64) []byte { +// stored by *Tendermint* address (not owner address) followed by start height +func GetValidatorSlashingPeriodKey(v sdk.ConsAddress, startHeight int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(startHeight)) return append(GetValidatorSlashingPeriodPrefix(v), b...) diff --git a/x/slashing/signing_info.go b/x/slashing/signing_info.go index 9edd9910f38a..e76fea53f2d1 100644 --- a/x/slashing/signing_info.go +++ b/x/slashing/signing_info.go @@ -8,7 +8,7 @@ import ( ) // Stored by *validator* address (not owner address) -func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ValAddress) (info ValidatorSigningInfo, found bool) { +func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info ValidatorSigningInfo, found bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(GetValidatorSigningInfoKey(address)) if bz == nil { @@ -21,14 +21,14 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.ValAddress) } // Stored by *validator* address (not owner address) -func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ValAddress, info ValidatorSigningInfo) { +func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info ValidatorSigningInfo) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(info) store.Set(GetValidatorSigningInfoKey(address), bz) } // Stored by *validator* address (not owner address) -func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.ValAddress, index int64) (signed bool) { +func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64) (signed bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(GetValidatorSigningBitArrayKey(address, index)) if bz == nil { @@ -41,7 +41,7 @@ func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.ValAddr } // Stored by *validator* address (not owner address) -func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.ValAddress, index int64, signed bool) { +func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, signed bool) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(signed) store.Set(GetValidatorSigningBitArrayKey(address, index), bz) diff --git a/x/slashing/signing_info_test.go b/x/slashing/signing_info_test.go index f92c43581b5a..7aff0da95f1b 100644 --- a/x/slashing/signing_info_test.go +++ b/x/slashing/signing_info_test.go @@ -11,7 +11,7 @@ import ( func TestGetSetValidatorSigningInfo(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(addrs[0])) + info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0])) require.False(t, found) newInfo := ValidatorSigningInfo{ StartHeight: int64(4), @@ -19,8 +19,8 @@ func TestGetSetValidatorSigningInfo(t *testing.T) { JailedUntil: time.Unix(2, 0), SignedBlocksCounter: int64(10), } - keeper.setValidatorSigningInfo(ctx, sdk.ValAddress(addrs[0]), newInfo) - info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(addrs[0])) + keeper.setValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0]), newInfo) + info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0])) require.True(t, found) require.Equal(t, info.StartHeight, int64(4)) require.Equal(t, info.IndexOffset, int64(3)) @@ -30,9 +30,9 @@ func TestGetSetValidatorSigningInfo(t *testing.T) { func TestGetSetValidatorSigningBitArray(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - signed := keeper.getValidatorSigningBitArray(ctx, sdk.ValAddress(addrs[0]), 0) + signed := keeper.getValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0) require.False(t, signed) // treat empty key as unsigned - keeper.setValidatorSigningBitArray(ctx, sdk.ValAddress(addrs[0]), 0, true) - signed = keeper.getValidatorSigningBitArray(ctx, sdk.ValAddress(addrs[0]), 0) + keeper.setValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0, true) + signed = keeper.getValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0) require.True(t, signed) // now should be signed } diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 8ad8e3068952..61d25071eb80 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -8,7 +8,7 @@ import ( ) // Cap an infraction's slash amount by the slashing period in which it was committed -func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fraction sdk.Dec, infractionHeight int64) (revisedFraction sdk.Dec) { +func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ConsAddress, fraction sdk.Dec, infractionHeight int64) (revisedFraction sdk.Dec) { // Fetch the newest slashing period starting before this infraction was committed slashingPeriod := k.getValidatorSlashingPeriodForHeight(ctx, address, infractionHeight) @@ -36,7 +36,7 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ValAddress, fra // This function retrieves the most recent slashing period starting // before a particular height - so the slashing period that was "in effect" // at the time of an infraction committed at that height. -func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ValAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { +func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ConsAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) // Get the most recent slashing period at or before the infraction height start := GetValidatorSlashingPeriodPrefix(address) @@ -67,7 +67,7 @@ func (k Keeper) addOrUpdateValidatorSlashingPeriod(ctx sdk.Context, slashingPeri func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) ValidatorSlashingPeriod { var slashingPeriodValue ValidatorSlashingPeriodValue k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) - address := sdk.ValAddress(key[1 : 1+sdk.AddrLen]) + address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen]) startHeight := int64(binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) return ValidatorSlashingPeriod{ ValidatorAddr: address, @@ -88,10 +88,10 @@ func NewValidatorSlashingPeriod(startHeight int64, endHeight int64, slashedSoFar // Slashing period for a validator type ValidatorSlashingPeriod struct { - ValidatorAddr sdk.ValAddress `json:"validator_addr"` // validator which this slashing period is for - StartHeight int64 `json:"start_height"` // starting height of the slashing period - EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress - SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period + ValidatorAddr sdk.ConsAddress `json:"validator_addr"` // validator which this slashing period is for + StartHeight int64 `json:"start_height"` // starting height of the slashing period + EndHeight int64 `json:"end_height"` // ending height of the slashing period, or sentinel value of 0 for in-progress + SlashedSoFar sdk.Dec `json:"slashed_so_far"` // fraction of validator stake slashed so far in this slashing period } // Value part of slashing period (validator address & start height are stored in the key) diff --git a/x/slashing/slashing_period_test.go b/x/slashing/slashing_period_test.go index b3db42b9b23d..54157bb9cc0e 100644 --- a/x/slashing/slashing_period_test.go +++ b/x/slashing/slashing_period_test.go @@ -10,7 +10,7 @@ import ( func TestGetSetValidatorSlashingPeriod(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - addr := sdk.ValAddress(addrs[0]) + addr := sdk.ConsAddress(addrs[0]) height := int64(5) require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) }) newPeriod := ValidatorSlashingPeriod{ @@ -61,7 +61,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) { func TestValidatorSlashingPeriodCap(t *testing.T) { ctx, _, _, _, keeper := createTestInput(t) - addr := sdk.ValAddress(addrs[0]) + addr := sdk.ConsAddress(addrs[0]) height := int64(5) newPeriod := ValidatorSlashingPeriod{ ValidatorAddr: addr, diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 1053823786c2..82af340f76ca 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -30,10 +30,10 @@ var ( newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB51"), newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB52"), } - addrs = []sdk.AccAddress{ - sdk.AccAddress(pks[0].Address()), - sdk.AccAddress(pks[1].Address()), - sdk.AccAddress(pks[2].Address()), + addrs = []sdk.ValAddress{ + sdk.ValAddress(pks[0].Address()), + sdk.ValAddress(pks[1].Address()), + sdk.ValAddress(pks[2].Address()), } initCoins = sdk.NewInt(200) ) @@ -75,7 +75,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para require.Nil(t, err) for _, addr := range addrs { - _, _, err = ck.AddCoins(ctx, addr, sdk.Coins{ + _, _, err = ck.AddCoins(ctx, sdk.AccAddress(addr), sdk.Coins{ {sk.GetParams(ctx).BondDenom, initCoins}, }) } diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 9eb956e6710a..40705cf515b1 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -21,7 +21,7 @@ func TestBeginBlocker(t *testing.T) { require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) - require.Equal(t, ck.GetCoins(ctx, 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, sdk.ValAddress(addr)).GetPower())) val := abci.Validator{ @@ -40,7 +40,7 @@ func TestBeginBlocker(t *testing.T) { } BeginBlocker(ctx, req, keeper) - info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(pk.Address())) + info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(pk.Address())) require.True(t, found) require.Equal(t, ctx.BlockHeight(), info.StartHeight) require.Equal(t, int64(1), info.IndexOffset) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index e7f2d07c32ff..0ea24e639672 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -594,7 +594,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // call the unbond hook if present if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ValAddress()) + k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) } // return updated validator @@ -626,7 +626,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // call the bond hook if present if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBonded(ctx, validator.ValAddress()) + k.validatorHooks.OnValidatorBonded(ctx, validator.ConsAddress()) } // return updated validator diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index aa45ac4873a8..6a53965ca859 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -247,8 +247,8 @@ func (v Validator) Equal(c2 Validator) bool { } // return the TM validator address -func (v Validator) ValAddress() sdk.ValAddress { - return sdk.ValAddress(v.PubKey.Address()) +func (v Validator) ConsAddress() sdk.ConsAddress { + return sdk.ConsAddress(v.PubKey.Address()) } // constant used in flags to indicate that description field should not be updated From c257ac841ccd7e8abcdc9c7b58abf2e1fad81228 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 31 Aug 2018 15:51:13 +0200 Subject: [PATCH 26/26] 'make format' --- server/tm_cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/tm_cmds.go b/server/tm_cmds.go index b6daf0775320..bf208a5becdf 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -7,11 +7,11 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" "github.com/tendermint/tendermint/p2p" pvm "github.com/tendermint/tendermint/privval" - "github.com/cosmos/cosmos-sdk/client" ) // ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout