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
* Merge pull request #1856: gen-tx: Support User Given Key Passwords

* Fix broken CLI test(s)
  • Loading branch information
alexanderbez authored and rigelrozanski committed Aug 1, 2018
1 parent 7b54e4b commit a980579
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 62 deletions.
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ BREAKING CHANGES
* [x/gov] Governance parameters are now stored in globalparams store
* [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr
* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64
* [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
57 changes: 41 additions & 16 deletions cmd/gaia/app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@ 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"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/stake"

"github.com/spf13/pflag"

"github.com/tendermint/tendermint/crypto"
tmtypes "github.com/tendermint/tendermint/types"
)

// DefaultKeyPass contains the default key password for genesis transactions
const DefaultKeyPass = "12345678"

var (
// bonded tokens given to genesis validators/accounts
freeFermionVal = int64(100)
Expand Down Expand Up @@ -81,30 +87,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,
) (appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err 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 appGenTx, cliPrint, validator, err
}

if keyPass == "" {
keyPass = DefaultKeyPass
}

addr, secret, err := server.GenerateSaveCoinKey(
genTxConfig.CliRoot,
genTxConfig.Name,
keyPass,
genTxConfig.Overwrite,
)
if err != nil {
return
return appGenTx, cliPrint, validator, 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 appGenTx, cliPrint, validator, err
}

cliPrint = json.RawMessage(bz)

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

return appGenTx, cliPrint, validator, err
}

// Generate a gaia genesis transaction without flags
Expand Down
70 changes: 35 additions & 35 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 @@ -176,7 +176,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())

proposalsQuery := tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags))
proposalsQuery := tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags), "")
require.Equal(t, "No matching proposals found", proposalsQuery)

// submit a test proposal
Expand All @@ -187,7 +187,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 @@ -197,15 +197,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags))
proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags), "")
require.Equal(t, " 1 - Test", proposalsQuery)

depositStr := fmt.Sprintf("gaiacli gov deposit %v", flags)
depositStr += fmt.Sprintf(" --from=%s", "foo")
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 @@ -219,7 +219,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 All @@ -231,10 +231,10 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(1), votes[0].ProposalID)
require.Equal(t, gov.OptionYes, votes[0].Option)

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=DepositPeriod %v", flags))
proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=DepositPeriod %v", flags), "")
require.Equal(t, "No matching proposals found", proposalsQuery)

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=VotingPeriod %v", flags))
proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=VotingPeriod %v", flags), "")
require.Equal(t, " 1 - Test", proposalsQuery)

// submit a second test proposal
Expand All @@ -245,10 +245,10 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
spStr += fmt.Sprintf(" --title=%s", "Apples")
spStr += fmt.Sprintf(" --description=%s", "test")

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

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --latest=1 %v", flags))
proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --latest=1 %v", flags), "")
require.Equal(t, " 2 - Apples", proposalsQuery)
}

Expand Down Expand Up @@ -291,7 +291,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 @@ -304,7 +304,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 @@ -315,7 +315,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 @@ -329,7 +329,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 @@ -338,7 +338,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 @@ -347,7 +347,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 @@ -356,7 +356,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
7 changes: 5 additions & 2 deletions cmd/gaia/testnets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,13 +476,16 @@ gaiacli account <account_cosmosaccaddr> --block=<block_height>

## Create your Own Testnet

To create your own testnet, first each validator will need to install gaiad and run gen-tx
To create your own testnet, first each validator will need to install gaiad and
run `gen-tx`:

```bash
gaiad init gen-tx --name <account_name>
```

This populations `$HOME/.gaiad/gen-tx/` with a json file.
The validator will be prompted to enter a password for their new account.

This populates `$HOME/.gaiad/gen-tx/` with a json file.

Now these json files need to be aggregated together via Github, a Google form, pastebin or other methods.

Expand Down
Loading

0 comments on commit a980579

Please sign in to comment.