Upgrade to tm version 23.0. (#1927)

* Start upgrade. Currently go test ./... hangs.

* (squash this) Fix staking tests

* wip

* note what changes need to be made to make this work on tm v0.23.0

* Fix addr -> pubkey map

* cleanup code

* Fix slashing test failures except for begin blocker

* fix all slashing tests

* fix lcd tests

* Address PR comments

* add link to changelog.

* (wip) start making addrToPubkey map persisted. Since amino can't handle maps,
we have to change from what this commit is doing.

* Use the correct method of storing a map

* (squash this) address PR comments

* Did you run 'make'?

* remove gaiadebug binary
This commit is contained in:
Dev Ojha 2018-08-12 02:33:48 -05:00 committed by Ethan Buchman
parent 691048c88a
commit b2a4aecc44
42 changed files with 260 additions and 166 deletions

18
Gopkg.lock generated
View File

@ -423,7 +423,7 @@
version = "v0.9.2"
[[projects]]
digest = "1:eb0f8bee357e6c28c9ad5fa074545b5085d0dcf580ba0e7024ab8c3285a5c815"
digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -486,8 +486,8 @@
"version",
]
pruneopts = "UT"
revision = "d542d2c3945116697f60451e6a407082c41c3cc9"
version = "v0.22.8"
revision = "013b9cef642f875634c614019ab13b17570778ad"
version = "v0.23.0"
[[projects]]
digest = "1:5bd938386bd1f61a581bf8cd6ff2b7b2f79c542929176db4ceb44965440dae07"
@ -498,11 +498,14 @@
[[projects]]
branch = "master"
digest = "1:65a21a9e051d54eb6a3f70c659a765f706a998d9287c302269f4ed8054b2a852"
digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5"
name = "golang.org/x/crypto"
packages = [
"blowfish",
"chacha20poly1305",
"curve25519",
"hkdf",
"internal/chacha20",
"internal/subtle",
"nacl/box",
"nacl/secretbox",
@ -534,9 +537,12 @@
[[projects]]
branch = "master"
digest = "1:4d7a8265af700258feaff86722049eb5b787240d66dfaf45ff4962f09de6e0be"
digest = "1:4d64ef38a30b73db6e8e7a2824b7fd356d921e0ee3fdd3248658996821d3b47d"
name = "golang.org/x/sys"
packages = ["unix"]
packages = [
"cpu",
"unix",
]
pruneopts = "UT"
revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945"

View File

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

View File

@ -1,3 +1,10 @@
## v0.24.0 PENDING
^--- PENDING wasn't purged on sdk v0.23.0 release.
BREAKING CHANGES
* Update to tendermint v0.23.0. This involves removing crypto.Pubkey,
maintaining a validator address to pubkey map, and using time.Time instead of int64 for time. [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927)
## PENDING
BREAKING CHANGES

View File

@ -387,7 +387,8 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
}
// set the signed validators for addition to context in deliverTx
app.signedValidators = req.Validators
// TODO: communicate this result to the address to pubkey map in slashing
app.signedValidators = req.LastCommitInfo.GetValidators()
return
}
@ -412,11 +413,7 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
Log: result.Log,
GasWanted: result.GasWanted,
GasUsed: result.GasUsed,
Fee: cmn.KI64Pair{
[]byte(result.FeeDenom),
result.FeeAmount,
},
Tags: result.Tags,
Tags: result.Tags,
}
}

View File

