Merge branch 'develop' into rigel/stake-spec-compliance

This commit is contained in:
Rigel 2018-07-03 13:37:59 -04:00 committed by GitHub
commit f50c7be976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 296 additions and 188 deletions

View File

@ -83,7 +83,7 @@ jobs:
name: Test cli
command: |
export PATH="$GOBIN:$PATH"
make test_cli_retry
make test_cli
test_cover:
<<: *defaults

View File

@ -82,6 +82,7 @@ IMPROVEMENTS
* added contributing guidelines
BUG FIXES
* [x/slashing] \#1510 Unrevoked validators cannot un-revoke themselves
* [gaia] Added self delegation for validators in the genesis creation
* [lcd] tests now don't depend on raw json text
* [stake] error strings lower case

View File

@ -1,34 +1,35 @@
# Simple usage with a mounted data directory:
# > docker build -t gaia .
# > docker run -v $HOME/.gaiad:/root/.gaiad gaia init
# > docker run -v $HOME/.gaiad:/root/.gaiad gaia start
FROM alpine:edge
# > docker run -it -p 46657:46657 -p 46656:46656 -v ~/.gaiad:/root/.gaiad -v ~/.gaiacli:/root/.gaiacli gaia gaiad init
# > docker run -it -p 46657:46657 -p 46656:46656 -v ~/.gaiad:/root/.gaiad -v ~/.gaiacli:/root/.gaiacli gaia gaiad start
FROM golang:alpine AS build-env
# Set up dependencies
ENV PACKAGES go glide make git libc-dev bash
ENV PACKAGES make git libc-dev bash gcc linux-headers eudev-dev
# Set up GOPATH & PATH
ENV GOPATH /root/go
ENV BASE_PATH $GOPATH/src/github.com/cosmos
ENV REPO_PATH $BASE_PATH/cosmos-sdk
ENV WORKDIR /cosmos/
ENV PATH $GOPATH/bin:$PATH
# Link expected Go repo path
RUN mkdir -p $WORKDIR $GOPATH/pkg $ $GOPATH/bin $BASE_PATH
# Set working directory for the build
WORKDIR /go/src/github.com/cosmos/cosmos-sdk
# Add source files
ADD . $REPO_PATH
COPY . .
# Install minimum necessary dependencies, build Cosmos SDK, remove packages
RUN apk add --no-cache $PACKAGES && \
cd $REPO_PATH && make get_tools && make get_vendor_deps && make build && make install && \
apk del $PACKAGES
make get_tools && \
make get_vendor_deps && \
make build && \
make install
# Set entrypoint
# Final image
FROM alpine:edge
ENTRYPOINT ["gaiad"]
# Install ca-certificates
RUN apk add --update ca-certificates
WORKDIR /root
# Copy over binaries from the build-env
COPY --from=build-env /go/bin/gaiad /usr/bin/gaiad
COPY --from=build-env /go/bin/gaiacli /usr/bin/gaiacli
# Run gaiad by default, omit entrypoint to ease using container with gaiacli
CMD ["gaiad"]

View File

