Skip to content

Commit

Permalink
Merge pull request #1856: gen-tx: Support User Given Key Passwords
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksandr Bezobchuk committed Jul 27, 2018
1 parent 9812c88 commit a3982d7
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 51 deletions.
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ BREAKING CHANGES
* `gaiacli gov vote --voter`
* [x/gov] Added tags sub-package, changed tags to use dash-case
* [x/gov] Governance parameters are now stored in globalparams store
* [cli] Genesis/key creation (`init`) now supports user-provided key passwords

FEATURES
* [lcd] Can now query governance proposals by ProposalStatus
Expand Down
7 changes: 6 additions & 1 deletion client/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ func GetPassword(prompt string, buf *bufio.Reader) (pass string, err error) {
} else {
pass, err = readLineFromBuf(buf)
}

if err != nil {
return "", err
}

if len(pass) < MinPassLength {
return "", errors.Errorf("password must be at least %d characters", MinPassLength)
// Return the given password to the upstream client so it can handle a
// non-STDIN failure gracefully.
return pass, errors.Errorf("password must be at least %d characters", MinPassLength)
}

return pass, nil
}

Expand Down
49 changes: 36 additions & 13 deletions cmd/gaia/app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package app
import (
"encoding/json"
"errors"
"fmt"

"github.com/spf13/pflag"
"github.com/tendermint/tendermint/crypto"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -20,6 +22,8 @@ var (
// bonded tokens given to genesis validators/accounts
freeFermionVal = int64(100)
freeFermionsAcc = int64(50)

DefaultKeyPass = "12345678"
)

// State to Unmarshal
Expand Down Expand Up @@ -81,30 +85,49 @@ type GaiaGenTx struct {
PubKey string `json:"pub_key"`
}

// Generate a gaia genesis transaction with flags
func GaiaAppGenTx(cdc *wire.Codec, pk crypto.PubKey, genTxConfig config.GenTx) (
appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) {
// GaiaAppGenTx generates a Gaia genesis transaction.
func GaiaAppGenTx(
cdc *wire.Codec, pk crypto.PubKey, genTxConfig config.GenTx,
) (json.RawMessage, json.RawMessage, tmtypes.GenesisValidator, error) {
if genTxConfig.Name == "" {
return nil, nil, tmtypes.GenesisValidator{}, errors.New("Must specify --name (validator moniker)")
}

var addr sdk.AccAddress
var secret string
addr, secret, err = server.GenerateSaveCoinKey(genTxConfig.CliRoot, genTxConfig.Name, "1234567890", genTxConfig.Overwrite)
buf := client.BufferStdin()
prompt := fmt.Sprintf("Password for account '%s' (default %s):", genTxConfig.Name, DefaultKeyPass)

keyPass, err := client.GetPassword(prompt, buf)
if err != nil && keyPass != "" {
// An error was returned that either failed to read the password from
// STDIN or the given password is not empty but failed to meet minimum
// length requirements.
return nil, nil, tmtypes.GenesisValidator{}, err
}

if keyPass == "" {
keyPass = DefaultKeyPass
}

addr, secret, err := server.GenerateSaveCoinKey(
genTxConfig.CliRoot,
genTxConfig.Name,
keyPass,
genTxConfig.Overwrite,
)
if err != nil {
return
return nil, nil, tmtypes.GenesisValidator{}, err
}

mm := map[string]string{"secret": secret}
var bz []byte
bz, err = cdc.MarshalJSON(mm)
bz, err := cdc.MarshalJSON(mm)
if err != nil {
return
return nil, nil, tmtypes.GenesisValidator{}, err
}

cliPrint = json.RawMessage(bz)
cliPrint := json.RawMessage(bz)
appGenTx, _, validator, err := GaiaAppGenTxNF(cdc, pk, addr, genTxConfig.Name)

appGenTx, _, validator, err = GaiaAppGenTxNF(cdc, pk, addr, genTxConfig.Name)
return
return appGenTx, cliPrint, validator, err
}

// Generate a gaia genesis transaction without flags
Expand Down
58 changes: 29 additions & 29 deletions cmd/gaia/cli_test/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
)

var (
pass = "1234567890"
gaiadHome = ""
gaiacliHome = ""
)
Expand All @@ -35,11 +34,12 @@ func init() {
}

func TestGaiaCLISend(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome))
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass)
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)

chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass)

// get a free port, also setup some common flags
servAddr, port, err := server.FreeTCPAddr()
Expand All @@ -59,7 +59,7 @@ func TestGaiaCLISend(t *testing.T) {
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())

executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags))
Expand All @@ -68,7 +68,7 @@ func TestGaiaCLISend(t *testing.T) {
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())

// test autosequencing
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags))
Expand All @@ -77,7 +77,7 @@ func TestGaiaCLISend(t *testing.T) {
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf("steak").Int64())

// test memo
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo --memo 'testmemo'", flags, barAddr), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo --memo 'testmemo'", flags, barAddr), app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags))
Expand All @@ -87,11 +87,11 @@ func TestGaiaCLISend(t *testing.T) {
}

func TestGaiaCLICreateValidator(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome))
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass)
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass)

// get a free port, also setup some common flags
servAddr, port, err := server.FreeTCPAddr()
Expand All @@ -109,7 +109,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome))
barCeshPubKey := sdk.MustBech32ifyValPub(barPubKey)

executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags))
Expand All @@ -124,7 +124,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
cvStr += fmt.Sprintf(" --amount=%v", "2steak")
cvStr += fmt.Sprintf(" --moniker=%v", "bar-vally")

