From 77a0041f54ffd0090fe8b814e16b6a9a443df7c6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 11 Sep 2018 18:26:10 +0800 Subject: [PATCH 1/2] Work in progress --- Makefile | 2 +- x/slashing/keys.go | 2 +- x/slashing/slashing_period.go | 21 ++++++++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 88ead03e6a99..95affa4edca6 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ test_sim_gaia_nondeterminism: test_sim_gaia_fast: @echo "Running quick Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take awhile!" diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 1f84a285dd7c..5cd3dfbfa5a0 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -34,7 +34,7 @@ func GetValidatorSlashingPeriodPrefix(v sdk.ConsAddress) []byte { // stored by *Tendermint* address (not operator address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ConsAddress, startHeight int64) []byte { b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(startHeight)) + binary.LittleEndian.PutUint64(b, ^uint64(startHeight)) // Newest-first, invert the height return append(GetValidatorSlashingPeriodPrefix(v), b...) } diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index fc57e663ae4a..0474042562c8 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -15,7 +15,7 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ConsAddress, fr // 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)) + panic(fmt.Sprintf("slashing period ended before infraction: validator %s, infraction height %d, slashing period ended at %d", address, infractionHeight, slashingPeriod.EndHeight)) } // Calculate the updated total slash amount @@ -38,12 +38,22 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ConsAddress, fr // at the time of an infraction committed at that height. func (k Keeper) getValidatorSlashingPeriodForHeight(ctx sdk.Context, address sdk.ConsAddress, height int64) (slashingPeriod ValidatorSlashingPeriod) { store := ctx.KVStore(k.storeKey) + // TODO + itr := store.Prefix(ValidatorSlashingPeriodKey).Iterator(nil, nil) + for itr.Valid() { + fmt.Printf("Key: %X\n", itr.Key()) + period := k.unmarshalSlashingPeriodKeyValue(itr.Key(), itr.Value()) + fmt.Printf("Key: %X, period: %v\n", itr.Key(), period) + itr.Next() + } + // TODO // Get the most recent slashing period at or before the infraction height - start := GetValidatorSlashingPeriodPrefix(address) + start := GetValidatorSlashingPeriodKey(address, height) end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodKey(address, height)) - iterator := store.ReverseIterator(start, end) + fmt.Printf("start: %X, end: %X\n", start, end) + iterator := store.Iterator(start, end) if !iterator.Valid() { - panic("expected to find slashing period, but none was found") + panic(fmt.Sprintf("expected to find slashing period for validator %s before height %d, but none was found", address, height)) } slashingPeriod = k.unmarshalSlashingPeriodKeyValue(iterator.Key(), iterator.Value()) return @@ -60,6 +70,7 @@ func (k Keeper) addOrUpdateValidatorSlashingPeriod(ctx sdk.Context, slashingPeri } store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(slashingPeriodValue) + fmt.Printf("Set slashing period for validator: %s\n", slashingPeriod.ValidatorAddr) store.Set(GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), bz) } @@ -68,7 +79,7 @@ func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) Valida var slashingPeriodValue ValidatorSlashingPeriodValue k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen]) - startHeight := int64(binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) + startHeight := int64(^binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) return ValidatorSlashingPeriod{ ValidatorAddr: address, StartHeight: startHeight, From af1cb43da8aaddc849fd408972c2ee2f3f13dd43 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 12 Sep 2018 00:33:52 +0800 Subject: [PATCH 2/2] Isolate iteration issue --- types/store.go | 24 ++++++++++++++++++++++++ x/slashing/keys.go | 2 +- x/slashing/slashing_period.go | 21 +++++++++++---------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/types/store.go b/types/store.go index e895b24c94d8..4aa195d9851f 100644 --- a/types/store.go +++ b/types/store.go @@ -306,6 +306,30 @@ func PrefixEndBytes(prefix []byte) []byte { return end } +// PrefixStartBytes returns the []byte that would start a +// range query for all []byte with a certain prefix +func PrefixStartBytes(prefix []byte) []byte { + if prefix == nil { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + + for { + if end[len(end)-1] != byte(0) { + end[len(end)-1]-- + break + } else { + end = end[:len(end)-1] + if len(end) == 0 { + panic("could not subtract") + } + } + } + return end +} + // TransientStoreKey is used for indexing transient stores in a MultiStore type TransientStoreKey struct { name string diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 5cd3dfbfa5a0..1f84a285dd7c 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -34,7 +34,7 @@ func GetValidatorSlashingPeriodPrefix(v sdk.ConsAddress) []byte { // stored by *Tendermint* address (not operator address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ConsAddress, startHeight int64) []byte { b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, ^uint64(startHeight)) // Newest-first, invert the height + binary.LittleEndian.PutUint64(b, uint64(startHeight)) return append(GetValidatorSlashingPeriodPrefix(v), b...) } diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 0474042562c8..44e5a6242d41 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -1,6 +1,7 @@ package slashing import ( + "bytes" "encoding/binary" "fmt" @@ -38,20 +39,20 @@ func (k Keeper) capBySlashingPeriod(ctx sdk.Context, address sdk.ConsAddress, fr // at the time of an infraction committed at that height. 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) + end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodKey(address, height)) + fmt.Printf("start: %X, end: %X, diff: %v\n", start, end, bytes.Compare(start, end)) // TODO - itr := store.Prefix(ValidatorSlashingPeriodKey).Iterator(nil, nil) + itr := sdk.KVStorePrefixIterator(store, GetValidatorSlashingPeriodPrefix(address)) for itr.Valid() { fmt.Printf("Key: %X\n", itr.Key()) period := k.unmarshalSlashingPeriodKeyValue(itr.Key(), itr.Value()) - fmt.Printf("Key: %X, period: %v\n", itr.Key(), period) + fmt.Printf("Found %X => %v\n", address, period) itr.Next() } - // TODO - // Get the most recent slashing period at or before the infraction height - start := GetValidatorSlashingPeriodKey(address, height) - end := sdk.PrefixEndBytes(GetValidatorSlashingPeriodKey(address, height)) - fmt.Printf("start: %X, end: %X\n", start, end) - iterator := store.Iterator(start, end) + // END TODO + iterator := store.ReverseIterator(start, end) if !iterator.Valid() { panic(fmt.Sprintf("expected to find slashing period for validator %s before height %d, but none was found", address, height)) } @@ -70,7 +71,7 @@ func (k Keeper) addOrUpdateValidatorSlashingPeriod(ctx sdk.Context, slashingPeri } store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshalBinary(slashingPeriodValue) - fmt.Printf("Set slashing period for validator: %s\n", slashingPeriod.ValidatorAddr) + fmt.Printf("Set slashing period for validator: %X => %s\n", GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), slashingPeriod.ValidatorAddr) store.Set(GetValidatorSlashingPeriodKey(slashingPeriod.ValidatorAddr, slashingPeriod.StartHeight), bz) } @@ -79,7 +80,7 @@ func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) Valida var slashingPeriodValue ValidatorSlashingPeriodValue k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen]) - startHeight := int64(^binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) + startHeight := int64(binary.LittleEndian.Uint64(key[1+sdk.AddrLen : 1+sdk.AddrLen+8])) return ValidatorSlashingPeriod{ ValidatorAddr: address, StartHeight: startHeight,