@ -92,15 +92,9 @@ test: test_unit
test_cli:
@go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test`
test_cli_retry:
for i in 1 2 3; do make test_cli && break || sleep 2; done
test_unit:
@go test $(PACKAGES_NOCLITEST)
test_unit_retry:
for i in 1 2 3; do make test_unit && break || sleep 2; done
test_race:
@go test -race $(PACKAGES_NOCLITEST)

View File

@ -11,10 +11,10 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
tmtypes "github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"

View File

@ -9,9 +9,9 @@ import (
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
cmn "github.com/tendermint/tendermint/libs/common"
rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
@ -141,13 +141,22 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msgs []sdk.Msg, cdc
sequence := ctx.Sequence
memo := ctx.Memo
fee := sdk.Coin{}
if ctx.Fee != "" {
parsedFee, err := sdk.ParseCoin(ctx.Fee)
if err != nil {
return nil, err
}
fee = parsedFee
}
signMsg := auth.StdSignMsg{
ChainID: chainID,
AccountNumber: accnum,
Sequence: sequence,
Msgs: msgs,
Memo: memo,
Fee: auth.NewStdFee(ctx.Gas, sdk.Coin{}), // TODO run simulate to estimate gas?
Fee: auth.NewStdFee(ctx.Gas, fee), // TODO run simulate to estimate gas?
}
keybase, err := keys.GetKeyBase()

View File

@ -11,6 +11,7 @@ type CoreContext struct {
ChainID string
Height int64
Gas int64
Fee string
TrustNode bool
NodeURI string
FromAddressName string
@ -41,6 +42,12 @@ func (c CoreContext) WithGas(gas int64) CoreContext {
return c
}
// WithFee - return a copy of the context with an updated fee
func (c CoreContext) WithFee(fee string) CoreContext {
c.Fee = fee
return c
}
// WithTrustNode - return a copy of the context with an updated TrustNode flag
func (c CoreContext) WithTrustNode(trustNode bool) CoreContext {
c.TrustNode = trustNode

View File

@ -31,6 +31,7 @@ func NewCoreContextFromViper() CoreContext {
ChainID: chainID,
Height: viper.GetInt64(client.FlagHeight),
Gas: viper.GetInt64(client.FlagGas),
Fee: viper.GetString(client.FlagFee),
TrustNode: viper.GetBool(client.FlagTrustNode),
FromAddressName: viper.GetString(client.FlagName),
NodeURI: nodeURI,

View File

@ -13,9 +13,9 @@ import (
cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/common"
p2p "github.com/tendermint/tendermint/p2p"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/tendermint/tendermint/libs/common"
client "github.com/cosmos/cosmos-sdk/client"
keys "github.com/cosmos/cosmos-sdk/client/keys"

View File

@ -9,8 +9,8 @@ import (
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log"
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
cmn "github.com/tendermint/tendermint/libs/common"
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
client "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"

View File

@ -19,14 +19,14 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
nm "github.com/tendermint/tendermint/node"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/client"
keys "github.com/cosmos/cosmos-sdk/client/keys"
@ -169,7 +169,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.Address) (
//time.Sleep(time.Second)
//tests.WaitForHeight(2, port)
tests.WaitForStart(port)
tests.WaitForLCDStart(port)
tests.WaitForHeight(1, port)
// for use in defer

View File

@ -5,10 +5,10 @@ import (
"os"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -37,12 +37,13 @@ type GaiaApp struct {
cdc *wire.Codec
// keys to access the substores
keyMain *sdk.KVStoreKey
keyAccount *sdk.KVStoreKey
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
keySlashing *sdk.KVStoreKey
keyGov *sdk.KVStoreKey
keyMain *sdk.KVStoreKey
keyAccount *sdk.KVStoreKey
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
keySlashing *sdk.KVStoreKey
keyGov *sdk.KVStoreKey
keyFeeCollection *sdk.KVStoreKey
// Manage getting and setting accounts
accountMapper auth.AccountMapper
@ -59,14 +60,15 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
// create your application object
var app = &GaiaApp{
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
cdc: cdc,
keyMain: sdk.NewKVStoreKey("main"),
keyAccount: sdk.NewKVStoreKey("acc"),
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
cdc: cdc,
keyMain: sdk.NewKVStoreKey("main"),
keyAccount: sdk.NewKVStoreKey("acc"),
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
keyFeeCollection: sdk.NewKVStoreKey("fee"),
}
// define the accountMapper
@ -82,6 +84,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)
// register message routes
app.Router().
@ -96,7 +99,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())

View File

@ -7,6 +7,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/server"
@ -16,7 +19,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/tendermint/tendermint/crypto"
)
func TestGaiaCLISend(t *testing.T) {
@ -34,9 +36,10 @@ func TestGaiaCLISend(t *testing.T) {
flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID)
// start gaiad server
proc := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
defer proc.Stop(false)
tests.WaitForStart(port)
tests.WaitForTMStart(port)
tests.WaitForNextHeightTM(port)
fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json")
fooCech, err := sdk.Bech32ifyAcc(fooAddr)
@ -90,9 +93,10 @@ func TestGaiaCLICreateValidator(t *testing.T) {
flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID)
// start gaiad server
proc := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
defer proc.Stop(false)
tests.WaitForStart(port)
tests.WaitForTMStart(port)
tests.WaitForNextHeightTM(port)
fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json")
fooCech, err := sdk.Bech32ifyAcc(fooAddr)
@ -130,19 +134,20 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, "2/1", validator.PoolShares.Amount.String())
// unbond a single share
unbondStr := fmt.Sprintf("gaiacli stake unbond %v", flags)
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
unbondStr += fmt.Sprintf(" --name=%v", "bar")
unbondStr += fmt.Sprintf(" --address-validator=%v", barCech)
unbondStr += fmt.Sprintf(" --address-delegator=%v", barCech)
unbondStr += fmt.Sprintf(" --shares=%v", "1")
unbondStr += fmt.Sprintf(" --sequence=%v", "1")
t.Log(fmt.Sprintf("debug unbondStr: %v\n", unbondStr))
unbondStr += fmt.Sprintf(" --shares-amount=%v", "1")
executeWrite(t, unbondStr, pass)
success := executeWrite(t, unbondStr, pass)
require.True(t, success)
tests.WaitForNextHeightTM(port)
/* // this won't be what we expect because we've only started unbonding, haven't completed
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags))
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
*/
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %v --output=json %v", barCech, flags))
require.Equal(t, "1/1", validator.PoolShares.Amount.String())
}
@ -162,9 +167,10 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
flags := fmt.Sprintf("--node=%v --chain-id=%v", servAddr, chainID)
// start gaiad server
proc := tests.GoExecuteT(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --rpc.laddr=%v", servAddr))
defer proc.Stop(false)
tests.WaitForStart(port)
tests.WaitForTMStart(port)
tests.WaitForNextHeightTM(port)
fooAddr, _ := executeGetAddrPK(t, "gaiacli keys show foo --output=json")
fooCech, err := sdk.Bech32ifyAcc(fooAddr)
@ -203,14 +209,27 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
//___________________________________________________________________________________
// executors
func executeWrite(t *testing.T, cmdStr string, writes ...string) {
func executeWrite(t *testing.T, cmdStr string, writes ...string) bool {
proc := tests.GoExecuteT(t, cmdStr)
for _, write := range writes {
_, err := proc.StdinPipe.Write([]byte(write + "\n"))
require.NoError(t, err)
}
stdout, stderr, err := proc.ReadAll()
if err != nil {
fmt.Println("Err on proc.ReadAll()", err, cmdStr)
}
// Log output.
if len(stdout) > 0 {
t.Log("Stdout:", cmn.Green(string(stdout)))
}
if len(stderr) > 0 {
t.Log("Stderr:", cmn.Red(string(stderr)))
}
proc.Wait()
return proc.ExitState.Success()
// bz := proc.StdoutBuffer.Bytes()
// fmt.Println("EXEC WRITE", string(bz))
}

View File

@ -6,10 +6,10 @@ import (
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/server"

View File

@ -4,10 +4,10 @@ import (
"encoding/json"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"

View File

@ -7,10 +7,10 @@ import (
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/examples/democoin/app"
"github.com/cosmos/cosmos-sdk/server"

View File

@ -5,9 +5,9 @@ import (
"path/filepath"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
)
// AppCreator lets us lazily initialize app, using home dir

View File

@ -18,12 +18,12 @@ import (
"github.com/tendermint/tendermint/crypto"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
tmtypes "github.com/tendermint/tendermint/types"
tmcli "github.com/tendermint/tendermint/libs/cli"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
tmtypes "github.com/tendermint/tendermint/types"
clkeys "github.com/cosmos/cosmos-sdk/client/keys"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"

View File

@ -7,9 +7,9 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
gc "github.com/cosmos/cosmos-sdk/server/config"

View File

@ -8,10 +8,10 @@ import (
"github.com/tendermint/tendermint/abci/server"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/node"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
cmn "github.com/tendermint/tendermint/libs/common"
)
const (

View File

@ -7,8 +7,8 @@ import (
"golang.org/x/crypto/ripemd160"
abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/crypto/merkle"
dbm "github.com/tendermint/tendermint/libs/db"
sdk "github.com/cosmos/cosmos-sdk/types"
)

View File

@ -5,8 +5,8 @@ import (
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/crypto/merkle"
dbm "github.com/tendermint/tendermint/libs/db"
sdk "github.com/cosmos/cosmos-sdk/types"
)

View File

@ -1,6 +1,8 @@
package tests
import (
"fmt"
"io/ioutil"
"strings"
"testing"
@ -21,13 +23,15 @@ func ExecuteT(t *testing.T, cmd string) (out string) {
}
// Start process and wait.
proc, err := StartProcess("", name, args, nil, nil)
proc, err := StartProcess("", name, args)
require.NoError(t, err)
proc.Wait()
// Get the output.
outbz := proc.StdoutBuffer.Bytes()
errbz := proc.StderrBuffer.Bytes()
outbz, errbz, err := proc.ReadAll()
if err != nil {
fmt.Println("Err on proc.ReadAll()", err, args)
}
proc.Wait()
// Log output.
if len(outbz) > 0 {
@ -56,36 +60,38 @@ func GoExecuteT(t *testing.T, cmd string) (proc *Process) {
}
// Start process.
proc, err := StartProcess("", name, args, nil, nil)
proc, err := StartProcess("", name, args)
require.NoError(t, err)
// Run goroutines to log stdout.
go func() {
buf := make([]byte, 10240) // TODO Document the effects.
for {
n, err := proc.StdoutBuffer.Read(buf)
if err != nil {
return
}
if n > 0 {
t.Log("Stdout:", cmn.Green(string(buf[:n])))
}
}
}()
// Run goroutines to log stderr.
go func() {
buf := make([]byte, 10240) // TODO Document the effects.
for {
n, err := proc.StderrBuffer.Read(buf)
if err != nil {
return
}
if n > 0 {
t.Log("Stderr:", cmn.Red(string(buf[:n])))
}
}
}()
return proc
}
// Same as GoExecuteT but spawns a go routine to ReadAll off stdout.
func GoExecuteTWithStdout(t *testing.T, cmd string) (proc *Process) {
t.Log("Running", cmn.Cyan(cmd))
// Split cmd to name and args.
split := strings.Split(cmd, " ")
require.True(t, len(split) > 0, "no command provided")
name, args := split[0], []string(nil)
if len(split) > 1 {
args = split[1:]
}
// Start process.
proc, err := CreateProcess("", name, args)
require.NoError(t, err)
// Without this, the test halts ?!
go func() {
_, err := ioutil.ReadAll(proc.StdoutPipe)
if err != nil {
fmt.Println("-------------ERR-----------------------", err)
return
}
}()
err = proc.Cmd.Start()
require.NoError(t, err)
proc.Pid = proc.Cmd.Process.Pid
return proc
}

View File

@ -1,8 +1,8 @@
package tests
import (
"bytes"
"io"
"io/ioutil"
"os"
"os/exec"
"time"
@ -10,26 +10,37 @@ import (
// execution process
type Process struct {
ExecPath string
Args []string
Pid int
StartTime time.Time
EndTime time.Time
Cmd *exec.Cmd `json:"-"`
ExitState *os.ProcessState `json:"-"`
WaitCh chan struct{} `json:"-"`
StdinPipe io.WriteCloser `json:"-"`
StdoutBuffer *bytes.Buffer `json:"-"`
StderrBuffer *bytes.Buffer `json:"-"`
ExecPath string
Args []string
Pid int
StartTime time.Time
EndTime time.Time
Cmd *exec.Cmd `json:"-"`
ExitState *os.ProcessState `json:"-"`
StdinPipe io.WriteCloser `json:"-"`
StdoutPipe io.ReadCloser `json:"-"`
StderrPipe io.ReadCloser `json:"-"`
}
// dir: The working directory. If "", os.Getwd() is used.
// name: Command name
// args: Args to command. (should not include name)
// outFile, errFile: If not nil, will use, otherwise new Buffers will be
// allocated. Either way, Process.Cmd.StdoutPipe and Process.Cmd.StderrPipe will be nil
// respectively.
func StartProcess(dir string, name string, args []string, outFile, errFile io.WriteCloser) (*Process, error) {
func StartProcess(dir string, name string, args []string) (*Process, error) {
proc, err := CreateProcess(dir, name, args)
if err != nil {
return nil, err
}
// cmd start
if err := proc.Cmd.Start(); err != nil {
return nil, err
}
proc.Pid = proc.Cmd.Process.Pid
return proc, nil
}
// Same as StartProcess but doesn't start the process
func CreateProcess(dir string, name string, args []string) (*Process, error) {
var cmd = exec.Command(name, args...) // is not yet started.
// cmd dir
if dir == "" {
@ -46,52 +57,27 @@ func StartProcess(dir string, name string, args []string, outFile, errFile io.Wr
if err != nil {
return nil, err
}
// cmd stdout, stderr
var outBuffer, errBuffer *bytes.Buffer
if outFile != nil {
cmd.Stdout = outFile
} else {
outBuffer = bytes.NewBuffer(nil)
cmd.Stdout = outBuffer
}
if errFile != nil {
cmd.Stderr = errFile
} else {
errBuffer = bytes.NewBuffer(nil)
cmd.Stderr = errBuffer
}
// cmd start
if err := cmd.Start(); err != nil {
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
proc := &Process{
ExecPath: name,
Args: args,
Pid: cmd.Process.Pid,
StartTime: time.Now(),
Cmd: cmd,
ExitState: nil,
WaitCh: make(chan struct{}),
StdinPipe: stdin,
ExecPath: name,
Args: args,
StartTime: time.Now(),
Cmd: cmd,
ExitState: nil,
StdinPipe: stdin,
StdoutPipe: stdout,
StderrPipe: stderr,
}
if outBuffer != nil {
proc.StdoutBuffer = outBuffer
}
if errBuffer != nil {
proc.StderrBuffer = errBuffer
}
go func() {
err := proc.Cmd.Wait()
if err != nil {
// fmt.Printf("Process exit: %v\n", err)
if exitError, ok := err.(*exec.ExitError); ok {
proc.ExitState = exitError.ProcessState
}
}
proc.ExitState = proc.Cmd.ProcessState
proc.EndTime = time.Now() // TODO make this goroutine-safe
close(proc.WaitCh)
}()
return proc, nil
}
@ -106,5 +92,26 @@ func (proc *Process) Stop(kill bool) error {
// wait for the process
func (proc *Process) Wait() {
<-proc.WaitCh
err := proc.Cmd.Wait()
if err != nil {
// fmt.Printf("Process exit: %v\n", err)
if exitError, ok := err.(*exec.ExitError); ok {
proc.ExitState = exitError.ProcessState
}
}
proc.ExitState = proc.Cmd.ProcessState
proc.EndTime = time.Now() // TODO make this goroutine-safe
}
// ReadAll calls ioutil.ReadAll on the StdoutPipe and StderrPipe.
func (proc *Process) ReadAll() (stdout []byte, stderr []byte, err error) {
outbz, err := ioutil.ReadAll(proc.StdoutPipe)
if err != nil {
return nil, nil, err
}
errbz, err := ioutil.ReadAll(proc.StderrPipe)
if err != nil {
return nil, nil, err
}
return outbz, errbz, nil
}

View File

@ -21,13 +21,20 @@ func WaitForNextHeightTM(port string) {
// Wait for N tendermint blocks to pass using the Tendermint RPC
// on localhost
func WaitForNextNBlocksTM(n int64, port string) {
// get the latest block and wait for n more
url := fmt.Sprintf("http://localhost:%v", port)
cl := tmclient.NewHTTP(url, "/websocket")
resBlock, err := cl.Block(nil)
if err != nil {
panic(err)
var height int64
if err != nil || resBlock.Block == nil {
// wait for the first block to exist
WaitForHeightTM(1, port)
height = 1 + n
} else {
height = resBlock.Block.Height + n
}
waitForHeightTM(resBlock.Block.Height+n, url)
waitForHeightTM(height, url)
}
// Wait for the given height from the Tendermint RPC
@ -57,7 +64,6 @@ func waitForHeightTM(height int64, url string) {
if resBlock.Block != nil &&
resBlock.Block.Height >= height {
fmt.Println("HEIGHT", resBlock.Block.Height)
return
}
time.Sleep(time.Millisecond * 100)
@ -115,10 +121,23 @@ func waitForHeight(height int64, url string) {
}
}
// wait for tendermint to start
func WaitForStart(port string) {
var err error
// wait for tendermint to start by querying the LCD
func WaitForLCDStart(port string) {
url := fmt.Sprintf("http://localhost:%v/blocks/latest", port)
WaitForStart(url)
}
// wait for tendermint to start by querying tendermint
func WaitForTMStart(port string) {
url := fmt.Sprintf("http://localhost:%v/block", port)
WaitForStart(url)
}
// WaitForStart waits for the node to start by pinging the url
// every 100ms for 5s until it returns 200. If it takes longer than 5s,
// it panics.
func WaitForStart(url string) {
var err error
// ping the status endpoint a few times a second
// for a few seconds until we get a good response.
@ -131,6 +150,8 @@ func WaitForStart(port string) {
if err != nil || res == nil {
continue
}
// body, _ := ioutil.ReadAll(res.Body)
// fmt.Println("BODY", string(body))
err = res.Body.Close()
if err != nil {
panic(err)

View File

@ -106,7 +106,7 @@ func TestSlashingMsgs(t *testing.T) {
// no signing info yet
checkValidatorSigningInfo(t, mapp, keeper, addr1, false)
// unrevoke should fail with unknown validator
// unrevoke should fail with validator not revoked
res := mock.SignCheck(mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, priv1)
require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeInvalidValidator), res.Code)
require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotRevoked), res.Code)
}

View File

@ -12,8 +12,9 @@ const (
// Default slashing codespace
DefaultCodespace sdk.CodespaceType = 10
CodeInvalidValidator CodeType = 101
CodeValidatorJailed CodeType = 102
CodeInvalidValidator CodeType = 101
CodeValidatorJailed CodeType = 102
CodeValidatorNotRevoked CodeType = 103
)
func ErrNoValidatorForAddress(codespace sdk.CodespaceType) sdk.Error {
@ -25,3 +26,6 @@ func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error {
func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeValidatorJailed, "validator jailed, cannot yet be unrevoked")
}
func ErrValidatorNotRevoked(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeValidatorNotRevoked, "validator not revoked, cannot be unrevoked")
}

View File

@ -26,6 +26,10 @@ func handleMsgUnrevoke(ctx sdk.Context, msg MsgUnrevoke, k Keeper) sdk.Result {
return ErrNoValidatorForAddress(k.codespace).Result()
}
if !validator.GetRevoked() {
return ErrValidatorNotRevoked(k.codespace).Result()
}
addr := validator.GetPubKey().Address()
// Signing info must exist

View File

@ -0,0 +1,28 @@
package slashing
import (
"testing"
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
)
func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
// initial setup
ctx, ck, sk, keeper := createTestInput(t)
slh := NewHandler(keeper)
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// assert non-revoked validator can't be unrevoked
got = slh(ctx, NewMsgUnrevoke(addr))
require.False(t, got.IsOK(), "allowed unrevoke of non-revoked validator")
require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotRevoked), got.Code)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
@ -154,9 +155,10 @@ func GetCmdRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
Short: "redelegate illiquid tokens from one validator to another",
}
cmd.AddCommand(
GetCmdBeginRedelegate(storeName, cdc),
GetCmdCompleteRedelegate(cdc),
)
client.PostCommands(
GetCmdBeginRedelegate(storeName, cdc),
GetCmdCompleteRedelegate(cdc),
)...)
return cmd
}
@ -301,9 +303,10 @@ func GetCmdUnbond(storeName string, cdc *wire.Codec) *cobra.Command {
Short: "begin or complete unbonding shares from a validator",
}
cmd.AddCommand(
GetCmdBeginUnbonding(storeName, cdc),
GetCmdCompleteUnbonding(cdc),
)
client.PostCommands(
GetCmdBeginUnbonding(storeName, cdc),
GetCmdCompleteUnbonding(cdc),
)...)
return cmd
}