executeWrite(t, cvStr, pass)
executeWrite(t, cvStr, app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags))
Expand All @@ -140,7 +140,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
unbondStr += fmt.Sprintf(" --address-validator=%s", barAddr)
unbondStr += fmt.Sprintf(" --shares-amount=%v", "1")

success := executeWrite(t, unbondStr, pass)
success := executeWrite(t, unbondStr, app.DefaultKeyPass)
require.True(t, success)
tests.WaitForNextNBlocksTM(2, port)

Expand All @@ -153,11 +153,11 @@ func TestGaiaCLICreateValidator(t *testing.T) {
}

func TestGaiaCLISubmitProposal(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome))
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), pass)
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), pass)
executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass)

// get a free port, also setup some common flags
servAddr, port, err := server.FreeTCPAddr()
Expand All @@ -184,7 +184,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
spStr += fmt.Sprintf(" --title=%s", "Test")
spStr += fmt.Sprintf(" --description=%s", "test")

executeWrite(t, spStr, pass)
executeWrite(t, spStr, app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
Expand All @@ -199,7 +199,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
depositStr += fmt.Sprintf(" --deposit=%s", "10steak")
depositStr += fmt.Sprintf(" --proposal-id=%s", "1")

executeWrite(t, depositStr, pass)
executeWrite(t, depositStr, app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
Expand All @@ -213,7 +213,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
voteStr += fmt.Sprintf(" --proposal-id=%s", "1")
voteStr += fmt.Sprintf(" --option=%s", "Yes")

executeWrite(t, voteStr, pass)
executeWrite(t, voteStr, app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)

vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposal-id=1 --voter=%s --output=json %v", fooAddr, flags))
Expand Down Expand Up @@ -265,7 +265,7 @@ func executeWrite(t *testing.T, cmdStr string, writes ...string) bool {
}

func executeInit(t *testing.T, cmdStr string) (chainID string) {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, app.DefaultKeyPass)

var initRes map[string]json.RawMessage
err := json.Unmarshal([]byte(out), &initRes)
Expand All @@ -278,7 +278,7 @@ func executeInit(t *testing.T, cmdStr string) (chainID string) {
}

func executeGetAddrPK(t *testing.T, cmdStr string) (sdk.AccAddress, crypto.PubKey) {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var ko keys.KeyOutput
keys.UnmarshalJSON([]byte(out), &ko)

Expand All @@ -289,7 +289,7 @@ func executeGetAddrPK(t *testing.T, cmdStr string) (sdk.AccAddress, crypto.PubKe
}

func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var initRes map[string]json.RawMessage
err := json.Unmarshal([]byte(out), &initRes)
require.NoError(t, err, "out %v, err %v", out, err)
Expand All @@ -303,7 +303,7 @@ func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount {
}

func executeGetValidator(t *testing.T, cmdStr string) stake.Validator {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var validator stake.Validator
cdc := app.MakeCodec()
err := cdc.UnmarshalJSON([]byte(out), &validator)
Expand All @@ -312,7 +312,7 @@ func executeGetValidator(t *testing.T, cmdStr string) stake.Validator {
}

func executeGetProposal(t *testing.T, cmdStr string) gov.Proposal {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var proposal gov.Proposal
cdc := app.MakeCodec()
err := cdc.UnmarshalJSON([]byte(out), &proposal)
Expand All @@ -321,7 +321,7 @@ func executeGetProposal(t *testing.T, cmdStr string) gov.Proposal {
}

func executeGetVote(t *testing.T, cmdStr string) gov.Vote {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var vote gov.Vote
cdc := app.MakeCodec()
err := cdc.UnmarshalJSON([]byte(out), &vote)
Expand All @@ -330,7 +330,7 @@ func executeGetVote(t *testing.T, cmdStr string) gov.Vote {
}

func executeGetVotes(t *testing.T, cmdStr string) []gov.Vote {
out := tests.ExecuteT(t, cmdStr)
out := tests.ExecuteT(t, cmdStr, "")
var votes []gov.Vote
cdc := app.MakeCodec()
err := cdc.UnmarshalJSON([]byte(out), &votes)
Expand Down
23 changes: 15 additions & 8 deletions tests/gobash.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tests

import (
"fmt"
"io"
"io/ioutil"
"strings"
"testing"
Expand All @@ -10,39 +11,45 @@ import (
cmn "github.com/tendermint/tendermint/libs/common"
)

// Execute the command, return stdout, logging stdout/err to t.
func ExecuteT(t *testing.T, cmd string) (out string) {
// ExecuteT executes the command, pipes any input to STDIN and return STDOUT,
// logging STDOUT/STDERR to t.
func ExecuteT(t *testing.T, cmd, input string) (out string) {
t.Log("Running", cmn.Cyan(cmd))

// Split cmd to name and args.
// 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 and wait.
proc, err := StartProcess("", name, args)
require.NoError(t, err)

// Get the output.
// if input is provided, pass it to STDIN and close the pipe
if input != "" {
_, err = io.WriteString(proc.StdinPipe, input)
require.NoError(t, err)
proc.StdinPipe.Close()
}

outbz, errbz, err := proc.ReadAll()
if err != nil {
fmt.Println("Err on proc.ReadAll()", err, args)
}

proc.Wait()

// Log output.
if len(outbz) > 0 {
t.Log("Stdout:", cmn.Green(string(outbz)))
}

if len(errbz) > 0 {
t.Log("Stderr:", cmn.Red(string(errbz)))
}

// Collect STDOUT output.
out = strings.Trim(string(outbz), "\n") //trim any new lines
out = strings.Trim(string(outbz), "\n")
return out
}

Expand Down

0 comments on commit a3982d7

Please sign in to comment.