@ -6,6 +6,7 @@ import (
"net/http"
"regexp"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/client/tx"
@ -564,7 +565,7 @@ func TestUnrevoke(t *testing.T) {
signingInfo := getSigningInfo(t, port, pkString)
tests.WaitForHeight(4, port)
require.Equal(t, true, signingInfo.IndexOffset > 0)
require.Equal(t, int64(0), signingInfo.JailedUntil)
require.Equal(t, time.Unix(0, 0).UTC(), signingInfo.JailedUntil)
require.Equal(t, true, signingInfo.SignedBlocksCounter > 0)
}

View File

@ -223,7 +223,7 @@ func startTM(
proxy.NewLocalClientCreator(app),
genDocProvider,
dbProvider,
nm.DefaultMetricsProvider,
nm.DefaultMetricsProvider(tmcfg.Instrumentation),
logger.With("module", "node"),
)
if err != nil {

View File

@ -44,5 +44,5 @@ func SignTxRequstHandler(w http.ResponseWriter, r *http.Request) {
return
}
w.Write(sig.Bytes())
w.Write(sig)
}

View File

@ -148,7 +148,8 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
tags := gov.EndBlocker(ctx, app.govKeeper)
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
// Add these new validators to the addr -> pubkey map.
app.slashingKeeper.AddValidators(ctx, validatorUpdates)
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,
@ -181,6 +182,9 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
// return sdk.ErrGenesisParse("").TraceCause(err, "")
}
// load the address to pubkey map
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData)
gov.InitGenesis(ctx, app.govKeeper, gov.DefaultGenesisState())
return abci.ResponseInitChain{

Binary file not shown.

View File

@ -15,12 +15,14 @@ type byter interface {
Bytes() []byte
}
func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) {
func checkAminoBinary(t *testing.T, src, dst interface{}, size int) {
// Marshal to binary bytes.
bz, err := cdc.MarshalBinaryBare(src)
require.Nil(t, err, "%+v", err)
// Make sure this is compatible with current (Bytes()) encoding.
require.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch")
if byterSrc, ok := src.(byter); ok {
// Make sure this is compatible with current (Bytes()) encoding.
require.Equal(t, byterSrc.Bytes(), bz, "Amino binary vs Bytes() mismatch")
}
// Make sure we have the expected length.
if size != -1 {
require.Equal(t, size, len(bz), "Amino binary size mismatch")
@ -55,8 +57,6 @@ func ExamplePrintRegisteredTypes() {
//| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | |
//| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | |
//| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | |
//| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | |
//| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | |
}
func TestKeyEncodings(t *testing.T) {
@ -86,13 +86,11 @@ func TestKeyEncodings(t *testing.T) {
require.EqualValues(t, tc.privKey, priv3)
// Check (de/en)codings of Signatures.
var sig1, sig2, sig3 tcrypto.Signature
var sig1, sig2 []byte
sig1, err := tc.privKey.Sign([]byte("something"))
require.NoError(t, err)
checkAminoBinary(t, sig1, &sig2, -1) // Signature size changes for Secp anyways.
require.EqualValues(t, sig1, sig2)
checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes.
require.EqualValues(t, sig1, sig3)
// Check (de/en)codings of PubKeys.
pubKey := tc.privKey.PubKey()
@ -107,7 +105,7 @@ func TestKeyEncodings(t *testing.T) {
func TestNilEncodings(t *testing.T) {
// Check nil Signature.
var a, b tcrypto.Signature
var a, b []byte
checkAminoJSON(t, &a, &b, true)
require.EqualValues(t, a, b)

View File

@ -199,7 +199,7 @@ func (kb dbKeybase) Get(name string) (Info, error) {
// Sign signs the msg with the named key.
// It returns an error if the key doesn't exist or the decryption fails.
func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig tmcrypto.Signature, pub tmcrypto.PubKey, err error) {
func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub tmcrypto.PubKey, err error) {
info, err := kb.Get(name)
if err != nil {
return

View File

@ -146,7 +146,7 @@ func TestSignVerify(t *testing.T) {
cases := []struct {
key crypto.PubKey
data []byte
sig crypto.Signature
sig []byte
valid bool
}{
// proper matches

View File

@ -16,7 +16,7 @@ type Keybase interface {
Delete(name, passphrase string) error
// Sign some bytes, looking up the private key to use
Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error)
Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error)
// CreateMnemonic creates a new mnemonic, and derives a hierarchical deterministic
// key from that.

View File

@ -114,7 +114,7 @@ func (pkl PrivKeyLedgerSecp256k1) Equals(other tmcrypto.PrivKey) bool {
// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, returning
// an error, so this should only trigger if the private key is held in memory
// for a while before use.
func (pkl PrivKeyLedgerSecp256k1) Sign(msg []byte) (tmcrypto.Signature, error) {
func (pkl PrivKeyLedgerSecp256k1) Sign(msg []byte) ([]byte, error) {
sig, err := pkl.signLedgerSecp256k1(msg)
if err != nil {
return nil, err
@ -135,13 +135,8 @@ func (pkl PrivKeyLedgerSecp256k1) getPubKey() (key tmcrypto.PubKey, err error) {
return key, err
}
func (pkl PrivKeyLedgerSecp256k1) signLedgerSecp256k1(msg []byte) (tmcrypto.Signature, error) {
sigBytes, err := pkl.ledger.SignSECP256K1(pkl.Path, msg)
if err != nil {
return nil, err
}
return tmsecp256k1.SignatureSecp256k1FromBytes(sigBytes), nil
func (pkl PrivKeyLedgerSecp256k1) signLedgerSecp256k1(msg []byte) ([]byte, error) {
return pkl.ledger.SignSECP256K1(pkl.Path, msg)
}
func (pkl PrivKeyLedgerSecp256k1) pubkeyLedgerSecp256k1() (pub tmcrypto.PubKey, err error) {

View File

@ -150,7 +150,7 @@ func NewCodec() *wire.Codec {
```
Note: We also register the types in the `tendermint/tendermint/crypto` module so that `crypto.PubKey`
and `crypto.Signature` are encoded/decoded correctly.
is encoded/decoded correctly.
Amino supports encoding and decoding in both a binary and JSON format.
See the [codec API docs](https://godoc.org/github.com/tendermint/go-amino#Codec) for more details.
@ -166,7 +166,7 @@ type app2Tx struct {
sdk.Msg
PubKey crypto.PubKey
Signature crypto.Signature
Signature []byte
}
// This tx only has one Msg.

View File

@ -160,7 +160,7 @@ The standard form for signatures is `StdSignature`:
// the first transaction made by the account.
type StdSignature struct {
crypto.PubKey `json:"pub_key"` // optional
crypto.Signature `json:"signature"`
[]byte `json:"signature"`
AccountNumber int64 `json:"account_number"`
Sequence int64 `json:"sequence"`
}

View File

@ -183,7 +183,7 @@ type app2Tx struct {
sdk.Msg
PubKey crypto.PubKey
Signature crypto.Signature
Signature []byte
}
// This tx only has one Msg.
@ -191,7 +191,7 @@ func (tx app2Tx) GetMsgs() []sdk.Msg {
return []sdk.Msg{tx.Msg}
}
func (tx app2Tx) GetSignature() crypto.Signature {
func (tx app2Tx) GetSignature() []byte {
return tx.Signature
}

View File

@ -279,7 +279,7 @@ type TxInput struct {
Address []byte `json:"address"` // Hash of the PubKey
Coins Coins `json:"coins"` //
Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput
Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx
Signature []byte `json:"signature"` // Depends on the PubKey type and the whole Tx
PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0
}

Binary file not shown.

View File

@ -101,7 +101,7 @@ func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) {
proxy.NewLocalClientCreator(app),
node.DefaultGenesisDocProviderFunc(cfg),
node.DefaultDBProvider,
node.DefaultMetricsProvider,
node.DefaultMetricsProvider(cfg.Instrumentation),
ctx.Logger.With("module", "node"),
)
if err != nil {

View File

@ -158,10 +158,10 @@ func (msg StdSignMsg) Bytes() []byte {
// Standard Signature
type StdSignature struct {
crypto.PubKey `json:"pub_key"` // optional
crypto.Signature `json:"signature"`
AccountNumber int64 `json:"account_number"`
Sequence int64 `json:"sequence"`
crypto.PubKey `json:"pub_key"` // optional
Signature []byte `json:"signature"`
AccountNumber int64 `json:"account_number"`
Sequence int64 `json:"sequence"`
}
// logic for standard transaction decoding

14
x/slashing/genesis.go Normal file
View File

@ -0,0 +1,14 @@
package slashing
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
// InitGenesis initializes the keeper's address to pubkey map.
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
for _, validator := range data.Validators {
keeper.addPubkey(ctx, validator.GetPubKey())
}
return
}

View File

@ -39,7 +39,7 @@ func handleMsgUnrevoke(ctx sdk.Context, msg MsgUnrevoke, k Keeper) sdk.Result {
}
// Cannot be unrevoked until out of jail
if ctx.BlockHeader().Time < info.JailedUntil {
if ctx.BlockHeader().Time.Before(info.JailedUntil) {
return ErrValidatorJailed(k.codespace).Result()
}

View File

@ -2,10 +2,14 @@ package slashing
import (
"fmt"
"time"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/params"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
)
@ -15,7 +19,6 @@ type Keeper struct {
cdc *wire.Codec
validatorSet sdk.ValidatorSet
params params.Getter
// codespace
codespace sdk.CodespaceType
}
@ -33,10 +36,10 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, params pa
}
// handle a validator signing two blocks at the same height
func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, timestamp int64, power int64) {
func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, timestamp time.Time, power int64) {
logger := ctx.Logger().With("module", "x/slashing")
time := ctx.BlockHeader().Time
age := time - timestamp
age := time.Sub(timestamp)
address := sdk.ValAddress(pubkey.Address())
// Double sign too old
@ -60,23 +63,26 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infracti
if !found {
panic(fmt.Sprintf("Expected signing info for validator %s but not found", address))
}
signInfo.JailedUntil = time + k.DoubleSignUnbondDuration(ctx)
signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx))
k.setValidatorSigningInfo(ctx, address, signInfo)
}
// handle a validator signature, must be called once per validator per block
// nolint gocyclo
func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey, power int64, signed bool) {
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(pubkey.Address())
address := sdk.ValAddress(addr)
pubkey, err := k.getPubkey(ctx, addr)
if err != nil {
panic(fmt.Sprintf("Validator address %v not found", addr))
}
// Local index, so counts blocks validator *should* have signed
// Will use the 0-value default signing info if not present, except for start height
signInfo, found := k.getValidatorSigningInfo(ctx, address)
if !found {
// If this validator has never been seen before, construct a new SigningInfo with the correct start height
signInfo = NewValidatorSigningInfo(height, 0, 0, 0)
signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0)
}
index := signInfo.IndexOffset % k.SignedBlocksWindow(ctx)
signInfo.IndexOffset++
@ -98,7 +104,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
}
if !signed {
logger.Info(fmt.Sprintf("Absent validator %s at height %d, %d signed, threshold %d", pubkey.Address(), height, signInfo.SignedBlocksCounter, k.MinSignedPerWindow(ctx)))
logger.Info(fmt.Sprintf("Absent validator %s at height %d, %d signed, threshold %d", addr, height, signInfo.SignedBlocksCounter, k.MinSignedPerWindow(ctx)))
}
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) {
@ -109,7 +115,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx)))
k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx))
k.validatorSet.Revoke(ctx, pubkey)
signInfo.JailedUntil = ctx.BlockHeader().Time + k.DowntimeUnbondDuration(ctx)
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
} else {
// Validator was (a) not found or (b) already revoked, don't slash
logger.Info(fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already revoked",
@ -120,3 +126,46 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
// Set the updated signing info
k.setValidatorSigningInfo(ctx, address, signInfo)
}
// AddValidators adds the validators to the keepers validator addr to pubkey mapping.
func (k Keeper) AddValidators(ctx sdk.Context, vals []abci.Validator) {
for i := 0; i < len(vals); i++ {
val := vals[i]
pubkey, err := tmtypes.PB2TM.PubKey(val.PubKey)
if err != nil {
panic(err)
}
k.addPubkey(ctx, pubkey)
}
}
// TODO: Make a method to remove the pubkey from the map when a validator is unbonded.
func (k Keeper) addPubkey(ctx sdk.Context, pubkey crypto.PubKey) {
addr := pubkey.Address()
k.setAddrPubkeyRelation(ctx, addr, pubkey)
}
func (k Keeper) getPubkey(ctx sdk.Context, address crypto.Address) (crypto.PubKey, error) {
store := ctx.KVStore(k.storeKey)
var pubkey crypto.PubKey
err := k.cdc.UnmarshalBinary(store.Get(getAddrPubkeyRelationKey(address)), &pubkey)
if err != nil {
return nil, fmt.Errorf("address %v not found", address)
}
return pubkey, nil
}
func (k Keeper) setAddrPubkeyRelation(ctx sdk.Context, addr crypto.Address, pubkey crypto.PubKey) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(pubkey)
store.Set(getAddrPubkeyRelationKey(addr), bz)
}
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...)
}

View File

@ -2,13 +2,12 @@ package slashing
import (
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
)
// Have to change these parameters for tests
@ -29,15 +28,16 @@ func TestHandleDoubleSign(t *testing.T) {
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
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.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// handle a signature to set signing info
keeper.handleValidatorSignature(ctx, val, amtInt, true)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
// double sign less than max age
keeper.handleDoubleSign(ctx, val, 0, 0, amtInt)
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
// should be revoked
require.True(t, sk.Validator(ctx, addr).GetRevoked())
@ -45,10 +45,10 @@ func TestHandleDoubleSign(t *testing.T) {
sk.Unrevoke(ctx, val)
// power should be reduced
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
ctx = ctx.WithBlockHeader(abci.Header{Time: 1 + keeper.MaxEvidenceAge(ctx)})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
// double sign past max age
keeper.handleDoubleSign(ctx, val, 0, 0, amtInt)
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
}
@ -64,7 +64,8 @@ func TestHandleAbsentValidator(t *testing.T) {
slh := NewHandler(keeper)
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
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.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
@ -72,13 +73,15 @@ func TestHandleAbsentValidator(t *testing.T) {
require.Equal(t, int64(0), info.StartHeight)
require.Equal(t, int64(0), info.IndexOffset)
require.Equal(t, int64(0), info.SignedBlocksCounter)
require.Equal(t, int64(0), info.JailedUntil)
// default time.Time value
var blankTime time.Time
require.Equal(t, blankTime, info.JailedUntil)
height := int64(0)
// 1000 first blocks OK
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, true)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
}
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
@ -88,7 +91,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// 500 blocks missed
for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)); height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
}
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
@ -103,7 +106,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// 501st block missed
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(0), info.StartHeight)
@ -118,7 +121,7 @@ func TestHandleAbsentValidator(t *testing.T) {
require.False(t, got.IsOK())
// unrevocation should succeed after jail expiration
ctx = ctx.WithBlockHeader(abci.Header{Time: keeper.DowntimeUnbondDuration(ctx) + 1})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.DowntimeUnbondDuration(ctx))})
got = slh(ctx, NewMsgUnrevoke(addr))
require.True(t, got.IsOK())
@ -140,7 +143,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// validator should not be immediately revoked again
height++
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
validator, _ = sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus())
@ -148,14 +151,14 @@ func TestHandleAbsentValidator(t *testing.T) {
nextHeight := height + keeper.MinSignedPerWindow(ctx) + 1
for ; height < nextHeight; height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
}
// validator should be revoked again after 500 unsigned blocks
nextHeight = height + keeper.MinSignedPerWindow(ctx) + 1
for ; height <= nextHeight; height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
}
validator, _ = sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Unbonded, validator.GetStatus())
@ -171,7 +174,8 @@ func TestHandleNewValidator(t *testing.T) {
sh := stake.NewHandler(sk)
got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
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, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
@ -179,16 +183,16 @@ func TestHandleNewValidator(t *testing.T) {
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
// Now a validator, for two blocks
keeper.handleValidatorSignature(ctx, val, 100, true)
keeper.handleValidatorSignature(ctx, val.Address(), 100, true)
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 2)
keeper.handleValidatorSignature(ctx, val, 100, false)
keeper.handleValidatorSignature(ctx, val.Address(), 100, false)
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(keeper.SignedBlocksWindow(ctx)+1), info.StartHeight)
require.Equal(t, int64(2), info.IndexOffset)
require.Equal(t, int64(1), info.SignedBlocksCounter)
require.Equal(t, int64(0), info.JailedUntil)
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
// validator should be bonded still, should not have been revoked or slashed
validator, _ := sk.GetValidatorByPubKey(ctx, val)
@ -208,19 +212,20 @@ func TestHandleAlreadyRevoked(t *testing.T) {
sh := stake.NewHandler(sk)
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates)
// 1000 first blocks OK
height := int64(0)
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, true)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
}
// 501 blocks missed
for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx))+1; height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
}
// validator should have been revoked and slashed
@ -232,7 +237,7 @@ func TestHandleAlreadyRevoked(t *testing.T) {
// another block missed
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
// validator should not have been slashed twice
validator, _ = sk.GetValidatorByPubKey(ctx, val)

View File

@ -1,6 +1,8 @@
package slashing
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -17,8 +19,8 @@ const (
// MaxEvidenceAge - Max age for evidence - 21 days (3 weeks)
// MaxEvidenceAge = 60 * 60 * 24 * 7 * 3
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, MaxEvidenceAgeKey, defaultMaxEvidenceAge)
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, MaxEvidenceAgeKey, defaultMaxEvidenceAge)) * time.Second
}
// SignedBlocksWindow - sliding window for downtime slashing
@ -34,13 +36,13 @@ func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
}
// Double-sign unbond duration
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, DoubleSignUnbondDurationKey, defaultDoubleSignUnbondDuration)
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, DoubleSignUnbondDurationKey, defaultDoubleSignUnbondDuration)) * time.Second
}
// Downtime unbond duration
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, DowntimeUnbondDurationKey, defaultDowntimeUnbondDuration)
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, DowntimeUnbondDurationKey, defaultDowntimeUnbondDuration)) * time.Second
}
// SlashFractionDoubleSign - currently default 5%

View File

@ -3,6 +3,7 @@ package slashing
import (
"encoding/binary"
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -48,7 +49,7 @@ func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.ValAddr
}
// Construct a new `ValidatorSigningInfo` struct
func NewValidatorSigningInfo(startHeight int64, indexOffset int64, jailedUntil int64, signedBlocksCounter int64) ValidatorSigningInfo {
func NewValidatorSigningInfo(startHeight int64, indexOffset int64, jailedUntil time.Time, signedBlocksCounter int64) ValidatorSigningInfo {
return ValidatorSigningInfo{
StartHeight: startHeight,
IndexOffset: indexOffset,
@ -59,15 +60,15 @@ func NewValidatorSigningInfo(startHeight int64, indexOffset int64, jailedUntil i
// Signing info for a validator
type ValidatorSigningInfo struct {
StartHeight int64 `json:"start_height"` // height at which validator was first a candidate OR was unrevoked
IndexOffset int64 `json:"index_offset"` // index offset into signed block bit array
JailedUntil int64 `json:"jailed_until"` // timestamp validator cannot be unrevoked until
SignedBlocksCounter int64 `json:"signed_blocks_counter"` // signed blocks counter (to avoid scanning the array every time)
StartHeight int64 `json:"start_height"` // height at which validator was first a candidate OR was unrevoked
IndexOffset int64 `json:"index_offset"` // index offset into signed block bit array
JailedUntil time.Time `json:"jailed_until"` // timestamp validator cannot be unrevoked until
SignedBlocksCounter int64 `json:"signed_blocks_counter"` // signed blocks counter (to avoid scanning the array every time)
}
// Return human readable signing info
func (i ValidatorSigningInfo) HumanReadableString() string {
return fmt.Sprintf("Start height: %d, index offset: %d, jailed until: %d, signed blocks counter: %d",
return fmt.Sprintf("Start height: %d, index offset: %d, jailed until: %v, signed blocks counter: %d",
i.StartHeight, i.IndexOffset, i.JailedUntil, i.SignedBlocksCounter)
}

View File

@ -2,6 +2,7 @@ package slashing
import (
"testing"
"time"
"github.com/stretchr/testify/require"
@ -15,7 +16,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) {
newInfo := ValidatorSigningInfo{
StartHeight: int64(4),
IndexOffset: int64(3),
JailedUntil: int64(2),
JailedUntil: time.Unix(2, 0),
SignedBlocksCounter: int64(10),
}
keeper.setValidatorSigningInfo(ctx, sdk.ValAddress(addrs[0]), newInfo)
@ -23,7 +24,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) {
require.True(t, found)
require.Equal(t, info.StartHeight, int64(4))
require.Equal(t, info.IndexOffset, int64(3))
require.Equal(t, info.JailedUntil, int64(2))
require.Equal(t, info.JailedUntil, time.Unix(2, 0).UTC())
require.Equal(t, info.SignedBlocksCounter, int64(10))
}

View File

@ -20,13 +20,9 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) (tags
// Iterate over all the validators which *should* have signed this block
// Store whether or not they have actually signed it and slash/unbond any
// which have missed too many blocks in a row (downtime slashing)
for _, signingValidator := range req.Validators {
for _, signingValidator := range req.LastCommitInfo.GetValidators() {
present := signingValidator.SignedLastBlock
pubkey, err := tmtypes.PB2TM.PubKey(signingValidator.Validator.PubKey)
if err != nil {
panic(err)
}
sk.handleValidatorSignature(ctx, pubkey, signingValidator.Validator.Power, present)
sk.handleValidatorSignature(ctx, signingValidator.Validator.Address, signingValidator.Validator.Power, present)
}
// Iterate through any newly discovered evidence of infraction

View File

@ -2,11 +2,11 @@ package slashing
import (
"testing"
"time"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
@ -19,21 +19,24 @@ func TestBeginBlocker(t *testing.T) {
// bond the validator
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, pk, amt))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
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.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
val := abci.Validator{
PubKey: tmtypes.TM2PB.PubKey(pk),
Power: amt.Int64(),
Address: pk.Address(),
Power: amt.Int64(),
}
// mark the validator as having signed
req := abci.RequestBeginBlock{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: true,
}},
LastCommitInfo: abci.LastCommitInfo{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: true,
}},
},
}
BeginBlocker(ctx, req, keeper)
@ -41,7 +44,7 @@ func TestBeginBlocker(t *testing.T) {
require.True(t, found)
require.Equal(t, ctx.BlockHeight(), info.StartHeight)
require.Equal(t, int64(1), info.IndexOffset)
require.Equal(t, int64(0), info.JailedUntil)
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
require.Equal(t, int64(1), info.SignedBlocksCounter)
height := int64(0)
@ -50,10 +53,12 @@ func TestBeginBlocker(t *testing.T) {
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
req = abci.RequestBeginBlock{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: true,
}},
LastCommitInfo: abci.LastCommitInfo{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: true,
}},
},
}
BeginBlocker(ctx, req, keeper)
}
@ -62,10 +67,12 @@ func TestBeginBlocker(t *testing.T) {
for ; height < ((keeper.SignedBlocksWindow(ctx) * 2) - keeper.MinSignedPerWindow(ctx) + 1); height++ {
ctx = ctx.WithBlockHeight(height)
req = abci.RequestBeginBlock{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: false,
}},
LastCommitInfo: abci.LastCommitInfo{
Validators: []abci.SigningValidator{{
Validator: val,
SignedLastBlock: false,
}},
},
}
BeginBlocker(ctx, req, keeper)
}

View File

@ -1,6 +1,8 @@
package stake
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/tags"
@ -38,7 +40,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
// Process provision inflation
blockTime := ctx.BlockHeader().Time
if blockTime-pool.InflationLastTime >= 3600 {
if blockTime.Sub(pool.InflationLastTime) >= time.Hour {
params := k.GetParams(ctx)
pool.InflationLastTime = blockTime
pool = pool.ProcessProvisions(params)

View File

@ -2,6 +2,7 @@ package stake
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -500,7 +501,7 @@ func TestUnbondingPeriod(t *testing.T) {
// set the unbonding time
params := keeper.GetParams(ctx)
params.UnbondingTime = 7
params.UnbondingTime = 7 * time.Second
keeper.SetParams(ctx, params)
// create the validator
@ -516,19 +517,19 @@ func TestUnbondingPeriod(t *testing.T) {
// cannot complete unbonding at same time
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper)
require.True(t, !got.IsOK(), "expected no error")
require.True(t, !got.IsOK(), "expected an error")
// cannot complete unbonding at time 6 seconds later
origHeader := ctx.BlockHeader()
headerTime6 := origHeader
headerTime6.Time += 6
headerTime6.Time = headerTime6.Time.Add(time.Second * 6)
ctx = ctx.WithBlockHeader(headerTime6)
got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper)
require.True(t, !got.IsOK(), "expected no error")
require.True(t, !got.IsOK(), "expected an error")
// can complete unbonding at time 7 seconds later
headerTime7 := origHeader
headerTime7.Time += 7
headerTime7.Time = headerTime7.Time.Add(time.Second * 7)
ctx = ctx.WithBlockHeader(headerTime7)
got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error")
@ -541,7 +542,7 @@ func TestRedelegationPeriod(t *testing.T) {
// set the unbonding time
params := keeper.GetParams(ctx)
params.UnbondingTime = 7
params.UnbondingTime = 7 * time.Second
keeper.SetParams(ctx, params)
// create the validators
@ -580,14 +581,14 @@ func TestRedelegationPeriod(t *testing.T) {
// cannot complete redelegation at time 6 seconds later
origHeader := ctx.BlockHeader()
headerTime6 := origHeader
headerTime6.Time += 6
headerTime6.Time = headerTime6.Time.Add(time.Second * 6)
ctx = ctx.WithBlockHeader(headerTime6)
got = handleMsgCompleteRedelegate(ctx, msgCompleteRedelegate, keeper)
require.True(t, !got.IsOK(), "expected an error")
// can complete redelegation at time 7 seconds later
headerTime7 := origHeader
headerTime7.Time += 7
headerTime7.Time = headerTime7.Time.Add(time.Second * 7)
ctx = ctx.WithBlockHeader(headerTime7)
got = handleMsgCompleteRedelegate(ctx, msgCompleteRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error")

View File

@ -327,7 +327,7 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk
// create the unbonding delegation
params := k.GetParams(ctx)
minTime := ctx.BlockHeader().Time + params.UnbondingTime
minTime := ctx.BlockHeader().Time.Add(params.UnbondingTime)
balance := sdk.Coin{params.BondDenom, returnAmount.RoundInt()}
ubd := types.UnbondingDelegation{
@ -351,7 +351,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr
// ensure that enough time has passed
ctxTime := ctx.BlockHeader().Time
if ubd.MinTime > ctxTime {
if ubd.MinTime.After(ctxTime) {
return types.ErrNotMature(k.Codespace(), "unbonding", "unit-time", ubd.MinTime, ctxTime)
}
@ -389,7 +389,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAd
}
// create the unbonding delegation
minTime := ctx.BlockHeader().Time + params.UnbondingTime
minTime := ctx.BlockHeader().Time.Add(params.UnbondingTime)
red := types.Redelegation{
DelegatorAddr: delegatorAddr,
@ -415,7 +415,7 @@ func (k Keeper) CompleteRedelegation(ctx sdk.Context, delegatorAddr, validatorSr
// ensure that enough time has passed
ctxTime := ctx.BlockHeader().Time
if red.MinTime > ctxTime {
if red.MinTime.After(ctxTime) {
return types.ErrNotMature(k.Codespace(), "redelegation", "unit-time", red.MinTime, ctxTime)
}

View File

@ -2,6 +2,7 @@ package keeper
import (
"testing"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
@ -115,7 +116,7 @@ func TestUnbondingDelegation(t *testing.T) {
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[0],
CreationHeight: 0,
MinTime: 0,
MinTime: time.Unix(0, 0),
Balance: sdk.NewInt64Coin("steak", 5),
}
@ -188,7 +189,7 @@ func TestGetRedelegationsFromValidator(t *testing.T) {
ValidatorSrcAddr: addrVals[0],
ValidatorDstAddr: addrVals[1],
CreationHeight: 0,
MinTime: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5),
SharesDst: sdk.NewRat(5),
}
@ -218,7 +219,7 @@ func TestRedelegation(t *testing.T) {
ValidatorSrcAddr: addrVals[0],
ValidatorDstAddr: addrVals[1],
CreationHeight: 0,
MinTime: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5),
SharesDst: sdk.NewRat(5),
}

View File

@ -159,7 +159,7 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
return sdk.ZeroRat()
}
if unbondingDelegation.MinTime < now {
if unbondingDelegation.MinTime.Before(now) {
// Unbonding delegation no longer eligible for slashing, skip it
// TODO Settle and delete it automatically?
return sdk.ZeroRat()
@ -203,7 +203,7 @@ func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, re
return sdk.ZeroRat()
}
if redelegation.MinTime < now {
if redelegation.MinTime.Before(now) {
// Redelegation no longer eligible for slashing, skip it
// TODO Delete it automatically?
return sdk.ZeroRat()

View File

@ -2,6 +2,7 @@ package keeper
import (
"testing"
"time"
"github.com/stretchr/testify/require"
@ -70,7 +71,7 @@ func TestSlashUnbondingDelegation(t *testing.T) {
ValidatorAddr: addrVals[0],
CreationHeight: 0,
// expiration timestamp (beyond which the unbonding delegation shouldn't be slashed)
MinTime: 0,
MinTime: time.Unix(0, 0),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
Balance: sdk.NewInt64Coin(params.BondDenom, 10),
}
@ -81,14 +82,14 @@ func TestSlashUnbondingDelegation(t *testing.T) {
require.Equal(t, int64(0), slashAmount.RoundInt64())
// after the expiration time, no longer eligible for slashing
ctx = ctx.WithBlockHeader(abci.Header{Time: int64(10)})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(10, 0)})
keeper.SetUnbondingDelegation(ctx, ubd)
slashAmount = keeper.slashUnbondingDelegation(ctx, ubd, 0, fraction)
require.Equal(t, int64(0), slashAmount.RoundInt64())
// test valid slash, before expiration timestamp and to which stake contributed
oldPool := keeper.GetPool(ctx)
ctx = ctx.WithBlockHeader(abci.Header{Time: int64(0)})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(0, 0)})
keeper.SetUnbondingDelegation(ctx, ubd)
slashAmount = keeper.slashUnbondingDelegation(ctx, ubd, 0, fraction)
require.Equal(t, int64(5), slashAmount.RoundInt64())
@ -114,7 +115,7 @@ func TestSlashRedelegation(t *testing.T) {
ValidatorDstAddr: addrVals[1],
CreationHeight: 0,
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(10),
SharesDst: sdk.NewRat(10),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
@ -137,7 +138,7 @@ func TestSlashRedelegation(t *testing.T) {
require.Equal(t, int64(0), slashAmount.RoundInt64())
// after the expiration time, no longer eligible for slashing
ctx = ctx.WithBlockHeader(abci.Header{Time: int64(10)})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(10, 0)})
keeper.SetRedelegation(ctx, rd)
validator, found = keeper.GetValidator(ctx, addrVals[1])
require.True(t, found)
@ -146,7 +147,7 @@ func TestSlashRedelegation(t *testing.T) {
// test valid slash, before expiration timestamp and to which stake contributed
oldPool := keeper.GetPool(ctx)
ctx = ctx.WithBlockHeader(abci.Header{Time: int64(0)})
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(0, 0)})
keeper.SetRedelegation(ctx, rd)
validator, found = keeper.GetValidator(ctx, addrVals[1])
require.True(t, found)
@ -209,7 +210,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
ValidatorAddr: addrVals[0],
CreationHeight: 11,
// expiration timestamp (beyond which the unbonding delegation shouldn't be slashed)
MinTime: 0,
MinTime: time.Unix(0, 0),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 4),
Balance: sdk.NewInt64Coin(params.BondDenom, 4),
}
@ -310,7 +311,7 @@ func TestSlashWithRedelegation(t *testing.T) {
ValidatorSrcAddr: addrVals[0],
ValidatorDstAddr: addrVals[1],
CreationHeight: 11,
MinTime: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6),
SharesDst: sdk.NewRat(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
@ -432,7 +433,7 @@ func TestSlashBoth(t *testing.T) {
ValidatorDstAddr: addrVals[1],
CreationHeight: 11,
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6),
SharesDst: sdk.NewRat(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
@ -454,7 +455,7 @@ func TestSlashBoth(t *testing.T) {
ValidatorAddr: addrVals[0],
CreationHeight: 11,
// expiration timestamp (beyond which the unbonding delegation shouldn't be slashed)
MinTime: 0,
MinTime: time.Unix(0, 0),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 4),
Balance: sdk.NewInt64Coin(params.BondDenom, 4),
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
@ -100,14 +101,14 @@ type UnbondingDelegation struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // delegator
ValidatorAddr sdk.AccAddress `json:"validator_addr"` // validator unbonding from owner addr
CreationHeight int64 `json:"creation_height"` // height which the unbonding took place
MinTime int64 `json:"min_time"` // unix time for unbonding completion
MinTime time.Time `json:"min_time"` // unix time for unbonding completion
InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion
Balance sdk.Coin `json:"balance"` // atoms to receive at completion
}
type ubdValue struct {
CreationHeight int64
MinTime int64
MinTime time.Time
InitialBalance sdk.Coin
Balance sdk.Coin
}
@ -186,7 +187,7 @@ type Redelegation struct {
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` // validator redelegation source owner addr
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` // validator redelegation destination owner addr
CreationHeight int64 `json:"creation_height"` // height which the redelegation took place
MinTime int64 `json:"min_time"` // unix time for redelegation completion
MinTime time.Time `json:"min_time"` // unix time for redelegation completion
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
Balance sdk.Coin `json:"balance"` // current balance
SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating
@ -195,7 +196,7 @@ type Redelegation struct {
type redValue struct {
CreationHeight int64
MinTime int64
MinTime time.Time
InitialBalance sdk.Coin
Balance sdk.Coin
SharesSrc sdk.Rat

View File

@ -2,6 +2,7 @@ package types
import (
"testing"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
@ -57,7 +58,7 @@ func TestUnbondingDelegationEqual(t *testing.T) {
require.True(t, ok)
ud2.ValidatorAddr = addr3
ud2.MinTime = 20 * 20 * 2
ud2.MinTime = time.Unix(20*20*2, 0)
ok = ud1.Equal(ud2)
require.False(t, ok)
@ -93,7 +94,7 @@ func TestRedelegationEqual(t *testing.T) {
r2.SharesDst = sdk.NewRat(10)
r2.SharesSrc = sdk.NewRat(20)
r2.MinTime = 20 * 20 * 2
r2.MinTime = time.Unix(20*20*2, 0)
ok = r1.Equal(r2)
require.False(t, ok)

View File

@ -3,6 +3,7 @@ package types
import (
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -110,7 +111,7 @@ func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
}
func ErrNotMature(codespace sdk.CodespaceType, operation, descriptor string, got, min int64) sdk.Error {
func ErrNotMature(codespace sdk.CodespaceType, operation, descriptor string, got, min time.Time) sdk.Error {
msg := fmt.Sprintf("%v is not mature requires a min %v of %v, currently it is %v",
operation, descriptor, got, min)
return sdk.NewError(codespace, CodeUnauthorized, msg)

View File

@ -2,13 +2,14 @@ package types
import (
"bytes"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// defaultUnbondingTime reflects three weeks in seconds as the default
// unbonding time.
const defaultUnbondingTime int64 = 60 * 60 * 24 * 3
const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
// Params defines the high level settings for staking
type Params struct {
@ -17,7 +18,7 @@ type Params struct {
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms
UnbondingTime int64 `json:"unbonding_time"`
UnbondingTime time.Duration `json:"unbonding_time"`
MaxValidators uint16 `json:"max_validators"` // maximum number of validators
BondDenom string `json:"bond_denom"` // bondable coin denomination

View File

@ -3,16 +3,17 @@ package types
import (
"bytes"
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Pool - dynamic parameters of the current state
type Pool struct {
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
@ -32,7 +33,7 @@ func InitialPool() Pool {
return Pool{
LooseTokens: sdk.ZeroRat(),
BondedTokens: sdk.ZeroRat(),
InflationLastTime: 0,
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
DateLastCommissionReset: 0,
PrevBondedShares: sdk.ZeroRat(),

View File

@ -3,6 +3,7 @@ package types
import (
"fmt"
"testing"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
@ -184,7 +185,7 @@ func TestRemoveDelShares(t *testing.T) {
pool := Pool{
BondedTokens: sdk.NewRat(248305),
LooseTokens: sdk.NewRat(232147),
InflationLastTime: 0,
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
}
shares := sdk.NewRat(29)
@ -232,7 +233,7 @@ func TestPossibleOverflow(t *testing.T) {
pool := Pool{
LooseTokens: sdk.NewRat(100),
BondedTokens: poolTokens,
InflationLastTime: 0,
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
}
tokens := int64(71)