Merge remote-tracking branch 'origin/develop' into rigel/fee-distribution
This commit is contained in:
commit
46db96bdb7
|
@ -679,7 +679,6 @@
|
||||||
"github.com/tendermint/tmlibs/cli",
|
"github.com/tendermint/tmlibs/cli",
|
||||||
"github.com/zondax/ledger-goclient",
|
"github.com/zondax/ledger-goclient",
|
||||||
"golang.org/x/crypto/blowfish",
|
"golang.org/x/crypto/blowfish",
|
||||||
"golang.org/x/crypto/ripemd160",
|
|
||||||
]
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -157,11 +157,11 @@ test_sim_gaia_nondeterminism:
|
||||||
|
|
||||||
test_sim_gaia_fast:
|
test_sim_gaia_fast:
|
||||||
@echo "Running quick Gaia simulation. This may take several minutes..."
|
@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=400 -SimulationBlockSize=200 -SimulationCommit=true -v -timeout 24h
|
||||||
|
|
||||||
test_sim_gaia_slow:
|
test_sim_gaia_slow:
|
||||||
@echo "Running full Gaia simulation. This may take awhile!"
|
@echo "Running full Gaia simulation. This may take awhile!"
|
||||||
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h
|
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -SimulationCommit=true -v -timeout 24h
|
||||||
|
|
||||||
SIM_NUM_BLOCKS ?= 210
|
SIM_NUM_BLOCKS ?= 210
|
||||||
SIM_BLOCK_SIZE ?= 200
|
SIM_BLOCK_SIZE ?= 200
|
||||||
|
|
14
PENDING.md
14
PENDING.md
|
@ -33,6 +33,7 @@ BREAKING CHANGES
|
||||||
renamed for accounts and validator operators:
|
renamed for accounts and validator operators:
|
||||||
* `cosmosaccaddr` / `cosmosaccpub` => `cosmos` / `cosmospub`
|
* `cosmosaccaddr` / `cosmosaccpub` => `cosmos` / `cosmospub`
|
||||||
* `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub`
|
* `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub`
|
||||||
|
* [x/stake] [#1013] TendermintUpdates now uses transient store
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal
|
* [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal
|
||||||
|
@ -43,10 +44,10 @@ BREAKING CHANGES
|
||||||
* [simulation] Remove log and testing.TB from Operation and Invariants, in favor of using errors \#2282
|
* [simulation] Remove log and testing.TB from Operation and Invariants, in favor of using errors \#2282
|
||||||
* [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211)
|
* [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211)
|
||||||
* [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441)
|
* [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441)
|
||||||
|
* [store] Change storeInfo within the root multistore to use tmhash instead of ripemd160 \#2308
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
|
|
||||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||||
|
@ -61,8 +62,9 @@ FEATURES
|
||||||
* [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in
|
* [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in
|
||||||
* [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Add `--bech` to `gaiacli keys show` and respective REST endpoint to
|
* [\#2040](https://github.com/cosmos/cosmos-sdk/issues/2040) Add `--bech` to `gaiacli keys show` and respective REST endpoint to
|
||||||
provide desired Bech32 prefix encoding
|
provide desired Bech32 prefix encoding
|
||||||
* [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution.
|
* [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) [\#2306](https://github.com/cosmos/cosmos-sdk/pull/2306) Passing --gas=simulate triggers a simulation of the tx before the actual execution.
|
||||||
* [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0.
|
The gas estimate obtained via the simulation will be used as gas limit in the actual execution.
|
||||||
|
* [cli] [\#2047](https://github.com/cosmos/cosmos-sdk/issues/2047) The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=simulate.
|
||||||
* [cli] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated.
|
* [cli] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add --dry-run flag to perform a simulation of a transaction without broadcasting it. The --gas flag is ignored as gas would be automatically estimated.
|
||||||
* [cli] [\#2204](https://github.com/cosmos/cosmos-sdk/issues/2204) Support generating and broadcasting messages with multiple signatures via command line:
|
* [cli] [\#2204](https://github.com/cosmos/cosmos-sdk/issues/2204) Support generating and broadcasting messages with multiple signatures via command line:
|
||||||
* [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT.
|
* [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT.
|
||||||
|
@ -97,6 +99,7 @@ IMPROVEMENTS
|
||||||
* [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883).
|
* [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883).
|
||||||
* [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200)
|
* [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200)
|
||||||
* [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state.
|
* [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state.
|
||||||
|
* Add SDK validation to `config.toml` (namely disabling `create_empty_blocks`) \#1571
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present.
|
* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present.
|
||||||
|
@ -106,6 +109,9 @@ IMPROVEMENTS
|
||||||
* [store] \#1952, \#2281 Update IAVL dependency to v0.11.0
|
* [store] \#1952, \#2281 Update IAVL dependency to v0.11.0
|
||||||
* [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153)
|
* [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153)
|
||||||
* [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282
|
* [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282
|
||||||
|
* [simulation] Add a concept of weighting the operations \#2303
|
||||||
|
* [simulation] Logs get written to file if large, and also get printed on panics \#2285
|
||||||
|
* [gaiad] \#1992 Add optional flag to `gaiad testnet` to make config directory of daemon (default `gaiad`) and cli (default `gaiacli`) configurable
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
||||||
|
@ -118,6 +124,8 @@ BUG FIXES
|
||||||
* [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command.
|
* [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command.
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
* [x/stake] Return correct Tendermint validator update set on `EndBlocker` by not
|
||||||
|
including non previously bonded validators that have zero power. [#2189](https://github.com/cosmos/cosmos-sdk/issues/2189)
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988)
|
* [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988)
|
||||||
|
|
|
@ -120,13 +120,20 @@ func (app *BaseApp) RegisterCodespace(codespace sdk.CodespaceType) sdk.Codespace
|
||||||
return app.codespacer.RegisterNext(codespace)
|
return app.codespacer.RegisterNext(codespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount a store to the provided key in the BaseApp multistore
|
// Mount IAVL stores to the provided keys in the BaseApp multistore
|
||||||
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
|
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
app.MountStore(key, sdk.StoreTypeIAVL)
|
app.MountStore(key, sdk.StoreTypeIAVL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mount stores to the provided keys in the BaseApp multistore
|
||||||
|
func (app *BaseApp) MountStoresTransient(keys ...*sdk.TransientStoreKey) {
|
||||||
|
for _, key := range keys {
|
||||||
|
app.MountStore(key, sdk.StoreTypeTransient)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mount a store to the provided key in the BaseApp multistore, using a specified DB
|
// Mount a store to the provided key in the BaseApp multistore, using a specified DB
|
||||||
func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) {
|
func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) {
|
||||||
app.cms.MountStoreWithDB(key, typ, db)
|
app.cms.MountStoreWithDB(key, typ, db)
|
||||||
|
|
|
@ -27,8 +27,6 @@ type CLIContext struct {
|
||||||
Client rpcclient.Client
|
Client rpcclient.Client
|
||||||
Logger io.Writer
|
Logger io.Writer
|
||||||
Height int64
|
Height int64
|
||||||
Gas int64
|
|
||||||
GasAdjustment float64
|
|
||||||
NodeURI string
|
NodeURI string
|
||||||
FromAddressName string
|
FromAddressName string
|
||||||
AccountStore string
|
AccountStore string
|
||||||
|
@ -58,8 +56,6 @@ func NewCLIContext() CLIContext {
|
||||||
AccountStore: ctxAccStoreName,
|
AccountStore: ctxAccStoreName,
|
||||||
FromAddressName: viper.GetString(client.FlagFrom),
|
FromAddressName: viper.GetString(client.FlagFrom),
|
||||||
Height: viper.GetInt64(client.FlagHeight),
|
Height: viper.GetInt64(client.FlagHeight),
|
||||||
Gas: viper.GetInt64(client.FlagGas),
|
|
||||||
GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment),
|
|
||||||
TrustNode: viper.GetBool(client.FlagTrustNode),
|
TrustNode: viper.GetBool(client.FlagTrustNode),
|
||||||
UseLedger: viper.GetBool(client.FlagUseLedger),
|
UseLedger: viper.GetBool(client.FlagUseLedger),
|
||||||
Async: viper.GetBool(client.FlagAsync),
|
Async: viper.GetBool(client.FlagAsync),
|
||||||
|
@ -164,9 +160,3 @@ func (ctx CLIContext) WithCertifier(certifier tmlite.Certifier) CLIContext {
|
||||||
ctx.Certifier = certifier
|
ctx.Certifier = certifier
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithGasAdjustment returns a copy of the context with an updated GasAdjustment flag.
|
|
||||||
func (ctx CLIContext) WithGasAdjustment(adjustment float64) CLIContext {
|
|
||||||
ctx.GasAdjustment = adjustment
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import "github.com/spf13/cobra"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
const (
|
const (
|
||||||
|
@ -9,6 +14,7 @@ const (
|
||||||
// occur between the tx simulation and the actual run.
|
// occur between the tx simulation and the actual run.
|
||||||
DefaultGasAdjustment = 1.0
|
DefaultGasAdjustment = 1.0
|
||||||
DefaultGasLimit = 200000
|
DefaultGasLimit = 200000
|
||||||
|
GasFlagSimulate = "simulate"
|
||||||
|
|
||||||
FlagUseLedger = "ledger"
|
FlagUseLedger = "ledger"
|
||||||
FlagChainID = "chain-id"
|
FlagChainID = "chain-id"
|
||||||
|
@ -32,7 +38,10 @@ const (
|
||||||
|
|
||||||
// LineBreak can be included in a command list to provide a blank line
|
// LineBreak can be included in a command list to provide a blank line
|
||||||
// to help with readability
|
// to help with readability
|
||||||
var LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}}
|
var (
|
||||||
|
LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}}
|
||||||
|
GasFlagVar = GasSetting{Gas: DefaultGasLimit}
|
||||||
|
)
|
||||||
|
|
||||||
// GetCommands adds common flags to query commands
|
// GetCommands adds common flags to query commands
|
||||||
func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
|
func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
|
||||||
|
@ -58,7 +67,6 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
|
||||||
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
|
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
|
||||||
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
|
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
|
||||||
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
|
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
|
||||||
c.Flags().Int64(FlagGas, DefaultGasLimit, "gas limit to set per-transaction; set to 0 to calculate required gas automatically")
|
|
||||||
c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
|
c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
|
||||||
c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously")
|
c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously")
|
||||||
c.Flags().Bool(FlagJson, false, "return output in json format")
|
c.Flags().Bool(FlagJson, false, "return output in json format")
|
||||||
|
@ -66,6 +74,50 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
|
||||||
c.Flags().Bool(FlagTrustNode, true, "Don't verify proofs for query responses")
|
c.Flags().Bool(FlagTrustNode, true, "Don't verify proofs for query responses")
|
||||||
c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it")
|
c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it")
|
||||||
c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT")
|
c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT")
|
||||||
|
// --gas can accept integers and "simulate"
|
||||||
|
c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf(
|
||||||
|
"gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)", GasFlagSimulate, DefaultGasLimit))
|
||||||
}
|
}
|
||||||
return cmds
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gas flag parsing functions
|
||||||
|
|
||||||
|
// GasSetting encapsulates the possible values passed through the --gas flag.
|
||||||
|
type GasSetting struct {
|
||||||
|
Simulate bool
|
||||||
|
Gas int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the flag's value type.
|
||||||
|
func (v *GasSetting) Type() string { return "string" }
|
||||||
|
|
||||||
|
// Set parses and sets the value of the --gas flag.
|
||||||
|
func (v *GasSetting) Set(s string) (err error) {
|
||||||
|
v.Simulate, v.Gas, err = ReadGasFlag(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *GasSetting) String() string {
|
||||||
|
if v.Simulate {
|
||||||
|
return GasFlagSimulate
|
||||||
|
}
|
||||||
|
return strconv.FormatInt(v.Gas, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseGasFlag parses the value of the --gas flag.
|
||||||
|
func ReadGasFlag(s string) (simulate bool, gas int64, err error) {
|
||||||
|
switch s {
|
||||||
|
case "":
|
||||||
|
gas = DefaultGasLimit
|
||||||
|
case GasFlagSimulate:
|
||||||
|
simulate = true
|
||||||
|
default:
|
||||||
|
gas, err = strconv.ParseInt(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("gas must be either integer or %q", GasFlagSimulate)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -19,7 +17,7 @@ const (
|
||||||
FlagAddress = "address"
|
FlagAddress = "address"
|
||||||
// FlagPublicKey represents the user's public key on the command line.
|
// FlagPublicKey represents the user's public key on the command line.
|
||||||
FlagPublicKey = "pubkey"
|
FlagPublicKey = "pubkey"
|
||||||
// FlagBechPrefix defines a desired Bech32 prefix encoding for a key
|
// FlagBechPrefix defines a desired Bech32 prefix encoding for a key.
|
||||||
FlagBechPrefix = "bech"
|
FlagBechPrefix = "bech"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,21 +27,33 @@ func showKeysCmd() *cobra.Command {
|
||||||
Short: "Show key info for the given name",
|
Short: "Show key info for the given name",
|
||||||
Long: `Return public details of one local key.`,
|
Long: `Return public details of one local key.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: runShowCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)")
|
||||||
|
cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)")
|
||||||
|
cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func runShowCmd(cmd *cobra.Command, args []string) error {
|
||||||
name := args[0]
|
name := args[0]
|
||||||
info, err := getKey(name)
|
|
||||||
|
info, err := GetKeyInfo(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
showAddress := viper.GetBool(FlagAddress)
|
isShowAddr := viper.GetBool(FlagAddress)
|
||||||
showPublicKey := viper.GetBool(FlagPublicKey)
|
isShowPubKey := viper.GetBool(FlagPublicKey)
|
||||||
outputSet := cmd.Flag(cli.OutputFlag).Changed
|
isOutputSet := cmd.Flag(cli.OutputFlag).Changed
|
||||||
|
|
||||||
if showAddress && showPublicKey {
|
if isShowAddr && isShowPubKey {
|
||||||
return errors.New("cannot use both --address and --pubkey at once")
|
return errors.New("cannot use both --address and --pubkey at once")
|
||||||
}
|
}
|
||||||
if outputSet && (showAddress || showPublicKey) {
|
|
||||||
|
if isOutputSet && (isShowAddr || isShowPubKey) {
|
||||||
return errors.New("cannot use --output with --address or --pubkey")
|
return errors.New("cannot use --output with --address or --pubkey")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,22 +63,15 @@ func showKeysCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case showAddress:
|
case isShowAddr:
|
||||||
printKeyAddress(info, bechKeyOut)
|
printKeyAddress(info, bechKeyOut)
|
||||||
case showPublicKey:
|
case isShowPubKey:
|
||||||
printPubKey(info, bechKeyOut)
|
printPubKey(info, bechKeyOut)
|
||||||
default:
|
default:
|
||||||
printKeyInfo(info, bechKeyOut)
|
printKeyInfo(info, bechKeyOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)")
|
|
||||||
cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)")
|
|
||||||
cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)")
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
|
func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
|
||||||
|
@ -84,15 +87,6 @@ func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
|
||||||
return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix)
|
return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKey(name string) (keys.Info, error) {
|
|
||||||
kb, err := GetKeyBase()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return kb.Get(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
// REST
|
// REST
|
||||||
|
|
||||||
|
@ -113,7 +107,7 @@ func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := getKey(name)
|
info, err := GetKeyInfo(name)
|
||||||
// TODO: check for the error if key actually does not exist, instead of
|
// TODO: check for the error if key actually does not exist, instead of
|
||||||
// assuming this as the reason
|
// assuming this as the reason
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -267,21 +267,29 @@ func TestCoinSend(t *testing.T) {
|
||||||
require.Equal(t, int64(1), mycoins.Amount.Int64())
|
require.Equal(t, int64(1), mycoins.Amount.Int64())
|
||||||
|
|
||||||
// test failure with too little gas
|
// test failure with too little gas
|
||||||
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 100, 0, "")
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "100", 0, "")
|
||||||
|
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
||||||
|
|
||||||
|
// test failure with negative gas
|
||||||
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "-200", 0, "")
|
||||||
|
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
||||||
|
|
||||||
|
// test failure with 0 gas
|
||||||
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "0", 0, "")
|
||||||
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
||||||
|
|
||||||
// test failure with wrong adjustment
|
// test failure with wrong adjustment
|
||||||
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 0, 0.1, "")
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "simulate", 0.1, "")
|
||||||
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
|
||||||
|
|
||||||
// run simulation and test success with estimated gas
|
// run simulation and test success with estimated gas
|
||||||
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?simulate=true")
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "", 0, "?simulate=true")
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var responseBody struct {
|
var responseBody struct {
|
||||||
GasEstimate int64 `json:"gas_estimate"`
|
GasEstimate int64 `json:"gas_estimate"`
|
||||||
}
|
}
|
||||||
require.Nil(t, json.Unmarshal([]byte(body), &responseBody))
|
require.Nil(t, json.Unmarshal([]byte(body), &responseBody))
|
||||||
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, responseBody.GasEstimate, 0, "")
|
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, fmt.Sprintf("%v", responseBody.GasEstimate), 0, "")
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +330,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
acc := getAccount(t, port, addr)
|
acc := getAccount(t, port, addr)
|
||||||
|
|
||||||
// generate TX
|
// generate TX
|
||||||
res, body, _ := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "?generate_only=true")
|
res, body, _ := doSendWithGas(t, port, seed, name, password, addr, "simulate", 0, "?generate_only=true")
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
var msg auth.StdTx
|
var msg auth.StdTx
|
||||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg))
|
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg))
|
||||||
|
@ -792,7 +800,7 @@ func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account {
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas int64, gasAdjustment float64, queryStr string) (res *http.Response, body string, receiveAddr sdk.AccAddress) {
|
func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas string, gasAdjustment float64, queryStr string) (res *http.Response, body string, receiveAddr sdk.AccAddress) {
|
||||||
|
|
||||||
// create receive address
|
// create receive address
|
||||||
kb := client.MockKeyBase()
|
kb := client.MockKeyBase()
|
||||||
|
@ -811,14 +819,14 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc
|
||||||
}
|
}
|
||||||
|
|
||||||
gasStr := ""
|
gasStr := ""
|
||||||
if gas > 0 {
|
if len(gas) != 0 {
|
||||||
gasStr = fmt.Sprintf(`
|
gasStr = fmt.Sprintf(`
|
||||||
"gas":"%v",
|
"gas":%q,
|
||||||
`, gas)
|
`, gas)
|
||||||
}
|
}
|
||||||
gasAdjustmentStr := ""
|
gasAdjustmentStr := ""
|
||||||
if gasAdjustment > 0 {
|
if gasAdjustment > 0 {
|
||||||
gasStr = fmt.Sprintf(`
|
gasAdjustmentStr = fmt.Sprintf(`
|
||||||
"gas_adjustment":"%v",
|
"gas_adjustment":"%v",
|
||||||
`, gasAdjustment)
|
`, gasAdjustment)
|
||||||
}
|
}
|
||||||
|
@ -837,7 +845,7 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) {
|
func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) {
|
||||||
res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, 0, 0, "")
|
res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, "", 0, "")
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
||||||
err := cdc.UnmarshalJSON([]byte(body), &resultTx)
|
err := cdc.UnmarshalJSON([]byte(body), &resultTx)
|
||||||
|
|
|
@ -24,8 +24,8 @@ func SendTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
autogas := cliCtx.DryRun || (cliCtx.Gas == 0)
|
|
||||||
if autogas {
|
if txBldr.SimulateGas || cliCtx.DryRun {
|
||||||
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs)
|
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -50,20 +50,10 @@ func SendTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg)
|
||||||
return cliCtx.EnsureBroadcastTx(txBytes)
|
return cliCtx.EnsureBroadcastTx(txBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value.
|
|
||||||
func SimulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg, gas int64) (estimated, adjusted int64, err error) {
|
|
||||||
txBytes, err := txBldr.WithGas(gas).BuildWithPubKey(name, msgs)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnrichCtxWithGas calculates the gas estimate that would be consumed by the
|
// EnrichCtxWithGas calculates the gas estimate that would be consumed by the
|
||||||
// transaction and set the transaction's respective value accordingly.
|
// transaction and set the transaction's respective value accordingly.
|
||||||
func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
|
func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
|
||||||
_, adjusted, err := SimulateMsgs(txBldr, cliCtx, name, msgs, 0)
|
_, adjusted, err := simulateMsgs(txBldr, cliCtx, name, msgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return txBldr, err
|
return txBldr, err
|
||||||
}
|
}
|
||||||
|
@ -143,6 +133,16 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string,
|
||||||
return txBldr.SignStdTx(name, passphrase, stdTx, appendSig)
|
return txBldr.SignStdTx(name, passphrase, stdTx, appendSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value.
|
||||||
|
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted int64, err error) {
|
||||||
|
txBytes, err := txBldr.BuildWithPubKey(name, msgs)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, txBldr.GasAdjustment)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func adjustGasEstimate(estimate int64, adjustment float64) int64 {
|
func adjustGasEstimate(estimate int64, adjustment float64) int64 {
|
||||||
return int64(adjustment * float64(estimate))
|
return int64(adjustment * float64(estimate))
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if txBldr.Gas == 0 {
|
if txBldr.SimulateGas {
|
||||||
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs)
|
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, cliCtx.FromAddressName, msgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -43,6 +43,7 @@ type GaiaApp struct {
|
||||||
keyAccount *sdk.KVStoreKey
|
keyAccount *sdk.KVStoreKey
|
||||||
keyIBC *sdk.KVStoreKey
|
keyIBC *sdk.KVStoreKey
|
||||||
keyStake *sdk.KVStoreKey
|
keyStake *sdk.KVStoreKey
|
||||||
|
tkeyStake *sdk.TransientStoreKey
|
||||||
keySlashing *sdk.KVStoreKey
|
keySlashing *sdk.KVStoreKey
|
||||||
keyGov *sdk.KVStoreKey
|
keyGov *sdk.KVStoreKey
|
||||||
keyFeeCollection *sdk.KVStoreKey
|
keyFeeCollection *sdk.KVStoreKey
|
||||||
|
@ -74,6 +75,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
||||||
keyAccount: sdk.NewKVStoreKey("acc"),
|
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||||
keyIBC: sdk.NewKVStoreKey("ibc"),
|
keyIBC: sdk.NewKVStoreKey("ibc"),
|
||||||
keyStake: sdk.NewKVStoreKey("stake"),
|
keyStake: sdk.NewKVStoreKey("stake"),
|
||||||
|
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
|
||||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||||
keyGov: sdk.NewKVStoreKey("gov"),
|
keyGov: sdk.NewKVStoreKey("gov"),
|
||||||
keyFeeCollection: sdk.NewKVStoreKey("fee"),
|
keyFeeCollection: sdk.NewKVStoreKey("fee"),
|
||||||
|
@ -92,7 +94,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
||||||
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
||||||
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||||
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
||||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
||||||
app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks())
|
app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks())
|
||||||
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
|
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
|
||||||
|
@ -114,8 +116,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
||||||
app.SetBeginBlocker(app.BeginBlocker)
|
app.SetBeginBlocker(app.BeginBlocker)
|
||||||
app.SetEndBlocker(app.EndBlocker)
|
app.SetEndBlocker(app.EndBlocker)
|
||||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake,
|
||||||
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
|
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
||||||
|
app.MountStoresTransient(app.tkeyParams, app.tkeyStake)
|
||||||
err := app.LoadLatestVersion(app.keyMain)
|
err := app.LoadLatestVersion(app.keyMain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmn.Exit(err.Error())
|
cmn.Exit(err.Error())
|
||||||
|
|
|
@ -89,19 +89,19 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json
|
||||||
return appState
|
return appState
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAndRunTxs(app *GaiaApp) []simulation.Operation {
|
func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
|
||||||
return []simulation.Operation{
|
return []simulation.WeightedOperation{
|
||||||
banksim.SimulateSingleInputMsgSend(app.accountMapper),
|
{100, banksim.SimulateSingleInputMsgSend(app.accountMapper)},
|
||||||
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper),
|
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
|
||||||
govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper),
|
{100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper),
|
{100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgEditValidator(app.stakeKeeper),
|
{5, stakesim.SimulateMsgEditValidator(app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper),
|
{100, stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper),
|
{100, stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper),
|
{100, stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper),
|
{100, stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper)},
|
||||||
stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper),
|
{100, stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper)},
|
||||||
slashingsim.SimulateMsgUnjail(app.slashingKeeper),
|
{100, slashingsim.SimulateMsgUnjail(app.slashingKeeper)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func BenchmarkFullGaiaSimulation(b *testing.B) {
|
||||||
|
|
||||||
// Run randomized simulation
|
// Run randomized simulation
|
||||||
// TODO parameterize numbers, save for a later PR
|
// TODO parameterize numbers, save for a later PR
|
||||||
simulation.SimulateFromSeed(
|
err := simulation.SimulateFromSeed(
|
||||||
b, app.BaseApp, appStateFn, seed,
|
b, app.BaseApp, appStateFn, seed,
|
||||||
testAndRunTxs(app),
|
testAndRunTxs(app),
|
||||||
[]simulation.RandSetup{},
|
[]simulation.RandSetup{},
|
||||||
|
@ -140,6 +140,10 @@ func BenchmarkFullGaiaSimulation(b *testing.B) {
|
||||||
blockSize,
|
blockSize,
|
||||||
commit,
|
commit,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
b.Fail()
|
||||||
|
}
|
||||||
if commit {
|
if commit {
|
||||||
fmt.Println("GoLevelDB Stats")
|
fmt.Println("GoLevelDB Stats")
|
||||||
fmt.Println(db.Stats()["leveldb.stats"])
|
fmt.Println(db.Stats()["leveldb.stats"])
|
||||||
|
@ -164,7 +168,7 @@ func TestFullGaiaSimulation(t *testing.T) {
|
||||||
require.Equal(t, "GaiaApp", app.Name())
|
require.Equal(t, "GaiaApp", app.Name())
|
||||||
|
|
||||||
// Run randomized simulation
|
// Run randomized simulation
|
||||||
simulation.SimulateFromSeed(
|
err := simulation.SimulateFromSeed(
|
||||||
t, app.BaseApp, appStateFn, seed,
|
t, app.BaseApp, appStateFn, seed,
|
||||||
testAndRunTxs(app),
|
testAndRunTxs(app),
|
||||||
[]simulation.RandSetup{},
|
[]simulation.RandSetup{},
|
||||||
|
@ -176,6 +180,7 @@ func TestFullGaiaSimulation(t *testing.T) {
|
||||||
if commit {
|
if commit {
|
||||||
fmt.Println("Database Size", db.Stats()["database.size"])
|
fmt.Println("Database Size", db.Stats()["database.size"])
|
||||||
}
|
}
|
||||||
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make another test for the fuzzer itself, which just has noOp txs
|
// TODO: Make another test for the fuzzer itself, which just has noOp txs
|
||||||
|
@ -204,9 +209,9 @@ func TestAppStateDeterminism(t *testing.T) {
|
||||||
[]simulation.Invariant{},
|
[]simulation.Invariant{},
|
||||||
50,
|
50,
|
||||||
100,
|
100,
|
||||||
false,
|
true,
|
||||||
)
|
)
|
||||||
app.Commit()
|
//app.Commit()
|
||||||
appHash := app.LastCommitID().Hash
|
appHash := app.LastCommitID().Hash
|
||||||
appHashList[j] = appHash
|
appHashList[j] = appHash
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,16 @@ func TestGaiaCLIGasAuto(t *testing.T) {
|
||||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
|
||||||
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
|
||||||
|
|
||||||
|
// Test failure with negative gas
|
||||||
|
success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=-100 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
||||||
|
require.False(t, success)
|
||||||
|
|
||||||
|
// Test failure with 0 gas
|
||||||
|
success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
||||||
|
require.False(t, success)
|
||||||
|
|
||||||
// Enable auto gas
|
// Enable auto gas
|
||||||
success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli send %v --json --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
success, stdout, _ := executeWriteRetStdStreams(t, fmt.Sprintf("gaiacli send %v --json --gas=simulate --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
// check that gas wanted == gas used
|
// check that gas wanted == gas used
|
||||||
cdc := app.MakeCodec()
|
cdc := app.MakeCodec()
|
||||||
|
@ -381,7 +389,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
|
||||||
|
|
||||||
// Test generate sendTx, estimate gas
|
// Test generate sendTx, estimate gas
|
||||||
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
success, stdout, stderr = executeWriteRetStdStreams(t, fmt.Sprintf(
|
||||||
"gaiacli send %v --amount=10steak --to=%s --from=foo --gas=0 --generate-only",
|
"gaiacli send %v --amount=10steak --to=%s --from=foo --gas=simulate --generate-only",
|
||||||
flags, barAddr), []string{}...)
|
flags, barAddr), []string{}...)
|
||||||
require.True(t, success)
|
require.True(t, success)
|
||||||
require.NotEmpty(t, stderr)
|
require.NotEmpty(t, stderr)
|
||||||
|
|
|
@ -134,6 +134,7 @@ type GaiaApp struct {
|
||||||
keyAccount *sdk.KVStoreKey
|
keyAccount *sdk.KVStoreKey
|
||||||
keyIBC *sdk.KVStoreKey
|
keyIBC *sdk.KVStoreKey
|
||||||
keyStake *sdk.KVStoreKey
|
keyStake *sdk.KVStoreKey
|
||||||
|
tkeyStake *sdk.TransientStoreKey
|
||||||
keySlashing *sdk.KVStoreKey
|
keySlashing *sdk.KVStoreKey
|
||||||
keyParams *sdk.KVStoreKey
|
keyParams *sdk.KVStoreKey
|
||||||
|
|
||||||
|
@ -161,6 +162,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
|
||||||
keyAccount: sdk.NewKVStoreKey("acc"),
|
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||||
keyIBC: sdk.NewKVStoreKey("ibc"),
|
keyIBC: sdk.NewKVStoreKey("ibc"),
|
||||||
keyStake: sdk.NewKVStoreKey("stake"),
|
keyStake: sdk.NewKVStoreKey("stake"),
|
||||||
|
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
|
||||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||||
keyParams: sdk.NewKVStoreKey("params"),
|
keyParams: sdk.NewKVStoreKey("params"),
|
||||||
}
|
}
|
||||||
|
@ -176,7 +178,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
|
||||||
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
||||||
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||||
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
|
||||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
|
||||||
|
|
||||||
// register message routes
|
// register message routes
|
||||||
|
|
|
@ -57,7 +57,9 @@ module.exports = {
|
||||||
{
|
{
|
||||||
title: "Lotion JS",
|
title: "Lotion JS",
|
||||||
collapsable: false,
|
collapsable: false,
|
||||||
children: [["/lotion/overview", "Overview"], "/lotion/building-an-app"]
|
children: [
|
||||||
|
["/lotion/overview", "Overview"]
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Validators",
|
title: "Validators",
|
||||||
|
|
|
@ -763,7 +763,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te
|
||||||
"chain_id": "string",
|
"chain_id": "string",
|
||||||
"account_number": 0,
|
"account_number": 0,
|
||||||
"sequence": 0,
|
"sequence": 0,
|
||||||
"gas": 0
|
"gas": "simulate"
|
||||||
},
|
},
|
||||||
"depositer": "string",
|
"depositer": "string",
|
||||||
"amount": 0,
|
"amount": 0,
|
||||||
|
@ -866,7 +866,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te
|
||||||
"chain_id": "string",
|
"chain_id": "string",
|
||||||
"account_number": 0,
|
"account_number": 0,
|
||||||
"sequence": 0,
|
"sequence": 0,
|
||||||
"gas": 0
|
"gas": "simulate"
|
||||||
},
|
},
|
||||||
// A cosmos address
|
// A cosmos address
|
||||||
"voter": "string",
|
"voter": "string",
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
# Building an App
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
Lotion requires __node v7.6.0__ or higher, and a mac or linux machine.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
```
|
|
||||||
$ npm install lotion
|
|
||||||
```
|
|
||||||
|
|
||||||
## Simple App
|
|
||||||
`app.js`:
|
|
||||||
```js
|
|
||||||
let lotion = require('lotion')
|
|
||||||
|
|
||||||
let app = lotion({
|
|
||||||
initialState: {
|
|
||||||
count: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.use(function (state, tx) {
|
|
||||||
if(state.count === tx.nonce) {
|
|
||||||
state.count++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.listen(3000)
|
|
||||||
```
|
|
||||||
|
|
||||||
run `node app.js`, then:
|
|
||||||
```bash
|
|
||||||
$ curl http://localhost:3000/state
|
|
||||||
# { "count": 0 }
|
|
||||||
|
|
||||||
$ curl http://localhost:3000/txs -d '{ "nonce": 0 }'
|
|
||||||
# { "ok": true }
|
|
||||||
|
|
||||||
$ curl http://localhost:3000/state
|
|
||||||
# { "count": 1 }
|
|
||||||
```
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
You can learn more about Lotion JS by visiting Lotion on [Github](https://github.com/keppel/lotion).
|
|
|
@ -1,5 +1,54 @@
|
||||||
# Lotion JS Overview
|
# Overview
|
||||||
|
|
||||||
Lotion is a new way to create blockchain apps in JavaScript, which aims to make writing new blockchains fast and fun. It builds on top of Tendermint using the ABCI protocol. Lotion lets you write secure, scalable applications that can easily interoperate with other blockchains on the Cosmos Network using IBC.
|
Lotion is an alternative to the Cosmos SDK and allows you to create blockchain apps in JavaScript. It aims to make writing new blockchain apps fast and easy by using the ABCI protocol to build on top of Tendermint. Lotion lets you write secure, scalable applications that can easily interoperate with other blockchains on the Cosmos Network using IBC.
|
||||||
|
|
||||||
Lotion itself is a tiny framework; its true power comes from the network of small, focused modules built upon it. Adding a fully-featured cryptocurrency to your blockchain, for example, takes only a few lines of code.
|
Lotion itself is a tiny framework; its true power comes from the network of small, focused modules built upon it. Adding a fully-featured cryptocurrency to your blockchain, for example, takes only a few lines of code.
|
||||||
|
|
||||||
|
For more information see the [website](https://lotionjs.com) and [GitHub repo](https://github.com/keppel/lotion), for complete documentation which expands on the following example.
|
||||||
|
|
||||||
|
## Building an App
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Lotion requires __node v7.6.0__ or higher, and a mac or linux machine.
|
||||||
|
:::
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install lotion
|
||||||
|
```
|
||||||
|
|
||||||
|
### Simple App
|
||||||
|
|
||||||
|
`app.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let lotion = require('lotion')
|
||||||
|
|
||||||
|
let app = lotion({
|
||||||
|
initialState: {
|
||||||
|
count: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.use(function (state, tx) {
|
||||||
|
if(state.count === tx.nonce) {
|
||||||
|
state.count++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(3000)
|
||||||
|
```
|
||||||
|
|
||||||
|
run `node app.js`, then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ curl http://localhost:3000/state
|
||||||
|
# { "count": 0 }
|
||||||
|
|
||||||
|
$ curl http://localhost:3000/txs -d '{ "nonce": 0 }'
|
||||||
|
# { "ok": true }
|
||||||
|
|
||||||
|
$ curl http://localhost:3000/state
|
||||||
|
# { "count": 1 }
|
||||||
|
```
|
||||||
|
|
|
@ -111,7 +111,7 @@ The `--amount` flag accepts the format `--amount=<value|coin_name>`.
|
||||||
|
|
||||||
::: tip Note
|
::: tip Note
|
||||||
You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag.
|
You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag.
|
||||||
If set to 0, the gas limit will be automatically estimated.
|
If you pass `--gas=simulate`, the gas limit will be automatically estimated.
|
||||||
Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.0.
|
Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.0.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ the changes cleared
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
EndBlock() ValidatorSetChanges
|
EndBlock() ValidatorSetChanges
|
||||||
vsc = GetTendermintUpdates()
|
vsc = GetValidTendermintUpdates()
|
||||||
ClearTendermintUpdates()
|
ClearTendermintUpdates()
|
||||||
return vsc
|
return vsc
|
||||||
```
|
```
|
||||||
|
|
|
@ -253,7 +253,7 @@ first time.
|
||||||
|
|
||||||
Accounts are serialized and stored in a Merkle tree under the key
|
Accounts are serialized and stored in a Merkle tree under the key
|
||||||
``base/a/<address>``, where ``<address>`` is the address of the account.
|
``base/a/<address>``, where ``<address>`` is the address of the account.
|
||||||
Typically, the address of the account is the 20-byte ``RIPEMD160`` hash
|
Typically, the address of the account is the first 20-bytes of the ``sha256`` hash
|
||||||
of the public key, but other formats are acceptable as well, as defined
|
of the public key, but other formats are acceptable as well, as defined
|
||||||
in the `Tendermint crypto
|
in the `Tendermint crypto
|
||||||
library <https://github.com/tendermint/tendermint/tree/master/crypto>`__. The Merkle tree
|
library <https://github.com/tendermint/tendermint/tree/master/crypto>`__. The Merkle tree
|
||||||
|
|
|
@ -55,7 +55,7 @@ func getMockApp(t *testing.T) *mock.App {
|
||||||
|
|
||||||
mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold"))
|
mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold"))
|
||||||
|
|
||||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyCool}))
|
require.NoError(t, mapp.CompleteSetup(keyCool))
|
||||||
return mapp
|
return mapp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ func getMockApp(t *testing.T) *mock.App {
|
||||||
|
|
||||||
mapp.SetInitChainer(getInitChainer(mapp, keeper))
|
mapp.SetInitChainer(getInitChainer(mapp, keeper))
|
||||||
|
|
||||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyPOW}))
|
require.NoError(t, mapp.CompleteSetup(keyPOW))
|
||||||
|
|
||||||
mapp.Seal()
|
mapp.Seal()
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ var (
|
||||||
nodeDirPrefix = "node-dir-prefix"
|
nodeDirPrefix = "node-dir-prefix"
|
||||||
nValidators = "v"
|
nValidators = "v"
|
||||||
outputDir = "output-dir"
|
outputDir = "output-dir"
|
||||||
|
nodeDaemonHome = "node-daemon-home"
|
||||||
|
nodeCliHome = "node-cli-home"
|
||||||
|
|
||||||
startingIPAddress = "starting-ip-address"
|
startingIPAddress = "starting-ip-address"
|
||||||
)
|
)
|
||||||
|
@ -39,7 +41,7 @@ Note, strict routability for addresses is turned off in the config file.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
gaiad testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2
|
gaiad testnet --v 4 --o ./output --starting-ip-address 192.168.10.2
|
||||||
`,
|
`,
|
||||||
RunE: func(_ *cobra.Command, _ []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
config := ctx.Config
|
config := ctx.Config
|
||||||
|
@ -53,6 +55,10 @@ Example:
|
||||||
"Directory to store initialization data for the testnet")
|
"Directory to store initialization data for the testnet")
|
||||||
cmd.Flags().String(nodeDirPrefix, "node",
|
cmd.Flags().String(nodeDirPrefix, "node",
|
||||||
"Prefix the directory name for each node with (node results in node0, node1, ...)")
|
"Prefix the directory name for each node with (node results in node0, node1, ...)")
|
||||||
|
cmd.Flags().String(nodeDaemonHome, "gaiad",
|
||||||
|
"Home directory of the node's daemon configuration")
|
||||||
|
cmd.Flags().String(nodeCliHome, "gaiacli",
|
||||||
|
"Home directory of the node's cli configuration")
|
||||||
|
|
||||||
cmd.Flags().String(startingIPAddress, "192.168.0.1",
|
cmd.Flags().String(startingIPAddress, "192.168.0.1",
|
||||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||||
|
@ -66,8 +72,10 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err
|
||||||
// Generate private key, node ID, initial transaction
|
// Generate private key, node ID, initial transaction
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
||||||
nodeDir := filepath.Join(outDir, nodeDirName, "gaiad")
|
nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
|
||||||
clientDir := filepath.Join(outDir, nodeDirName, "gaiacli")
|
nodeCliHomeName := viper.GetString(nodeCliHome)
|
||||||
|
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
||||||
|
clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName)
|
||||||
gentxsDir := filepath.Join(outDir, "gentxs")
|
gentxsDir := filepath.Join(outDir, "gentxs")
|
||||||
config.SetRoot(nodeDir)
|
config.SetRoot(nodeDir)
|
||||||
|
|
||||||
|
@ -122,7 +130,8 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
|
|
||||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
||||||
nodeDir := filepath.Join(outDir, nodeDirName, "gaiad")
|
nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
|
||||||
|
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
||||||
gentxsDir := filepath.Join(outDir, "gentxs")
|
gentxsDir := filepath.Join(outDir, "gentxs")
|
||||||
initConfig := InitConfig{
|
initConfig := InitConfig{
|
||||||
chainID,
|
chainID,
|
||||||
|
|
|
@ -51,6 +51,10 @@ func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = validateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||||
logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel())
|
logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,6 +100,14 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate the config with the sdk's requirements.
|
||||||
|
func validateConfig(conf *cfg.Config) error {
|
||||||
|
if conf.Consensus.CreateEmptyBlocks == false {
|
||||||
|
return errors.New("config option CreateEmptyBlocks = false is currently unsupported")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// add server commands
|
// add server commands
|
||||||
func AddCommands(
|
func AddCommands(
|
||||||
ctx *Context, cdc *wire.Codec,
|
ctx *Context, cdc *wire.Codec,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tendermint/iavl"
|
"github.com/tendermint/iavl"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
@ -47,7 +48,6 @@ func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHas
|
||||||
Version: height,
|
Version: height,
|
||||||
StoreInfos: storeInfos,
|
StoreInfos: storeInfos,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(appHash, ci.Hash()) {
|
if !bytes.Equal(appHash, ci.Hash()) {
|
||||||
return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash")
|
return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tendermint/iavl"
|
"github.com/tendermint/iavl"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
"github.com/tendermint/tendermint/libs/db"
|
"github.com/tendermint/tendermint/libs/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVerifyMultiStoreCommitInfo(t *testing.T) {
|
func TestVerifyMultiStoreCommitInfo(t *testing.T) {
|
||||||
appHash, _ := hex.DecodeString("ebf3c1fb724d3458023c8fefef7b33add2fc1e84")
|
appHash, _ := hex.DecodeString("69959B1B4E68E0F7BD3551A50C8F849B81801AF2")
|
||||||
|
|
||||||
substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828")
|
substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828")
|
||||||
storeName := "acc"
|
storeName := "acc"
|
||||||
|
@ -83,13 +84,13 @@ func TestVerifyMultiStoreCommitInfo(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
commitHash, err := VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash)
|
commitHash, err := VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash)
|
||||||
assert.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, commitHash, substoreRootHash)
|
require.Equal(t, commitHash, substoreRootHash)
|
||||||
|
|
||||||
appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3")
|
appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3")
|
||||||
|
|
||||||
_, err = VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash)
|
_, err = VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash)
|
||||||
assert.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo")
|
require.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyRangeProof(t *testing.T) {
|
func TestVerifyRangeProof(t *testing.T) {
|
||||||
|
|
|
@ -5,10 +5,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/crypto/ripemd160"
|
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/crypto/merkle"
|
"github.com/tendermint/tendermint/crypto/merkle"
|
||||||
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
@ -424,7 +423,7 @@ func (si storeInfo) Hash() []byte {
|
||||||
// Doesn't write Name, since merkle.SimpleHashFromMap() will
|
// Doesn't write Name, since merkle.SimpleHashFromMap() will
|
||||||
// include them via the keys.
|
// include them via the keys.
|
||||||
bz, _ := cdc.MarshalBinary(si.Core) // Does not error
|
bz, _ := cdc.MarshalBinary(si.Core) // Does not error
|
||||||
hasher := ripemd160.New()
|
hasher := tmhash.New()
|
||||||
_, err := hasher.Write(bz)
|
_, err := hasher.Write(bz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Handle with #870
|
// TODO: Handle with #870
|
||||||
|
|
|
@ -16,7 +16,9 @@ type TxBuilder struct {
|
||||||
Codec *wire.Codec
|
Codec *wire.Codec
|
||||||
AccountNumber int64
|
AccountNumber int64
|
||||||
Sequence int64
|
Sequence int64
|
||||||
Gas int64
|
Gas int64 // TODO: should this turn into uint64? requires further discussion - see #2173
|
||||||
|
GasAdjustment float64
|
||||||
|
SimulateGas bool
|
||||||
ChainID string
|
ChainID string
|
||||||
Memo string
|
Memo string
|
||||||
Fee string
|
Fee string
|
||||||
|
@ -36,9 +38,11 @@ func NewTxBuilderFromCLI() TxBuilder {
|
||||||
|
|
||||||
return TxBuilder{
|
return TxBuilder{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
Gas: viper.GetInt64(client.FlagGas),
|
|
||||||
AccountNumber: viper.GetInt64(client.FlagAccountNumber),
|
AccountNumber: viper.GetInt64(client.FlagAccountNumber),
|
||||||
|
Gas: client.GasFlagVar.Gas,
|
||||||
|
GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment),
|
||||||
Sequence: viper.GetInt64(client.FlagSequence),
|
Sequence: viper.GetInt64(client.FlagSequence),
|
||||||
|
SimulateGas: client.GasFlagVar.Simulate,
|
||||||
Fee: viper.GetString(client.FlagFee),
|
Fee: viper.GetString(client.FlagFee),
|
||||||
Memo: viper.GetString(client.FlagMemo),
|
Memo: viper.GetString(client.FlagMemo),
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func getBenchmarkMockApp() (*mock.App, error) {
|
||||||
bankKeeper := NewBaseKeeper(mapp.AccountMapper)
|
bankKeeper := NewBaseKeeper(mapp.AccountMapper)
|
||||||
mapp.Router().AddRoute("bank", NewHandler(bankKeeper))
|
mapp.Router().AddRoute("bank", NewHandler(bankKeeper))
|
||||||
|
|
||||||
err := mapp.CompleteSetup([]*sdk.KVStoreKey{})
|
err := mapp.CompleteSetup()
|
||||||
return mapp, err
|
return mapp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ type sendBody struct {
|
||||||
ChainID string `json:"chain_id"`
|
ChainID string `json:"chain_id"`
|
||||||
AccountNumber int64 `json:"account_number"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequence int64 `json:"sequence"`
|
Sequence int64 `json:"sequence"`
|
||||||
Gas int64 `json:"gas"`
|
Gas string `json:"gas"`
|
||||||
GasAdjustment string `json:"gas_adjustment"`
|
GasAdjustment string `json:"gas_adjustment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,31 +81,37 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
txBldr := authtxb.TxBuilder{
|
simulateGas, gas, err := cliclient.ReadGasFlag(m.Gas)
|
||||||
Codec: cdc,
|
if err != nil {
|
||||||
Gas: m.Gas,
|
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
ChainID: m.ChainID,
|
return
|
||||||
AccountNumber: m.AccountNumber,
|
|
||||||
Sequence: m.Sequence,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, cliclient.DefaultGasAdjustment)
|
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, cliclient.DefaultGasAdjustment)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cliCtx = cliCtx.WithGasAdjustment(adjustment)
|
txBldr := authtxb.TxBuilder{
|
||||||
|
Codec: cdc,
|
||||||
|
Gas: gas,
|
||||||
|
GasAdjustment: adjustment,
|
||||||
|
SimulateGas: simulateGas,
|
||||||
|
ChainID: m.ChainID,
|
||||||
|
AccountNumber: m.AccountNumber,
|
||||||
|
Sequence: m.Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
if utils.HasDryRunArg(r) || m.Gas == 0 {
|
if utils.HasDryRunArg(r) || txBldr.SimulateGas {
|
||||||
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if utils.HasDryRunArg(r) {
|
if utils.HasDryRunArg(r) {
|
||||||
utils.WriteSimulationResponse(w, txBldr.Gas)
|
utils.WriteSimulationResponse(w, newBldr.Gas)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txBldr = newCtx
|
txBldr = newBldr
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.HasGenerateOnlyArg(r) {
|
if utils.HasGenerateOnlyArg(r) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ func TestBankWithRandomMessages(t *testing.T) {
|
||||||
bankKeeper := bank.NewBaseKeeper(mapper)
|
bankKeeper := bank.NewBaseKeeper(mapper)
|
||||||
mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper))
|
mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper))
|
||||||
|
|
||||||
err := mapp.CompleteSetup([]*sdk.KVStoreKey{})
|
err := mapp.CompleteSetup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ func TestBankWithRandomMessages(t *testing.T) {
|
||||||
|
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.Operation{
|
[]simulation.WeightedOperation{
|
||||||
SimulateSingleInputMsgSend(mapper),
|
{1, SimulateSingleInputMsgSend(mapper)},
|
||||||
},
|
},
|
||||||
[]simulation.RandSetup{},
|
[]simulation.RandSetup{},
|
||||||
[]simulation.Invariant{
|
[]simulation.Invariant{
|
||||||
|
|
|
@ -20,7 +20,7 @@ type baseReq struct {
|
||||||
ChainID string `json:"chain_id"`
|
ChainID string `json:"chain_id"`
|
||||||
AccountNumber int64 `json:"account_number"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequence int64 `json:"sequence"`
|
Sequence int64 `json:"sequence"`
|
||||||
Gas int64 `json:"gas"`
|
Gas string `json:"gas"`
|
||||||
GasAdjustment string `json:"gas_adjustment"`
|
GasAdjustment string `json:"gas_adjustment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,32 +69,37 @@ func (req baseReq) baseReqValidate(w http.ResponseWriter) bool {
|
||||||
// TODO: Build this function out into a more generic base-request
|
// TODO: Build this function out into a more generic base-request
|
||||||
// (probably should live in client/lcd).
|
// (probably should live in client/lcd).
|
||||||
func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) {
|
func signAndBuild(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) {
|
||||||
var err error
|
simulateGas, gas, err := client.ReadGasFlag(baseReq.Gas)
|
||||||
txBldr := authtxb.TxBuilder{
|
if err != nil {
|
||||||
Codec: cdc,
|
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
AccountNumber: baseReq.AccountNumber,
|
return
|
||||||
Sequence: baseReq.Sequence,
|
|
||||||
ChainID: baseReq.ChainID,
|
|
||||||
Gas: baseReq.Gas,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment)
|
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cliCtx = cliCtx.WithGasAdjustment(adjustment)
|
txBldr := authtxb.TxBuilder{
|
||||||
|
Codec: cdc,
|
||||||
|
Gas: gas,
|
||||||
|
GasAdjustment: adjustment,
|
||||||
|
SimulateGas: simulateGas,
|
||||||
|
ChainID: baseReq.ChainID,
|
||||||
|
AccountNumber: baseReq.AccountNumber,
|
||||||
|
Sequence: baseReq.Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
if utils.HasDryRunArg(r) || baseReq.Gas == 0 {
|
if utils.HasDryRunArg(r) || txBldr.SimulateGas {
|
||||||
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg})
|
newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if utils.HasDryRunArg(r) {
|
if utils.HasDryRunArg(r) {
|
||||||
utils.WriteSimulationResponse(w, txBldr.Gas)
|
utils.WriteSimulationResponse(w, newBldr.Gas)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txBldr = newCtx
|
txBldr = newBldr
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.HasGenerateOnlyArg(r) {
|
if utils.HasGenerateOnlyArg(r) {
|
||||||
|
|
|
@ -114,8 +114,14 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
|
resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
|
||||||
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
||||||
|
|
||||||
logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted",
|
logger.Info(
|
||||||
inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit()))
|
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %v steak); deleted",
|
||||||
|
inactiveProposal.GetProposalID(),
|
||||||
|
inactiveProposal.GetTitle(),
|
||||||
|
keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"),
|
||||||
|
inactiveProposal.GetTotalDeposit().AmountOf("steak"),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if earliest Active Proposal ended voting period yet
|
// Check if earliest Active Proposal ended voting period yet
|
||||||
|
@ -143,7 +149,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
activeProposal.SetTallyResult(tallyResults)
|
activeProposal.SetTallyResult(tallyResults)
|
||||||
keeper.SetProposal(ctx, activeProposal)
|
keeper.SetProposal(ctx, activeProposal)
|
||||||
|
|
||||||
logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - tallied, passed: %v",
|
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
|
||||||
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))
|
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))
|
||||||
|
|
||||||
for _, valAddr := range nonVotingVals {
|
for _, valAddr := range nonVotingVals {
|
||||||
|
@ -154,7 +160,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
val.GetPower().RoundInt64(),
|
val.GetPower().RoundInt64(),
|
||||||
keeper.GetTallyingProcedure(ctx).GovernancePenalty)
|
keeper.GetTallyingProcedure(ctx).GovernancePenalty)
|
||||||
|
|
||||||
logger.Info(fmt.Sprintf("Validator %s failed to vote on proposal %d, slashing",
|
logger.Info(fmt.Sprintf("validator %s failed to vote on proposal %d; slashing",
|
||||||
val.GetOperator(), activeProposal.GetProposalID()))
|
val.GetOperator(), activeProposal.GetProposalID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,22 +8,33 @@ import (
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// query endpoints supported by the governance Querier
|
||||||
|
const (
|
||||||
|
QueryProposals = "proposals"
|
||||||
|
QueryProposal = "proposal"
|
||||||
|
QueryDeposits = "deposits"
|
||||||
|
QueryDeposit = "deposit"
|
||||||
|
QueryVotes = "votes"
|
||||||
|
QueryVote = "vote"
|
||||||
|
QueryTally = "tally"
|
||||||
|
)
|
||||||
|
|
||||||
func NewQuerier(keeper Keeper) sdk.Querier {
|
func NewQuerier(keeper Keeper) sdk.Querier {
|
||||||
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
|
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
|
||||||
switch path[0] {
|
switch path[0] {
|
||||||
case "proposal":
|
case QueryProposals:
|
||||||
return queryProposal(ctx, path[1:], req, keeper)
|
|
||||||
case "deposit":
|
|
||||||
return queryDeposit(ctx, path[1:], req, keeper)
|
|
||||||
case "vote":
|
|
||||||
return queryVote(ctx, path[1:], req, keeper)
|
|
||||||
case "deposits":
|
|
||||||
return queryDeposits(ctx, path[1:], req, keeper)
|
|
||||||
case "votes":
|
|
||||||
return queryVotes(ctx, path[1:], req, keeper)
|
|
||||||
case "proposals":
|
|
||||||
return queryProposals(ctx, path[1:], req, keeper)
|
return queryProposals(ctx, path[1:], req, keeper)
|
||||||
case "tally":
|
case QueryProposal:
|
||||||
|
return queryProposal(ctx, path[1:], req, keeper)
|
||||||
|
case QueryDeposits:
|
||||||
|
return queryDeposits(ctx, path[1:], req, keeper)
|
||||||
|
case QueryDeposit:
|
||||||
|
return queryDeposit(ctx, path[1:], req, keeper)
|
||||||
|
case QueryVotes:
|
||||||
|
return queryVotes(ctx, path[1:], req, keeper)
|
||||||
|
case QueryVote:
|
||||||
|
return queryVote(ctx, path[1:], req, keeper)
|
||||||
|
case QueryTally:
|
||||||
return queryTally(ctx, path[1:], req, keeper)
|
return queryTally(ctx, path[1:], req, keeper)
|
||||||
default:
|
default:
|
||||||
return nil, sdk.ErrUnknownRequest("unknown gov query endpoint")
|
return nil, sdk.ErrUnknownRequest("unknown gov query endpoint")
|
||||||
|
|
|
@ -156,13 +156,16 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
||||||
return operationSimulateMsgVote(k, sk, nil, -1)
|
return operationSimulateMsgVote(k, sk, nil, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
|
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||||
if key == nil {
|
if key == nil {
|
||||||
key = simulation.RandomKey(r, keys)
|
key = simulation.RandomKey(r, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if proposalID < 0 {
|
if proposalID < 0 {
|
||||||
proposalID, ok = randomProposalID(r, k, ctx)
|
proposalID, ok = randomProposalID(r, k, ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -171,15 +174,18 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey,
|
||||||
}
|
}
|
||||||
addr := sdk.AccAddress(key.PubKey().Address())
|
addr := sdk.AccAddress(key.PubKey().Address())
|
||||||
option := randomVotingOption(r)
|
option := randomVotingOption(r)
|
||||||
|
|
||||||
msg := gov.NewMsgVote(addr, proposalID, option)
|
msg := gov.NewMsgVote(addr, proposalID, option)
|
||||||
if msg.ValidateBasic() != nil {
|
if msg.ValidateBasic() != nil {
|
||||||
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, write := ctx.CacheContext()
|
||||||
result := gov.NewHandler(k)(ctx, msg)
|
result := gov.NewHandler(k)(ctx, msg)
|
||||||
if result.IsOK() {
|
if result.IsOK() {
|
||||||
write()
|
write()
|
||||||
}
|
}
|
||||||
|
|
||||||
event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK()))
|
event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK()))
|
||||||
action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
||||||
return action, nil, nil
|
return action, nil, nil
|
||||||
|
|
|
@ -26,7 +26,8 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
mapper := mapp.AccountMapper
|
mapper := mapp.AccountMapper
|
||||||
bankKeeper := bank.NewBaseKeeper(mapper)
|
bankKeeper := bank.NewBaseKeeper(mapper)
|
||||||
stakeKey := sdk.NewKVStoreKey("stake")
|
stakeKey := sdk.NewKVStoreKey("stake")
|
||||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace)
|
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
|
||||||
|
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
|
||||||
paramKey := sdk.NewKVStoreKey("params")
|
paramKey := sdk.NewKVStoreKey("params")
|
||||||
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey)
|
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey)
|
||||||
govKey := sdk.NewKVStoreKey("gov")
|
govKey := sdk.NewKVStoreKey("gov")
|
||||||
|
@ -37,7 +38,7 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
return abci.ResponseEndBlock{}
|
return abci.ResponseEndBlock{}
|
||||||
})
|
})
|
||||||
|
|
||||||
err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey, paramKey, govKey})
|
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, govKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -56,10 +57,10 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
// Test with unscheduled votes
|
// Test with unscheduled votes
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.Operation{
|
[]simulation.WeightedOperation{
|
||||||
SimulateMsgSubmitProposal(govKeeper, stakeKeeper),
|
{2, SimulateMsgSubmitProposal(govKeeper, stakeKeeper)},
|
||||||
SimulateMsgDeposit(govKeeper, stakeKeeper),
|
{3, SimulateMsgDeposit(govKeeper, stakeKeeper)},
|
||||||
SimulateMsgVote(govKeeper, stakeKeeper),
|
{20, SimulateMsgVote(govKeeper, stakeKeeper)},
|
||||||
}, []simulation.RandSetup{
|
}, []simulation.RandSetup{
|
||||||
setup,
|
setup,
|
||||||
}, []simulation.Invariant{
|
}, []simulation.Invariant{
|
||||||
|
@ -71,9 +72,9 @@ func TestGovWithRandomMessages(t *testing.T) {
|
||||||
// Test with scheduled votes
|
// Test with scheduled votes
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.Operation{
|
[]simulation.WeightedOperation{
|
||||||
SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper),
|
{10, SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper)},
|
||||||
SimulateMsgDeposit(govKeeper, stakeKeeper),
|
{5, SimulateMsgDeposit(govKeeper, stakeKeeper)},
|
||||||
}, []simulation.RandSetup{
|
}, []simulation.RandSetup{
|
||||||
setup,
|
setup,
|
||||||
}, []simulation.Invariant{
|
}, []simulation.Invariant{
|
||||||
|
|
|
@ -28,18 +28,19 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
|
||||||
|
|
||||||
keyGlobalParams := sdk.NewKVStoreKey("params")
|
keyGlobalParams := sdk.NewKVStoreKey("params")
|
||||||
keyStake := sdk.NewKVStoreKey("stake")
|
keyStake := sdk.NewKVStoreKey("stake")
|
||||||
|
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||||
keyGov := sdk.NewKVStoreKey("gov")
|
keyGov := sdk.NewKVStoreKey("gov")
|
||||||
|
|
||||||
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams)
|
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams)
|
||||||
ck := bank.NewBaseKeeper(mapp.AccountMapper)
|
ck := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||||
sk := stake.NewKeeper(mapp.Cdc, keyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
|
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||||
keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace)
|
keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace)
|
||||||
mapp.Router().AddRoute("gov", NewHandler(keeper))
|
mapp.Router().AddRoute("gov", NewHandler(keeper))
|
||||||
|
|
||||||
mapp.SetEndBlocker(getEndBlocker(keeper))
|
mapp.SetEndBlocker(getEndBlocker(keeper))
|
||||||
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
|
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
|
||||||
|
|
||||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keyGov, keyGlobalParams}))
|
require.NoError(t, mapp.CompleteSetup(keyStake, keyGov, keyGlobalParams, tkeyStake))
|
||||||
|
|
||||||
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})
|
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ func getMockApp(t *testing.T) *mock.App {
|
||||||
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||||
mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper))
|
mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper))
|
||||||
|
|
||||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyIBC}))
|
require.NoError(t, mapp.CompleteSetup(keyIBC))
|
||||||
return mapp
|
return mapp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ type transferBody struct {
|
||||||
SrcChainID string `json:"src_chain_id"`
|
SrcChainID string `json:"src_chain_id"`
|
||||||
AccountNumber int64 `json:"account_number"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequence int64 `json:"sequence"`
|
Sequence int64 `json:"sequence"`
|
||||||
Gas int64 `json:"gas"`
|
Gas string `json:"gas"`
|
||||||
GasAdjustment string `json:"gas_adjustment"`
|
GasAdjustment string `json:"gas_adjustment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,21 +71,26 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C
|
||||||
packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID)
|
packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID)
|
||||||
msg := ibc.IBCTransferMsg{packet}
|
msg := ibc.IBCTransferMsg{packet}
|
||||||
|
|
||||||
txBldr := authtxb.TxBuilder{
|
simulateGas, gas, err := client.ReadGasFlag(m.Gas)
|
||||||
Codec: cdc,
|
if err != nil {
|
||||||
ChainID: m.SrcChainID,
|
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
AccountNumber: m.AccountNumber,
|
return
|
||||||
Sequence: m.Sequence,
|
|
||||||
Gas: m.Gas,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cliCtx = cliCtx.WithGasAdjustment(adjustment)
|
txBldr := authtxb.TxBuilder{
|
||||||
|
Codec: cdc,
|
||||||
|
Gas: gas,
|
||||||
|
GasAdjustment: adjustment,
|
||||||
|
SimulateGas: simulateGas,
|
||||||
|
ChainID: m.SrcChainID,
|
||||||
|
AccountNumber: m.AccountNumber,
|
||||||
|
Sequence: m.Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
if utils.HasDryRunArg(r) || m.Gas == 0 {
|
if utils.HasDryRunArg(r) || txBldr.SimulateGas {
|
||||||
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package mock
|
package mock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -75,11 +76,21 @@ func NewApp() *App {
|
||||||
|
|
||||||
// CompleteSetup completes the application setup after the routes have been
|
// CompleteSetup completes the application setup after the routes have been
|
||||||
// registered.
|
// registered.
|
||||||
func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error {
|
func (app *App) CompleteSetup(newKeys ...sdk.StoreKey) error {
|
||||||
newKeys = append(newKeys, app.KeyMain)
|
newKeys = append(newKeys, app.KeyMain)
|
||||||
newKeys = append(newKeys, app.KeyAccount)
|
newKeys = append(newKeys, app.KeyAccount)
|
||||||
|
|
||||||
app.MountStoresIAVL(newKeys...)
|
for _, key := range newKeys {
|
||||||
|
switch key.(type) {
|
||||||
|
case *sdk.KVStoreKey:
|
||||||
|
app.MountStore(key, sdk.StoreTypeIAVL)
|
||||||
|
case *sdk.TransientStoreKey:
|
||||||
|
app.MountStore(key, sdk.StoreTypeTransient)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported StoreKey: %+v", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := app.LoadLatestVersion(app.KeyMain)
|
err := app.LoadLatestVersion(app.KeyMain)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -41,7 +41,7 @@ func getMockApp(t *testing.T) *App {
|
||||||
mApp := NewApp()
|
mApp := NewApp()
|
||||||
|
|
||||||
mApp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return })
|
mApp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return })
|
||||||
require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{}))
|
require.NoError(t, mApp.CompleteSetup())
|
||||||
|
|
||||||
return mApp
|
return mApp
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime/debug"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -23,12 +24,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Simulate tests application by sending random messages.
|
// Simulate tests application by sending random messages.
|
||||||
func Simulate(
|
func Simulate(t *testing.T, app *baseapp.BaseApp,
|
||||||
t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []Operation, setups []RandSetup,
|
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
|
||||||
invariants []Invariant, numBlocks int, blockSize int, commit bool,
|
ops []WeightedOperation, setups []RandSetup,
|
||||||
) {
|
invariants []Invariant, numBlocks int, blockSize int, commit bool) error {
|
||||||
|
|
||||||
time := time.Now().UnixNano()
|
time := time.Now().UnixNano()
|
||||||
SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
|
return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp,
|
func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp,
|
||||||
|
@ -53,10 +55,13 @@ func randTimestamp(r *rand.Rand) time.Time {
|
||||||
|
|
||||||
// SimulateFromSeed tests an application by running the provided
|
// SimulateFromSeed tests an application by running the provided
|
||||||
// operations, testing the provided invariants, but using the provided seed.
|
// operations, testing the provided invariants, but using the provided seed.
|
||||||
func SimulateFromSeed(
|
func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
|
||||||
tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup,
|
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
|
||||||
invariants []Invariant, numBlocks int, blockSize int, commit bool,
|
seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant,
|
||||||
) {
|
numBlocks int, blockSize int, commit bool) (simError error) {
|
||||||
|
|
||||||
|
// in case we have to end early, don't os.Exit so that we can run cleanup code.
|
||||||
|
stopEarly := false
|
||||||
testingMode, t, b := getTestingMode(tb)
|
testingMode, t, b := getTestingMode(tb)
|
||||||
fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
|
fmt.Printf("Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
|
||||||
r := rand.New(rand.NewSource(seed))
|
r := rand.New(rand.NewSource(seed))
|
||||||
|
@ -79,12 +84,12 @@ func SimulateFromSeed(
|
||||||
|
|
||||||
// Setup code to catch SIGTERM's
|
// Setup code to catch SIGTERM's
|
||||||
c := make(chan os.Signal)
|
c := make(chan os.Signal)
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
|
||||||
go func() {
|
go func() {
|
||||||
<-c
|
receivedSignal := <-c
|
||||||
fmt.Printf("Exiting early due to SIGTERM, on block %d, operation %d\n", header.Height, opCount)
|
fmt.Printf("Exiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount)
|
||||||
DisplayEvents(events)
|
simError = fmt.Errorf("Exited due to %s", receivedSignal)
|
||||||
os.Exit(128 + int(syscall.SIGTERM))
|
stopEarly = true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var pastTimes []time.Time
|
var pastTimes []time.Time
|
||||||
|
@ -95,15 +100,27 @@ func SimulateFromSeed(
|
||||||
operationQueue := make(map[int][]Operation)
|
operationQueue := make(map[int][]Operation)
|
||||||
var blockLogBuilders []*strings.Builder
|
var blockLogBuilders []*strings.Builder
|
||||||
|
|
||||||
if !testingMode {
|
if testingMode {
|
||||||
b.ResetTimer()
|
|
||||||
} else {
|
|
||||||
blockLogBuilders = make([]*strings.Builder, numBlocks)
|
blockLogBuilders = make([]*strings.Builder, numBlocks)
|
||||||
}
|
}
|
||||||
displayLogs := logPrinter(testingMode, blockLogBuilders)
|
displayLogs := logPrinter(testingMode, blockLogBuilders)
|
||||||
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks, displayLogs)
|
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks, displayLogs)
|
||||||
|
if !testingMode {
|
||||||
|
b.ResetTimer()
|
||||||
|
} else {
|
||||||
|
// Recover logs in case of panic
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Println("Panic with err\n", r)
|
||||||
|
stackTrace := string(debug.Stack())
|
||||||
|
fmt.Println(stackTrace)
|
||||||
|
displayLogs()
|
||||||
|
simError = fmt.Errorf("Simulation halted due to panic on block %d", header.Height)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < numBlocks; i++ {
|
for i := 0; i < numBlocks && !stopEarly; i++ {
|
||||||
// Log the header time for future lookup
|
// Log the header time for future lookup
|
||||||
pastTimes = append(pastTimes, header.Time)
|
pastTimes = append(pastTimes, header.Time)
|
||||||
pastSigningValidators = append(pastSigningValidators, request.LastCommitInfo.Validators)
|
pastSigningValidators = append(pastSigningValidators, request.LastCommitInfo.Validators)
|
||||||
|
@ -122,10 +139,9 @@ func SimulateFromSeed(
|
||||||
|
|
||||||
// Run queued operations. Ignores blocksize if blocksize is too small
|
// Run queued operations. Ignores blocksize if blocksize is too small
|
||||||
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event)
|
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event)
|
||||||
opCount += numQueuedOpsRan
|
|
||||||
thisBlockSize -= numQueuedOpsRan
|
thisBlockSize -= numQueuedOpsRan
|
||||||
operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter)
|
operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter)
|
||||||
opCount += operations
|
opCount += operations + numQueuedOpsRan
|
||||||
|
|
||||||
res := app.EndBlock(abci.RequestEndBlock{})
|
res := app.EndBlock(abci.RequestEndBlock{})
|
||||||
header.Height++
|
header.Height++
|
||||||
|
@ -146,19 +162,38 @@ func SimulateFromSeed(
|
||||||
// Update the validator set
|
// Update the validator set
|
||||||
validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event)
|
validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event)
|
||||||
}
|
}
|
||||||
|
if stopEarly {
|
||||||
|
DisplayEvents(events)
|
||||||
|
return
|
||||||
|
}
|
||||||
fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount)
|
fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount)
|
||||||
DisplayEvents(events)
|
DisplayEvents(events)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
|
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
|
||||||
// memory overhead
|
// memory overhead
|
||||||
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func(
|
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func(
|
||||||
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
|
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
|
||||||
|
totalOpWeight := 0
|
||||||
|
for i := 0; i < len(ops); i++ {
|
||||||
|
totalOpWeight += ops[i].Weight
|
||||||
|
}
|
||||||
|
selectOp := func(r *rand.Rand) Operation {
|
||||||
|
x := r.Intn(totalOpWeight)
|
||||||
|
for i := 0; i < len(ops); i++ {
|
||||||
|
if x <= ops[i].Weight {
|
||||||
|
return ops[i].Op
|
||||||
|
}
|
||||||
|
x -= ops[i].Weight
|
||||||
|
}
|
||||||
|
// shouldn't happen
|
||||||
|
return ops[0].Op
|
||||||
|
}
|
||||||
return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||||
keys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
|
keys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
|
||||||
for j := 0; j < blocksize; j++ {
|
for j := 0; j < blocksize; j++ {
|
||||||
logUpdate, futureOps, err := ops[r.Intn(len(ops))](r, app, ctx, keys, event)
|
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, keys, event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
displayLogs()
|
displayLogs()
|
||||||
tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err)
|
tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err)
|
||||||
|
@ -324,18 +359,14 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator,
|
||||||
// updateValidators mimicks Tendermint's update logic
|
// updateValidators mimicks Tendermint's update logic
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
||||||
|
|
||||||
for _, update := range updates {
|
for _, update := range updates {
|
||||||
switch {
|
switch {
|
||||||
case update.Power == 0:
|
case update.Power == 0:
|
||||||
// // TEMPORARY DEBUG CODE TO PROVE THAT THE OLD METHOD WAS BROKEN
|
if _, ok := current[string(update.PubKey.Data)]; !ok {
|
||||||
// // (i.e. didn't catch in the event of problem)
|
tb.Fatalf("tried to delete a nonexistent validator")
|
||||||
// if val, ok := tb.(*testing.T); ok {
|
}
|
||||||
// require.NotNil(val, current[string(update.PubKey.Data)])
|
|
||||||
// }
|
|
||||||
// // CORRECT CHECK
|
|
||||||
// if _, ok := current[string(update.PubKey.Data)]; !ok {
|
|
||||||
// tb.Fatalf("tried to delete a nonexistent validator")
|
|
||||||
// }
|
|
||||||
event("endblock/validatorupdates/kicked")
|
event("endblock/validatorupdates/kicked")
|
||||||
delete(current, string(update.PubKey.Data))
|
delete(current, string(update.PubKey.Data))
|
||||||
default:
|
default:
|
||||||
|
@ -350,5 +381,6 @@ func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValida
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,13 @@ type (
|
||||||
BlockHeight int
|
BlockHeight int
|
||||||
Op Operation
|
Op Operation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WeightedOperation is an operation with associated weight.
|
||||||
|
// This is used to bias the selection operation within the simulator.
|
||||||
|
WeightedOperation struct {
|
||||||
|
Weight int
|
||||||
|
Op Operation
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeriodicInvariant returns an Invariant function closure that asserts
|
// PeriodicInvariant returns an Invariant function closure that asserts
|
||||||
|
|
|
@ -3,9 +3,11 @@ package simulation
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
|
||||||
|
@ -94,15 +96,36 @@ func assertAllInvariants(t *testing.T, app *baseapp.BaseApp, invariants []Invari
|
||||||
func logPrinter(testingmode bool, logs []*strings.Builder) func() {
|
func logPrinter(testingmode bool, logs []*strings.Builder) func() {
|
||||||
if testingmode {
|
if testingmode {
|
||||||
return func() {
|
return func() {
|
||||||
|
numLoggers := 0
|
||||||
for i := 0; i < len(logs); i++ {
|
for i := 0; i < len(logs); i++ {
|
||||||
// We're passed the last created block
|
// We're passed the last created block
|
||||||
if logs[i] == nil {
|
if logs[i] == nil {
|
||||||
return
|
numLoggers = i - 1
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
var f *os.File
|
||||||
|
if numLoggers > 10 {
|
||||||
|
fileName := fmt.Sprintf("simulation_log_%s.txt", time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
fmt.Printf("Too many logs to display, instead writing to %s\n", fileName)
|
||||||
|
f, _ = os.Create(fileName)
|
||||||
|
}
|
||||||
|
for i := 0; i < numLoggers; i++ {
|
||||||
|
if f != nil {
|
||||||
|
_, err := f.WriteString(fmt.Sprintf("Begin block %d\n", i))
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to write logs to file")
|
||||||
|
}
|
||||||
|
_, err = f.WriteString((*logs[i]).String())
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to write logs to file")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
fmt.Printf("Begin block %d\n", i)
|
fmt.Printf("Begin block %d\n", i)
|
||||||
fmt.Println((*logs[i]).String())
|
fmt.Println((*logs[i]).String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,12 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
|
||||||
|
|
||||||
RegisterWire(mapp.Cdc)
|
RegisterWire(mapp.Cdc)
|
||||||
keyStake := sdk.NewKVStoreKey("stake")
|
keyStake := sdk.NewKVStoreKey("stake")
|
||||||
|
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||||
keySlashing := sdk.NewKVStoreKey("slashing")
|
keySlashing := sdk.NewKVStoreKey("slashing")
|
||||||
keyParams := sdk.NewKVStoreKey("params")
|
keyParams := sdk.NewKVStoreKey("params")
|
||||||
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
|
||||||
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
|
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
|
||||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
|
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
|
||||||
|
|
||||||
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace))
|
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace))
|
||||||
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
||||||
|
@ -38,7 +39,7 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
|
||||||
|
|
||||||
mapp.SetEndBlocker(getEndBlocker(stakeKeeper))
|
mapp.SetEndBlocker(getEndBlocker(stakeKeeper))
|
||||||
mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper))
|
mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper))
|
||||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keySlashing, keyParams}))
|
require.NoError(t, mapp.CompleteSetup(keyStake, keySlashing, keyParams, tkeyStake))
|
||||||
|
|
||||||
return mapp, stakeKeeper, keeper
|
return mapp, stakeKeeper, keeper
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,22 +70,20 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
txBldr := authtxb.TxBuilder{
|
txBldr := authtxb.TxBuilder{
|
||||||
Codec: cdc,
|
Codec: cdc,
|
||||||
ChainID: m.ChainID,
|
ChainID: m.ChainID,
|
||||||
AccountNumber: m.AccountNumber,
|
AccountNumber: m.AccountNumber,
|
||||||
Sequence: m.Sequence,
|
Sequence: m.Sequence,
|
||||||
Gas: m.Gas,
|
Gas: m.Gas,
|
||||||
|
GasAdjustment: adjustment,
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := slashing.NewMsgUnjail(valAddr)
|
msg := slashing.NewMsgUnjail(valAddr)
|
||||||
|
|
||||||
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cliCtx = cliCtx.WithGasAdjustment(adjustment)
|
|
||||||
|
|
||||||
if utils.HasDryRunArg(r) || m.Gas == 0 {
|
if utils.HasDryRunArg(r) || m.Gas == 0 {
|
||||||
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -52,11 +52,13 @@ func createTestCodec() *wire.Codec {
|
||||||
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
|
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
|
||||||
keyAcc := sdk.NewKVStoreKey("acc")
|
keyAcc := sdk.NewKVStoreKey("acc")
|
||||||
keyStake := sdk.NewKVStoreKey("stake")
|
keyStake := sdk.NewKVStoreKey("stake")
|
||||||
|
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||||
keySlashing := sdk.NewKVStoreKey("slashing")
|
keySlashing := sdk.NewKVStoreKey("slashing")
|
||||||
keyParams := sdk.NewKVStoreKey("params")
|
keyParams := sdk.NewKVStoreKey("params")
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
ms := store.NewCommitMultiStore(db)
|
ms := store.NewCommitMultiStore(db)
|
||||||
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
||||||
|
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
|
||||||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||||
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
|
||||||
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
||||||
|
@ -67,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
|
||||||
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
|
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
|
||||||
ck := bank.NewBaseKeeper(accountMapper)
|
ck := bank.NewBaseKeeper(accountMapper)
|
||||||
params := params.NewKeeper(cdc, keyParams)
|
params := params.NewKeeper(cdc, keyParams)
|
||||||
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
|
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, stake.DefaultCodespace)
|
||||||
genesis := stake.DefaultGenesisState()
|
genesis := stake.DefaultGenesisState()
|
||||||
|
|
||||||
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
|
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
|
||||||
|
|
|
@ -34,14 +34,15 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
|
||||||
RegisterWire(mApp.Cdc)
|
RegisterWire(mApp.Cdc)
|
||||||
|
|
||||||
keyStake := sdk.NewKVStoreKey("stake")
|
keyStake := sdk.NewKVStoreKey("stake")
|
||||||
|
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||||
bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper)
|
bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper)
|
||||||
keeper := NewKeeper(mApp.Cdc, keyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
|
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
|
||||||
|
|
||||||
mApp.Router().AddRoute("stake", NewHandler(keeper))
|
mApp.Router().AddRoute("stake", NewHandler(keeper))
|
||||||
mApp.SetEndBlocker(getEndBlocker(keeper))
|
mApp.SetEndBlocker(getEndBlocker(keeper))
|
||||||
mApp.SetInitChainer(getInitChainer(mApp, keeper))
|
mApp.SetInitChainer(getInitChainer(mApp, keeper))
|
||||||
|
|
||||||
require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{keyStake}))
|
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake))
|
||||||
return mApp, keeper
|
return mApp, keeper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ type EditDelegationsBody struct {
|
||||||
ChainID string `json:"chain_id"`
|
ChainID string `json:"chain_id"`
|
||||||
AccountNumber int64 `json:"account_number"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequence int64 `json:"sequence"`
|
Sequence int64 `json:"sequence"`
|
||||||
Gas int64 `json:"gas"`
|
Gas string `json:"gas"`
|
||||||
GasAdjustment string `json:"gas_adjustment"`
|
GasAdjustment string `json:"gas_adjustment"`
|
||||||
Delegations []msgDelegationsInput `json:"delegations"`
|
Delegations []msgDelegationsInput `json:"delegations"`
|
||||||
BeginUnbondings []msgBeginUnbondingInput `json:"begin_unbondings"`
|
BeginUnbondings []msgBeginUnbondingInput `json:"begin_unbondings"`
|
||||||
|
@ -263,10 +263,21 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simulateGas, gas, err := client.ReadGasFlag(m.Gas)
|
||||||
|
if err != nil {
|
||||||
|
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
txBldr := authtxb.TxBuilder{
|
txBldr := authtxb.TxBuilder{
|
||||||
Codec: cdc,
|
Codec: cdc,
|
||||||
|
Gas: gas,
|
||||||
|
GasAdjustment: adjustment,
|
||||||
|
SimulateGas: simulateGas,
|
||||||
ChainID: m.ChainID,
|
ChainID: m.ChainID,
|
||||||
Gas: m.Gas,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign messages
|
// sign messages
|
||||||
|
@ -275,26 +286,19 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
|
||||||
// increment sequence for each message
|
// increment sequence for each message
|
||||||
txBldr = txBldr.WithAccountNumber(m.AccountNumber)
|
txBldr = txBldr.WithAccountNumber(m.AccountNumber)
|
||||||
txBldr = txBldr.WithSequence(m.Sequence)
|
txBldr = txBldr.WithSequence(m.Sequence)
|
||||||
|
|
||||||
m.Sequence++
|
m.Sequence++
|
||||||
|
|
||||||
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, m.GasAdjustment, client.DefaultGasAdjustment)
|
if utils.HasDryRunArg(r) || txBldr.SimulateGas {
|
||||||
if !ok {
|
newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
||||||
return
|
|
||||||
}
|
|
||||||
cliCtx = cliCtx.WithGasAdjustment(adjustment)
|
|
||||||
|
|
||||||
if utils.HasDryRunArg(r) || m.Gas == 0 {
|
|
||||||
newCtx, err := utils.EnrichCtxWithGas(txBldr, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if utils.HasDryRunArg(r) {
|
if utils.HasDryRunArg(r) {
|
||||||
utils.WriteSimulationResponse(w, txBldr.Gas)
|
utils.WriteSimulationResponse(w, newBldr.Gas)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txBldr = newCtx
|
txBldr = newBldr
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.HasGenerateOnlyArg(r) {
|
if utils.HasGenerateOnlyArg(r) {
|
||||||
|
|
|
@ -52,8 +52,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
|
||||||
k.SetIntraTxCounter(ctx, 0)
|
k.SetIntraTxCounter(ctx, 0)
|
||||||
|
|
||||||
// calculate validator set changes
|
// calculate validator set changes
|
||||||
ValidatorUpdates = k.GetTendermintUpdates(ctx)
|
ValidatorUpdates = k.GetValidTendermintUpdates(ctx)
|
||||||
k.ClearTendermintUpdates(ctx)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
This document provided a bit more insight as to the purpose of several related
|
This document provided a bit more insight as to the purpose of several related
|
||||||
prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
|
prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
|
||||||
|
|
||||||
|
# IAVL Store
|
||||||
|
|
||||||
## Validators
|
## Validators
|
||||||
- Prefix Key Space: ValidatorsKey
|
- Prefix Key Space: ValidatorsKey
|
||||||
|
@ -36,10 +37,13 @@ prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
|
||||||
through this set to determine who we've kicked out.
|
through this set to determine who we've kicked out.
|
||||||
retrieving validator by tendermint index
|
retrieving validator by tendermint index
|
||||||
|
|
||||||
|
# Transient Store
|
||||||
|
|
||||||
|
The transient store persists between transations but not between blocks
|
||||||
|
|
||||||
## Tendermint Updates
|
## Tendermint Updates
|
||||||
- Prefix Key Space: TendermintUpdatesKey
|
- Prefix Key Space: TendermintUpdatesTKey
|
||||||
- Key/Sort: Validator Operator Address
|
- Key/Sort: Validator Operator Address
|
||||||
- Value: Tendermint ABCI Validator
|
- Value: Tendermint ABCI Validator
|
||||||
- Contains: Validators are queued to affect the consensus validation set in Tendermint
|
- Contains: Validators are queued to affect the consensus validation set in Tendermint
|
||||||
- Used For: Informing Tendermint of the validator set updates, is used only intra-block, as the
|
- Used For: Informing Tendermint of the validator set updates
|
||||||
updates are applied then cleared on endblock
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
// keeper of the stake store
|
// keeper of the stake store
|
||||||
type Keeper struct {
|
type Keeper struct {
|
||||||
storeKey sdk.StoreKey
|
storeKey sdk.StoreKey
|
||||||
|
storeTKey sdk.StoreKey
|
||||||
cdc *wire.Codec
|
cdc *wire.Codec
|
||||||
bankKeeper bank.Keeper
|
bankKeeper bank.Keeper
|
||||||
validatorHooks sdk.ValidatorHooks
|
validatorHooks sdk.ValidatorHooks
|
||||||
|
@ -19,9 +20,10 @@ type Keeper struct {
|
||||||
codespace sdk.CodespaceType
|
codespace sdk.CodespaceType
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
||||||
keeper := Keeper{
|
keeper := Keeper{
|
||||||
storeKey: key,
|
storeKey: key,
|
||||||
|
storeTKey: tkey,
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
bankKeeper: ck,
|
bankKeeper: ck,
|
||||||
validatorHooks: nil,
|
validatorHooks: nil,
|
||||||
|
|
|
@ -22,14 +22,16 @@ var (
|
||||||
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
|
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
|
||||||
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
|
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
|
||||||
ValidatorPowerCliffKey = []byte{0x07} // key for the power of the validator on the cliff
|
ValidatorPowerCliffKey = []byte{0x07} // key for the power of the validator on the cliff
|
||||||
TendermintUpdatesKey = []byte{0x08} // prefix for each key to a validator which is being updated
|
IntraTxCounterKey = []byte{0x08} // key for intra-block tx index
|
||||||
IntraTxCounterKey = []byte{0x09} // key for intra-block tx index
|
DelegationKey = []byte{0x09} // key for a delegation
|
||||||
DelegationKey = []byte{0x0A} // key for a delegation
|
UnbondingDelegationKey = []byte{0x0A} // key for an unbonding-delegation
|
||||||
UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation
|
UnbondingDelegationByValIndexKey = []byte{0x0B} // prefix for each key for an unbonding-delegation, by validator operator
|
||||||
UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator operator
|
RedelegationKey = []byte{0x0C} // key for a redelegation
|
||||||
RedelegationKey = []byte{0x0D} // key for a redelegation
|
RedelegationByValSrcIndexKey = []byte{0x0D} // prefix for each key for an redelegation, by source validator operator
|
||||||
RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator operator
|
RedelegationByValDstIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by destination validator operator
|
||||||
RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator operator
|
|
||||||
|
// Keys for store prefixes (transient)
|
||||||
|
TendermintUpdatesTKey = []byte{0x00} // prefix for each key to a validator which is being updated
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
||||||
|
@ -98,8 +100,8 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte {
|
||||||
// get the key for the accumulated update validators
|
// get the key for the accumulated update validators
|
||||||
// VALUE: abci.Validator
|
// VALUE: abci.Validator
|
||||||
// note records using these keys should never persist between blocks
|
// note records using these keys should never persist between blocks
|
||||||
func GetTendermintUpdatesKey(operatorAddr sdk.ValAddress) []byte {
|
func GetTendermintUpdatesTKey(operatorAddr sdk.ValAddress) []byte {
|
||||||
return append(TendermintUpdatesKey, operatorAddr.Bytes()...)
|
return append(TendermintUpdatesTKey, operatorAddr.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//______________________________________________________________________________
|
//______________________________________________________________________________
|
||||||
|
|
|
@ -28,7 +28,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
|
|
||||||
if slashFactor.LT(sdk.ZeroDec()) {
|
if slashFactor.LT(sdk.ZeroDec()) {
|
||||||
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
|
panic(fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Amount of slashing = slash slashFactor * power at time of infraction
|
// Amount of slashing = slash slashFactor * power at time of infraction
|
||||||
|
@ -50,7 +50,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
|
|
||||||
// should not be slashing unbonded
|
// should not be slashing unbonded
|
||||||
if validator.IsUnbonded(ctx) {
|
if validator.IsUnbonded(ctx) {
|
||||||
panic(fmt.Sprintf("should not be slashing unbonded validator: %v", validator))
|
panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator()))
|
||||||
}
|
}
|
||||||
|
|
||||||
operatorAddress := validator.GetOperator()
|
operatorAddress := validator.GetOperator()
|
||||||
|
@ -72,7 +72,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
|
|
||||||
// Special-case slash at current height for efficiency - we don't need to look through unbonding delegations or redelegations
|
// Special-case slash at current height for efficiency - we don't need to look through unbonding delegations or redelegations
|
||||||
logger.Info(fmt.Sprintf(
|
logger.Info(fmt.Sprintf(
|
||||||
"Slashing at current height %d, not scanning unbonding delegations & redelegations",
|
"slashing at current height %d, not scanning unbonding delegations & redelegations",
|
||||||
infractionHeight))
|
infractionHeight))
|
||||||
|
|
||||||
case infractionHeight < ctx.BlockHeight():
|
case infractionHeight < ctx.BlockHeight():
|
||||||
|
@ -117,8 +117,8 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
|
|
||||||
// Log that a slash occurred!
|
// Log that a slash occurred!
|
||||||
logger.Info(fmt.Sprintf(
|
logger.Info(fmt.Sprintf(
|
||||||
"Validator %s slashed by slashFactor %s, burned %v tokens",
|
"validator %s slashed by slash factor of %s; burned %v tokens",
|
||||||
pubkey.Address(), slashFactor.String(), tokensToBurn))
|
validator.GetOperator(), slashFactor.String(), tokensToBurn))
|
||||||
|
|
||||||
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
||||||
return
|
return
|
||||||
|
@ -127,8 +127,12 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
// jail a validator
|
// jail a validator
|
||||||
func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) {
|
func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) {
|
||||||
k.setJailed(ctx, pubkey, true)
|
k.setJailed(ctx, pubkey, true)
|
||||||
|
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
logger.Info(fmt.Sprintf("Validator %s jailed", pubkey.Address()))
|
logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr))
|
||||||
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -136,8 +140,12 @@ func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) {
|
||||||
// unjail a validator
|
// unjail a validator
|
||||||
func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) {
|
func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) {
|
||||||
k.setJailed(ctx, pubkey, false)
|
k.setJailed(ctx, pubkey, false)
|
||||||
|
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
logger.Info(fmt.Sprintf("Validator %s unjailed", pubkey.Address()))
|
logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr))
|
||||||
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -146,7 +154,7 @@ func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) {
|
||||||
func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) {
|
func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) {
|
||||||
validator, found := k.GetValidatorByPubKey(ctx, pubkey)
|
validator, found := k.GetValidatorByPubKey(ctx, pubkey)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Errorf("Validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed))
|
panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed))
|
||||||
}
|
}
|
||||||
validator.Jailed = isJailed
|
validator.Jailed = isJailed
|
||||||
k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it
|
k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it
|
||||||
|
|
|
@ -90,10 +90,12 @@ func ParamsNoInflation() types.Params {
|
||||||
func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) {
|
func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) {
|
||||||
|
|
||||||
keyStake := sdk.NewKVStoreKey("stake")
|
keyStake := sdk.NewKVStoreKey("stake")
|
||||||
|
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||||
keyAcc := sdk.NewKVStoreKey("acc")
|
keyAcc := sdk.NewKVStoreKey("acc")
|
||||||
|
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
ms := store.NewCommitMultiStore(db)
|
ms := store.NewCommitMultiStore(db)
|
||||||
|
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
|
||||||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||||
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
||||||
err := ms.LoadLatestVersion()
|
err := ms.LoadLatestVersion()
|
||||||
|
@ -107,7 +109,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
||||||
auth.ProtoBaseAccount, // prototype
|
auth.ProtoBaseAccount, // prototype
|
||||||
)
|
)
|
||||||
ck := bank.NewBaseKeeper(accountMapper)
|
ck := bank.NewBaseKeeper(accountMapper)
|
||||||
keeper := NewKeeper(cdc, keyStake, ck, types.DefaultCodespace)
|
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, types.DefaultCodespace)
|
||||||
keeper.SetPool(ctx, types.InitialPool())
|
keeper.SetPool(ctx, types.InitialPool())
|
||||||
keeper.SetNewParams(ctx, types.DefaultParams())
|
keeper.SetNewParams(ctx, types.DefaultParams())
|
||||||
keeper.InitIntraTxCounter(ctx)
|
keeper.InitIntraTxCounter(ctx)
|
||||||
|
|
|
@ -158,9 +158,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
|
||||||
}
|
}
|
||||||
address := GetAddressFromValBondedIndexKey(iterator.Key())
|
address := GetAddressFromValBondedIndexKey(iterator.Key())
|
||||||
validator, found := k.GetValidator(ctx, address)
|
validator, found := k.GetValidator(ctx, address)
|
||||||
if !found {
|
ensureValidatorFound(found, address)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", address))
|
|
||||||
}
|
|
||||||
|
|
||||||
validators[i] = validator
|
validators[i] = validator
|
||||||
i++
|
i++
|
||||||
|
@ -184,9 +182,8 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
|
||||||
}
|
}
|
||||||
address := iterator.Value()
|
address := iterator.Value()
|
||||||
validator, found := k.GetValidator(ctx, address)
|
validator, found := k.GetValidator(ctx, address)
|
||||||
if !found {
|
ensureValidatorFound(found, address)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", address))
|
|
||||||
}
|
|
||||||
if validator.Status == sdk.Bonded {
|
if validator.Status == sdk.Bonded {
|
||||||
validators[i] = validator
|
validators[i] = validator
|
||||||
i++
|
i++
|
||||||
|
@ -201,32 +198,41 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
|
||||||
// Accumulated updates to the active/bonded validator set for tendermint
|
// Accumulated updates to the active/bonded validator set for tendermint
|
||||||
|
|
||||||
// get the most recently updated validators
|
// get the most recently updated validators
|
||||||
func (k Keeper) GetTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) {
|
//
|
||||||
store := ctx.KVStore(k.storeKey)
|
// CONTRACT: Only validators with non-zero power or zero-power that were bonded
|
||||||
|
// at the previous block height or were removed from the validator set entirely
|
||||||
|
// are returned to Tendermint.
|
||||||
|
func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) {
|
||||||
|
tstore := ctx.TransientStore(k.storeTKey)
|
||||||
|
|
||||||
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) //smallest to largest
|
iterator := sdk.KVStorePrefixIterator(tstore, TendermintUpdatesTKey)
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
valBytes := iterator.Value()
|
var abciVal abci.Validator
|
||||||
var val abci.Validator
|
|
||||||
k.cdc.MustUnmarshalBinary(valBytes, &val)
|
abciValBytes := iterator.Value()
|
||||||
updates = append(updates, val)
|
k.cdc.MustUnmarshalBinary(abciValBytes, &abciVal)
|
||||||
|
|
||||||
|
val, found := k.GetValidator(ctx, abciVal.GetAddress())
|
||||||
|
if found {
|
||||||
|
// The validator is new or already exists in the store and must adhere to
|
||||||
|
// Tendermint invariants.
|
||||||
|
prevBonded := val.BondHeight < ctx.BlockHeight() && val.BondHeight > val.UnbondingHeight
|
||||||
|
zeroPower := val.GetPower().Equal(sdk.ZeroDec())
|
||||||
|
|
||||||
|
if !zeroPower || zeroPower && prevBonded {
|
||||||
|
updates = append(updates, abciVal)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Add the ABCI validator in such a case where the validator was removed
|
||||||
|
// from the store as it must have existed before.
|
||||||
|
updates = append(updates, abciVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iterator.Close()
|
iterator.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all validator update entries after applied to Tendermint
|
|
||||||
func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
|
|
||||||
store := ctx.KVStore(k.storeKey)
|
|
||||||
|
|
||||||
// delete subspace
|
|
||||||
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey)
|
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
|
||||||
store.Delete(iterator.Key())
|
|
||||||
}
|
|
||||||
iterator.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
//___________________________________________________________________________
|
//___________________________________________________________________________
|
||||||
|
|
||||||
// Perform all the necessary steps for when a validator changes its power. This
|
// Perform all the necessary steps for when a validator changes its power. This
|
||||||
|
@ -237,15 +243,20 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
// TODO: Remove above nolint, function needs to be simplified!
|
// TODO: Remove above nolint, function needs to be simplified!
|
||||||
func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator {
|
func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||||
store := ctx.KVStore(k.storeKey)
|
tstore := ctx.TransientStore(k.storeTKey)
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
oldValidator, oldFound := k.GetValidator(ctx, validator.OperatorAddr)
|
oldValidator, oldFound := k.GetValidator(ctx, validator.OperatorAddr)
|
||||||
|
|
||||||
validator = k.updateForJailing(ctx, oldFound, oldValidator, validator)
|
validator = k.updateForJailing(ctx, oldFound, oldValidator, validator)
|
||||||
powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator)
|
powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator)
|
||||||
validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator)
|
validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator)
|
||||||
valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool)
|
valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool)
|
||||||
cliffPower := k.GetCliffValidatorPower(ctx)
|
cliffPower := k.GetCliffValidatorPower(ctx)
|
||||||
|
cliffValExists := (cliffPower != nil)
|
||||||
|
var valPowerLTcliffPower bool
|
||||||
|
if cliffValExists {
|
||||||
|
valPowerLTcliffPower = (bytes.Compare(valPower, cliffPower) == -1)
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
|
@ -257,9 +268,9 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
|
||||||
(oldFound && oldValidator.Status == sdk.Bonded):
|
(oldFound && oldValidator.Status == sdk.Bonded):
|
||||||
|
|
||||||
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
||||||
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz)
|
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz)
|
||||||
|
|
||||||
if cliffPower != nil {
|
if cliffValExists {
|
||||||
cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx))
|
cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx))
|
||||||
if bytes.Equal(cliffAddr, validator.OperatorAddr) {
|
if bytes.Equal(cliffAddr, validator.OperatorAddr) {
|
||||||
k.updateCliffValidator(ctx, validator)
|
k.updateCliffValidator(ctx, validator)
|
||||||
|
@ -267,14 +278,13 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
|
||||||
}
|
}
|
||||||
|
|
||||||
// if is a new validator and the new power is less than the cliff validator
|
// if is a new validator and the new power is less than the cliff validator
|
||||||
case cliffPower != nil && !oldFound &&
|
case cliffValExists && !oldFound && valPowerLTcliffPower:
|
||||||
bytes.Compare(valPower, cliffPower) == -1: //(valPower < cliffPower
|
|
||||||
// skip to completion
|
// skip to completion
|
||||||
|
|
||||||
// if was unbonded and the new power is less than the cliff validator
|
// if was unbonded and the new power is less than the cliff validator
|
||||||
case cliffPower != nil &&
|
case cliffValExists &&
|
||||||
(oldFound && oldValidator.Status == sdk.Unbonded) &&
|
(oldFound && oldValidator.Status == sdk.Unbonded) &&
|
||||||
bytes.Compare(valPower, cliffPower) == -1: //(valPower < cliffPower
|
valPowerLTcliffPower: //(valPower < cliffPower
|
||||||
// skip to completion
|
// skip to completion
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -293,7 +303,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
|
||||||
// if decreased in power but still bonded, update Tendermint validator
|
// if decreased in power but still bonded, update Tendermint validator
|
||||||
if oldFound && oldValidator.BondedTokens().GT(validator.BondedTokens()) {
|
if oldFound && oldValidator.BondedTokens().GT(validator.BondedTokens()) {
|
||||||
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
||||||
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz)
|
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +325,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
|
|
||||||
oldCliffVal, found := k.GetValidator(ctx, cliffAddr)
|
oldCliffVal, found := k.GetValidator(ctx, cliffAddr)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("cliff validator record not found for address: %v\n", cliffAddr))
|
panic(fmt.Sprintf("cliff validator record not found for address: %X\n", cliffAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a validator iterator ranging from smallest to largest by power
|
// Create a validator iterator ranging from smallest to largest by power
|
||||||
|
@ -327,12 +337,10 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
if iterator.Valid() {
|
if iterator.Valid() {
|
||||||
ownerAddr := iterator.Value()
|
ownerAddr := iterator.Value()
|
||||||
currVal, found := k.GetValidator(ctx, ownerAddr)
|
currVal, found := k.GetValidator(ctx, ownerAddr)
|
||||||
if !found {
|
ensureValidatorFound(found, ownerAddr)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr))
|
|
||||||
}
|
|
||||||
|
|
||||||
if currVal.Status != sdk.Bonded || currVal.Jailed {
|
if currVal.Status != sdk.Bonded || currVal.Jailed {
|
||||||
panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %s\n", ownerAddr))
|
panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %X\n", ownerAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
newCliffVal = currVal
|
newCliffVal = currVal
|
||||||
|
@ -345,13 +353,10 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool)
|
newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool)
|
||||||
|
|
||||||
if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) {
|
if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) {
|
||||||
|
|
||||||
// The affected validator remains the cliff validator, however, since
|
// The affected validator remains the cliff validator, however, since
|
||||||
// the store does not contain the new power, update the new power rank.
|
// the store does not contain the new power, update the new power rank.
|
||||||
store.Set(ValidatorPowerCliffKey, affectedValRank)
|
store.Set(ValidatorPowerCliffKey, affectedValRank)
|
||||||
|
|
||||||
} else if bytes.Compare(affectedValRank, newCliffValRank) > 0 {
|
} else if bytes.Compare(affectedValRank, newCliffValRank) > 0 {
|
||||||
|
|
||||||
// The affected validator no longer remains the cliff validator as it's
|
// The affected validator no longer remains the cliff validator as it's
|
||||||
// power is greater than the new cliff validator.
|
// power is greater than the new cliff validator.
|
||||||
k.setCliffValidator(ctx, newCliffVal, pool)
|
k.setCliffValidator(ctx, newCliffVal, pool)
|
||||||
|
@ -382,18 +387,20 @@ func (k Keeper) getPowerIncreasing(ctx sdk.Context, oldFound bool, oldValidator,
|
||||||
|
|
||||||
// get the bond height and incremented intra-tx counter
|
// get the bond height and incremented intra-tx counter
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func (k Keeper) bondIncrement(ctx sdk.Context, oldFound bool, oldValidator,
|
func (k Keeper) bondIncrement(
|
||||||
newValidator types.Validator) (height int64, intraTxCounter int16) {
|
ctx sdk.Context, found bool, oldValidator types.Validator) (height int64, intraTxCounter int16) {
|
||||||
|
|
||||||
// if already a validator, copy the old block height and counter, else set them
|
// if already a validator, copy the old block height and counter
|
||||||
if oldFound && oldValidator.Status == sdk.Bonded {
|
if found && oldValidator.Status == sdk.Bonded {
|
||||||
height = oldValidator.BondHeight
|
height = oldValidator.BondHeight
|
||||||
intraTxCounter = oldValidator.BondIntraTxCounter
|
intraTxCounter = oldValidator.BondIntraTxCounter
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
height = ctx.BlockHeight()
|
height = ctx.BlockHeight()
|
||||||
counter := k.GetIntraTxCounter(ctx)
|
counter := k.GetIntraTxCounter(ctx)
|
||||||
intraTxCounter = counter
|
intraTxCounter = counter
|
||||||
|
|
||||||
k.SetIntraTxCounter(ctx, counter+1)
|
k.SetIntraTxCounter(ctx, counter+1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -454,29 +461,25 @@ func (k Keeper) UpdateBondedValidators(
|
||||||
} else {
|
} else {
|
||||||
var found bool
|
var found bool
|
||||||
validator, found = k.GetValidator(ctx, ownerAddr)
|
validator, found = k.GetValidator(ctx, ownerAddr)
|
||||||
if !found {
|
ensureValidatorFound(found, ownerAddr)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we've reached jailed validators no further bonded validators exist
|
// if we've reached jailed validators no further bonded validators exist
|
||||||
if validator.Jailed {
|
if validator.Jailed {
|
||||||
break
|
if validator.Status == sdk.Bonded {
|
||||||
|
panic(fmt.Sprintf("jailed validator cannot be bonded, address: %X\n", ownerAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment bondedValidatorsCount / get the validator to bond
|
break
|
||||||
if validator.Status != sdk.Bonded {
|
|
||||||
validatorToBond = validator
|
|
||||||
if newValidatorBonded {
|
|
||||||
panic("already decided to bond a validator, can't bond another!")
|
|
||||||
}
|
|
||||||
newValidatorBonded = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment the total number of bonded validators and potentially mark
|
// increment the total number of bonded validators and potentially mark
|
||||||
// the validator to bond
|
// the validator to bond
|
||||||
if validator.Status != sdk.Bonded {
|
if validator.Status != sdk.Bonded {
|
||||||
validatorToBond = validator
|
validatorToBond = validator
|
||||||
|
if newValidatorBonded {
|
||||||
|
panic("already decided to bond a validator, can't bond another!")
|
||||||
|
}
|
||||||
newValidatorBonded = true
|
newValidatorBonded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,9 +505,7 @@ func (k Keeper) UpdateBondedValidators(
|
||||||
if newValidatorBonded {
|
if newValidatorBonded {
|
||||||
if oldCliffValidatorAddr != nil {
|
if oldCliffValidatorAddr != nil {
|
||||||
oldCliffVal, found := k.GetValidator(ctx, oldCliffValidatorAddr)
|
oldCliffVal, found := k.GetValidator(ctx, oldCliffValidatorAddr)
|
||||||
if !found {
|
ensureValidatorFound(found, oldCliffValidatorAddr)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr))
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Equal(validatorToBond.OperatorAddr, affectedValidator.OperatorAddr) {
|
if bytes.Equal(validatorToBond.OperatorAddr, affectedValidator.OperatorAddr) {
|
||||||
|
|
||||||
|
@ -512,7 +513,6 @@ func (k Keeper) UpdateBondedValidators(
|
||||||
// validator was newly bonded and has greater power
|
// validator was newly bonded and has greater power
|
||||||
k.beginUnbondingValidator(ctx, oldCliffVal)
|
k.beginUnbondingValidator(ctx, oldCliffVal)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// otherwise begin unbonding the affected validator, which must
|
// otherwise begin unbonding the affected validator, which must
|
||||||
// have been kicked out
|
// have been kicked out
|
||||||
affectedValidator = k.beginUnbondingValidator(ctx, affectedValidator)
|
affectedValidator = k.beginUnbondingValidator(ctx, affectedValidator)
|
||||||
|
@ -560,9 +560,7 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
|
||||||
|
|
||||||
ownerAddr := iterator.Value()
|
ownerAddr := iterator.Value()
|
||||||
validator, found = k.GetValidator(ctx, ownerAddr)
|
validator, found = k.GetValidator(ctx, ownerAddr)
|
||||||
if !found {
|
ensureValidatorFound(found, ownerAddr)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, found = toKickOut[string(ownerAddr)]
|
_, found = toKickOut[string(ownerAddr)]
|
||||||
if found {
|
if found {
|
||||||
|
@ -605,9 +603,7 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) {
|
||||||
for key := range toKickOut {
|
for key := range toKickOut {
|
||||||
ownerAddr := []byte(key)
|
ownerAddr := []byte(key)
|
||||||
validator, found := k.GetValidator(ctx, ownerAddr)
|
validator, found := k.GetValidator(ctx, ownerAddr)
|
||||||
if !found {
|
ensureValidatorFound(found, ownerAddr)
|
||||||
panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr))
|
|
||||||
}
|
|
||||||
k.beginUnbondingValidator(ctx, validator)
|
k.beginUnbondingValidator(ctx, validator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +633,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
||||||
|
|
||||||
// add to accumulated changes for tendermint
|
// add to accumulated changes for tendermint
|
||||||
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
|
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
|
||||||
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI)
|
tstore := ctx.TransientStore(k.storeTKey)
|
||||||
|
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
|
||||||
|
|
||||||
// also remove from the Bonded types.Validators Store
|
// also remove from the Bonded types.Validators Store
|
||||||
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
||||||
|
@ -662,6 +659,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator))
|
panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validator.BondHeight = ctx.BlockHeight()
|
||||||
|
|
||||||
// set the status
|
// set the status
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||||
k.SetPool(ctx, pool)
|
k.SetPool(ctx, pool)
|
||||||
|
@ -672,7 +671,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
|
|
||||||
// add to accumulated changes for tendermint
|
// add to accumulated changes for tendermint
|
||||||
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator())
|
||||||
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI)
|
tstore := ctx.TransientStore(k.storeTKey)
|
||||||
|
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
|
||||||
|
|
||||||
// call the bond hook if present
|
// call the bond hook if present
|
||||||
if k.validatorHooks != nil {
|
if k.validatorHooks != nil {
|
||||||
|
@ -707,7 +707,8 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
||||||
|
|
||||||
bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
|
bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
|
||||||
store.Set(GetTendermintUpdatesKey(address), bz)
|
tstore := ctx.TransientStore(k.storeTKey)
|
||||||
|
tstore.Set(GetTendermintUpdatesTKey(address), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
//__________________________________________________________________________
|
//__________________________________________________________________________
|
||||||
|
@ -738,3 +739,9 @@ func (k Keeper) clearCliffValidator(ctx sdk.Context) {
|
||||||
store.Delete(ValidatorPowerCliffKey)
|
store.Delete(ValidatorPowerCliffKey)
|
||||||
store.Delete(ValidatorCliffIndexKey)
|
store.Delete(ValidatorCliffIndexKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureValidatorFound(found bool, ownerAddr []byte) {
|
||||||
|
if !found {
|
||||||
|
panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,18 +6,34 @@ import (
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// for testing, remove all validator update entries after applied to Tendermint
|
||||||
|
func clearTendermintUpdates(ctx sdk.Context, k Keeper) {
|
||||||
|
store := ctx.TransientStore(k.storeTKey)
|
||||||
|
|
||||||
|
// delete subspace
|
||||||
|
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesTKey)
|
||||||
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
|
store.Delete(iterator.Key())
|
||||||
|
}
|
||||||
|
iterator.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//_______________________________________________________
|
||||||
|
|
||||||
func TestSetValidator(t *testing.T) {
|
func TestSetValidator(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 10)
|
ctx, _, keeper := CreateTestInput(t, false, 10)
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
valPubKey := PKs[0]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
// test how the validator is set from a purely unbonbed pool
|
// test how the validator is set from a purely unbonbed pool
|
||||||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
validator := types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||||
require.Equal(t, sdk.Unbonded, validator.Status)
|
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
|
@ -26,14 +42,14 @@ func TestSetValidator(t *testing.T) {
|
||||||
keeper.UpdateValidator(ctx, validator)
|
keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
// after the save the validator should be bonded
|
// after the save the validator should be bonded
|
||||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
validator, found := keeper.GetValidator(ctx, valAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
|
|
||||||
// Check each store for being saved
|
// Check each store for being saved
|
||||||
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
resVal, found := keeper.GetValidator(ctx, valAddr)
|
||||||
assert.True(ValEq(t, validator, resVal))
|
assert.True(ValEq(t, validator, resVal))
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
|
||||||
|
@ -45,7 +61,7 @@ func TestSetValidator(t *testing.T) {
|
||||||
require.Equal(t, 1, len(resVals))
|
require.Equal(t, 1, len(resVals))
|
||||||
assert.True(ValEq(t, validator, resVals[0]))
|
assert.True(ValEq(t, validator, resVals[0]))
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validator.ABCIValidator(), updates[0])
|
require.Equal(t, validator.ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
@ -633,67 +649,35 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
|
||||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the tracked changes to the gotValidator set
|
func TestGetValidTendermintUpdatesAllNone(t *testing.T) {
|
||||||
func TestClearTendermintUpdates(t *testing.T) {
|
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
||||||
|
|
||||||
amts := []int64{100, 400, 200}
|
|
||||||
validators := make([]types.Validator, len(amts))
|
|
||||||
for i, amt := range amts {
|
|
||||||
pool := keeper.GetPool(ctx)
|
|
||||||
validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{})
|
|
||||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
|
||||||
keeper.SetPool(ctx, pool)
|
|
||||||
keeper.UpdateValidator(ctx, validators[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
|
||||||
require.Equal(t, len(amts), len(updates))
|
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
|
||||||
require.Equal(t, 0, len(updates))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTendermintUpdatesAllNone(t *testing.T) {
|
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
var validators [2]types.Validator
|
var validators [2]types.Validator
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{})
|
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test from nothing to something
|
// test from nothing to something
|
||||||
// tendermintUpdate set: {} -> {c1, c3}
|
// tendermintUpdate set: {} -> {c1, c3}
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
assert.Equal(t, 2, len(updates))
|
assert.Equal(t, 2, len(updates))
|
||||||
assert.Equal(t, validators[0].ABCIValidator(), updates[0])
|
assert.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
assert.Equal(t, validators[1].ABCIValidator(), updates[1])
|
assert.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
|
||||||
// test from something to nothing
|
|
||||||
// tendermintUpdate set: {} -> {c1, c2, c3, c4}
|
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
||||||
|
|
||||||
keeper.RemoveValidator(ctx, validators[0].OperatorAddr)
|
|
||||||
keeper.RemoveValidator(ctx, validators[1].OperatorAddr)
|
|
||||||
|
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
|
||||||
assert.Equal(t, 2, len(updates))
|
|
||||||
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey)
|
|
||||||
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey)
|
|
||||||
assert.Equal(t, int64(0), updates[0].Power)
|
|
||||||
assert.Equal(t, int64(0), updates[1].Power)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesIdentical(t *testing.T) {
|
func TestGetValidTendermintUpdatesIdentical(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -706,17 +690,17 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test identical,
|
// test identical,
|
||||||
// tendermintUpdate set: {} -> {}
|
// tendermintUpdate set: {} -> {}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
func TestGetValidTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -729,8 +713,8 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test single value change
|
// test single value change
|
||||||
// tendermintUpdate set: {} -> {c1'}
|
// tendermintUpdate set: {} -> {c1'}
|
||||||
|
@ -738,13 +722,13 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
validators[0].Tokens = sdk.NewDec(600)
|
validators[0].Tokens = sdk.NewDec(600)
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
func TestGetValidTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -757,8 +741,8 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test multiple value change
|
// test multiple value change
|
||||||
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
||||||
|
@ -769,13 +753,13 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates))
|
require.Equal(t, 2, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesInserted(t *testing.T) {
|
func TestGetValidTendermintUpdatesInserted(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20, 5, 15, 25}
|
amts := []int64{10, 20, 5, 15, 25}
|
||||||
|
@ -788,34 +772,34 @@ func TestGetTendermintUpdatesInserted(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test validtor added at the beginning
|
// test validtor added at the beginning
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
// test validtor added at the beginning
|
// test validtor added at the beginning
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[3].ABCIValidator(), updates[0])
|
require.Equal(t, validators[3].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
// test validtor added at the end
|
// test validtor added at the end
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
validators[4] = keeper.UpdateValidator(ctx, validators[4])
|
validators[4] = keeper.UpdateValidator(ctx, validators[4])
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[4].ABCIValidator(), updates[0])
|
require.Equal(t, validators[4].ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) {
|
func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
params := types.DefaultParams()
|
params := types.DefaultParams()
|
||||||
params.MaxValidators = 2
|
params.MaxValidators = 2
|
||||||
|
@ -831,32 +815,32 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test validator added at the end but not inserted in the valset
|
// test validator added at the end but not inserted in the valset
|
||||||
// tendermintUpdate set: {} -> {}
|
// tendermintUpdate set: {} -> {}
|
||||||
keeper.UpdateValidator(ctx, validators[2])
|
keeper.UpdateValidator(ctx, validators[2])
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(updates))
|
require.Equal(t, 0, len(updates))
|
||||||
|
|
||||||
// test validator change its power and become a gotValidator (pushing out an existing)
|
// test validator change its power and become a gotValidator (pushing out an existing)
|
||||||
// tendermintUpdate set: {} -> {c0, c4}
|
// tendermintUpdate set: {} -> {c0, c4}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10))
|
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
||||||
|
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates), "%v", updates)
|
require.Equal(t, 2, len(updates), "%v", updates)
|
||||||
require.Equal(t, validators[0].ABCIValidatorZero(), updates[0])
|
require.Equal(t, validators[0].ABCIValidatorZero(), updates[0])
|
||||||
require.Equal(t, validators[2].ABCIValidator(), updates[1])
|
require.Equal(t, validators[2].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
func TestGetValidTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{100, 100}
|
amts := []int64{100, 100}
|
||||||
|
@ -869,8 +853,8 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
}
|
}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
clearTendermintUpdates(ctx, keeper)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// check initial power
|
// check initial power
|
||||||
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||||
|
@ -890,8 +874,158 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||||
|
|
||||||
// Tendermint updates should reflect power change
|
// Tendermint updates should reflect power change
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates))
|
require.Equal(t, 2, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetValidTendermintUpdatesNewValidator(t *testing.T) {
|
||||||
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.MaxValidators = uint16(3)
|
||||||
|
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
amts := []int64{100, 100}
|
||||||
|
var validators [2]types.Validator
|
||||||
|
|
||||||
|
// initialize some validators into the state
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, len(validators), len(updates))
|
||||||
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
|
||||||
|
clearTendermintUpdates(ctx, keeper)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// update initial validator set
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a new validator that goes from zero power, to non-zero power, back to
|
||||||
|
// zero power
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
valPubKey := PKs[len(validators)+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
amt := sdk.NewInt(100)
|
||||||
|
|
||||||
|
validator := types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, amt)
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.RemoveDelShares(pool, sdk.NewDecFromInt(amt))
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// add a new validator that increases in power
|
||||||
|
valPubKey = PKs[len(validators)+2]
|
||||||
|
valAddr = sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validator = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(500))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, len(validators)+1, len(updates))
|
||||||
|
require.Equal(t, validator.ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[0].ABCIValidator(), updates[1])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetValidTendermintUpdatesBondTransition(t *testing.T) {
|
||||||
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.MaxValidators = uint16(2)
|
||||||
|
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
amts := []int64{100, 200, 300}
|
||||||
|
var validators [3]types.Validator
|
||||||
|
|
||||||
|
// initialize some validators into the state
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
moniker := fmt.Sprintf("%d", i)
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{Moniker: moniker})
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 2, len(updates))
|
||||||
|
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
|
||||||
|
clearTendermintUpdates(ctx, keeper)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// delegate to validator with lowest power but not enough to bond
|
||||||
|
ctx = ctx.WithBlockHeight(1)
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
validator, found := keeper.GetValidator(ctx, validators[0].OperatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(1))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[0] = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// create a series of events that will bond and unbond the validator with
|
||||||
|
// lowest power in a single block context (height)
|
||||||
|
ctx = ctx.WithBlockHeight(2)
|
||||||
|
pool = keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
validator, found = keeper.GetValidator(ctx, validators[1].OperatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.RemoveDelShares(pool, validator.DelegatorShares)
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(250))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[1] = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 1, len(updates))
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
|
clearTendermintUpdates(ctx, keeper)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ func TestStakeWithRandomMessages(t *testing.T) {
|
||||||
mapper := mapp.AccountMapper
|
mapper := mapp.AccountMapper
|
||||||
bankKeeper := bank.NewBaseKeeper(mapper)
|
bankKeeper := bank.NewBaseKeeper(mapper)
|
||||||
stakeKey := sdk.NewKVStoreKey("stake")
|
stakeKey := sdk.NewKVStoreKey("stake")
|
||||||
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace)
|
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
|
||||||
|
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
|
||||||
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
|
||||||
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||||
validatorUpdates := stake.EndBlocker(ctx, stakeKeeper)
|
validatorUpdates := stake.EndBlocker(ctx, stakeKeeper)
|
||||||
|
@ -32,7 +33,7 @@ func TestStakeWithRandomMessages(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey})
|
err := mapp.CompleteSetup(stakeKey, stakeTKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -44,14 +45,14 @@ func TestStakeWithRandomMessages(t *testing.T) {
|
||||||
|
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.Operation{
|
[]simulation.WeightedOperation{
|
||||||
SimulateMsgCreateValidator(mapper, stakeKeeper),
|
{10, SimulateMsgCreateValidator(mapper, stakeKeeper)},
|
||||||
SimulateMsgEditValidator(stakeKeeper),
|
{5, SimulateMsgEditValidator(stakeKeeper)},
|
||||||
SimulateMsgDelegate(mapper, stakeKeeper),
|
{15, SimulateMsgDelegate(mapper, stakeKeeper)},
|
||||||
SimulateMsgBeginUnbonding(mapper, stakeKeeper),
|
{10, SimulateMsgBeginUnbonding(mapper, stakeKeeper)},
|
||||||
SimulateMsgCompleteUnbonding(stakeKeeper),
|
{3, SimulateMsgCompleteUnbonding(stakeKeeper)},
|
||||||
SimulateMsgBeginRedelegate(mapper, stakeKeeper),
|
{10, SimulateMsgBeginRedelegate(mapper, stakeKeeper)},
|
||||||
SimulateMsgCompleteRedelegate(stakeKeeper),
|
{3, SimulateMsgCompleteRedelegate(stakeKeeper)},
|
||||||
}, []simulation.RandSetup{
|
}, []simulation.RandSetup{
|
||||||
Setup(mapp, stakeKeeper),
|
Setup(mapp, stakeKeeper),
|
||||||
}, []simulation.Invariant{
|
}, []simulation.Invariant{
|
||||||
|
|
|
@ -33,7 +33,7 @@ var (
|
||||||
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey
|
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey
|
||||||
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
|
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
|
||||||
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
||||||
GetTendermintUpdatesKey = keeper.GetTendermintUpdatesKey
|
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
|
||||||
GetDelegationKey = keeper.GetDelegationKey
|
GetDelegationKey = keeper.GetDelegationKey
|
||||||
GetDelegationsKey = keeper.GetDelegationsKey
|
GetDelegationsKey = keeper.GetDelegationsKey
|
||||||
ParamKey = keeper.ParamKey
|
ParamKey = keeper.ParamKey
|
||||||
|
@ -44,7 +44,7 @@ var (
|
||||||
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
|
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
|
||||||
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey
|
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey
|
||||||
ValidatorPowerCliffKey = keeper.ValidatorPowerCliffKey
|
ValidatorPowerCliffKey = keeper.ValidatorPowerCliffKey
|
||||||
TendermintUpdatesKey = keeper.TendermintUpdatesKey
|
TendermintUpdatesTKey = keeper.TendermintUpdatesTKey
|
||||||
DelegationKey = keeper.DelegationKey
|
DelegationKey = keeper.DelegationKey
|
||||||
IntraTxCounterKey = keeper.IntraTxCounterKey
|
IntraTxCounterKey = keeper.IntraTxCounterKey
|
||||||
GetUBDKey = keeper.GetUBDKey
|
GetUBDKey = keeper.GetUBDKey
|
||||||
|
|
Loading…
Reference in New Issue